PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
rewriteHandler.h File Reference
#include "utils/relcache.h"
#include "nodes/parsenodes.h"
Include dependency graph for rewriteHandler.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

ListQueryRewrite (Query *parsetree)
 
void AcquireRewriteLocks (Query *parsetree, bool forExecute, bool forUpdatePushedDown)
 
Nodebuild_column_default (Relation rel, int attrno)
 
Queryget_view_query (Relation view)
 
const char * view_query_is_auto_updatable (Query *viewquery, bool check_cols)
 
int relation_is_updatable (Oid reloid, bool include_triggers, Bitmapset *include_cols)
 

Function Documentation

void AcquireRewriteLocks ( Query parsetree,
bool  forExecute,
bool  forUpdatePushedDown 
)

Definition at line 134 of file rewriteHandler.c.

References AccessShareLock, acquireLocksOnSubLinks(), AcquireRewriteLocks(), Assert, Query::cteList, CommonTableExpr::ctequery, elog, ERROR, acquireLocksOnSubLinks_context::for_execute, get_parse_rowmark(), get_rte_attribute_is_dropped(), Query::hasSubLinks, heap_close, heap_open(), IsA, RangeTblEntry::joinaliasvars, lappend(), lfirst, NIL, NoLock, NULL, QTW_IGNORE_RC_SUBQUERIES, query_tree_walker(), RelationData::rd_rel, RangeTblEntry::relid, RangeTblEntry::relkind, Query::resultRelation, RowExclusiveLock, RowShareLock, rt_fetch, Query::rtable, RTE_JOIN, RTE_RELATION, RTE_SUBQUERY, RangeTblEntry::rtekind, strip_implicit_coercions(), RangeTblEntry::subquery, Var::varattno, Var::varlevelsup, and Var::varno.

Referenced by acquireLocksOnSubLinks(), AcquireRewriteLocks(), ApplyRetrieveRule(), get_query_def(), make_ruledef(), refresh_matview_datafill(), and rewriteRuleAction().

137 {
138  ListCell *l;
139  int rt_index;
141 
142  context.for_execute = forExecute;
143 
144  /*
145  * First, process RTEs of the current query level.
146  */
147  rt_index = 0;
148  foreach(l, parsetree->rtable)
149  {
150  RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
151  Relation rel;
152  LOCKMODE lockmode;
153  List *newaliasvars;
154  Index curinputvarno;
155  RangeTblEntry *curinputrte;
156  ListCell *ll;
157 
158  ++rt_index;
159  switch (rte->rtekind)
160  {
161  case RTE_RELATION:
162 
163  /*
164  * Grab the appropriate lock type for the relation, and do not
165  * release it until end of transaction. This protects the
166  * rewriter and planner against schema changes mid-query.
167  *
168  * Assuming forExecute is true, this logic must match what the
169  * executor will do, else we risk lock-upgrade deadlocks.
170  */
171  if (!forExecute)
172  lockmode = AccessShareLock;
173  else if (rt_index == parsetree->resultRelation)
174  lockmode = RowExclusiveLock;
175  else if (forUpdatePushedDown ||
176  get_parse_rowmark(parsetree, rt_index) != NULL)
177  lockmode = RowShareLock;
178  else
179  lockmode = AccessShareLock;
180 
181  rel = heap_open(rte->relid, lockmode);
182 
183  /*
184  * While we have the relation open, update the RTE's relkind,
185  * just in case it changed since this rule was made.
186  */
187  rte->relkind = rel->rd_rel->relkind;
188 
189  heap_close(rel, NoLock);
190  break;
191 
192  case RTE_JOIN:
193 
194  /*
195  * Scan the join's alias var list to see if any columns have
196  * been dropped, and if so replace those Vars with null
197  * pointers.
198  *
199  * Since a join has only two inputs, we can expect to see
200  * multiple references to the same input RTE; optimize away
201  * multiple fetches.
202  */
203  newaliasvars = NIL;
204  curinputvarno = 0;
205  curinputrte = NULL;
206  foreach(ll, rte->joinaliasvars)
207  {
208  Var *aliasitem = (Var *) lfirst(ll);
209  Var *aliasvar = aliasitem;
210 
211  /* Look through any implicit coercion */
212  aliasvar = (Var *) strip_implicit_coercions((Node *) aliasvar);
213 
214  /*
215  * If the list item isn't a simple Var, then it must
216  * represent a merged column, ie a USING column, and so it
217  * couldn't possibly be dropped, since it's referenced in
218  * the join clause. (Conceivably it could also be a null
219  * pointer already? But that's OK too.)
220  */
221  if (aliasvar && IsA(aliasvar, Var))
222  {
223  /*
224  * The elements of an alias list have to refer to
225  * earlier RTEs of the same rtable, because that's the
226  * order the planner builds things in. So we already
227  * processed the referenced RTE, and so it's safe to
228  * use get_rte_attribute_is_dropped on it. (This might
229  * not hold after rewriting or planning, but it's OK
230  * to assume here.)
231  */
232  Assert(aliasvar->varlevelsup == 0);
233  if (aliasvar->varno != curinputvarno)
234  {
235  curinputvarno = aliasvar->varno;
236  if (curinputvarno >= rt_index)
237  elog(ERROR, "unexpected varno %d in JOIN RTE %d",
238  curinputvarno, rt_index);
239  curinputrte = rt_fetch(curinputvarno,
240  parsetree->rtable);
241  }
242  if (get_rte_attribute_is_dropped(curinputrte,
243  aliasvar->varattno))
244  {
245  /* Replace the join alias item with a NULL */
246  aliasitem = NULL;
247  }
248  }
249  newaliasvars = lappend(newaliasvars, aliasitem);
250  }
251  rte->joinaliasvars = newaliasvars;
252  break;
253 
254  case RTE_SUBQUERY:
255 
256  /*
257  * The subquery RTE itself is all right, but we have to
258  * recurse to process the represented subquery.
259  */
261  forExecute,
262  (forUpdatePushedDown ||
263  get_parse_rowmark(parsetree, rt_index) != NULL));
264  break;
265 
266  default:
267  /* ignore other types of RTEs */
268  break;
269  }
270  }
271 
272  /* Recurse into subqueries in WITH */
273  foreach(l, parsetree->cteList)
274  {
275  CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
276 
277  AcquireRewriteLocks((Query *) cte->ctequery, forExecute, false);
278  }
279 
280  /*
281  * Recurse into sublink subqueries, too. But we already did the ones in
282  * the rtable and cteList.
283  */
284  if (parsetree->hasSubLinks)
285  query_tree_walker(parsetree, acquireLocksOnSubLinks, &context,
287 }
#define NIL
Definition: pg_list.h:69
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2246
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
List * joinaliasvars
Definition: parsenodes.h:988
Index varlevelsup
Definition: primnodes.h:173
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
static bool acquireLocksOnSubLinks(Node *node, acquireLocksOnSubLinks_context *context)
int LOCKMODE
Definition: lockdefs.h:26
int resultRelation
Definition: parsenodes.h:120
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:509
AttrNumber varattno
Definition: primnodes.h:168
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
Definition: primnodes.h:163
#define QTW_IGNORE_RC_SUBQUERIES
Definition: nodeFuncs.h:22
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
List * lappend(List *list, void *datum)
Definition: list.c:128
Index varno
Definition: primnodes.h:166
#define RowShareLock
Definition: lockdefs.h:37
bool get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
unsigned int Index
Definition: c.h:365
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
#define lfirst(lc)
Definition: pg_list.h:106
RTEKind rtekind
Definition: parsenodes.h:944
List * cteList
Definition: parsenodes.h:133
Query * subquery
Definition: parsenodes.h:967
bool hasSubLinks
Definition: parsenodes.h:126
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
Node * strip_implicit_coercions(Node *node)
Definition: nodeFuncs.c:612
Node* build_column_default ( Relation  rel,
int  attrno 
)

Definition at line 1112 of file rewriteHandler.c.

References COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, tupleDesc::constr, tupleConstr::defval, ereport, errcode(), errhint(), errmsg(), ERROR, exprType(), format_type_be(), get_typdefault(), NameStr, NULL, tupleConstr::num_defval, RelationData::rd_att, stringToNode(), and TupleDescAttr.

Referenced by ATExecAddColumn(), ATExecAlterColumnType(), BeginCopyFrom(), rewriteTargetListIU(), rewriteValuesRTE(), and slot_fill_defaults().

1113 {
1114  TupleDesc rd_att = rel->rd_att;
1115  Form_pg_attribute att_tup = TupleDescAttr(rd_att, attrno - 1);
1116  Oid atttype = att_tup->atttypid;
1117  int32 atttypmod = att_tup->atttypmod;
1118  Node *expr = NULL;
1119  Oid exprtype;
1120 
1121  /*
1122  * Scan to see if relation has a default for this column.
1123  */
1124  if (rd_att->constr && rd_att->constr->num_defval > 0)
1125  {
1126  AttrDefault *defval = rd_att->constr->defval;
1127  int ndef = rd_att->constr->num_defval;
1128 
1129  while (--ndef >= 0)
1130  {
1131  if (attrno == defval[ndef].adnum)
1132  {
1133  /*
1134  * Found it, convert string representation to node tree.
1135  */
1136  expr = stringToNode(defval[ndef].adbin);
1137  break;
1138  }
1139  }
1140  }
1141 
1142  if (expr == NULL)
1143  {
1144  /*
1145  * No per-column default, so look for a default for the type itself.
1146  */
1147  expr = get_typdefault(atttype);
1148  }
1149 
1150  if (expr == NULL)
1151  return NULL; /* No default anywhere */
1152 
1153  /*
1154  * Make sure the value is coerced to the target column type; this will
1155  * generally be true already, but there seem to be some corner cases
1156  * involving domain defaults where it might not be true. This should match
1157  * the parser's processing of non-defaulted expressions --- see
1158  * transformAssignedExpr().
1159  */
1160  exprtype = exprType(expr);
1161 
1162  expr = coerce_to_target_type(NULL, /* no UNKNOWN params here */
1163  expr, exprtype,
1164  atttype, atttypmod,
1167  -1);
1168  if (expr == NULL)
1169  ereport(ERROR,
1170  (errcode(ERRCODE_DATATYPE_MISMATCH),
1171  errmsg("column \"%s\" is of type %s"
1172  " but default expression is of type %s",
1173  NameStr(att_tup->attname),
1174  format_type_be(atttype),
1175  format_type_be(exprtype)),
1176  errhint("You will need to rewrite or cast the expression.")));
1177 
1178  return expr;
1179 }
void * stringToNode(char *str)
Definition: read.c:38
int errhint(const char *fmt,...)
Definition: elog.c:987
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
Definition: nodes.h:509
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:256
AttrDefault * defval
Definition: tupdesc.h:39
#define ERROR
Definition: elog.h:43
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
Definition: parse_coerce.c:77
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ereport(elevel, rest)
Definition: elog.h:122
TupleDesc rd_att
Definition: rel.h:115
uint16 num_defval
Definition: tupdesc.h:41
#define NULL
Definition: c.h:229
Node * get_typdefault(Oid typid)
Definition: lsyscache.c:2198
TupleConstr * constr
Definition: tupdesc.h:78
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:499
Query* get_view_query ( Relation  view)

Definition at line 2130 of file rewriteHandler.c.

References RewriteRule::actions, Assert, CMD_SELECT, elog, ERROR, RewriteRule::event, i, linitial, list_length(), NULL, RuleLock::numLocks, RelationData::rd_rel, RelationData::rd_rules, RELKIND_VIEW, and RuleLock::rules.

Referenced by ATExecSetRelOptions(), relation_is_updatable(), and rewriteTargetView().

2131 {
2132  int i;
2133 
2134  Assert(view->rd_rel->relkind == RELKIND_VIEW);
2135 
2136  for (i = 0; i < view->rd_rules->numLocks; i++)
2137  {
2138  RewriteRule *rule = view->rd_rules->rules[i];
2139 
2140  if (rule->event == CMD_SELECT)
2141  {
2142  /* A _RETURN rule should have only one action */
2143  if (list_length(rule->actions) != 1)
2144  elog(ERROR, "invalid _RETURN rule action specification");
2145 
2146  return (Query *) linitial(rule->actions);
2147  }
2148  }
2149 
2150  elog(ERROR, "failed to find _RETURN rule for view");
2151  return NULL; /* keep compiler quiet */
2152 }
int numLocks
Definition: prs2lock.h:42
Form_pg_class rd_rel
Definition: rel.h:114
Definition: localtime.c:82
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
CmdType event
Definition: prs2lock.h:27
RewriteRule ** rules
Definition: prs2lock.h:43
List * actions
Definition: prs2lock.h:29
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
RuleLock * rd_rules
Definition: rel.h:118
static int list_length(const List *l)
Definition: pg_list.h:89
#define RELKIND_VIEW
Definition: pg_class.h:164
int i
#define elog
Definition: elog.h:219
List* QueryRewrite ( Query parsetree)

Definition at line 3576 of file rewriteHandler.c.

References Assert, Query::canSetTag, Query::commandType, fireRIRrules(), lappend(), lfirst, NIL, NULL, QSRC_INSTEAD_RULE, QSRC_ORIGINAL, QSRC_QUAL_INSTEAD_RULE, Query::queryId, Query::querySource, and RewriteQuery().

Referenced by ExecCreateTableAs(), ExplainOneUtility(), ExplainQuery(), PerformCursorOpen(), pg_rewrite_query(), PrepareQuery(), and refresh_matview_datafill().

3577 {
3578  uint32 input_query_id = parsetree->queryId;
3579  List *querylist;
3580  List *results;
3581  ListCell *l;
3582  CmdType origCmdType;
3583  bool foundOriginalQuery;
3584  Query *lastInstead;
3585 
3586  /*
3587  * This function is only applied to top-level original queries
3588  */
3589  Assert(parsetree->querySource == QSRC_ORIGINAL);
3590  Assert(parsetree->canSetTag);
3591 
3592  /*
3593  * Step 1
3594  *
3595  * Apply all non-SELECT rules possibly getting 0 or many queries
3596  */
3597  querylist = RewriteQuery(parsetree, NIL);
3598 
3599  /*
3600  * Step 2
3601  *
3602  * Apply all the RIR rules on each query
3603  *
3604  * This is also a handy place to mark each query with the original queryId
3605  */
3606  results = NIL;
3607  foreach(l, querylist)
3608  {
3609  Query *query = (Query *) lfirst(l);
3610 
3611  query = fireRIRrules(query, NIL, false);
3612 
3613  query->queryId = input_query_id;
3614 
3615  results = lappend(results, query);
3616  }
3617 
3618  /*
3619  * Step 3
3620  *
3621  * Determine which, if any, of the resulting queries is supposed to set
3622  * the command-result tag; and update the canSetTag fields accordingly.
3623  *
3624  * If the original query is still in the list, it sets the command tag.
3625  * Otherwise, the last INSTEAD query of the same kind as the original is
3626  * allowed to set the tag. (Note these rules can leave us with no query
3627  * setting the tag. The tcop code has to cope with this by setting up a
3628  * default tag based on the original un-rewritten query.)
3629  *
3630  * The Asserts verify that at most one query in the result list is marked
3631  * canSetTag. If we aren't checking asserts, we can fall out of the loop
3632  * as soon as we find the original query.
3633  */
3634  origCmdType = parsetree->commandType;
3635  foundOriginalQuery = false;
3636  lastInstead = NULL;
3637 
3638  foreach(l, results)
3639  {
3640  Query *query = (Query *) lfirst(l);
3641 
3642  if (query->querySource == QSRC_ORIGINAL)
3643  {
3644  Assert(query->canSetTag);
3645  Assert(!foundOriginalQuery);
3646  foundOriginalQuery = true;
3647 #ifndef USE_ASSERT_CHECKING
3648  break;
3649 #endif
3650  }
3651  else
3652  {
3653  Assert(!query->canSetTag);
3654  if (query->commandType == origCmdType &&
3655  (query->querySource == QSRC_INSTEAD_RULE ||
3657  lastInstead = query;
3658  }
3659  }
3660 
3661  if (!foundOriginalQuery && lastInstead != NULL)
3662  lastInstead->canSetTag = true;
3663 
3664  return results;
3665 }
#define NIL
Definition: pg_list.h:69
uint32 queryId
Definition: parsenodes.h:114
static List * RewriteQuery(Query *parsetree, List *rewrite_events)
unsigned int uint32
Definition: c.h:268
List * lappend(List *list, void *datum)
Definition: list.c:128
CmdType commandType
Definition: parsenodes.h:110
#define NULL
Definition: c.h:229
QuerySource querySource
Definition: parsenodes.h:112
#define Assert(condition)
Definition: c.h:676
#define lfirst(lc)
Definition: pg_list.h:106
static Query * fireRIRrules(Query *parsetree, List *activeRIRs, bool forUpdatePushedDown)
bool canSetTag
Definition: parsenodes.h:116
Definition: pg_list.h:45
CmdType
Definition: nodes.h:649
int relation_is_updatable ( Oid  reloid,
bool  include_triggers,
Bitmapset include_cols 
)

Definition at line 2466 of file rewriteHandler.c.

References AccessShareLock, adjust_view_column_set(), ALL_EVENTS, Assert, bms_int_members(), bms_is_empty(), CMD_DELETE, CMD_INSERT, CMD_UPDATE, RewriteRule::event, FdwRoutine::ExecForeignDelete, FdwRoutine::ExecForeignInsert, FdwRoutine::ExecForeignUpdate, FromExpr::fromlist, get_view_query(), GetFdwRoutineForRelation(), i, FdwRoutine::IsForeignRelUpdatable, RewriteRule::isInstead, Query::jointree, linitial, NULL, RuleLock::numLocks, RewriteRule::qual, RelationData::rd_rel, RelationData::rd_rules, relation_close(), relation_is_updatable(), RangeTblEntry::relid, RangeTblEntry::relkind, RELKIND_FOREIGN_TABLE, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_VIEW, rt_fetch, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, RangeTblRef::rtindex, RuleLock::rules, Query::targetList, TriggerDesc::trig_delete_instead_row, TriggerDesc::trig_insert_instead_row, TriggerDesc::trig_update_instead_row, RelationData::trigdesc, try_relation_open(), view_cols_are_auto_updatable(), and view_query_is_auto_updatable().

Referenced by pg_column_is_updatable(), pg_relation_is_updatable(), and relation_is_updatable().

2469 {
2470  int events = 0;
2471  Relation rel;
2472  RuleLock *rulelocks;
2473 
2474 #define ALL_EVENTS ((1 << CMD_INSERT) | (1 << CMD_UPDATE) | (1 << CMD_DELETE))
2475 
2476  rel = try_relation_open(reloid, AccessShareLock);
2477 
2478  /*
2479  * If the relation doesn't exist, return zero rather than throwing an
2480  * error. This is helpful since scanning an information_schema view under
2481  * MVCC rules can result in referencing rels that have actually been
2482  * deleted already.
2483  */
2484  if (rel == NULL)
2485  return 0;
2486 
2487  /* If the relation is a table, it is always updatable */
2488  if (rel->rd_rel->relkind == RELKIND_RELATION ||
2489  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2490  {
2492  return ALL_EVENTS;
2493  }
2494 
2495  /* Look for unconditional DO INSTEAD rules, and note supported events */
2496  rulelocks = rel->rd_rules;
2497  if (rulelocks != NULL)
2498  {
2499  int i;
2500 
2501  for (i = 0; i < rulelocks->numLocks; i++)
2502  {
2503  if (rulelocks->rules[i]->isInstead &&
2504  rulelocks->rules[i]->qual == NULL)
2505  {
2506  events |= ((1 << rulelocks->rules[i]->event) & ALL_EVENTS);
2507  }
2508  }
2509 
2510  /* If we have rules for all events, we're done */
2511  if (events == ALL_EVENTS)
2512  {
2514  return events;
2515  }
2516  }
2517 
2518  /* Similarly look for INSTEAD OF triggers, if they are to be included */
2519  if (include_triggers)
2520  {
2521  TriggerDesc *trigDesc = rel->trigdesc;
2522 
2523  if (trigDesc)
2524  {
2525  if (trigDesc->trig_insert_instead_row)
2526  events |= (1 << CMD_INSERT);
2527  if (trigDesc->trig_update_instead_row)
2528  events |= (1 << CMD_UPDATE);
2529  if (trigDesc->trig_delete_instead_row)
2530  events |= (1 << CMD_DELETE);
2531 
2532  /* If we have triggers for all events, we're done */
2533  if (events == ALL_EVENTS)
2534  {
2536  return events;
2537  }
2538  }
2539  }
2540 
2541  /* If this is a foreign table, check which update events it supports */
2542  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2543  {
2544  FdwRoutine *fdwroutine = GetFdwRoutineForRelation(rel, false);
2545 
2546  if (fdwroutine->IsForeignRelUpdatable != NULL)
2547  events |= fdwroutine->IsForeignRelUpdatable(rel);
2548  else
2549  {
2550  /* Assume presence of executor functions is sufficient */
2551  if (fdwroutine->ExecForeignInsert != NULL)
2552  events |= (1 << CMD_INSERT);
2553  if (fdwroutine->ExecForeignUpdate != NULL)
2554  events |= (1 << CMD_UPDATE);
2555  if (fdwroutine->ExecForeignDelete != NULL)
2556  events |= (1 << CMD_DELETE);
2557  }
2558 
2560  return events;
2561  }
2562 
2563  /* Check if this is an automatically updatable view */
2564  if (rel->rd_rel->relkind == RELKIND_VIEW)
2565  {
2566  Query *viewquery = get_view_query(rel);
2567 
2568  if (view_query_is_auto_updatable(viewquery, false) == NULL)
2569  {
2570  Bitmapset *updatable_cols;
2571  int auto_events;
2572  RangeTblRef *rtr;
2573  RangeTblEntry *base_rte;
2574  Oid baseoid;
2575 
2576  /*
2577  * Determine which of the view's columns are updatable. If there
2578  * are none within the set of columns we are looking at, then the
2579  * view doesn't support INSERT/UPDATE, but it may still support
2580  * DELETE.
2581  */
2583  &updatable_cols, NULL);
2584 
2585  if (include_cols != NULL)
2586  updatable_cols = bms_int_members(updatable_cols, include_cols);
2587 
2588  if (bms_is_empty(updatable_cols))
2589  auto_events = (1 << CMD_DELETE); /* May support DELETE */
2590  else
2591  auto_events = ALL_EVENTS; /* May support all events */
2592 
2593  /*
2594  * The base relation must also support these update commands.
2595  * Tables are always updatable, but for any other kind of base
2596  * relation we must do a recursive check limited to the columns
2597  * referenced by the locally updatable columns in this view.
2598  */
2599  rtr = (RangeTblRef *) linitial(viewquery->jointree->fromlist);
2600  base_rte = rt_fetch(rtr->rtindex, viewquery->rtable);
2601  Assert(base_rte->rtekind == RTE_RELATION);
2602 
2603  if (base_rte->relkind != RELKIND_RELATION &&
2604  base_rte->relkind != RELKIND_PARTITIONED_TABLE)
2605  {
2606  baseoid = base_rte->relid;
2607  include_cols = adjust_view_column_set(updatable_cols,
2608  viewquery->targetList);
2609  auto_events &= relation_is_updatable(baseoid,
2610  include_triggers,
2611  include_cols);
2612  }
2613  events |= auto_events;
2614  }
2615  }
2616 
2617  /* If we reach here, the relation may support some update commands */
2619  return events;
2620 }
ExecForeignDelete_function ExecForeignDelete
Definition: fdwapi.h:199
Node * qual
Definition: prs2lock.h:28
int numLocks
Definition: prs2lock.h:42
FromExpr * jointree
Definition: parsenodes.h:136
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1153
ExecForeignInsert_function ExecForeignInsert
Definition: fdwapi.h:197
static const char * view_cols_are_auto_updatable(Query *viewquery, Bitmapset *required_cols, Bitmapset **updatable_cols, char **non_updatable_col)
#define AccessShareLock
Definition: lockdefs.h:36
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
List * fromlist
Definition: primnodes.h:1471
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
bool isInstead
Definition: prs2lock.h:31
List * targetList
Definition: parsenodes.h:138
bool trig_insert_instead_row
Definition: reltrigger.h:57
#define linitial(l)
Definition: pg_list.h:111
List * rtable
Definition: parsenodes.h:135
#define ALL_EVENTS
TriggerDesc * trigdesc
Definition: rel.h:120
int relation_is_updatable(Oid reloid, bool include_triggers, Bitmapset *include_cols)
CmdType event
Definition: prs2lock.h:27
RewriteRule ** rules
Definition: prs2lock.h:43
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
bool trig_update_instead_row
Definition: reltrigger.h:62
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:663
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
bool trig_delete_instead_row
Definition: reltrigger.h:67
static Bitmapset * adjust_view_column_set(Bitmapset *cols, List *targetlist)
ExecForeignUpdate_function ExecForeignUpdate
Definition: fdwapi.h:198
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
RuleLock * rd_rules
Definition: rel.h:118
RTEKind rtekind
Definition: parsenodes.h:944
FdwRoutine * GetFdwRoutineForRelation(Relation relation, bool makecopy)
Definition: foreign.c:395
#define RELKIND_VIEW
Definition: pg_class.h:164
Query * get_view_query(Relation view)
int i
IsForeignRelUpdatable_function IsForeignRelUpdatable
Definition: fdwapi.h:201
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:791
const char * view_query_is_auto_updatable(Query *viewquery, bool check_cols)
#define RELKIND_RELATION
Definition: pg_class.h:160
const char* view_query_is_auto_updatable ( Query viewquery,
bool  check_cols 
)

Definition at line 2243 of file rewriteHandler.c.

References Query::cteList, Query::distinctClause, FromExpr::fromlist, gettext_noop, Query::groupClause, Query::groupingSets, Query::hasAggs, Query::hasTargetSRFs, Query::hasWindowFuncs, Query::havingQual, IsA, Query::jointree, lfirst, Query::limitCount, Query::limitOffset, linitial, list_length(), NIL, NULL, RangeTblEntry::relkind, RELKIND_FOREIGN_TABLE, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_VIEW, rt_fetch, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, RangeTblRef::rtindex, Query::setOperations, RangeTblEntry::tablesample, Query::targetList, and view_col_is_auto_updatable().

Referenced by ATExecSetRelOptions(), DefineView(), relation_is_updatable(), and rewriteTargetView().

2244 {
2245  RangeTblRef *rtr;
2246  RangeTblEntry *base_rte;
2247 
2248  /*----------
2249  * Check if the view is simply updatable. According to SQL-92 this means:
2250  * - No DISTINCT clause.
2251  * - Each TLE is a column reference, and each column appears at most once.
2252  * - FROM contains exactly one base relation.
2253  * - No GROUP BY or HAVING clauses.
2254  * - No set operations (UNION, INTERSECT or EXCEPT).
2255  * - No sub-queries in the WHERE clause that reference the target table.
2256  *
2257  * We ignore that last restriction since it would be complex to enforce
2258  * and there isn't any actual benefit to disallowing sub-queries. (The
2259  * semantic issues that the standard is presumably concerned about don't
2260  * arise in Postgres, since any such sub-query will not see any updates
2261  * executed by the outer query anyway, thanks to MVCC snapshotting.)
2262  *
2263  * We also relax the second restriction by supporting part of SQL:1999
2264  * feature T111, which allows for a mix of updatable and non-updatable
2265  * columns, provided that an INSERT or UPDATE doesn't attempt to assign to
2266  * a non-updatable column.
2267  *
2268  * In addition we impose these constraints, involving features that are
2269  * not part of SQL-92:
2270  * - No CTEs (WITH clauses).
2271  * - No OFFSET or LIMIT clauses (this matches a SQL:2008 restriction).
2272  * - No system columns (including whole-row references) in the tlist.
2273  * - No window functions in the tlist.
2274  * - No set-returning functions in the tlist.
2275  *
2276  * Note that we do these checks without recursively expanding the view.
2277  * If the base relation is a view, we'll recursively deal with it later.
2278  *----------
2279  */
2280  if (viewquery->distinctClause != NIL)
2281  return gettext_noop("Views containing DISTINCT are not automatically updatable.");
2282 
2283  if (viewquery->groupClause != NIL || viewquery->groupingSets)
2284  return gettext_noop("Views containing GROUP BY are not automatically updatable.");
2285 
2286  if (viewquery->havingQual != NULL)
2287  return gettext_noop("Views containing HAVING are not automatically updatable.");
2288 
2289  if (viewquery->setOperations != NULL)
2290  return gettext_noop("Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable.");
2291 
2292  if (viewquery->cteList != NIL)
2293  return gettext_noop("Views containing WITH are not automatically updatable.");
2294 
2295  if (viewquery->limitOffset != NULL || viewquery->limitCount != NULL)
2296  return gettext_noop("Views containing LIMIT or OFFSET are not automatically updatable.");
2297 
2298  /*
2299  * We must not allow window functions or set returning functions in the
2300  * targetlist. Otherwise we might end up inserting them into the quals of
2301  * the main query. We must also check for aggregates in the targetlist in
2302  * case they appear without a GROUP BY.
2303  *
2304  * These restrictions ensure that each row of the view corresponds to a
2305  * unique row in the underlying base relation.
2306  */
2307  if (viewquery->hasAggs)
2308  return gettext_noop("Views that return aggregate functions are not automatically updatable.");
2309 
2310  if (viewquery->hasWindowFuncs)
2311  return gettext_noop("Views that return window functions are not automatically updatable.");
2312 
2313  if (viewquery->hasTargetSRFs)
2314  return gettext_noop("Views that return set-returning functions are not automatically updatable.");
2315 
2316  /*
2317  * The view query should select from a single base relation, which must be
2318  * a table or another view.
2319  */
2320  if (list_length(viewquery->jointree->fromlist) != 1)
2321  return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");
2322 
2323  rtr = (RangeTblRef *) linitial(viewquery->jointree->fromlist);
2324  if (!IsA(rtr, RangeTblRef))
2325  return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");
2326 
2327  base_rte = rt_fetch(rtr->rtindex, viewquery->rtable);
2328  if (base_rte->rtekind != RTE_RELATION ||
2329  (base_rte->relkind != RELKIND_RELATION &&
2330  base_rte->relkind != RELKIND_FOREIGN_TABLE &&
2331  base_rte->relkind != RELKIND_VIEW &&
2332  base_rte->relkind != RELKIND_PARTITIONED_TABLE))
2333  return gettext_noop("Views that do not select from a single table or view are not automatically updatable.");
2334 
2335  if (base_rte->tablesample)
2336  return gettext_noop("Views containing TABLESAMPLE are not automatically updatable.");
2337 
2338  /*
2339  * Check that the view has at least one updatable column. This is required
2340  * for INSERT/UPDATE but not for DELETE.
2341  */
2342  if (check_cols)
2343  {
2344  ListCell *cell;
2345  bool found;
2346 
2347  found = false;
2348  foreach(cell, viewquery->targetList)
2349  {
2350  TargetEntry *tle = (TargetEntry *) lfirst(cell);
2351 
2352  if (view_col_is_auto_updatable(rtr, tle) == NULL)
2353  {
2354  found = true;
2355  break;
2356  }
2357  }
2358 
2359  if (!found)
2360  return gettext_noop("Views that have no updatable columns are not automatically updatable.");
2361  }
2362 
2363  return NULL; /* the view is updatable */
2364 }
Node * limitOffset
Definition: parsenodes.h:158
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
FromExpr * jointree
Definition: parsenodes.h:136
bool hasAggs
Definition: parsenodes.h:123
List * groupingSets
Definition: parsenodes.h:148
#define gettext_noop(x)
Definition: c.h:139
List * fromlist
Definition: primnodes.h:1471
List * targetList
Definition: parsenodes.h:138
#define linitial(l)
Definition: pg_list.h:111
List * rtable
Definition: parsenodes.h:135
List * distinctClause
Definition: parsenodes.h:154
Node * limitCount
Definition: parsenodes.h:159
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
bool hasTargetSRFs
Definition: parsenodes.h:125
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
bool hasWindowFuncs
Definition: parsenodes.h:124
static int list_length(const List *l)
Definition: pg_list.h:89
RTEKind rtekind
Definition: parsenodes.h:944
List * cteList
Definition: parsenodes.h:133
Node * setOperations
Definition: parsenodes.h:163
List * groupClause
Definition: parsenodes.h:146
#define RELKIND_VIEW
Definition: pg_class.h:164
static const char * view_col_is_auto_updatable(RangeTblRef *rtr, TargetEntry *tle)
Node * havingQual
Definition: parsenodes.h:150
#define RELKIND_RELATION
Definition: pg_class.h:160
struct TableSampleClause * tablesample
Definition: parsenodes.h:962