Install a data-type-based solution for protecting pg_get_expr(). REL9_1_ALPHA1
authorTom Lane
Fri, 3 Sep 2010 01:34:55 +0000 (01:34 +0000)
committerTom Lane
Fri, 3 Sep 2010 01:34:55 +0000 (01:34 +0000)
Since the code underlying pg_get_expr() is not secure against malformed
input, and can't practically be made so, we need to prevent miscreants
from feeding arbitrary data to it.  We can do this securely by declaring
pg_get_expr() to take a new datatype "pg_node_tree" and declaring the
system catalog columns that hold nodeToString output to be of that type.
There is no way at SQL level to create a non-null value of type pg_node_tree.
Since the backend-internal operations that fill those catalog columns
operate below the SQL level, they are oblivious to the datatype relabeling
and don't need any changes.

19 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/func.sgml
src/backend/bootstrap/bootstrap.c
src/backend/utils/adt/pseudotypes.c
src/include/catalog/catversion.h
src/include/catalog/genbki.h
src/include/catalog/pg_attrdef.h
src/include/catalog/pg_cast.h
src/include/catalog/pg_constraint.h
src/include/catalog/pg_index.h
src/include/catalog/pg_proc.h
src/include/catalog/pg_rewrite.h
src/include/catalog/pg_trigger.h
src/include/catalog/pg_type.h
src/include/utils/builtins.h
src/test/regress/expected/opr_sanity.out
src/test/regress/expected/type_sanity.out
src/test/regress/sql/opr_sanity.sql
src/test/regress/sql/type_sanity.sql

index d287e84866949f8ec0181fd2e57f56ba9f057ea6..d53477ca47a70806638dad097a9361e4bd6137f6 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
 
      
       adbin
-      text
+      pg_node_tree
       
       The internal representation of the column default value
      
 
      
       conbin
-      text
+      pg_node_tree
       
       If a check constraint, an internal representation of the expression
      
 
      
       indexprs
-      text
+      pg_node_tree
       
       
        Expression trees (in nodeToString()
 
      
       indpred
-      text
+      pg_node_tree
       
       
        Expression tree (in nodeToString()
 
      
       proargdefaults
-      text
+      pg_node_tree
       
       
        Expression trees (in nodeToString() representation)
 
      
       ev_qual
-      text
+      pg_node_tree
       
       
        Expression tree (in the form of a
 
      
       ev_action
-      text
+      pg_node_tree
       
       
        Query tree (in the form of a
 
      
       tgqual
-      text
+      pg_node_tree
       
       Expression tree (in nodeToString()
        representation) for the trigger's WHEN condition, or null
 
      
       typdefaultbin
-      text
+      pg_node_tree
       
       
-       If typdefaultbin is not null, it is the nodeToString()
+       If typdefaultbin is not null, it is the
+       nodeToString()
        representation of a default expression for the type.  This is
        only used for domains.
       
        default expression represented by typdefaultbin.  If
        typdefaultbin is null and typdefault is
        not, then typdefault is the external representation of
-       the type's default value, which might be fed to the type's input
+       the type's default value, which can be fed to the type's input
        converter to produce a constant.
       
      
index 01fbd315b904dc8f64ab94eef04c1193c0a52c83..8d1015b9f8e967602bf174c0846bd73d67bb5115 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
  
   Functions and Operators
@@ -12746,13 +12746,13 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
        get definition of a constraint
       
       
-       pg_get_expr(expr_textrelation_oid)
+       pg_get_expr(pg_node_treerelation_oid)
        text
        decompile internal form of an expression, assuming that any Vars
        in it refer to the relation indicated by the second parameter
       
       
-       pg_get_expr(expr_textrelation_oid, pretty_bool)
+       pg_get_expr(pg_node_treerelation_oid, pretty_bool)
        text
        decompile internal form of an expression, assuming that any Vars
        in it refer to the relation indicated by the second parameter
index 080d80e296b7b8276f193c648e254e7c6d0dbb1d..c4744966ca23ff5b29ac1acdbd041c35e71d8cbc 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.261 2010/04/20 01:38:52 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.262 2010/09/03 01:34:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -72,7 +72,8 @@ int           numattr;            /* number of attributes for cur. rel */
 
 /*
  * Basic information associated with each type.  This is used before
- * pg_type is created.
+ * pg_type is filled, so it has to cover the datatypes used as column types
+ * in the core "bootstrapped" catalogs.
  *
  *     XXX several of these input/output functions do catalog scans
  *         (e.g., F_REGPROCIN scans pg_proc).  this obviously creates some
@@ -122,6 +123,8 @@ static const struct typinfo TypInfo[] = {
    F_XIDIN, F_XIDOUT},
    {"cid", CIDOID, 0, 4, true, 'i', 'p',
    F_CIDIN, F_CIDOUT},
+   {"pg_node_tree", PGNODETREEOID, 0, -1, false, 'i', 'x',
+   F_PG_NODE_TREE_IN, F_PG_NODE_TREE_OUT},
    {"int2vector", INT2VECTOROID, INT2OID, -1, false, 'i', 'p',
    F_INT2VECTORIN, F_INT2VECTOROUT},
    {"oidvector", OIDVECTOROID, OIDOID, -1, false, 'i', 'p',
index 6a56129e9719b67dec50cad5053b6c3a78e1340b..8986e06904400b8b3c8abf4b0bf3f57c96bef49a 100644 (file)
@@ -16,7 +16,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/adt/pseudotypes.c,v 1.23 2010/01/02 16:57:55 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/adt/pseudotypes.c,v 1.24 2010/09/03 01:34:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -398,3 +398,58 @@ shell_out(PG_FUNCTION_ARGS)
 
    PG_RETURN_VOID();           /* keep compiler quiet */
 }
+
+
+/*
+ * pg_node_tree_in     - input routine for type PG_NODE_TREE.
+ *
+ * pg_node_tree isn't really a pseudotype --- it's real enough to be a table
+ * column --- but it presently has no operations of its own, and disallows
+ * input too, so its I/O functions seem to fit here as much as anywhere.
+ */
+Datum
+pg_node_tree_in(PG_FUNCTION_ARGS)
+{
+   /*
+    * We disallow input of pg_node_tree values because the SQL functions that
+    * operate on the type are not secure against malformed input.
+    */
+   ereport(ERROR,
+           (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+            errmsg("cannot accept a value of type pg_node_tree")));
+
+   PG_RETURN_VOID();           /* keep compiler quiet */
+}
+
+/*
+ * pg_node_tree_out        - output routine for type PG_NODE_TREE.
+ *
+ * The internal representation is the same as TEXT, so just pass it off.
+ */
+Datum
+pg_node_tree_out(PG_FUNCTION_ARGS)
+{
+   return textout(fcinfo);
+}
+
+/*
+ * pg_node_tree_recv       - binary input routine for type PG_NODE_TREE.
+ */
+Datum
+pg_node_tree_recv(PG_FUNCTION_ARGS)
+{
+   ereport(ERROR,
+           (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+            errmsg("cannot accept a value of type pg_node_tree")));
+
+   PG_RETURN_VOID();           /* keep compiler quiet */
+}
+
+/*
+ * pg_node_tree_send       - binary output routine for type PG_NODE_TREE.
+ */
+Datum
+pg_node_tree_send(PG_FUNCTION_ARGS)
+{
+   return textsend(fcinfo);
+}
index f5a96c81f58e2eeb29d023de7ed91d143874f969..fef5e686a01bd678830771332fba206f77a3e604 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.597 2010/08/24 06:30:43 itagaki Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.598 2010/09/03 01:34:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 201008241
+#define CATALOG_VERSION_NO 201009021
 
 #endif
index 0fe9b74e716ed1a6dbe715341348cd3af8723e3a..9d92ca7b31d4bd97749b00b26dec489efca0c864 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/genbki.h,v 1.6 2010/01/05 01:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/genbki.h,v 1.7 2010/09/03 01:34:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,7 +35,8 @@
 #define DESCR(x)  extern int no_such_variable
 #define SHDESCR(x) extern int no_such_variable
 
-/* PHONY type definition for use in catalog structure definitions only */
+/* PHONY type definitions for use in catalog structure definitions only */
 typedef int aclitem;
+typedef int pg_node_tree;
 
 #endif   /* GENBKI_H */
index 81da20a50265212b8467146d07d0a99493ad4b8b..1b3153a7e7782174a0083dfab9b7d3c75773dc29 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_attrdef.h,v 1.26 2010/01/05 01:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_attrdef.h,v 1.27 2010/09/03 01:34:55 tgl Exp $
  *
  * NOTES
  *   the genbki.pl script reads this file and generates .bki
 
 CATALOG(pg_attrdef,2604)
 {
-   Oid         adrelid;
-   int2        adnum;
-   text        adbin;
-   text        adsrc;
+   Oid         adrelid;        /* OID of table containing attribute */
+   int2        adnum;          /* attnum of attribute */
+   pg_node_tree adbin;         /* nodeToString representation of default */
+   text        adsrc;          /* human-readable representation of default */
 } FormData_pg_attrdef;
 
 /* ----------------
index ca8b0b921bf5e3d97f398ea85ead3c791fd7ce26..db2333d4d983d640d8ff5647209203e2b84901ad 100644 (file)
@@ -10,7 +10,7 @@
  *
  * Copyright (c) 2002-2010, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.45 2010/07/16 02:15:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.46 2010/09/03 01:34:55 tgl Exp $
  *
  * NOTES
  *   the genbki.pl script reads this file and generates .bki
@@ -235,6 +235,9 @@ DATA(insert ( 1043   19 1400 i f ));
 DATA(insert (  18   23   77 e f ));
 DATA(insert (  23   18   78 e f ));
 
+/* pg_node_tree can be coerced to, but not from, text */
+DATA(insert (  194  25    0 i b ));
+
 /*
  * Datetime category
  */
index 63fddc697bc3dfd5e895b2daa85a053a8ce8135d..bbfd576733954481254f52e0587a0f444a7c3560 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_constraint.h,v 1.41 2010/08/07 02:44:07 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_constraint.h,v 1.42 2010/09/03 01:34:55 tgl Exp $
  *
  * NOTES
  *   the genbki.pl script reads this file and generates .bki
@@ -129,7 +129,7 @@ CATALOG(pg_constraint,2606)
    /*
     * If a check constraint, nodeToString representation of expression
     */
-   text        conbin;
+   pg_node_tree conbin;
 
    /*
     * If a check constraint, source-text representation of expression
index 685fae3c0e7dbef9f9e4dae0e63f8138ecd88b97..c6a1a22c02bc101d4c864be79a2dadbc83898817 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_index.h,v 1.50 2010/01/05 01:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_index.h,v 1.51 2010/09/03 01:34:55 tgl Exp $
  *
  * NOTES
  *   the genbki.pl script reads this file and generates .bki
@@ -45,10 +45,10 @@ CATALOG(pg_index,2610) BKI_WITHOUT_OIDS BKI_SCHEMA_MACRO
    int2vector  indkey;         /* column numbers of indexed cols, or 0 */
    oidvector   indclass;       /* opclass identifiers */
    int2vector  indoption;      /* per-column flags (AM-specific meanings) */
-   text        indexprs;       /* expression trees for index attributes that
+   pg_node_tree indexprs;      /* expression trees for index attributes that
                                 * are not simple column references; one for
                                 * each zero entry in indkey[] */
-   text        indpred;        /* expression tree for predicate, if a partial
+   pg_node_tree indpred;       /* expression tree for predicate, if a partial
                                 * index; else NULL */
 } FormData_pg_index;
 
index b3f1e14fd32fb74b4f9bdddc273c6ff70881fd50..33f5c218e3c0c47fd96fb22451c770c7a7439950 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.581 2010/08/24 06:30:43 itagaki Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.582 2010/09/03 01:34:55 tgl Exp $
  *
  * NOTES
  *   The script catalog/genbki.pl reads this file and generates .bki
@@ -57,8 +57,8 @@ CATALOG(pg_proc,1255) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81) BKI_SCHEMA_MACRO
    Oid         proallargtypes[1];      /* all param types (NULL if IN only) */
    char        proargmodes[1]; /* parameter modes (NULL if IN only) */
    text        proargnames[1]; /* parameter names (NULL if no names) */
-   text        proargdefaults; /* list of expression trees for argument
-                                * defaults (NULL if none) */
+   pg_node_tree proargdefaults; /* list of expression trees for argument
+                                 * defaults (NULL if none) */
    text        prosrc;         /* procedure source text */
    text        probin;         /* secondary procedure info (can be NULL) */
    text        proconfig[1];   /* procedure-local GUC settings */
@@ -399,6 +399,15 @@ DESCR("is contained by?");
 DATA(insert OID = 193 (  box_contain_pt    PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ box_contain_pt _null_ _null_ _null_ ));
 DESCR("contains?");
 
+DATA(insert OID = 195 (  pg_node_tree_in   PGNSP PGUID 12 1 0 0 f f f t f i 1 0 194 "2275" _null_ _null_ _null_ _null_ pg_node_tree_in _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 196 (  pg_node_tree_out  PGNSP PGUID 12 1 0 0 f f f t f i 1 0 2275 "194" _null_ _null_ _null_ _null_ pg_node_tree_out _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 197 (  pg_node_tree_recv PGNSP PGUID 12 1 0 0 f f f t f s 1 0 194 "2281" _null_ _null_ _null_ _null_ pg_node_tree_recv _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 198 (  pg_node_tree_send PGNSP PGUID 12 1 0 0 f f f t f s 1 0 17 "194" _null_ _null_ _null_ _null_   pg_node_tree_send _null_ _null_ _null_ ));
+DESCR("I/O");
+
 /* OIDS 200 - 299 */
 
 DATA(insert OID = 200 (  float4in         PGNSP PGUID 12 1 0 0 f f f t f i 1 0 700 "2275" _null_ _null_ _null_ _null_  float4in _null_ _null_ _null_ ));
@@ -2317,7 +2326,7 @@ DATA(insert OID = 1662 (  pg_get_triggerdef    PGNSP PGUID 12 1 0 0 f f f t f s
 DESCR("trigger description");
 DATA(insert OID = 1387 (  pg_get_constraintdef PGNSP PGUID 12 1 0 0 f f f t f s 1 0 25 "26" _null_ _null_ _null_ _null_ pg_get_constraintdef _null_ _null_ _null_ ));
 DESCR("constraint description");
-DATA(insert OID = 1716 (  pg_get_expr         PGNSP PGUID 12 1 0 0 f f f t f s 2 0 25 "25 26" _null_ _null_ _null_ _null_ pg_get_expr _null_ _null_ _null_ ));
+DATA(insert OID = 1716 (  pg_get_expr         PGNSP PGUID 12 1 0 0 f f f t f s 2 0 25 "194 26" _null_ _null_ _null_ _null_ pg_get_expr _null_ _null_ _null_ ));
 DESCR("deparse an encoded expression");
 DATA(insert OID = 1665 (  pg_get_serial_sequence   PGNSP PGUID 12 1 0 0 f f f t f s 2 0 25 "25 25" _null_ _null_ _null_ _null_ pg_get_serial_sequence _null_ _null_ _null_ ));
 DESCR("name of sequence for a serial column");
@@ -4170,7 +4179,7 @@ DATA(insert OID = 2507 (  pg_get_indexdef    PGNSP PGUID 12 1 0 0 f f f t f s 3
 DESCR("index description (full create statement or single expression) with pretty-print option");
 DATA(insert OID = 2508 (  pg_get_constraintdef PGNSP PGUID 12 1 0 0 f f f t f s 2 0 25 "26 16" _null_ _null_ _null_ _null_ pg_get_constraintdef_ext _null_ _null_ _null_ ));
 DESCR("constraint description with pretty-print option");
-DATA(insert OID = 2509 (  pg_get_expr         PGNSP PGUID 12 1 0 0 f f f t f s 3 0 25 "25 26 16" _null_ _null_ _null_ _null_ pg_get_expr_ext _null_ _null_ _null_ ));
+DATA(insert OID = 2509 (  pg_get_expr         PGNSP PGUID 12 1 0 0 f f f t f s 3 0 25 "194 26 16" _null_ _null_ _null_ _null_ pg_get_expr_ext _null_ _null_ _null_ ));
 DESCR("deparse an encoded expression with pretty-print option");
 DATA(insert OID = 2510 (  pg_prepared_statement PGNSP PGUID 12 1 1000 0 f f f t t s 0 0 2249 "" "{25,25,1184,2211,16}" "{o,o,o,o,o}" "{name,statement,prepare_time,parameter_types,from_sql}" _null_ pg_prepared_statement _null_ _null_ _null_ ));
 DESCR("get the prepared statements for this session");
index 20d4e00c43307477b10a6af5c4509fd5f8f8f08e..acb3e83b0581aaf0dfcafd49dbf3f6733f948b29 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_rewrite.h,v 1.35 2010/01/05 01:06:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_rewrite.h,v 1.36 2010/09/03 01:34:55 tgl Exp $
  *
  * NOTES
  *   the genbki.pl script reads this file and generates .bki
@@ -41,8 +41,8 @@ CATALOG(pg_rewrite,2618)
    bool        is_instead;
 
    /* NB: remaining fields must be accessed via heap_getattr */
-   text        ev_qual;
-   text        ev_action;
+   pg_node_tree ev_qual;
+   pg_node_tree ev_action;
 } FormData_pg_rewrite;
 
 /* ----------------
index 7c9547504333291aaf572522b8f6e125a3639526..9a548dca86ca7ec482c6d62e3c442a137028b7c5 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_trigger.h,v 1.39 2010/01/17 22:56:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_trigger.h,v 1.40 2010/09/03 01:34:55 tgl Exp $
  *
  * NOTES
  *   the genbki.pl script reads this file and generates .bki
@@ -53,7 +53,7 @@ CATALOG(pg_trigger,2620)
    /* VARIABLE LENGTH FIELDS (note: tgattr and tgargs must not be null) */
    int2vector  tgattr;         /* column numbers, if trigger is on columns */
    bytea       tgargs;         /* first\000second\000tgnargs\000 */
-   text        tgqual;         /* WHEN expression, or NULL if none */
+   pg_node_tree tgqual;        /* WHEN expression, or NULL if none */
 } FormData_pg_trigger;
 
 /* ----------------
index 3a10da25c374e49f8af067e4194dd0d03a58f1a0..5d997dc73160624898891a826a4fcbf1ae0212a1 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.212 2010/01/05 01:06:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.213 2010/09/03 01:34:55 tgl Exp $
  *
  * NOTES
  *   the genbki.pl script reads this file and generates .bki
@@ -199,7 +199,7 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO
     * a default expression for the type.  Currently this is only used for
     * domains.
     */
-   text        typdefaultbin;  /* VARIABLE LENGTH FIELD */
+   pg_node_tree typdefaultbin; /* VARIABLE LENGTH FIELD */
 
    /*
     * typdefault is NULL if the type has no associated default value. If
@@ -343,6 +343,10 @@ DESCR("XML content");
 #define XMLOID 142
 DATA(insert OID = 143 ( _xml      PGNSP PGUID -1 f b A f t \054 0 142 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
 
+DATA(insert OID = 194 (    pg_node_tree    PGNSP PGUID -1 f b S f t \054 0 0 0 pg_node_tree_in pg_node_tree_out pg_node_tree_recv pg_node_tree_send - - - i x f 0 -1 0 _null_ _null_ ));
+DESCR("string representing an internal node tree");
+#define PGNODETREEOID  194
+
 /* OIDS 200 - 299 */
 
 DATA(insert OID = 210 (  smgr     PGNSP PGUID 2 t b U f t \054 0 0 0 smgrin smgrout - - - - - s p f 0 -1 0 _null_ _null_ ));
index 4612cb354302eb0f81074ba120fb86e4065b966c..c7e50d2512232851ca0994b7acb7a87e69597767 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.355 2010/08/24 06:30:44 itagaki Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.356 2010/09/03 01:34:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -510,6 +510,10 @@ extern Datum anyelement_in(PG_FUNCTION_ARGS);
 extern Datum anyelement_out(PG_FUNCTION_ARGS);
 extern Datum shell_in(PG_FUNCTION_ARGS);
 extern Datum shell_out(PG_FUNCTION_ARGS);
+extern Datum pg_node_tree_in(PG_FUNCTION_ARGS);
+extern Datum pg_node_tree_out(PG_FUNCTION_ARGS);
+extern Datum pg_node_tree_recv(PG_FUNCTION_ARGS);
+extern Datum pg_node_tree_send(PG_FUNCTION_ARGS);
 
 /* regexp.c */
 extern Datum nameregexeq(PG_FUNCTION_ARGS);
index f6fee25de5574cef89640bbf0b3aa5f2dc7b5398..4703d497c1b4eed0a882f6365bc6eb6c46ed4962 100644 (file)
@@ -400,22 +400,25 @@ WHERE c.castfunc = p.oid AND
 -- As of 8.3, this finds the casts from xml to text, varchar, and bpchar,
 -- because those are binary-compatible while the reverse goes through
 -- texttoxml(), which does an XML syntax check.
-SELECT *
+-- As of 9.1, this finds the cast from pg_node_tree to text, which we
+-- intentionally do not provide a reverse pathway for.
+SELECT castsource::regtype, casttarget::regtype, castfunc, castcontext
 FROM pg_cast c
 WHERE c.castmethod = 'b' AND
     NOT EXISTS (SELECT 1 FROM pg_cast k
                 WHERE k.castmethod = 'b' AND
                     k.castsource = c.casttarget AND
                     k.casttarget = c.castsource);
- castsource | casttarget | castfunc | castcontext | castmethod 
-------------+------------+----------+-------------+------------
-         25 |       1042 |        0 | i           | b
-       1043 |       1042 |        0 | i           | b
-        650 |        869 |        0 | i           | b
-        142 |         25 |        0 | a           | b
-        142 |       1043 |        0 | a           | b
-        142 |       1042 |        0 | a           | b
-(6 rows)
+    castsource     |    casttarget     | castfunc | castcontext 
+-------------------+-------------------+----------+-------------
+ text              | character         |        0 | i
+ character varying | character         |        0 | i
+ pg_node_tree      | text              |        0 | i
+ cidr              | inet              |        0 | i
+ xml               | text              |        0 | a
+ xml               | character varying |        0 | a
+ xml               | character         |        0 | a
+(7 rows)
 
 -- **************** pg_operator ****************
 -- Look for illegal values in pg_operator fields.
index be86ee313be3c3bf2b80f1403f8416c5a9eac827..b7433653d1eebdb66415992940b00d8f43e82284 100644 (file)
@@ -57,18 +57,19 @@ WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
 (0 rows)
 
 -- Look for basic or enum types that don't have an array type.
--- NOTE: as of 8.0, this check finds smgr and unknown.
+-- NOTE: as of 9.1, this check finds pg_node_tree, smgr, and unknown.
 SELECT p1.oid, p1.typname
 FROM pg_type as p1
 WHERE p1.typtype in ('b','e') AND p1.typname NOT LIKE E'\\_%' AND NOT EXISTS
     (SELECT 1 FROM pg_type as p2
      WHERE p2.typname = ('_' || p1.typname)::name AND
            p2.typelem = p1.oid and p1.typarray = p2.oid);
- oid | typname 
------+---------
+ oid |   typname    
+-----+--------------
+ 194 | pg_node_tree
  210 | smgr
  705 | unknown
-(2 rows)
+(3 rows)
 
 -- Make sure typarray points to a varlena array type of our own base
 SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype, 
index 46ec24cca6f759f691391a7df2bbe85fd2d00eca..0d084a1f7a619a90e8fa96f1579c6cdb1180f921 100644 (file)
@@ -318,7 +318,10 @@ WHERE c.castfunc = p.oid AND
 -- because those are binary-compatible while the reverse goes through
 -- texttoxml(), which does an XML syntax check.
 
-SELECT *
+-- As of 9.1, this finds the cast from pg_node_tree to text, which we
+-- intentionally do not provide a reverse pathway for.
+
+SELECT castsource::regtype, casttarget::regtype, castfunc, castcontext
 FROM pg_cast c
 WHERE c.castmethod = 'b' AND
     NOT EXISTS (SELECT 1 FROM pg_cast k
index 265ef5e26e2f33d954c935f3ab8afeba9c6d7899..479bf8542a7e805937e6ccb7c7294ffd195224db 100644 (file)
@@ -51,7 +51,7 @@ WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
     (p1.typtype != 'c' AND p1.typrelid != 0);
 
 -- Look for basic or enum types that don't have an array type.
--- NOTE: as of 8.0, this check finds smgr and unknown.
+-- NOTE: as of 9.1, this check finds pg_node_tree, smgr, and unknown.
 
 SELECT p1.oid, p1.typname
 FROM pg_type as p1