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