]> granicus.if.org Git - postgresql/commitdiff
Install a data-type-based solution for protecting pg_get_expr(). REL9_1_ALPHA1
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 3 Sep 2010 01:34:55 +0000 (01:34 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
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 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.227 2010/08/25 18:18:41 petere Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.228 2010/09/03 01:34:54 tgl Exp $ -->
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
  -->
 
      <row>
       <entry><structfield>adbin</structfield></entry>
-      <entry><type>text</type></entry>
+      <entry><type>pg_node_tree</type></entry>
       <entry></entry>
       <entry>The internal representation of the column default value</entry>
      </row>
 
      <row>
       <entry><structfield>conbin</structfield></entry>
-      <entry><type>text</type></entry>
+      <entry><type>pg_node_tree</type></entry>
       <entry></entry>
       <entry>If a check constraint, an internal representation of the expression</entry>
      </row>
 
      <row>
       <entry><structfield>indexprs</structfield></entry>
-      <entry><type>text</type></entry>
+      <entry><type>pg_node_tree</type></entry>
       <entry></entry>
       <entry>
        Expression trees (in <function>nodeToString()</function>
 
      <row>
       <entry><structfield>indpred</structfield></entry>
-      <entry><type>text</type></entry>
+      <entry><type>pg_node_tree</type></entry>
       <entry></entry>
       <entry>
        Expression tree (in <function>nodeToString()</function>
 
      <row>
       <entry><structfield>proargdefaults</structfield></entry>
-      <entry><type>text</type></entry>
+      <entry><type>pg_node_tree</type></entry>
       <entry></entry>
       <entry>
        Expression trees (in <function>nodeToString()</function> representation)
 
      <row>
       <entry><structfield>ev_qual</structfield></entry>
-      <entry><type>text</type></entry>
+      <entry><type>pg_node_tree</type></entry>
       <entry></entry>
       <entry>
        Expression tree (in the form of a
 
      <row>
       <entry><structfield>ev_action</structfield></entry>
-      <entry><type>text</type></entry>
+      <entry><type>pg_node_tree</type></entry>
       <entry></entry>
       <entry>
        Query tree (in the form of a
 
      <row>
       <entry><structfield>tgqual</structfield></entry>
-      <entry><type>text</type></entry>
+      <entry><type>pg_node_tree</type></entry>
       <entry></entry>
       <entry>Expression tree (in <function>nodeToString()</function>
        representation) for the trigger's <literal>WHEN</> condition, or null
 
      <row>
       <entry><structfield>typdefaultbin</structfield></entry>
-      <entry><type>text</type></entry>
+      <entry><type>pg_node_tree</type></entry>
       <entry></entry>
       <entry><para>
-       If <structfield>typdefaultbin</> is not null, it is the <function>nodeToString()</function>
+       If <structfield>typdefaultbin</> is not null, it is the
+       <function>nodeToString()</function>
        representation of a default expression for the type.  This is
        only used for domains.
       </para></entry>
        default expression represented by <structfield>typdefaultbin</>.  If
        <structfield>typdefaultbin</> is null and <structfield>typdefault</> is
        not, then <structfield>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.
       </para></entry>
      </row>
index 01fbd315b904dc8f64ab94eef04c1193c0a52c83..8d1015b9f8e967602bf174c0846bd73d67bb5115 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.531 2010/09/01 18:22:29 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.532 2010/09/03 01:34:54 tgl Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -12746,13 +12746,13 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
        <entry>get definition of a constraint</entry>
       </row>
       <row>
-       <entry><literal><function>pg_get_expr</function>(<parameter>expr_text</parameter>, <parameter>relation_oid</>)</literal></entry>
+       <entry><literal><function>pg_get_expr</function>(<parameter>pg_node_tree</parameter>, <parameter>relation_oid</>)</literal></entry>
        <entry><type>text</type></entry>
        <entry>decompile internal form of an expression, assuming that any Vars
        in it refer to the relation indicated by the second parameter</entry>
       </row>
       <row>
-       <entry><literal><function>pg_get_expr</function>(<parameter>expr_text</parameter>, <parameter>relation_oid</>, <parameter>pretty_bool</>)</literal></entry>
+       <entry><literal><function>pg_get_expr</function>(<parameter>pg_node_tree</parameter>, <parameter>relation_oid</>, <parameter>pretty_bool</>)</literal></entry>
        <entry><type>text</type></entry>
        <entry>decompile internal form of an expression, assuming that any Vars
        in it refer to the relation indicated by the second parameter</entry>
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