diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-11-24 23:21:06 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-11-24 23:21:45 -0500 |
commit | 9ed439a9c07b69c2617cc98596611fdbdc22472c (patch) | |
tree | 67de5b64612bdcd4006e0a00730aa87e49aa73bb /src/backend/executor | |
parent | e90710f34a6d5a73475e4241852b377675600325 (diff) | |
download | postgresql-9ed439a9c07b69c2617cc98596611fdbdc22472c.tar.gz postgresql-9ed439a9c07b69c2617cc98596611fdbdc22472c.zip |
Fix unsupported options in CREATE TABLE ... AS EXECUTE.
The WITH [NO] DATA option was not supported, nor the ability to specify
replacement column names; the former limitation wasn't even documented, as
per recent complaint from Naoya Anzai. Fix by moving the responsibility
for supporting these options into the executor. It actually takes less
code this way ...
catversion bump due to change in representation of IntoClause, which might
affect stored rules.
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execMain.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 708831a5c34..d19e0978e4e 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -56,6 +56,7 @@ #include "storage/smgr.h" #include "tcop/utility.h" #include "utils/acl.h" +#include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/snapmgr.h" @@ -306,6 +307,13 @@ standard_ExecutorRun(QueryDesc *queryDesc, (*dest->rStartup) (dest, operation, queryDesc->tupDesc); /* + * if it's CREATE TABLE AS ... WITH NO DATA, skip plan execution + */ + if (estate->es_select_into && + queryDesc->plannedstmt->intoClause->skipData) + direction = NoMovementScanDirection; + + /* * run plan */ if (!ScanDirectionIsNoMovement(direction)) @@ -2388,6 +2396,7 @@ OpenIntoRel(QueryDesc *queryDesc) { IntoClause *into = queryDesc->plannedstmt->intoClause; EState *estate = queryDesc->estate; + TupleDesc intoTupDesc = queryDesc->tupDesc; Relation intoRelationDesc; char *intoName; Oid namespaceId; @@ -2416,6 +2425,31 @@ OpenIntoRel(QueryDesc *queryDesc) errmsg("ON COMMIT can only be used on temporary tables"))); /* + * If a column name list was specified in CREATE TABLE AS, override the + * column names derived from the query. (Too few column names are OK, too + * many are not.) It would probably be all right to scribble directly on + * the query's result tupdesc, but let's be safe and make a copy. + */ + if (into->colNames) + { + ListCell *lc; + + intoTupDesc = CreateTupleDescCopy(intoTupDesc); + attnum = 1; + foreach(lc, into->colNames) + { + char *colname = strVal(lfirst(lc)); + + if (attnum > intoTupDesc->natts) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("CREATE TABLE AS specifies too many column names"))); + namestrcpy(&(intoTupDesc->attrs[attnum - 1]->attname), colname); + attnum++; + } + } + + /* * Find namespace to create in, check its permissions */ intoName = into->rel->relname; @@ -2477,7 +2511,7 @@ OpenIntoRel(QueryDesc *queryDesc) InvalidOid, InvalidOid, GetUserId(), - queryDesc->tupDesc, + intoTupDesc, NIL, RELKIND_RELATION, into->rel->relpersistence, @@ -2519,7 +2553,7 @@ OpenIntoRel(QueryDesc *queryDesc) intoRelationDesc = heap_open(intoRelationId, AccessExclusiveLock); /* - * check INSERT permission on the constructed table. + * Check INSERT permission on the constructed table. */ rte = makeNode(RangeTblEntry); rte->rtekind = RTE_RELATION; @@ -2527,7 +2561,7 @@ OpenIntoRel(QueryDesc *queryDesc) rte->relkind = RELKIND_RELATION; rte->requiredPerms = ACL_INSERT; - for (attnum = 1; attnum <= queryDesc->tupDesc->natts; attnum++) + for (attnum = 1; attnum <= intoTupDesc->natts; attnum++) rte->modifiedCols = bms_add_member(rte->modifiedCols, attnum - FirstLowInvalidHeapAttributeNumber); |