Commit b943f502 authored by Bruce Momjian's avatar Bruce Momjian

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
parent 28b3a3d4
......@@ -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.
......
......@@ -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;
......@@ -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;
......@@ -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;
......@@ -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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment