Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b943f50

Browse files
committed
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
1 parent 28b3a3d commit b943f50

File tree

5 files changed

+86
-5
lines changed

5 files changed

+86
-5
lines changed

src/backend/parser/parse_utilcmd.c

+39-5
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#include "rewrite/rewriteManip.h"
5757
#include "utils/acl.h"
5858
#include "utils/builtins.h"
59+
#include "utils/guc.h"
5960
#include "utils/lsyscache.h"
6061
#include "utils/rel.h"
6162
#include "utils/syscache.h"
@@ -150,6 +151,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
150151
Oid namespaceid;
151152
Oid existing_relid;
152153
ParseCallbackState pcbstate;
154+
bool like_found = false;
153155

154156
/*
155157
* We must not scribble on the passed-in CreateStmt, so copy it. (This is
@@ -242,7 +244,10 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
242244

243245
/*
244246
* Run through each primary element in the table creation clause. Separate
245-
* column defs from constraints, and do preliminary analysis.
247+
* column defs from constraints, and do preliminary analysis. We have to
248+
* process column-defining clauses first because it can control the
249+
* presence of columns which are referenced by columns referenced by
250+
* constraints.
246251
*/
247252
foreach(elements, stmt->tableElts)
248253
{
@@ -254,21 +259,47 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
254259
transformColumnDefinition(&cxt, (ColumnDef *) element);
255260
break;
256261

257-
case T_Constraint:
258-
transformTableConstraint(&cxt, (Constraint *) element);
259-
break;
260-
261262
case T_TableLikeClause:
263+
if (!like_found)
264+
{
265+
cxt.hasoids = false;
266+
like_found = true;
267+
}
262268
transformTableLikeClause(&cxt, (TableLikeClause *) element);
263269
break;
264270

271+
case T_Constraint:
272+
/* process later */
273+
break;
274+
265275
default:
266276
elog(ERROR, "unrecognized node type: %d",
267277
(int) nodeTag(element));
268278
break;
269279
}
270280
}
271281

282+
if (like_found)
283+
{
284+
/*
285+
* To match INHERITS, the existance of any LIKE table with OIDs
286+
* causes the new table to have oids. For the same reason,
287+
* WITH/WITHOUT OIDs is also ignored with LIKE. We prepend
288+
* because the first oid option list entry is honored. Our
289+
* prepended WITHOUT OIDS clause will be overridden if an
290+
* inherited table has oids.
291+
*/
292+
stmt->options = lcons(makeDefElem("oids",
293+
(Node *)makeInteger(cxt.hasoids)), stmt->options);
294+
}
295+
296+
foreach(elements, stmt->tableElts)
297+
{
298+
Node *element = lfirst(elements);
299+
300+
if (nodeTag(element) == T_Constraint)
301+
transformTableConstraint(&cxt, (Constraint *) element);
302+
}
272303
/*
273304
* transformIndexConstraints wants cxt.alist to contain only index
274305
* statements, so transfer anything we already have into save_alist.
@@ -860,6 +891,9 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
860891
}
861892
}
862893

894+
/* We use oids if at least one LIKE'ed table has oids. */
895+
cxt->hasoids = cxt->hasoids || relation->rd_rel->relhasoids;
896+
863897
/*
864898
* Copy CHECK constraints if requested, being careful to adjust attribute
865899
* numbers so they match the child.

src/test/regress/expected/create_table.out

+3
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,6 @@ ERROR: relation "as_select1" already exists
250250
CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
251251
NOTICE: relation "as_select1" already exists, skipping
252252
DROP TABLE as_select1;
253+
-- check that the oid column is added before the primary key is checked
254+
CREATE TABLE oid_pk (f1 INT, PRIMARY KEY(oid)) WITH OIDS;
255+
DROP TABLE oid_pk;

src/test/regress/expected/create_table_like.out

+27
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,30 @@ DROP TYPE ctlty1;
228228
DROP VIEW ctlv1;
229229
DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12;
230230
NOTICE: table "ctlt10" does not exist, skipping
231+
/* LIKE WITH OIDS */
232+
CREATE TABLE has_oid (x INTEGER) WITH OIDS;
233+
CREATE TABLE no_oid (y INTEGER);
234+
CREATE TABLE like_test (z INTEGER, LIKE has_oid);
235+
SELECT oid FROM like_test;
236+
oid
237+
-----
238+
(0 rows)
239+
240+
CREATE TABLE like_test2 (z INTEGER, LIKE no_oid);
241+
SELECT oid FROM like_test2; -- fail
242+
ERROR: column "oid" does not exist
243+
LINE 1: SELECT oid FROM like_test2;
244+
^
245+
CREATE TABLE like_test3 (z INTEGER, LIKE has_oid, LIKE no_oid);
246+
SELECT oid FROM like_test3;
247+
oid
248+
-----
249+
(0 rows)
250+
251+
CREATE TABLE like_test4 (z INTEGER, PRIMARY KEY(oid), LIKE has_oid);
252+
SELECT oid FROM like_test4;
253+
oid
254+
-----
255+
(0 rows)
256+
257+
DROP TABLE has_oid, no_oid, like_test, like_test2, like_test3, like_test4;

src/test/regress/sql/create_table.sql

+4
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,7 @@ CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
265265
CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
266266
CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
267267
DROP TABLE as_select1;
268+
269+
-- check that the oid column is added before the primary key is checked
270+
CREATE TABLE oid_pk (f1 INT, PRIMARY KEY(oid)) WITH OIDS;
271+
DROP TABLE oid_pk;

src/test/regress/sql/create_table_like.sql

+13
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,16 @@ DROP SEQUENCE ctlseq1;
119119
DROP TYPE ctlty1;
120120
DROP VIEW ctlv1;
121121
DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12;
122+
123+
/* LIKE WITH OIDS */
124+
CREATE TABLE has_oid (x INTEGER) WITH OIDS;
125+
CREATE TABLE no_oid (y INTEGER);
126+
CREATE TABLE like_test (z INTEGER, LIKE has_oid);
127+
SELECT oid FROM like_test;
128+
CREATE TABLE like_test2 (z INTEGER, LIKE no_oid);
129+
SELECT oid FROM like_test2; -- fail
130+
CREATE TABLE like_test3 (z INTEGER, LIKE has_oid, LIKE no_oid);
131+
SELECT oid FROM like_test3;
132+
CREATE TABLE like_test4 (z INTEGER, PRIMARY KEY(oid), LIKE has_oid);
133+
SELECT oid FROM like_test4;
134+
DROP TABLE has_oid, no_oid, like_test, like_test2, like_test3, like_test4;

0 commit comments

Comments
 (0)