Install a data-type-based solution for protecting pg_get_expr().

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.
This commit is contained in:
Tom Lane 2010-09-03 01:34:55 +00:00
parent 8ab6a6b456
commit 303696c3b4
19 changed files with 149 additions and 62 deletions

View 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
-->
@ -797,7 +797,7 @@
<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>
@ -1917,7 +1917,7 @@
<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>
@ -2915,7 +2915,7 @@
<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>
@ -2928,7 +2928,7 @@
<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>
@ -3980,7 +3980,7 @@
<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)
@ -4129,7 +4129,7 @@
<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
@ -4140,7 +4140,7 @@
<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
@ -4839,7 +4839,7 @@
<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
@ -5622,10 +5622,11 @@
<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>
@ -5642,7 +5643,7 @@
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>

View 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>

View 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',

View 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);
}

View 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

View 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 */

View 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
@ -30,10 +30,10 @@
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;
/* ----------------

View 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
*/

View 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

View 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;

View 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");

View 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;
/* ----------------

View 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;
/* ----------------

View 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_ ));

View 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);

View 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.

View 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,

View 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

View 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