analyzeCTE(ParseState *pstate, CommonTableExpr *cte)
{
Query *query;
+ CTESearchClause *search_clause = cte->search_clause;
+ CTECycleClause *cycle_clause = cte->cycle_clause;
/* Analysis not done already */
Assert(!IsA(cte->ctequery, Query));
+ /*
+ * Before analyzing the CTE's query, we'd better identify the data type of
+ * the cycle mark column if any, since the query could refer to that.
+ * Other validity checks on the cycle clause will be done afterwards.
+ */
+ if (cycle_clause)
+ {
+ TypeCacheEntry *typentry;
+ Oid op;
+
+ cycle_clause->cycle_mark_value =
+ transformExpr(pstate, cycle_clause->cycle_mark_value,
+ EXPR_KIND_CYCLE_MARK);
+ cycle_clause->cycle_mark_default =
+ transformExpr(pstate, cycle_clause->cycle_mark_default,
+ EXPR_KIND_CYCLE_MARK);
+
+ cycle_clause->cycle_mark_type =
+ select_common_type(pstate,
+ list_make2(cycle_clause->cycle_mark_value,
+ cycle_clause->cycle_mark_default),
+ "CYCLE", NULL);
+ cycle_clause->cycle_mark_value =
+ coerce_to_common_type(pstate,
+ cycle_clause->cycle_mark_value,
+ cycle_clause->cycle_mark_type,
+ "CYCLE/SET/TO");
+ cycle_clause->cycle_mark_default =
+ coerce_to_common_type(pstate,
+ cycle_clause->cycle_mark_default,
+ cycle_clause->cycle_mark_type,
+ "CYCLE/SET/DEFAULT");
+
+ cycle_clause->cycle_mark_typmod =
+ select_common_typmod(pstate,
+ list_make2(cycle_clause->cycle_mark_value,
+ cycle_clause->cycle_mark_default),
+ cycle_clause->cycle_mark_type);
+
+ cycle_clause->cycle_mark_collation =
+ select_common_collation(pstate,
+ list_make2(cycle_clause->cycle_mark_value,
+ cycle_clause->cycle_mark_default),
+ true);
+
+ /* Might as well look up the relevant <> operator while we are at it */
+ typentry = lookup_type_cache(cycle_clause->cycle_mark_type,
+ TYPECACHE_EQ_OPR);
+ if (!OidIsValid(typentry->eq_opr))
+ ereport(ERROR,
+ errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("could not identify an equality operator for type %s",
+ format_type_be(cycle_clause->cycle_mark_type)));
+ op = get_negator(typentry->eq_opr);
+ if (!OidIsValid(op))
+ ereport(ERROR,
+ errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("could not identify an inequality operator for type %s",
+ format_type_be(cycle_clause->cycle_mark_type)));
+
+ cycle_clause->cycle_mark_neop = op;
+ }
+
+ /* Now we can get on with analyzing the CTE's query */
query = parse_sub_analyze(cte->ctequery, pstate, cte, false, true);
cte->ctequery = (Node *) query;
elog(ERROR, "wrong number of output columns in WITH");
}
- if (cte->search_clause || cte->cycle_clause)
+ /*
+ * Now make validity checks on the SEARCH and CYCLE clauses, if present.
+ */
+ if (search_clause || cycle_clause)
{
Query *ctequery;
SetOperationStmt *sos;
errmsg("with a SEARCH or CYCLE clause, the right side of the UNION must be a SELECT")));
}
- if (cte->search_clause)
+ if (search_clause)
{
ListCell *lc;
List *seen = NIL;
- foreach(lc, cte->search_clause->search_col_list)
+ foreach(lc, search_clause->search_col_list)
{
String *colname = lfirst_node(String, lc);
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("search column \"%s\" not in WITH query column list",
strVal(colname)),
- parser_errposition(pstate, cte->search_clause->location)));
+ parser_errposition(pstate, search_clause->location)));
if (list_member(seen, colname))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_COLUMN),
errmsg("search column \"%s\" specified more than once",
strVal(colname)),
- parser_errposition(pstate, cte->search_clause->location)));
+ parser_errposition(pstate, search_clause->location)));
seen = lappend(seen, colname);
}
- if (list_member(cte->ctecolnames, makeString(cte->search_clause->search_seq_column)))
+ if (list_member(cte->ctecolnames, makeString(search_clause->search_seq_column)))
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("search sequence column name \"%s\" already used in WITH query column list",
- cte->search_clause->search_seq_column),
- parser_errposition(pstate, cte->search_clause->location));
+ search_clause->search_seq_column),
+ parser_errposition(pstate, search_clause->location));
}
- if (cte->cycle_clause)
+ if (cycle_clause)
{
ListCell *lc;
List *seen = NIL;
- TypeCacheEntry *typentry;
- Oid op;
- foreach(lc, cte->cycle_clause->cycle_col_list)
+ foreach(lc, cycle_clause->cycle_col_list)
{
String *colname = lfirst_node(String, lc);
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cycle column \"%s\" not in WITH query column list",
strVal(colname)),
- parser_errposition(pstate, cte->cycle_clause->location)));
+ parser_errposition(pstate, cycle_clause->location)));
if (list_member(seen, colname))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_COLUMN),
errmsg("cycle column \"%s\" specified more than once",
strVal(colname)),
- parser_errposition(pstate, cte->cycle_clause->location)));
+ parser_errposition(pstate, cycle_clause->location)));
seen = lappend(seen, colname);
}
- if (list_member(cte->ctecolnames, makeString(cte->cycle_clause->cycle_mark_column)))
+ if (list_member(cte->ctecolnames, makeString(cycle_clause->cycle_mark_column)))
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cycle mark column name \"%s\" already used in WITH query column list",
- cte->cycle_clause->cycle_mark_column),
- parser_errposition(pstate, cte->cycle_clause->location));
-
- cte->cycle_clause->cycle_mark_value = transformExpr(pstate, cte->cycle_clause->cycle_mark_value,
- EXPR_KIND_CYCLE_MARK);
- cte->cycle_clause->cycle_mark_default = transformExpr(pstate, cte->cycle_clause->cycle_mark_default,
- EXPR_KIND_CYCLE_MARK);
+ cycle_clause->cycle_mark_column),
+ parser_errposition(pstate, cycle_clause->location));
- if (list_member(cte->ctecolnames, makeString(cte->cycle_clause->cycle_path_column)))
+ if (list_member(cte->ctecolnames, makeString(cycle_clause->cycle_path_column)))
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cycle path column name \"%s\" already used in WITH query column list",
- cte->cycle_clause->cycle_path_column),
- parser_errposition(pstate, cte->cycle_clause->location));
+ cycle_clause->cycle_path_column),
+ parser_errposition(pstate, cycle_clause->location));
- if (strcmp(cte->cycle_clause->cycle_mark_column,
- cte->cycle_clause->cycle_path_column) == 0)
+ if (strcmp(cycle_clause->cycle_mark_column,
+ cycle_clause->cycle_path_column) == 0)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cycle mark column name and cycle path column name are the same"),
- parser_errposition(pstate, cte->cycle_clause->location));
-
- cte->cycle_clause->cycle_mark_type = select_common_type(pstate,
- list_make2(cte->cycle_clause->cycle_mark_value,
- cte->cycle_clause->cycle_mark_default),
- "CYCLE", NULL);
- cte->cycle_clause->cycle_mark_value = coerce_to_common_type(pstate,
- cte->cycle_clause->cycle_mark_value,
- cte->cycle_clause->cycle_mark_type,
- "CYCLE/SET/TO");
- cte->cycle_clause->cycle_mark_default = coerce_to_common_type(pstate,
- cte->cycle_clause->cycle_mark_default,
- cte->cycle_clause->cycle_mark_type,
- "CYCLE/SET/DEFAULT");
-
- cte->cycle_clause->cycle_mark_typmod = select_common_typmod(pstate,
- list_make2(cte->cycle_clause->cycle_mark_value,
- cte->cycle_clause->cycle_mark_default),
- cte->cycle_clause->cycle_mark_type);
-
- cte->cycle_clause->cycle_mark_collation = select_common_collation(pstate,
- list_make2(cte->cycle_clause->cycle_mark_value,
- cte->cycle_clause->cycle_mark_default),
- true);
-
- typentry = lookup_type_cache(cte->cycle_clause->cycle_mark_type, TYPECACHE_EQ_OPR);
- if (!typentry->eq_opr)
- ereport(ERROR,
- errcode(ERRCODE_UNDEFINED_FUNCTION),
- errmsg("could not identify an equality operator for type %s",
- format_type_be(cte->cycle_clause->cycle_mark_type)));
- op = get_negator(typentry->eq_opr);
- if (!op)
- ereport(ERROR,
- errcode(ERRCODE_UNDEFINED_FUNCTION),
- errmsg("could not identify an inequality operator for type %s",
- format_type_be(cte->cycle_clause->cycle_mark_type)));
-
- cte->cycle_clause->cycle_mark_neop = op;
+ parser_errposition(pstate, cycle_clause->location));
}
- if (cte->search_clause && cte->cycle_clause)
+ if (search_clause && cycle_clause)
{
- if (strcmp(cte->search_clause->search_seq_column,
- cte->cycle_clause->cycle_mark_column) == 0)
+ if (strcmp(search_clause->search_seq_column,
+ cycle_clause->cycle_mark_column) == 0)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("search sequence column name and cycle mark column name are the same"),
- parser_errposition(pstate, cte->search_clause->location));
+ parser_errposition(pstate, search_clause->location));
- if (strcmp(cte->search_clause->search_seq_column,
- cte->cycle_clause->cycle_path_column) == 0)
+ if (strcmp(search_clause->search_seq_column,
+ cycle_clause->cycle_path_column) == 0)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("search sequence column name and cycle path column name are the same"),
- parser_errposition(pstate, cte->search_clause->location));
+ parser_errposition(pstate, search_clause->location));
}
}