aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2015-10-05 21:19:16 -0400
committerBruce Momjian <bruce@momjian.us>2015-10-05 21:19:16 -0400
commitb943f502b788a3708ca660785fd14a4ee938fdcd (patch)
tree218ef8c4f5e3143fb4d43ee67ffd4371bb036466
parent28b3a3d41a8b72841a3f5067217f639a7d337c0e (diff)
downloadpostgresql-b943f502b788a3708ca660785fd14a4ee938fdcd.tar.gz
postgresql-b943f502b788a3708ca660785fd14a4ee938fdcd.zip
Have CREATE TABLE LIKE add OID column if any LIKEd table has one
Also, process constraints for LIKEd tables at the end so an OID column can be referenced in a constraint. Report by Tom Lane
-rw-r--r--src/backend/parser/parse_utilcmd.c44
-rw-r--r--src/test/regress/expected/create_table.out3
-rw-r--r--src/test/regress/expected/create_table_like.out27
-rw-r--r--src/test/regress/sql/create_table.sql4
-rw-r--r--src/test/regress/sql/create_table_like.sql13
5 files changed, 86 insertions, 5 deletions
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 16d40c72406..14384d58dbe 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -56,6 +56,7 @@
#include "rewrite/rewriteManip.h"
#include "utils/acl.h"
#include "utils/builtins.h"
+#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
@@ -150,6 +151,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
Oid namespaceid;
Oid existing_relid;
ParseCallbackState pcbstate;
+ bool like_found = false;
/*
* We must not scribble on the passed-in CreateStmt, so copy it. (This is
@@ -242,7 +244,10 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
/*
* Run through each primary element in the table creation clause. Separate
- * column defs from constraints, and do preliminary analysis.
+ * column defs from constraints, and do preliminary analysis. We have to
+ * process column-defining clauses first because it can control the
+ * presence of columns which are referenced by columns referenced by
+ * constraints.
*/
foreach(elements, stmt->tableElts)
{
@@ -254,14 +259,19 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
transformColumnDefinition(&cxt, (ColumnDef *) element);
break;
- case T_Constraint:
- transformTableConstraint(&cxt, (Constraint *) element);
- break;
-
case T_TableLikeClause:
+ if (!like_found)
+ {
+ cxt.hasoids = false;
+ like_found = true;
+ }
transformTableLikeClause(&cxt, (TableLikeClause *) element);
break;
+ case T_Constraint:
+ /* process later */
+ break;
+
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(element));
@@ -269,6 +279,27 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
}
}
+ if (like_found)
+ {
+ /*
+ * To match INHERITS, the existance of any LIKE table with OIDs
+ * causes the new table to have oids. For the same reason,
+ * WITH/WITHOUT OIDs is also ignored with LIKE. We prepend
+ * because the first oid option list entry is honored. Our
+ * prepended WITHOUT OIDS clause will be overridden if an
+ * inherited table has oids.
+ */
+ stmt->options = lcons(makeDefElem("oids",
+ (Node *)makeInteger(cxt.hasoids)), stmt->options);
+ }
+
+ foreach(elements, stmt->tableElts)
+ {
+ Node *element = lfirst(elements);
+
+ if (nodeTag(element) == T_Constraint)
+ transformTableConstraint(&cxt, (Constraint *) element);
+ }
/*
* transformIndexConstraints wants cxt.alist to contain only index
* statements, so transfer anything we already have into save_alist.
@@ -860,6 +891,9 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
}
}
+ /* We use oids if at least one LIKE'ed table has oids. */
+ cxt->hasoids = cxt->hasoids || relation->rd_rel->relhasoids;
+
/*
* Copy CHECK constraints if requested, being careful to adjust attribute
* numbers so they match the child.
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index 8ba7bbc1113..41ceb874e8f 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -250,3 +250,6 @@ ERROR: relation "as_select1" already exists
CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
NOTICE: relation "as_select1" already exists, skipping
DROP TABLE as_select1;
+-- check that the oid column is added before the primary key is checked
+CREATE TABLE oid_pk (f1 INT, PRIMARY KEY(oid)) WITH OIDS;
+DROP TABLE oid_pk;
diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out
index a5fac7b1074..97edde17cf7 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -228,3 +228,30 @@ DROP TYPE ctlty1;
DROP VIEW ctlv1;
DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12;
NOTICE: table "ctlt10" does not exist, skipping
+/* LIKE WITH OIDS */
+CREATE TABLE has_oid (x INTEGER) WITH OIDS;
+CREATE TABLE no_oid (y INTEGER);
+CREATE TABLE like_test (z INTEGER, LIKE has_oid);
+SELECT oid FROM like_test;
+ oid
+-----
+(0 rows)
+
+CREATE TABLE like_test2 (z INTEGER, LIKE no_oid);
+SELECT oid FROM like_test2; -- fail
+ERROR: column "oid" does not exist
+LINE 1: SELECT oid FROM like_test2;
+ ^
+CREATE TABLE like_test3 (z INTEGER, LIKE has_oid, LIKE no_oid);
+SELECT oid FROM like_test3;
+ oid
+-----
+(0 rows)
+
+CREATE TABLE like_test4 (z INTEGER, PRIMARY KEY(oid), LIKE has_oid);
+SELECT oid FROM like_test4;
+ oid
+-----
+(0 rows)
+
+DROP TABLE has_oid, no_oid, like_test, like_test2, like_test3, like_test4;
diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql
index 03bb5ff704e..78bdc8bf5e7 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -265,3 +265,7 @@ CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
DROP TABLE as_select1;
+
+-- check that the oid column is added before the primary key is checked
+CREATE TABLE oid_pk (f1 INT, PRIMARY KEY(oid)) WITH OIDS;
+DROP TABLE oid_pk;
diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql
index 2d017bc02b5..6dded1fdefc 100644
--- a/src/test/regress/sql/create_table_like.sql
+++ b/src/test/regress/sql/create_table_like.sql
@@ -119,3 +119,16 @@ DROP SEQUENCE ctlseq1;
DROP TYPE ctlty1;
DROP VIEW ctlv1;
DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12;
+
+/* LIKE WITH OIDS */
+CREATE TABLE has_oid (x INTEGER) WITH OIDS;
+CREATE TABLE no_oid (y INTEGER);
+CREATE TABLE like_test (z INTEGER, LIKE has_oid);
+SELECT oid FROM like_test;
+CREATE TABLE like_test2 (z INTEGER, LIKE no_oid);
+SELECT oid FROM like_test2; -- fail
+CREATE TABLE like_test3 (z INTEGER, LIKE has_oid, LIKE no_oid);
+SELECT oid FROM like_test3;
+CREATE TABLE like_test4 (z INTEGER, PRIMARY KEY(oid), LIKE has_oid);
+SELECT oid FROM like_test4;
+DROP TABLE has_oid, no_oid, like_test, like_test2, like_test3, like_test4;