PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
createas.h File Reference
Include dependency graph for createas.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

ObjectAddress ExecCreateTableAs (ParseState *pstate, CreateTableAsStmt *stmt, ParamListInfo params, QueryEnvironment *queryEnv, QueryCompletion *qc)
 
int GetIntoRelEFlags (IntoClause *intoClause)
 
DestReceiverCreateIntoRelDestReceiver (IntoClause *intoClause)
 
bool CreateTableAsRelExists (CreateTableAsStmt *ctas)
 

Function Documentation

◆ CreateIntoRelDestReceiver()

DestReceiver * CreateIntoRelDestReceiver ( IntoClause intoClause)

Definition at line 441 of file createas.c.

442{
443 DR_intorel *self = (DR_intorel *) palloc0(sizeof(DR_intorel));
444
449 self->pub.mydest = DestIntoRel;
450 self->into = intoClause;
451 /* other private fields will be set during intorel_startup */
452
453 return (DestReceiver *) self;
454}
static void intorel_shutdown(DestReceiver *self)
Definition: createas.c:615
static bool intorel_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: createas.c:584
static void intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: createas.c:460
static void intorel_destroy(DestReceiver *self)
Definition: createas.c:635
@ DestIntoRel
Definition: dest.h:94
void * palloc0(Size size)
Definition: mcxt.c:1973
IntoClause * into
Definition: createas.c:54
DestReceiver pub
Definition: createas.c:53
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
void(* rDestroy)(DestReceiver *self)
Definition: dest.h:126
CommandDest mydest
Definition: dest.h:128

References DestIntoRel, DR_intorel::into, intorel_destroy(), intorel_receive(), intorel_shutdown(), intorel_startup(), _DestReceiver::mydest, palloc0(), DR_intorel::pub, _DestReceiver::rDestroy, _DestReceiver::receiveSlot, _DestReceiver::rShutdown, and _DestReceiver::rStartup.

Referenced by CreateDestReceiver(), ExecCreateTableAs(), and ExplainOnePlan().

◆ CreateTableAsRelExists()

bool CreateTableAsRelExists ( CreateTableAsStmt ctas)

Definition at line 394 of file createas.c.

395{
396 Oid nspid;
397 Oid oldrelid;
398 ObjectAddress address;
399 IntoClause *into = ctas->into;
400
402
403 oldrelid = get_relname_relid(into->rel->relname, nspid);
404 if (OidIsValid(oldrelid))
405 {
406 if (!ctas->if_not_exists)
408 (errcode(ERRCODE_DUPLICATE_TABLE),
409 errmsg("relation \"%s\" already exists",
410 into->rel->relname)));
411
412 /*
413 * The relation exists and IF NOT EXISTS has been specified.
414 *
415 * If we are in an extension script, insist that the pre-existing
416 * object be a member of the extension, to avoid security risks.
417 */
418 ObjectAddressSet(address, RelationRelationId, oldrelid);
420
421 /* OK to skip */
423 (errcode(ERRCODE_DUPLICATE_TABLE),
424 errmsg("relation \"%s\" already exists, skipping",
425 into->rel->relname)));
426 return true;
427 }
428
429 /* Relation does not exist, it can be created */
430 return false;
431}
#define OidIsValid(objectId)
Definition: c.h:746
int nspid
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:149
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:2025
Oid RangeVarGetCreationNamespace(const RangeVar *newRelation)
Definition: namespace.c:654
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void checkMembershipInCurrentExtension(const ObjectAddress *object)
Definition: pg_depend.c:258
unsigned int Oid
Definition: postgres_ext.h:30
IntoClause * into
Definition: parsenodes.h:3988
RangeVar * rel
Definition: primnodes.h:163
char * relname
Definition: primnodes.h:83

References checkMembershipInCurrentExtension(), ereport, errcode(), errmsg(), ERROR, get_relname_relid(), CreateTableAsStmt::if_not_exists, CreateTableAsStmt::into, NOTICE, nspid, ObjectAddressSet, OidIsValid, RangeVarGetCreationNamespace(), IntoClause::rel, and RangeVar::relname.

Referenced by ExecCreateTableAs(), and ExplainOneUtility().

◆ ExecCreateTableAs()

ObjectAddress ExecCreateTableAs ( ParseState pstate,
CreateTableAsStmt stmt,
ParamListInfo  params,
QueryEnvironment queryEnv,
QueryCompletion qc 
)

Definition at line 223 of file createas.c.

226{
227 Query *query = castNode(Query, stmt->query);
228 IntoClause *into = stmt->into;
229 JumbleState *jstate = NULL;
230 bool is_matview = (into->viewQuery != NULL);
231 bool do_refresh = false;
233 ObjectAddress address;
234
235 /* Check if the relation exists or not */
238
239 /*
240 * Create the tuple receiver object and insert info it will need
241 */
243
244 /* Query contained by CTAS needs to be jumbled if requested */
245 if (IsQueryIdEnabled())
246 jstate = JumbleQuery(query);
247
249 (*post_parse_analyze_hook) (pstate, query, jstate);
250
251 /*
252 * The contained Query could be a SELECT, or an EXECUTE utility command.
253 * If the latter, we just pass it off to ExecuteQuery.
254 */
255 if (query->commandType == CMD_UTILITY &&
256 IsA(query->utilityStmt, ExecuteStmt))
257 {
258 ExecuteStmt *estmt = castNode(ExecuteStmt, query->utilityStmt);
259
260 Assert(!is_matview); /* excluded by syntax */
261 ExecuteQuery(pstate, estmt, into, params, dest, qc);
262
263 /* get object address that intorel_startup saved for us */
264 address = ((DR_intorel *) dest)->reladdr;
265
266 return address;
267 }
268 Assert(query->commandType == CMD_SELECT);
269
270 /*
271 * For materialized views, always skip data during table creation, and use
272 * REFRESH instead (see below).
273 */
274 if (is_matview)
275 {
276 do_refresh = !into->skipData;
277 into->skipData = true;
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 /*
291 * For materialized views, reuse the REFRESH logic, which locks down
292 * security-restricted operations and restricts the search_path. This
293 * reduces the chance that a subsequent refresh will fail.
294 */
295 if (do_refresh)
296 RefreshMatViewByOid(address.objectId, true, false, false,
297 pstate->p_sourcetext, qc);
298
299 }
300 else
301 {
302 List *rewritten;
304 QueryDesc *queryDesc;
305
306 Assert(!is_matview);
307
308 /*
309 * Parse analysis was done already, but we still have to run the rule
310 * rewriter. We do not do AcquireRewriteLocks: we assume the query
311 * either came straight from the parser, or suitable locks were
312 * acquired by plancache.c.
313 */
314 rewritten = QueryRewrite(query);
315
316 /* SELECT should never rewrite to more or less than one SELECT query */
317 if (list_length(rewritten) != 1)
318 elog(ERROR, "unexpected rewrite result for CREATE TABLE AS SELECT");
319 query = linitial_node(Query, rewritten);
320 Assert(query->commandType == CMD_SELECT);
321
322 /* plan the query */
323 plan = pg_plan_query(query, pstate->p_sourcetext,
324 CURSOR_OPT_PARALLEL_OK, params);
325
326 /*
327 * Use a snapshot with an updated command ID to ensure this query sees
328 * results of any previously executed queries. (This could only
329 * matter if the planner executed an allegedly-stable function that
330 * changed the database contents, but let's do it anyway to be
331 * parallel to the EXPLAIN code path.)
332 */
335
336 /* Create a QueryDesc, redirecting output to our tuple receiver */
337 queryDesc = CreateQueryDesc(plan, NULL, pstate->p_sourcetext,
339 dest, params, queryEnv, 0);
340
341 /* call ExecutorStart to prepare the plan for execution */
342 if (!ExecutorStart(queryDesc, GetIntoRelEFlags(into)))
343 elog(ERROR, "ExecutorStart() failed unexpectedly");
344
345 /* run the plan to completion */
346 ExecutorRun(queryDesc, ForwardScanDirection, 0);
347
348 /* save the rowcount if we're given a qc to fill */
349 if (qc)
350 SetQueryCompletion(qc, CMDTAG_SELECT, queryDesc->estate->es_processed);
351
352 /* get object address that intorel_startup saved for us */
353 address = ((DR_intorel *) dest)->reladdr;
354
355 /* and clean up */
356 ExecutorFinish(queryDesc);
357 ExecutorEnd(queryDesc);
358
359 FreeQueryDesc(queryDesc);
360
362 }
363
364 return address;
365}
void ExecuteQuery(ParseState *pstate, ExecuteStmt *stmt, IntoClause *intoClause, ParamListInfo params, DestReceiver *dest, QueryCompletion *qc)
Definition: prepare.c:150
static void SetQueryCompletion(QueryCompletion *qc, CommandTag commandTag, uint64 nprocessed)
Definition: cmdtag.h:37
bool CreateTableAsRelExists(CreateTableAsStmt *ctas)
Definition: createas.c:394
static ObjectAddress create_ctas_nodata(List *tlist, IntoClause *into)
Definition: createas.c:155
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:376
DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)
Definition: createas.c:441
#define elog(elevel,...)
Definition: elog.h:225
bool ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:128
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:538
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:475
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:365
Assert(PointerIsAligned(start, uint64))
#define stmt
Definition: indent_codes.h:59
ObjectAddress RefreshMatViewByOid(Oid matviewOid, bool is_create, bool skipData, bool concurrent, const char *queryString, QueryCompletion *qc)
Definition: matview.c:165
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
@ CMD_UTILITY
Definition: nodes.h:276
@ CMD_SELECT
Definition: nodes.h:271
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
const ObjectAddress InvalidObjectAddress
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3385
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:59
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
#define plan(x)
Definition: pg_regress.c:161
PlannedStmt * pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:882
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:112
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, CachedPlan *cplan, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:72
static bool IsQueryIdEnabled(void)
Definition: queryjumble.h:95
JumbleState * JumbleQuery(Query *query)
List * QueryRewrite(Query *parsetree)
@ ForwardScanDirection
Definition: sdir.h:28
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:731
void PopActiveSnapshot(void)
Definition: snapmgr.c:762
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:719
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:787
#define InvalidSnapshot
Definition: snapshot.h:119
uint64 es_processed
Definition: execnodes.h:712
bool skipData
Definition: primnodes.h:171
Definition: pg_list.h:54
EState * estate
Definition: execdesc.h:49

References Assert(), castNode, CMD_SELECT, CMD_UTILITY, Query::commandType, create_ctas_nodata(), CreateIntoRelDestReceiver(), CreateQueryDesc(), CreateTableAsRelExists(), CURSOR_OPT_PARALLEL_OK, generate_unaccent_rules::dest, elog, ERROR, EState::es_processed, QueryDesc::estate, ExecuteQuery(), ExecutorEnd(), ExecutorFinish(), ExecutorRun(), ExecutorStart(), ForwardScanDirection, FreeQueryDesc(), GetActiveSnapshot(), GetIntoRelEFlags(), InvalidObjectAddress, InvalidSnapshot, IsA, IsQueryIdEnabled(), JumbleQuery(), linitial_node, list_length(), ObjectAddress::objectId, ParseState::p_sourcetext, pg_plan_query(), plan, PopActiveSnapshot(), post_parse_analyze_hook, PushCopiedSnapshot(), QueryRewrite(), RefreshMatViewByOid(), SetQueryCompletion(), IntoClause::skipData, stmt, Query::targetList, UpdateActiveSnapshotCommandId(), and Query::utilityStmt.

Referenced by ProcessUtilitySlow().

◆ GetIntoRelEFlags()

int GetIntoRelEFlags ( IntoClause intoClause)

Definition at line 376 of file createas.c.

377{
378 int flags = 0;
379
380 if (intoClause->skipData)
381 flags |= EXEC_FLAG_WITH_NO_DATA;
382
383 return flags;
384}
#define EXEC_FLAG_WITH_NO_DATA
Definition: executor.h:72

References EXEC_FLAG_WITH_NO_DATA, and IntoClause::skipData.

Referenced by ExecCreateTableAs(), ExecuteQuery(), and ExplainOnePlan().