aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execMain.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-11-24 23:21:06 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2011-11-24 23:21:45 -0500
commit9ed439a9c07b69c2617cc98596611fdbdc22472c (patch)
tree67de5b64612bdcd4006e0a00730aa87e49aa73bb /src/backend/executor/execMain.c
parente90710f34a6d5a73475e4241852b377675600325 (diff)
downloadpostgresql-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/execMain.c')
-rw-r--r--src/backend/executor/execMain.c40
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);