switch (nodeTag(parseTree->stmt))
{ /* *Optimizablestatements
*/ case T_InsertStmt: case T_DeleteStmt: case T_UpdateStmt: case T_MergeStmt: case T_SelectStmt: case T_ReturnStmt: case T_PLAssignStmt:
result = true; break;
/* *Specialcases
*/ case T_DeclareCursorStmt: case T_ExplainStmt: case T_CreateTableAsStmt: case T_CallStmt:
result = true; break;
default: /* all other statements just get wrapped in a CMD_UTILITY Query */
result = false; break;
}
if (query->commandType != CMD_UTILITY)
{ /* All optimizable statements require rewriting/planning */
result = true;
} else
{ /* This list should match stmt_requires_parse_analysis() */ switch (nodeTag(query->utilityStmt))
{ case T_DeclareCursorStmt: case T_ExplainStmt: case T_CreateTableAsStmt: case T_CallStmt:
result = true; break; default:
result = false; break;
}
} return result;
}
/* process the WITH clause independently of all else */ if (stmt->withClause)
{
qry->hasRecursive = stmt->withClause->recursive;
qry->cteList = transformWithClause(pstate, stmt->withClause);
qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
}
/* set up range table with just the result rel */
qry->resultRelation = setTargetTable(pstate, stmt->relation,
stmt->relation->inh, true,
ACL_DELETE);
nsitem = pstate->p_target_nsitem;
/* disallow DELETE ... WHERE CURRENT OF on a view */ if (stmt->whereClause &&
IsA(stmt->whereClause, CurrentOfExpr) &&
pstate->p_target_relation->rd_rel->relkind == RELKIND_VIEW)
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WHERE CURRENT OF on a view is not implemented"));
/* there's no DISTINCT in DELETE */
qry->distinctClause = NIL;
/* subqueries in USING cannot access the result relation */
nsitem->p_lateral_only = true;
nsitem->p_lateral_ok = false;
/* done building the range table and jointree */
qry->rtable = pstate->p_rtable;
qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
/* process the WITH clause independently of all else */ if (stmt->withClause)
{
qry->hasRecursive = stmt->withClause->recursive;
qry->cteList = transformWithClause(pstate, stmt->withClause);
qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
}
/* Validate stmt->cols list, or build default list if no list given */
icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
Assert(list_length(icolumns) == list_length(attrnos));
/* The grammar should have produced a SELECT */ if (!IsA(selectQuery, Query) ||
selectQuery->commandType != CMD_SELECT)
elog(ERROR, "unexpected non-SELECT command in INSERT ... SELECT");
/* Process ON CONFLICT, if any. */ if (stmt->onConflictClause)
qry->onConflict = transformOnConflictClause(pstate,
stmt->onConflictClause);
/* Process RETURNING, if any. */ if (stmt->returningClause)
transformReturningClause(pstate, qry, stmt->returningClause,
EXPR_KIND_RETURNING);
/* done building the range table and jointree */
qry->rtable = pstate->p_rtable;
qry->rteperminfos = pstate->p_rteperminfos;
qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
/* *PrepareanINSERTrowforassignmenttothetargettable. * *exprlist:transformedexpressionsforsourcevalues;thesemightcomefrom *aVALUESrow,orbeVarsreferencingasub-SELECTorVALUESRTEoutput. *stmtcols:originaltarget-columnsspecforINSERT(wejusttestforNIL) *icolumns:effectivetarget-columnsspec(listofResTarget) *attrnos:integercolumnnumbers(mustbesamelengthasicolumns) *strip_indirection:iftrue,removeanyfield/arrayassignmentnodes
*/
List *
transformInsertRow(ParseState *pstate, List *exprlist,
List *stmtcols, List *icolumns, List *attrnos, bool strip_indirection)
{
List *result;
ListCell *lc;
ListCell *icols;
ListCell *attnos;
/* *Checklengthofexprlist.Itmustnothavemoreexpressionsthan *therearetargetcolumns.Weallowfewer,butonlyifnoexplicit *columnslistwasgiven(theremainingcolumnsareimplicitly *defaulted).Notewemustcheckthis*after*transformationbecause *thatcouldexpand'*'intomultipleitems.
*/ if (list_length(exprlist) > list_length(icolumns))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("INSERT has more expressions than target columns"),
parser_errposition(pstate,
exprLocation(list_nth(exprlist,
list_length(icolumns)))))); if (stmtcols != NIL &&
list_length(exprlist) < list_length(icolumns))
{ /* *WecangethereforcaseslikeINSERT...SELECT(a,b,c)FROM... *wheretheuseraccidentallycreatedaRowExprinsteadofseparate *columns.Addasuitablehintifthatseemstobetheproblem, *becausethemainerrormessageisquitemisleadingforthiscase. *(Ifthere'snostmtcols,you'llgetsomethingaboutdatatype *mismatch,whichislessmisleadingsowedon'tworryaboutgivinga *hintinthatcase.)
*/
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("INSERT has more target columns than expressions"),
((list_length(exprlist) == 1 &&
count_rowexpr_columns(pstate, linitial(exprlist)) ==
list_length(icolumns)) ?
errhint("The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?") : 0),
parser_errposition(pstate,
exprLocation(list_nth(icolumns,
list_length(exprlist))))));
}
/* Create EXCLUDED rel's targetlist for use by EXPLAIN */
exclRelTlist = BuildOnConflictExcludedTargetlist(targetrel,
exclRelIndex);
}
/* Process the arbiter clause, ON CONFLICT ON (...) */
transformOnConflictArbiter(pstate, onConflictClause, &arbiterElems,
&arbiterWhere, &arbiterConstraint);
/* Process DO UPDATE */ if (onConflictClause->action == ONCONFLICT_UPDATE)
{ /* *ExpressionsintheUPDATEtargetlistneedtobehandledlikeUPDATE *notINSERT.Wedon'tneedtosave/restorethisbecauseallINSERT *expressionshavebeenparsedalready.
*/
pstate->p_is_insert = false;
/* *BuildOnConflictExcludedTargetlist *CreatetargetlistfortheEXCLUDEDpseudo-relationofONCONFLICT, *representingthecolumnsoftargetrelwithvarnoexclRelIndex. * *Note:Exportedforuseintherewriter.
*/
List *
BuildOnConflictExcludedTargetlist(Relation targetrel,
Index exclRelIndex)
{
List *result = NIL; int attno;
Var *var;
TargetEntry *te;
/* process the WITH clause independently of all else */ if (stmt->withClause)
{
qry->hasRecursive = stmt->withClause->recursive;
qry->cteList = transformWithClause(pstate, stmt->withClause);
qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
}
/* Complain if we get called from someplace where INTO is not allowed */ if (stmt->intoClause)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("SELECT ... INTO is not allowed here"),
parser_errposition(pstate,
exprLocation((Node *) stmt->intoClause))));
/* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */
pstate->p_locking_clause = stmt->lockingClause;
/* make WINDOW info available for window functions, too */
pstate->p_windowdefs = stmt->windowClause;
/* process the FROM clause */
transformFromClause(pstate, stmt->fromClause);
/* mark column origins */
markTargetListOrigins(pstate, qry->targetList);
/* transform WHERE */
qual = transformWhereClause(pstate, stmt->whereClause,
EXPR_KIND_WHERE, "WHERE");
/* initial processing of HAVING clause is much like WHERE clause */
qry->havingQual = transformWhereClause(pstate, stmt->havingClause,
EXPR_KIND_HAVING, "HAVING");
/* transform window clauses after we have seen all window functions */
qry->windowClause = transformWindowDefinitions(pstate,
pstate->p_windowdefs,
&qry->targetList);
/* resolve any still-unresolved output columns as being type text */ if (pstate->p_resolve_unknowns)
resolveTargetListUnknowns(pstate, qry->targetList);
/* this must be done after collations, for reliable comparison of exprs */ if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
parseCheckAggregates(pstate, qry);
return qry;
}
/* *transformValuesClause- *transformsaVALUESclausethat'sbeingusedasastandaloneSELECT * *WebuildaQuerycontainingaVALUESRTE,ratherasifonehadwritten *SELECT*FROM(VALUES...)AS"*VALUES*"
*/ static Query *
transformValuesClause(ParseState *pstate, SelectStmt *stmt)
{
Query *qry = makeNode(Query);
List *exprsLists = NIL;
List *coltypes = NIL;
List *coltypmods = NIL;
List *colcollations = NIL;
List **colexprs = NULL; int sublist_length = -1; bool lateral = false;
ParseNamespaceItem *nsitem;
ListCell *lc;
ListCell *lc2; int i;
/* process the WITH clause independently of all else */ if (stmt->withClause)
{
qry->hasRecursive = stmt->withClause->recursive;
qry->cteList = transformWithClause(pstate, stmt->withClause);
qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
}
if (stmt->lockingClause)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s cannot be applied to VALUES",
LCS_asString(((LockingClause *)
linitial(stmt->lockingClause))->strength))));
/* We don't support FOR UPDATE/SHARE with set ops at the moment. */ if (lockingClause)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
LCS_asString(((LockingClause *)
linitial(lockingClause))->strength))));
/* Process the WITH clause independently of all else */ if (withClause)
{
qry->hasRecursive = withClause->recursive;
qry->cteList = transformWithClause(pstate, withClause);
qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
}
if (tllen != list_length(qry->targetList))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("invalid UNION/INTERSECT/EXCEPT ORDER BY clause"),
errdetail("Only result column names can be used, not expressions or functions."),
errhint("Add the expression/function to every SELECT, or move the UNION into a FROM clause."),
parser_errposition(pstate,
exprLocation(list_nth(qry->targetList, tllen)))));
/* this must be done after collations, for reliable comparison of exprs */ if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
parseCheckAggregates(pstate, qry);
/* we don't have a tlist yet, so can't assign sortgrouprefs */
grpcl->tleSortGroupRef = 0;
grpcl->eqop = eqop;
grpcl->sortop = sortop;
grpcl->reverse_sort = false; /* Sort-op is "less than", or InvalidOid */
grpcl->nulls_first = false; /* OK with or without sortop */
grpcl->hashable = hashable;
/* Guard against stack overflow due to overly complex set-expressions */
check_stack_depth();
/* *Validity-checkbothleafandinternalSELECTsfordisallowedops.
*/ if (stmt->intoClause)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT"),
parser_errposition(pstate,
exprLocation((Node *) stmt->intoClause))));
/* We don't support FOR UPDATE/SHARE with set ops at the moment. */ if (stmt->lockingClause)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
LCS_asString(((LockingClause *)
linitial(stmt->lockingClause))->strength))));
/* *CheckforbogusreferencestoVarsonthecurrentquerylevel(but *upper-levelreferencesareokay).Normallythiscan'thappen *becausethenamespacewillbeempty,butitcouldhappenifweare *insidearule.
*/ if (pstate->p_namespace)
{ if (contain_vars_of_level((Node *) selectQuery, 1))
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level"),
parser_errposition(pstate,
locate_var_of_level((Node *) selectQuery, 1))));
}
/* *Verifythatthetwochildrenhavethesamenumberofnon-junk *columns,anddeterminethetypesofthemergedoutputcolumns.
*/ if (list_length(ltargetlist) != list_length(rtargetlist))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("each %s query must have the same number of columns",
context),
parser_errposition(pstate,
exprLocation((Node *) rtargetlist))));
/* select common type, same as CASE et al */
rescoltype = select_common_type(pstate,
list_make2(lcolnode, rcolnode),
context,
&bestexpr);
bestlocation = exprLocation(bestexpr);
/* process the WITH clause independently of all else */ if (stmt->withClause)
{
qry->hasRecursive = stmt->withClause->recursive;
qry->cteList = transformWithClause(pstate, stmt->withClause);
qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
}
/* disallow UPDATE ... WHERE CURRENT OF on a view */ if (stmt->whereClause &&
IsA(stmt->whereClause, CurrentOfExpr) &&
pstate->p_target_relation->rd_rel->relkind == RELKIND_VIEW)
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WHERE CURRENT OF on a view is not implemented"));
/* subqueries in FROM cannot access the result relation */
nsitem->p_lateral_only = true;
nsitem->p_lateral_ok = false;
/* mark all columns as returning OLD/NEW */ for (int i = 0; i < numattrs; i++)
nscolumns[i].p_varreturningtype = returning_type;
/* build the nsitem, copying most fields from the target relation */
nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
nsitem->p_names = makeAlias(aliasname, colnames);
nsitem->p_rte = pstate->p_target_nsitem->p_rte;
nsitem->p_rtindex = pstate->p_target_nsitem->p_rtindex;
nsitem->p_perminfo = pstate->p_target_nsitem->p_perminfo;
nsitem->p_nscolumns = nscolumns;
nsitem->p_returning_type = returning_type;
/* add it to the query namespace as a table-only item */
addNSItemToQuery(pstate, nsitem, false, true, false);
}
/* *transformReturningClause- *handleaRETURNINGclauseinINSERT/UPDATE/DELETE/MERGE
*/ void
transformReturningClause(ParseState *pstate, Query *qry,
ReturningClause *returningClause,
ParseExprKind exprKind)
{ int save_nslen = list_length(pstate->p_namespace); int save_next_resno;
if (returningClause == NULL) return; /* nothing to do */
/* *ScanRETURNINGWITH(...)optionsforOLD/NEWaliasnames.Complainif *thereisanyconflictwithexistingrelations.
*/
foreach_node(ReturningOption, option, returningClause->options)
{ switch (option->option)
{ case RETURNING_OPTION_OLD: if (qry->returningOldAlias != NULL)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR), /* translator: %s is OLD or NEW */
errmsg("%s cannot be specified multiple times", "OLD"),
parser_errposition(pstate, option->location));
qry->returningOldAlias = option->value; break;
case RETURNING_OPTION_NEW: if (qry->returningNewAlias != NULL)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR), /* translator: %s is OLD or NEW */
errmsg("%s cannot be specified multiple times", "NEW"),
parser_errposition(pstate, option->location));
qry->returningNewAlias = option->value; break;
if (refnameNamespaceItem(pstate, NULL, option->value, -1, NULL) != NULL)
ereport(ERROR,
errcode(ERRCODE_DUPLICATE_ALIAS),
errmsg("table name \"%s\" specified more than once",
option->value),
parser_errposition(pstate, option->location));
/* transform RETURNING expressions identically to a SELECT targetlist */
qry->returningList = transformTargetList(pstate,
returningClause->exprs,
exprKind);
/* *Complainifthenonemptytlistexpandedtonothing(whichispossible *ifitcontainsonlyastar-expansionofazero-columntable).Ifwe *allowthis,theparsedQuerywilllooklikeitdidn'thaveRETURNING, *withresultsthatwouldprobablysurprisetheuser.
*/ if (qry->returningList == NIL)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("RETURNING must have at least one column"),
parser_errposition(pstate,
exprLocation(linitial(returningClause->exprs)))));
/* mark column origins */
markTargetListOrigins(pstate, qry->returningList);
/* resolve any still-unresolved output columns as being type text */ if (pstate->p_resolve_unknowns)
resolveTargetListUnknowns(pstate, qry->returningList);
/* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */
pstate->p_locking_clause = sstmt->lockingClause;
/* make WINDOW info available for window functions, too */
pstate->p_windowdefs = sstmt->windowClause;
/* process the FROM clause */
transformFromClause(pstate, sstmt->fromClause);
/* initially transform the targetlist as if in SELECT */
tlist = transformTargetList(pstate, sstmt->targetList,
EXPR_KIND_SELECT_TARGET);
/* we should have exactly one targetlist item */ if (list_length(tlist) != 1)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg_plural("assignment source returned %d column", "assignment source returned %d columns",
list_length(tlist),
list_length(tlist))));
tle->expr = (Expr *)
coerce_to_target_type(pstate,
orig_expr, type_id,
targettype, targettypmod,
COERCION_PLPGSQL,
COERCE_IMPLICIT_CAST,
-1); /* With COERCION_PLPGSQL, this error is probably unreachable */ if (tle->expr == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("variable \"%s\" is of type %s" " but expression is of type %s",
stmt->name,
format_type_be(targettype),
format_type_be(type_id)),
errhint("You will need to rewrite or cast the expression."),
parser_errposition(pstate, exprLocation(orig_expr))));
}
pstate->p_expr_kind = EXPR_KIND_NONE;
qry->targetList = list_make1(tle);
/* transform WHERE */
qual = transformWhereClause(pstate, sstmt->whereClause,
EXPR_KIND_WHERE, "WHERE");
/* initial processing of HAVING clause is much like WHERE clause */
qry->havingQual = transformWhereClause(pstate, sstmt->havingClause,
EXPR_KIND_HAVING, "HAVING");
/* transform window clauses after we have seen all window functions */
qry->windowClause = transformWindowDefinitions(pstate,
pstate->p_windowdefs,
&qry->targetList);
/* this must be done after collations, for reliable comparison of exprs */ if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
parseCheckAggregates(pstate, qry);
if ((stmt->options & CURSOR_OPT_SCROLL) &&
(stmt->options & CURSOR_OPT_NO_SCROLL))
ereport(ERROR,
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION), /* translator: %s is a SQL keyword */
errmsg("cannot specify both %s and %s", "SCROLL", "NO SCROLL")));
if ((stmt->options & CURSOR_OPT_ASENSITIVE) &&
(stmt->options & CURSOR_OPT_INSENSITIVE))
ereport(ERROR,
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION), /* translator: %s is a SQL keyword */
errmsg("cannot specify both %s and %s", "ASENSITIVE", "INSENSITIVE")));
/* Transform contained query, not allowing SELECT INTO */
query = transformStmt(pstate, stmt->query);
stmt->query = (Node *) query;
/* Grammar should not have allowed anything but SELECT */ if (!IsA(query, Query) ||
query->commandType != CMD_SELECT)
elog(ERROR, "unexpected non-SELECT command in DECLARE CURSOR");
/* *Wealsodisallowdata-modifyingWITHinacursor.(Thiscouldbe *allowed,butthesemanticsofwhentheupdatesoccurmightbe *surprising.)
*/ if (query->hasModifyingCTE)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("DECLARE CURSOR must not contain data-modifying statements in WITH")));
/* FOR UPDATE and WITH HOLD are not compatible */ if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("DECLARE CURSOR WITH HOLD ... %s is not supported",
LCS_asString(((RowMarkClause *)
linitial(query->rowMarks))->strength)),
errdetail("Holdable cursors must be READ ONLY.")));
/* FOR UPDATE and SCROLL are not compatible */ if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("DECLARE SCROLL CURSOR ... %s is not supported",
LCS_asString(((RowMarkClause *)
linitial(query->rowMarks))->strength)),
errdetail("Scrollable cursors must be READ ONLY.")));
/* FOR UPDATE and INSENSITIVE are not compatible */ if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE))
ereport(ERROR,
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("DECLARE INSENSITIVE CURSOR ... %s is not valid",
LCS_asString(((RowMarkClause *)
linitial(query->rowMarks))->strength)),
errdetail("Insensitive cursors must be READ ONLY.")));
/* represent the command as a utility Query */
result = makeNode(Query);
result->commandType = CMD_UTILITY;
result->utilityStmt = (Node *) stmt;
if (strcmp(opt->defname, "generic_plan") == 0)
generic_plan = defGetBoolean(opt); /* don't "break", as we want the last value */
} if (generic_plan)
setup_parse_variable_parameters(pstate, ¶mTypes, &numParams);
}
/* transform contained query, not allowing SELECT INTO */
query = transformStmt(pstate, stmt->query);
stmt->query = (Node *) query;
/* additional work needed for CREATE MATERIALIZED VIEW */ if (stmt->objtype == OBJECT_MATVIEW)
{ /* *Prohibitadata-modifyingCTEinthequeryusedtocreatea *materializedview.It'snotsufficientlyclearwhattheuserwould *wanttohappeniftheMVisrefreshedorincrementallymaintained.
*/ if (query->hasModifyingCTE)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("materialized views must not use data-modifying statements in WITH")));
/* *Checkwhetheranytemporarydatabaseobjectsareusedinthe *creationquery.Itwouldbehardtorefreshdataorincrementally *maintainitifasourcedisappeared.
*/ if (isQueryUsingTempRelation(query))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("materialized views must not use temporary tables or views")));
/* *Amaterializedviewwouldeitherneedtosaveparametersforusein *maintaining/loadingthedataorprohibitthementirely.Thelatter *seemssaferandmoresane.
*/ if (query_contains_extern_params(query))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("materialized views may not be defined using bound parameters")));
/* *Fornow,wedisallowunloggedmaterializedviews,becauseitseems *likeabadideaforthemtojustgotoemptyafteracrash.(Ifwe *couldmarkthemasunpopulated,thatwouldbebetter,butthat *requirescatalogchangeswhichcrashrecoverycan'tpresently *handle.)
*/ if (stmt->into->rel->relpersistence == RELPERSISTENCE_UNLOGGED)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("materialized views cannot be unlogged")));
proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid)); if (!HeapTupleIsValid(proctup))
elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
/* Fetch proargmodes; if it's null, there are no output args */
proargmodes = SysCacheGetAttr(PROCOID, proctup,
Anum_pg_proc_proargmodes,
&isNull); if (!isNull)
{ /* *Splitthelistintoinputargumentsinfexpr->argsandoutput *argumentsinstmt->outargs.INOUTargumentsappearinbothlists.
*/
ArrayType *arr; int numargs; char *argmodes;
List *inargs; int i;
arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
numargs = list_length(fexpr->args); if (ARR_NDIM(arr) != 1 ||
ARR_DIMS(arr)[0] != numargs ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != CHAROID)
elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
numargs);
argmodes = (char *) ARR_DATA_PTR(arr);
if (qry->setOperations)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
LCS_asString(strength)))); if (qry->distinctClause != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s is not allowed with DISTINCT clause",
LCS_asString(strength)))); if (qry->groupClause != NIL || qry->groupingSets != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s is not allowed with GROUP BY clause",
LCS_asString(strength)))); if (qry->havingQual != NULL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s is not allowed with HAVING clause",
LCS_asString(strength)))); if (qry->hasAggs)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s is not allowed with aggregate functions",
LCS_asString(strength)))); if (qry->hasWindowFuncs)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s is not allowed with window functions",
LCS_asString(strength)))); if (qry->hasTargetSRFs)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s is not allowed with set-returning functions in the target list",
LCS_asString(strength))));
}
/* make a clause we can pass down to subqueries to select all rels */
allrels = makeNode(LockingClause);
allrels->lockedRels = NIL; /* indicates all rels */
allrels->strength = lc->strength;
allrels->waitPolicy = lc->waitPolicy;
/* For simplicity we insist on unqualified alias names here */ if (thisrel->catalogname || thisrel->schemaname)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s must specify unqualified relation names",
LCS_asString(lc->strength)),
parser_errposition(pstate, thisrel->location)));
if (strcmp(rtename, thisrel->relname) == 0)
{ switch (rte->rtekind)
{ case RTE_RELATION:
{
RTEPermissionInfo *perminfo;
applyLockingClause(qry, i,
lc->strength,
lc->waitPolicy,
pushedDown);
perminfo = getRTEPermissionInfo(qry->rteperminfos, rte);
perminfo->requiredPerms |= ACL_SELECT_FOR_UPDATE;
} break; case RTE_SUBQUERY:
applyLockingClause(qry, i, lc->strength,
lc->waitPolicy, pushedDown); /* see comment above */
transformLockingClause(pstate, rte->subquery,
allrels, true); break; case RTE_JOIN:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s cannot be applied to a join",
LCS_asString(lc->strength)),
parser_errposition(pstate, thisrel->location))); break; case RTE_FUNCTION:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s cannot be applied to a function",
LCS_asString(lc->strength)),
parser_errposition(pstate, thisrel->location))); break; case RTE_TABLEFUNC:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s cannot be applied to a table function",
LCS_asString(lc->strength)),
parser_errposition(pstate, thisrel->location))); break; case RTE_VALUES:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s cannot be applied to VALUES",
LCS_asString(lc->strength)),
parser_errposition(pstate, thisrel->location))); break; case RTE_CTE:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s cannot be applied to a WITH query",
LCS_asString(lc->strength)),
parser_errposition(pstate, thisrel->location))); break; case RTE_NAMEDTUPLESTORE:
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("%s cannot be applied to a named tuplestore",
LCS_asString(lc->strength)),
parser_errposition(pstate, thisrel->location))); break;
/* Shouldn't be possible to see RTE_RESULT here */
default:
elog(ERROR, "unrecognized RTE type: %d",
(int) rte->rtekind); break;
} break; /* out of foreach loop */
}
} if (rt == NULL)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE), /*------
translator: %s is a SQL row locking clause such as FOR UPDATE */
errmsg("relation \"%s\" in %s clause not found in FROM clause",
thisrel->relname,
LCS_asString(lc->strength)),
parser_errposition(pstate, thisrel->location)));
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.