PostgreSQL Source Code  git master
createas.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * createas.c
4  * Execution of CREATE TABLE ... AS, a/k/a SELECT INTO.
5  * Since CREATE MATERIALIZED VIEW shares syntax and most behaviors,
6  * we implement that here, too.
7  *
8  * We implement this by diverting the query's normal output to a
9  * specialized DestReceiver type.
10  *
11  * Formerly, CTAS was implemented as a variant of SELECT, which led
12  * to assorted legacy behaviors that we still try to preserve, notably that
13  * we must return a tuples-processed count in the QueryCompletion. (We no
14  * longer do that for CTAS ... WITH NO DATA, however.)
15  *
16  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
17  * Portions Copyright (c) 1994, Regents of the University of California
18  *
19  *
20  * IDENTIFICATION
21  * src/backend/commands/createas.c
22  *
23  *-------------------------------------------------------------------------
24  */
25 #include "postgres.h"
26 
27 #include "access/heapam.h"
28 #include "access/reloptions.h"
29 #include "access/tableam.h"
30 #include "access/xact.h"
31 #include "catalog/namespace.h"
32 #include "catalog/toasting.h"
33 #include "commands/createas.h"
34 #include "commands/matview.h"
35 #include "commands/prepare.h"
36 #include "commands/tablecmds.h"
37 #include "commands/view.h"
38 #include "miscadmin.h"
39 #include "nodes/makefuncs.h"
40 #include "nodes/nodeFuncs.h"
41 #include "rewrite/rewriteHandler.h"
42 #include "tcop/tcopprot.h"
43 #include "utils/builtins.h"
44 #include "utils/lsyscache.h"
45 #include "utils/rel.h"
46 #include "utils/rls.h"
47 #include "utils/snapmgr.h"
48 
49 typedef struct
50 {
51  DestReceiver pub; /* publicly-known function pointers */
52  IntoClause *into; /* target relation specification */
53  /* These fields are filled by intorel_startup: */
54  Relation rel; /* relation to write to */
55  ObjectAddress reladdr; /* address of rel, for ExecCreateTableAs */
56  CommandId output_cid; /* cmin to insert in output tuples */
57  int ti_options; /* table_tuple_insert performance options */
58  BulkInsertState bistate; /* bulk insert state */
59 } DR_intorel;
60 
61 /* utility functions for CTAS definition creation */
62 static ObjectAddress create_ctas_internal(List *attrList, IntoClause *into);
63 static ObjectAddress create_ctas_nodata(List *tlist, IntoClause *into);
64 
65 /* DestReceiver routines for collecting data */
66 static void intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo);
67 static bool intorel_receive(TupleTableSlot *slot, DestReceiver *self);
68 static void intorel_shutdown(DestReceiver *self);
69 static void intorel_destroy(DestReceiver *self);
70 
71 
72 /*
73  * create_ctas_internal
74  *
75  * Internal utility used for the creation of the definition of a relation
76  * created via CREATE TABLE AS or a materialized view. Caller needs to
77  * provide a list of attributes (ColumnDef nodes).
78  */
79 static ObjectAddress
81 {
82  CreateStmt *create = makeNode(CreateStmt);
83  bool is_matview;
84  char relkind;
85  Datum toast_options;
86  static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
87  ObjectAddress intoRelationAddr;
88 
89  /* This code supports both CREATE TABLE AS and CREATE MATERIALIZED VIEW */
90  is_matview = (into->viewQuery != NULL);
91  relkind = is_matview ? RELKIND_MATVIEW : RELKIND_RELATION;
92 
93  /*
94  * Create the target relation by faking up a CREATE TABLE parsetree and
95  * passing it to DefineRelation.
96  */
97  create->relation = into->rel;
98  create->tableElts = attrList;
99  create->inhRelations = NIL;
100  create->ofTypename = NULL;
101  create->constraints = NIL;
102  create->options = into->options;
103  create->oncommit = into->onCommit;
104  create->tablespacename = into->tableSpaceName;
105  create->if_not_exists = false;
106  create->accessMethod = into->accessMethod;
107 
108  /*
109  * Create the relation. (This will error out if there's an existing view,
110  * so we don't need more code to complain if "replace" is false.)
111  */
112  intoRelationAddr = DefineRelation(create, relkind, InvalidOid, NULL, NULL);
113 
114  /*
115  * If necessary, create a TOAST table for the target table. Note that
116  * NewRelationCreateToastTable ends with CommandCounterIncrement(), so
117  * that the TOAST table will be visible for insertion.
118  */
120 
121  /* parse and validate reloptions for the toast table */
122  toast_options = transformRelOptions((Datum) 0,
123  create->options,
124  "toast",
125  validnsps,
126  true, false);
127 
128  (void) heap_reloptions(RELKIND_TOASTVALUE, toast_options, true);
129 
130  NewRelationCreateToastTable(intoRelationAddr.objectId, toast_options);
131 
132  /* Create the "view" part of a materialized view. */
133  if (is_matview)
134  {
135  /* StoreViewQuery scribbles on tree, so make a copy */
136  Query *query = (Query *) copyObject(into->viewQuery);
137 
138  StoreViewQuery(intoRelationAddr.objectId, query, false);
140  }
141 
142  return intoRelationAddr;
143 }
144 
145 
146 /*
147  * create_ctas_nodata
148  *
149  * Create CTAS or materialized view when WITH NO DATA is used, starting from
150  * the targetlist of the SELECT or view definition.
151  */
152 static ObjectAddress
154 {
155  List *attrList;
156  ListCell *t,
157  *lc;
158 
159  /*
160  * Build list of ColumnDefs from non-junk elements of the tlist. If a
161  * column name list was specified in CREATE TABLE AS, override the column
162  * names in the query. (Too few column names are OK, too many are not.)
163  */
164  attrList = NIL;
165  lc = list_head(into->colNames);
166  foreach(t, tlist)
167  {
168  TargetEntry *tle = (TargetEntry *) lfirst(t);
169 
170  if (!tle->resjunk)
171  {
172  ColumnDef *col;
173  char *colname;
174 
175  if (lc)
176  {
177  colname = strVal(lfirst(lc));
178  lc = lnext(into->colNames, lc);
179  }
180  else
181  colname = tle->resname;
182 
183  col = makeColumnDef(colname,
184  exprType((Node *) tle->expr),
185  exprTypmod((Node *) tle->expr),
186  exprCollation((Node *) tle->expr));
187 
188  /*
189  * It's possible that the column is of a collatable type but the
190  * collation could not be resolved, so double-check. (We must
191  * check this here because DefineRelation would adopt the type's
192  * default collation rather than complaining.)
193  */
194  if (!OidIsValid(col->collOid) &&
196  ereport(ERROR,
197  (errcode(ERRCODE_INDETERMINATE_COLLATION),
198  errmsg("no collation was derived for column \"%s\" with collatable type %s",
199  col->colname,
201  errhint("Use the COLLATE clause to set the collation explicitly.")));
202 
203  attrList = lappend(attrList, col);
204  }
205  }
206 
207  if (lc != NULL)
208  ereport(ERROR,
209  (errcode(ERRCODE_SYNTAX_ERROR),
210  errmsg("too many column names were specified")));
211 
212  /* Create the relation definition using the ColumnDef list */
213  return create_ctas_internal(attrList, into);
214 }
215 
216 
217 /*
218  * ExecCreateTableAs -- execute a CREATE TABLE AS command
219  */
222  ParamListInfo params, QueryEnvironment *queryEnv,
223  QueryCompletion *qc)
224 {
225  Query *query = castNode(Query, stmt->query);
226  IntoClause *into = stmt->into;
227  bool is_matview = (into->viewQuery != NULL);
229  Oid save_userid = InvalidOid;
230  int save_sec_context = 0;
231  int save_nestlevel = 0;
232  ObjectAddress address;
233  List *rewritten;
234  PlannedStmt *plan;
235  QueryDesc *queryDesc;
236 
237  /* Check if the relation exists or not */
239  return InvalidObjectAddress;
240 
241  /*
242  * Create the tuple receiver object and insert info it will need
243  */
245 
246  /*
247  * The contained Query could be a SELECT, or an EXECUTE utility command.
248  * If the latter, we just pass it off to ExecuteQuery.
249  */
250  if (query->commandType == CMD_UTILITY &&
251  IsA(query->utilityStmt, ExecuteStmt))
252  {
253  ExecuteStmt *estmt = castNode(ExecuteStmt, query->utilityStmt);
254 
255  Assert(!is_matview); /* excluded by syntax */
256  ExecuteQuery(pstate, estmt, into, params, dest, qc);
257 
258  /* get object address that intorel_startup saved for us */
259  address = ((DR_intorel *) dest)->reladdr;
260 
261  return address;
262  }
263  Assert(query->commandType == CMD_SELECT);
264 
265  /*
266  * For materialized views, lock down security-restricted operations and
267  * arrange to make GUC variable changes local to this command. This is
268  * not necessary for security, but this keeps the behavior similar to
269  * REFRESH MATERIALIZED VIEW. Otherwise, one could create a materialized
270  * view not possible to refresh.
271  */
272  if (is_matview)
273  {
274  GetUserIdAndSecContext(&save_userid, &save_sec_context);
275  SetUserIdAndSecContext(save_userid,
276  save_sec_context | SECURITY_RESTRICTED_OPERATION);
277  save_nestlevel = NewGUCNestLevel();
278  }
279 
280  if (into->skipData)
281  {
282  /*
283  * If WITH NO DATA was specified, do not go through the rewriter,
284  * planner and executor. Just define the relation using a code path
285  * similar to CREATE VIEW. This avoids dump/restore problems stemming
286  * from running the planner before all dependencies are set up.
287  */
288  address = create_ctas_nodata(query->targetList, into);
289  }
290  else
291  {
292  /*
293  * Parse analysis was done already, but we still have to run the rule
294  * rewriter. We do not do AcquireRewriteLocks: we assume the query
295  * either came straight from the parser, or suitable locks were
296  * acquired by plancache.c.
297  */
298  rewritten = QueryRewrite(query);
299 
300  /* SELECT should never rewrite to more or less than one SELECT query */
301  if (list_length(rewritten) != 1)
302  elog(ERROR, "unexpected rewrite result for %s",
303  is_matview ? "CREATE MATERIALIZED VIEW" :
304  "CREATE TABLE AS SELECT");
305  query = linitial_node(Query, rewritten);
306  Assert(query->commandType == CMD_SELECT);
307 
308  /* plan the query */
309  plan = pg_plan_query(query, pstate->p_sourcetext,
310  CURSOR_OPT_PARALLEL_OK, params);
311 
312  /*
313  * Use a snapshot with an updated command ID to ensure this query sees
314  * results of any previously executed queries. (This could only
315  * matter if the planner executed an allegedly-stable function that
316  * changed the database contents, but let's do it anyway to be
317  * parallel to the EXPLAIN code path.)
318  */
321 
322  /* Create a QueryDesc, redirecting output to our tuple receiver */
323  queryDesc = CreateQueryDesc(plan, pstate->p_sourcetext,
325  dest, params, queryEnv, 0);
326 
327  /* call ExecutorStart to prepare the plan for execution */
328  ExecutorStart(queryDesc, GetIntoRelEFlags(into));
329 
330  /* run the plan to completion */
331  ExecutorRun(queryDesc, ForwardScanDirection, 0, true);
332 
333  /* save the rowcount if we're given a qc to fill */
334  if (qc)
335  SetQueryCompletion(qc, CMDTAG_SELECT, queryDesc->estate->es_processed);
336 
337  /* get object address that intorel_startup saved for us */
338  address = ((DR_intorel *) dest)->reladdr;
339 
340  /* and clean up */
341  ExecutorFinish(queryDesc);
342  ExecutorEnd(queryDesc);
343 
344  FreeQueryDesc(queryDesc);
345 
347  }
348 
349  if (is_matview)
350  {
351  /* Roll back any GUC changes */
352  AtEOXact_GUC(false, save_nestlevel);
353 
354  /* Restore userid and security context */
355  SetUserIdAndSecContext(save_userid, save_sec_context);
356  }
357 
358  return address;
359 }
360 
361 /*
362  * GetIntoRelEFlags --- compute executor flags needed for CREATE TABLE AS
363  *
364  * This is exported because EXPLAIN and PREPARE need it too. (Note: those
365  * callers still need to deal explicitly with the skipData flag; since they
366  * use different methods for suppressing execution, it doesn't seem worth
367  * trying to encapsulate that part.)
368  */
369 int
371 {
372  int flags = 0;
373 
374  if (intoClause->skipData)
375  flags |= EXEC_FLAG_WITH_NO_DATA;
376 
377  return flags;
378 }
379 
380 /*
381  * CreateTableAsRelExists --- check existence of relation for CreateTableAsStmt
382  *
383  * Utility wrapper checking if the relation pending for creation in this
384  * CreateTableAsStmt query already exists or not. Returns true if the
385  * relation exists, otherwise false.
386  */
387 bool
389 {
390  Oid nspid;
391  Oid oldrelid;
392  ObjectAddress address;
393  IntoClause *into = ctas->into;
394 
396 
397  oldrelid = get_relname_relid(into->rel->relname, nspid);
398  if (OidIsValid(oldrelid))
399  {
400  if (!ctas->if_not_exists)
401  ereport(ERROR,
402  (errcode(ERRCODE_DUPLICATE_TABLE),
403  errmsg("relation \"%s\" already exists",
404  into->rel->relname)));
405 
406  /*
407  * The relation exists and IF NOT EXISTS has been specified.
408  *
409  * If we are in an extension script, insist that the pre-existing
410  * object be a member of the extension, to avoid security risks.
411  */
412  ObjectAddressSet(address, RelationRelationId, oldrelid);
414 
415  /* OK to skip */
416  ereport(NOTICE,
417  (errcode(ERRCODE_DUPLICATE_TABLE),
418  errmsg("relation \"%s\" already exists, skipping",
419  into->rel->relname)));
420  return true;
421  }
422 
423  /* Relation does not exist, it can be created */
424  return false;
425 }
426 
427 /*
428  * CreateIntoRelDestReceiver -- create a suitable DestReceiver object
429  *
430  * intoClause will be NULL if called from CreateDestReceiver(), in which
431  * case it has to be provided later. However, it is convenient to allow
432  * self->into to be filled in immediately for other callers.
433  */
434 DestReceiver *
436 {
437  DR_intorel *self = (DR_intorel *) palloc0(sizeof(DR_intorel));
438 
439  self->pub.receiveSlot = intorel_receive;
440  self->pub.rStartup = intorel_startup;
441  self->pub.rShutdown = intorel_shutdown;
442  self->pub.rDestroy = intorel_destroy;
443  self->pub.mydest = DestIntoRel;
444  self->into = intoClause;
445  /* other private fields will be set during intorel_startup */
446 
447  return (DestReceiver *) self;
448 }
449 
450 /*
451  * intorel_startup --- executor startup
452  */
453 static void
454 intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
455 {
456  DR_intorel *myState = (DR_intorel *) self;
457  IntoClause *into = myState->into;
458  bool is_matview;
459  List *attrList;
460  ObjectAddress intoRelationAddr;
461  Relation intoRelationDesc;
462  ListCell *lc;
463  int attnum;
464 
465  Assert(into != NULL); /* else somebody forgot to set it */
466 
467  /* This code supports both CREATE TABLE AS and CREATE MATERIALIZED VIEW */
468  is_matview = (into->viewQuery != NULL);
469 
470  /*
471  * Build column definitions using "pre-cooked" type and collation info. If
472  * a column name list was specified in CREATE TABLE AS, override the
473  * column names derived from the query. (Too few column names are OK, too
474  * many are not.)
475  */
476  attrList = NIL;
477  lc = list_head(into->colNames);
478  for (attnum = 0; attnum < typeinfo->natts; attnum++)
479  {
480  Form_pg_attribute attribute = TupleDescAttr(typeinfo, attnum);
481  ColumnDef *col;
482  char *colname;
483 
484  if (lc)
485  {
486  colname = strVal(lfirst(lc));
487  lc = lnext(into->colNames, lc);
488  }
489  else
490  colname = NameStr(attribute->attname);
491 
492  col = makeColumnDef(colname,
493  attribute->atttypid,
494  attribute->atttypmod,
495  attribute->attcollation);
496 
497  /*
498  * It's possible that the column is of a collatable type but the
499  * collation could not be resolved, so double-check. (We must check
500  * this here because DefineRelation would adopt the type's default
501  * collation rather than complaining.)
502  */
503  if (!OidIsValid(col->collOid) &&
505  ereport(ERROR,
506  (errcode(ERRCODE_INDETERMINATE_COLLATION),
507  errmsg("no collation was derived for column \"%s\" with collatable type %s",
508  col->colname,
510  errhint("Use the COLLATE clause to set the collation explicitly.")));
511 
512  attrList = lappend(attrList, col);
513  }
514 
515  if (lc != NULL)
516  ereport(ERROR,
517  (errcode(ERRCODE_SYNTAX_ERROR),
518  errmsg("too many column names were specified")));
519 
520  /*
521  * Actually create the target table
522  */
523  intoRelationAddr = create_ctas_internal(attrList, into);
524 
525  /*
526  * Finally we can open the target table
527  */
528  intoRelationDesc = table_open(intoRelationAddr.objectId, AccessExclusiveLock);
529 
530  /*
531  * Make sure the constructed table does not have RLS enabled.
532  *
533  * check_enable_rls() will ereport(ERROR) itself if the user has requested
534  * something invalid, and otherwise will return RLS_ENABLED if RLS should
535  * be enabled here. We don't actually support that currently, so throw
536  * our own ereport(ERROR) if that happens.
537  */
538  if (check_enable_rls(intoRelationAddr.objectId, InvalidOid, false) == RLS_ENABLED)
539  ereport(ERROR,
540  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
541  errmsg("policies not yet implemented for this command")));
542 
543  /*
544  * Tentatively mark the target as populated, if it's a matview and we're
545  * going to fill it; otherwise, no change needed.
546  */
547  if (is_matview && !into->skipData)
548  SetMatViewPopulatedState(intoRelationDesc, true);
549 
550  /*
551  * Fill private fields of myState for use by later routines
552  */
553  myState->rel = intoRelationDesc;
554  myState->reladdr = intoRelationAddr;
555  myState->output_cid = GetCurrentCommandId(true);
557 
558  /*
559  * If WITH NO DATA is specified, there is no need to set up the state for
560  * bulk inserts as there are no tuples to insert.
561  */
562  if (!into->skipData)
563  myState->bistate = GetBulkInsertState();
564  else
565  myState->bistate = NULL;
566 
567  /*
568  * Valid smgr_targblock implies something already wrote to the relation.
569  * This may be harmless, but this function hasn't planned for it.
570  */
571  Assert(RelationGetTargetBlock(intoRelationDesc) == InvalidBlockNumber);
572 }
573 
574 /*
575  * intorel_receive --- receive one tuple
576  */
577 static bool
579 {
580  DR_intorel *myState = (DR_intorel *) self;
581 
582  /* Nothing to insert if WITH NO DATA is specified. */
583  if (!myState->into->skipData)
584  {
585  /*
586  * Note that the input slot might not be of the type of the target
587  * relation. That's supported by table_tuple_insert(), but slightly
588  * less efficient than inserting with the right slot - but the
589  * alternative would be to copy into a slot of the right type, which
590  * would not be cheap either. This also doesn't allow accessing per-AM
591  * data (say a tuple's xmin), but since we don't do that here...
592  */
593  table_tuple_insert(myState->rel,
594  slot,
595  myState->output_cid,
596  myState->ti_options,
597  myState->bistate);
598  }
599 
600  /* We know this is a newly created relation, so there are no indexes */
601 
602  return true;
603 }
604 
605 /*
606  * intorel_shutdown --- executor end
607  */
608 static void
610 {
611  DR_intorel *myState = (DR_intorel *) self;
612  IntoClause *into = myState->into;
613 
614  if (!into->skipData)
615  {
616  FreeBulkInsertState(myState->bistate);
617  table_finish_bulk_insert(myState->rel, myState->ti_options);
618  }
619 
620  /* close rel, but keep lock until commit */
621  table_close(myState->rel, NoLock);
622  myState->rel = NULL;
623 }
624 
625 /*
626  * intorel_destroy --- release DestReceiver object
627  */
628 static void
630 {
631  pfree(self);
632 }
void ExecuteQuery(ParseState *pstate, ExecuteStmt *stmt, IntoClause *intoClause, ParamListInfo params, DestReceiver *dest, QueryCompletion *qc)
Definition: prepare.c:147
#define InvalidBlockNumber
Definition: block.h:33
#define NameStr(name)
Definition: c.h:746
#define Assert(condition)
Definition: c.h:858
uint32 CommandId
Definition: c.h:666
#define OidIsValid(objectId)
Definition: c.h:775
static void SetQueryCompletion(QueryCompletion *qc, CommandTag commandTag, uint64 nprocessed)
Definition: cmdtag.h:38
int nspid
static void intorel_shutdown(DestReceiver *self)
Definition: createas.c:609
static ObjectAddress create_ctas_internal(List *attrList, IntoClause *into)
Definition: createas.c:80
bool CreateTableAsRelExists(CreateTableAsStmt *ctas)
Definition: createas.c:388
DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)
Definition: createas.c:435
static ObjectAddress create_ctas_nodata(List *tlist, IntoClause *into)
Definition: createas.c:153
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:370
static bool intorel_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: createas.c:578
static void intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: createas.c:454
ObjectAddress ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, ParamListInfo params, QueryEnvironment *queryEnv, QueryCompletion *qc)
Definition: createas.c:221
static void intorel_destroy(DestReceiver *self)
Definition: createas.c:629
@ DestIntoRel
Definition: dest.h:94
int errhint(const char *fmt,...)
Definition: elog.c:1319
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:149
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:467
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:407
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:124
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:297
#define EXEC_FLAG_WITH_NO_DATA
Definition: executor.h:71
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
int NewGUCNestLevel(void)
Definition: guc.c:2237
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:2264
BulkInsertState GetBulkInsertState(void)
Definition: heapam.c:1923
void FreeBulkInsertState(BulkInsertState bistate)
Definition: heapam.c:1940
#define stmt
Definition: indent_codes.h:59
List * lappend(List *list, void *datum)
Definition: list.c:339
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:43
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:3081
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1885
ColumnDef * makeColumnDef(const char *colname, Oid typeOid, int32 typmod, Oid collOid)
Definition: makefuncs.c:492
void SetMatViewPopulatedState(Relation relation, bool newstate)
Definition: matview.c:79
void pfree(void *pointer)
Definition: mcxt.c:1520
void * palloc0(Size size)
Definition: mcxt.c:1346
#define SECURITY_RESTRICTED_OPERATION
Definition: miscadmin.h:315
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition: miscinit.c:635
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition: miscinit.c:642
Oid RangeVarGetCreationNamespace(const RangeVar *newRelation)
Definition: namespace.c:639
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:298
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:816
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define copyObject(obj)
Definition: nodes.h:224
@ CMD_UTILITY
Definition: nodes.h:270
@ CMD_SELECT
Definition: nodes.h:265
#define makeNode(_type_)
Definition: nodes.h:155
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3302
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
void checkMembershipInCurrentExtension(const ObjectAddress *object)
Definition: pg_depend.c:257
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
#define NIL
Definition: pg_list.h:68
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
#define plan(x)
Definition: pg_regress.c:162
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:886
uintptr_t Datum
Definition: postgres.h:64
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:67
#define RelationGetTargetBlock(relation)
Definition: rel.h:601
Datum transformRelOptions(Datum oldOptions, List *defList, const char *namspace, char *validnsps[], bool acceptOidsOff, bool isReset)
Definition: reloptions.c:1156
bytea * heap_reloptions(char relkind, Datum reloptions, bool validate)
Definition: reloptions.c:2019
#define HEAP_RELOPT_NAMESPACES
Definition: reloptions.h:61
List * QueryRewrite(Query *parsetree)
int check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
Definition: rls.c:52
@ RLS_ENABLED
Definition: rls.h:45
@ ForwardScanDirection
Definition: sdir.h:28
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:712
void PopActiveSnapshot(void)
Definition: snapmgr.c:743
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:700
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:770
#define InvalidSnapshot
Definition: snapshot.h:123
char * colname
Definition: parsenodes.h:726
TypeName * typeName
Definition: parsenodes.h:727
Oid collOid
Definition: parsenodes.h:742
List * tableElts
Definition: parsenodes.h:2659
TypeName * ofTypename
Definition: parsenodes.h:2664
OnCommitAction oncommit
Definition: parsenodes.h:2668
List * options
Definition: parsenodes.h:2667
bool if_not_exists
Definition: parsenodes.h:2671
List * inhRelations
Definition: parsenodes.h:2660
RangeVar * relation
Definition: parsenodes.h:2658
char * tablespacename
Definition: parsenodes.h:2669
char * accessMethod
Definition: parsenodes.h:2670
List * constraints
Definition: parsenodes.h:2665
IntoClause * into
Definition: parsenodes.h:3904
Relation rel
Definition: createas.c:54
ObjectAddress reladdr
Definition: createas.c:55
BulkInsertState bistate
Definition: createas.c:58
IntoClause * into
Definition: createas.c:52
int ti_options
Definition: createas.c:57
CommandId output_cid
Definition: createas.c:56
DestReceiver pub
Definition: createas.c:51
uint64 es_processed
Definition: execnodes.h:671
List * colNames
Definition: primnodes.h:163
char * tableSpaceName
Definition: primnodes.h:167
bool skipData
Definition: primnodes.h:170
OnCommitAction onCommit
Definition: primnodes.h:166
List * options
Definition: primnodes.h:165
char * accessMethod
Definition: primnodes.h:164
RangeVar * rel
Definition: primnodes.h:162
Definition: pg_list.h:54
Definition: nodes.h:129
const char * p_sourcetext
Definition: parse_node.h:193
EState * estate
Definition: execdesc.h:48
CmdType commandType
Definition: parsenodes.h:121
Node * utilityStmt
Definition: parsenodes.h:136
List * targetList
Definition: parsenodes.h:191
char * relname
Definition: primnodes.h:82
Expr * expr
Definition: primnodes.h:2160
Oid typeOid
Definition: parsenodes.h:269
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
#define TABLE_INSERT_SKIP_FSM
Definition: tableam.h:260
static void table_finish_bulk_insert(Relation rel, int options)
Definition: tableam.h:1605
static void table_tuple_insert(Relation rel, TupleTableSlot *slot, CommandId cid, int options, struct BulkInsertStateData *bistate)
Definition: tableam.h:1412
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition: tablecmds.c:699
void NewRelationCreateToastTable(Oid relOid, Datum reloptions)
Definition: toasting.c:70
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define strVal(v)
Definition: value.h:82
void StoreViewQuery(Oid viewOid, Query *viewParse, bool replace)
Definition: view.c:511
void CommandCounterIncrement(void)
Definition: xact.c:1097
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:826