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 438 of file createas.c.

439{
440 DR_intorel *self = (DR_intorel *) palloc0(sizeof(DR_intorel));
441
446 self->pub.mydest = DestIntoRel;
447 self->into = intoClause;
448 /* other private fields will be set during intorel_startup */
449
450 return (DestReceiver *) self;
451}
static void intorel_shutdown(DestReceiver *self)
Definition: createas.c:612
static bool intorel_receive(TupleTableSlot *slot, DestReceiver *self)
Definition: createas.c:581
static void intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: createas.c:457
static void intorel_destroy(DestReceiver *self)
Definition: createas.c:632
@ DestIntoRel
Definition: dest.h:94
void * palloc0(Size size)
Definition: mcxt.c:1347
IntoClause * into
Definition: createas.c:52
DestReceiver pub
Definition: createas.c:51
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 391 of file createas.c.

392{
393 Oid nspid;
394 Oid oldrelid;
395 ObjectAddress address;
396 IntoClause *into = ctas->into;
397
399
400 oldrelid = get_relname_relid(into->rel->relname, nspid);
401 if (OidIsValid(oldrelid))
402 {
403 if (!ctas->if_not_exists)
405 (errcode(ERRCODE_DUPLICATE_TABLE),
406 errmsg("relation \"%s\" already exists",
407 into->rel->relname)));
408
409 /*
410 * The relation exists and IF NOT EXISTS has been specified.
411 *
412 * If we are in an extension script, insist that the pre-existing
413 * object be a member of the extension, to avoid security risks.
414 */
415 ObjectAddressSet(address, RelationRelationId, oldrelid);
417
418 /* OK to skip */
420 (errcode(ERRCODE_DUPLICATE_TABLE),
421 errmsg("relation \"%s\" already exists, skipping",
422 into->rel->relname)));
423 return true;
424 }
425
426 /* Relation does not exist, it can be created */
427 return false;
428}
#define OidIsValid(objectId)
Definition: c.h:729
int nspid
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#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:1885
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:31
IntoClause * into
Definition: parsenodes.h:3920
RangeVar * rel
Definition: primnodes.h:162
char * relname
Definition: primnodes.h:82

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 221 of file createas.c.

224{
225 Query *query = castNode(Query, stmt->query);
226 IntoClause *into = stmt->into;
227 JumbleState *jstate = NULL;
228 bool is_matview = (into->viewQuery != NULL);
229 bool do_refresh = false;
231 ObjectAddress address;
232
233 /* Check if the relation exists or not */
236
237 /*
238 * Create the tuple receiver object and insert info it will need
239 */
241
242 /* Query contained by CTAS needs to be jumbled if requested */
243 if (IsQueryIdEnabled())
244 jstate = JumbleQuery(query);
245
247 (*post_parse_analyze_hook) (pstate, query, jstate);
248
249 /*
250 * The contained Query could be a SELECT, or an EXECUTE utility command.
251 * If the latter, we just pass it off to ExecuteQuery.
252 */
253 if (query->commandType == CMD_UTILITY &&
254 IsA(query->utilityStmt, ExecuteStmt))
255 {
256 ExecuteStmt *estmt = castNode(ExecuteStmt, query->utilityStmt);
257
258 Assert(!is_matview); /* excluded by syntax */
259 ExecuteQuery(pstate, estmt, into, params, dest, qc);
260
261 /* get object address that intorel_startup saved for us */
262 address = ((DR_intorel *) dest)->reladdr;
263
264 return address;
265 }
266 Assert(query->commandType == CMD_SELECT);
267
268 /*
269 * For materialized views, always skip data during table creation, and use
270 * REFRESH instead (see below).
271 */
272 if (is_matview)
273 {
274 do_refresh = !into->skipData;
275 into->skipData = true;
276 }
277
278 if (into->skipData)
279 {
280 /*
281 * If WITH NO DATA was specified, do not go through the rewriter,
282 * planner and executor. Just define the relation using a code path
283 * similar to CREATE VIEW. This avoids dump/restore problems stemming
284 * from running the planner before all dependencies are set up.
285 */
286 address = create_ctas_nodata(query->targetList, into);
287
288 /*
289 * For materialized views, reuse the REFRESH logic, which locks down
290 * security-restricted operations and restricts the search_path. This
291 * reduces the chance that a subsequent refresh will fail.
292 */
293 if (do_refresh)
294 RefreshMatViewByOid(address.objectId, true, false, false,
295 pstate->p_sourcetext, qc);
296
297 }
298 else
299 {
300 List *rewritten;
302 QueryDesc *queryDesc;
303
304 Assert(!is_matview);
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 rewritten = QueryRewrite(query);
313
314 /* SELECT should never rewrite to more or less than one SELECT query */
315 if (list_length(rewritten) != 1)
316 elog(ERROR, "unexpected rewrite result for CREATE TABLE AS SELECT");
317 query = linitial_node(Query, rewritten);
318 Assert(query->commandType == CMD_SELECT);
319
320 /* plan the query */
321 plan = pg_plan_query(query, pstate->p_sourcetext,
322 CURSOR_OPT_PARALLEL_OK, params);
323
324 /*
325 * Use a snapshot with an updated command ID to ensure this query sees
326 * results of any previously executed queries. (This could only
327 * matter if the planner executed an allegedly-stable function that
328 * changed the database contents, but let's do it anyway to be
329 * parallel to the EXPLAIN code path.)
330 */
333
334 /* Create a QueryDesc, redirecting output to our tuple receiver */
335 queryDesc = CreateQueryDesc(plan, pstate->p_sourcetext,
337 dest, params, queryEnv, 0);
338
339 /* call ExecutorStart to prepare the plan for execution */
340 ExecutorStart(queryDesc, GetIntoRelEFlags(into));
341
342 /* run the plan to completion */
343 ExecutorRun(queryDesc, ForwardScanDirection, 0);
344
345 /* save the rowcount if we're given a qc to fill */
346 if (qc)
347 SetQueryCompletion(qc, CMDTAG_SELECT, queryDesc->estate->es_processed);
348
349 /* get object address that intorel_startup saved for us */
350 address = ((DR_intorel *) dest)->reladdr;
351
352 /* and clean up */
353 ExecutorFinish(queryDesc);
354 ExecutorEnd(queryDesc);
355
356 FreeQueryDesc(queryDesc);
357
359 }
360
361 return address;
362}
void ExecuteQuery(ParseState *pstate, ExecuteStmt *stmt, IntoClause *intoClause, ParamListInfo params, DestReceiver *dest, QueryCompletion *qc)
Definition: prepare.c:147
#define Assert(condition)
Definition: c.h:812
static void SetQueryCompletion(QueryCompletion *qc, CommandTag commandTag, uint64 nprocessed)
Definition: cmdtag.h:37
bool CreateTableAsRelExists(CreateTableAsStmt *ctas)
Definition: createas.c:391
static ObjectAddress create_ctas_nodata(List *tlist, IntoClause *into)
Definition: createas.c:153
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:373
DestReceiver * CreateIntoRelDestReceiver(IntoClause *intoClause)
Definition: createas.c:438
#define elog(elevel,...)
Definition: elog.h:225
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:463
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:403
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:119
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:294
#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:158
@ CMD_UTILITY
Definition: nodes.h:270
@ CMD_SELECT
Definition: nodes.h:265
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
const ObjectAddress InvalidObjectAddress
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3317
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:881
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
static bool IsQueryIdEnabled(void)
Definition: queryjumble.h:77
JumbleState * JumbleQuery(Query *query)
List * QueryRewrite(Query *parsetree)
@ ForwardScanDirection
Definition: sdir.h:28
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:672
void PopActiveSnapshot(void)
Definition: snapmgr.c:703
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:660
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:728
#define InvalidSnapshot
Definition: snapshot.h:119
uint64 es_processed
Definition: execnodes.h:679
bool skipData
Definition: primnodes.h:170
Definition: pg_list.h:54
EState * estate
Definition: execdesc.h:48

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 373 of file createas.c.

374{
375 int flags = 0;
376
377 if (intoClause->skipData)
378 flags |= EXEC_FLAG_WITH_NO_DATA;
379
380 return flags;
381}
#define EXEC_FLAG_WITH_NO_DATA
Definition: executor.h:71

References EXEC_FLAG_WITH_NO_DATA, and IntoClause::skipData.

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