diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/dependency.c | 55 | ||||
-rw-r--r-- | src/backend/catalog/information_schema.sql | 5 | ||||
-rw-r--r-- | src/backend/commands/sequence.c | 102 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 63 | ||||
-rw-r--r-- | src/backend/parser/analyze.c | 7 | ||||
-rw-r--r-- | src/backend/utils/adt/regproc.c | 19 |
6 files changed, 140 insertions, 111 deletions
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 227b21c6564..8060055ff72 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -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; diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql index b56117a806f..4671f81f914 100644 --- a/src/backend/catalog/information_schema.sql +++ b/src/backend/catalog/information_schema.sql @@ -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 diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 5af9ba55b6e..9bf801f2308 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -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) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index b3d0e017f15..b2877cebb76 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -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 diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 099bb714831..be91872df55 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -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); diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index 3f150010273..3a52c8756d1 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -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 $ * *------------------------------------------------------------------------- */ @@ -1090,6 +1090,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. */ List * |