aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;