]> granicus.if.org Git - postgresql/commitdiff
Add pg_get_serial_sequence() function, and cause pg_dump to use it.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 25 Jun 2004 17:20:29 +0000 (17:20 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
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 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.210 2004/06/24 19:57:14 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.211 2004/06/25 17:20:21 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -7228,29 +7228,13 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
     <primary>pg_get_userbyid</primary>
    </indexterm>
 
+   <indexterm zone="functions-misc">
+    <primary>pg_get_serial_sequence</primary>
+   </indexterm>
+
   <para>
    <xref linkend="functions-misc-catalog-table"> lists functions that
    extract information from the system catalogs.
-   <function>pg_get_viewdef</function>,
-   <function>pg_get_ruledef</function>,
-   <function>pg_get_indexdef</function>,
-   <function>pg_get_triggerdef</function>, and
-   <function>pg_get_constraintdef</function> 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 <quote>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 <productname>PostgreSQL</>;
-   avoid using pretty-printed output for dump purposes.
-   Passing <literal>false</> for the pretty-print parameter yields the
-   same result as the variant that does not have the parameter at all.
-   <function>pg_get_expr</function> 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.
-   <function>pg_get_userbyid</function>
-   extracts a user's name given a user ID number.
   </para>
 
    <table id="functions-misc-catalog-table">
@@ -7335,10 +7319,49 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
        <entry><type>name</type></entry>
        <entry>get user name with given ID</entry>
       </row>
+      <row>
+       <entry><literal><function>pg_get_serial_sequence</function>(<parameter>table_name</parameter>, <parameter>column_name</parameter>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get name of the sequence that a serial or bigserial column
+       uses</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
 
+  <para>
+   <function>pg_get_viewdef</function>,
+   <function>pg_get_ruledef</function>,
+   <function>pg_get_indexdef</function>,
+   <function>pg_get_triggerdef</function>, and
+   <function>pg_get_constraintdef</function> 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.)
+   <function>pg_get_expr</function> 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 <quote>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 <productname>PostgreSQL</>;
+   avoid using pretty-printed output for dump purposes.
+   Passing <literal>false</> for the pretty-print parameter yields the
+   same result as the variant that does not have the parameter at all.
+  </para>
+
+  <para>
+   <function>pg_get_userbyid</function>
+   extracts a user's name given a user ID number.
+   <function>pg_get_serial_sequence</function>
+   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 <xref
+   linkend="functions-sequence">).
+   NULL is returned if the column does not have a sequence attached.
+  </para>
+
    <indexterm zone="functions-misc">
     <primary>obj_description</primary>
    </indexterm>
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);