aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/dependency.c55
-rw-r--r--src/backend/catalog/information_schema.sql5
-rw-r--r--src/backend/commands/sequence.c102
-rw-r--r--src/backend/commands/tablecmds.c63
-rw-r--r--src/backend/parser/analyze.c7
-rw-r--r--src/backend/utils/adt/regproc.c19
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 *