Add pg_get_serial_sequence() function, and cause pg_dump to use it.
authorTom Lane
Fri, 25 Jun 2004 17:20:29 +0000 (17:20 +0000)
committerTom Lane
Fri, 25 Jun 2004 17:20:29 +0000 (17:20 +0000)
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

doc/src/sgml/func.sgml
src/backend/utils/adt/ruleutils.c
src/bin/pg_dump/pg_dump.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/utils/builtins.h

index 106c4cf775fa5f945225f7b965f453e225272a87..3c23f43a59f19bfb70bf75e9c104f1ee51933669 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -7228,29 +7228,13 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
     pg_get_userbyid
    
 
+   
+    pg_get_serial_sequence
+   
+
   
     lists functions that
    extract information from the system catalogs.
-   pg_get_viewdef,
-   pg_get_ruledef,
-   pg_get_indexdef,
-   pg_get_triggerdef, and
-   pg_get_constraintdef respectively
-   reconstruct the creating command for a view, rule, index, trigger, or
-   constraint.  (Note that this is a decompiled reconstruction, not
-   the original text of the command.)  Most of these come in two
-   variants, one of which can optionally pretty-print the result.
-   The pretty-printed format is more readable, but the default format is more
-   likely to be
-   interpreted the same way by future versions of PostgreSQL;
-   avoid using pretty-printed output for dump purposes.
-   Passing false for the pretty-print parameter yields the
-   same result as the variant that does not have the parameter at all.
-   pg_get_expr decompiles the internal form of an
-   individual expression, such as the default value for a column.  It
-   may be useful when examining the contents of system catalogs.
-   pg_get_userbyid
-   extracts a user's name given a user ID number.
   
 
    
@@ -7335,10 +7319,49 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
        name
        get user name with given ID
       
+      
+       pg_get_serial_sequence(table_namecolumn_name)
+       text
+       get name of the sequence that a serial or bigserial column
+       uses
+      
      
     
    
 
+  
+   pg_get_viewdef,
+   pg_get_ruledef,
+   pg_get_indexdef,
+   pg_get_triggerdef, and
+   pg_get_constraintdef respectively
+   reconstruct the creating command for a view, rule, index, trigger, or
+   constraint.  (Note that this is a decompiled reconstruction, not
+   the original text of the command.)
+   pg_get_expr decompiles the internal form of an
+   individual expression, such as the default value for a column.  It
+   may be useful when examining the contents of system catalogs.
+   Most of these functions come in two
+   variants, one of which can optionally pretty-print the result.
+   The pretty-printed format is more readable, but the default format is more
+   likely to be
+   interpreted the same way by future versions of PostgreSQL;
+   avoid using pretty-printed output for dump purposes.
+   Passing false for the pretty-print parameter yields the
+   same result as the variant that does not have the parameter at all.
+  
+
+  
+   pg_get_userbyid
+   extracts a user's name given a user ID number.
+   pg_get_serial_sequence
+   fetches the name of the sequence associated with a serial or
+   bigserial column.  The name is suitably formatted
+   for passing to the sequence functions (see 
+   linkend="functions-sequence">).
+   NULL is returned if the column does not have a sequence attached.
+  
+
    
     obj_description
    
index 1a2fe54d7ace4c19861fd9b4a7f1de1a849c2341..208cbf5d31b55990362347217e49a1e5ad1189cf 100644 (file)
@@ -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.
  *
 
 #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
  *
index 694a42e3b4afddad94cbdf3038018b2fe9320a8f..00793ebbced6299b55dd5ee87c45e8605c312454 100644 (file)
@@ -12,7 +12,7 @@
  * by PostgreSQL
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.376 2004/06/21 13:36:41 tgl Exp $
+ *   $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.377 2004/06/25 17:20:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -7319,9 +7319,27 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 
    if (!schemaOnly)
    {
+       TableInfo   *owning_tab;
+
        resetPQExpBuffer(query);
        appendPQExpBuffer(query, "SELECT pg_catalog.setval(");
-       appendStringLiteral(query, fmtId(tbinfo->dobj.name), true);
+       /*
+        * If this is a SERIAL sequence, then use the pg_get_serial_sequence
+        * function to avoid hard-coding the sequence name.  Note that this
+        * implicitly assumes that the sequence and its owning table are in
+        * the same schema, because we don't schema-qualify the reference.
+        */
+       if (OidIsValid(tbinfo->owning_tab) &&
+           (owning_tab = findTableByOid(tbinfo->owning_tab)) != NULL)
+       {
+           appendPQExpBuffer(query, "pg_catalog.pg_get_serial_sequence(");
+           appendStringLiteral(query, fmtId(owning_tab->dobj.name), true);
+           appendPQExpBuffer(query, ", ");
+           appendStringLiteral(query, owning_tab->attnames[tbinfo->owning_col-1], true);
+           appendPQExpBuffer(query, ")");
+       }
+       else
+           appendStringLiteral(query, fmtId(tbinfo->dobj.name), true);
        appendPQExpBuffer(query, ", %s, %s);\n",
                          last, (called ? "true" : "false"));
 
index 8bb47ad78c733e9076d20acf112f725739ba0dc9..ac6f8a1fa0cdddb4218c74ca2093644986d95941 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.239 2004/06/21 04:06:07 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.240 2004/06/25 17:20:28 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 200406202
+#define CATALOG_VERSION_NO 200406251
 
 #endif
index ecaf82efab1743d6b1436060368f82f134394b65..489fa9ca9baa5a5c250c65b681bab154364fb4bc 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.338 2004/06/16 01:26:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.339 2004/06/25 17:20:28 tgl Exp $
  *
  * NOTES
  *   The script catalog/genbki.sh reads this file and generates .bki
@@ -2238,6 +2238,8 @@ DATA(insert OID = 1387 (  pg_get_constraintdef PGNSP PGUID 12 f f t f s 1 25 "26
 DESCR("constraint description");
 DATA(insert OID = 1716 (  pg_get_expr         PGNSP PGUID 12 f f t f s 2 25 "25 26" _null_ pg_get_expr - _null_ ));
 DESCR("deparse an encoded expression");
+DATA(insert OID = 1665 (  pg_get_serial_sequence   PGNSP PGUID 12 f f t f s 2 25 "25 25" _null_  pg_get_serial_sequence - _null_ ));
+DESCR("name of sequence for a serial column");
 
 
 /* Generic referential integrity constraint triggers */
index 281f3067fa4485583ee72a763e5717e1e4691d59..99974cdec126497952244e71e125c0b3f720576d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.243 2004/06/13 21:57:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.244 2004/06/25 17:20:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -472,9 +472,10 @@ extern Datum pg_get_triggerdef(PG_FUNCTION_ARGS);
 extern Datum pg_get_constraintdef(PG_FUNCTION_ARGS);
 extern Datum pg_get_constraintdef_ext(PG_FUNCTION_ARGS);
 extern char *pg_get_constraintdef_string(Oid constraintId);
-extern Datum pg_get_userbyid(PG_FUNCTION_ARGS);
 extern Datum pg_get_expr(PG_FUNCTION_ARGS);
 extern Datum pg_get_expr_ext(PG_FUNCTION_ARGS);
+extern Datum pg_get_userbyid(PG_FUNCTION_ARGS);
+extern Datum pg_get_serial_sequence(PG_FUNCTION_ARGS);
 extern char *deparse_expression(Node *expr, List *dpcontext,
                   bool forceprefix, bool showimplicit);
 extern List *deparse_context_for(const char *aliasname, Oid relid);