* transformWithClause - * Transform the list of WITH clause "common table expressions" into * Query nodes. * * The result is the list of transformed CTEs to be put into the output * Query. (This is in fact the same as the ending value of p_ctenamespace, * but it seems cleaner to not expose that in the function's API.) */
| 109 | * but it seems cleaner to not expose that in the function's API.) |
| 110 | */ |
| 111 | List * |
| 112 | transformWithClause(ParseState *pstate, WithClause *withClause) |
| 113 | { |
| 114 | ListCell *lc; |
| 115 | |
| 116 | /* Only one WITH clause per query level */ |
| 117 | Assert(pstate->p_ctenamespace == NIL); |
| 118 | Assert(pstate->p_future_ctes == NIL); |
| 119 | |
| 120 | /* |
| 121 | * WITH RECURSIVE is disabled if gp_recursive_cte is not set |
| 122 | * to allow recursive CTEs. |
| 123 | */ |
| 124 | if (withClause->recursive && !gp_recursive_cte) |
| 125 | ereport(ERROR, |
| 126 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 127 | errmsg("RECURSIVE clauses in WITH queries are currently disabled"), |
| 128 | errhint("In order to use recursive CTEs, \"gp_recursive_cte\" must be turned on."))); |
| 129 | |
| 130 | /* |
| 131 | * For either type of WITH, there must not be duplicate CTE names in the |
| 132 | * list. Check this right away so we needn't worry later. |
| 133 | * |
| 134 | * Also, tentatively mark each CTE as non-recursive, and initialize its |
| 135 | * reference count to zero, and set pstate->p_hasModifyingCTE if needed. |
| 136 | */ |
| 137 | foreach(lc, withClause->ctes) |
| 138 | { |
| 139 | CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc); |
| 140 | ListCell *rest; |
| 141 | |
| 142 | for_each_cell(rest, withClause->ctes, lnext(withClause->ctes, lc)) |
| 143 | { |
| 144 | CommonTableExpr *cte2 = (CommonTableExpr *) lfirst(rest); |
| 145 | |
| 146 | if (strcmp(cte->ctename, cte2->ctename) == 0) |
| 147 | ereport(ERROR, |
| 148 | (errcode(ERRCODE_DUPLICATE_ALIAS), |
| 149 | errmsg("WITH query name \"%s\" specified more than once", |
| 150 | cte2->ctename), |
| 151 | parser_errposition(pstate, cte2->location))); |
| 152 | } |
| 153 | |
| 154 | cte->cterecursive = false; |
| 155 | cte->cterefcount = 0; |
| 156 | |
| 157 | if (!IsA(cte->ctequery, SelectStmt)) |
| 158 | { |
| 159 | /* must be a data-modifying statement */ |
| 160 | Assert(IsA(cte->ctequery, InsertStmt) || |
| 161 | IsA(cte->ctequery, UpdateStmt) || |
| 162 | IsA(cte->ctequery, DeleteStmt)); |
| 163 | |
| 164 | |
| 165 | /* |
| 166 | * Since GPDB currently only support a single writer gang, only one |
| 167 | * writable clause is permitted per CTE. Once we get flexible gangs |
| 168 | * with more than one writer gang we can lift this restriction. |
no test coverage detected