aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/ruleutils.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-06-25 17:20:29 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-06-25 17:20:29 +0000
commita0e842d81b435681a46e6dd1e50f14f9967ced37 (patch)
tree4eb2b2eaf42ff1048c9b942ef206eb005889e682 /src/backend/utils/adt/ruleutils.c
parentef2880263c95eeb4dc02624fd7fbc0c90edece83 (diff)
downloadpostgresql-a0e842d81b435681a46e6dd1e50f14f9967ced37.tar.gz
postgresql-a0e842d81b435681a46e6dd1e50f14f9967ced37.zip
Add pg_get_serial_sequence() function, and cause pg_dump to use it.
This eliminates the assumption that a serial column's sequence will have the same name on reload that it was given in the original database. Christopher Kings-Lynne
Diffstat (limited to 'src/backend/utils/adt/ruleutils.c')
-rw-r--r--src/backend/utils/adt/ruleutils.c114
1 files changed, 113 insertions, 1 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 1a2fe54d7ac..208cbf5d31b 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.173 2004/06/18 06:13:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.174 2004/06/25 17:20:24 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -42,12 +42,14 @@
#include "access/genam.h"
#include "catalog/catname.h"
+#include "catalog/dependency.h"
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_cast.h"
#include "catalog/pg_constraint.h"
+#include "catalog/pg_depend.h"
#include "catalog/pg_index.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
@@ -1232,6 +1234,116 @@ pg_get_userbyid(PG_FUNCTION_ARGS)
PG_RETURN_NAME(result);
}
+
+/*
+ * pg_get_serial_sequence
+ * Get the name of the sequence used by a serial column,
+ * formatted suitably for passing to setval, nextval or currval.
+ */
+Datum
+pg_get_serial_sequence(PG_FUNCTION_ARGS)
+{
+ text *tablename = PG_GETARG_TEXT_P(0);
+ text *columnname = PG_GETARG_TEXT_P(1);
+ RangeVar *tablerv;
+ 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,
+ "pg_get_serial_sequence"));
+ tableOid = RangeVarGetRelid(tablerv, false);
+
+ /* Get the number of the column */
+ column = DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(columnname)));
+
+ attnum = get_attnum(tableOid, column);
+ if (attnum == InvalidAttrNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ column, tablerv->relname)));
+
+ /* Search the dependency table for the dependent sequence */
+ depRel = heap_openr(DependRelationName, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_refclassid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(RelOid_pg_class));
+ 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, DependReferenceIndex, true,
+ SnapshotNow, 3, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
+
+ /*
+ * We assume any internal dependency of a relation on a column
+ * must be what we are looking for.
+ */
+ if (deprec->classid == RelOid_pg_class &&
+ deprec->objsubid == 0 &&
+ deprec->deptype == DEPENDENCY_INTERNAL)
+ {
+ sequenceId = deprec->objid;
+ break;
+ }
+ }
+
+ systable_endscan(scan);
+ heap_close(depRel, AccessShareLock);
+
+ if (OidIsValid(sequenceId))
+ {
+ HeapTuple classtup;
+ Form_pg_class classtuple;
+ char *nspname;
+ char *result;
+
+ /* Get the sequence's pg_class entry */
+ classtup = SearchSysCache(RELOID,
+ ObjectIdGetDatum(sequenceId),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(classtup))
+ elog(ERROR, "cache lookup failed for relation %u", sequenceId);
+ classtuple = (Form_pg_class) GETSTRUCT(classtup);
+
+ /* Get the namespace */
+ nspname = get_namespace_name(classtuple->relnamespace);
+ if (!nspname)
+ elog(ERROR, "cache lookup failed for namespace %u",
+ classtuple->relnamespace);
+
+ /* And construct the result string */
+ result = quote_qualified_identifier(nspname,
+ NameStr(classtuple->relname));
+
+ ReleaseSysCache(classtup);
+
+ PG_RETURN_TEXT_P(string_to_text(result));
+ }
+
+ PG_RETURN_NULL();
+}
+
+
/* ----------
* deparse_expression - General utility for deparsing expressions
*