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