diff -dcrpN pgsql.orig/doc/src/sgml/catalogs.sgml pgsql/doc/src/sgml/catalogs.sgml
*** pgsql.orig/doc/src/sgml/catalogs.sgml 2007-02-15 12:35:59.000000000 +0100
--- pgsql/doc/src/sgml/catalogs.sgml 2007-02-26 00:07:11.000000000 +0100
***************
*** 969,974 ****
--- 969,993 ----
+
+ attidentity
+ bool
+
+
+ This column is an IDENTITY column.
+
+
+
+
+ attforceddef
+ bool
+
+
+ This column is defined as GENERATED ALWAYS and the
+ default value is always enforced.
+
+
+
diff -dcrpN pgsql.orig/doc/src/sgml/datatype.sgml pgsql/doc/src/sgml/datatype.sgml
*** pgsql.orig/doc/src/sgml/datatype.sgml 2007-02-09 07:22:55.000000000 +0100
--- pgsql/doc/src/sgml/datatype.sgml 2007-02-27 23:52:39.000000000 +0100
*************** ALTER SEQUENCE
+ Identity Columns
+
+
+ identity
+
+
+
+ sequence
+ and identity column
+
+
+
+ Identity columns are similar to the
+ pseudo data types serial and
+ bigserial but also have different properties.
+
+
+
+ Identity is not a type, but a type
+ modifier. As such, an identity column isn't
+ limited to numeric types. Every type that has an implicit
+ cast from int8 can be used as an
+ identity column.
+
+
+ CREATE TABLE tablename (
+ colname coltype
+ GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY
+ );
+
+
+ In the above example coltype can be e.g. float,
+ decimal or text.
+
+
+
+ There is a difference in the order of events that
+ leads to the generation of the next value of the
+ underlying sequence. A serial column gets
+ its default value the same way as other, non-serial
+ columns, e.g. the columns are assigned with default values
+ first, then the row is validated the row via NOT NULL,
+ CHECK and other constraints. The identity column
+ is left out of these checks in the first phase then
+ it gets assigned with its default value and after all
+ finally it's also validated via constraints. That means
+ that the sequence values are not inflated when some other
+ field fails its constraint validation. This is especially
+ important for some application where strict numbering
+ is required. As a consequence, an identity
+ column cannot have a CHECK constraint.
+
+
+
+ Sequence generation options can be specified at table creation:
+
+
+ CREATE TABLE tablename (
+ colname coltype
+ GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [( sequence_options )]
+ );
+
+
+ The optional sequence_options
+ are the same sequence options that can be used to
+ CREATE or ALTER a sequence.
+
+
+
+ For an identity column, either
+ GENERATED ALWAYS or
+ GENERATED BY DEFAULT can be specified.
+ The behaviour for GENERATED BY DEFAULT
+ is similar to the serial pseudo-type, e.g.
+ the sequence next value generation can be suppressed
+ at INSERT by providing a value manually.
+ With GENERATED ALWAYS, the sequence
+ generation cannot be suppressed, the manually provided
+ value is ignored.
+
+
+
+ There can be only one identity column
+ in a table at any time.
+
+
+
+ The identity column in PostgreSQL conforms
+ to the SQL:2003 standard.
+
+
+
+
+ Generated Columns
+
+
+ generated
+
+
+
+ Generated is not a type, but a type
+ modifier. As such, a generated column isn't
+ limited to numeric types. Generated columns
+ are columns with enforced DEFAULT values.
+ This kind of columns can be used to keep a "static" value
+ in the table whose value may depend on other columns of
+ the same row.
+
+
+ CREATE TABLE tablename (
+ colname coltype
+ GENERATED ALWAYS AS ( expression )
+ );
+
+
+
+
+ The value of the generated column is
+ computed after all other columns are assigned with their
+ values but before the identity column's
+ next serial value is computed. A generated
+ column cannot reference other generated
+ or identity columns. A generated
+ column cannot have a CHECK constraint.
+
+
+
+ The generated column in PostgreSQL conforms
+ to the SQL:2003 standard.
+
+
diff -dcrpN pgsql.orig/doc/src/sgml/ref/alter_table.sgml pgsql/doc/src/sgml/ref/alter_table.sgml
*** pgsql.orig/doc/src/sgml/ref/alter_table.sgml 2007-02-09 07:23:10.000000000 +0100
--- pgsql/doc/src/sgml/ref/alter_table.sgml 2007-02-26 00:07:11.000000000 +0100
*************** where act
*** 36,41 ****
--- 36,43 ----
ALTER [ COLUMN ] column TYPE type [ USING expression ]
ALTER [ COLUMN ] column SET DEFAULT expression
ALTER [ COLUMN ] column DROP DEFAULT
+ ALTER [ COLUMN ] column SET GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY
+ ALTER [ COLUMN ] column DROP IDENTITY
ALTER [ COLUMN ] column { SET | DROP } NOT NULL
ALTER [ COLUMN ] column SET STATISTICS integer
ALTER [ COLUMN ] column SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
*************** where act
*** 118,123 ****
--- 120,146 ----
+ SET/GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY
+
+
+ This form "upgrades" a column that has an associated
+ sequence to an IDENTITY column. See also
+ ALTER SEQUENCE ... OWNED BY
+
+
+
+
+
+ SET/DROP IDENTITY
+
+
+ This form downgrades an IDENTITY to a regular column.
+ The column still keeps the OWNED sequence and its DEFAULT.
+
+
+
+
+
SET/DROP NOT NULL
*************** where act
*** 358,363 ****
--- 381,393 ----
(or an index, sequence, or view) or the name of an individual column in
a table. There is no effect on the stored data.
+
+
+ If the renamed column is SERIAL or it's an
+ identity column, the underlying sequence is
+ also renamed so it always tries to keep the
+ tablename_columnname_seq form.
+
*************** ALTER TABLE table ALTER COLUMN anycol TY
*** 661,667 ****
drop the default with DROP DEFAULT>, perform the ALTER
TYPE>, and then use SET DEFAULT> to add a suitable new
default. Similar considerations apply to indexes and constraints involving
! the column.
--- 691,698 ----
drop the default with DROP DEFAULT>, perform the ALTER
TYPE>, and then use SET DEFAULT> to add a suitable new
default. Similar considerations apply to indexes and constraints involving
! the column. Note that both SET DEFAULT and DROP DEFAULT are forbidden
! on IDENTITY and GENERATED ALWAYS columns.
diff -dcrpN pgsql.orig/doc/src/sgml/ref/copy.sgml pgsql/doc/src/sgml/ref/copy.sgml
*** pgsql.orig/doc/src/sgml/ref/copy.sgml 2007-02-09 07:23:11.000000000 +0100
--- pgsql/doc/src/sgml/ref/copy.sgml 2007-02-26 00:07:11.000000000 +0100
*************** PostgreSQL documentation
*** 22,27 ****
--- 22,28 ----
COPY tablename [ ( column [, ...] ) ]
+ [ OVERRIDING { SYSTEM | USER } VALUE ]
FROM { 'filename' | STDIN }
[ [ WITH ]
[ BINARY ]
*************** COPY { ta
*** 116,121 ****
--- 117,134 ----
+ OVERRIDING { SYSTEM | USER } VALUE
+
+
+ Specifies that values override enforced default values
+ for GENERATED ALWAYS columns. Only effective for
+ COPY tablename FROM
+ Only allowed for the owner of the table.
+
+
+
+
+
filename
diff -dcrpN pgsql.orig/doc/src/sgml/ref/create_table.sgml pgsql/doc/src/sgml/ref/create_table.sgml
*** pgsql.orig/doc/src/sgml/ref/create_table.sgml 2007-02-09 07:23:12.000000000 +0100
--- pgsql/doc/src/sgml/ref/create_table.sgml 2007-02-26 00:07:11.000000000 +0100
*************** PostgreSQL documentation
*** 21,27 ****
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name ( [
! { column_name data_type [ DEFAULT default_expr> ] [ column_constraint [ ... ] ]
| table_constraint
| LIKE parent_table [ { INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS } ] ... }
[, ... ]
--- 21,29 ----
CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name ( [
! { column_name data_type
! | [ DEFAULT default_expr> | GENERATED ALWAYS AS (default_expr ) | GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] ]
! | [ column_constraint [ ... ] ]
| table_constraint
| LIKE parent_table [ { INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS } ] ... }
[, ... ]
*************** and table
*** 186,191 ****
--- 188,236 ----
+ GENERATED ALWAYS AS (
+ default_expr )
+
+
+ This creates a GENERATED column. It's similar
+ to the DEFAULT> clause, with the following
+ exceptions. In an INSERT operation the default value
+ will be enforced even when an expression is specified.
+ This can be overridden by specifying OVERRIDING SYSTEM VALUE
+ but it's only allowed for the table owner.
+ In an UPDATE statement, only
+ SET colname = DEFAULT
+ is allowed for such columns.
+
+
+
+
+
+ GENERATED { ALWAYS BY DEFAULT } AS IDENTITY [ (
+ sequence_options ) ]
+
+
+ This clause creates an identity column, whose default value
+ will be generated by an automatically created sequence.
+ For the SERIAL> pseudo-type this is implicit.
+ However, any type that has implicit cast from bigint
+ can be specified for the column.
+
+
+
+ With GENERATED ALWAYS AS IDENTITY, the default value
+ will always be enforced in an INSERT operation.
+ OVERRIDING SYSTEM VALUE works the same just as with GENERATED columns.
+ However, any occurence of such columns in an UPDATE statement is forbidden.
+ With this feature, one can approximate the autoincrementer type
+ that other DBMSs provide, e.g.:
+ INSERT INTO table (id, ... ) VALUES (0, ...);
+ will insert a new column with the next sequence value instead of 0.
+
+
+
+
+
INHERITS ( parent_table [, ... ] )
diff -dcrpN pgsql.orig/doc/src/sgml/ref/insert.sgml pgsql/doc/src/sgml/ref/insert.sgml
*** pgsql.orig/doc/src/sgml/ref/insert.sgml 2007-02-09 07:23:12.000000000 +0100
--- pgsql/doc/src/sgml/ref/insert.sgml 2007-02-26 00:07:11.000000000 +0100
*************** PostgreSQL documentation
*** 21,26 ****
--- 21,27 ----
INSERT INTO table [ ( column [, ...] ) ]
+ [ OVERRIDING { SYSTEM | USER } VALUE ]
{ DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }
[ RETURNING * | output_expression [ AS output_name ] [, ...] ]
*************** INSERT INTO objtype == ACL_OBJECT_RELATION &&
+ pg_class_tuple->relkind == RELKIND_SEQUENCE &&
+ (istmt->privileges & (ACL_UPDATE|ACL_INSERT)))
+ {
+ InternalGrant seq_istmt;
+ Oid sequenceId;
+ int idx;
+
+ seq_istmt.is_grant = istmt->is_grant;
+ seq_istmt.objtype = ACL_OBJECT_SEQUENCE;
+ seq_istmt.all_privs = true;
+ seq_istmt.privileges = ACL_ALL_RIGHTS_SEQUENCE;
+ seq_istmt.grantees = istmt->grantees;
+ /* don't give out GRANT on the supporting sequence */
+ seq_istmt.grant_option = false;
+ seq_istmt.behavior = istmt->behavior;
+ seq_istmt.objects = NIL;
+ for (idx = 0; idx < relation->rd_att->natts; idx++)
+ {
+ if (relation->rd_att->attrs[idx]->attisdropped)
+ continue;
+ if (relation->rd_att->attrs[idx]->attidentity)
+ {
+ sequenceId = get_relid_att_serial_sequence(relOid, idx);
+ if (OidIsValid(sequenceId))
+ seq_istmt.objects = lappend_oid(seq_istmt.objects, sequenceId);
+ }
+ }
+ if (seq_istmt.objects)
+ {
+ ExecGrantStmt_oids(&seq_istmt);
+ list_free(seq_istmt.objects);
+ }
+ }
+
ReleaseSysCache(tuple);
pfree(new_acl);
*************** ExecGrant_Relation(InternalGrant *istmt)
*** 720,725 ****
--- 761,877 ----
heap_close(relation, RowExclusiveLock);
}
+ /*
+ * This is called when a new IDENTITY column is
+ * added to the table. It adds UPDATE permission
+ * for those who have INSERT or UPDATE permission
+ * on the table over the newly created sequence.
+ */
+ void
+ ExecGrant_Sequence(Oid relOid, int attnum, Oid seqOid)
+ {
+ Relation relation;
+ Datum aclDatum;
+ Form_pg_class pg_class_tuple;
+ bool isNull;
+ AclMode avail_goptions;
+ AclMode this_privileges;
+ Acl *acl;
+ Oid grantorId;
+ Oid ownerId;
+ HeapTuple tuple;
+ int nmembers;
+ Oid *members;
+ InternalGrant istmt;
+ int idx;
+
+ /*
+ * Fill istmt in advance.
+ */
+ istmt.is_grant = true;
+ istmt.objtype = ACL_OBJECT_SEQUENCE;
+ istmt.all_privs = true;
+ istmt.privileges = ACL_ALL_RIGHTS_SEQUENCE;
+ istmt.grantees = NULL;
+ istmt.grant_option = false;
+ istmt.behavior = DROP_RESTRICT;
+ istmt.objects = NULL;
+
+ relation = heap_open(RelationRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCache(RELOID,
+ ObjectIdGetDatum(relOid),
+ 0, 0, 0);
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", relOid);
+ pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
+
+ /* Not sensible to grant on an index */
+ if (pg_class_tuple->relkind == RELKIND_INDEX)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is an index",
+ NameStr(pg_class_tuple->relname))));
+
+ /* Composite types aren't tables either */
+ if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is a composite type",
+ NameStr(pg_class_tuple->relname))));
+
+ /*
+ * Get owner ID and working copy of existing ACL. If there's no ACL,
+ * substitute the proper default.
+ */
+ ownerId = pg_class_tuple->relowner;
+ aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
+ &isNull);
+
+ if (isNull)
+ acl = acldefault(ACL_OBJECT_RELATION, ownerId);
+ else
+ acl = DatumGetAclPCopy(aclDatum);
+
+ /* Determine ID to do the grant as, and available grant options */
+ this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
+ select_best_grantor(GetUserId(), this_privileges,
+ acl, ownerId,
+ &grantorId, &avail_goptions);
+
+ /*
+ * Restrict the privileges to what we can actually grant, and emit
+ * the standards-mandated warning and error messages.
+ */
+ this_privileges =
+ restrict_and_check_grant(false, avail_goptions,
+ true,
+ this_privileges,
+ relOid, grantorId,
+ ACL_KIND_CLASS,
+ NameStr(pg_class_tuple->relname));
+
+ nmembers = aclmemberspriv(acl, &members, (ACL_UPDATE|ACL_INSERT), false);
+ for (idx = 0; idx < nmembers; idx++)
+ istmt.grantees = lappend_oid(istmt.grantees, members[idx]);
+ pfree(members);
+
+ ReleaseSysCache(tuple);
+
+ pfree(acl);
+
+ heap_close(relation, RowExclusiveLock);
+
+ if (istmt.grantees != NULL)
+ {
+ istmt.objects = list_make1_oid(seqOid);
+ ExecGrant_Relation(&istmt);
+ list_free(istmt.grantees);
+ list_free(istmt.objects);
+ }
+ }
+
static void
ExecGrant_Database(InternalGrant *istmt)
{
diff -dcrpN pgsql.orig/src/backend/catalog/heap.c pgsql/src/backend/catalog/heap.c
*** pgsql.orig/src/backend/catalog/heap.c 2007-02-15 12:36:04.000000000 +0100
--- pgsql/src/backend/catalog/heap.c 2007-02-26 12:53:47.000000000 +0100
*************** RemoveAttrDefaultById(Oid attrdefId)
*** 1199,1204 ****
--- 1199,1206 ----
myattnum, myrelid);
((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
+ ((Form_pg_attribute) GETSTRUCT(tuple))->attidentity = false;
+ ((Form_pg_attribute) GETSTRUCT(tuple))->attforceddef = false;
simple_heap_update(attr_rel, &tuple->t_self, tuple);
*************** heap_drop_with_catalog(Oid relid)
*** 1292,1298 ****
* The expression must be presented as a nodeToString() string.
*/
void
! StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin)
{
Node *expr;
char *adsrc;
--- 1294,1300 ----
* The expression must be presented as a nodeToString() string.
*/
void
! StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin, bool attidentity, bool attforceddef)
{
Node *expr;
char *adsrc;
*************** StoreAttrDefault(Relation rel, AttrNumbe
*** 1306,1312 ****
Oid attrdefOid;
ObjectAddress colobject,
defobject;
!
/*
* Need to construct source equivalent of given node-string.
*/
--- 1308,1315 ----
Oid attrdefOid;
ObjectAddress colobject,
defobject;
! List *rtable;
!
/*
* Need to construct source equivalent of given node-string.
*/
*************** StoreAttrDefault(Relation rel, AttrNumbe
*** 1365,1370 ****
--- 1368,1375 ----
if (!attStruct->atthasdef)
{
attStruct->atthasdef = true;
+ attStruct->attidentity = attidentity;
+ attStruct->attforceddef = attforceddef;
simple_heap_update(attrrel, &atttup->t_self, atttup);
/* keep catalog indexes current */
CatalogUpdateIndexes(attrrel, atttup);
*************** StoreAttrDefault(Relation rel, AttrNumbe
*** 1385,1391 ****
/*
* Record dependencies on objects used in the expression, too.
*/
! recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);
}
/*
--- 1390,1412 ----
/*
* Record dependencies on objects used in the expression, too.
*/
! if (!attidentity && attforceddef)
! {
! ParseState *pstate;
! RangeTblEntry *rte;
!
! pstate = make_parsestate(NULL);
! rte = addRangeTableEntryForRelation(pstate,
! rel,
! NULL,
! false,
! true);
! addRTEtoQuery(pstate, rte, true, true, true);
! rtable = list_make1(rte);
! }
! else
! rtable = NIL;
! recordDependencyOnExpr(&defobject, expr, rtable, DEPENDENCY_NORMAL);
}
/*
*************** StoreConstraints(Relation rel, TupleDesc
*** 1504,1510 ****
for (i = 0; i < constr->num_defval; i++)
StoreAttrDefault(rel, constr->defval[i].adnum,
! constr->defval[i].adbin);
for (i = 0; i < constr->num_check; i++)
StoreRelCheck(rel, constr->check[i].ccname,
--- 1525,1532 ----
for (i = 0; i < constr->num_defval; i++)
StoreAttrDefault(rel, constr->defval[i].adnum,
! constr->defval[i].adbin,
! false, false);
for (i = 0; i < constr->num_check; i++)
StoreRelCheck(rel, constr->check[i].ccname,
*************** AddRelationRawConstraints(Relation rel,
*** 1554,1559 ****
--- 1576,1583 ----
ListCell *cell;
Node *expr;
CookedConstraint *cooked;
+ int varno;
+ int sublevels_up;
/*
* Get info about existing constraints.
*************** AddRelationRawConstraints(Relation rel,
*** 1584,1601 ****
{
RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
expr = cookDefault(pstate, colDef->raw_default,
atp->atttypid, atp->atttypmod,
! NameStr(atp->attname));
! StoreAttrDefault(rel, colDef->attnum, nodeToString(expr));
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_DEFAULT;
cooked->name = NULL;
cooked->attnum = colDef->attnum;
cooked->expr = expr;
cookedConstraints = lappend(cookedConstraints, cooked);
}
--- 1608,1660 ----
{
RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
+ int attnum;
expr = cookDefault(pstate, colDef->raw_default,
atp->atttypid, atp->atttypmod,
! NameStr(atp->attname),
! !colDef->is_identity && colDef->force_default);
! varno = RTERangeTablePosn(pstate, rte, &sublevels_up);
!
! if (!colDef->is_identity && colDef->force_default)
! {
! varno = RTERangeTablePosn(pstate, rte, &sublevels_up);
!
! for (attnum = 1; attnum <= tupleDesc->natts; attnum++)
! {
! if (tupleDesc->attrs[attnum - 1]->attisdropped)
! continue;
! if (tupleDesc->attrs[attnum - 1]->attidentity ||
! tupleDesc->attrs[attnum - 1]->attforceddef)
! {
! Node *var;
!
! var = scanRTEForColumn(pstate,
! rte,
! NameStr(tupleDesc->attrs[attnum - 1]->attname),
! -1);
! if (contain_var_reference(expr, varno, ((Var *)var)->varattno, sublevels_up))
! ereport(ERROR,
! (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
! errmsg("%s column \"%s\" of table \"%s\" cannot be referenced by GENERATED column \"%s\"",
! tupleDesc->attrs[attnum - 1]->attidentity ?
! "IDENTITY" : "GENERATED",
! get_attname(RelationGetRelid(rel), attnum),
! RelationGetRelationName(rel),
! get_attname(RelationGetRelid(rel), colDef->attnum))));
! }
! }
! }
!
! StoreAttrDefault(rel, colDef->attnum, nodeToString(expr), colDef->is_identity, colDef->force_default);
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_DEFAULT;
cooked->name = NULL;
cooked->attnum = colDef->attnum;
cooked->expr = expr;
+ cooked->force_default = colDef->force_default;
cookedConstraints = lappend(cookedConstraints, cooked);
}
*************** AddRelationRawConstraints(Relation rel,
*** 1608,1613 ****
--- 1667,1673 ----
{
Constraint *cdef = (Constraint *) lfirst(cell);
char *ccname;
+ int attnum;
if (cdef->contype != CONSTR_CHECK || cdef->raw_expr == NULL)
continue;
*************** AddRelationRawConstraints(Relation rel,
*** 1618,1623 ****
--- 1678,1709 ----
*/
expr = transformExpr(pstate, cdef->raw_expr);
+ varno = RTERangeTablePosn(pstate, rte, &sublevels_up);
+
+ for (attnum = 1; attnum <= tupleDesc->natts; attnum++)
+ {
+ if (tupleDesc->attrs[attnum - 1]->attisdropped)
+ continue;
+ if (tupleDesc->attrs[attnum - 1]->attidentity ||
+ tupleDesc->attrs[attnum - 1]->attforceddef)
+ {
+ Node *var;
+
+ var = scanRTEForColumn(pstate,
+ rte,
+ NameStr(tupleDesc->attrs[attnum - 1]->attname),
+ -1);
+ if (contain_var_reference(expr, varno, ((Var *)var)->varattno, sublevels_up))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
+ errmsg("%s column \"%s\" of table \"%s\" cannot be referenced in CHECK constraint",
+ tupleDesc->attrs[attnum - 1]->attidentity ?
+ "IDENTITY" : "GENERATED",
+ get_attname(RelationGetRelid(rel), attnum),
+ RelationGetRelationName(rel))));
+ }
+ }
+
/*
* Make sure it yields a boolean result.
*/
*************** cookDefault(ParseState *pstate,
*** 1799,1805 ****
Node *raw_default,
Oid atttypid,
int32 atttypmod,
! char *attname)
{
Node *expr;
--- 1885,1892 ----
Node *raw_default,
Oid atttypid,
int32 atttypmod,
! char *attname,
! bool force_default)
{
Node *expr;
*************** cookDefault(ParseState *pstate,
*** 1813,1819 ****
/*
* Make sure default expr does not refer to any vars.
*/
! if (contain_var_clause(expr))
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("cannot use column references in default expression")));
--- 1900,1906 ----
/*
* Make sure default expr does not refer to any vars.
*/
! if (!force_default && contain_var_clause(expr))
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("cannot use column references in default expression")));
diff -dcrpN pgsql.orig/src/backend/catalog/index.c pgsql/src/backend/catalog/index.c
*** pgsql.orig/src/backend/catalog/index.c 2007-02-15 12:36:04.000000000 +0100
--- pgsql/src/backend/catalog/index.c 2007-02-26 00:07:11.000000000 +0100
*************** ConstructTupleDescriptor(Relation heapRe
*** 166,171 ****
--- 166,173 ----
to->atthasdef = false;
to->attislocal = true;
to->attinhcount = 0;
+ to->attidentity = false;
+ to->attforceddef = false;
}
else
{
diff -dcrpN pgsql.orig/src/backend/commands/copy.c pgsql/src/backend/commands/copy.c
*** pgsql.orig/src/backend/commands/copy.c 2007-02-25 16:14:15.000000000 +0100
--- pgsql/src/backend/commands/copy.c 2007-02-26 10:25:30.000000000 +0100
***************
*** 40,45 ****
--- 40,46 ----
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
+ #include "utils/rel.h"
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
*************** typedef struct CopyStateData
*** 159,164 ****
--- 160,167 ----
char *raw_buf;
int raw_buf_index; /* next byte to process */
int raw_buf_len; /* total # of bytes stored */
+
+ bool overriding; /* OVERRIDING SYSTEM VALUE */
} CopyStateData;
typedef CopyStateData *CopyState;
*************** DoCopy(const CopyStmt *stmt)
*** 1137,1142 ****
--- 1140,1146 ----
cstate->copy_dest = COPY_FILE; /* default */
cstate->filename = stmt->filename;
+ cstate->overriding = stmt->overriding; /* OVERRIDING SYSTEM VALUE */
if (is_from) /* copy from file to database */
CopyFrom(cstate);
*************** CopyFrom(CopyState cstate)
*** 1676,1681 ****
--- 1680,1707 ----
RelationGetRelationName(cstate->rel))));
}
+ if (cstate->overriding)
+ {
+ TupleDesc tupDesc = RelationGetDescr(cstate->rel);
+ Form_pg_attribute *attr = tupDesc->attrs;
+ int idx;
+ bool hasforceddef;
+
+ hasforceddef = false;
+ for (idx = 0; idx < tupDesc->natts; idx++)
+ {
+ if (attr[idx]->attisdropped)
+ continue;
+ hasforceddef |= attr[idx]->attforceddef;
+ }
+ if (hasforceddef)
+ {
+ Oid relid = RelationGetRelid(cstate->rel);
+ if (!pg_class_ownercheck(relid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
+ get_rel_name(relid));
+ }
+ }
if (pipe)
{
if (whereToSendOutput == DestRemote)
*************** CopyFrom(CopyState cstate)
*** 1763,1769 ****
fmgr_info(in_func_oid, &in_functions[attnum - 1]);
/* Get default info if needed */
! if (!list_member_int(cstate->attnumlist, attnum))
{
/* attribute is NOT to be copied from input */
/* use default value if one exists */
--- 1789,1796 ----
fmgr_info(in_func_oid, &in_functions[attnum - 1]);
/* Get default info if needed */
! if (!list_member_int(cstate->attnumlist, attnum) ||
! (attr[attnum - 1]->attforceddef && !cstate->overriding))
{
/* attribute is NOT to be copied from input */
/* use default value if one exists */
*************** CopyFrom(CopyState cstate)
*** 2096,2103 ****
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
/* Check the constraints of the tuple */
! if (cstate->rel->rd_att->constr)
! ExecConstraints(resultRelInfo, slot, estate);
/* OK, store the tuple and create index entries for it */
fast_heap_insert(cstate->rel, tuple, use_wal);
--- 2123,2132 ----
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
/* Check the constraints of the tuple */
! if (cstate->rel->rd_att->constr) {
! ExecConstraints(resultRelInfo, slot, estate, false, false);
! ExecConstraints(resultRelInfo, slot, estate, true, true);
! }
/* OK, store the tuple and create index entries for it */
fast_heap_insert(cstate->rel, tuple, use_wal);
diff -dcrpN pgsql.orig/src/backend/commands/sequence.c pgsql/src/backend/commands/sequence.c
*** pgsql.orig/src/backend/commands/sequence.c 2007-02-09 07:23:21.000000000 +0100
--- pgsql/src/backend/commands/sequence.c 2007-02-26 00:07:11.000000000 +0100
*************** DefineSequence(CreateSeqStmt *seq)
*** 129,134 ****
--- 129,136 ----
coldef->raw_default = NULL;
coldef->cooked_default = NULL;
coldef->constraints = NIL;
+ coldef->is_identity = false;
+ coldef->force_default = false;
null[i - 1] = ' ';
*************** process_owned_by(Relation seqrel, List *
*** 1234,1247 ****
{
ObjectAddress refobject,
depobject;
refobject.classId = RelationRelationId;
! refobject.objectId = RelationGetRelid(tablerel);
refobject.objectSubId = attnum;
depobject.classId = RelationRelationId;
! depobject.objectId = RelationGetRelid(seqrel);
depobject.objectSubId = 0;
recordDependencyOn(&depobject, &refobject, DEPENDENCY_AUTO);
}
/* Done, but hold lock until commit */
--- 1236,1253 ----
{
ObjectAddress refobject,
depobject;
+ Oid tableId, seqId;
+ tableId = RelationGetRelid(tablerel);
+ seqId = RelationGetRelid(seqrel);
refobject.classId = RelationRelationId;
! refobject.objectId = tableId;
refobject.objectSubId = attnum;
depobject.classId = RelationRelationId;
! depobject.objectId = seqId;
depobject.objectSubId = 0;
recordDependencyOn(&depobject, &refobject, DEPENDENCY_AUTO);
+ ExecGrant_Sequence(tableId, attnum, seqId);
}
/* Done, but hold lock until commit */
diff -dcrpN pgsql.orig/src/backend/commands/tablecmds.c pgsql/src/backend/commands/tablecmds.c
*** pgsql.orig/src/backend/commands/tablecmds.c 2007-02-20 14:59:37.000000000 +0100
--- pgsql/src/backend/commands/tablecmds.c 2007-02-26 12:02:25.000000000 +0100
***************
*** 34,39 ****
--- 34,40 ----
#include "catalog/toasting.h"
#include "commands/cluster.h"
#include "commands/defrem.h"
+ #include "commands/sequence.h"
#include "commands/tablecmds.h"
#include "commands/tablespace.h"
#include "commands/trigger.h"
*************** static void StoreCatalogInheritance1(Oid
*** 173,178 ****
--- 174,180 ----
int16 seqNumber, Relation inhRelation);
static int findAttrByName(const char *attributeName, List *schema);
static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
+ static void renameseqfor(Oid tableOid, const char *newrelname, const char *oldattname, const char *newattname);
static void AlterIndexNamespaces(Relation classRel, Relation rel,
Oid oldNspOid, Oid newNspOid);
static void AlterSeqNamespaces(Relation classRel, Relation rel,
*************** static void ATExecEnableDisableTrigger(R
*** 256,261 ****
--- 258,265 ----
bool enable, bool skip_system);
static void ATExecAddInherit(Relation rel, RangeVar *parent);
static void ATExecDropInherit(Relation rel, RangeVar *parent);
+ static void ATExecAlterSeq(Relation rel, char *column, List *seq_opts);
+ static void ATExecIdentity(Relation rel, char *column, bool is_identity, bool force_default);
static void copy_relation_data(Relation rel, SMgrRelation dst);
*************** DefineRelation(CreateStmt *stmt, char re
*** 284,289 ****
--- 288,294 ----
Datum reloptions;
ListCell *listptr;
AttrNumber attnum;
+ int identity_count;
/*
* Truncate relname to appropriate length (probably a waste of time, as
*************** DefineRelation(CreateStmt *stmt, char re
*** 367,372 ****
--- 372,392 ----
stmt->relation->istemp,
&inheritOids, &old_constraints, &parentOidCount);
+ identity_count = 0;
+ foreach(listptr, schema)
+ {
+ ColumnDef *colDef = lfirst(listptr);
+
+ if (colDef->is_identity)
+ {
+ identity_count++;
+ if (identity_count > 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("multiple IDENTITY columns are not allowed")));
+ }
+ }
+
/*
* Create a relation descriptor from the relation schema and create the
* relation. Note that in this stage only inherited (pre-cooked) defaults
*************** DefineRelation(CreateStmt *stmt, char re
*** 481,486 ****
--- 501,508 ----
rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
rawEnt->attnum = attnum;
rawEnt->raw_default = colDef->raw_default;
+ rawEnt->is_identity = colDef->is_identity;
+ rawEnt->force_default = colDef->force_default;
rawDefaults = lappend(rawDefaults, rawEnt);
}
}
*************** MergeAttributes(List *schema, List *supe
*** 932,937 ****
--- 954,961 ----
def->raw_default = NULL;
def->cooked_default = NULL;
def->constraints = NIL;
+ def->is_identity = false;
+ def->force_default = false;
inhSchema = lappend(inhSchema, def);
newattno[parent_attno - 1] = ++child_attno;
}
*************** MergeAttributes(List *schema, List *supe
*** 976,981 ****
--- 1000,1007 ----
def->cooked_default = bogus_marker;
have_bogus_defaults = true;
}
+ def->is_identity = attribute->attidentity;
+ def->force_default = attribute->attforceddef;
}
}
*************** MergeAttributes(List *schema, List *supe
*** 1066,1071 ****
--- 1092,1099 ----
{
def->raw_default = newdef->raw_default;
def->cooked_default = newdef->cooked_default;
+ def->is_identity = newdef->is_identity;
+ def->force_default = newdef->force_default;
}
}
else
*************** setRelhassubclassInRelation(Oid relation
*** 1410,1415 ****
--- 1438,1470 ----
}
+ static void renameseqfor(Oid tableOid, const char *newrelname, const char *oldattname, const char *newattname)
+ {
+ int attnum;
+ Oid sequenceId;
+
+ if (!newrelname)
+ newrelname = get_rel_name(tableOid);
+ attnum = get_attnum(tableOid, oldattname);
+ if (attnum == InvalidAttrNumber)
+ return;
+
+ sequenceId = get_relid_att_serial_sequence(tableOid, attnum);
+
+ if (OidIsValid(sequenceId))
+ {
+ char *sname;
+
+ sname = ChooseRelationName(newrelname,
+ newattname,
+ "seq",
+ get_rel_namespace(sequenceId));
+ renamerel(sequenceId, sname);
+ elog(NOTICE, "supporting sequence for column \"%s\" renamed to \"%s\"", newattname, sname);
+ pfree(sname);
+ }
+ }
+
/*
* renameatt - changes the name of a attribute in a relation
*
*************** renameatt(Oid myrelid,
*** 1612,1617 ****
--- 1667,1678 ----
heap_close(attrelation, RowExclusiveLock);
relation_close(targetrelation, NoLock); /* close rel but keep lock */
+
+ /*
+ * Also rename the underlying sequence
+ * if this column is SERIAL or GENERATED AS IDENTITY.
+ */
+ renameseqfor(myrelid, NULL, oldattname, newattname);
}
/*
*************** renamerel(Oid myrelid, const char *newre
*** 1633,1638 ****
--- 1694,1700 ----
char *oldrelname;
char relkind;
bool relhastriggers;
+ int idx;
/*
* Grab an exclusive lock on the target table or index, which we will NOT
*************** renamerel(Oid myrelid, const char *newre
*** 1680,1685 ****
--- 1742,1756 ----
/* keep the system catalog indexes current */
CatalogUpdateIndexes(relrelation, reltup);
+ for (idx = 0; idx < targetrelation->rd_att->natts; idx++)
+ {
+ char *attname;
+ if (targetrelation->rd_att->attrs[idx]->attisdropped)
+ continue;
+ attname = NameStr(targetrelation->rd_att->attrs[idx]->attname);
+ renameseqfor(myrelid, newrelname, attname, attname);
+ }
+
heap_freetuple(reltup);
heap_close(relrelation, RowExclusiveLock);
*************** ATPrepCmd(List **wqueue, Relation rel, A
*** 1966,1971 ****
--- 2037,2045 ----
case AT_DisableTrigUser:
case AT_AddInherit: /* INHERIT / NO INHERIT */
case AT_DropInherit:
+ case AT_SetSeqOpts:
+ case AT_SetIdentity:
+ case AT_DropIdentity:
ATSimplePermissions(rel, false);
/* These commands never recurse */
/* No command-specific prep needed */
*************** ATExecCmd(AlteredTableInfo *tab, Relatio
*** 2155,2160 ****
--- 2229,2243 ----
case AT_DropInherit:
ATExecDropInherit(rel, (RangeVar *) cmd->def);
break;
+ case AT_SetSeqOpts:
+ ATExecAlterSeq(rel, cmd->name, (List *)cmd->def);
+ break;
+ case AT_SetIdentity:
+ ATExecIdentity(rel, cmd->name, true, cmd->force_default);
+ break;
+ case AT_DropIdentity:
+ ATExecIdentity(rel, cmd->name, false, false);
+ break;
default: /* oops */
elog(ERROR, "unrecognized alter table type: %d",
(int) cmd->subtype);
*************** ATExecAddColumn(AlteredTableInfo *tab, R
*** 2914,2919 ****
--- 2997,3012 ----
Form_pg_type tform;
Expr *defval;
+ if (colDef->is_identity)
+ {
+ for (i = 0; i < rel->rd_att->natts; i++)
+ if (rel->rd_att->attrs[i]->attidentity)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("multiple IDENTITY columns are not allowed")));
+
+ }
+
attrdesc = heap_open(AttributeRelationId, RowExclusiveLock);
/*
*************** ATExecAddColumn(AlteredTableInfo *tab, R
*** 3021,3026 ****
--- 3114,3121 ----
attribute->attisdropped = false;
attribute->attislocal = colDef->is_local;
attribute->attinhcount = colDef->inhcount;
+ attribute->attidentity = colDef->is_identity;
+ attribute->attforceddef = colDef->force_default;
ReleaseSysCache(typeTuple);
*************** ATExecAddColumn(AlteredTableInfo *tab, R
*** 3058,3063 ****
--- 3153,3160 ----
rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
rawEnt->attnum = attribute->attnum;
rawEnt->raw_default = copyObject(colDef->raw_default);
+ rawEnt->is_identity = colDef->is_identity;
+ rawEnt->force_default = colDef->force_default;
/*
* This function is intended for CREATE TABLE, so it processes a
*************** ATExecColumnDefault(Relation rel, const
*** 3315,3320 ****
--- 3412,3429 ----
errmsg("cannot alter system column \"%s\"",
colName)));
+ if (rel->rd_att->attrs[attnum - 1]->attidentity)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot alter IDENTITY column \"%s\"",
+ colName)));
+
+ if (rel->rd_att->attrs[attnum - 1]->attforceddef)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot alter GENERATED ALWAYS column \"%s\"",
+ colName)));
+
/*
* Remove any old default for the column. We use RESTRICT here for
* safety, but at present we do not expect anything to depend on the
*************** ATExecColumnDefault(Relation rel, const
*** 3330,3335 ****
--- 3439,3446 ----
rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
rawEnt->attnum = attnum;
rawEnt->raw_default = newDefault;
+ rawEnt->is_identity = false;
+ rawEnt->force_default = false;
/*
* This function is intended for CREATE TABLE, so it processes a
*************** ATExecAlterColumnType(AlteredTableInfo *
*** 4793,4798 ****
--- 4904,4911 ----
ScanKeyData key[3];
SysScanDesc scan;
HeapTuple depTup;
+ bool attidentity;
+ bool attforceddef;
attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
*************** ATExecAlterColumnType(AlteredTableInfo *
*** 4850,4855 ****
--- 4963,4970 ----
}
else
defaultexpr = NULL;
+ attidentity = attTup->attidentity;
+ attforceddef = attTup->attforceddef;
/*
* Find everything that depends on the column (constraints, indexes, etc),
*************** ATExecAlterColumnType(AlteredTableInfo *
*** 5098,5104 ****
*/
RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true);
! StoreAttrDefault(rel, attnum, nodeToString(defaultexpr));
}
/* Cleanup */
--- 5213,5219 ----
*/
RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true);
! StoreAttrDefault(rel, attnum, nodeToString(defaultexpr), attidentity, attforceddef);
}
/* Cleanup */
*************** decompile_conbin(HeapTuple contup, Tuple
*** 6024,6029 ****
--- 6139,6272 ----
}
/*
+ * ALTER TABLE RESTART WITH / SET sequence_options
+ */
+ static void
+ ATExecAlterSeq(Relation rel, char *column, List *seq_opts)
+ {
+ Oid tableOid;
+ AttrNumber attnum;
+ Oid sequenceId;
+
+ tableOid = RelationGetRelid(rel);
+ attnum = get_attnum(tableOid, column);
+
+ if (attnum == InvalidAttrNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ column, RelationGetRelationName(rel))));
+
+ sequenceId = get_relid_att_serial_sequence(tableOid, attnum);
+ if (OidIsValid(sequenceId))
+ {
+ HeapTuple seqtup;
+
+ seqtup = SearchSysCache(RELOID,
+ ObjectIdGetDatum(sequenceId),
+ 0, 0, 0);
+ if (HeapTupleIsValid(seqtup))
+ {
+ Form_pg_class seq = (Form_pg_class) GETSTRUCT(seqtup);
+ HeapTuple nsptup;
+ RangeVar *rv = NULL;
+
+ nsptup = SearchSysCache(NAMESPACEOID,
+ ObjectIdGetDatum(seq->relnamespace),
+ 0, 0, 0);
+ if (HeapTupleIsValid(nsptup))
+ {
+ Form_pg_namespace nsp = (Form_pg_namespace) GETSTRUCT(nsptup);
+ rv = makeRangeVar(NameStr(nsp->nspname), NameStr(seq->relname));
+ ReleaseSysCache(nsptup);
+ }
+
+ ReleaseSysCache(seqtup);
+
+ if (rv != NULL)
+ {
+ AlterSeqStmt *newcmd;
+
+ newcmd = makeNode(AlterSeqStmt);
+ newcmd->sequence = rv;
+ newcmd->options = seq_opts;
+ AlterSequence(newcmd);
+ pfree(newcmd);
+ pfree(rv);
+ }
+ }
+ } else
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("column \"%s\" of relation \"%s\" is not an IDENTITY or SERIAL column",
+ column, RelationGetRelationName(rel))));
+ }
+
+ static void
+ ATExecIdentity(Relation rel, char *column, bool is_identity, bool force_default)
+ {
+ Oid tableOid;
+ AttrNumber attnum;
+ Oid sequenceId;
+ TupleDesc tupleDesc;
+ int idx;
+
+ tableOid = RelationGetRelid(rel);
+ attnum = get_attnum(tableOid, column);
+
+ if (attnum == InvalidAttrNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ column, RelationGetRelationName(rel))));
+
+ tupleDesc = RelationGetDescr(rel);
+ if (is_identity)
+ {
+ for (idx = 0; idx < tupleDesc->natts; idx++)
+ {
+ if (tupleDesc->attrs[idx]->attisdropped)
+ continue;
+ if (attnum != (idx + 1) &&
+ tupleDesc->attrs[idx]->attidentity)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("multiple IDENTITY columns are not allowed")));
+ }
+ } else
+ force_default = false;
+
+ sequenceId = get_relid_att_serial_sequence(tableOid, attnum);
+
+ if (OidIsValid(sequenceId) &&
+ ((is_identity &&
+ !tupleDesc->attrs[attnum - 1]->attidentity &&
+ !tupleDesc->attrs[attnum - 1]->attforceddef) ||
+ (!is_identity &&
+ tupleDesc->attrs[attnum - 1]->attidentity)))
+ {
+ Node *old_default = build_column_default(rel, attnum);
+
+ /* Rewrite the DEFAULT parameters */
+
+ RemoveAttrDefault(RelationGetRelid(rel),
+ attnum,
+ DROP_RESTRICT,
+ false);
+
+ StoreAttrDefault(rel,
+ attnum,
+ nodeToString(old_default),
+ is_identity,
+ force_default);
+ } else
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("column \"%s\" of relation \"%s\" is not a plain SERIAL column",
+ column, RelationGetRelationName(rel))));
+ }
+
+ /*
* Check columns in child table match up with columns in parent, and increment
* their attinhcount.
*
diff -dcrpN pgsql.orig/src/backend/commands/typecmds.c pgsql/src/backend/commands/typecmds.c
*** pgsql.orig/src/backend/commands/typecmds.c 2007-02-15 12:36:06.000000000 +0100
--- pgsql/src/backend/commands/typecmds.c 2007-02-26 00:07:11.000000000 +0100
*************** DefineDomain(CreateDomainStmt *stmt)
*** 718,724 ****
defaultExpr = cookDefault(pstate, constr->raw_expr,
basetypeoid,
basetypeMod,
! domainName);
/*
* Expression must be stored as a nodeToString result, but we
--- 718,725 ----
defaultExpr = cookDefault(pstate, constr->raw_expr,
basetypeoid,
basetypeMod,
! domainName,
! false);
/*
* Expression must be stored as a nodeToString result, but we
*************** AlterDomainDefault(List *names, Node *de
*** 1285,1291 ****
defaultExpr = cookDefault(pstate, defaultRaw,
typTup->typbasetype,
typTup->typtypmod,
! NameStr(typTup->typname));
/*
* Expression must be stored as a nodeToString result, but we also
--- 1286,1293 ----
defaultExpr = cookDefault(pstate, defaultRaw,
typTup->typbasetype,
typTup->typtypmod,
! NameStr(typTup->typname),
! false);
/*
* Expression must be stored as a nodeToString result, but we also
diff -dcrpN pgsql.orig/src/backend/commands/view.c pgsql/src/backend/commands/view.c
*** pgsql.orig/src/backend/commands/view.c 2007-01-10 19:58:23.000000000 +0100
--- pgsql/src/backend/commands/view.c 2007-02-26 00:07:11.000000000 +0100
*************** DefineVirtualRelation(const RangeVar *re
*** 126,131 ****
--- 126,133 ----
def->raw_default = NULL;
def->cooked_default = NULL;
def->constraints = NIL;
+ def->is_identity = false;
+ def->force_default = false;
attrList = lappend(attrList, def);
}
diff -dcrpN pgsql.orig/src/backend/executor/execMain.c pgsql/src/backend/executor/execMain.c
*** pgsql.orig/src/backend/executor/execMain.c 2007-02-25 16:14:15.000000000 +0100
--- pgsql/src/backend/executor/execMain.c 2007-02-27 22:57:50.000000000 +0100
***************
*** 45,55 ****
--- 45,58 ----
#include "executor/instrument.h"
#include "executor/nodeSubplan.h"
#include "miscadmin.h"
+ #include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "parser/parse_clause.h"
#include "parser/parsetree.h"
+ #include "rewrite/rewriteHandler.h"
#include "storage/smgr.h"
#include "utils/acl.h"
+ #include "./utils/datum.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
*************** static TupleTableSlot *ExecutePlan(EStat
*** 74,91 ****
CmdType operation,
long numberTuples,
ScanDirection direction,
! DestReceiver *dest);
static void ExecSelect(TupleTableSlot *slot,
DestReceiver *dest, EState *estate);
static void ExecInsert(TupleTableSlot *slot, ItemPointer tupleid,
TupleTableSlot *planSlot,
! DestReceiver *dest, EState *estate);
static void ExecDelete(ItemPointer tupleid,
TupleTableSlot *planSlot,
DestReceiver *dest, EState *estate);
static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
TupleTableSlot *planSlot,
! DestReceiver *dest, EState *estate);
static void ExecProcessReturning(ProjectionInfo *projectReturning,
TupleTableSlot *tupleSlot,
TupleTableSlot *planSlot,
--- 77,101 ----
CmdType operation,
long numberTuples,
ScanDirection direction,
! DestReceiver *dest,
! bool idSetToDefault);
static void ExecSelect(TupleTableSlot *slot,
DestReceiver *dest, EState *estate);
static void ExecInsert(TupleTableSlot *slot, ItemPointer tupleid,
TupleTableSlot *planSlot,
! DestReceiver *dest, EState *estate,
! bool idSetToDefault);
static void ExecDelete(ItemPointer tupleid,
TupleTableSlot *planSlot,
DestReceiver *dest, EState *estate);
static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
TupleTableSlot *planSlot,
! DestReceiver *dest, EState *estate,
! bool idSetToDefault);
! static HeapTuple ExecGenerated(TupleTableSlot *slot,
! HeapTuple tuple,
! EState *estate,
! bool idSetToDefault);
static void ExecProcessReturning(ProjectionInfo *projectReturning,
TupleTableSlot *tupleSlot,
TupleTableSlot *planSlot,
*************** ExecutorRun(QueryDesc *queryDesc,
*** 244,250 ****
operation,
count,
direction,
! dest);
/*
* shutdown tuple receiver, if we started it
--- 254,261 ----
operation,
count,
direction,
! dest,
! queryDesc->idSetToDefault);
/*
* shutdown tuple receiver, if we started it
*************** ExecutePlan(EState *estate,
*** 1013,1019 ****
CmdType operation,
long numberTuples,
ScanDirection direction,
! DestReceiver *dest)
{
JunkFilter *junkfilter;
TupleTableSlot *planSlot;
--- 1024,1031 ----
CmdType operation,
long numberTuples,
ScanDirection direction,
! DestReceiver *dest,
! bool idSetToDefault)
{
JunkFilter *junkfilter;
TupleTableSlot *planSlot;
*************** lnext: ;
*** 1222,1228 ****
break;
case CMD_INSERT:
! ExecInsert(slot, tupleid, planSlot, dest, estate);
result = NULL;
break;
--- 1234,1240 ----
break;
case CMD_INSERT:
! ExecInsert(slot, tupleid, planSlot, dest, estate, idSetToDefault);
result = NULL;
break;
*************** lnext: ;
*** 1232,1238 ****
break;
case CMD_UPDATE:
! ExecUpdate(slot, tupleid, planSlot, dest, estate);
result = NULL;
break;
--- 1244,1250 ----
break;
case CMD_UPDATE:
! ExecUpdate(slot, tupleid, planSlot, dest, estate, idSetToDefault);
result = NULL;
break;
*************** ExecInsert(TupleTableSlot *slot,
*** 1309,1315 ****
ItemPointer tupleid,
TupleTableSlot *planSlot,
DestReceiver *dest,
! EState *estate)
{
HeapTuple tuple;
ResultRelInfo *resultRelInfo;
--- 1321,1328 ----
ItemPointer tupleid,
TupleTableSlot *planSlot,
DestReceiver *dest,
! EState *estate,
! bool idSetToDefault)
{
HeapTuple tuple;
ResultRelInfo *resultRelInfo;
*************** ExecInsert(TupleTableSlot *slot,
*** 1358,1367 ****
}
/*
! * Check the constraints of the tuple
*/
if (resultRelationDesc->rd_att->constr)
! ExecConstraints(resultRelInfo, slot, estate);
/*
* insert the tuple
--- 1371,1382 ----
}
/*
! * Check the constraints of the tuple, skipping IDENTITY/GENERATED columns
*/
if (resultRelationDesc->rd_att->constr)
! ExecConstraints(resultRelInfo, slot, estate, false, false);
!
! tuple = ExecGenerated(slot, tuple, estate, idSetToDefault);
/*
* insert the tuple
*************** ExecUpdate(TupleTableSlot *slot,
*** 1541,1547 ****
ItemPointer tupleid,
TupleTableSlot *planSlot,
DestReceiver *dest,
! EState *estate)
{
HeapTuple tuple;
ResultRelInfo *resultRelInfo;
--- 1556,1563 ----
ItemPointer tupleid,
TupleTableSlot *planSlot,
DestReceiver *dest,
! EState *estate,
! bool idSetToDefault)
{
HeapTuple tuple;
ResultRelInfo *resultRelInfo;
*************** ExecUpdate(TupleTableSlot *slot,
*** 1610,1616 ****
*/
lreplace:;
if (resultRelationDesc->rd_att->constr)
! ExecConstraints(resultRelInfo, slot, estate);
/*
* replace the heap tuple
--- 1626,1634 ----
*/
lreplace:;
if (resultRelationDesc->rd_att->constr)
! ExecConstraints(resultRelInfo, slot, estate, false, false);
!
! tuple = ExecGenerated(slot, tuple, estate, idSetToDefault);
/*
* replace the heap tuple
*************** ExecRelCheck(ResultRelInfo *resultRelInf
*** 1757,1763 ****
void
ExecConstraints(ResultRelInfo *resultRelInfo,
! TupleTableSlot *slot, EState *estate)
{
Relation rel = resultRelInfo->ri_RelationDesc;
TupleConstr *constr = rel->rd_att->constr;
--- 1775,1782 ----
void
ExecConstraints(ResultRelInfo *resultRelInfo,
! TupleTableSlot *slot, EState *estate,
! bool process_identity, bool process_generated)
{
Relation rel = resultRelInfo->ri_RelationDesc;
TupleConstr *constr = rel->rd_att->constr;
*************** ExecConstraints(ResultRelInfo *resultRel
*** 1772,1777 ****
--- 1791,1804 ----
for (attrChk = 1; attrChk <= natts; attrChk++)
{
if (rel->rd_att->attrs[attrChk - 1]->attnotnull &&
+ ((!process_identity && !process_generated &&
+ !rel->rd_att->attrs[attrChk - 1]->attidentity &&
+ !rel->rd_att->attrs[attrChk - 1]->attforceddef) ||
+ ( process_identity &&
+ rel->rd_att->attrs[attrChk - 1]->attidentity) ||
+ ( process_generated &&
+ rel->rd_att->attrs[attrChk - 1]->attforceddef &&
+ !rel->rd_att->attrs[attrChk - 1]->attidentity)) &&
slot_attisnull(slot, attrChk))
ereport(ERROR,
(errcode(ERRCODE_NOT_NULL_VIOLATION),
*************** ExecConstraints(ResultRelInfo *resultRel
*** 1780,1786 ****
}
}
! if (constr->num_check > 0)
{
const char *failed;
--- 1807,1814 ----
}
}
! if (constr->num_check > 0 &&
! !process_identity && !process_generated)
{
const char *failed;
*************** ExecConstraints(ResultRelInfo *resultRel
*** 1793,1798 ****
--- 1821,1969 ----
}
/*
+ * ExecGenerated --- evaluate IDENTITY/GENERATED columns
+ */
+ static HeapTuple
+ ExecGenerated(TupleTableSlot *slot,
+ HeapTuple tuple,
+ EState *estate,
+ bool idSetToDefault)
+ {
+ ResultRelInfo *resultRelInfo;
+ Relation resultRelationDesc;
+ TupleDesc tupleDesc;
+ int attnum;
+ bool saw_generated;
+ int identity_attnum;
+
+ resultRelInfo = estate->es_result_relation_info;
+ resultRelationDesc = resultRelInfo->ri_RelationDesc;
+
+ saw_generated = false;
+ identity_attnum = 0;
+ tupleDesc = resultRelationDesc->rd_att;
+ for (attnum = 1; attnum <= tupleDesc->natts; attnum++)
+ {
+ if (tupleDesc->attrs[attnum - 1]->attisdropped)
+ continue;
+ if (tupleDesc->attrs[attnum - 1]->attidentity)
+ identity_attnum = attnum;
+ else if (tupleDesc->attrs[attnum - 1]->attforceddef)
+ saw_generated = true;
+ }
+
+ if (saw_generated || identity_attnum > 0)
+ {
+ ExprContext *econtext;
+ ExprState *exprstate;
+ Datum values[tupleDesc->natts];
+ bool isnull[tupleDesc->natts];
+ bool replace[tupleDesc->natts];
+
+ econtext = GetPerTupleExprContext(estate);
+ econtext->ecxt_scantuple = slot;
+
+ if (saw_generated)
+ {
+ heap_deform_tuple(tuple, tupleDesc, values, isnull);
+ memset(replace, 0, sizeof(replace));
+
+ for (attnum = 1; attnum <= tupleDesc->natts; attnum++)
+ {
+ Form_pg_attribute att_tup = tupleDesc->attrs[attnum - 1];
+
+ if (att_tup->attisdropped || att_tup->attidentity)
+ continue;
+ if (att_tup->attforceddef)
+ {
+ Expr *expr;
+ Datum const_val;
+ bool const_is_null;
+ int16 resultTypLen;
+ bool resultTypByVal;
+
+ expr = (Expr *)
+ build_column_default(resultRelationDesc,
+ attnum);
+ exprstate = ExecPrepareExpr(expr, estate);
+ const_val = ExecEvalExprSwitchContext(exprstate,
+ econtext,
+ &const_is_null,
+ NULL);
+ get_typlenbyval(att_tup->atttypid,
+ &resultTypLen,
+ &resultTypByVal);
+ if (!const_is_null)
+ const_val = datumCopy(const_val,
+ resultTypByVal,
+ resultTypLen);
+ values[attnum - 1] = const_val;
+ isnull[attnum - 1] = const_is_null;
+ replace[attnum - 1] = true;
+ }
+ }
+
+ tuple = heap_modify_tuple(tuple, tupleDesc,
+ values,
+ isnull,
+ replace);
+
+ slot = ExecStoreTuple(tuple, slot, InvalidBuffer, false);
+
+ if (resultRelationDesc->rd_att->constr)
+ ExecConstraints(resultRelInfo, slot, estate, false, true);
+ }
+
+ if (identity_attnum > 0)
+ {
+ Form_pg_attribute att_tup = tupleDesc->attrs[identity_attnum - 1];
+
+ if (idSetToDefault)
+ {
+ Expr *expr;
+ Datum const_val;
+ bool const_is_null;
+ int16 resultTypLen;
+ bool resultTypByVal;
+
+ heap_deform_tuple(tuple, tupleDesc, values, isnull);
+ memset(replace, 0, sizeof(replace));
+
+ expr = (Expr *)
+ build_column_default(resultRelationDesc,
+ identity_attnum);
+ exprstate = ExecPrepareExpr(expr, estate);
+ const_val = ExecEvalExprSwitchContext(exprstate,
+ econtext,
+ &const_is_null,
+ NULL);
+ get_typlenbyval(att_tup->atttypid,
+ &resultTypLen,
+ &resultTypByVal);
+ if (!const_is_null)
+ const_val = datumCopy(const_val,
+ resultTypByVal,
+ resultTypLen);
+ values[identity_attnum - 1] = const_val;
+ isnull[identity_attnum - 1] = const_is_null;
+ replace[identity_attnum - 1] = true;
+
+ tuple = heap_modify_tuple(tuple, tupleDesc,
+ values,
+ isnull,
+ replace);
+
+ slot = ExecStoreTuple(tuple, slot, InvalidBuffer, false);
+ }
+
+ if (resultRelationDesc->rd_att->constr)
+ ExecConstraints(resultRelInfo, slot, estate, true, false);
+ }
+ }
+ return tuple;
+ }
+
+ /*
* ExecProcessReturning --- evaluate a RETURNING list and send to dest
*
* projectReturning: RETURNING projection info for current result rel
*************** intorel_destroy(DestReceiver *self)
*** 2566,2568 ****
--- 2737,2740 ----
{
pfree(self);
}
+
diff -dcrpN pgsql.orig/src/backend/nodes/copyfuncs.c pgsql/src/backend/nodes/copyfuncs.c
*** pgsql.orig/src/backend/nodes/copyfuncs.c 2007-02-25 16:14:18.000000000 +0100
--- pgsql/src/backend/nodes/copyfuncs.c 2007-02-27 22:54:01.000000000 +0100
*************** _copyPlannedStmt(PlannedStmt *from)
*** 82,87 ****
--- 82,88 ----
COPY_NODE_FIELD(returningLists);
COPY_NODE_FIELD(rowMarks);
COPY_SCALAR_FIELD(nParamExec);
+ COPY_SCALAR_FIELD(idSetToDefault);
return newnode;
}
*************** _copyColumnDef(ColumnDef *from)
*** 1734,1739 ****
--- 1735,1742 ----
COPY_NODE_FIELD(raw_default);
COPY_STRING_FIELD(cooked_default);
COPY_NODE_FIELD(constraints);
+ COPY_SCALAR_FIELD(is_identity);
+ COPY_SCALAR_FIELD(force_default);
return newnode;
}
*************** _copyConstraint(Constraint *from)
*** 1750,1755 ****
--- 1753,1760 ----
COPY_NODE_FIELD(keys);
COPY_NODE_FIELD(options);
COPY_STRING_FIELD(indexspace);
+ COPY_SCALAR_FIELD(force_default);
+ COPY_NODE_FIELD(seq_opts);
return newnode;
}
*************** _copyQuery(Query *from)
*** 1814,1819 ****
--- 1819,1826 ----
COPY_NODE_FIELD(limitCount);
COPY_NODE_FIELD(rowMarks);
COPY_NODE_FIELD(setOperations);
+ COPY_SCALAR_FIELD(commandOverride);
+ COPY_SCALAR_FIELD(idSetToDefault);
return newnode;
}
*************** _copyInsertStmt(InsertStmt *from)
*** 1827,1832 ****
--- 1834,1840 ----
COPY_NODE_FIELD(cols);
COPY_NODE_FIELD(selectStmt);
COPY_NODE_FIELD(returningList);
+ COPY_SCALAR_FIELD(commandOverride);
return newnode;
}
*************** _copyAlterTableCmd(AlterTableCmd *from)
*** 1920,1925 ****
--- 1928,1934 ----
COPY_NODE_FIELD(def);
COPY_NODE_FIELD(transform);
COPY_SCALAR_FIELD(behavior);
+ COPY_SCALAR_FIELD(force_default);
return newnode;
}
diff -dcrpN pgsql.orig/src/backend/nodes/equalfuncs.c pgsql/src/backend/nodes/equalfuncs.c
*** pgsql.orig/src/backend/nodes/equalfuncs.c 2007-02-25 16:14:18.000000000 +0100
--- pgsql/src/backend/nodes/equalfuncs.c 2007-02-27 22:54:40.000000000 +0100
*************** _equalQuery(Query *a, Query *b)
*** 715,720 ****
--- 715,722 ----
COMPARE_NODE_FIELD(limitCount);
COMPARE_NODE_FIELD(rowMarks);
COMPARE_NODE_FIELD(setOperations);
+ COMPARE_SCALAR_FIELD(commandOverride);
+ COMPARE_SCALAR_FIELD(idSetToDefault);
return true;
}
*************** _equalInsertStmt(InsertStmt *a, InsertSt
*** 726,731 ****
--- 728,734 ----
COMPARE_NODE_FIELD(cols);
COMPARE_NODE_FIELD(selectStmt);
COMPARE_NODE_FIELD(returningList);
+ COMPARE_SCALAR_FIELD(commandOverride);
return true;
}
*************** _equalAlterTableCmd(AlterTableCmd *a, Al
*** 807,812 ****
--- 810,816 ----
COMPARE_NODE_FIELD(def);
COMPARE_NODE_FIELD(transform);
COMPARE_SCALAR_FIELD(behavior);
+ COMPARE_SCALAR_FIELD(force_default);
return true;
}
*************** _equalColumnDef(ColumnDef *a, ColumnDef
*** 1736,1741 ****
--- 1740,1747 ----
COMPARE_NODE_FIELD(raw_default);
COMPARE_STRING_FIELD(cooked_default);
COMPARE_NODE_FIELD(constraints);
+ COMPARE_SCALAR_FIELD(is_identity);
+ COMPARE_SCALAR_FIELD(force_default);
return true;
}
*************** _equalConstraint(Constraint *a, Constrai
*** 1750,1755 ****
--- 1756,1763 ----
COMPARE_NODE_FIELD(keys);
COMPARE_NODE_FIELD(options);
COMPARE_STRING_FIELD(indexspace);
+ COMPARE_SCALAR_FIELD(force_default);
+ COMPARE_NODE_FIELD(seq_opts);
return true;
}
diff -dcrpN pgsql.orig/src/backend/nodes/outfuncs.c pgsql/src/backend/nodes/outfuncs.c
*** pgsql.orig/src/backend/nodes/outfuncs.c 2007-02-25 16:14:18.000000000 +0100
--- pgsql/src/backend/nodes/outfuncs.c 2007-02-27 22:55:35.000000000 +0100
*************** _outPlannedStmt(StringInfo str, PlannedS
*** 249,254 ****
--- 249,255 ----
WRITE_NODE_FIELD(returningLists);
WRITE_NODE_FIELD(rowMarks);
WRITE_INT_FIELD(nParamExec);
+ WRITE_BOOL_FIELD(idSetToDefault);
}
/*
*************** _outColumnDef(StringInfo str, ColumnDef
*** 1605,1610 ****
--- 1606,1613 ----
WRITE_NODE_FIELD(raw_default);
WRITE_STRING_FIELD(cooked_default);
WRITE_NODE_FIELD(constraints);
+ WRITE_BOOL_FIELD(is_identity);
+ WRITE_BOOL_FIELD(force_default);
}
static void
*************** _outQuery(StringInfo str, Query *node)
*** 1694,1699 ****
--- 1697,1704 ----
WRITE_NODE_FIELD(limitCount);
WRITE_NODE_FIELD(rowMarks);
WRITE_NODE_FIELD(setOperations);
+ WRITE_BOOL_FIELD(commandOverride);
+ WRITE_BOOL_FIELD(idSetToDefault);
}
static void
*************** _outConstraint(StringInfo str, Constrain
*** 1958,1969 ****
--- 1963,1980 ----
appendStringInfo(str, "DEFAULT");
WRITE_NODE_FIELD(raw_expr);
WRITE_STRING_FIELD(cooked_expr);
+ WRITE_BOOL_FIELD(force_default);
break;
case CONSTR_NOTNULL:
appendStringInfo(str, "NOT_NULL");
break;
+ case CONSTR_IDENTITY:
+ appendStringInfo(str, "IDENTITY");
+ WRITE_NODE_FIELD(seq_opts);
+ break;
+
default:
appendStringInfo(str, "");
break;
diff -dcrpN pgsql.orig/src/backend/nodes/readfuncs.c pgsql/src/backend/nodes/readfuncs.c
*** pgsql.orig/src/backend/nodes/readfuncs.c 2007-02-25 16:14:18.000000000 +0100
--- pgsql/src/backend/nodes/readfuncs.c 2007-02-27 22:55:56.000000000 +0100
*************** _readQuery(void)
*** 154,159 ****
--- 154,161 ----
READ_NODE_FIELD(limitCount);
READ_NODE_FIELD(rowMarks);
READ_NODE_FIELD(setOperations);
+ READ_BOOL_FIELD(commandOverride);
+ READ_BOOL_FIELD(idSetToDefault);
READ_DONE();
}
diff -dcrpN pgsql.orig/src/backend/optimizer/plan/planner.c pgsql/src/backend/optimizer/plan/planner.c
*** pgsql.orig/src/backend/optimizer/plan/planner.c 2007-02-25 16:14:21.000000000 +0100
--- pgsql/src/backend/optimizer/plan/planner.c 2007-02-27 22:52:38.000000000 +0100
*************** planner(Query *parse, bool isCursor, int
*** 161,166 ****
--- 161,167 ----
result->returningLists = root->returningLists;
result->rowMarks = parse->rowMarks;
result->nParamExec = list_length(glob->paramlist);
+ result->idSetToDefault = parse->idSetToDefault;
return result;
}
diff -dcrpN pgsql.orig/src/backend/parser/analyze.c pgsql/src/backend/parser/analyze.c
*** pgsql.orig/src/backend/parser/analyze.c 2007-02-25 16:14:24.000000000 +0100
--- pgsql/src/backend/parser/analyze.c 2007-02-26 00:07:11.000000000 +0100
*************** transformInsertStmt(ParseState *pstate,
*** 548,553 ****
--- 548,554 ----
ListCell *lc;
qry->commandType = CMD_INSERT;
+ qry->commandOverride = stmt->commandOverride;
pstate->p_is_insert = true;
/*
*************** transformColumnDefinition(ParseState *ps
*** 1035,1040 ****
--- 1036,1044 ----
bool saw_nullable;
Constraint *constraint;
ListCell *clist;
+ bool saw_identity;
+ bool force_default;
+ List *seq_opts;
cxt->columns = lappend(cxt->columns, column);
*************** transformColumnDefinition(ParseState *ps
*** 1060,1070 ****
}
}
/* Do necessary work on the column type declaration */
transformColumnType(pstate, column);
! /* Special actions for SERIAL pseudo-types */
! if (is_serial)
{
Oid snamespaceid;
char *snamespace;
--- 1064,1098 ----
}
}
+ /* Check for GENERATED ... AS IDENTITY constructs */
+ saw_identity = false;
+ force_default = false;
+ seq_opts = NULL;
+ foreach(clist, column->constraints)
+ {
+ constraint = lfirst(clist);
+
+ switch (constraint->contype) {
+ case CONSTR_IDENTITY:
+ if (saw_identity)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("multiple GENERATED ... AS IDENTITY constructs specified for column \"%s\" of table \"%s\"",
+ column->colname, cxt->relation->relname)));
+ saw_identity = true;
+ force_default = constraint->force_default;
+ seq_opts = constraint->seq_opts;
+ break;
+ default:
+ continue;
+ }
+ }
+
/* Do necessary work on the column type declaration */
transformColumnType(pstate, column);
! /* Special actions for SERIAL pseudo-types or IDENTITY columns */
! if (is_serial || saw_identity)
{
Oid snamespaceid;
char *snamespace;
*************** transformColumnDefinition(ParseState *ps
*** 1106,1112 ****
*/
seqstmt = makeNode(CreateSeqStmt);
seqstmt->sequence = makeRangeVar(snamespace, sname);
! seqstmt->options = NIL;
cxt->blist = lappend(cxt->blist, seqstmt);
--- 1134,1140 ----
*/
seqstmt = makeNode(CreateSeqStmt);
seqstmt->sequence = makeRangeVar(snamespace, sname);
! seqstmt->options = seq_opts;
cxt->blist = lappend(cxt->blist, seqstmt);
*************** transformColumnDefinition(ParseState *ps
*** 1152,1157 ****
--- 1180,1186 ----
constraint->raw_expr = (Node *) funccallnode;
constraint->cooked_expr = NULL;
constraint->keys = NIL;
+ constraint->force_default = force_default;
column->constraints = lappend(column->constraints, constraint);
constraint = makeNode(Constraint);
*************** transformColumnDefinition(ParseState *ps
*** 1213,1221 ****
--- 1242,1254 ----
errmsg("multiple default values specified for column \"%s\" of table \"%s\"",
column->colname, cxt->relation->relname)));
column->raw_default = constraint->raw_expr;
+ force_default = constraint->force_default;
Assert(constraint->cooked_expr == NULL);
break;
+ case CONSTR_IDENTITY: /* This was processed above, we only have to detect it here. */
+ break;
+
case CONSTR_PRIMARY:
case CONSTR_UNIQUE:
if (constraint->keys == NIL)
*************** transformColumnDefinition(ParseState *ps
*** 1240,1245 ****
--- 1273,1280 ----
break;
}
}
+ column->is_identity = saw_identity;
+ column->force_default = force_default;
}
static void
*************** transformInhRelation(ParseState *pstate,
*** 1383,1388 ****
--- 1418,1425 ----
def->raw_default = NULL;
def->cooked_default = NULL;
def->constraints = NIL;
+ def->is_identity = false;
+ def->force_default = false;
/*
* Add to column list
*************** transformInhRelation(ParseState *pstate,
*** 1417,1422 ****
--- 1454,1461 ----
*/
def->cooked_default = pstrdup(this_default);
+ def->is_identity = attribute->attidentity;
+ def->force_default = attribute->attforceddef;
}
}
diff -dcrpN pgsql.orig/src/backend/parser/gram.y pgsql/src/backend/parser/gram.y
*** pgsql.orig/src/backend/parser/gram.y 2007-02-25 16:14:26.000000000 +0100
--- pgsql/src/backend/parser/gram.y 2007-02-26 00:07:11.000000000 +0100
*************** static Node *makeXmlExpr(XmlExprOp op, c
*** 285,291 ****
%type fetch_direction select_limit_value select_offset_value
! %type OptSeqList
%type OptSeqElem
%type insert_rest
--- 285,291 ----
%type fetch_direction select_limit_value select_offset_value
! %type OptSeqList SeqList
%type OptSeqElem
%type insert_rest
*************** static Node *makeXmlExpr(XmlExprOp op, c
*** 313,318 ****
--- 313,319 ----
%type relation_expr
%type relation_expr_opt_alias
%type target_el single_set_clause set_target insert_column_item
+ %type OptOverride UserSystem
%type Typename SimpleTypename ConstTypename
GenericType Numeric opt_float
*************** static Node *makeXmlExpr(XmlExprOp op, c
*** 340,345 ****
--- 341,348 ----
%type TableLikeOption
%type ColQualList
%type ColConstraint ColConstraintElem ConstraintAttr
+ %type AlwaysByDefault IdentityGenerated IdentitySpec
+ %type SetIdentityAlwaysByDefault
%type key_actions key_delete key_match key_update key_action
%type ConstraintAttributeSpec ConstraintDeferrabilitySpec
ConstraintTimeSpec
*************** static Node *makeXmlExpr(XmlExprOp op, c
*** 365,371 ****
/* ordinary key words in alphabetical order */
%token ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
! AGGREGATE ALL ALSO ALTER ANALYSE ANALYZE AND ANY ARRAY AS ASC
ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION
BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
--- 368,374 ----
/* ordinary key words in alphabetical order */
%token ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
! AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC
ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION
BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
*************** static Node *makeXmlExpr(XmlExprOp op, c
*** 389,399 ****
FALSE_P FAMILY FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD
FREEZE FROM FULL FUNCTION
! GLOBAL GRANT GRANTED GREATEST GROUP_P
HANDLER HAVING HEADER_P HOLD HOUR_P
! IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
INDEX INDEXES INHERIT INHERITS INITIALLY INNER_P INOUT INPUT_P
INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT
INTERVAL INTO INVOKER IS ISNULL ISOLATION
--- 392,402 ----
FALSE_P FAMILY FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD
FREEZE FROM FULL FUNCTION
! GENERATED GLOBAL GRANT GRANTED GREATEST GROUP_P
HANDLER HAVING HEADER_P HOLD HOUR_P
! IDENTITY IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
INDEX INDEXES INHERIT INHERITS INITIALLY INNER_P INOUT INPUT_P
INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT
INTERVAL INTO INVOKER IS ISNULL ISOLATION
*************** static Node *makeXmlExpr(XmlExprOp op, c
*** 413,419 ****
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC
OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR
! ORDER OUT_P OUTER_P OVERLAPS OVERLAY OWNED OWNER
PARTIAL PASSWORD PLACING POSITION
PRECISION PRESERVE PREPARE PREPARED PRIMARY
--- 416,422 ----
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC
OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR
! ORDER OUT_P OUTER_P OVERLAPS OVERLAY OVERRIDING OWNED OWNER
PARTIAL PASSWORD PLACING POSITION
PRECISION PRESERVE PREPARE PREPARED PRIMARY
*************** alter_table_cmd:
*** 1410,1415 ****
--- 1413,1449 ----
n->def = (Node *) makeString($6);
$$ = (Node *)n;
}
+ | ALTER opt_column ColId SET SeqList
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_SetSeqOpts;
+ n->name = $3;
+ n->def = (Node *) $5;
+ $$ = (Node *)n;
+ }
+ | ALTER opt_column ColId RESTART opt_with NumericOnly
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_SetSeqOpts;
+ n->name = $3;
+ n->def = (Node *)list_make1(makeDefElem("restart", (Node *)$6));
+ $$ = (Node *)n;
+ }
+ | ALTER opt_column ColId SET GENERATED SetIdentityAlwaysByDefault AS IDENTITY
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_SetIdentity;
+ n->name = $3;
+ n->force_default = $6;
+ $$ = (Node *)n;
+ }
+ | ALTER opt_column ColId DROP IDENTITY
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ n->subtype = AT_DropIdentity;
+ n->name = $3;
+ $$ = (Node *)n;
+ }
/* ALTER TABLE DROP [COLUMN] [RESTRICT|CASCADE] */
| DROP opt_column ColId opt_drop_behavior
{
*************** alter_using:
*** 1602,1607 ****
--- 1636,1646 ----
| /* EMPTY */ { $$ = NULL; }
;
+ SetIdentityAlwaysByDefault:
+ ALWAYS { $$ = true; }
+ | BY DEFAULT { $$ = false; }
+ ;
+
/*****************************************************************************
*************** ClosePortalStmt:
*** 1635,1649 ****
*
*****************************************************************************/
! CopyStmt: COPY opt_binary qualified_name opt_column_list opt_oids
copy_from copy_file_name copy_delimiter opt_with copy_opt_list
{
CopyStmt *n = makeNode(CopyStmt);
n->relation = $3;
n->query = NULL;
n->attlist = $4;
! n->is_from = $6;
! n->filename = $7;
n->options = NIL;
/* Concatenate user-supplied flags */
--- 1674,1689 ----
*
*****************************************************************************/
! CopyStmt: COPY opt_binary qualified_name opt_column_list opt_oids OptOverride
copy_from copy_file_name copy_delimiter opt_with copy_opt_list
{
CopyStmt *n = makeNode(CopyStmt);
n->relation = $3;
n->query = NULL;
n->attlist = $4;
! n->overriding = $6;
! n->is_from = $7;
! n->filename = $8;
n->options = NIL;
/* Concatenate user-supplied flags */
*************** CopyStmt: COPY opt_binary qualified_name
*** 1651,1660 ****
n->options = lappend(n->options, $2);
if ($5)
n->options = lappend(n->options, $5);
! if ($8)
! n->options = lappend(n->options, $8);
! if ($10)
! n->options = list_concat(n->options, $10);
$$ = (Node *)n;
}
| COPY select_with_parens TO copy_file_name opt_with
--- 1691,1700 ----
n->options = lappend(n->options, $2);
if ($5)
n->options = lappend(n->options, $5);
! if ($9)
! n->options = lappend(n->options, $9);
! if ($11)
! n->options = list_concat(n->options, $11);
$$ = (Node *)n;
}
| COPY select_with_parens TO copy_file_name opt_with
*************** columnDef: ColId Typename ColQualList
*** 1856,1861 ****
--- 1896,1903 ----
n->typename = $2;
n->constraints = $3;
n->is_local = true;
+ n->is_identity = false;
+ n->force_default = false;
$$ = (Node *)n;
}
;
*************** ColConstraint:
*** 1905,1910 ****
--- 1947,1958 ----
* DEFAULT expression must be b_expr not a_expr to prevent shift/reduce
* conflict on NOT (since NOT might start a subsequent NOT NULL constraint,
* or be part of a_expr NOT LIKE or similar constructs).
+ *
+ * In the SQL2003 spec, DEFAULT, GENERATED ... AS IDENTITY and
+ * GENERATED ALWAYS AS () are mutually exclusive, that will
+ * be handled by analyze.c as conflicting DEFAULT constraints.
+ * Also, to avoid
+ * - Zoltan Boszormenyi
*/
ColConstraintElem:
NOT NULL_P
*************** ColConstraintElem:
*** 1997,2002 ****
--- 2045,2109 ----
n->initdeferred = FALSE;
$$ = (Node *)n;
}
+ | GENERATED AlwaysByDefault
+ {
+ $$ = $2;
+ }
+ ;
+
+ AlwaysByDefault:
+ BY DEFAULT AS IDENTITY IdentitySpec { $$ = $5; }
+ | ALWAYS AS IdentityGenerated
+ {
+ Constraint *n = (Constraint *)$3;
+ n->force_default = true;
+ $$ = (Node *)n;
+ }
+ ;
+
+ IdentityGenerated:
+ '(' a_expr ')'
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_DEFAULT;
+ n->name = NULL;
+ n->raw_expr = $2;
+ n->cooked_expr = NULL;
+ n->keys = NULL;
+ n->indexspace = NULL;
+ $$ = (Node *)n;
+ }
+ | IDENTITY IdentitySpec
+ {
+ $$ = $2;
+ }
+ ;
+
+ IdentitySpec:
+ '(' SeqList ')'
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_IDENTITY;
+ n->name = NULL;
+ n->raw_expr = NULL;
+ n->cooked_expr = NULL;
+ n->keys = NULL;
+ n->indexspace = NULL;
+ n->seq_opts = $2;
+ $$ = (Node *)n;
+ }
+ | /* EMPTY */
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_IDENTITY;
+ n->name = NULL;
+ n->raw_expr = NULL;
+ n->cooked_expr = NULL;
+ n->keys = NULL;
+ n->indexspace = NULL;
+ n->seq_opts = NULL;
+ $$ = (Node *)n;
+ }
;
/*
*************** CreateAsElement:
*** 2309,2314 ****
--- 2416,2423 ----
n->raw_default = NULL;
n->cooked_default = NULL;
n->constraints = NIL;
+ n->is_identity = false;
+ n->force_default = false;
$$ = (Node *)n;
}
;
*************** OptSeqList: OptSeqList OptSeqElem {
*** 2347,2352 ****
--- 2456,2466 ----
| /*EMPTY*/ { $$ = NIL; }
;
+ SeqList: SeqList OptSeqElem { $$ = lappend($1, $2); }
+ | OptSeqElem { $$ = list_make1($1); }
+ ;
+
+
OptSeqElem: CACHE NumericOnly
{
$$ = makeDefElem("cache", (Node *)$2);
*************** InsertStmt:
*** 5527,5543 ****
;
insert_rest:
! SelectStmt
{
$$ = makeNode(InsertStmt);
$$->cols = NIL;
! $$->selectStmt = $1;
}
! | '(' insert_column_list ')' SelectStmt
{
$$ = makeNode(InsertStmt);
$$->cols = $2;
! $$->selectStmt = $4;
}
| DEFAULT VALUES
{
--- 5641,5659 ----
;
insert_rest:
! OptOverride SelectStmt
{
$$ = makeNode(InsertStmt);
$$->cols = NIL;
! $$->commandOverride = $1;
! $$->selectStmt = $2;
}
! | '(' insert_column_list ')' OptOverride SelectStmt
{
$$ = makeNode(InsertStmt);
$$->cols = $2;
! $$->commandOverride = $4;
! $$->selectStmt = $5;
}
| DEFAULT VALUES
{
*************** set_target_list:
*** 5710,5715 ****
--- 5826,5847 ----
;
+ OptOverride:
+ OVERRIDING UserSystem VALUE_P
+ {
+ $$ = $2;
+ }
+ | /* EMPTY */
+ {
+ $$ = false;
+ }
+ ;
+
+ UserSystem:
+ SYSTEM_P { $$ = true; }
+ | USER { $$ = false; }
+ ;
+
/*****************************************************************************
*
* QUERY:
*************** unreserved_keyword:
*** 8667,8672 ****
--- 8799,8805 ----
| AGGREGATE
| ALSO
| ALTER
+ | ALWAYS
| ASSERTION
| ASSIGNMENT
| AT
*************** unreserved_keyword:
*** 8731,8736 ****
--- 8864,8870 ----
| FORCE
| FORWARD
| FUNCTION
+ | GENERATED
| GLOBAL
| GRANTED
| HANDLER
*************** unreserved_keyword:
*** 8791,8796 ****
--- 8925,8931 ----
| OIDS
| OPERATOR
| OPTION
+ | OVERRIDING
| OWNED
| OWNER
| PARTIAL
*************** reserved_keyword:
*** 9016,9021 ****
--- 9151,9157 ----
| GRANT
| GROUP_P
| HAVING
+ | IDENTITY
| IN_P
| INITIALLY
| INTERSECT
diff -dcrpN pgsql.orig/src/backend/parser/keywords.c pgsql/src/backend/parser/keywords.c
*** pgsql.orig/src/backend/parser/keywords.c 2007-01-26 18:53:03.000000000 +0100
--- pgsql/src/backend/parser/keywords.c 2007-02-26 00:07:11.000000000 +0100
*************** static const ScanKeyword ScanKeywords[]
*** 42,47 ****
--- 42,48 ----
{"all", ALL},
{"also", ALSO},
{"alter", ALTER},
+ {"always", ALWAYS},
{"analyse", ANALYSE}, /* British spelling */
{"analyze", ANALYZE},
{"and", AND},
*************** static const ScanKeyword ScanKeywords[]
*** 157,162 ****
--- 158,164 ----
{"from", FROM},
{"full", FULL},
{"function", FUNCTION},
+ {"generated", GENERATED},
{"global", GLOBAL},
{"grant", GRANT},
{"granted", GRANTED},
*************** static const ScanKeyword ScanKeywords[]
*** 167,172 ****
--- 169,175 ----
{"header", HEADER_P},
{"hold", HOLD},
{"hour", HOUR_P},
+ {"identity", IDENTITY},
{"if", IF_P},
{"ilike", ILIKE},
{"immediate", IMMEDIATE},
*************** static const ScanKeyword ScanKeywords[]
*** 262,267 ****
--- 265,271 ----
{"outer", OUTER_P},
{"overlaps", OVERLAPS},
{"overlay", OVERLAY},
+ {"overriding", OVERRIDING},
{"owned", OWNED},
{"owner", OWNER},
{"partial", PARTIAL},
diff -dcrpN pgsql.orig/src/backend/rewrite/rewriteHandler.c pgsql/src/backend/rewrite/rewriteHandler.c
*** pgsql.orig/src/backend/rewrite/rewriteHandler.c 2007-02-09 07:23:34.000000000 +0100
--- pgsql/src/backend/rewrite/rewriteHandler.c 2007-02-27 23:26:09.000000000 +0100
***************
*** 13,18 ****
--- 13,19 ----
*/
#include "postgres.h"
+ #include "miscadmin.h"
#include "access/heapam.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
***************
*** 23,28 ****
--- 24,30 ----
#include "parser/parsetree.h"
#include "rewrite/rewriteHandler.h"
#include "rewrite/rewriteManip.h"
+ #include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
*************** rewriteTargetList(Query *parsetree, Rela
*** 534,539 ****
--- 536,542 ----
List **attrno_list)
{
CmdType commandType = parsetree->commandType;
+ bool commandOverride = parsetree->commandOverride;
TargetEntry **new_tles;
List *new_tlist = NIL;
List *junk_tlist = NIL;
*************** rewriteTargetList(Query *parsetree, Rela
*** 543,548 ****
--- 546,553 ----
numattrs;
ListCell *temp;
+ parsetree->idSetToDefault = false;
+
if (attrno_list) /* initialize optional result list */
*attrno_list = NIL;
*************** rewriteTargetList(Query *parsetree, Rela
*** 618,632 ****
continue;
/*
! * Handle the two cases where we need to insert a default expression:
! * it's an INSERT and there's no tlist entry for the column, or the
! * tlist entry is a DEFAULT placeholder node.
*/
! if ((new_tle == NULL && commandType == CMD_INSERT) ||
(new_tle && new_tle->expr && IsA(new_tle->expr, SetToDefault)))
{
Node *new_expr;
new_expr = build_column_default(target_relation, attrno);
/*
--- 623,681 ----
continue;
/*
! * Handle the three cases where we need to insert a default expression:
! * - it's an INSERT and there's no tlist entry for the column, or
! * - it's an INSERT and the column is GENERATED ALWAYS
! * - the tlist entry is a DEFAULT placeholder node
! * Fail for UPDATE to non-default on GENERATED ALWAYS AS () columns.
! * Fail for UPDATE on GENERATED ALWAYS AS IDENTITY columns
! * Fail for INSERT into GENERATED ALWAYS column with OVERRIDING SYSTEM VALUE by a non-owner
*/
! if (commandType == CMD_UPDATE && att_tup->atthasdef && att_tup->attforceddef &&
! new_tle && new_tle->expr)
! {
! if (att_tup->attidentity)
! elog(ERROR, "UPDATE prohibited on GENERATED ALWAYS AS IDENTITY attributes");
! else if (!IsA(new_tle->expr, SetToDefault))
! elog(ERROR, "UPDATE to non-default value prohibited on GENERATED ALWAYS attributes");
! }
! if (commandType == CMD_INSERT && att_tup->atthasdef && att_tup->attforceddef)
! {
! if (commandOverride &&
! !pg_class_ownercheck(RelationGetRelid(target_relation),
! GetUserId()))
! aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
! RelationGetRelationName(target_relation));
! if (att_tup->attidentity)
! {
! parsetree->idSetToDefault = true;
! continue;
! }
! }
! if (((new_tle == NULL || (att_tup->atthasdef && att_tup->attforceddef && !commandOverride)) && commandType == CMD_INSERT) ||
(new_tle && new_tle->expr && IsA(new_tle->expr, SetToDefault)))
{
Node *new_expr;
+ /*
+ * We have to make note of an unassigned IDENTITY column here
+ * so we can distinguish unassigned and assigned state later.
+ */
+ if (att_tup->attidentity)
+ {
+ if ((commandType == CMD_INSERT && new_tle == NULL) ||
+ (new_tle && new_tle->expr && IsA(new_tle->expr, SetToDefault)))
+ {
+ parsetree->idSetToDefault = true;
+ continue;
+ }
+ }
+ /*
+ * Skip all GENERATED columns that were assigned with DEFAULT.
+ */
+ if (att_tup->attforceddef && !att_tup->attidentity)
+ continue;
+
new_expr = build_column_default(target_relation, attrno);
/*
diff -dcrpN pgsql.orig/src/backend/tcop/pquery.c pgsql/src/backend/tcop/pquery.c
*** pgsql.orig/src/backend/tcop/pquery.c 2007-02-25 16:14:28.000000000 +0100
--- pgsql/src/backend/tcop/pquery.c 2007-02-27 22:47:27.000000000 +0100
*************** CreateQueryDesc(PlannedStmt *plannedstmt
*** 79,84 ****
--- 79,85 ----
qd->tupDesc = NULL;
qd->estate = NULL;
qd->planstate = NULL;
+ qd->idSetToDefault = plannedstmt->idSetToDefault;
return qd;
}
diff -dcrpN pgsql.orig/src/backend/utils/adt/acl.c pgsql/src/backend/utils/adt/acl.c
*** pgsql.orig/src/backend/utils/adt/acl.c 2007-01-10 19:58:45.000000000 +0100
--- pgsql/src/backend/utils/adt/acl.c 2007-02-26 00:07:11.000000000 +0100
*************** aclmembers(const Acl *acl, Oid **roleids
*** 1224,1229 ****
--- 1224,1301 ----
}
/*
+ * aclmemberspriv
+ * Find out all the roleids mentioned in an Acl
+ * if they have all or any of the privileges.
+ * Note that we do not distinguish grantors from grantees.
+ *
+ * *roleids is set to point to a palloc'd array containing distinct OIDs
+ * in sorted order. The length of the array is the function result.
+ */
+ int
+ aclmemberspriv(const Acl *acl, Oid **roleids, AclMode privs, bool is_equal)
+ {
+ Oid *list;
+ const AclItem *acldat;
+ int i,
+ j,
+ k;
+
+ if (acl == NULL || ACL_NUM(acl) == 0)
+ {
+ *roleids = NULL;
+ return 0;
+ }
+
+ /* Check only PRIVILEGES, not GRANT options */
+ privs &= 0xFFFF;
+
+ check_acl(acl);
+
+ /* Allocate the worst-case space requirement */
+ list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
+ acldat = ACL_DAT(acl);
+
+ /*
+ * Walk the ACL collecting mentioned RoleIds.
+ */
+ j = 0;
+ for (i = 0; i < ACL_NUM(acl); i++)
+ {
+ const AclItem *ai = &acldat[i];
+
+ if ((is_equal && (ai->ai_privs & 0xFFFF) == privs) ||
+ (!is_equal && (ai->ai_privs & privs)))
+ {
+ if (ai->ai_grantee != ACL_ID_PUBLIC)
+ list[j++] = ai->ai_grantee;
+ /* grantor is currently never PUBLIC, but let's check anyway */
+ if (ai->ai_grantor != ACL_ID_PUBLIC)
+ list[j++] = ai->ai_grantor;
+ }
+ }
+
+ /* Sort the array */
+ qsort(list, j, sizeof(Oid), oidComparator);
+
+ /* Remove duplicates from the array */
+ k = 0;
+ for (i = 1; i < j; i++)
+ {
+ if (list[k] != list[i])
+ list[++k] = list[i];
+ }
+
+ /*
+ * We could repalloc the array down to minimum size, but it's hardly worth
+ * it since it's only transient memory.
+ */
+ *roleids = list;
+
+ return k + 1;
+ }
+
+ /*
* oidComparator
* qsort comparison function for Oids
*/
diff -dcrpN pgsql.orig/src/backend/utils/adt/ruleutils.c pgsql/src/backend/utils/adt/ruleutils.c
*** pgsql.orig/src/backend/utils/adt/ruleutils.c 2007-02-25 16:14:29.000000000 +0100
--- pgsql/src/backend/utils/adt/ruleutils.c 2007-02-26 00:07:11.000000000 +0100
*************** pg_get_serial_sequence(PG_FUNCTION_ARGS)
*** 1258,1268 ****
Oid tableOid;
char *column;
AttrNumber attnum;
! Oid sequenceId = InvalidOid;
! Relation depRel;
! ScanKeyData key[3];
! SysScanDesc scan;
! HeapTuple tup;
/* Get the OID of the table */
tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
--- 1258,1264 ----
Oid tableOid;
char *column;
AttrNumber attnum;
! Oid sequenceId;
/* Get the OID of the table */
tablerv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
*************** pg_get_serial_sequence(PG_FUNCTION_ARGS)
*** 1279,1324 ****
errmsg("column \"%s\" of relation \"%s\" does not exist",
column, tablerv->relname)));
! /* Search the dependency table for the dependent sequence */
! depRel = heap_open(DependRelationId, AccessShareLock);
!
! ScanKeyInit(&key[0],
! Anum_pg_depend_refclassid,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(RelationRelationId));
! ScanKeyInit(&key[1],
! Anum_pg_depend_refobjid,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(tableOid));
! ScanKeyInit(&key[2],
! Anum_pg_depend_refobjsubid,
! BTEqualStrategyNumber, F_INT4EQ,
! Int32GetDatum(attnum));
!
! 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 auto dependency of a sequence on a column must be
! * what we are looking for. (We need the relkind test because indexes
! * can also have auto dependencies on columns.)
! */
! if (deprec->classid == RelationRelationId &&
! deprec->objsubid == 0 &&
! deprec->deptype == DEPENDENCY_AUTO &&
! get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
! {
! sequenceId = deprec->objid;
! break;
! }
! }
!
! systable_endscan(scan);
! heap_close(depRel, AccessShareLock);
if (OidIsValid(sequenceId))
{
--- 1275,1281 ----
errmsg("column \"%s\" of relation \"%s\" does not exist",
column, tablerv->relname)));
! sequenceId = get_relid_att_serial_sequence(tableOid, attnum);
if (OidIsValid(sequenceId))
{
diff -dcrpN pgsql.orig/src/backend/utils/cache/lsyscache.c pgsql/src/backend/utils/cache/lsyscache.c
*** pgsql.orig/src/backend/utils/cache/lsyscache.c 2007-02-15 12:36:11.000000000 +0100
--- pgsql/src/backend/utils/cache/lsyscache.c 2007-02-26 00:07:11.000000000 +0100
***************
*** 15,25 ****
--- 15,30 ----
*/
#include "postgres.h"
+ #include "access/genam.h"
#include "access/hash.h"
+ #include "access/heapam.h"
#include "access/nbtree.h"
#include "bootstrap/bootstrap.h"
+ #include "catalog/dependency.h"
+ #include "catalog/indexing.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h"
+ #include "catalog/pg_depend.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
***************
*** 32,37 ****
--- 37,43 ----
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/datum.h"
+ #include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
*************** get_relid_attribute_name(Oid relid, Attr
*** 786,791 ****
--- 792,855 ----
}
/*
+ * get_relid_attribute_sequence
+ * Expose pg_get_serial_sequence() internally.
+ * Assumes that attnum is valid for the table.
+ */
+ Oid
+ get_relid_att_serial_sequence(Oid relid, AttrNumber attnum)
+ {
+ Oid sequenceId = InvalidOid;
+ Relation depRel;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ /* Search the dependency table for the dependent sequence */
+ depRel = heap_open(DependRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_refclassid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(RelationRelationId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_refobjid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ ScanKeyInit(&key[2],
+ Anum_pg_depend_refobjsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(attnum));
+
+ 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 auto dependency of a sequence on a column must be
+ * what we are looking for. (We need the relkind test because indexes
+ * can also have auto dependencies on columns.)
+ */
+ if (deprec->classid == RelationRelationId &&
+ deprec->objsubid == 0 &&
+ deprec->deptype == DEPENDENCY_AUTO &&
+ get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
+ {
+ sequenceId = deprec->objid;
+ break;
+ }
+ }
+
+ systable_endscan(scan);
+ heap_close(depRel, AccessShareLock);
+
+ return sequenceId;
+ }
+
+ /*
* get_attnum
*
* Given the relation id and the attribute name,
diff -dcrpN pgsql.orig/src/backend/utils/cache/relcache.c pgsql/src/backend/utils/cache/relcache.c
*** pgsql.orig/src/backend/utils/cache/relcache.c 2007-01-26 18:53:09.000000000 +0100
--- pgsql/src/backend/utils/cache/relcache.c 2007-02-26 12:52:22.000000000 +0100
*************** RelationBuildLocalRelation(const char *r
*** 2273,2278 ****
--- 2273,2285 ----
for (i = 0; i < natts; i++)
{
rel->rd_att->attrs[i]->attnotnull = tupDesc->attrs[i]->attnotnull;
+ /*
+ * Initialize these early so AddRelationRawConstraints()
+ * can detect the field properties correctly on just to be
+ * created tables.
+ */
+ rel->rd_att->attrs[i]->attidentity = tupDesc->attrs[i]->attidentity;
+ rel->rd_att->attrs[i]->attforceddef = tupDesc->attrs[i]->attforceddef;
has_not_null |= tupDesc->attrs[i]->attnotnull;
}
diff -dcrpN pgsql.orig/src/bin/pg_dump/pg_dump.c pgsql/src/bin/pg_dump/pg_dump.c
*** pgsql.orig/src/bin/pg_dump/pg_dump.c 2007-02-15 12:36:14.000000000 +0100
--- pgsql/src/bin/pg_dump/pg_dump.c 2007-02-26 00:07:11.000000000 +0100
*************** dumpTableData_insert(Archive *fout, void
*** 1196,1201 ****
--- 1196,1203 ----
appendPQExpBuffer(q, ") ");
archputs(q->data, fout);
}
+ if (tbinfo->hasforceddef)
+ archprintf(fout, "OVERRIDING SYSTEM VALUE ");
archprintf(fout, "VALUES (");
for (field = 0; field < nfields; field++)
{
*************** dumpTableData(Archive *fout, TableDataIn
*** 1297,1304 ****
/* must use 2 steps here 'cause fmtId is nonreentrant */
appendPQExpBuffer(copyBuf, "COPY %s ",
fmtId(tbinfo->dobj.name));
! appendPQExpBuffer(copyBuf, "%s %sFROM stdin;\n",
fmtCopyColumnList(tbinfo),
(tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : "");
copyStmt = copyBuf->data;
}
--- 1299,1307 ----
/* must use 2 steps here 'cause fmtId is nonreentrant */
appendPQExpBuffer(copyBuf, "COPY %s ",
fmtId(tbinfo->dobj.name));
! appendPQExpBuffer(copyBuf, "%s %s%sFROM stdin;\n",
fmtCopyColumnList(tbinfo),
+ tbinfo->hasforceddef ? "OVERRIDING SYSTEM VALUE " : "",
(tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : "");
copyStmt = copyBuf->data;
}
*************** getTableAttrs(TableInfo *tblinfo, int nu
*** 4260,4265 ****
--- 4263,4270 ----
int i_atthasdef;
int i_attisdropped;
int i_attislocal;
+ int i_attidentity;
+ int i_attforceddef;
PGresult *res;
int ntups;
bool hasdefaults;
*************** getTableAttrs(TableInfo *tblinfo, int nu
*** 4297,4308 ****
resetPQExpBuffer(q);
! if (g_fout->remoteVersion >= 70300)
{
/* need left join here to not fail on dropped columns ... */
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, a.attstattarget, a.attstorage, t.typstorage, "
"a.attnotnull, a.atthasdef, a.attisdropped, a.attislocal, "
! "pg_catalog.format_type(t.oid,a.atttypmod) as atttypname "
"from pg_catalog.pg_attribute a left join pg_catalog.pg_type t "
"on a.atttypid = t.oid "
"where a.attrelid = '%u'::pg_catalog.oid "
--- 4302,4328 ----
resetPQExpBuffer(q);
! if (g_fout->remoteVersion >= 80300)
{
/* need left join here to not fail on dropped columns ... */
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, a.attstattarget, a.attstorage, t.typstorage, "
"a.attnotnull, a.atthasdef, a.attisdropped, a.attislocal, "
! "pg_catalog.format_type(t.oid,a.atttypmod) as atttypname, "
! "a.attidentity, a.attforceddef "
! "from pg_catalog.pg_attribute a left join pg_catalog.pg_type t "
! "on a.atttypid = t.oid "
! "where a.attrelid = '%u'::pg_catalog.oid "
! "and a.attnum > 0::pg_catalog.int2 "
! "order by a.attrelid, a.attnum",
! tbinfo->dobj.catId.oid);
! }
! else if (g_fout->remoteVersion >= 70300)
! {
! /* need left join here to not fail on dropped columns ... */
! appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, a.attstattarget, a.attstorage, t.typstorage, "
! "a.attnotnull, a.atthasdef, a.attisdropped, a.attislocal, "
! "pg_catalog.format_type(t.oid,a.atttypmod) as atttypname, "
! "false as attidentity, false as attforceddef "
"from pg_catalog.pg_attribute a left join pg_catalog.pg_type t "
"on a.atttypid = t.oid "
"where a.attrelid = '%u'::pg_catalog.oid "
*************** getTableAttrs(TableInfo *tblinfo, int nu
*** 4319,4325 ****
*/
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, -1 as attstattarget, a.attstorage, t.typstorage, "
"a.attnotnull, a.atthasdef, false as attisdropped, false as attislocal, "
! "format_type(t.oid,a.atttypmod) as atttypname "
"from pg_attribute a left join pg_type t "
"on a.atttypid = t.oid "
"where a.attrelid = '%u'::oid "
--- 4339,4346 ----
*/
appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, -1 as attstattarget, a.attstorage, t.typstorage, "
"a.attnotnull, a.atthasdef, false as attisdropped, false as attislocal, "
! "format_type(t.oid,a.atttypmod) as atttypname, "
! "false as attidentity, false as attforceddef "
"from pg_attribute a left join pg_type t "
"on a.atttypid = t.oid "
"where a.attrelid = '%u'::oid "
*************** getTableAttrs(TableInfo *tblinfo, int nu
*** 4332,4338 ****
/* format_type not available before 7.1 */
appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, -1 as attstattarget, attstorage, attstorage as typstorage, "
"attnotnull, atthasdef, false as attisdropped, false as attislocal, "
! "(select typname from pg_type where oid = atttypid) as atttypname "
"from pg_attribute a "
"where attrelid = '%u'::oid "
"and attnum > 0::int2 "
--- 4353,4360 ----
/* format_type not available before 7.1 */
appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, -1 as attstattarget, attstorage, attstorage as typstorage, "
"attnotnull, atthasdef, false as attisdropped, false as attislocal, "
! "(select typname from pg_type where oid = atttypid) as atttypname, "
! "false as attidentity, false as attforceddef "
"from pg_attribute a "
"where attrelid = '%u'::oid "
"and attnum > 0::int2 "
*************** getTableAttrs(TableInfo *tblinfo, int nu
*** 4356,4361 ****
--- 4378,4385 ----
i_atthasdef = PQfnumber(res, "atthasdef");
i_attisdropped = PQfnumber(res, "attisdropped");
i_attislocal = PQfnumber(res, "attislocal");
+ i_attidentity = PQfnumber(res, "attidentity");
+ i_attforceddef = PQfnumber(res, "attforceddef");
tbinfo->numatts = ntups;
tbinfo->attnames = (char **) malloc(ntups * sizeof(char *));
*************** getTableAttrs(TableInfo *tblinfo, int nu
*** 4366,4371 ****
--- 4390,4397 ----
tbinfo->typstorage = (char *) malloc(ntups * sizeof(char));
tbinfo->attisdropped = (bool *) malloc(ntups * sizeof(bool));
tbinfo->attislocal = (bool *) malloc(ntups * sizeof(bool));
+ tbinfo->attidentity = (bool *) malloc(ntups * sizeof(bool));
+ tbinfo->attforceddef = (bool *) malloc(ntups * sizeof(bool));
tbinfo->notnull = (bool *) malloc(ntups * sizeof(bool));
tbinfo->attrdefs = (AttrDefInfo **) malloc(ntups * sizeof(AttrDefInfo *));
tbinfo->inhAttrs = (bool *) malloc(ntups * sizeof(bool));
*************** getTableAttrs(TableInfo *tblinfo, int nu
*** 4389,4394 ****
--- 4415,4423 ----
tbinfo->typstorage[j] = *(PQgetvalue(res, j, i_typstorage));
tbinfo->attisdropped[j] = (PQgetvalue(res, j, i_attisdropped)[0] == 't');
tbinfo->attislocal[j] = (PQgetvalue(res, j, i_attislocal)[0] == 't');
+ tbinfo->attidentity[j] = (PQgetvalue(res, j, i_attidentity)[0] == 't');
+ tbinfo->attforceddef[j] = (PQgetvalue(res, j, i_attforceddef)[0] == 't');
+ tbinfo->hasforceddef |= tbinfo->attforceddef[j];
tbinfo->notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't');
tbinfo->attrdefs[j] = NULL; /* fix below */
if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
*************** dumpTableSchema(Archive *fout, TableInfo
*** 7872,7879 ****
/*
* Default value --- suppress if inherited or to be printed
* separately.
*/
! if (tbinfo->attrdefs[j] != NULL &&
!tbinfo->inhAttrDef[j] &&
!tbinfo->attrdefs[j]->separate)
appendPQExpBuffer(q, " DEFAULT %s",
--- 7901,7917 ----
/*
* Default value --- suppress if inherited or to be printed
* separately.
+ * A GENERATED column cannot be built from building block
+ * such as a SERIAL or IDENTITY column, only ADDed or DROPped.
+ * Hence emit the GENERATED property in the schema itself.
*/
! if (tbinfo->attforceddef[j] &&
! !tbinfo->attidentity[j])
! {
! appendPQExpBuffer(q, " GENERATED ALWAYS AS ( %s )",
! tbinfo->attrdefs[j]->adef_expr);
! }
! else if (tbinfo->attrdefs[j] != NULL &&
!tbinfo->inhAttrDef[j] &&
!tbinfo->attrdefs[j]->separate)
appendPQExpBuffer(q, " DEFAULT %s",
*************** dumpAttrDef(Archive *fout, AttrDefInfo *
*** 8044,8055 ****
q = createPQExpBuffer();
delq = createPQExpBuffer();
! appendPQExpBuffer(q, "ALTER TABLE %s ",
fmtId(tbinfo->dobj.name));
! appendPQExpBuffer(q, "ALTER COLUMN %s SET DEFAULT %s;\n",
fmtId(tbinfo->attnames[adnum - 1]),
adinfo->adef_expr);
/*
* DROP must be fully qualified in case same name appears in pg_catalog
*/
--- 8082,8108 ----
q = createPQExpBuffer();
delq = createPQExpBuffer();
! if (tbinfo->attidentity[adnum - 1] ||
! !tbinfo->attforceddef[adnum - 1])
! {
! appendPQExpBuffer(q, "ALTER TABLE %s ",
fmtId(tbinfo->dobj.name));
! appendPQExpBuffer(q, "ALTER COLUMN %s SET DEFAULT %s;\n",
fmtId(tbinfo->attnames[adnum - 1]),
adinfo->adef_expr);
+ if (tbinfo->attidentity[adnum - 1])
+ {
+ appendPQExpBuffer(q, "ALTER TABLE %s",
+ fmtId(tbinfo->dobj.name));
+ appendPQExpBuffer(q, " ALTER %s",
+ fmtId(tbinfo->attnames[adnum - 1]));
+ appendPQExpBuffer(q, " SET GENERATED %s AS IDENTITY;\n",
+ tbinfo->attforceddef[adnum - 1] ?
+ "ALWAYS" : "BY DEFAULT");
+ }
+ }
+
/*
* DROP must be fully qualified in case same name appears in pg_catalog
*/
diff -dcrpN pgsql.orig/src/bin/pg_dump/pg_dump.h pgsql/src/bin/pg_dump/pg_dump.h
*** pgsql.orig/src/bin/pg_dump/pg_dump.h 2007-02-20 14:59:53.000000000 +0100
--- pgsql/src/bin/pg_dump/pg_dump.h 2007-02-26 00:07:11.000000000 +0100
*************** typedef struct _tableInfo
*** 258,263 ****
--- 258,266 ----
char *typstorage; /* type storage scheme */
bool *attisdropped; /* true if attr is dropped; don't dump it */
bool *attislocal; /* true if attr has local definition */
+ bool *attidentity; /* true if attr is GENERATED AS IDENTITY */
+ bool *attforceddef; /* true if attr is GENERATED ALWAYS */
+ bool hasforceddef; /* true if any of the attrs is GENERATED ALWAYS */
/*
* Note: we need to store per-attribute notnull, default, and constraint
diff -dcrpN pgsql.orig/src/include/catalog/heap.h pgsql/src/include/catalog/heap.h
*** pgsql.orig/src/include/catalog/heap.h 2007-01-10 19:59:08.000000000 +0100
--- pgsql/src/include/catalog/heap.h 2007-02-26 00:07:11.000000000 +0100
*************** typedef struct RawColumnDefault
*** 21,26 ****
--- 21,28 ----
{
AttrNumber attnum; /* attribute to attach default to */
Node *raw_default; /* default value (untransformed parse tree) */
+ bool is_identity; /* column is GENERATED AS IDENTITY */
+ bool force_default; /* column is GENERATED ALWAYS */
} RawColumnDefault;
typedef struct CookedConstraint
*************** typedef struct CookedConstraint
*** 29,34 ****
--- 31,37 ----
char *name; /* name, or NULL if none */
AttrNumber attnum; /* which attr (only for DEFAULT) */
Node *expr; /* transformed default or check expr */
+ bool force_default; /* GENERATED ALWAYS */
} CookedConstraint;
extern Relation heap_create(const char *relname,
*************** extern List *AddRelationRawConstraints(R
*** 71,83 ****
List *rawColDefaults,
List *rawConstraints);
! extern void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin);
extern Node *cookDefault(ParseState *pstate,
Node *raw_default,
Oid atttypid,
int32 atttypmod,
! char *attname);
extern int RemoveRelConstraints(Relation rel, const char *constrName,
DropBehavior behavior);
--- 74,87 ----
List *rawColDefaults,
List *rawConstraints);
! extern void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin, bool attidentity, bool attforceddef);
extern Node *cookDefault(ParseState *pstate,
Node *raw_default,
Oid atttypid,
int32 atttypmod,
! char *attname,
! bool force_default);
extern int RemoveRelConstraints(Relation rel, const char *constrName,
DropBehavior behavior);
diff -dcrpN pgsql.orig/src/include/catalog/pg_attribute.h pgsql/src/include/catalog/pg_attribute.h
*** pgsql.orig/src/include/catalog/pg_attribute.h 2007-01-26 18:53:15.000000000 +0100
--- pgsql/src/include/catalog/pg_attribute.h 2007-02-26 00:07:11.000000000 +0100
*************** CATALOG(pg_attribute,1249) BKI_BOOTSTRAP
*** 149,154 ****
--- 149,160 ----
/* Number of times inherited from direct parent relation(s) */
int4 attinhcount;
+
+ /* GENERATED ... AS IDENTITY or SERIAL */
+ bool attidentity;
+
+ /* GENERATED ALWAYS */
+ bool attforceddef;
} FormData_pg_attribute;
/*
*************** CATALOG(pg_attribute,1249) BKI_BOOTSTRAP
*** 157,163 ****
* because of alignment padding at the end of the struct.)
*/
#define ATTRIBUTE_TUPLE_SIZE \
! (offsetof(FormData_pg_attribute,attinhcount) + sizeof(int4))
/* ----------------
* Form_pg_attribute corresponds to a pointer to a tuple with
--- 163,169 ----
* because of alignment padding at the end of the struct.)
*/
#define ATTRIBUTE_TUPLE_SIZE \
! (offsetof(FormData_pg_attribute,attforceddef) + sizeof(bool))
/* ----------------
* Form_pg_attribute corresponds to a pointer to a tuple with
*************** typedef FormData_pg_attribute *Form_pg_a
*** 171,177 ****
* ----------------
*/
! #define Natts_pg_attribute 17
#define Anum_pg_attribute_attrelid 1
#define Anum_pg_attribute_attname 2
#define Anum_pg_attribute_atttypid 3
--- 177,183 ----
* ----------------
*/
! #define Natts_pg_attribute 19
#define Anum_pg_attribute_attrelid 1
#define Anum_pg_attribute_attname 2
#define Anum_pg_attribute_atttypid 3
*************** typedef FormData_pg_attribute *Form_pg_a
*** 189,194 ****
--- 195,202 ----
#define Anum_pg_attribute_attisdropped 15
#define Anum_pg_attribute_attislocal 16
#define Anum_pg_attribute_attinhcount 17
+ #define Anum_pg_attribute_attidentity 18
+ #define Anum_pg_attribute_attforceddef 19
*************** typedef FormData_pg_attribute *Form_pg_a
*** 222,455 ****
* ----------------
*/
#define Schema_pg_type \
! { 1247, {"typname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typnamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typowner"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typlen"}, 21, -1, 2, 4, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1247, {"typbyval"}, 16, -1, 1, 5, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typtype"}, 18, -1, 1, 6, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typisdefined"}, 16, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typdelim"}, 18, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typrelid"}, 26, -1, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typelem"}, 26, -1, 4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typinput"}, 24, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typoutput"}, 24, -1, 4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typreceive"}, 24, -1, 4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typsend"}, 24, -1, 4, 14, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typmodin"}, 24, -1, 4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typmodout"}, 24, -1, 4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typanalyze"}, 24, -1, 4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typalign"}, 18, -1, 1, 18, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typstorage"}, 18, -1, 1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typnotnull"}, 16, -1, 1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typbasetype"}, 26, -1, 4, 21, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typtypmod"}, 23, -1, 4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typndims"}, 23, -1, 4, 23, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typdefaultbin"}, 25, -1, -1, 24, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1247, {"typdefault"}, 25, -1, -1, 25, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
! DATA(insert ( 1247 typname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0));
! DATA(insert ( 1247 typnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typowner 26 -1 4 3 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typlen 21 -1 2 4 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1247 typbyval 16 -1 1 5 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typtype 18 -1 1 6 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typisdefined 16 -1 1 7 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typdelim 18 -1 1 8 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typrelid 26 -1 4 9 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typelem 26 -1 4 10 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typinput 24 -1 4 11 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typoutput 24 -1 4 12 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typreceive 24 -1 4 13 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typsend 24 -1 4 14 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typmodin 24 -1 4 15 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typmodout 24 -1 4 16 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typanalyze 24 -1 4 17 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typalign 18 -1 1 18 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typstorage 18 -1 1 19 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typnotnull 16 -1 1 20 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typbasetype 26 -1 4 21 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typtypmod 23 -1 4 22 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typndims 23 -1 4 23 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typdefaultbin 25 -1 -1 24 0 -1 -1 f x i f f f t 0));
! DATA(insert ( 1247 typdefault 25 -1 -1 25 0 -1 -1 f x i f f f t 0));
! DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
! DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
/* ----------------
* pg_proc
* ----------------
*/
#define Schema_pg_proc \
! { 1255, {"proname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
! { 1255, {"pronamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1255, {"proowner"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1255, {"prolang"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1255, {"procost"}, 700, -1, 4, 5, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
! { 1255, {"prorows"}, 700, -1, 4, 6, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
! { 1255, {"proisagg"}, 16, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1255, {"prosecdef"}, 16, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1255, {"proisstrict"}, 16, -1, 1, 9, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1255, {"proretset"}, 16, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1255, {"provolatile"}, 18, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1255, {"pronargs"}, 21, -1, 2, 12, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1255, {"prorettype"}, 26, -1, 4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1255, {"proargtypes"}, 30, -1, -1, 14, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
! { 1255, {"proallargtypes"}, 1028, -1, -1, 15, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1255, {"proargmodes"}, 1002, -1, -1, 16, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1255, {"proargnames"}, 1009, -1, -1, 17, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1255, {"prosrc"}, 25, -1, -1, 18, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1255, {"probin"}, 17, -1, -1, 19, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1255, {"proacl"}, 1034, -1, -1, 20, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
! DATA(insert ( 1255 proname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0));
! DATA(insert ( 1255 pronamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1255 proowner 26 -1 4 3 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1255 prolang 26 -1 4 4 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1255 procost 700 -1 4 5 0 -1 -1 f p i t f f t 0));
! DATA(insert ( 1255 prorows 700 -1 4 6 0 -1 -1 f p i t f f t 0));
! DATA(insert ( 1255 proisagg 16 -1 1 7 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1255 prosecdef 16 -1 1 8 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1255 proisstrict 16 -1 1 9 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1255 proretset 16 -1 1 10 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1255 provolatile 18 -1 1 11 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1255 pronargs 21 -1 2 12 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1255 prorettype 26 -1 4 13 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1255 proargtypes 30 -1 -1 14 1 -1 -1 f p i t f f t 0));
! DATA(insert ( 1255 proallargtypes 1028 -1 -1 15 1 -1 -1 f x i f f f t 0));
! DATA(insert ( 1255 proargmodes 1002 -1 -1 16 1 -1 -1 f x i f f f t 0));
! DATA(insert ( 1255 proargnames 1009 -1 -1 17 1 -1 -1 f x i f f f t 0));
! DATA(insert ( 1255 prosrc 25 -1 -1 18 0 -1 -1 f x i f f f t 0));
! DATA(insert ( 1255 probin 17 -1 -1 19 0 -1 -1 f x i f f f t 0));
! DATA(insert ( 1255 proacl 1034 -1 -1 20 1 -1 -1 f x i f f f t 0));
! DATA(insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
! DATA(insert ( 1255 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1255 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1255 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1255 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1255 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1255 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
/* ----------------
* pg_attribute
* ----------------
*/
#define Schema_pg_attribute \
! { 1249, {"attrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1249, {"attname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
! { 1249, {"atttypid"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1249, {"attstattarget"}, 23, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1249, {"attlen"}, 21, -1, 2, 5, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1249, {"attnum"}, 21, -1, 2, 6, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1249, {"attndims"}, 23, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1249, {"attcacheoff"}, 23, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1249, {"atttypmod"}, 23, -1, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1249, {"attbyval"}, 16, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1249, {"attstorage"}, 18, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1249, {"attalign"}, 18, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1249, {"attnotnull"}, 16, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1249, {"atthasdef"}, 16, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1249, {"attisdropped"}, 16, -1, 1, 15, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1249, {"attislocal"}, 16, -1, 1, 16, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1249, {"attinhcount"}, 23, -1, 4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }
! DATA(insert ( 1249 attrelid 26 -1 4 1 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1249 attname 19 -1 NAMEDATALEN 2 0 -1 -1 f p i t f f t 0));
! DATA(insert ( 1249 atttypid 26 -1 4 3 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1249 attstattarget 23 -1 4 4 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1249 attlen 21 -1 2 5 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1249 attnum 21 -1 2 6 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1249 attndims 23 -1 4 7 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1249 attcacheoff 23 -1 4 8 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1249 atttypmod 23 -1 4 9 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1249 attbyval 16 -1 1 10 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1249 attstorage 18 -1 1 11 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1249 attalign 18 -1 1 12 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1249 attnotnull 16 -1 1 13 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1249 atthasdef 16 -1 1 14 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1249 attisdropped 16 -1 1 15 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1249 attislocal 16 -1 1 16 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1249 attinhcount 23 -1 4 17 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1249 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
/* no OIDs in pg_attribute */
! DATA(insert ( 1249 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1249 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1249 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1249 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
/* ----------------
* pg_class
* ----------------
*/
#define Schema_pg_class \
! { 1259, {"relname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"relnamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"reltype"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"relowner"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"relam"}, 26, -1, 4, 5, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"relfilenode"}, 26, -1, 4, 6, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"reltablespace"}, 26, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"relpages"}, 23, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"reltuples"}, 700, -1, 4, 9, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"reltoastrelid"}, 26, -1, 4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"reltoastidxid"}, 26, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"relhasindex"}, 16, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relisshared"}, 16, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relkind"}, 18, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relnatts"}, 21, -1, 2, 15, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relchecks"}, 21, -1, 2, 16, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"reltriggers"}, 21, -1, 2, 17, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relukeys"}, 21, -1, 2, 18, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relfkeys"}, 21, -1, 2, 19, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relrefs"}, 21, -1, 2, 20, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relhasoids"}, 16, -1, 1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relhaspkey"}, 16, -1, 1, 22, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relhasrules"}, 16, -1, 1, 23, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relhassubclass"},16, -1, 1, 24, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relfrozenxid"}, 28, -1, 4, 25, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"relacl"}, 1034, -1, -1, 26, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1259, {"reloptions"}, 1009, -1, -1, 27, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
! DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0));
! DATA(insert ( 1259 relnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 reltype 26 -1 4 3 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 relowner 26 -1 4 4 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 relam 26 -1 4 5 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 relfilenode 26 -1 4 6 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 reltablespace 26 -1 4 7 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 relpages 23 -1 4 8 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 reltuples 700 -1 4 9 0 -1 -1 f p i t f f t 0));
! DATA(insert ( 1259 reltoastrelid 26 -1 4 10 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 reltoastidxid 26 -1 4 11 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 relhasindex 16 -1 1 12 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relisshared 16 -1 1 13 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relkind 18 -1 1 14 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relnatts 21 -1 2 15 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relchecks 21 -1 2 16 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 reltriggers 21 -1 2 17 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relukeys 21 -1 2 18 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relfkeys 21 -1 2 19 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relrefs 21 -1 2 20 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relhasoids 16 -1 1 21 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relhaspkey 16 -1 1 22 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relhasrules 16 -1 1 23 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relhassubclass 16 -1 1 24 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relfrozenxid 28 -1 4 25 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 relacl 1034 -1 -1 26 1 -1 -1 f x i f f f t 0));
! DATA(insert ( 1259 reloptions 1009 -1 -1 27 1 -1 -1 f x i f f f t 0));
! DATA(insert ( 1259 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
! DATA(insert ( 1259 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
/* ----------------
* pg_index
--- 230,468 ----
* ----------------
*/
#define Schema_pg_type \
! { 1247, {"typname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typnamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typowner"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typlen"}, 21, -1, 2, 4, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, false, false }, \
! { 1247, {"typbyval"}, 16, -1, 1, 5, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1247, {"typtype"}, 18, -1, 1, 6, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1247, {"typisdefined"}, 16, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1247, {"typdelim"}, 18, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1247, {"typrelid"}, 26, -1, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typelem"}, 26, -1, 4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typinput"}, 24, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typoutput"}, 24, -1, 4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typreceive"}, 24, -1, 4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typsend"}, 24, -1, 4, 14, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typmodin"}, 24, -1, 4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typmodout"}, 24, -1, 4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typanalyze"}, 24, -1, 4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typalign"}, 18, -1, 1, 18, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1247, {"typstorage"}, 18, -1, 1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1247, {"typnotnull"}, 16, -1, 1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1247, {"typbasetype"}, 26, -1, 4, 21, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typtypmod"}, 23, -1, 4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typndims"}, 23, -1, 4, 23, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1247, {"typdefaultbin"}, 25, -1, -1, 24, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, false, false }, \
! { 1247, {"typdefault"}, 25, -1, -1, 25, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, false, false }
! DATA(insert ( 1247 typname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0 f f));
! DATA(insert ( 1247 typnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typowner 26 -1 4 3 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typlen 21 -1 2 4 0 -1 -1 t p s t f f t 0 f f));
! DATA(insert ( 1247 typbyval 16 -1 1 5 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1247 typtype 18 -1 1 6 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1247 typisdefined 16 -1 1 7 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1247 typdelim 18 -1 1 8 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1247 typrelid 26 -1 4 9 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typelem 26 -1 4 10 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typinput 24 -1 4 11 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typoutput 24 -1 4 12 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typreceive 24 -1 4 13 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typsend 24 -1 4 14 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typmodin 24 -1 4 15 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typmodout 24 -1 4 16 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typanalyze 24 -1 4 17 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typalign 18 -1 1 18 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1247 typstorage 18 -1 1 19 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1247 typnotnull 16 -1 1 20 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1247 typbasetype 26 -1 4 21 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typtypmod 23 -1 4 22 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typndims 23 -1 4 23 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 typdefaultbin 25 -1 -1 24 0 -1 -1 f x i f f f t 0 f f));
! DATA(insert ( 1247 typdefault 25 -1 -1 25 0 -1 -1 f x i f f f t 0 f f));
! DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0 f f));
! DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1247 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0 f f));
/* ----------------
* pg_proc
* ----------------
*/
#define Schema_pg_proc \
! { 1255, {"proname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1255, {"pronamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1255, {"proowner"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1255, {"prolang"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1255, {"procost"}, 700, -1, 4, 5, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1255, {"prorows"}, 700, -1, 4, 6, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1255, {"proisagg"}, 16, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1255, {"prosecdef"}, 16, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1255, {"proisstrict"}, 16, -1, 1, 9, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1255, {"proretset"}, 16, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1255, {"provolatile"}, 18, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1255, {"pronargs"}, 21, -1, 2, 12, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, false, false }, \
! { 1255, {"prorettype"}, 26, -1, 4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1255, {"proargtypes"}, 30, -1, -1, 14, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1255, {"proallargtypes"}, 1028, -1, -1, 15, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, false, false }, \
! { 1255, {"proargmodes"}, 1002, -1, -1, 16, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, false, false }, \
! { 1255, {"proargnames"}, 1009, -1, -1, 17, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, false, false }, \
! { 1255, {"prosrc"}, 25, -1, -1, 18, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, false, false }, \
! { 1255, {"probin"}, 17, -1, -1, 19, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, false, false }, \
! { 1255, {"proacl"}, 1034, -1, -1, 20, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, false, false }
! DATA(insert ( 1255 proname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0 f f));
! DATA(insert ( 1255 pronamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1255 proowner 26 -1 4 3 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1255 prolang 26 -1 4 4 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1255 procost 700 -1 4 5 0 -1 -1 f p i t f f t 0 f f));
! DATA(insert ( 1255 prorows 700 -1 4 6 0 -1 -1 f p i t f f t 0 f f));
! DATA(insert ( 1255 proisagg 16 -1 1 7 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1255 prosecdef 16 -1 1 8 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1255 proisstrict 16 -1 1 9 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1255 proretset 16 -1 1 10 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1255 provolatile 18 -1 1 11 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1255 pronargs 21 -1 2 12 0 -1 -1 t p s t f f t 0 f f));
! DATA(insert ( 1255 prorettype 26 -1 4 13 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1255 proargtypes 30 -1 -1 14 1 -1 -1 f p i t f f t 0 f f));
! DATA(insert ( 1255 proallargtypes 1028 -1 -1 15 1 -1 -1 f x i f f f t 0 f f));
! DATA(insert ( 1255 proargmodes 1002 -1 -1 16 1 -1 -1 f x i f f f t 0 f f));
! DATA(insert ( 1255 proargnames 1009 -1 -1 17 1 -1 -1 f x i f f f t 0 f f));
! DATA(insert ( 1255 prosrc 25 -1 -1 18 0 -1 -1 f x i f f f t 0 f f));
! DATA(insert ( 1255 probin 17 -1 -1 19 0 -1 -1 f x i f f f t 0 f f));
! DATA(insert ( 1255 proacl 1034 -1 -1 20 1 -1 -1 f x i f f f t 0 f f));
! DATA(insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0 f f));
! DATA(insert ( 1255 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1255 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1255 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1255 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1255 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1255 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0 f f));
/* ----------------
* pg_attribute
* ----------------
*/
#define Schema_pg_attribute \
! { 1249, {"attrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1249, {"attname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1249, {"atttypid"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1249, {"attstattarget"}, 23, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1249, {"attlen"}, 21, -1, 2, 5, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, false, false }, \
! { 1249, {"attnum"}, 21, -1, 2, 6, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, false, false }, \
! { 1249, {"attndims"}, 23, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1249, {"attcacheoff"}, 23, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1249, {"atttypmod"}, 23, -1, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1249, {"attbyval"}, 16, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1249, {"attstorage"}, 18, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1249, {"attalign"}, 18, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1249, {"attnotnull"}, 16, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1249, {"atthasdef"}, 16, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1249, {"attisdropped"}, 16, -1, 1, 15, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1249, {"attislocal"}, 16, -1, 1, 16, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1249, {"attinhcount"}, 23, -1, 4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1249, {"attidentity"}, 16, -1, 1, 18, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1249, {"attforceddef"}, 16, -1, 1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }
!
! DATA(insert ( 1249 attrelid 26 -1 4 1 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1249 attname 19 -1 NAMEDATALEN 2 0 -1 -1 f p i t f f t 0 f f));
! DATA(insert ( 1249 atttypid 26 -1 4 3 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1249 attstattarget 23 -1 4 4 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1249 attlen 21 -1 2 5 0 -1 -1 t p s t f f t 0 f f));
! DATA(insert ( 1249 attnum 21 -1 2 6 0 -1 -1 t p s t f f t 0 f f));
! DATA(insert ( 1249 attndims 23 -1 4 7 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1249 attcacheoff 23 -1 4 8 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1249 atttypmod 23 -1 4 9 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1249 attbyval 16 -1 1 10 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1249 attstorage 18 -1 1 11 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1249 attalign 18 -1 1 12 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1249 attnotnull 16 -1 1 13 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1249 atthasdef 16 -1 1 14 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1249 attisdropped 16 -1 1 15 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1249 attislocal 16 -1 1 16 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1249 attinhcount 23 -1 4 17 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1249 attidentity 16 -1 1 18 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1249 attforceddef 16 -1 1 19 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1249 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0 f f));
/* no OIDs in pg_attribute */
! DATA(insert ( 1249 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1249 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1249 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1249 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0 f f));
/* ----------------
* pg_class
* ----------------
*/
#define Schema_pg_class \
! { 1259, {"relname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1259, {"relnamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1259, {"reltype"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1259, {"relowner"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1259, {"relam"}, 26, -1, 4, 5, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1259, {"relfilenode"}, 26, -1, 4, 6, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1259, {"reltablespace"}, 26, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1259, {"relpages"}, 23, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1259, {"reltuples"}, 700, -1, 4, 9, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1259, {"reltoastrelid"}, 26, -1, 4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1259, {"reltoastidxid"}, 26, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1259, {"relhasindex"}, 16, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1259, {"relisshared"}, 16, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1259, {"relkind"}, 18, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1259, {"relnatts"}, 21, -1, 2, 15, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, false, false }, \
! { 1259, {"relchecks"}, 21, -1, 2, 16, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, false, false }, \
! { 1259, {"reltriggers"}, 21, -1, 2, 17, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, false, false }, \
! { 1259, {"relukeys"}, 21, -1, 2, 18, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, false, false }, \
! { 1259, {"relfkeys"}, 21, -1, 2, 19, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, false, false }, \
! { 1259, {"relrefs"}, 21, -1, 2, 20, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, false, false }, \
! { 1259, {"relhasoids"}, 16, -1, 1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1259, {"relhaspkey"}, 16, -1, 1, 22, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1259, {"relhasrules"}, 16, -1, 1, 23, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1259, {"relhassubclass"},16, -1, 1, 24, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 1259, {"relfrozenxid"}, 28, -1, 4, 25, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 1259, {"relacl"}, 1034, -1, -1, 26, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, false, false }, \
! { 1259, {"reloptions"}, 1009, -1, -1, 27, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, false, false }
! DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0 f f));
! DATA(insert ( 1259 relnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 reltype 26 -1 4 3 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 relowner 26 -1 4 4 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 relam 26 -1 4 5 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 relfilenode 26 -1 4 6 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 reltablespace 26 -1 4 7 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 relpages 23 -1 4 8 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 reltuples 700 -1 4 9 0 -1 -1 f p i t f f t 0 f f));
! DATA(insert ( 1259 reltoastrelid 26 -1 4 10 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 reltoastidxid 26 -1 4 11 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 relhasindex 16 -1 1 12 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1259 relisshared 16 -1 1 13 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1259 relkind 18 -1 1 14 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1259 relnatts 21 -1 2 15 0 -1 -1 t p s t f f t 0 f f));
! DATA(insert ( 1259 relchecks 21 -1 2 16 0 -1 -1 t p s t f f t 0 f f));
! DATA(insert ( 1259 reltriggers 21 -1 2 17 0 -1 -1 t p s t f f t 0 f f));
! DATA(insert ( 1259 relukeys 21 -1 2 18 0 -1 -1 t p s t f f t 0 f f));
! DATA(insert ( 1259 relfkeys 21 -1 2 19 0 -1 -1 t p s t f f t 0 f f));
! DATA(insert ( 1259 relrefs 21 -1 2 20 0 -1 -1 t p s t f f t 0 f f));
! DATA(insert ( 1259 relhasoids 16 -1 1 21 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1259 relhaspkey 16 -1 1 22 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1259 relhasrules 16 -1 1 23 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1259 relhassubclass 16 -1 1 24 0 -1 -1 t p c t f f t 0 f f));
! DATA(insert ( 1259 relfrozenxid 28 -1 4 25 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 relacl 1034 -1 -1 26 1 -1 -1 f x i f f f t 0 f f));
! DATA(insert ( 1259 reloptions 1009 -1 -1 27 1 -1 -1 f x i f f f t 0 f f));
! DATA(insert ( 1259 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0 f f));
! DATA(insert ( 1259 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0 f f));
! DATA(insert ( 1259 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0 f f));
/* ----------------
* pg_index
*************** DATA(insert ( 1259 tableoid 26 0 4 -
*** 460,476 ****
* ----------------
*/
#define Schema_pg_index \
! { 0, {"indexrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 0, {"indrelid"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 0, {"indnatts"}, 21, -1, 2, 3, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 0, {"indisunique"}, 16, -1, 1, 4, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 0, {"indisprimary"}, 16, -1, 1, 5, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 0, {"indisclustered"}, 16, -1, 1, 6, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 0, {"indisvalid"}, 16, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 0, {"indkey"}, 22, -1, -1, 8, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
! { 0, {"indclass"}, 30, -1, -1, 9, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
! { 0, {"indoption"}, 22, -1, -1, 10, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
! { 0, {"indexprs"}, 25, -1, -1, 11, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 0, {"indpred"}, 25, -1, -1, 12, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
#endif /* PG_ATTRIBUTE_H */
--- 473,489 ----
* ----------------
*/
#define Schema_pg_index \
! { 0, {"indexrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 0, {"indrelid"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 0, {"indnatts"}, 21, -1, 2, 3, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, false, false }, \
! { 0, {"indisunique"}, 16, -1, 1, 4, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 0, {"indisprimary"}, 16, -1, 1, 5, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 0, {"indisclustered"}, 16, -1, 1, 6, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 0, {"indisvalid"}, 16, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, false, false }, \
! { 0, {"indkey"}, 22, -1, -1, 8, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 0, {"indclass"}, 30, -1, -1, 9, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 0, {"indoption"}, 22, -1, -1, 10, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0, false, false }, \
! { 0, {"indexprs"}, 25, -1, -1, 11, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, false, false }, \
! { 0, {"indpred"}, 25, -1, -1, 12, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, false, false }
#endif /* PG_ATTRIBUTE_H */
diff -dcrpN pgsql.orig/src/include/catalog/pg_class.h pgsql/src/include/catalog/pg_class.h
*** pgsql.orig/src/include/catalog/pg_class.h 2007-01-26 18:53:15.000000000 +0100
--- pgsql/src/include/catalog/pg_class.h 2007-02-26 00:07:11.000000000 +0100
*************** typedef FormData_pg_class *Form_pg_class
*** 134,140 ****
/* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 25 0 0 0 0 0 t f f f 3 _null_ _null_ ));
DESCR("");
! DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f f 3 _null_ _null_ ));
DESCR("");
DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 20 0 0 0 0 0 t f f f 3 _null_ _null_ ));
DESCR("");
--- 134,140 ----
/* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 25 0 0 0 0 0 t f f f 3 _null_ _null_ ));
DESCR("");
! DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 19 0 0 0 0 0 f f f f 3 _null_ _null_ ));
DESCR("");
DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 20 0 0 0 0 0 t f f f 3 _null_ _null_ ));
DESCR("");
diff -dcrpN pgsql.orig/src/include/executor/execdesc.h pgsql/src/include/executor/execdesc.h
*** pgsql.orig/src/include/executor/execdesc.h 2007-02-25 16:14:32.000000000 +0100
--- pgsql/src/include/executor/execdesc.h 2007-02-27 22:43:54.000000000 +0100
*************** typedef struct QueryDesc
*** 47,52 ****
--- 47,54 ----
TupleDesc tupDesc; /* descriptor for result tuples */
EState *estate; /* executor's query-wide state */
PlanState *planstate; /* tree of per-plan-node state */
+ bool idSetToDefault; /* The table in the query has an IDENTITY column
+ and it has to be set to DEFAULT */
} QueryDesc;
/* in pquery.c */
diff -dcrpN pgsql.orig/src/include/executor/executor.h pgsql/src/include/executor/executor.h
*** pgsql.orig/src/include/executor/executor.h 2007-02-25 16:14:32.000000000 +0100
--- pgsql/src/include/executor/executor.h 2007-02-26 10:24:34.000000000 +0100
*************** extern void ExecutorRewind(QueryDesc *qu
*** 133,139 ****
extern void ExecEndPlan(PlanState *planstate, EState *estate);
extern bool ExecContextForcesOids(PlanState *planstate, bool *hasoids);
extern void ExecConstraints(ResultRelInfo *resultRelInfo,
! TupleTableSlot *slot, EState *estate);
extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
ItemPointer tid, TransactionId priorXmax, CommandId curCid);
extern DestReceiver *CreateIntoRelDestReceiver(void);
--- 133,140 ----
extern void ExecEndPlan(PlanState *planstate, EState *estate);
extern bool ExecContextForcesOids(PlanState *planstate, bool *hasoids);
extern void ExecConstraints(ResultRelInfo *resultRelInfo,
! TupleTableSlot *slot, EState *estate,
! bool process_identity, bool process_generated);
extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
ItemPointer tid, TransactionId priorXmax, CommandId curCid);
extern DestReceiver *CreateIntoRelDestReceiver(void);
diff -dcrpN pgsql.orig/src/include/nodes/parsenodes.h pgsql/src/include/nodes/parsenodes.h
*** pgsql.orig/src/include/nodes/parsenodes.h 2007-02-25 16:14:32.000000000 +0100
--- pgsql/src/include/nodes/parsenodes.h 2007-02-27 22:37:54.000000000 +0100
*************** typedef struct Query
*** 129,134 ****
--- 129,139 ----
Node *setOperations; /* set-operation tree if this is top level of
* a UNION/INTERSECT/EXCEPT query */
+
+ bool commandOverride; /* OVERRIDING SYSTEM VALUE */
+
+ bool idSetToDefault; /* The table query has an IDENTITY column and
+ it has to be set to DEFAULT */
} Query;
*************** typedef struct ColumnDef
*** 389,394 ****
--- 394,401 ----
Node *raw_default; /* default value (untransformed parse tree) */
char *cooked_default; /* nodeToString representation */
List *constraints; /* other constraints on column */
+ bool is_identity; /* GENERATED AS IDENTITY */
+ bool force_default; /* GENERATED ALWAYS */
} ColumnDef;
/*
*************** typedef struct InsertStmt
*** 673,678 ****
--- 680,686 ----
List *cols; /* optional: names of the target columns */
Node *selectStmt; /* the source SELECT/VALUES, or NULL */
List *returningList; /* list of expressions to return */
+ bool commandOverride;/* OVERRIDING SYSTEM VALUE */
} InsertStmt;
/* ----------------------
*************** typedef enum AlterTableType
*** 903,909 ****
AT_EnableTrigUser, /* ENABLE TRIGGER USER */
AT_DisableTrigUser, /* DISABLE TRIGGER USER */
AT_AddInherit, /* INHERIT parent */
! AT_DropInherit /* NO INHERIT parent */
} AlterTableType;
typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */
--- 911,920 ----
AT_EnableTrigUser, /* ENABLE TRIGGER USER */
AT_DisableTrigUser, /* DISABLE TRIGGER USER */
AT_AddInherit, /* INHERIT parent */
! AT_DropInherit, /* NO INHERIT parent */
! AT_SetSeqOpts, /* SET sequence_options for IDENTITY columns */
! AT_SetIdentity, /* SET IDENTITY */
! AT_DropIdentity /* DROP IDENTITY */
} AlterTableType;
typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */
*************** typedef struct AlterTableCmd /* one subc
*** 916,921 ****
--- 927,935 ----
* index, constraint, or parent table */
Node *transform; /* transformation expr for ALTER TYPE */
DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */
+ bool force_default; /* SET GENERATED
+ { ALWAYS | BY DEFAULT }
+ AS IDENTITY */
} AlterTableCmd;
*************** typedef struct CopyStmt
*** 1035,1040 ****
--- 1049,1055 ----
bool is_from; /* TO or FROM */
char *filename; /* filename, or NULL for STDIN/STDOUT */
List *options; /* List of DefElem nodes */
+ bool overriding; /* OVERRIDING SYSTEM VALUE */
} CopyStmt;
/* ----------------------
*************** typedef enum ConstrType /* types of co
*** 1094,1100 ****
CONSTR_ATTR_DEFERRABLE, /* attributes for previous constraint node */
CONSTR_ATTR_NOT_DEFERRABLE,
CONSTR_ATTR_DEFERRED,
! CONSTR_ATTR_IMMEDIATE
} ConstrType;
typedef struct Constraint
--- 1109,1116 ----
CONSTR_ATTR_DEFERRABLE, /* attributes for previous constraint node */
CONSTR_ATTR_NOT_DEFERRABLE,
CONSTR_ATTR_DEFERRED,
! CONSTR_ATTR_IMMEDIATE,
! CONSTR_IDENTITY
} ConstrType;
typedef struct Constraint
*************** typedef struct Constraint
*** 1108,1113 ****
--- 1124,1131 ----
List *options; /* options from WITH clause */
char *indexspace; /* index tablespace for PKEY/UNIQUE
* constraints; NULL for default */
+ bool force_default; /* GENERATED ALWAYS */
+ List *seq_opts; /* SEQUENCE options for GENERATED ... AS IDENTITY */
} Constraint;
/* ----------
diff -dcrpN pgsql.orig/src/include/nodes/plannodes.h pgsql/src/include/nodes/plannodes.h
*** pgsql.orig/src/include/nodes/plannodes.h 2007-02-25 16:14:32.000000000 +0100
--- pgsql/src/include/nodes/plannodes.h 2007-02-27 22:43:29.000000000 +0100
*************** typedef struct PlannedStmt
*** 65,70 ****
--- 65,73 ----
List *rowMarks; /* a list of RowMarkClause's */
int nParamExec; /* number of PARAM_EXEC Params used */
+
+ bool idSetToDefault; /* The table in query has an IDENTITY column
+ and it has to be set to DEFAULT */
} PlannedStmt;
/* macro for fetching the Plan associated with a SubPlan node */
diff -dcrpN pgsql.orig/src/include/utils/acl.h pgsql/src/include/utils/acl.h
*** pgsql.orig/src/include/utils/acl.h 2007-01-26 18:53:18.000000000 +0100
--- pgsql/src/include/utils/acl.h 2007-02-26 00:07:11.000000000 +0100
*************** extern Acl *aclnewowner(const Acl *old_a
*** 215,221 ****
extern AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId,
AclMode mask, AclMaskHow how);
extern int aclmembers(const Acl *acl, Oid **roleids);
!
extern bool has_privs_of_role(Oid member, Oid role);
extern bool is_member_of_role(Oid member, Oid role);
extern bool is_member_of_role_nosuper(Oid member, Oid role);
--- 215,221 ----
extern AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId,
AclMode mask, AclMaskHow how);
extern int aclmembers(const Acl *acl, Oid **roleids);
! extern int aclmemberspriv(const Acl *acl, Oid **roleids, AclMode privs, bool is_equal);
extern bool has_privs_of_role(Oid member, Oid role);
extern bool is_member_of_role(Oid member, Oid role);
extern bool is_member_of_role_nosuper(Oid member, Oid role);
*************** extern Datum hash_aclitem(PG_FUNCTION_AR
*** 245,250 ****
--- 245,251 ----
*/
extern void ExecuteGrantStmt(GrantStmt *stmt);
extern void ExecGrantStmt_oids(InternalGrant *istmt);
+ extern void ExecGrant_Sequence(Oid relOid, int attnum, Oid seqOid);
extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid,
AclMode mask, AclMaskHow how);
diff -dcrpN pgsql.orig/src/include/utils/lsyscache.h pgsql/src/include/utils/lsyscache.h
*** pgsql.orig/src/include/utils/lsyscache.h 2007-02-15 12:36:15.000000000 +0100
--- pgsql/src/include/utils/lsyscache.h 2007-02-26 00:07:11.000000000 +0100
*************** extern Oid get_opfamily_proc(Oid opfamil
*** 53,58 ****
--- 53,59 ----
int16 procnum);
extern char *get_attname(Oid relid, AttrNumber attnum);
extern char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
+ extern Oid get_relid_att_serial_sequence(Oid relid, AttrNumber attnum);
extern AttrNumber get_attnum(Oid relid, const char *attname);
extern Oid get_atttype(Oid relid, AttrNumber attnum);
extern int32 get_atttypmod(Oid relid, AttrNumber attnum);
diff -dcrpN pgsql.orig/src/test/regress/expected/identity.out pgsql/src/test/regress/expected/identity.out
*** pgsql.orig/src/test/regress/expected/identity.out 1970-01-01 01:00:00.000000000 +0100
--- pgsql/src/test/regress/expected/identity.out 2007-02-28 00:02:13.000000000 +0100
***************
*** 0 ****
--- 1,633 ----
+ --
+ -- IDENTITY
+ -- 2006.08.01 Zoltan Boszormenyi
+ --
+ --
+ -- Test GENERATED BY DEFAULT AS IDENTITY with default sequence
+ --
+ create table id (id serial generated by default as identity primary key, name text);
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "id_pkey" for table "id"
+ insert into id (name) values ('a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (0, 'a');
+ --
+ -- This must complain about UNIQUE violation
+ --
+ insert into id (id, name) values (0, 'a');
+ ERROR: duplicate key violates unique constraint "id_pkey"
+ select * from id;
+ id | name
+ ----+------
+ 1 | a
+ 2 | a
+ 3 | a
+ 4 | a
+ 0 | a
+ (5 rows)
+
+ --
+ -- This must complain because SERIAL and IDENTITY has
+ -- implicit NOT NULL constraint
+ --
+ insert into id (id, name) values (null, 'a');
+ ERROR: null value in column "id" violates not-null constraint
+ select * from id;
+ id | name
+ ----+------
+ 1 | a
+ 2 | a
+ 3 | a
+ 4 | a
+ 0 | a
+ (5 rows)
+
+ update id set id = default where id = 0;
+ select * from id;
+ id | name
+ ----+------
+ 1 | a
+ 2 | a
+ 3 | a
+ 4 | a
+ 5 | a
+ (5 rows)
+
+ drop table id;
+ --
+ -- Test GENERATED BY DEFAULT AS IDENTITY with modified sequence
+ --
+ create table id (id serial generated by default as identity(start 3) primary key, name text);
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "id_pkey" for table "id"
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (0, 'a');
+ --
+ -- This must complain about UNIQUE violation
+ --
+ insert into id (id, name) values (0, 'a');
+ ERROR: duplicate key violates unique constraint "id_pkey"
+ select * from id;
+ id | name
+ ----+------
+ 3 | a
+ 4 | a
+ 5 | a
+ 0 | a
+ (4 rows)
+
+ drop table id;
+ --
+ -- Test GENERATED ALWAYS AS IDENTITY with default sequence
+ --
+ create table id (id serial generated always as identity primary key, name text);
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "id_pkey" for table "id"
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (0, 'a');
+ insert into id (id, name) values (0, 'a');
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ id | name
+ ----+------
+ 1 | a
+ 2 | a
+ 3 | a
+ 4 | a
+ 5 | a
+ 6 | a
+ (6 rows)
+
+ --
+ -- It should update 0 rows
+ --
+ update id set name = 'b' where id = 0;
+ select * from id;
+ id | name
+ ----+------
+ 1 | a
+ 2 | a
+ 3 | a
+ 4 | a
+ 5 | a
+ 6 | a
+ (6 rows)
+
+ drop table id;
+ --
+ -- Test GENERATED ALWAYS AS IDENTITY with modified sequence
+ --
+ create table id (id serial generated always as identity(start 3) primary key, name text);
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "id_pkey" for table "id"
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (0, 'a');
+ insert into id (id, name) values (0, 'a');
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ id | name
+ ----+------
+ 3 | a
+ 4 | a
+ 5 | a
+ 6 | a
+ 7 | a
+ 8 | a
+ (6 rows)
+
+ --
+ -- It should update 0 rows
+ --
+ update id set name = 'b' where id = 0;
+ select * from id;
+ id | name
+ ----+------
+ 3 | a
+ 4 | a
+ 5 | a
+ 6 | a
+ 7 | a
+ 8 | a
+ (6 rows)
+
+ drop table id;
+ --
+ -- Test GENERATED BY DEFAULT AS (expr)
+ -- It must give a syntax error but drop it anyway.
+ --
+ create table id (id integer generated by default as (1), name text);
+ ERROR: syntax error at or near "("
+ LINE 1: ...eate table id (id integer generated by default as (1), name ...
+ ^
+ drop table id;
+ ERROR: table "id" does not exist
+ --
+ -- Test GENERATED ALWAYS AS ( expr )
+ --
+ create table id (id integer generated always as (1), name text);
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ id | name
+ ----+------
+ 1 | a
+ 1 | a
+ (2 rows)
+
+ --
+ -- It should update 0 rows
+ --
+ update id set name = 'b' where id = 0;
+ select * from id;
+ id | name
+ ----+------
+ 1 | a
+ 1 | a
+ (2 rows)
+
+ drop table id;
+ --
+ -- Test IDENTITY with non-integer columns
+ --
+ create table id (id decimal(10,2) generated always as identity(start 3), name text);
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ id | name
+ ------+------
+ 3.00 | a
+ 4.00 | a
+ (2 rows)
+
+ alter table id alter id type real;
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ id | name
+ ----+------
+ 3 | a
+ 4 | a
+ 5 | a
+ (3 rows)
+
+ alter table id alter id type integer;
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ id | name
+ ----+------
+ 3 | a
+ 4 | a
+ 5 | a
+ 6 | a
+ (4 rows)
+
+ --
+ -- It should update 0 rows
+ --
+ update id set name = 'b' where id = 0;
+ select * from id;
+ id | name
+ ----+------
+ 3 | a
+ 4 | a
+ 5 | a
+ 6 | a
+ (4 rows)
+
+ update id set name = 'b' where id = 5;
+ select * from id;
+ id | name
+ ----+------
+ 3 | a
+ 4 | a
+ 6 | a
+ 5 | b
+ (4 rows)
+
+ drop table id;
+ --
+ -- Test OVERRIDING and UPDATE on GENERATED ALWAYS columns
+ --
+ create table id (id serial generated always as identity, name text generated always as ('x'));
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ insert into id (id, name) values (0, 'a');
+ insert into id (id, name) overriding user value values (0, 'a');
+ insert into id (id, name) overriding system value values (0, 'a');
+ --
+ -- It's expected to fail because of GENERATED ALWAYS AS IDENTITY.
+ --
+ update id set id = 6 where id = 0;
+ ERROR: UPDATE prohibited on GENERATED ALWAYS AS IDENTITY attributes
+ --
+ -- It's expected to fail because of GENERATED ALWAYS AS IDENTITY.
+ --
+ update id set id = default where id = 0;
+ ERROR: UPDATE prohibited on GENERATED ALWAYS AS IDENTITY attributes
+ --
+ -- It's expected to fail because of GENERATED ALWAYS.
+ --
+ update id set name = 'b' where id = 0;
+ ERROR: UPDATE to non-default value prohibited on GENERATED ALWAYS attributes
+ --
+ -- It's expected to succeed
+ --
+ update id set name = default where id = 0;
+ --
+ -- Test ALTER TABLE sequence options
+ --
+ alter table id alter id restart with 10;
+ insert into id (id, name) values (0, 'a');
+ alter table id alter id set increment by 5;
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ id | name
+ ----+------
+ 1 | x
+ 2 | x
+ 3 | x
+ 10 | x
+ 15 | x
+ (5 rows)
+
+ --
+ -- Test ALTER TABLE RENAME
+ --
+ select pg_get_serial_sequence('id', 'id');
+ pg_get_serial_sequence
+ ------------------------
+ public.id_id_seq
+ (1 row)
+
+ alter table id rename id to di;
+ NOTICE: supporting sequence for column "di" renamed to "id_di_seq"
+ insert into id (di, name) values (0, 'a');
+ select pg_get_serial_sequence('id', 'di');
+ pg_get_serial_sequence
+ ------------------------
+ public.id_di_seq
+ (1 row)
+
+ alter table id rename to di;
+ NOTICE: supporting sequence for column "di" renamed to "di_di_seq"
+ insert into di (di, name) values (0, 'a');
+ select pg_get_serial_sequence('di', 'di');
+ pg_get_serial_sequence
+ ------------------------
+ public.di_di_seq
+ (1 row)
+
+ select * from di;
+ di | name
+ ----+------
+ 1 | x
+ 2 | x
+ 3 | x
+ 10 | x
+ 15 | x
+ 20 | x
+ 25 | x
+ (7 rows)
+
+ --
+ -- Test SET/DROP DEFAULT
+ --
+ alter table di alter di drop default;
+ ERROR: cannot alter IDENTITY column "di"
+ alter table di alter di set default 1;
+ ERROR: cannot alter IDENTITY column "di"
+ --
+ -- Test ALTER TABLE DROP COLUMN
+ --
+ alter table di add column id integer;
+ update di set id = di;
+ alter table di drop column di;
+ select * from di;
+ name | id
+ ------+----
+ x | 1
+ x | 2
+ x | 3
+ x | 10
+ x | 15
+ x | 20
+ x | 25
+ (7 rows)
+
+ --
+ -- Test privilege over the underlying sequence[s].
+ -- I use it to test for two things:
+ -- 1) DROP USER fails because objects are still referenced
+ -- 2) It doesn't crash because of overzealous
+ -- pfree()/list_free() usage.
+ --
+ create user mytestuser;
+ grant insert on di to mytestuser;
+ alter table di add id5 serial generated always as identity (start 20);
+ NOTICE: ALTER TABLE will create implicit sequence "di_id5_seq" for serial column "di.id5"
+ drop user mytestuser;
+ ERROR: role "mytestuser" cannot be dropped because some objects depend on it
+ DETAIL: access to sequence di_id5_seq
+ access to table di
+ alter table di drop id5;
+ drop user mytestuser;
+ ERROR: role "mytestuser" cannot be dropped because some objects depend on it
+ DETAIL: access to table di
+ revoke all on di from mytestuser;
+ drop user mytestuser;
+ drop table di;
+ --
+ -- Test the late generation of the IDENTITY column
+ --
+ create table id (id serial generated always as identity (start 3), t text not null);
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ insert into id (id, t) values (0, null);
+ ERROR: null value in column "t" violates not-null constraint
+ insert into id (id, t) values (0, 't');
+ insert into id (id, t) values (0, null);
+ ERROR: null value in column "t" violates not-null constraint
+ insert into id (id, t) values (0, 't');
+ select * from id;
+ id | t
+ ----+---
+ 3 | t
+ 4 | t
+ (2 rows)
+
+ drop table id;
+ --
+ -- Test multiple IDENTITY columns in a single table
+ --
+ -- This must fail, no multiple IDENTITY allowed
+ create table id (
+ id1 serial generated always as identity (start 3),
+ id2 serial generated always as identity (start 5)
+ );
+ NOTICE: CREATE TABLE will create implicit sequence "id_id1_seq" for serial column "id.id1"
+ NOTICE: CREATE TABLE will create implicit sequence "id_id2_seq" for serial column "id.id2"
+ ERROR: multiple IDENTITY columns are not allowed
+ -- This succeeds
+ create table id (id1 serial generated always as identity (start 3), t text not null);
+ NOTICE: CREATE TABLE will create implicit sequence "id_id1_seq" for serial column "id.id1"
+ insert into id (t) values (null) returning id1;
+ ERROR: null value in column "t" violates not-null constraint
+ insert into id (t) values ('a') returning id1;
+ id1
+ -----
+ 3
+ (1 row)
+
+ select * from id;
+ id1 | t
+ -----+---
+ 3 | a
+ (1 row)
+
+ -- This must fail, no multiple IDENTITY allowed
+ alter table id add id2 serial generated always as identity (start 5);
+ NOTICE: ALTER TABLE will create implicit sequence "id_id2_seq" for serial column "id.id2"
+ ERROR: multiple IDENTITY columns are not allowed
+ -- Downgrade id1 to normal serial
+ alter table id alter id1 drop identity;
+ insert into id (t) values (null) returning id1;
+ ERROR: null value in column "t" violates not-null constraint
+ insert into id (t) values ('a') returning id1;
+ id1
+ -----
+ 5
+ (1 row)
+
+ select * from id;
+ id1 | t
+ -----+---
+ 3 | a
+ 5 | a
+ (2 rows)
+
+ -- Not this succeeds
+ alter table id add id2 serial generated always as identity (start 5);
+ NOTICE: ALTER TABLE will create implicit sequence "id_id2_seq" for serial column "id.id2"
+ insert into id (t) values (null) returning id1, id2;
+ ERROR: null value in column "t" violates not-null constraint
+ insert into id (t) values ('a') returning id1, id2;
+ id1 | id2
+ -----+-----
+ 7 | 7
+ (1 row)
+
+ select * from id;
+ id1 | t | id2
+ -----+---+-----
+ 3 | a | 5
+ 5 | a | 6
+ 7 | a | 7
+ (3 rows)
+
+ -- Downgrade id2 to normal serial
+ alter table id alter id2 drop identity;
+ insert into id (t) values (null) returning id1, id2;
+ ERROR: null value in column "t" violates not-null constraint
+ insert into id (t) values ('a') returning id1, id2;
+ id1 | id2
+ -----+-----
+ 9 | 9
+ (1 row)
+
+ select * from id;
+ id1 | t | id2
+ -----+---+-----
+ 3 | a | 5
+ 5 | a | 6
+ 7 | a | 7
+ 9 | a | 9
+ (4 rows)
+
+ -- Upgrade id1 to identity
+ alter table id alter id1 set generated always as identity;
+ -- Upgrade id2 to identity, this must fail
+ alter table id alter id2 set generated always as identity;
+ ERROR: multiple IDENTITY columns are not allowed
+ select * from id;
+ id1 | t | id2
+ -----+---+-----
+ 3 | a | 5
+ 5 | a | 6
+ 7 | a | 7
+ 9 | a | 9
+ (4 rows)
+
+ drop table id;
+ --
+ -- Check for forbidden CHECK constraints
+ --
+ create table id (
+ id serial generated always as identity check (id > 3),
+ t varchar(40) generated always as ('') not null check (t <> ''));
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ ERROR: IDENTITY column "id" of table "id" cannot be referenced in CHECK constraint
+ drop table id;
+ ERROR: table "id" does not exist
+ create table id (
+ t varchar(40) generated always as ('') not null check (t <> ''),
+ id serial generated always as identity check (id > 3));
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ ERROR: GENERATED column "t" of table "id" cannot be referenced in CHECK constraint
+ drop table id;
+ ERROR: table "id" does not exist
+ create table id (
+ id serial generated always as identity,
+ t varchar(40) generated always as ('') not null,
+ check (id > 3),
+ check (t <> ''));
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ ERROR: IDENTITY column "id" of table "id" cannot be referenced in CHECK constraint
+ drop table id;
+ ERROR: table "id" does not exist
+ create table id (
+ id serial generated always as identity,
+ t varchar(40) generated always as ('') not null);
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ alter table id add check(id > 3);
+ ERROR: IDENTITY column "id" of table "id" cannot be referenced in CHECK constraint
+ alter table id add check(t <> '');
+ ERROR: GENERATED column "t" of table "id" cannot be referenced in CHECK constraint
+ alter table id add t2 text generated always as ('a') check (t2 <> '');
+ ERROR: GENERATED column "t2" of table "id" cannot be referenced in CHECK constraint
+ drop table id;
+ --
+ -- Test GENERATED columns
+ --
+ --
+ -- This should fail, IDENTITY cannot be referenced by GENERATED
+ --
+ create table id (
+ id serial generated always as identity,
+ g integer generated always as ( id + 1 ));
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ ERROR: IDENTITY column "id" of table "id" cannot be referenced by GENERATED column "g"
+ drop table id;
+ ERROR: table "id" does not exist
+ --
+ -- This should fail, GENERATED cannot be referenced by GENERATED
+ --
+ create table id (
+ id serial generated always as identity,
+ i1 integer,
+ i2 integer,
+ g1 integer generated always as ( i1 + i2 ),
+ g2 integer generated always as ( i1 + g1 ));
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ ERROR: GENERATED column "g1" of table "id" cannot be referenced by GENERATED column "g2"
+ drop table id;
+ ERROR: table "id" does not exist
+ --
+ -- Test simple expression (col1 + col2) as GENERATED column
+ --
+ --
+ -- Test INSERT with GENERATED columns
+ --
+ create table id (
+ id serial generated always as identity,
+ i1 integer,
+ i2 integer,
+ g1 integer generated always as ( i1 + i2 ));
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ --
+ -- g1 has to be 3
+ --
+ insert into id (i1, i2) values (1, 2);
+ insert into id (id, i1, i2, g1) values (default, 1, 2, default);
+ select * from id;
+ id | i1 | i2 | g1
+ ----+----+----+----
+ 1 | 1 | 2 | 3
+ 2 | 1 | 2 | 3
+ (2 rows)
+
+ --
+ -- g1 has to be recomputed as 4
+ --
+ update id set i1 = 2 where id = 1;
+ select * from id;
+ id | i1 | i2 | g1
+ ----+----+----+----
+ 2 | 1 | 2 | 3
+ 1 | 2 | 2 | 4
+ (2 rows)
+
+ drop table id;
+ --
+ -- Test complex expression as GENERATED column
+ --
+ create table id (
+ id serial generated always as identity,
+ i1 integer,
+ i2 integer,
+ g1 integer generated always as (
+ case when i1 is null and i2 is null then -1
+ when i1 is null then i2
+ when i2 is null then i1
+ else i1 + i2
+ end ));
+ NOTICE: CREATE TABLE will create implicit sequence "id_id_seq" for serial column "id.id"
+ insert into id (i1, i2) values (null, null);
+ insert into id (i1, i2) values (10, null);
+ insert into id (i1, i2) values (null, 20 );
+ insert into id (i1, i2) values (10, 20 );
+ select * from id;
+ id | i1 | i2 | g1
+ ----+----+----+----
+ 1 | | | -1
+ 2 | 10 | | 10
+ 3 | | 20 | 20
+ 4 | 10 | 20 | 30
+ (4 rows)
+
+ drop table id;
diff -dcrpN pgsql.orig/src/test/regress/parallel_schedule pgsql/src/test/regress/parallel_schedule
*** pgsql.orig/src/test/regress/parallel_schedule 2007-02-09 07:23:50.000000000 +0100
--- pgsql/src/test/regress/parallel_schedule 2007-02-26 00:07:11.000000000 +0100
***************
*** 2,8 ****
# The first group of parallel test
# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.39 2007/02/09 03:35:35 tgl Exp $
# ----------
! test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric uuid
# Depends on things setup during char, varchar and text
test: strings
--- 2,8 ----
# The first group of parallel test
# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.39 2007/02/09 03:35:35 tgl Exp $
# ----------
! test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric uuid identity
# Depends on things setup during char, varchar and text
test: strings
diff -dcrpN pgsql.orig/src/test/regress/serial_schedule pgsql/src/test/regress/serial_schedule
*** pgsql.orig/src/test/regress/serial_schedule 2007-02-09 07:23:51.000000000 +0100
--- pgsql/src/test/regress/serial_schedule 2007-02-26 00:07:11.000000000 +0100
*************** test: float8
*** 14,19 ****
--- 14,20 ----
test: bit
test: numeric
test: uuid
+ test: identity
test: strings
test: numerology
test: point
diff -dcrpN pgsql.orig/src/test/regress/sql/identity.sql pgsql/src/test/regress/sql/identity.sql
*** pgsql.orig/src/test/regress/sql/identity.sql 1970-01-01 01:00:00.000000000 +0100
--- pgsql/src/test/regress/sql/identity.sql 2007-02-28 00:01:18.000000000 +0100
***************
*** 0 ****
--- 1,318 ----
+ --
+ -- IDENTITY
+ -- 2006.08.01 Zoltan Boszormenyi
+ --
+
+ --
+ -- Test GENERATED BY DEFAULT AS IDENTITY with default sequence
+ --
+ create table id (id serial generated by default as identity primary key, name text);
+ insert into id (name) values ('a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (0, 'a');
+ --
+ -- This must complain about UNIQUE violation
+ --
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ --
+ -- This must complain because SERIAL and IDENTITY has
+ -- implicit NOT NULL constraint
+ --
+ insert into id (id, name) values (null, 'a');
+ select * from id;
+ update id set id = default where id = 0;
+ select * from id;
+ drop table id;
+ --
+ -- Test GENERATED BY DEFAULT AS IDENTITY with modified sequence
+ --
+ create table id (id serial generated by default as identity(start 3) primary key, name text);
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (0, 'a');
+ --
+ -- This must complain about UNIQUE violation
+ --
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ drop table id;
+ --
+ -- Test GENERATED ALWAYS AS IDENTITY with default sequence
+ --
+ create table id (id serial generated always as identity primary key, name text);
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (0, 'a');
+ insert into id (id, name) values (0, 'a');
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ --
+ -- It should update 0 rows
+ --
+ update id set name = 'b' where id = 0;
+ select * from id;
+ drop table id;
+ --
+ -- Test GENERATED ALWAYS AS IDENTITY with modified sequence
+ --
+ create table id (id serial generated always as identity(start 3) primary key, name text);
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (0, 'a');
+ insert into id (id, name) values (0, 'a');
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ --
+ -- It should update 0 rows
+ --
+ update id set name = 'b' where id = 0;
+ select * from id;
+ drop table id;
+ --
+ -- Test GENERATED BY DEFAULT AS (expr)
+ -- It must give a syntax error but drop it anyway.
+ --
+ create table id (id integer generated by default as (1), name text);
+ drop table id;
+ --
+ -- Test GENERATED ALWAYS AS ( expr )
+ --
+ create table id (id integer generated always as (1), name text);
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ --
+ -- It should update 0 rows
+ --
+ update id set name = 'b' where id = 0;
+ select * from id;
+ drop table id;
+ --
+ -- Test IDENTITY with non-integer columns
+ --
+ create table id (id decimal(10,2) generated always as identity(start 3), name text);
+ insert into id (id, name) values (default, 'a');
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ alter table id alter id type real;
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ alter table id alter id type integer;
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ --
+ -- It should update 0 rows
+ --
+ update id set name = 'b' where id = 0;
+ select * from id;
+ update id set name = 'b' where id = 5;
+ select * from id;
+ drop table id;
+ --
+ -- Test OVERRIDING and UPDATE on GENERATED ALWAYS columns
+ --
+ create table id (id serial generated always as identity, name text generated always as ('x'));
+ insert into id (id, name) values (0, 'a');
+ insert into id (id, name) overriding user value values (0, 'a');
+ insert into id (id, name) overriding system value values (0, 'a');
+ --
+ -- It's expected to fail because of GENERATED ALWAYS AS IDENTITY.
+ --
+ update id set id = 6 where id = 0;
+ --
+ -- It's expected to fail because of GENERATED ALWAYS AS IDENTITY.
+ --
+ update id set id = default where id = 0;
+ --
+ -- It's expected to fail because of GENERATED ALWAYS.
+ --
+ update id set name = 'b' where id = 0;
+ --
+ -- It's expected to succeed
+ --
+ update id set name = default where id = 0;
+ --
+ -- Test ALTER TABLE sequence options
+ --
+ alter table id alter id restart with 10;
+ insert into id (id, name) values (0, 'a');
+ alter table id alter id set increment by 5;
+ insert into id (id, name) values (0, 'a');
+ select * from id;
+ --
+ -- Test ALTER TABLE RENAME
+ --
+ select pg_get_serial_sequence('id', 'id');
+ alter table id rename id to di;
+ insert into id (di, name) values (0, 'a');
+ select pg_get_serial_sequence('id', 'di');
+ alter table id rename to di;
+ insert into di (di, name) values (0, 'a');
+ select pg_get_serial_sequence('di', 'di');
+ select * from di;
+ --
+ -- Test SET/DROP DEFAULT
+ --
+ alter table di alter di drop default;
+ alter table di alter di set default 1;
+ --
+ -- Test ALTER TABLE DROP COLUMN
+ --
+ alter table di add column id integer;
+ update di set id = di;
+ alter table di drop column di;
+ select * from di;
+ --
+ -- Test privilege over the underlying sequence[s].
+ -- I use it to test for two things:
+ -- 1) DROP USER fails because objects are still referenced
+ -- 2) It doesn't crash because of overzealous
+ -- pfree()/list_free() usage.
+ --
+ create user mytestuser;
+ grant insert on di to mytestuser;
+ alter table di add id5 serial generated always as identity (start 20);
+ drop user mytestuser;
+ alter table di drop id5;
+ drop user mytestuser;
+ revoke all on di from mytestuser;
+ drop user mytestuser;
+ drop table di;
+ --
+ -- Test the late generation of the IDENTITY column
+ --
+ create table id (id serial generated always as identity (start 3), t text not null);
+ insert into id (id, t) values (0, null);
+ insert into id (id, t) values (0, 't');
+ insert into id (id, t) values (0, null);
+ insert into id (id, t) values (0, 't');
+ select * from id;
+ drop table id;
+ --
+ -- Test multiple IDENTITY columns in a single table
+ --
+ -- This must fail, no multiple IDENTITY allowed
+ create table id (
+ id1 serial generated always as identity (start 3),
+ id2 serial generated always as identity (start 5)
+ );
+ -- This succeeds
+ create table id (id1 serial generated always as identity (start 3), t text not null);
+ insert into id (t) values (null) returning id1;
+ insert into id (t) values ('a') returning id1;
+ select * from id;
+ -- This must fail, no multiple IDENTITY allowed
+ alter table id add id2 serial generated always as identity (start 5);
+ -- Downgrade id1 to normal serial
+ alter table id alter id1 drop identity;
+ insert into id (t) values (null) returning id1;
+ insert into id (t) values ('a') returning id1;
+ select * from id;
+ -- Not this succeeds
+ alter table id add id2 serial generated always as identity (start 5);
+ insert into id (t) values (null) returning id1, id2;
+ insert into id (t) values ('a') returning id1, id2;
+ select * from id;
+ -- Downgrade id2 to normal serial
+ alter table id alter id2 drop identity;
+ insert into id (t) values (null) returning id1, id2;
+ insert into id (t) values ('a') returning id1, id2;
+ select * from id;
+ -- Upgrade id1 to identity
+ alter table id alter id1 set generated always as identity;
+ -- Upgrade id2 to identity, this must fail
+ alter table id alter id2 set generated always as identity;
+ select * from id;
+ drop table id;
+ --
+ -- Check for forbidden CHECK constraints
+ --
+ create table id (
+ id serial generated always as identity check (id > 3),
+ t varchar(40) generated always as ('') not null check (t <> ''));
+ drop table id;
+ create table id (
+ t varchar(40) generated always as ('') not null check (t <> ''),
+ id serial generated always as identity check (id > 3));
+ drop table id;
+ create table id (
+ id serial generated always as identity,
+ t varchar(40) generated always as ('') not null,
+ check (id > 3),
+ check (t <> ''));
+ drop table id;
+ create table id (
+ id serial generated always as identity,
+ t varchar(40) generated always as ('') not null);
+ alter table id add check(id > 3);
+ alter table id add check(t <> '');
+ alter table id add t2 text generated always as ('a') check (t2 <> '');
+ drop table id;
+ --
+ -- Test GENERATED columns
+ --
+ --
+ -- This should fail, IDENTITY cannot be referenced by GENERATED
+ --
+ create table id (
+ id serial generated always as identity,
+ g integer generated always as ( id + 1 ));
+ drop table id;
+ --
+ -- This should fail, GENERATED cannot be referenced by GENERATED
+ --
+ create table id (
+ id serial generated always as identity,
+ i1 integer,
+ i2 integer,
+ g1 integer generated always as ( i1 + i2 ),
+ g2 integer generated always as ( i1 + g1 ));
+ drop table id;
+ --
+ -- Test simple expression (col1 + col2) as GENERATED column
+ --
+ --
+ -- Test INSERT with GENERATED columns
+ --
+ create table id (
+ id serial generated always as identity,
+ i1 integer,
+ i2 integer,
+ g1 integer generated always as ( i1 + i2 ));
+ --
+ -- g1 has to be 3
+ --
+ insert into id (i1, i2) values (1, 2);
+ insert into id (id, i1, i2, g1) values (default, 1, 2, default);
+ select * from id;
+ --
+ -- g1 has to be recomputed as 4
+ --
+ update id set i1 = 2 where id = 1;
+ select * from id;
+ drop table id;
+ --
+ -- Test complex expression as GENERATED column
+ --
+ create table id (
+ id serial generated always as identity,
+ i1 integer,
+ i2 integer,
+ g1 integer generated always as (
+ case when i1 is null and i2 is null then -1
+ when i1 is null then i2
+ when i2 is null then i1
+ else i1 + i2
+ end ));
+ insert into id (i1, i2) values (null, null);
+ insert into id (i1, i2) values (10, null);
+ insert into id (i1, i2) values (null, 20 );
+ insert into id (i1, i2) values (10, 20 );
+ select * from id;
+ drop table id;