diff -dcrpN pgsql.orig/doc/src/sgml/catalogs.sgml pgsql/doc/src/sgml/catalogs.sgml
*** pgsql.orig/doc/src/sgml/catalogs.sgml 2007-04-04 10:10:45.000000000 +0200
--- pgsql/doc/src/sgml/catalogs.sgml 2007-04-04 12:57:20.000000000 +0200
***************
*** 974,979 ****
--- 974,998 ----
+
+ attidentity
+ bool
+
+
+ This column is an IDENTITY column.
+
+
+
+
+ attgenerated
+ 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-04-04 10:10:47.000000000 +0200
--- pgsql/doc/src/sgml/datatype.sgml 2007-04-04 12:57:20.000000000 +0200
*************** 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.
+
+
+
+ Sequence generation options can also 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 an explicit value.
+ With GENERATED ALWAYS, the sequence
+ generation cannot be suppressed, the explicitly 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. 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. The expression is not limited to constants
+ as with the DEFAULT clause, instead it may use the same
+ range of expressions as the CHECK clause.
+
+
+ CREATE TABLE tablename (
+ colname coltype
+ GENERATED ALWAYS AS ( expression )
+ );
+
+
+
+
+ The value of the generated column is
+ computed after all other (regular) columns are assigned
+ with their values but before the identity
+ column's next serial value is computed. A generated
+ column cannot reference other generated columns.
+
+
+
+ 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-03-23 12:16:52.000000000 +0100
--- pgsql/doc/src/sgml/ref/alter_table.sgml 2007-04-04 12:57:20.000000000 +0200
*************** 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
*** 124,129 ****
--- 126,152 ----
+ 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
*** 385,390 ****
--- 408,420 ----
(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
*** 688,694 ****
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.
--- 718,725 ----
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-04-04 12:57:20.000000000 +0200
*************** 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-04-04 12:57:20.000000000 +0200
*************** 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-04-04 12:57:20.000000000 +0200
*************** 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 attnum))));
! }
! }
! }
!
! StoreAttrDefault(rel, colDef->attnum, nodeToString(expr), colDef->is_identity, colDef->is_generated);
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_DEFAULT;
cooked->name = NULL;
cooked->attnum = colDef->attnum;
cooked->expr = expr;
+ cooked->is_generated = colDef->is_generated;
cookedConstraints = lappend(cookedConstraints, cooked);
}
*************** cookDefault(ParseState *pstate,
*** 1799,1805 ****
Node *raw_default,
Oid atttypid,
int32 atttypmod,
! char *attname)
{
Node *expr;
--- 1857,1864 ----
Node *raw_default,
Oid atttypid,
int32 atttypmod,
! char *attname,
! bool is_generated)
{
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")));
--- 1872,1878 ----
/*
* Make sure default expr does not refer to any vars.
*/
! if (!is_generated && 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-03-30 09:33:53.000000000 +0200
--- pgsql/src/backend/catalog/index.c 2007-04-04 12:57:20.000000000 +0200
*************** ConstructTupleDescriptor(Relation heapRe
*** 166,171 ****
--- 166,173 ----
to->atthasdef = false;
to->attislocal = true;
to->attinhcount = 0;
+ to->attidentity = false;
+ to->attgenerated = 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-03-30 09:33:54.000000000 +0200
--- pgsql/src/backend/commands/copy.c 2007-04-04 14:20:49.000000000 +0200
***************
*** 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
*** 103,108 ****
--- 104,110 ----
QueryDesc *queryDesc; /* executable query to copy from */
List *attnumlist; /* integer list of attnums to copy */
char *filename; /* filename, or NULL for STDIN/STDOUT */
+ bool overriding; /* OVERRIDING SYSTEM VALUE */
bool binary; /* binary format? */
bool oids; /* include OIDs? */
bool csv_mode; /* Comma Separated Value format? */
*************** DoCopy(const CopyStmt *stmt, const char
*** 1124,1129 ****
--- 1126,1132 ----
cstate->copy_dest = COPY_FILE; /* default */
cstate->filename = stmt->filename;
+ cstate->overriding = stmt->overriding; /* OVERRIDING SYSTEM VALUE */
if (is_from)
CopyFrom(cstate); /* copy from file to database */
*************** CopyFrom(CopyState cstate)
*** 1626,1631 ****
--- 1629,1635 ----
Oid in_func_oid;
Datum *values;
char *nulls;
+ char *replace;
int nfields;
char **field_strings;
bool done = false;
*************** CopyFrom(CopyState cstate)
*** 1642,1647 ****
--- 1646,1652 ----
CommandId mycid = GetCurrentCommandId();
bool use_wal = true; /* by default, use WAL logging */
bool use_fsm = true; /* by default, use FSM for free space */
+ bool hasgenerated;
Assert(cstate->rel);
*************** CopyFrom(CopyState cstate)
*** 1765,1770 ****
--- 1770,1776 ----
slot = MakeSingleTupleTableSlot(tupDesc);
econtext = GetPerTupleExprContext(estate);
+ econtext->ecxt_scantuple = slot;
/*
* Pick up the required catalog information for each attribute in the
*************** CopyFrom(CopyState cstate)
*** 1777,1782 ****
--- 1783,1789 ----
defmap = (int *) palloc(num_phys_attrs * sizeof(int));
defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
+ hasgenerated = false;
for (attnum = 1; attnum <= num_phys_attrs; attnum++)
{
/* We don't need info for dropped attributes */
*************** CopyFrom(CopyState cstate)
*** 1793,1799 ****
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 */
--- 1800,1808 ----
fmgr_info(in_func_oid, &in_functions[attnum - 1]);
/* Get default info if needed */
! if (!list_member_int(cstate->attnumlist, attnum) ||
! attr[attnum - 1]->attidentity ||
! attr[attnum - 1]->attgenerated)
{
/* attribute is NOT to be copied from input */
/* use default value if one exists */
*************** CopyFrom(CopyState cstate)
*** 1806,1811 ****
--- 1815,1823 ----
defmap[num_defaults] = attnum - 1;
num_defaults++;
}
+
+ hasgenerated |= attr[attnum - 1]->attgenerated &&
+ !attr[attnum - 1]->attidentity;
}
}
*************** CopyFrom(CopyState cstate)
*** 1870,1875 ****
--- 1882,1888 ----
values = (Datum *) palloc(num_phys_attrs * sizeof(Datum));
nulls = (char *) palloc(num_phys_attrs * sizeof(char));
+ replace = (char *) palloc(num_phys_attrs * sizeof(char));
/* create workspace for CopyReadAttributes results */
nfields = file_has_oids ? (attr_count + 1) : attr_count;
*************** CopyFrom(CopyState cstate)
*** 2060,2069 ****
/*
* Now compute and insert any defaults available for the columns not
* provided by the input data. Anything not processed here or above
! * will remain NULL.
*/
for (i = 0; i < num_defaults; i++)
{
values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
&isnull, NULL);
if (!isnull)
--- 2073,2091 ----
/*
* Now compute and insert any defaults available for the columns not
* provided by the input data. Anything not processed here or above
! * will remain NULL. Skip GENERATED fields until the next phase.
! * Skip the IDENTITY field if the stream contains non-NULL value
! * and we got OVERRIDING SYSTEM VALUE.
*/
for (i = 0; i < num_defaults; i++)
{
+ if (attr[defmap[i]]->attgenerated &&
+ !attr[defmap[i]]->attidentity)
+ continue;
+ if (attr[defmap[i]]->attidentity &&
+ nulls[defmap[i]] == ' ' &&
+ cstate->overriding)
+ continue;
values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
&isnull, NULL);
if (!isnull)
*************** CopyFrom(CopyState cstate)
*** 2073,2078 ****
--- 2095,2127 ----
/* And now we can form the input tuple. */
tuple = heap_formtuple(tupDesc, values, nulls);
+ /*
+ * Generate DEFAULTs for GENERATED columns after all regular columns.
+ */
+ if (hasgenerated)
+ {
+ ExecStoreTuple(tuple, slot, InvalidBuffer, false);
+ MemSet(replace, ' ', num_phys_attrs * sizeof(char));
+ for (i = 0; i < num_defaults; i++)
+ {
+ if (attr[defmap[i]]->attgenerated &&
+ !attr[defmap[i]]->attidentity &&
+ (!cstate->overriding || nulls[defmap[i]] == 'n'))
+ {
+ values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
+ &isnull, NULL);
+ if (!isnull)
+ nulls[defmap[i]] = ' ';
+ replace[defmap[i]] = 'r';
+ }
+ }
+ tuple = heap_modifytuple(tuple,
+ tupDesc,
+ values,
+ nulls,
+ replace);
+ }
+
if (cstate->oids && file_has_oids)
HeapTupleSetOid(tuple, loaded_oid);
*************** CopyFrom(CopyState cstate)
*** 2138,2143 ****
--- 2187,2193 ----
pfree(values);
pfree(nulls);
+ pfree(replace);
pfree(field_strings);
pfree(in_functions);
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-04-04 14:24:03.000000000 +0200
*************** DefineSequence(CreateSeqStmt *seq)
*** 129,134 ****
--- 129,136 ----
coldef->raw_default = NULL;
coldef->cooked_default = NULL;
coldef->constraints = NIL;
+ coldef->is_identity = false;
+ coldef->is_generated = false;
null[i - 1] = ' ';
diff -dcrpN pgsql.orig/src/backend/commands/tablecmds.c pgsql/src/backend/commands/tablecmds.c
*** pgsql.orig/src/backend/commands/tablecmds.c 2007-03-23 12:17:08.000000000 +0100
--- pgsql/src/backend/commands/tablecmds.c 2007-04-04 12:57:20.000000000 +0200
***************
*** 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"
***************
*** 44,49 ****
--- 45,51 ----
#include "optimizer/clauses.h"
#include "optimizer/plancat.h"
#include "optimizer/prep.h"
+ #include "optimizer/var.h"
#include "parser/analyze.h"
#include "parser/gramparse.h"
#include "parser/parse_clause.h"
*************** static void StoreCatalogInheritance1(Oid
*** 174,179 ****
--- 176,182 ----
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 ATExecEnableDisableRule(Rela
*** 259,264 ****
--- 262,269 ----
char fires_when);
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 is_generated);
static void copy_relation_data(Relation rel, SMgrRelation dst);
*************** DefineRelation(CreateStmt *stmt, char re
*** 287,292 ****
--- 292,298 ----
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
*** 366,371 ****
--- 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
*** 480,485 ****
--- 501,508 ----
rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
rawEnt->attnum = attnum;
rawEnt->raw_default = colDef->raw_default;
+ rawEnt->is_identity = colDef->is_identity;
+ rawEnt->is_generated = colDef->is_generated;
rawDefaults = lappend(rawDefaults, rawEnt);
}
}
*************** MergeAttributes(List *schema, List *supe
*** 931,936 ****
--- 954,961 ----
def->raw_default = NULL;
def->cooked_default = NULL;
def->constraints = NIL;
+ def->is_identity = false;
+ def->is_generated = false;
inhSchema = lappend(inhSchema, def);
newattno[parent_attno - 1] = ++child_attno;
}
*************** MergeAttributes(List *schema, List *supe
*** 975,980 ****
--- 1000,1007 ----
def->cooked_default = bogus_marker;
have_bogus_defaults = true;
}
+ def->is_identity = attribute->attidentity;
+ def->is_generated = attribute->attgenerated;
}
}
*************** MergeAttributes(List *schema, List *supe
*** 1065,1070 ****
--- 1092,1099 ----
{
def->raw_default = newdef->raw_default;
def->cooked_default = newdef->cooked_default;
+ def->is_identity = newdef->is_identity;
+ def->is_generated = newdef->is_generated;
}
}
else
*************** setRelhassubclassInRelation(Oid relation
*** 1409,1414 ****
--- 1438,1471 ----
}
+ 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);
+ ereport(NOTICE,
+ (errmsg("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,
*** 1611,1616 ****
--- 1668,1679 ----
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
*** 1632,1637 ****
--- 1695,1701 ----
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
*** 1679,1684 ****
--- 1743,1757 ----
/* 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
*** 1971,1976 ****
--- 2044,2052 ----
case AT_DisableRule:
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
*** 2193,2198 ****
--- 2269,2283 ----
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->is_generated);
+ 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
*** 2952,2957 ****
--- 3037,3052 ----
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
*** 3059,3064 ****
--- 3154,3161 ----
attribute->attisdropped = false;
attribute->attislocal = colDef->is_local;
attribute->attinhcount = colDef->inhcount;
+ attribute->attidentity = colDef->is_identity;
+ attribute->attgenerated = colDef->is_generated;
ReleaseSysCache(typeTuple);
*************** ATExecAddColumn(AlteredTableInfo *tab, R
*** 3096,3101 ****
--- 3193,3200 ----
rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
rawEnt->attnum = attribute->attnum;
rawEnt->raw_default = copyObject(colDef->raw_default);
+ rawEnt->is_identity = colDef->is_identity;
+ rawEnt->is_generated = colDef->is_generated;
/*
* This function is intended for CREATE TABLE, so it processes a
*************** ATExecColumnDefault(Relation rel, const
*** 3353,3358 ****
--- 3452,3469 ----
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]->attgenerated)
+ 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
*** 3368,3373 ****
--- 3479,3486 ----
rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
rawEnt->attnum = attnum;
rawEnt->raw_default = newDefault;
+ rawEnt->is_identity = false;
+ rawEnt->is_generated = false;
/*
* This function is intended for CREATE TABLE, so it processes a
*************** ATExecDropColumn(Relation rel, const cha
*** 3549,3554 ****
--- 3662,3668 ----
DropBehavior behavior,
bool recurse, bool recursing)
{
+ TupleDesc tupleDesc;
HeapTuple tuple;
Form_pg_attribute targetatt;
AttrNumber attnum;
*************** ATExecDropColumn(Relation rel, const cha
*** 3678,3683 ****
--- 3792,3851 ----
}
/*
+ * Check for GENERATED columns that reference this column
+ */
+ tupleDesc = RelationGetDescr(rel);
+ if (attnum >= 1 &&
+ !tupleDesc->attrs[attnum - 1]->attidentity &&
+ !tupleDesc->attrs[attnum - 1]->attgenerated)
+ {
+ ParseState *pstate;
+ RangeTblEntry *rte;
+ int gen_attnum;
+ int varno;
+ int sublevels_up;
+
+ pstate = make_parsestate(NULL);
+ rte = addRangeTableEntryForRelation(pstate,
+ rel,
+ NULL,
+ false,
+ true);
+ addRTEtoQuery(pstate, rte, true, true, true);
+ varno = RTERangeTablePosn(pstate, rte, &sublevels_up);
+
+ for (gen_attnum = 1; gen_attnum <= tupleDesc->natts; gen_attnum++)
+ {
+ if (tupleDesc->attrs[gen_attnum - 1]->attisdropped)
+ continue;
+ if (tupleDesc->attrs[gen_attnum - 1]->attgenerated &&
+ !tupleDesc->attrs[gen_attnum - 1]->attidentity)
+ {
+ Node *expr;
+ Node *var;
+ expr = build_column_default(rel, gen_attnum);
+ var = scanRTEForColumn(pstate,
+ rte,
+ NameStr(tupleDesc->attrs[attnum - 1]->attname),
+ -1);
+ if (contain_var_reference(expr, varno, ((Var *)var)->varattno, sublevels_up))
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_WARNING),
+ errmsg("GENERATED column \"%s\" of relation \"%s\" referencing column \"%s\" was dropped",
+ NameStr(tupleDesc->attrs[gen_attnum - 1]->attname),
+ RelationGetRelationName(rel),
+ colName)));
+ ATExecDropColumn(rel,
+ NameStr(tupleDesc->attrs[gen_attnum - 1]->attname),
+ DROP_CASCADE,
+ false, false);
+ }
+ }
+ }
+ }
+
+ /*
* Perform the actual column deletion
*/
object.classId = RelationRelationId;
*************** ATExecAlterColumnType(AlteredTableInfo *
*** 4837,4842 ****
--- 5005,5012 ----
ScanKeyData key[3];
SysScanDesc scan;
HeapTuple depTup;
+ bool attidentity;
+ bool attgenerated;
attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
*************** ATExecAlterColumnType(AlteredTableInfo *
*** 4894,4899 ****
--- 5064,5071 ----
}
else
defaultexpr = NULL;
+ attidentity = attTup->attidentity;
+ attgenerated = attTup->attgenerated;
/*
* Find everything that depends on the column (constraints, indexes, etc),
*************** ATExecAlterColumnType(AlteredTableInfo *
*** 5142,5148 ****
*/
RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true);
! StoreAttrDefault(rel, attnum, nodeToString(defaultexpr));
}
/* Cleanup */
--- 5314,5320 ----
*/
RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true);
! StoreAttrDefault(rel, attnum, nodeToString(defaultexpr), attidentity, attgenerated);
}
/* Cleanup */
*************** decompile_conbin(HeapTuple contup, Tuple
*** 6080,6085 ****
--- 6252,6415 ----
}
/*
+ * 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 is_generated)
+ {
+ Oid tableOid;
+ Relation tableRel;
+ AttrNumber idattnum;
+ Oid sequenceId;
+ TupleDesc tupleDesc;
+ Relation attrelation;
+ HeapTuple atttup;
+ Form_pg_attribute attform;
+ int attnum;
+
+ tableOid = RelationGetRelid(rel);
+ tableRel = heap_open(tableOid, AccessExclusiveLock);
+
+ attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
+
+ atttup = SearchSysCacheCopyAttName(tableOid, column);
+ if (!HeapTupleIsValid(atttup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ column, RelationGetRelationName(rel))));
+
+ attform = (Form_pg_attribute) GETSTRUCT(atttup);
+
+ idattnum = attform->attnum;
+ if (idattnum <= 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot modify system column \"%s\"",
+ column)));
+
+ if (attform->attgenerated && !attform->attidentity)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("column \"%s\" of relation \"%s\" is a GENERATED column",
+ column, RelationGetRelationName(rel))));
+
+ if (is_identity)
+ {
+ tupleDesc = RelationGetDescr(rel);
+
+ for (attnum = 1; attnum <= tupleDesc->natts; attnum++)
+ {
+ if (tupleDesc->attrs[attnum - 1]->attisdropped)
+ continue;
+ if (idattnum != attnum &&
+ tupleDesc->attrs[attnum - 1]->attidentity)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("multiple IDENTITY columns are not allowed")));
+ }
+ } else
+ is_generated = false;
+
+ sequenceId = get_relid_att_serial_sequence(tableOid, idattnum);
+
+ if (!OidIsValid(sequenceId))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not have an associated sequence",
+ column, RelationGetRelationName(rel))));
+
+ if (is_identity && attform->attidentity)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("column \"%s\" of relation \"%s\" is an IDENTITY column",
+ column, RelationGetRelationName(rel))));
+
+ if (!is_identity && !attform->attidentity)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("column \"%s\" of relation \"%s\" is a non-IDENTITY serial column",
+ column, RelationGetRelationName(rel))));
+
+ /* Modify IDENTITY properties */
+ attform->attidentity = is_identity;
+ attform->attgenerated = is_generated;
+ simple_heap_update(attrelation, &atttup->t_self, atttup);
+
+ /* keep system catalog indexes current */
+ CatalogUpdateIndexes(attrelation, atttup);
+
+ heap_freetuple(atttup);
+
+ heap_close(attrelation, RowExclusiveLock);
+
+ CommandCounterIncrement();
+
+ heap_close(rel, NoLock);
+ }
+
+ /*
* 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-04-04 10:11:12.000000000 +0200
--- pgsql/src/backend/commands/typecmds.c 2007-04-04 12:57:20.000000000 +0200
*************** DefineDomain(CreateDomainStmt *stmt)
*** 730,736 ****
defaultExpr = cookDefault(pstate, constr->raw_expr,
basetypeoid,
basetypeMod,
! domainName);
/*
* Expression must be stored as a nodeToString result, but we
--- 730,737 ----
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
*** 1391,1397 ****
defaultExpr = cookDefault(pstate, defaultRaw,
typTup->typbasetype,
typTup->typtypmod,
! NameStr(typTup->typname));
/*
* Expression must be stored as a nodeToString result, but we also
--- 1392,1399 ----
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-03-13 11:39:31.000000000 +0100
--- pgsql/src/backend/commands/view.c 2007-04-04 12:57:20.000000000 +0200
*************** DefineVirtualRelation(const RangeVar *re
*** 127,132 ****
--- 127,134 ----
def->raw_default = NULL;
def->cooked_default = NULL;
def->constraints = NIL;
+ def->is_identity = false;
+ def->is_generated = 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-03-30 09:33:54.000000000 +0200
--- pgsql/src/backend/executor/execMain.c 2007-04-04 13:54:14.000000000 +0200
***************
*** 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 void ExecDelete(ItemPointer tuple
*** 87,92 ****
--- 90,98 ----
static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
TupleTableSlot *planSlot,
DestReceiver *dest, EState *estate);
+ static HeapTuple ExecGenerated(TupleTableSlot *slot,
+ HeapTuple tuple,
+ EState *estate);
static void ExecProcessReturning(ProjectionInfo *projectReturning,
TupleTableSlot *tupleSlot,
TupleTableSlot *planSlot,
*************** ExecInsert(TupleTableSlot *slot,
*** 1395,1400 ****
--- 1401,1408 ----
}
}
+ tuple = ExecGenerated(slot, tuple, estate);
+
/*
* Check the constraints of the tuple
*/
*************** ExecUpdate(TupleTableSlot *slot,
*** 1638,1643 ****
--- 1646,1656 ----
}
/*
+ * Fill in the GENERATED columns
+ */
+ tuple = ExecGenerated(slot, tuple, estate);
+
+ /*
* Check the constraints of the tuple
*
* If we generate a new candidate tuple after EvalPlanQual testing, we
*************** ExecConstraints(ResultRelInfo *resultRel
*** 1831,1836 ****
--- 1844,1927 ----
}
/*
+ * ExecGenerated --- evaluate GENERATED columns
+ */
+ static HeapTuple
+ ExecGenerated(TupleTableSlot *slot, HeapTuple tuple, EState *estate)
+ {
+ ResultRelInfo *resultRelInfo;
+ Relation resultRelationDesc;
+ TupleDesc tupleDesc;
+ ExprContext *econtext;
+ ExprState *exprstate;
+ int attnum;
+ Datum *values;
+ bool *isnull;
+ bool *replace;
+
+ resultRelInfo = estate->es_result_relation_info;
+ resultRelationDesc = resultRelInfo->ri_RelationDesc;
+
+ tupleDesc = resultRelationDesc->rd_att;
+
+ values = palloc0(tupleDesc->natts * sizeof(Datum));
+ isnull = palloc0(tupleDesc->natts * sizeof(bool));
+ replace= palloc0(tupleDesc->natts * sizeof(bool));
+
+ econtext = GetPerTupleExprContext(estate);
+ econtext->ecxt_scantuple = slot;
+
+ for (attnum = 1; attnum <= tupleDesc->natts; attnum++)
+ {
+ Form_pg_attribute att_tup = tupleDesc->attrs[attnum - 1];
+
+ if (att_tup->attisdropped)
+ continue;
+ if (att_tup->attgenerated && !att_tup->attidentity)
+ {
+ 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 = ExecEvalExpr(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);
+
+ ResetPerTupleExprContext(estate);
+
+ pfree(values);
+ pfree(isnull);
+ pfree(replace);
+ return tuple;
+ }
+
+ /*
* ExecProcessReturning --- evaluate a RETURNING list and send to dest
*
* projectReturning: RETURNING projection info for current result rel
diff -dcrpN pgsql.orig/src/backend/nodes/copyfuncs.c pgsql/src/backend/nodes/copyfuncs.c
*** pgsql.orig/src/backend/nodes/copyfuncs.c 2007-04-04 10:11:16.000000000 +0200
--- pgsql/src/backend/nodes/copyfuncs.c 2007-04-04 13:55:00.000000000 +0200
*************** _copyColumnDef(ColumnDef *from)
*** 1754,1759 ****
--- 1754,1761 ----
COPY_NODE_FIELD(raw_default);
COPY_STRING_FIELD(cooked_default);
COPY_NODE_FIELD(constraints);
+ COPY_SCALAR_FIELD(is_identity);
+ COPY_SCALAR_FIELD(is_generated);
return newnode;
}
*************** _copyConstraint(Constraint *from)
*** 1770,1775 ****
--- 1772,1779 ----
COPY_NODE_FIELD(keys);
COPY_NODE_FIELD(options);
COPY_STRING_FIELD(indexspace);
+ COPY_SCALAR_FIELD(is_generated);
+ COPY_NODE_FIELD(seq_opts);
return newnode;
}
*************** _copyQuery(Query *from)
*** 1834,1839 ****
--- 1838,1844 ----
COPY_NODE_FIELD(limitCount);
COPY_NODE_FIELD(rowMarks);
COPY_NODE_FIELD(setOperations);
+ COPY_SCALAR_FIELD(commandOverride);
return newnode;
}
*************** _copyInsertStmt(InsertStmt *from)
*** 1847,1852 ****
--- 1852,1858 ----
COPY_NODE_FIELD(cols);
COPY_NODE_FIELD(selectStmt);
COPY_NODE_FIELD(returningList);
+ COPY_SCALAR_FIELD(commandOverride);
return newnode;
}
*************** _copyAlterTableCmd(AlterTableCmd *from)
*** 1940,1945 ****
--- 1946,1952 ----
COPY_NODE_FIELD(def);
COPY_NODE_FIELD(transform);
COPY_SCALAR_FIELD(behavior);
+ COPY_SCALAR_FIELD(is_generated);
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-04-04 10:11:16.000000000 +0200
--- pgsql/src/backend/nodes/equalfuncs.c 2007-04-04 13:55:23.000000000 +0200
*************** _equalQuery(Query *a, Query *b)
*** 737,742 ****
--- 737,743 ----
COMPARE_NODE_FIELD(limitCount);
COMPARE_NODE_FIELD(rowMarks);
COMPARE_NODE_FIELD(setOperations);
+ COMPARE_SCALAR_FIELD(commandOverride);
return true;
}
*************** _equalInsertStmt(InsertStmt *a, InsertSt
*** 748,753 ****
--- 749,755 ----
COMPARE_NODE_FIELD(cols);
COMPARE_NODE_FIELD(selectStmt);
COMPARE_NODE_FIELD(returningList);
+ COMPARE_SCALAR_FIELD(commandOverride);
return true;
}
*************** _equalAlterTableCmd(AlterTableCmd *a, Al
*** 829,834 ****
--- 831,837 ----
COMPARE_NODE_FIELD(def);
COMPARE_NODE_FIELD(transform);
COMPARE_SCALAR_FIELD(behavior);
+ COMPARE_SCALAR_FIELD(is_generated);
return true;
}
*************** _equalColumnDef(ColumnDef *a, ColumnDef
*** 1765,1770 ****
--- 1768,1775 ----
COMPARE_NODE_FIELD(raw_default);
COMPARE_STRING_FIELD(cooked_default);
COMPARE_NODE_FIELD(constraints);
+ COMPARE_SCALAR_FIELD(is_identity);
+ COMPARE_SCALAR_FIELD(is_generated);
return true;
}
*************** _equalConstraint(Constraint *a, Constrai
*** 1779,1784 ****
--- 1784,1791 ----
COMPARE_NODE_FIELD(keys);
COMPARE_NODE_FIELD(options);
COMPARE_STRING_FIELD(indexspace);
+ COMPARE_SCALAR_FIELD(is_generated);
+ 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-03-28 17:16:12.000000000 +0200
--- pgsql/src/backend/nodes/outfuncs.c 2007-04-04 14:02:19.000000000 +0200
*************** _outColumnDef(StringInfo str, ColumnDef
*** 1620,1625 ****
--- 1620,1627 ----
WRITE_NODE_FIELD(raw_default);
WRITE_STRING_FIELD(cooked_default);
WRITE_NODE_FIELD(constraints);
+ WRITE_BOOL_FIELD(is_identity);
+ WRITE_BOOL_FIELD(is_generated);
}
static void
*************** _outQuery(StringInfo str, Query *node)
*** 1709,1714 ****
--- 1711,1717 ----
WRITE_NODE_FIELD(limitCount);
WRITE_NODE_FIELD(rowMarks);
WRITE_NODE_FIELD(setOperations);
+ WRITE_BOOL_FIELD(commandOverride);
}
static void
*************** _outConstraint(StringInfo str, Constrain
*** 1973,1984 ****
--- 1976,1993 ----
appendStringInfo(str, "DEFAULT");
WRITE_NODE_FIELD(raw_expr);
WRITE_STRING_FIELD(cooked_expr);
+ WRITE_BOOL_FIELD(is_generated);
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-03-28 17:16:12.000000000 +0200
--- pgsql/src/backend/nodes/readfuncs.c 2007-04-04 13:56:00.000000000 +0200
*************** _readQuery(void)
*** 154,159 ****
--- 154,160 ----
READ_NODE_FIELD(limitCount);
READ_NODE_FIELD(rowMarks);
READ_NODE_FIELD(setOperations);
+ READ_BOOL_FIELD(commandOverride);
READ_DONE();
}
diff -dcrpN pgsql.orig/src/backend/parser/analyze.c pgsql/src/backend/parser/analyze.c
*** pgsql.orig/src/backend/parser/analyze.c 2007-03-13 11:39:44.000000000 +0100
--- pgsql/src/backend/parser/analyze.c 2007-04-04 12:57:20.000000000 +0200
*************** transformInsertStmt(ParseState *pstate,
*** 453,458 ****
--- 453,459 ----
ListCell *lc;
qry->commandType = CMD_INSERT;
+ qry->commandOverride = stmt->commandOverride;
pstate->p_is_insert = true;
/*
*************** transformColumnDefinition(ParseState *ps
*** 940,945 ****
--- 941,949 ----
bool saw_nullable;
Constraint *constraint;
ListCell *clist;
+ bool saw_identity;
+ bool is_generated;
+ List *seq_opts;
cxt->columns = lappend(cxt->columns, column);
*************** transformColumnDefinition(ParseState *ps
*** 965,975 ****
}
}
/* Do necessary work on the column type declaration */
transformColumnType(pstate, column);
! /* Special actions for SERIAL pseudo-types */
! if (is_serial)
{
Oid snamespaceid;
char *snamespace;
--- 969,1003 ----
}
}
+ /* Check for GENERATED ... AS IDENTITY constructs */
+ saw_identity = false;
+ is_generated = 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;
+ is_generated = constraint->is_generated;
+ 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
*** 1011,1017 ****
*/
seqstmt = makeNode(CreateSeqStmt);
seqstmt->sequence = makeRangeVar(snamespace, sname);
! seqstmt->options = NIL;
cxt->blist = lappend(cxt->blist, seqstmt);
--- 1039,1045 ----
*/
seqstmt = makeNode(CreateSeqStmt);
seqstmt->sequence = makeRangeVar(snamespace, sname);
! seqstmt->options = seq_opts;
cxt->blist = lappend(cxt->blist, seqstmt);
*************** transformColumnDefinition(ParseState *ps
*** 1057,1062 ****
--- 1085,1091 ----
constraint->raw_expr = (Node *) funccallnode;
constraint->cooked_expr = NULL;
constraint->keys = NIL;
+ constraint->is_generated = is_generated;
column->constraints = lappend(column->constraints, constraint);
constraint = makeNode(Constraint);
*************** transformColumnDefinition(ParseState *ps
*** 1118,1126 ****
--- 1147,1159 ----
errmsg("multiple default values specified for column \"%s\" of table \"%s\"",
column->colname, cxt->relation->relname)));
column->raw_default = constraint->raw_expr;
+ is_generated = constraint->is_generated;
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
*** 1145,1150 ****
--- 1178,1185 ----
break;
}
}
+ column->is_identity = saw_identity;
+ column->is_generated = is_generated;
}
static void
*************** transformInhRelation(ParseState *pstate,
*** 1293,1298 ****
--- 1328,1335 ----
def->raw_default = NULL;
def->cooked_default = NULL;
def->constraints = NIL;
+ def->is_identity = false;
+ def->is_generated = false;
/*
* Add to column list
*************** transformInhRelation(ParseState *pstate,
*** 1327,1332 ****
--- 1364,1371 ----
*/
def->cooked_default = pstrdup(this_default);
+ def->is_identity = attribute->attidentity;
+ def->is_generated = attribute->attgenerated;
}
}
diff -dcrpN pgsql.orig/src/backend/parser/gram.y pgsql/src/backend/parser/gram.y
*** pgsql.orig/src/backend/parser/gram.y 2007-04-04 10:11:20.000000000 +0200
--- pgsql/src/backend/parser/gram.y 2007-04-04 12:57:20.000000000 +0200
*************** static Node *makeXmlExpr(XmlExprOp op, c
*** 286,292 ****
%type fetch_direction select_limit_value select_offset_value
! %type OptSeqList
%type OptSeqElem
%type insert_rest
--- 286,292 ----
%type fetch_direction select_limit_value select_offset_value
! %type OptSeqList SeqList
%type OptSeqElem
%type insert_rest
*************** static Node *makeXmlExpr(XmlExprOp op, c
*** 314,319 ****
--- 314,320 ----
%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
*** 341,346 ****
--- 342,349 ----
%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
*** 390,400 ****
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
--- 393,403 ----
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
*** 414,420 ****
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
--- 417,423 ----
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:
*** 1411,1416 ****
--- 1414,1450 ----
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->is_generated = $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:
*** 1651,1656 ****
--- 1685,1695 ----
| /* EMPTY */ { $$ = NULL; }
;
+ SetIdentityAlwaysByDefault:
+ ALWAYS { $$ = true; }
+ | BY DEFAULT { $$ = false; }
+ ;
+
/*****************************************************************************
*************** ClosePortalStmt:
*** 1684,1698 ****
*
*****************************************************************************/
! 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 */
--- 1723,1738 ----
*
*****************************************************************************/
! 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
*** 1700,1709 ****
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
--- 1740,1749 ----
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
*** 1905,1910 ****
--- 1945,1952 ----
n->typename = $2;
n->constraints = $3;
n->is_local = true;
+ n->is_identity = false;
+ n->is_generated = false;
$$ = (Node *)n;
}
;
*************** ColConstraintElem:
*** 2046,2051 ****
--- 2088,2152 ----
n->initdeferred = FALSE;
$$ = (Node *)n;
}
+ | GENERATED AlwaysByDefault
+ {
+ $$ = $2;
+ }
+ ;
+
+ AlwaysByDefault:
+ BY DEFAULT AS IDENTITY IdentitySpec { $$ = $5; }
+ | ALWAYS AS IdentityGenerated
+ {
+ Constraint *n = (Constraint *)$3;
+ n->is_generated = 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:
*** 2358,2363 ****
--- 2459,2466 ----
n->raw_default = NULL;
n->cooked_default = NULL;
n->constraints = NIL;
+ n->is_identity = false;
+ n->is_generated = false;
$$ = (Node *)n;
}
;
*************** OptSeqList: OptSeqList OptSeqElem {
*** 2396,2401 ****
--- 2499,2509 ----
| /*EMPTY*/ { $$ = NIL; }
;
+ SeqList: SeqList OptSeqElem { $$ = lappend($1, $2); }
+ | OptSeqElem { $$ = list_make1($1); }
+ ;
+
+
OptSeqElem: CACHE NumericOnly
{
$$ = makeDefElem("cache", (Node *)$2);
*************** InsertStmt:
*** 5603,5619 ****
;
insert_rest:
! SelectStmt
{
$$ = makeNode(InsertStmt);
$$->cols = NIL;
! $$->selectStmt = $1;
}
! | '(' insert_column_list ')' SelectStmt
{
$$ = makeNode(InsertStmt);
$$->cols = $2;
! $$->selectStmt = $4;
}
| DEFAULT VALUES
{
--- 5711,5729 ----
;
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
{
*************** opt_nowait: NOWAIT { $$ = TRUE; }
*** 5701,5706 ****
--- 5811,5832 ----
;
+ OptOverride:
+ OVERRIDING UserSystem VALUE_P
+ {
+ $$ = $2;
+ }
+ | /* EMPTY */
+ {
+ $$ = false;
+ }
+ ;
+
+ UserSystem:
+ SYSTEM_P { $$ = true; }
+ | USER { $$ = false; }
+ ;
+
/*****************************************************************************
*
* QUERY:
*************** unreserved_keyword:
*** 8793,8798 ****
--- 8919,8925 ----
| FORCE
| FORWARD
| FUNCTION
+ | GENERATED
| GLOBAL
| GRANTED
| HANDLER
*************** unreserved_keyword:
*** 8853,8858 ****
--- 8980,8986 ----
| OIDS
| OPERATOR
| OPTION
+ | OVERRIDING
| OWNED
| OWNER
| PARTIAL
*************** reserved_keyword:
*** 9079,9084 ****
--- 9207,9213 ----
| 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-04-04 10:11:20.000000000 +0200
--- pgsql/src/backend/parser/keywords.c 2007-04-04 12:57:20.000000000 +0200
*************** static const ScanKeyword ScanKeywords[]
*** 159,164 ****
--- 159,165 ----
{"from", FROM},
{"full", FULL},
{"function", FUNCTION},
+ {"generated", GENERATED},
{"global", GLOBAL},
{"grant", GRANT},
{"granted", GRANTED},
*************** static const ScanKeyword ScanKeywords[]
*** 169,174 ****
--- 170,176 ----
{"header", HEADER_P},
{"hold", HOLD},
{"hour", HOUR_P},
+ {"identity", IDENTITY},
{"if", IF_P},
{"ilike", ILIKE},
{"immediate", IMMEDIATE},
*************** static const ScanKeyword ScanKeywords[]
*** 264,269 ****
--- 266,272 ----
{"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-03-23 12:17:41.000000000 +0100
--- pgsql/src/backend/rewrite/rewriteHandler.c 2007-04-04 13:56:48.000000000 +0200
***************
*** 13,18 ****
--- 13,19 ----
*/
#include "postgres.h"
+ #include "miscadmin.h"
#include "access/heapam.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
***************
*** 24,29 ****
--- 25,31 ----
#include "rewrite/rewriteDefine.h"
#include "rewrite/rewriteHandler.h"
#include "rewrite/rewriteManip.h"
+ #include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "commands/trigger.h"
*************** rewriteTargetList(Query *parsetree, Rela
*** 536,541 ****
--- 538,544 ----
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
*** 620,634 ****
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,658 ----
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
*/
! if (commandType == CMD_UPDATE && att_tup->atthasdef && att_tup->attgenerated &&
! new_tle && new_tle->expr)
! {
! if (att_tup->attidentity)
! ereport(ERROR,
! (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! errmsg("UPDATE prohibited on GENERATED ALWAYS AS IDENTITY attributes")));
! else if (!IsA(new_tle->expr, SetToDefault))
! ereport(ERROR,
! (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! errmsg("UPDATE to non-default value prohibited on GENERATED ALWAYS attributes")));
! }
! if (((new_tle == NULL || (att_tup->attgenerated && !commandOverride)) && commandType == CMD_INSERT) ||
(new_tle && new_tle->expr && IsA(new_tle->expr, SetToDefault)))
{
Node *new_expr;
+ /*
+ * Skip all GENERATED columns that were assigned with DEFAULT.
+ */
+ if (att_tup->attgenerated && !att_tup->attidentity)
+ continue;
+
new_expr = build_column_default(target_relation, attrno);
/*
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-03-28 17:18:45.000000000 +0200
--- pgsql/src/backend/utils/adt/ruleutils.c 2007-04-04 12:57:20.000000000 +0200
*************** pg_get_serial_sequence(PG_FUNCTION_ARGS)
*** 1262,1272 ****
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));
--- 1262,1268 ----
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)
*** 1283,1328 ****
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))
{
--- 1279,1285 ----
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-04-04 10:12:37.000000000 +0200
--- pgsql/src/backend/utils/cache/lsyscache.c 2007-04-04 12:57:20.000000000 +0200
***************
*** 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-03-30 09:33:56.000000000 +0200
--- pgsql/src/backend/utils/cache/relcache.c 2007-04-04 14:32:06.000000000 +0200
*************** RelationBuildLocalRelation(const char *r
*** 2301,2306 ****
--- 2301,2308 ----
for (i = 0; i < natts; i++)
{
rel->rd_att->attrs[i]->attnotnull = tupDesc->attrs[i]->attnotnull;
+ rel->rd_att->attrs[i]->attidentity = tupDesc->attrs[i]->attidentity;
+ rel->rd_att->attrs[i]->attgenerated = tupDesc->attrs[i]->attgenerated;
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-04-04 10:12:40.000000000 +0200
--- pgsql/src/bin/pg_dump/pg_dump.c 2007-04-04 12:57:20.000000000 +0200
*************** dumpTableData_insert(Archive *fout, void
*** 1192,1197 ****
--- 1192,1199 ----
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
*** 1293,1300 ****
/* 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;
}
--- 1295,1303 ----
/* 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
*** 4282,4287 ****
--- 4285,4292 ----
int i_atthasdef;
int i_attisdropped;
int i_attislocal;
+ int i_attidentity;
+ int i_attgenerated;
PGresult *res;
int ntups;
bool hasdefaults;
*************** getTableAttrs(TableInfo *tblinfo, int nu
*** 4319,4330 ****
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 "
--- 4324,4350 ----
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.attgenerated "
! "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 attgenerated "
"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
*** 4341,4347 ****
*/
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 "
--- 4361,4368 ----
*/
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 attgenerated "
"from pg_attribute a left join pg_type t "
"on a.atttypid = t.oid "
"where a.attrelid = '%u'::oid "
*************** getTableAttrs(TableInfo *tblinfo, int nu
*** 4354,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 "
"from pg_attribute a "
"where attrelid = '%u'::oid "
"and attnum > 0::int2 "
--- 4375,4382 ----
/* 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 attgenerated "
"from pg_attribute a "
"where attrelid = '%u'::oid "
"and attnum > 0::int2 "
*************** getTableAttrs(TableInfo *tblinfo, int nu
*** 4378,4383 ****
--- 4400,4407 ----
i_atthasdef = PQfnumber(res, "atthasdef");
i_attisdropped = PQfnumber(res, "attisdropped");
i_attislocal = PQfnumber(res, "attislocal");
+ i_attidentity = PQfnumber(res, "attidentity");
+ i_attgenerated = PQfnumber(res, "attgenerated");
tbinfo->numatts = ntups;
tbinfo->attnames = (char **) malloc(ntups * sizeof(char *));
*************** getTableAttrs(TableInfo *tblinfo, int nu
*** 4388,4393 ****
--- 4412,4419 ----
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->attgenerated = (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
*** 4411,4416 ****
--- 4437,4445 ----
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->attgenerated[j] = (PQgetvalue(res, j, i_attgenerated)[0] == 't');
+ tbinfo->hasforceddef |= tbinfo->attgenerated[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
*** 7973,7980 ****
/*
* 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",
--- 8002,8018 ----
/*
* 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->attgenerated[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 *
*** 8145,8156 ****
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
*/
--- 8183,8209 ----
q = createPQExpBuffer();
delq = createPQExpBuffer();
! if (tbinfo->attidentity[adnum - 1] ||
! !tbinfo->attgenerated[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->attgenerated[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-03-23 12:18:57.000000000 +0100
--- pgsql/src/bin/pg_dump/pg_dump.h 2007-04-04 12:57:20.000000000 +0200
*************** 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 *attgenerated; /* 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-04-04 12:57:20.000000000 +0200
*************** 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 is_generated; /* 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 is_generated; /* 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 attgenerated);
extern Node *cookDefault(ParseState *pstate,
Node *raw_default,
Oid atttypid,
int32 atttypmod,
! char *attname,
! bool is_generated);
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-04-04 12:57:20.000000000 +0200
*************** 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 attgenerated;
} 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,attgenerated) + 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_attgenerated 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, {"attgenerated"}, 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 attgenerated 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
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-04-04 12:57:20.000000000 +0200
*************** 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/nodes/parsenodes.h pgsql/src/include/nodes/parsenodes.h
*** pgsql.orig/src/include/nodes/parsenodes.h 2007-04-04 10:12:42.000000000 +0200
--- pgsql/src/include/nodes/parsenodes.h 2007-04-04 13:58:31.000000000 +0200
*************** typedef struct Query
*** 129,134 ****
--- 129,136 ----
Node *setOperations; /* set-operation tree if this is top level of
* a UNION/INTERSECT/EXCEPT query */
+
+ bool commandOverride; /* OVERRIDING SYSTEM VALUE */
} Query;
*************** typedef struct ColumnDef
*** 389,394 ****
--- 391,398 ----
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 is_generated; /* GENERATED ALWAYS */
} ColumnDef;
/*
*************** typedef struct InsertStmt
*** 673,678 ****
--- 677,683 ----
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
*** 909,915 ****
AT_EnableReplicaRule, /* ENABLE REPLICA RULE name */
AT_DisableRule, /* DISABLE RULE name */
AT_AddInherit, /* INHERIT parent */
! AT_DropInherit /* NO INHERIT parent */
} AlterTableType;
typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */
--- 914,923 ----
AT_EnableReplicaRule, /* ENABLE REPLICA RULE name */
AT_DisableRule, /* DISABLE RULE name */
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
*** 922,927 ****
--- 930,938 ----
* index, constraint, or parent table */
Node *transform; /* transformation expr for ALTER TYPE */
DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */
+ bool is_generated; /* SET GENERATED
+ { ALWAYS | BY DEFAULT }
+ AS IDENTITY */
} AlterTableCmd;
*************** typedef struct CopyStmt
*** 1040,1045 ****
--- 1051,1057 ----
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
*** 1099,1105 ****
CONSTR_ATTR_DEFERRABLE, /* attributes for previous constraint node */
CONSTR_ATTR_NOT_DEFERRABLE,
CONSTR_ATTR_DEFERRED,
! CONSTR_ATTR_IMMEDIATE
} ConstrType;
typedef struct Constraint
--- 1111,1118 ----
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
*** 1113,1118 ****
--- 1126,1133 ----
List *options; /* options from WITH clause */
char *indexspace; /* index tablespace for PKEY/UNIQUE
* constraints; NULL for default */
+ bool is_generated; /* GENERATED ALWAYS */
+ List *seq_opts; /* SEQUENCE options for GENERATED ... AS IDENTITY */
} Constraint;
/* ----------
diff -dcrpN pgsql.orig/src/include/utils/lsyscache.h pgsql/src/include/utils/lsyscache.h
*** pgsql.orig/src/include/utils/lsyscache.h 2007-04-04 10:12:43.000000000 +0200
--- pgsql/src/include/utils/lsyscache.h 2007-04-04 12:57:20.000000000 +0200
*************** 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-04-04 13:50:22.000000000 +0200
***************
*** 0 ****
--- 1,702 ----
+ --
+ -- 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
+ 0 | 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
+ 0 | 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 | 0
+ x | 10
+ x | 15
+ x | 20
+ x | 25
+ (7 rows)
+
+ drop table di;
+ --
+ -- 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
+ -----
+ 4
+ (1 row)
+
+ select * from id;
+ id1 | t
+ -----+---
+ 4 | 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;
+ --
+ -- Try to drop IDENTITY again, it fails
+ --
+ alter table id alter id1 drop identity;
+ ERROR: column "id1" of relation "id" is a non-IDENTITY serial column
+ -- Insert new records
+ 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
+ -----
+ 6
+ (1 row)
+
+ select * from id;
+ id1 | t
+ -----+---
+ 4 | a
+ 6 | 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
+ -----+-----
+ 8 | 8
+ (1 row)
+
+ select * from id;
+ id1 | t | id2
+ -----+---+-----
+ 4 | a | 5
+ 6 | a | 6
+ 8 | a | 8
+ (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
+ -----+-----
+ 10 | 10
+ (1 row)
+
+ select * from id;
+ id1 | t | id2
+ -----+---+-----
+ 4 | a | 5
+ 6 | a | 6
+ 8 | a | 8
+ 10 | a | 10
+ (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
+ -----+---+-----
+ 4 | a | 5
+ 6 | a | 6
+ 8 | a | 8
+ 10 | a | 10
+ (4 rows)
+
+ drop table id;
+ --
+ -- Test GENERATED columns
+ --
+ 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"
+ insert into id (g) values (default);
+ select * from id;
+ id | g
+ ----+---
+ 1 | 2
+ (1 row)
+
+ 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 ));
+ 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)
+
+ --
+ -- Test DROP COLUMN on a column referenced by the GENERATED column
+ --
+ \d id
+ Table "public.id"
+ Column | Type | Modifiers
+ --------+---------+----------------------------------------------------------------------------------------------------------------------------------
+ id | integer | not null default nextval('id_id_seq'::regclass)
+ i1 | integer |
+ i2 | integer |
+ g1 | integer | default 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
+
+ alter table id drop i2;
+ NOTICE: GENERATED column "g1" of relation "id" referencing column "i2" was dropped
+ \d id
+ Table "public.id"
+ Column | Type | Modifiers
+ --------+---------+-------------------------------------------------
+ id | integer | not null default nextval('id_id_seq'::regclass)
+ i1 | integer |
+
+ drop table id;
+ --
+ -- Test plain COPY on IDENTITY/GENERATED columns
+ -- with missing column values. These should be generated.
+ --
+ 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"
+ copy id (i1, i2) from stdin;
+ select * from id;
+ id | i1 | i2 | g1
+ ----+----+----+----
+ 1 | | | -1
+ 2 | 10 | | 10
+ 3 | | 20 | 20
+ 4 | 10 | 20 | 30
+ (4 rows)
+
+ drop table id;
+ --
+ -- Test COPY OVERRIDING SYSTEM VALUE on IDENTITY/GENERATED columns
+ -- with missing column values. These should be generated.
+ --
+ 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"
+ copy id (i1, i2) overriding system value from stdin;
+ select * from id;
+ id | i1 | i2 | g1
+ ----+----+----+----
+ 1 | | | -1
+ 2 | 10 | | 10
+ 3 | | 20 | 20
+ 4 | 10 | 20 | 30
+ (4 rows)
+
+ drop table id;
+ --
+ -- Test COPY OVERRIDING SYSTEM VALUE on IDENTITY/GENERATED columns
+ -- with explicit column values. These should accept explicit values.
+ --
+ 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"
+ copy id (id, i1, i2, g1) overriding system value from stdin;
+ select * from id;
+ id | i1 | i2 | g1
+ ----+----+----+----
+ 1 | | | -2
+ 2 | 10 | | 37
+ 3 | | 20 | 36
+ 4 | 10 | 20 | 25
+ (4 rows)
+
+ --
+ -- Regenerate GENERATED values
+ --
+ update id set g1 = default where id = id;
+ select * from id;
+ id | i1 | i2 | g1
+ ----+----+----+----
+ 1 | | | -1
+ 2 | 10 | | 10
+ 3 | | 20 | 20
+ 4 | 10 | 20 | 30
+ (4 rows)
+
+ drop table id;
+ --
+ -- Test plain COPY on IDENTITY/GENERATED columns
+ -- with explicit column values. These should modify explicit values.
+ --
+ create table id (
+ id serial generated always as identity (start 5),
+ 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"
+ copy id (id, i1, i2, g1) from stdin;
+ select * from id;
+ id | i1 | i2 | g1
+ ----+----+----+----
+ 5 | | | -1
+ 6 | 10 | | 10
+ 7 | | 20 | 20
+ 8 | 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-04-04 10:12:44.000000000 +0200
--- pgsql/src/test/regress/parallel_schedule 2007-04-04 12:58:08.000000000 +0200
***************
*** 2,8 ****
# The first group of parallel test
# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.42 2007/04/02 03:49:42 tgl Exp $
# ----------
! test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric uuid enum
# 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.42 2007/04/02 03:49:42 tgl Exp $
# ----------
! test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric uuid enum 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-04-04 10:12:44.000000000 +0200
--- pgsql/src/test/regress/serial_schedule 2007-04-04 12:58:22.000000000 +0200
*************** test: bit
*** 15,20 ****
--- 15,21 ----
test: numeric
test: uuid
test: enum
+ 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-04-04 13:34:14.000000000 +0200
***************
*** 0 ****
--- 1,372 ----
+ --
+ -- 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;
+ drop table di;
+ --
+ -- 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;
+ --
+ -- Try to drop IDENTITY again, it fails
+ --
+ alter table id alter id1 drop identity;
+ -- Insert new records
+ 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;
+ --
+ -- Test GENERATED columns
+ --
+ create table id (
+ id serial generated always as identity,
+ g integer generated always as ( id + 1 ));
+ insert into id (g) values (default);
+ select * from id;
+ 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;
+ --
+ -- Test DROP COLUMN on a column referenced by the GENERATED column
+ --
+ \d id
+ alter table id drop i2;
+ \d id
+ drop table id;
+ --
+ -- Test plain COPY on IDENTITY/GENERATED columns
+ -- with missing column values. These should be generated.
+ --
+ 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 ));
+ copy id (i1, i2) from stdin;
+ \N \N
+ 10 \N
+ \N 20
+ 10 20
+ \.
+ select * from id;
+ drop table id;
+ --
+ -- Test COPY OVERRIDING SYSTEM VALUE on IDENTITY/GENERATED columns
+ -- with missing column values. These should be generated.
+ --
+ 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 ));
+ copy id (i1, i2) overriding system value from stdin;
+ \N \N
+ 10 \N
+ \N 20
+ 10 20
+ \.
+ select * from id;
+ drop table id;
+ --
+ -- Test COPY OVERRIDING SYSTEM VALUE on IDENTITY/GENERATED columns
+ -- with explicit column values. These should accept explicit values.
+ --
+ 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 ));
+ copy id (id, i1, i2, g1) overriding system value from stdin;
+ 1 \N \N -2
+ 2 10 \N 37
+ 3 \N 20 36
+ 4 10 20 25
+ \.
+ select * from id;
+ --
+ -- Regenerate GENERATED values
+ --
+ update id set g1 = default where id = id;
+ select * from id;
+ drop table id;
+ --
+ -- Test plain COPY on IDENTITY/GENERATED columns
+ -- with explicit column values. These should modify explicit values.
+ --
+ create table id (
+ id serial generated always as identity (start 5),
+ 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 ));
+ copy id (id, i1, i2, g1) from stdin;
+ 1 \N \N -2
+ 2 10 \N 37
+ 3 \N 20 36
+ 4 10 20 25
+ \.
+ select * from id;
+ drop table id;