Allow the second argument of pg_get_expr() to be just zero when deparsing
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 26 May 2009 17:36:05 +0000 (17:36 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 26 May 2009 17:36:05 +0000 (17:36 +0000)
an expression that's not supposed to contain variables.  Per discussion
with Gevik Babakhani, this eliminates the need for an ugly kluge (namely,
specifying some unrelated relation name).  Remove one such kluge from
pg_dump.

doc/src/sgml/func.sgml
src/backend/utils/adt/ruleutils.c
src/bin/pg_dump/pg_dump.c

index 0042b76417bb10cc13262d893545c25490056af0..42c6862471c17696b4635b3ea66bae613c2bd526 100644 (file)
@@ -12367,7 +12367,9 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
    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 can be
-   useful when examining the contents of system catalogs.
+   useful when examining the contents of system catalogs.  If the expression
+   might contain Vars, specify the OID of the relation they refer to as the
+   second parameter; if no Vars are expected, zero is sufficient.
    <function>pg_get_viewdef</function> reconstructs the <command>SELECT</>
    query that defines a view. Most of these functions come in two variants,
    one of which can optionally <quote>pretty-print</> the result.  The
index 63aecb0703d9c4969c6b4ac7f032528337158c86..b16a425daad29f5ffb774295220a7bf708096250 100644 (file)
@@ -146,7 +146,7 @@ static char *pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,
                                           int prettyFlags);
 static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
                                                        int prettyFlags);
-static char *pg_get_expr_worker(text *expr, Oid relid, char *relname,
+static text *pg_get_expr_worker(text *expr, Oid relid, const char *relname,
                                   int prettyFlags);
 static int print_function_arguments(StringInfo buf, HeapTuple proctup,
                                                 bool print_table_args, bool print_defaults);
@@ -1198,7 +1198,8 @@ decompile_column_index_array(Datum column_index_array, Oid relId,
  *
  * Currently, the expression can only refer to a single relation, namely
  * the one specified by the second parameter.  This is sufficient for
- * partial indexes, column default expressions, etc.
+ * partial indexes, column default expressions, etc.  We also support
+ * Var-free expressions, for which the OID can be InvalidOid.
  * ----------
  */
 Datum
@@ -1208,12 +1209,24 @@ pg_get_expr(PG_FUNCTION_ARGS)
        Oid                     relid = PG_GETARG_OID(1);
        char       *relname;
 
-       /* Get the name for the relation */
-       relname = get_rel_name(relid);
-       if (relname == NULL)
-               PG_RETURN_NULL();               /* should we raise an error? */
+       if (OidIsValid(relid))
+       {
+               /* Get the name for the relation */
+               relname = get_rel_name(relid);
 
-       PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, 0)));
+               /*
+                * If the OID isn't actually valid, don't throw an error, just return
+                * NULL.  This is a bit questionable, but it's what we've done
+                * historically, and it can help avoid unwanted failures when
+                * examining catalog entries for just-deleted relations.
+                */
+               if (relname == NULL)
+                       PG_RETURN_NULL();
+       }
+       else
+               relname = NULL;
+
+       PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, 0));
 }
 
 Datum
@@ -1227,16 +1240,22 @@ pg_get_expr_ext(PG_FUNCTION_ARGS)
 
        prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;
 
-       /* Get the name for the relation */
-       relname = get_rel_name(relid);
-       if (relname == NULL)
-               PG_RETURN_NULL();               /* should we raise an error? */
+       if (OidIsValid(relid))
+       {
+               /* Get the name for the relation */
+               relname = get_rel_name(relid);
+               /* See notes above */
+               if (relname == NULL)
+                       PG_RETURN_NULL();
+       }
+       else
+               relname = NULL;
 
-       PG_RETURN_TEXT_P(string_to_text(pg_get_expr_worker(expr, relid, relname, prettyFlags)));
+       PG_RETURN_TEXT_P(pg_get_expr_worker(expr, relid, relname, prettyFlags));
 }
 
-static char *
-pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
+static text *
+pg_get_expr_worker(text *expr, Oid relid, const char *relname, int prettyFlags)
 {
        Node       *node;
        List       *context;
@@ -1249,14 +1268,19 @@ pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
        /* Convert expression to node tree */
        node = (Node *) stringToNode(exprstr);
 
+       pfree(exprstr);
+
+       /* Prepare deparse context if needed */
+       if (OidIsValid(relid))
+               context = deparse_context_for(relname, relid);
+       else
+               context = NIL;
+
        /* Deparse */
-       context = deparse_context_for(relname, relid);
        str = deparse_expression_pretty(node, context, false, false,
                                                                        prettyFlags, 0);
 
-       pfree(exprstr);
-
-       return str;
+       return string_to_text(str);
 }
 
 
index 785f3a9003c4af228b992f4d3dafed849655866d..826215068c99fb1f6ca3f36f6d4b0663ca2d686e 100644 (file)
@@ -6186,13 +6186,14 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                                                  "typanalyze::pg_catalog.oid AS typanalyzeoid, "
                                                  "typcategory, typispreferred, "
                                                  "typdelim, typbyval, typalign, typstorage, "
-                                                 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, typdefault "
+                                                 "pg_catalog.pg_get_expr(typdefaultbin, 0) AS typdefaultbin, typdefault "
                                                  "FROM pg_catalog.pg_type "
                                                  "WHERE oid = '%u'::pg_catalog.oid",
                                                  tinfo->dobj.catId.oid);
        }
        else if (fout->remoteVersion >= 80300)
        {
+               /* Before 8.4, pg_get_expr does not allow 0 for its second arg */
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, typreceive, typsend, "
                                                  "typmodin, typmodout, typanalyze, "