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;