Commit 265f904d authored by Tom Lane's avatar Tom Lane

Code review for LIKE ... INCLUDING INDEXES patch. Fix failure to propagate

constraint status of copied indexes (bug #3774), as well as various other
small bugs such as failure to pstrdup when needed.  Allow INCLUDING INDEXES
indexes to be merged with identical declared indexes (perhaps not real useful,
but the code is there and having it not apply to LIKE indexes seems pretty
unorthogonal).  Avoid useless work in generateClonedIndexStmt().  Undo some
poorly chosen API changes, and put a couple of routines in modules that seem
to be better places for them.
parent ba9da684
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.6 2007/11/15 21:14:31 momjian Exp $
* $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.7 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -18,6 +18,7 @@
#include "access/reloptions.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "nodes/makefuncs.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/rel.h"
......@@ -149,6 +150,50 @@ transformRelOptions(Datum oldOptions, List *defList,
}
/*
* Convert the text-array format of reloptions into a List of DefElem.
* This is the inverse of transformRelOptions().
*/
List *
untransformRelOptions(Datum options)
{
List *result = NIL;
ArrayType *array;
Datum *optiondatums;
int noptions;
int i;
/* Nothing to do if no options */
if (options == (Datum) 0)
return result;
array = DatumGetArrayTypeP(options);
Assert(ARR_ELEMTYPE(array) == TEXTOID);
deconstruct_array(array, TEXTOID, -1, false, 'i',
&optiondatums, NULL, &noptions);
for (i = 0; i < noptions; i++)
{
char *s;
char *p;
Node *val = NULL;
s = DatumGetCString(DirectFunctionCall1(textout, optiondatums[i]));
p = strchr(s, '=');
if (p)
{
*p++ = '\0';
val = (Node *) makeString(pstrdup(p));
}
result = lappend(result, makeDefElem(pstrdup(s), val));
}
return result;
}
/*
* Interpret reloptions that are given in text-array format.
*
......
......@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.89 2007/07/17 05:02:00 neilc Exp $
* $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.90 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -252,7 +252,7 @@ Boot_DeclareIndexStmt:
LexIDStr($8),
NULL,
$10,
NULL, NIL, NULL,
NULL, NIL,
false, false, false,
false, false, true, false, false);
do_end();
......@@ -270,7 +270,7 @@ Boot_DeclareUniqueIndexStmt:
LexIDStr($9),
NULL,
$11,
NULL, NIL, NULL,
NULL, NIL,
true, false, false,
false, false, true, false, false);
do_end();
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_depend.c,v 1.24 2007/01/05 22:19:25 momjian Exp $
* $PostgreSQL: pgsql/src/backend/catalog/pg_depend.c,v 1.25 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -18,9 +18,11 @@
#include "access/heapam.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_depend.h"
#include "miscadmin.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
static bool isObjectPinned(const ObjectAddress *object, Relation rel);
......@@ -260,6 +262,62 @@ changeDependencyFor(Oid classId, Oid objectId,
return count;
}
/*
* isObjectPinned()
*
* Test if an object is required for basic database functionality.
* Caller must already have opened pg_depend.
*
* The passed subId, if any, is ignored; we assume that only whole objects
* are pinned (and that this implies pinning their components).
*/
static bool
isObjectPinned(const ObjectAddress *object, Relation rel)
{
bool ret = false;
SysScanDesc scan;
HeapTuple tup;
ScanKeyData key[2];
ScanKeyInit(&key[0],
Anum_pg_depend_refclassid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(object->classId));
ScanKeyInit(&key[1],
Anum_pg_depend_refobjid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(object->objectId));
scan = systable_beginscan(rel, DependReferenceIndexId, true,
SnapshotNow, 2, key);
/*
* Since we won't generate additional pg_depend entries for pinned
* objects, there can be at most one entry referencing a pinned object.
* Hence, it's sufficient to look at the first returned tuple; we don't
* need to loop.
*/
tup = systable_getnext(scan);
if (HeapTupleIsValid(tup))
{
Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
if (foundDep->deptype == DEPENDENCY_PIN)
ret = true;
}
systable_endscan(scan);
return ret;
}
/*
* Various special-purpose lookups and manipulations of pg_depend.
*/
/*
* Detect whether a sequence is marked as "owned" by a column
*
......@@ -359,52 +417,120 @@ markSequenceUnowned(Oid seqId)
heap_close(depRel, RowExclusiveLock);
}
/*
* isObjectPinned()
*
* Test if an object is required for basic database functionality.
* Caller must already have opened pg_depend.
* get_constraint_index
* Given the OID of a unique or primary-key constraint, return the
* OID of the underlying unique index.
*
* The passed subId, if any, is ignored; we assume that only whole objects
* are pinned (and that this implies pinning their components).
* Return InvalidOid if the index couldn't be found; this suggests the
* given OID is bogus, but we leave it to caller to decide what to do.
*/
static bool
isObjectPinned(const ObjectAddress *object, Relation rel)
Oid
get_constraint_index(Oid constraintId)
{
bool ret = false;
Oid indexId = InvalidOid;
Relation depRel;
ScanKeyData key[3];
SysScanDesc scan;
HeapTuple tup;
ScanKeyData key[2];
/* Search the dependency table for the dependent index */
depRel = heap_open(DependRelationId, AccessShareLock);
ScanKeyInit(&key[0],
Anum_pg_depend_refclassid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(object->classId));
ObjectIdGetDatum(ConstraintRelationId));
ScanKeyInit(&key[1],
Anum_pg_depend_refobjid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(object->objectId));
ObjectIdGetDatum(constraintId));
ScanKeyInit(&key[2],
Anum_pg_depend_refobjsubid,
BTEqualStrategyNumber, F_INT4EQ,
Int32GetDatum(0));
scan = systable_beginscan(rel, DependReferenceIndexId, true,
SnapshotNow, 2, key);
scan = systable_beginscan(depRel, DependReferenceIndexId, true,
SnapshotNow, 3, key);
/*
* Since we won't generate additional pg_depend entries for pinned
* objects, there can be at most one entry referencing a pinned object.
* Hence, it's sufficient to look at the first returned tuple; we don't
* need to loop.
*/
tup = systable_getnext(scan);
if (HeapTupleIsValid(tup))
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
if (foundDep->deptype == DEPENDENCY_PIN)
ret = true;
/*
* We assume any internal dependency of an index on the constraint
* must be what we are looking for. (The relkind test is just
* paranoia; there shouldn't be any such dependencies otherwise.)
*/
if (deprec->classid == RelationRelationId &&
deprec->objsubid == 0 &&
deprec->deptype == DEPENDENCY_INTERNAL &&
get_rel_relkind(deprec->objid) == RELKIND_INDEX)
{
indexId = deprec->objid;
break;
}
}
systable_endscan(scan);
heap_close(depRel, AccessShareLock);
return ret;
return indexId;
}
/*
* get_index_constraint
* Given the OID of an index, return the OID of the owning unique or
* primary-key constraint, or InvalidOid if no such constraint.
*/
Oid
get_index_constraint(Oid indexId)
{
Oid constraintId = InvalidOid;
Relation depRel;
ScanKeyData key[3];
SysScanDesc scan;
HeapTuple tup;
/* Search the dependency table for the index */
depRel = heap_open(DependRelationId, AccessShareLock);
ScanKeyInit(&key[0],
Anum_pg_depend_classid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(RelationRelationId));
ScanKeyInit(&key[1],
Anum_pg_depend_objid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(indexId));
ScanKeyInit(&key[2],
Anum_pg_depend_objsubid,
BTEqualStrategyNumber, F_INT4EQ,
Int32GetDatum(0));
scan = systable_beginscan(depRel, DependDependerIndexId, true,
SnapshotNow, 3, key);
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
/*
* We assume any internal dependency on a constraint
* must be what we are looking for.
*/
if (deprec->refclassid == ConstraintRelationId &&
deprec->refobjsubid == 0 &&
deprec->deptype == DEPENDENCY_INTERNAL)
{
constraintId = deprec->refobjid;
break;
}
}
systable_endscan(scan);
heap_close(depRel, AccessShareLock);
return constraintId;
}
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.167 2007/11/15 21:14:33 momjian Exp $
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.168 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -80,8 +80,6 @@ static bool relationHasPrimaryKey(Relation rel);
* to index on.
* 'predicate': the partial-index condition, or NULL if none.
* 'options': reloptions from WITH (in list-of-DefElem form).
* 'src_options': reloptions from the source index, if this is a cloned
* index produced by CREATE TABLE LIKE ... INCLUDING INDEXES
* 'unique': make the index enforce uniqueness.
* 'primary': mark the index as a primary key in the catalogs.
* 'isconstraint': index is for a PRIMARY KEY or UNIQUE constraint,
......@@ -103,7 +101,6 @@ DefineIndex(RangeVar *heapRelation,
List *attributeList,
Expr *predicate,
List *options,
char *src_options,
bool unique,
bool primary,
bool isconstraint,
......@@ -396,16 +393,9 @@ DefineIndex(RangeVar *heapRelation,
}
/*
* Parse AM-specific options, convert to text array form, validate. The
* src_options introduced due to using indexes via the "CREATE LIKE
* INCLUDING INDEXES" statement also need to be merged here
* Parse AM-specific options, convert to text array form, validate.
*/
if (src_options)
reloptions = unflatten_reloptions(src_options);
else
reloptions = (Datum) 0;
reloptions = transformRelOptions(reloptions, options, false, false);
reloptions = transformRelOptions((Datum) 0, options, false, false);
(void) index_reloptions(amoptions, reloptions, true);
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.236 2007/11/15 21:14:33 momjian Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.237 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -3795,7 +3795,6 @@ ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
stmt->indexParams, /* parameters */
(Expr *) stmt->whereClause,
stmt->options,
stmt->src_options,
stmt->unique,
stmt->primary,
stmt->isconstraint,
......
......@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.385 2007/11/15 22:25:15 momjian Exp $
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.386 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -2195,7 +2195,6 @@ _copyIndexStmt(IndexStmt *from)
COPY_STRING_FIELD(tableSpace);
COPY_NODE_FIELD(indexParams);
COPY_NODE_FIELD(options);
COPY_STRING_FIELD(src_options);
COPY_NODE_FIELD(whereClause);
COPY_SCALAR_FIELD(unique);
COPY_SCALAR_FIELD(primary);
......
......@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.315 2007/11/15 22:25:15 momjian Exp $
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.316 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1046,7 +1046,6 @@ _equalIndexStmt(IndexStmt *a, IndexStmt *b)
COMPARE_STRING_FIELD(tableSpace);
COMPARE_NODE_FIELD(indexParams);
COMPARE_NODE_FIELD(options);
COMPARE_STRING_FIELD(src_options);
COMPARE_NODE_FIELD(whereClause);
COMPARE_SCALAR_FIELD(unique);
COMPARE_SCALAR_FIELD(primary);
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.318 2007/11/15 22:25:15 momjian Exp $
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.319 2007/12/01 23:44:44 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
......@@ -1546,7 +1546,6 @@ _outIndexStmt(StringInfo str, IndexStmt *node)
WRITE_STRING_FIELD(tableSpace);
WRITE_NODE_FIELD(indexParams);
WRITE_NODE_FIELD(options);
WRITE_STRING_FIELD(src_options);
WRITE_NODE_FIELD(whereClause);
WRITE_BOOL_FIELD(unique);
WRITE_BOOL_FIELD(primary);
......
This diff is collapsed.
......@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.287 2007/11/15 21:14:38 momjian Exp $
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.288 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -924,7 +924,6 @@ ProcessUtility(Node *parsetree,
stmt->indexParams, /* parameters */
(Expr *) stmt->whereClause,
stmt->options,
stmt->src_options,
stmt->unique,
stmt->primary,
stmt->isconstraint,
......
......@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.265 2007/11/15 21:14:39 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.266 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -133,7 +133,6 @@ static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
int prettyFlags);
static char *pg_get_expr_worker(text *expr, Oid relid, char *relname,
int prettyFlags);
static Oid get_constraint_index(Oid constraintId);
static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
int prettyFlags);
static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
......@@ -195,6 +194,7 @@ static char *generate_relation_name(Oid relid);
static char *generate_function_name(Oid funcid, int nargs, Oid *argtypes);
static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
static text *string_to_text(char *str);
static char *flatten_reloptions(Oid relid);
#define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
......@@ -1384,68 +1384,6 @@ pg_get_serial_sequence(PG_FUNCTION_ARGS)
}
/*
* get_constraint_index
* Given the OID of a unique or primary-key constraint, return the
* OID of the underlying unique index.
*
* Return InvalidOid if the index couldn't be found; this suggests the
* given OID is bogus, but we leave it to caller to decide what to do.
*/
static Oid
get_constraint_index(Oid constraintId)
{
Oid indexId = InvalidOid;
Relation depRel;
ScanKeyData key[3];
SysScanDesc scan;
HeapTuple tup;
/* Search the dependency table for the dependent index */
depRel = heap_open(DependRelationId, AccessShareLock);
ScanKeyInit(&key[0],
Anum_pg_depend_refclassid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(ConstraintRelationId));
ScanKeyInit(&key[1],
Anum_pg_depend_refobjid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(constraintId));
ScanKeyInit(&key[2],
Anum_pg_depend_refobjsubid,
BTEqualStrategyNumber, F_INT4EQ,
Int32GetDatum(0));
scan = systable_beginscan(depRel, DependReferenceIndexId, true,
SnapshotNow, 3, key);
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
/*
* We assume any internal dependency of an index on the constraint
* must be what we are looking for. (The relkind test is just
* paranoia; there shouldn't be any such dependencies otherwise.)
*/
if (deprec->classid == RelationRelationId &&
deprec->objsubid == 0 &&
deprec->deptype == DEPENDENCY_INTERNAL &&
get_rel_relkind(deprec->objid) == RELKIND_INDEX)
{
indexId = deprec->objid;
break;
}
}
systable_endscan(scan);
heap_close(depRel, AccessShareLock);
return indexId;
}
/*
* deparse_expression - General utility for deparsing expressions
*
......@@ -5507,7 +5445,7 @@ string_to_text(char *str)
/*
* Generate a C string representing a relation's reloptions, or NULL if none.
*/
char *
static char *
flatten_reloptions(Oid relid)
{
char *result = NULL;
......@@ -5543,32 +5481,3 @@ flatten_reloptions(Oid relid)
return result;
}
/*
* Generate an Array Datum representing a relation's reloptions using
* a C string
*/
Datum
unflatten_reloptions(char *reloptstring)
{
Datum result = (Datum) 0;
if (reloptstring)
{
Datum sep,
relopts;
/*
* We want to use text_to_array(reloptstring, ', ') --- but
* DirectFunctionCall2(text_to_array) does not work, because
* text_to_array() relies on fcinfo to be valid. So use
* OidFunctionCall2.
*/
sep = DirectFunctionCall1(textin, CStringGetDatum(", "));
relopts = DirectFunctionCall1(textin, CStringGetDatum(reloptstring));
result = OidFunctionCall2(F_TEXT_TO_ARRAY, relopts, sep);
}
return result;
}
......@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.3 2007/01/05 22:19:51 momjian Exp $
* $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.4 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -23,6 +23,8 @@
extern Datum transformRelOptions(Datum oldOptions, List *defList,
bool ignoreOids, bool isReset);
extern List *untransformRelOptions(Datum options);
extern void parseRelOptions(Datum options, int numkeywords,
const char *const * keywords,
char **values, bool validate);
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.31 2007/11/15 21:14:42 momjian Exp $
* $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.32 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -207,6 +207,10 @@ extern bool sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId);
extern void markSequenceUnowned(Oid seqId);
extern Oid get_constraint_index(Oid constraintId);
extern Oid get_index_constraint(Oid indexId);
/* in pg_shdepend.c */
extern void recordSharedDependencyOn(ObjectAddress *depender,
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.86 2007/11/15 22:25:17 momjian Exp $
* $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.87 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -26,7 +26,6 @@ extern void DefineIndex(RangeVar *heapRelation,
List *attributeList,
Expr *predicate,
List *options,
char *src_options,
bool unique,
bool primary,
bool isconstraint,
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.356 2007/11/15 22:25:17 momjian Exp $
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.357 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1540,7 +1540,6 @@ typedef struct IndexStmt
char *tableSpace; /* tablespace, or NULL to use parent's */
List *indexParams; /* a list of IndexElem */
List *options; /* options from WITH clause */
char *src_options; /* relopts inherited from source index */
Node *whereClause; /* qualification (partial-index predicate) */
bool unique; /* is index unique? */
bool primary; /* is index on primary key? */
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.306 2007/11/15 21:14:45 momjian Exp $
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.307 2007/12/01 23:44:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -566,8 +566,6 @@ extern List *deparse_context_for_plan(Node *outer_plan, Node *inner_plan,
extern const char *quote_identifier(const char *ident);
extern char *quote_qualified_identifier(const char *namespace,
const char *ident);
extern char *flatten_reloptions(Oid relid);
extern Datum unflatten_reloptions(char *reloptstring);
/* tid.c */
extern Datum tidin(PG_FUNCTION_ARGS);
......
......@@ -634,6 +634,7 @@ SELECT * FROM inhg; /* Two records with three columns in order x=x, xx=text, y=y
DROP TABLE inhg;
CREATE TABLE inhg (x text, LIKE inhx INCLUDING INDEXES, y text); /* copies indexes */
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "inhg_pkey" for table "inhg"
INSERT INTO inhg VALUES (5, 10);
INSERT INTO inhg VALUES (20, 10); -- should fail
ERROR: duplicate key value violates unique constraint "inhg_pkey"
......@@ -647,6 +648,7 @@ CREATE UNIQUE INDEX inhz_xx_idx on inhz (xx) WHERE xx <> 'test';
/* Ok to create multiple unique indexes */
CREATE TABLE inhg (x text UNIQUE, LIKE inhz INCLUDING INDEXES);
NOTICE: CREATE TABLE / UNIQUE will create implicit index "inhg_x_key" for table "inhg"
NOTICE: CREATE TABLE / UNIQUE will create implicit index "inhg_yy_key" for table "inhg"
INSERT INTO inhg (xx, yy, x) VALUES ('test', 5, 10);
INSERT INTO inhg (xx, yy, x) VALUES ('test', 10, 15);
INSERT INTO inhg (xx, yy, x) VALUES ('foo', 10, 15); -- should fail
......
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