1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Change nextval and other sequence functions to specify their sequence

argument as a 'regclass' value instead of a text string.  The frontend
conversion of text string to pg_class OID is now encapsulated as an
implicitly-invocable coercion from text to regclass.  This provides
backwards compatibility to the old behavior when the sequence argument
is explicitly typed as 'text'.  When the argument is just an unadorned
literal string, it will be taken as 'regclass', which means that the
stored representation will be an OID.  This solves longstanding problems
with renaming sequences that are referenced in default expressions, as
well as new-in-8.1 problems with renaming such sequences' schemas or
moving them to another schema.  All per recent discussion.
Along the way, fix some rather serious problems in dbmirror's support
for mirroring sequence operations (int4 vs int8 confusion for instance).
This commit is contained in:
Tom Lane
2005-10-02 23:50:16 +00:00
parent 1b61ee3c69
commit aa731ed843
25 changed files with 515 additions and 342 deletions

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.45 2005/07/07 20:39:57 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.46 2005/10/02 23:50:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1030,6 +1030,59 @@ find_expr_references_walker(Node *node,
}
return false;
}
if (IsA(node, Const))
{
Const *con = (Const *) node;
Oid objoid;
/*
* If it's a regclass or similar literal referring to an existing
* object, add a reference to that object. (Currently, only the
* regclass case has any likely use, but we may as well handle all
* the OID-alias datatypes consistently.)
*/
if (!con->constisnull)
{
switch (con->consttype)
{
case REGPROCOID:
case REGPROCEDUREOID:
objoid = DatumGetObjectId(con->constvalue);
if (SearchSysCacheExists(PROCOID,
ObjectIdGetDatum(objoid),
0, 0, 0))
add_object_address(OCLASS_PROC, objoid, 0,
&context->addrs);
break;
case REGOPEROID:
case REGOPERATOROID:
objoid = DatumGetObjectId(con->constvalue);
if (SearchSysCacheExists(OPEROID,
ObjectIdGetDatum(objoid),
0, 0, 0))
add_object_address(OCLASS_OPERATOR, objoid, 0,
&context->addrs);
break;
case REGCLASSOID:
objoid = DatumGetObjectId(con->constvalue);
if (SearchSysCacheExists(RELOID,
ObjectIdGetDatum(objoid),
0, 0, 0))
add_object_address(OCLASS_CLASS, objoid, 0,
&context->addrs);
break;
case REGTYPEOID:
objoid = DatumGetObjectId(con->constvalue);
if (SearchSysCacheExists(TYPEOID,
ObjectIdGetDatum(objoid),
0, 0, 0))
add_object_address(OCLASS_TYPE, objoid, 0,
&context->addrs);
break;
}
}
return false;
}
if (IsA(node, FuncExpr))
{
FuncExpr *funcexpr = (FuncExpr *) node;

View File

@ -4,7 +4,7 @@
*
* Copyright (c) 2003-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.30 2005/07/26 00:04:18 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.31 2005/10/02 23:50:07 tgl Exp $
*/
/*
@ -357,7 +357,8 @@ CREATE VIEW columns AS
CAST(a.attname AS sql_identifier) AS column_name,
CAST(a.attnum AS cardinal_number) AS ordinal_position,
CAST(
CASE WHEN pg_has_role(c.relowner, 'MEMBER') THEN ad.adsrc ELSE null END
CASE WHEN pg_has_role(c.relowner, 'MEMBER') THEN pg_get_expr(ad.adbin, ad.adrelid)
ELSE null END
AS character_data)
AS column_default,
CAST(CASE WHEN a.attnotnull OR (t.typtype = 'd' AND t.typnotnull) THEN 'NO' ELSE 'YES' END

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.123 2005/06/07 07:08:34 neilc Exp $
* $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.124 2005/10/02 23:50:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -75,12 +75,12 @@ static SeqTable seqtab = NULL; /* Head of list of SeqTable items */
*/
static SeqTableData *last_used_seq = NULL;
static int64 nextval_internal(Oid relid);
static void acquire_share_lock(Relation seqrel, SeqTable seq);
static void init_sequence(RangeVar *relation,
SeqTable *p_elm, Relation *p_rel);
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel);
static Form_pg_sequence read_info(SeqTable elm, Relation rel, Buffer *buf);
static void init_params(List *options, Form_pg_sequence new, bool isInit);
static void do_setval(RangeVar *sequence, int64 next, bool iscalled);
static void do_setval(Oid relid, int64 next, bool iscalled);
/*
* DefineSequence
@ -302,6 +302,7 @@ DefineSequence(CreateSeqStmt *seq)
void
AlterSequence(AlterSeqStmt *stmt)
{
Oid relid;
SeqTable elm;
Relation seqrel;
Buffer buf;
@ -310,7 +311,8 @@ AlterSequence(AlterSeqStmt *stmt)
FormData_pg_sequence new;
/* open and AccessShareLock sequence */
init_sequence(stmt->sequence, &elm, &seqrel);
relid = RangeVarGetRelid(stmt->sequence, false);
init_sequence(relid, &elm, &seqrel);
/* allow ALTER to sequence owner only */
if (!pg_class_ownercheck(elm->relid, GetUserId()))
@ -372,11 +374,35 @@ AlterSequence(AlterSeqStmt *stmt)
}
/*
* Note: nextval with a text argument is no longer exported as a pg_proc
* entry, but we keep it around to ease porting of C code that may have
* called the function directly.
*/
Datum
nextval(PG_FUNCTION_ARGS)
{
text *seqin = PG_GETARG_TEXT_P(0);
RangeVar *sequence;
Oid relid;
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin));
relid = RangeVarGetRelid(sequence, false);
PG_RETURN_INT64(nextval_internal(relid));
}
Datum
nextval_oid(PG_FUNCTION_ARGS)
{
Oid relid = PG_GETARG_OID(0);
PG_RETURN_INT64(nextval_internal(relid));
}
static int64
nextval_internal(Oid relid)
{
SeqTable elm;
Relation seqrel;
Buffer buf;
@ -394,23 +420,21 @@ nextval(PG_FUNCTION_ARGS)
rescnt = 0;
bool logit = false;
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin));
/* open and AccessShareLock sequence */
init_sequence(sequence, &elm, &seqrel);
init_sequence(relid, &elm, &seqrel);
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for sequence %s",
sequence->relname)));
RelationGetRelationName(seqrel))));
if (elm->last != elm->cached) /* some numbers were cached */
{
last_used_seq = elm;
elm->last += elm->increment;
relation_close(seqrel, NoLock);
PG_RETURN_INT64(elm->last);
return elm->last;
}
/* lock page' buffer and read tuple */
@ -481,7 +505,7 @@ nextval(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("nextval: reached maximum value of sequence \"%s\" (%s)",
sequence->relname, buf)));
RelationGetRelationName(seqrel), buf)));
}
next = minv;
}
@ -504,7 +528,7 @@ nextval(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("nextval: reached minimum value of sequence \"%s\" (%s)",
sequence->relname, buf)));
RelationGetRelationName(seqrel), buf)));
}
next = maxv;
}
@ -576,34 +600,31 @@ nextval(PG_FUNCTION_ARGS)
relation_close(seqrel, NoLock);
PG_RETURN_INT64(result);
return result;
}
Datum
currval(PG_FUNCTION_ARGS)
currval_oid(PG_FUNCTION_ARGS)
{
text *seqin = PG_GETARG_TEXT_P(0);
RangeVar *sequence;
Oid relid = PG_GETARG_OID(0);
int64 result;
SeqTable elm;
Relation seqrel;
int64 result;
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin));
/* open and AccessShareLock sequence */
init_sequence(sequence, &elm, &seqrel);
init_sequence(relid, &elm, &seqrel);
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for sequence %s",
sequence->relname)));
RelationGetRelationName(seqrel))));
if (elm->increment == 0) /* nextval/read_info were not called */
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("currval of sequence \"%s\" is not yet defined in this session",
sequence->relname)));
RelationGetRelationName(seqrel))));
result = elm->last;
@ -645,6 +666,7 @@ lastval(PG_FUNCTION_ARGS)
result = last_used_seq->last;
relation_close(seqrel, NoLock);
PG_RETURN_INT64(result);
}
@ -662,7 +684,7 @@ lastval(PG_FUNCTION_ARGS)
* sequence.
*/
static void
do_setval(RangeVar *sequence, int64 next, bool iscalled)
do_setval(Oid relid, int64 next, bool iscalled)
{
SeqTable elm;
Relation seqrel;
@ -670,13 +692,13 @@ do_setval(RangeVar *sequence, int64 next, bool iscalled)
Form_pg_sequence seq;
/* open and AccessShareLock sequence */
init_sequence(sequence, &elm, &seqrel);
init_sequence(relid, &elm, &seqrel);
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for sequence %s",
sequence->relname)));
RelationGetRelationName(seqrel))));
/* lock page' buffer and read tuple */
seq = read_info(elm, seqrel, &buf);
@ -693,7 +715,8 @@ do_setval(RangeVar *sequence, int64 next, bool iscalled)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("setval: value %s is out of bounds for sequence \"%s\" (%s..%s)",
bufv, sequence->relname, bufm, bufx)));
bufv, RelationGetRelationName(seqrel),
bufm, bufx)));
}
/* save info in local cache */
@ -753,15 +776,12 @@ do_setval(RangeVar *sequence, int64 next, bool iscalled)
* See do_setval for discussion.
*/
Datum
setval(PG_FUNCTION_ARGS)
setval_oid(PG_FUNCTION_ARGS)
{
text *seqin = PG_GETARG_TEXT_P(0);
Oid relid = PG_GETARG_OID(0);
int64 next = PG_GETARG_INT64(1);
RangeVar *sequence;
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin));
do_setval(sequence, next, true);
do_setval(relid, next, true);
PG_RETURN_INT64(next);
}
@ -771,16 +791,13 @@ setval(PG_FUNCTION_ARGS)
* See do_setval for discussion.
*/
Datum
setval_and_iscalled(PG_FUNCTION_ARGS)
setval3_oid(PG_FUNCTION_ARGS)
{
text *seqin = PG_GETARG_TEXT_P(0);
Oid relid = PG_GETARG_OID(0);
int64 next = PG_GETARG_INT64(1);
bool iscalled = PG_GETARG_BOOL(2);
RangeVar *sequence;
sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin));
do_setval(sequence, next, iscalled);
do_setval(relid, next, iscalled);
PG_RETURN_INT64(next);
}
@ -822,15 +839,14 @@ acquire_share_lock(Relation seqrel, SeqTable seq)
}
/*
* Given a relation name, open and lock the sequence. p_elm and p_rel are
* Given a relation OID, open and lock the sequence. p_elm and p_rel are
* output parameters.
*/
static void
init_sequence(RangeVar *relation, SeqTable *p_elm, Relation *p_rel)
init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
{
Oid relid = RangeVarGetRelid(relation, false);
volatile SeqTable elm;
Relation seqrel;
volatile SeqTable elm;
/*
* Open the sequence relation.
@ -841,7 +857,7 @@ init_sequence(RangeVar *relation, SeqTable *p_elm, Relation *p_rel)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a sequence",
relation->relname)));
RelationGetRelationName(seqrel))));
/* Look to see if we already have a seqtable entry for relation */
for (elm = seqtab; elm != NULL; elm = elm->next)

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.171 2005/09/24 22:54:36 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.172 2005/10/02 23:50:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -168,8 +168,6 @@ static void AlterIndexNamespaces(Relation classRel, Relation rel,
static void AlterSeqNamespaces(Relation classRel, Relation rel,
Oid oldNspOid, Oid newNspOid,
const char *newNspName);
static void RebuildSerialDefaultExpr(Relation rel, AttrNumber attnum,
const char *seqname, const char *nspname);
static int transformColumnNameList(Oid relId, List *colList,
int16 *attnums, Oid *atttypids);
static int transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
@ -6313,15 +6311,6 @@ AlterSeqNamespaces(Relation classRel, Relation rel,
*/
AlterTypeNamespaceInternal(RelationGetForm(seqRel)->reltype,
newNspOid, false);
/*
* And we need to rebuild the column default expression that
* relies on this sequence.
*/
if (depForm->refobjsubid > 0)
RebuildSerialDefaultExpr(rel,
depForm->refobjsubid,
RelationGetRelationName(seqRel),
newNspName);
/* Now we can close it. Keep the lock till end of transaction. */
relation_close(seqRel, NoLock);
@ -6332,56 +6321,6 @@ AlterSeqNamespaces(Relation classRel, Relation rel,
relation_close(depRel, AccessShareLock);
}
/*
* Rebuild the default expression for a SERIAL column identified by rel
* and attnum. This is annoying, but we have to do it because the
* stored expression has the schema name as a text constant.
*
* The caller must be sure the specified column is really a SERIAL column,
* because no further checks are done here.
*/
static void
RebuildSerialDefaultExpr(Relation rel, AttrNumber attnum,
const char *seqname, const char *nspname)
{
char *qstring;
A_Const *snamenode;
FuncCall *funccallnode;
RawColumnDefault *rawEnt;
/*
* Create raw parse tree for the updated column default expression.
* This should match transformColumnDefinition() in parser/analyze.c.
*/
qstring = quote_qualified_identifier(nspname, seqname);
snamenode = makeNode(A_Const);
snamenode->val.type = T_String;
snamenode->val.val.str = qstring;
funccallnode = makeNode(FuncCall);
funccallnode->funcname = SystemFuncName("nextval");
funccallnode->args = list_make1(snamenode);
funccallnode->agg_star = false;
funccallnode->agg_distinct = false;
/*
* 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
* default.
*/
RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, false);
/* Do the equivalent of ALTER TABLE ... SET DEFAULT */
rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
rawEnt->attnum = attnum;
rawEnt->raw_default = (Node *) funccallnode;
/*
* This function is intended for CREATE TABLE, so it processes a
* _list_ of defaults, but we just do one.
*/
AddRelationRawConstraints(rel, list_make1(rawEnt), NIL);
}
/*
* This code supports

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.324 2005/08/01 20:31:09 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.325 2005/10/02 23:50:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -912,12 +912,15 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
* DEFAULT).
*
* Create an expression tree representing the function call
* nextval('"sequencename"')
* nextval('sequencename'). We cannot reduce the raw tree
* to cooked form until after the sequence is created, but
* there's no need to do so.
*/
qstring = quote_qualified_identifier(snamespace, sname);
snamenode = makeNode(A_Const);
snamenode->val.type = T_String;
snamenode->val.val.str = qstring;
snamenode->typename = SystemTypeName("regclass");
funccallnode = makeNode(FuncCall);
funccallnode->funcname = SystemFuncName("nextval");
funccallnode->args = list_make1(snamenode);

View File

@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.94 2005/04/14 20:03:26 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.95 2005/10/02 23:50:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1089,6 +1089,23 @@ regtypesend(PG_FUNCTION_ARGS)
}
/*
* text_regclass: convert text to regclass
*/
Datum
text_regclass(PG_FUNCTION_ARGS)
{
text *relname = PG_GETARG_TEXT_P(0);
Oid result;
RangeVar *rv;
rv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
result = RangeVarGetRelid(rv, false);
PG_RETURN_OID(result);
}
/*
* Given a C string, parse it into a qualified-name list.
*/

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.124 2005/08/14 19:20:45 tgl Exp $
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.125 2005/10/02 23:50:10 tgl Exp $
*/
#include "postgres_fe.h"
#include "describe.h"
@ -763,7 +763,8 @@ describeOneTableDetails(const char *schemaname,
/* Get column info (index requires additional checks) */
printfPQExpBuffer(&buf, "SELECT a.attname,");
appendPQExpBuffer(&buf, "\n pg_catalog.format_type(a.atttypid, a.atttypmod),"
"\n (SELECT substring(d.adsrc for 128) FROM pg_catalog.pg_attrdef d"
"\n (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)"
"\n FROM pg_catalog.pg_attrdef d"
"\n WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef),"
"\n a.attnotnull, a.attnum");
if (verbose)

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.302 2005/09/16 05:35:40 neilc Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.303 2005/10/02 23:50:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200509161
#define CATALOG_VERSION_NO 200510011
#endif

View File

@ -10,7 +10,7 @@
*
* Copyright (c) 2002-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.21 2005/04/14 01:38:20 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.22 2005/10/02 23:50:11 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -116,7 +116,9 @@ DATA(insert ( 16 23 2558 e ));
* from OID to int4 or int8. Similarly for each OID-alias type. Also allow
* implicit coercions between OID and each OID-alias type, as well as
* regproc<->regprocedure and regoper<->regoperator. (Other coercions
* between alias types must pass through OID.)
* between alias types must pass through OID.) Lastly, there is an implicit
* cast from text to regclass, which exists mainly to support legacy forms
* of nextval() and related functions.
*/
DATA(insert ( 20 26 1287 i ));
DATA(insert ( 21 26 313 i ));
@ -169,6 +171,7 @@ DATA(insert ( 21 2206 313 i ));
DATA(insert ( 23 2206 0 i ));
DATA(insert ( 2206 20 1288 a ));
DATA(insert ( 2206 23 0 a ));
DATA(insert ( 25 2205 1079 i ));
/*
* String category: this needs to be tightened up

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.385 2005/09/16 05:35:40 neilc Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.386 2005/10/02 23:50:11 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@ -2073,14 +2073,14 @@ DATA(insert OID = 1572 ( notlike PGNSP PGUID 12 f f t f i 2 16 "19 25" _null_
DESCR("does not match LIKE expression");
/* SEQUENCEs nextval & currval functions */
DATA(insert OID = 1574 ( nextval PGNSP PGUID 12 f f t f v 1 20 "25" _null_ _null_ _null_ nextval - _null_ ));
/* SEQUENCE functions */
DATA(insert OID = 1574 ( nextval PGNSP PGUID 12 f f t f v 1 20 "2205" _null_ _null_ _null_ nextval_oid - _null_ ));
DESCR("sequence next value");
DATA(insert OID = 1575 ( currval PGNSP PGUID 12 f f t f v 1 20 "25" _null_ _null_ _null_ currval - _null_ ));
DATA(insert OID = 1575 ( currval PGNSP PGUID 12 f f t f v 1 20 "2205" _null_ _null_ _null_ currval_oid - _null_ ));
DESCR("sequence current value");
DATA(insert OID = 1576 ( setval PGNSP PGUID 12 f f t f v 2 20 "25 20" _null_ _null_ _null_ setval - _null_ ));
DATA(insert OID = 1576 ( setval PGNSP PGUID 12 f f t f v 2 20 "2205 20" _null_ _null_ _null_ setval_oid - _null_ ));
DESCR("set sequence value");
DATA(insert OID = 1765 ( setval PGNSP PGUID 12 f f t f v 3 20 "25 20 16" _null_ _null_ _null_ setval_and_iscalled - _null_ ));
DATA(insert OID = 1765 ( setval PGNSP PGUID 12 f f t f v 3 20 "2205 20 16" _null_ _null_ _null_ setval3_oid - _null_ ));
DESCR("set sequence value and iscalled status");
DATA(insert OID = 1579 ( varbit_in PGNSP PGUID 12 f f t f i 3 1562 "2275 26 23" _null_ _null_ _null_ varbit_in - _null_ ));
@ -3190,6 +3190,8 @@ DATA(insert OID = 2220 ( regtypein PGNSP PGUID 12 f f t f s 1 2206 "2275" _nu
DESCR("I/O");
DATA(insert OID = 2221 ( regtypeout PGNSP PGUID 12 f f t f s 1 2275 "2206" _null_ _null_ _null_ regtypeout - _null_ ));
DESCR("I/O");
DATA(insert OID = 1079 ( regclass PGNSP PGUID 12 f f t f s 1 2205 "25" _null_ _null_ _null_ text_regclass - _null_ ));
DESCR("convert text to regclass");
DATA(insert OID = 2246 ( fmgr_internal_validator PGNSP PGUID 12 f f t f s 1 2278 "26" _null_ _null_ _null_ fmgr_internal_validator - _null_ ));
DESCR("(internal)");

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/commands/sequence.h,v 1.32 2005/06/07 07:08:35 neilc Exp $
* $PostgreSQL: pgsql/src/include/commands/sequence.h,v 1.33 2005/10/02 23:50:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -81,10 +81,11 @@ typedef struct xl_seq_rec
} xl_seq_rec;
extern Datum nextval(PG_FUNCTION_ARGS);
extern Datum currval(PG_FUNCTION_ARGS);
extern Datum nextval_oid(PG_FUNCTION_ARGS);
extern Datum currval_oid(PG_FUNCTION_ARGS);
extern Datum setval_oid(PG_FUNCTION_ARGS);
extern Datum setval3_oid(PG_FUNCTION_ARGS);
extern Datum lastval(PG_FUNCTION_ARGS);
extern Datum setval(PG_FUNCTION_ARGS);
extern Datum setval_and_iscalled(PG_FUNCTION_ARGS);
extern void DefineSequence(CreateSeqStmt *stmt);
extern void AlterSequence(AlterSeqStmt *stmt);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.264 2005/09/16 05:35:41 neilc Exp $
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.265 2005/10/02 23:50:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -482,6 +482,7 @@ extern Datum regtypein(PG_FUNCTION_ARGS);
extern Datum regtypeout(PG_FUNCTION_ARGS);
extern Datum regtyperecv(PG_FUNCTION_ARGS);
extern Datum regtypesend(PG_FUNCTION_ARGS);
extern Datum text_regclass(PG_FUNCTION_ARGS);
extern List *stringToQualifiedNameList(const char *string, const char *caller);
extern char *format_procedure(Oid procedure_oid);
extern char *format_operator(Oid operator_oid);

View File

@ -162,7 +162,7 @@ create domain ddef2 oid DEFAULT '12';
-- Type mixing, function returns int8
create domain ddef3 text DEFAULT 5;
create sequence ddef4_seq;
create domain ddef4 int4 DEFAULT nextval(cast('ddef4_seq' as text));
create domain ddef4 int4 DEFAULT nextval('ddef4_seq');
create domain ddef5 numeric(8,2) NOT NULL DEFAULT '12.12';
create table defaulttest
( col1 ddef1
@ -189,7 +189,6 @@ select * from defaulttest;
3 | 12 | 5 | 4 | 42 | 88 | 8000 | 12.12
(4 rows)
drop sequence ddef4_seq;
drop table defaulttest cascade;
-- Test ALTER DOMAIN .. NOT NULL
create domain dnotnulltest integer;
@ -300,6 +299,7 @@ drop domain ddef2 restrict;
drop domain ddef3 restrict;
drop domain ddef4 restrict;
drop domain ddef5 restrict;
drop sequence ddef4_seq;
-- Make sure that constraints of newly-added domain columns are
-- enforced correctly, even if there's no default value for the new
-- column. Per bug #1433

View File

@ -1335,10 +1335,10 @@ SELECT tablename, rulename, definition FROM pg_rules
rtest_nothn1 | rtest_nothn_r2 | CREATE RULE rtest_nothn_r2 AS ON INSERT TO rtest_nothn1 WHERE ((new.a >= 30) AND (new.a < 40)) DO INSTEAD NOTHING;
rtest_nothn2 | rtest_nothn_r3 | CREATE RULE rtest_nothn_r3 AS ON INSERT TO rtest_nothn2 WHERE (new.a >= 100) DO INSTEAD INSERT INTO rtest_nothn3 (a, b) VALUES (new.a, new.b);
rtest_nothn2 | rtest_nothn_r4 | CREATE RULE rtest_nothn_r4 AS ON INSERT TO rtest_nothn2 DO INSTEAD NOTHING;
rtest_order1 | rtest_order_r1 | CREATE RULE rtest_order_r1 AS ON INSERT TO rtest_order1 DO INSTEAD INSERT INTO rtest_order2 (a, b, c) VALUES (new.a, nextval('rtest_seq'::text), 'rule 1 - this should run 1st'::text);
rtest_order1 | rtest_order_r2 | CREATE RULE rtest_order_r2 AS ON INSERT TO rtest_order1 DO INSERT INTO rtest_order2 (a, b, c) VALUES (new.a, nextval('rtest_seq'::text), 'rule 2 - this should run 2nd'::text);
rtest_order1 | rtest_order_r3 | CREATE RULE rtest_order_r3 AS ON INSERT TO rtest_order1 DO INSTEAD INSERT INTO rtest_order2 (a, b, c) VALUES (new.a, nextval('rtest_seq'::text), 'rule 3 - this should run 3rd'::text);
rtest_order1 | rtest_order_r4 | CREATE RULE rtest_order_r4 AS ON INSERT TO rtest_order1 WHERE (new.a < 100) DO INSTEAD INSERT INTO rtest_order2 (a, b, c) VALUES (new.a, nextval('rtest_seq'::text), 'rule 4 - this should run 4th'::text);
rtest_order1 | rtest_order_r1 | CREATE RULE rtest_order_r1 AS ON INSERT TO rtest_order1 DO INSTEAD INSERT INTO rtest_order2 (a, b, c) VALUES (new.a, nextval('rtest_seq'::regclass), 'rule 1 - this should run 1st'::text);
rtest_order1 | rtest_order_r2 | CREATE RULE rtest_order_r2 AS ON INSERT TO rtest_order1 DO INSERT INTO rtest_order2 (a, b, c) VALUES (new.a, nextval('rtest_seq'::regclass), 'rule 2 - this should run 2nd'::text);
rtest_order1 | rtest_order_r3 | CREATE RULE rtest_order_r3 AS ON INSERT TO rtest_order1 DO INSTEAD INSERT INTO rtest_order2 (a, b, c) VALUES (new.a, nextval('rtest_seq'::regclass), 'rule 3 - this should run 3rd'::text);
rtest_order1 | rtest_order_r4 | CREATE RULE rtest_order_r4 AS ON INSERT TO rtest_order1 WHERE (new.a < 100) DO INSTEAD INSERT INTO rtest_order2 (a, b, c) VALUES (new.a, nextval('rtest_seq'::regclass), 'rule 4 - this should run 4th'::text);
rtest_person | rtest_pers_del | CREATE RULE rtest_pers_del AS ON DELETE TO rtest_person DO DELETE FROM rtest_admin WHERE (rtest_admin.pname = old.pname);
rtest_person | rtest_pers_upd | CREATE RULE rtest_pers_upd AS ON UPDATE TO rtest_person DO UPDATE rtest_admin SET pname = new.pname WHERE (rtest_admin.pname = old.pname);
rtest_system | rtest_sys_del | CREATE RULE rtest_sys_del AS ON DELETE TO rtest_system DO (DELETE FROM rtest_interface WHERE (rtest_interface.sysname = old.sysname); DELETE FROM rtest_admin WHERE (rtest_admin.sysname = old.sysname); );

View File

@ -19,18 +19,82 @@ SELECT * FROM serialTest;
force | 100
(3 rows)
-- basic sequence operations using both text and oid references
CREATE SEQUENCE sequence_test;
BEGIN;
SELECT nextval('sequence_test');
SELECT nextval('sequence_test'::text);
nextval
---------
1
(1 row)
SELECT nextval('sequence_test'::regclass);
nextval
---------
2
(1 row)
SELECT currval('sequence_test'::text);
currval
---------
2
(1 row)
SELECT currval('sequence_test'::regclass);
currval
---------
2
(1 row)
SELECT setval('sequence_test'::text, 32);
setval
--------
32
(1 row)
SELECT nextval('sequence_test'::regclass);
nextval
---------
33
(1 row)
SELECT setval('sequence_test'::text, 99, false);
setval
--------
99
(1 row)
SELECT nextval('sequence_test'::regclass);
nextval
---------
99
(1 row)
SELECT setval('sequence_test'::regclass, 32);
setval
--------
32
(1 row)
SELECT nextval('sequence_test'::text);
nextval
---------
33
(1 row)
SELECT setval('sequence_test'::regclass, 99, false);
setval
--------
99
(1 row)
SELECT nextval('sequence_test'::text);
nextval
---------
99
(1 row)
DROP SEQUENCE sequence_test;
END;
-- renaming sequences
CREATE SEQUENCE foo_seq;
ALTER TABLE foo_seq RENAME TO foo_seq_new;
@ -41,6 +105,45 @@ SELECT * FROM foo_seq_new;
(1 row)
DROP SEQUENCE foo_seq_new;
-- renaming serial sequences
ALTER TABLE serialtest_f2_seq RENAME TO serialtest_f2_foo;
INSERT INTO serialTest VALUES ('more');
SELECT * FROM serialTest;
f1 | f2
-------+-----
foo | 1
bar | 2
force | 100
more | 3
(4 rows)
--
-- Check dependencies of serial and ordinary sequences
--
CREATE TEMP SEQUENCE myseq2;
CREATE TEMP SEQUENCE myseq3;
CREATE TEMP TABLE t1 (
f1 serial,
f2 int DEFAULT nextval('myseq2'),
f3 int DEFAULT nextval('myseq3'::text)
);
NOTICE: CREATE TABLE will create implicit sequence "t1_f1_seq" for serial column "t1.f1"
-- Both drops should fail, but with different error messages:
DROP SEQUENCE t1_f1_seq;
ERROR: cannot drop sequence t1_f1_seq because table t1 column f1 requires it
HINT: You may drop table t1 column f1 instead.
DROP SEQUENCE myseq2;
NOTICE: default for table t1 column f2 depends on sequence myseq2
ERROR: cannot drop sequence myseq2 because other objects depend on it
HINT: Use DROP ... CASCADE to drop the dependent objects too.
-- This however will work:
DROP SEQUENCE myseq3;
DROP TABLE t1;
-- Fails because no longer existent:
DROP SEQUENCE t1_f1_seq;
ERROR: sequence "t1_f1_seq" does not exist
-- Now OK:
DROP SEQUENCE myseq2;
--
-- Alter sequence
--

View File

@ -147,9 +147,8 @@ DROP TABLE INSERT_CHILD;
--
DELETE FROM INSERT_TBL;
DROP SEQUENCE INSERT_SEQ;
CREATE SEQUENCE INSERT_SEQ START 4;
ALTER SEQUENCE INSERT_SEQ RESTART WITH 4;
CREATE TABLE tmp (xd INT, yd TEXT, zd INT);

View File

@ -213,8 +213,7 @@ DROP TABLE INSERT_CHILD;
-- Check constraints on INSERT INTO
--
DELETE FROM INSERT_TBL;
DROP SEQUENCE INSERT_SEQ;
CREATE SEQUENCE INSERT_SEQ START 4;
ALTER SEQUENCE INSERT_SEQ RESTART WITH 4;
CREATE TABLE tmp (xd INT, yd TEXT, zd INT);
INSERT INTO tmp VALUES (null, 'Y', null);
INSERT INTO tmp VALUES (5, '!check failed', null);

View File

@ -131,7 +131,7 @@ create domain ddef2 oid DEFAULT '12';
-- Type mixing, function returns int8
create domain ddef3 text DEFAULT 5;
create sequence ddef4_seq;
create domain ddef4 int4 DEFAULT nextval(cast('ddef4_seq' as text));
create domain ddef4 int4 DEFAULT nextval('ddef4_seq');
create domain ddef5 numeric(8,2) NOT NULL DEFAULT '12.12';
create table defaulttest
@ -155,7 +155,6 @@ COPY defaulttest(col5) FROM stdin;
select * from defaulttest;
drop sequence ddef4_seq;
drop table defaulttest cascade;
-- Test ALTER DOMAIN .. NOT NULL
@ -244,6 +243,7 @@ drop domain ddef2 restrict;
drop domain ddef3 restrict;
drop domain ddef4 restrict;
drop domain ddef5 restrict;
drop sequence ddef4_seq;
-- Make sure that constraints of newly-added domain columns are
-- enforced correctly, even if there's no default value for the new

View File

@ -10,13 +10,24 @@ INSERT INTO serialTest VALUES ('force', 100);
INSERT INTO serialTest VALUES ('wrong', NULL);
SELECT * FROM serialTest;
-- basic sequence operations using both text and oid references
CREATE SEQUENCE sequence_test;
BEGIN;
SELECT nextval('sequence_test');
SELECT nextval('sequence_test'::text);
SELECT nextval('sequence_test'::regclass);
SELECT currval('sequence_test'::text);
SELECT currval('sequence_test'::regclass);
SELECT setval('sequence_test'::text, 32);
SELECT nextval('sequence_test'::regclass);
SELECT setval('sequence_test'::text, 99, false);
SELECT nextval('sequence_test'::regclass);
SELECT setval('sequence_test'::regclass, 32);
SELECT nextval('sequence_test'::text);
SELECT setval('sequence_test'::regclass, 99, false);
SELECT nextval('sequence_test'::text);
DROP SEQUENCE sequence_test;
END;
-- renaming sequences
CREATE SEQUENCE foo_seq;
@ -24,6 +35,32 @@ ALTER TABLE foo_seq RENAME TO foo_seq_new;
SELECT * FROM foo_seq_new;
DROP SEQUENCE foo_seq_new;
-- renaming serial sequences
ALTER TABLE serialtest_f2_seq RENAME TO serialtest_f2_foo;
INSERT INTO serialTest VALUES ('more');
SELECT * FROM serialTest;
--
-- Check dependencies of serial and ordinary sequences
--
CREATE TEMP SEQUENCE myseq2;
CREATE TEMP SEQUENCE myseq3;
CREATE TEMP TABLE t1 (
f1 serial,
f2 int DEFAULT nextval('myseq2'),
f3 int DEFAULT nextval('myseq3'::text)
);
-- Both drops should fail, but with different error messages:
DROP SEQUENCE t1_f1_seq;
DROP SEQUENCE myseq2;
-- This however will work:
DROP SEQUENCE myseq3;
DROP TABLE t1;
-- Fails because no longer existent:
DROP SEQUENCE t1_f1_seq;
-- Now OK:
DROP SEQUENCE myseq2;
--
-- Alter sequence
--