| 176 | static void sqlfunction_destroy(DestReceiver *self); |
| 177 | |
| 178 | static bool |
| 179 | querytree_safe_for_qe_walker(Node *expr, void *context) |
| 180 | { |
| 181 | Assert(context == NULL); |
| 182 | |
| 183 | if (!expr) |
| 184 | { |
| 185 | /** |
| 186 | * Do not end recursion just because we have reached one leaf node. |
| 187 | */ |
| 188 | return false; |
| 189 | } |
| 190 | |
| 191 | switch(nodeTag(expr)) |
| 192 | { |
| 193 | case T_Query: |
| 194 | { |
| 195 | Query *q = (Query *) expr; |
| 196 | |
| 197 | if (!allow_segment_DML && |
| 198 | (q->commandType != CMD_SELECT |
| 199 | || (q->utilityStmt != NULL && |
| 200 | IsA(q->utilityStmt, CreateTableAsStmt)) |
| 201 | || q->resultRelation > 0)) |
| 202 | { |
| 203 | ereport(ERROR, |
| 204 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 205 | errmsg("function cannot execute on a QE slice because it issues a non-SELECT statement"))); |
| 206 | } |
| 207 | |
| 208 | ListCell * f = NULL; |
| 209 | foreach(f,q->rtable) |
| 210 | { |
| 211 | RangeTblEntry *rte = (RangeTblEntry *) lfirst(f); |
| 212 | |
| 213 | if (rte->rtekind == RTE_RELATION) |
| 214 | { |
| 215 | Assert(rte->relid != InvalidOid); |
| 216 | |
| 217 | Oid namespaceId = get_rel_namespace(rte->relid); |
| 218 | |
| 219 | Assert(namespaceId != InvalidOid); |
| 220 | |
| 221 | if (!(IsCatalogNamespace(namespaceId) || |
| 222 | IsToastNamespace(namespaceId) || |
| 223 | IsAoSegmentNamespace(namespaceId) || |
| 224 | (IsReplicatedTable(rte->relid) && |
| 225 | !IS_QUERY_DISPATCHER()))) |
| 226 | { |
| 227 | ereport(ERROR, |
| 228 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 229 | errmsg("function cannot execute on a QE slice because it accesses relation \"%s.%s\"", |
| 230 | quote_identifier(get_namespace_name(namespaceId)), |
| 231 | quote_identifier(get_rel_name(rte->relid))))); |
| 232 | } |
| 233 | } |
| 234 | } |
| 235 | query_tree_walker(q, querytree_safe_for_qe_walker, context, 0); |
no test coverage detected