Implement types regprocedure, regoper, regoperator, regclass, regtype

per pghackers discussion.  Add some more typsanity tests, and clean
up some problems exposed thereby (broken or missing array types for
some built-in types).  Also, clean up loose ends from unknownin/out
patch.
This commit is contained in:
Tom Lane 2002-04-25 02:56:56 +00:00
parent 4eac3919dd
commit 52200befd0
28 changed files with 1638 additions and 229 deletions

View File

@ -1,10 +1,10 @@
findoidjoins findoidjoins
This program scans a database, and prints oid fields (also regproc fields) This program scans a database, and prints oid fields (also regproc, regclass
and the tables they join to. CAUTION: it is ver-r-r-y slow on a large and regtype fields) and the tables they join to. CAUTION: it is ver-r-r-y
database, or even a not-so-large one. We don't really recommend running slow on a large database, or even a not-so-large one. We don't really
it on anything but an empty database, such as template1. recommend running it on anything but an empty database, such as template1.
Uses pgeasy library. Uses pgeasy library.

View File

@ -39,7 +39,9 @@ main(int argc, char **argv)
WHERE a.attnum > 0 AND \ WHERE a.attnum > 0 AND \
relkind = 'r' AND \ relkind = 'r' AND \
(typname = 'oid' OR \ (typname = 'oid' OR \
typname = 'regproc') AND \ typname = 'regproc' OR \
typname = 'regclass' OR \
typname = 'regtype') AND \
a.attrelid = c.oid AND \ a.attrelid = c.oid AND \
a.atttypid = t.oid \ a.atttypid = t.oid \
ORDER BY 2, a.attnum ; \ ORDER BY 2, a.attnum ; \
@ -77,7 +79,7 @@ main(int argc, char **argv)
DECLARE c_matches BINARY CURSOR FOR \ DECLARE c_matches BINARY CURSOR FOR \
SELECT count(*)::int4 \ SELECT count(*)::int4 \
FROM \"%s\" t1, \"%s\" t2 \ FROM \"%s\" t1, \"%s\" t2 \
WHERE RegprocToOid(t1.\"%s\") = t2.oid ", WHERE t1.\"%s\"::oid = t2.oid ",
relname, relname2, attname); relname, relname2, attname);
doquery(query); doquery(query);

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/bki.sgml,v 1.10 2002/03/22 19:20:02 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/bki.sgml,v 1.11 2002/04/25 02:56:55 tgl Exp $
--> -->
<chapter id="bki"> <chapter id="bki">
@ -122,7 +122,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/bki.sgml,v 1.10 2002/03/22 19:20:02 petere
storage. The following types are allowed: <type>bool</type>, storage. The following types are allowed: <type>bool</type>,
<type>bytea</type>, <type>char</type> (1 byte), <type>bytea</type>, <type>char</type> (1 byte),
<type>name</type>, <type>int2</type>, <type>int2vector</type>, <type>name</type>, <type>int2</type>, <type>int2vector</type>,
<type>int4</type>, <type>regproc</type>, <type>text</type>, <type>int4</type>, <type>regproc</type>, <type>regclass</type>,
<type>regtype</type>, <type>text</type>,
<type>oid</type>, <type>tid</type>, <type>xid</type>, <type>oid</type>, <type>tid</type>, <type>xid</type>,
<type>cid</type>, <type>oidvector</type>, <type>smgr</type>, <type>cid</type>, <type>oidvector</type>, <type>smgr</type>,
<type>_int4</type> (array), <type>_aclitem</type> (array). <type>_int4</type> (array), <type>_aclitem</type> (array).

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.89 2002/04/21 18:58:00 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.90 2002/04/25 02:56:55 tgl Exp $
--> -->
<chapter id="datatype"> <chapter id="datatype">
@ -172,12 +172,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.89 2002/04/21 18:58:00 th
<entry>exact numeric with selectable precision</entry> <entry>exact numeric with selectable precision</entry>
</row> </row>
<row>
<entry><type>oid</type></entry>
<entry></entry>
<entry>object identifier</entry>
</row>
<row> <row>
<entry><type>path</type></entry> <entry><type>path</type></entry>
<entry></entry> <entry></entry>
@ -2894,6 +2888,165 @@ SELECT SUBSTRING(b FROM 1 FOR 2) FROM test;
</sect1> </sect1>
<sect1 id="datatype-oid">
<title>Object Identifier Types</title>
<indexterm zone="datatype-oid">
<primary>object identifier</primary>
<secondary>data type</secondary>
</indexterm>
<indexterm zone="datatype-oid">
<primary>oid</primary>
</indexterm>
<indexterm zone="datatype-oid">
<primary>regproc</primary>
</indexterm>
<indexterm zone="datatype-oid">
<primary>regprocedure</primary>
</indexterm>
<indexterm zone="datatype-oid">
<primary>regoper</primary>
</indexterm>
<indexterm zone="datatype-oid">
<primary>regoperator</primary>
</indexterm>
<indexterm zone="datatype-oid">
<primary>regclass</primary>
</indexterm>
<indexterm zone="datatype-oid">
<primary>regtype</primary>
</indexterm>
<para>
Object identifiers (OIDs) are used internally by
<productname>PostgreSQL</productname> as primary keys for various system
tables. Also, an OID system column is added to user-created tables
(unless <literal>WITHOUT OIDS</> is specified at table creation time).
Type <type>oid</> represents an object identifier. There are also
several aliases for <type>oid</>: <type>regproc</>, <type>regprocedure</>,
<type>regoper</>, <type>regoperator</>, <type>regclass</>,
and <type>regtype</>.
</para>
<para>
The <type>oid</> type is currently implemented as an unsigned four-byte
integer.
Therefore, it is not large enough to provide database-wide uniqueness
in large databases, or even in large individual tables. So, using a
user-created table's OID column as a primary key is discouraged.
OIDs are best used only for references to system tables.
</para>
<para>
The <type>oid</> type itself has few operations beyond comparison
(which is implemented as unsigned comparison). It can be cast to
integer, however, and then manipulated using the standard integer
operators. (Beware of possible signed-versus-unsigned confusion
if you do this.)
</para>
<para>
The <type>oid</> alias types have no operations of their own except
for specialized input and output routines. These routines are able
to accept and display symbolic names for system objects, rather than
the raw numeric value that type <type>oid</> would use. The alias
types allow simplified lookup of OID values for objects: for example,
one may write <literal>'mytable'::regclass</> to get the OID of table
<literal>mytable</>, rather than <literal>SELECT oid FROM pg_class WHERE
relname = 'mytable'</>. (In reality, a much more complicated SELECT would
be needed to deal with selecting the right OID when there are multiple
tables named <literal>mytable</> in different schemas.)
</para>
<para>
<table tocentry="1">
<title>Object Identifier Types</title>
<tgroup cols="4">
<thead>
<row>
<entry>Type name</entry>
<entry>References</entry>
<entry>Description</entry>
<entry>Examples</entry>
</row>
</thead>
<tbody>
<row>
<entry><type>oid</></entry>
<entry>any</entry>
<entry>Numeric object identifier</entry>
<entry>564182</entry>
</row>
<row>
<entry><type>regproc</></entry>
<entry>pg_proc</entry>
<entry>Function name</entry>
<entry>sum</entry>
</row>
<row>
<entry><type>regprocedure</></entry>
<entry>pg_proc</entry>
<entry>Function with argument types</entry>
<entry>sum(int4)</entry>
</row>
<row>
<entry><type>regoper</></entry>
<entry>pg_operator</entry>
<entry>Operator name</entry>
<entry>+</entry>
</row>
<row>
<entry><type>regoperator</></entry>
<entry>pg_operator</entry>
<entry>Operator with argument types</entry>
<entry>*(integer,integer) -(NONE,integer)</entry>
</row>
<row>
<entry><type>regclass</></entry>
<entry>pg_class</entry>
<entry>Relation name</entry>
<entry>pg_type</entry>
</row>
<row>
<entry><type>regtype</></entry>
<entry>pg_type</entry>
<entry>Type name</entry>
<entry>integer</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
All of the alias types accept schema-qualified names, and will
display schema-qualified names on output if the object would not
be found in the current search path without being qualified.
The <type>regproc</> and <type>regoper</> alias types will only
accept input names that are unique (not overloaded), so they are
of limited use; for most uses <type>regprocedure</> or
<type>regoperator</> is more appropriate. For <type>regoperator</>,
unary operators are identified by writing NONE for the unused
operand.
</para>
</sect1>
</chapter> </chapter>
<!-- Keep this comment at the end of the file <!-- Keep this comment at the end of the file

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.125 2002/03/26 19:15:16 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.126 2002/04/25 02:56:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -109,12 +109,14 @@ static struct typinfo Procid[] = {
{"int2vector", INT2VECTOROID, 0, INDEX_MAX_KEYS * 2, F_INT2VECTORIN, F_INT2VECTOROUT}, {"int2vector", INT2VECTOROID, 0, INDEX_MAX_KEYS * 2, F_INT2VECTORIN, F_INT2VECTOROUT},
{"int4", INT4OID, 0, 4, F_INT4IN, F_INT4OUT}, {"int4", INT4OID, 0, 4, F_INT4IN, F_INT4OUT},
{"regproc", REGPROCOID, 0, 4, F_REGPROCIN, F_REGPROCOUT}, {"regproc", REGPROCOID, 0, 4, F_REGPROCIN, F_REGPROCOUT},
{"regclass", REGCLASSOID, 0, 4, F_REGCLASSIN, F_REGCLASSOUT},
{"regtype", REGTYPEOID, 0, 4, F_REGTYPEIN, F_REGTYPEOUT},
{"text", TEXTOID, 0, -1, F_TEXTIN, F_TEXTOUT}, {"text", TEXTOID, 0, -1, F_TEXTIN, F_TEXTOUT},
{"oid", OIDOID, 0, 4, F_OIDIN, F_OIDOUT}, {"oid", OIDOID, 0, 4, F_OIDIN, F_OIDOUT},
{"tid", TIDOID, 0, 6, F_TIDIN, F_TIDOUT}, {"tid", TIDOID, 0, 6, F_TIDIN, F_TIDOUT},
{"xid", XIDOID, 0, 4, F_XIDIN, F_XIDOUT}, {"xid", XIDOID, 0, 4, F_XIDIN, F_XIDOUT},
{"cid", CIDOID, 0, 4, F_CIDIN, F_CIDOUT}, {"cid", CIDOID, 0, 4, F_CIDIN, F_CIDOUT},
{"oidvector", 30, 0, INDEX_MAX_KEYS * 4, F_OIDVECTORIN, F_OIDVECTOROUT}, {"oidvector", OIDVECTOROID, 0, INDEX_MAX_KEYS * 4, F_OIDVECTORIN, F_OIDVECTOROUT},
{"smgr", 210, 0, 2, F_SMGRIN, F_SMGROUT}, {"smgr", 210, 0, 2, F_SMGRIN, F_SMGROUT},
{"_int4", 1007, INT4OID, -1, F_ARRAY_IN, F_ARRAY_OUT}, {"_int4", 1007, INT4OID, -1, F_ARRAY_IN, F_ARRAY_OUT},
{"_aclitem", 1034, 1033, -1, F_ARRAY_IN, F_ARRAY_OUT} {"_aclitem", 1034, 1033, -1, F_ARRAY_IN, F_ARRAY_OUT}
@ -600,7 +602,7 @@ DefineAttr(char *name, char *type, int attnum)
attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */ attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
attlen = attrtypes[attnum]->attlen = Ap->am_typ.typlen; attlen = attrtypes[attnum]->attlen = Ap->am_typ.typlen;
attrtypes[attnum]->attbyval = Ap->am_typ.typbyval; attrtypes[attnum]->attbyval = Ap->am_typ.typbyval;
attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;; attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;
attrtypes[attnum]->attalign = Ap->am_typ.typalign; attrtypes[attnum]->attalign = Ap->am_typ.typalign;
} }
else else
@ -610,28 +612,37 @@ DefineAttr(char *name, char *type, int attnum)
elog(DEBUG3, "column %s %s", NameStr(attrtypes[attnum]->attname), type); elog(DEBUG3, "column %s %s", NameStr(attrtypes[attnum]->attname), type);
attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */ attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
attlen = attrtypes[attnum]->attlen = Procid[typeoid].len; attlen = attrtypes[attnum]->attlen = Procid[typeoid].len;
attrtypes[attnum]->attstorage = 'p';
/* /*
* Cheat like mad to fill in these items from the length only. * Cheat like mad to fill in these items from the length only.
* This only has to work for types used in the system catalogs... * This only has to work for types that appear in Procid[].
*/ */
switch (attlen) switch (attlen)
{ {
case 1: case 1:
attrtypes[attnum]->attbyval = true; attrtypes[attnum]->attbyval = true;
attrtypes[attnum]->attstorage = 'p';
attrtypes[attnum]->attalign = 'c'; attrtypes[attnum]->attalign = 'c';
break; break;
case 2: case 2:
attrtypes[attnum]->attbyval = true; attrtypes[attnum]->attbyval = true;
attrtypes[attnum]->attstorage = 'p';
attrtypes[attnum]->attalign = 's'; attrtypes[attnum]->attalign = 's';
break; break;
case 4: case 4:
attrtypes[attnum]->attbyval = true; attrtypes[attnum]->attbyval = true;
attrtypes[attnum]->attstorage = 'p';
attrtypes[attnum]->attalign = 'i';
break;
case -1:
attrtypes[attnum]->attbyval = false;
attrtypes[attnum]->attstorage = 'x';
attrtypes[attnum]->attalign = 'i'; attrtypes[attnum]->attalign = 'i';
break; break;
default: default:
/* TID and fixed-length arrays, such as oidvector */
attrtypes[attnum]->attbyval = false; attrtypes[attnum]->attbyval = false;
attrtypes[attnum]->attstorage = 'p';
attrtypes[attnum]->attalign = 'i'; attrtypes[attnum]->attalign = 'i';
break; break;
} }
@ -803,6 +814,13 @@ cleanup()
/* ---------------- /* ----------------
* gettype * gettype
*
* NB: this is really ugly; it will return an integer index into Procid[],
* and not an OID at all, until the first reference to a type not known in
* Procid[]. At that point it will read and cache pg_type in the Typ array,
* and subsequently return a real OID (and set the global pointer Ap to
* point at the found row in Typ). So caller must check whether Typ is
* still NULL to determine what the return value is!
* ---------------- * ----------------
*/ */
static Oid static Oid
@ -827,7 +845,7 @@ gettype(char *type)
} }
else else
{ {
for (i = 0; i <= n_types; i++) for (i = 0; i < n_types; i++)
{ {
if (strncmp(type, Procid[i].name, NAMEDATALEN) == 0) if (strncmp(type, Procid[i].name, NAMEDATALEN) == 0)
return i; return i;

View File

@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.11 2002/04/17 20:57:56 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.12 2002/04/25 02:56:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -365,9 +365,12 @@ OpclassnameGetOpcid(Oid amid, const char *opcname)
* Given a possibly-qualified function name and argument count, * Given a possibly-qualified function name and argument count,
* retrieve a list of the possible matches. * retrieve a list of the possible matches.
* *
* If nargs is -1, we return all functions matching the given name,
* regardless of argument count.
*
* We search a single namespace if the function name is qualified, else * We search a single namespace if the function name is qualified, else
* all namespaces in the search path. The return list will never contain * all namespaces in the search path. The return list will never contain
* multiple entries with identical argument types --- in the multiple- * multiple entries with identical argument lists --- in the multiple-
* namespace case, we arrange for entries in earlier namespaces to mask * namespace case, we arrange for entries in earlier namespaces to mask
* identical entries in later namespaces. * identical entries in later namespaces.
*/ */
@ -423,11 +426,16 @@ FuncnameGetCandidates(List *names, int nargs)
namespaceId = InvalidOid; namespaceId = InvalidOid;
} }
/* Search syscache by name and nargs only */ /* Search syscache by name and (optionally) nargs only */
catlist = SearchSysCacheList(PROCNAMENSP, 2, if (nargs >= 0)
CStringGetDatum(funcname), catlist = SearchSysCacheList(PROCNAMENSP, 2,
Int16GetDatum(nargs), CStringGetDatum(funcname),
0, 0); Int16GetDatum(nargs),
0, 0);
else
catlist = SearchSysCacheList(PROCNAMENSP, 1,
CStringGetDatum(funcname),
0, 0, 0);
for (i = 0; i < catlist->n_members; i++) for (i = 0; i < catlist->n_members; i++)
{ {
@ -436,6 +444,8 @@ FuncnameGetCandidates(List *names, int nargs)
int pathpos = 0; int pathpos = 0;
FuncCandidateList newResult; FuncCandidateList newResult;
nargs = procform->pronargs;
if (OidIsValid(namespaceId)) if (OidIsValid(namespaceId))
{ {
/* Consider only procs in specified namespace */ /* Consider only procs in specified namespace */
@ -478,7 +488,8 @@ FuncnameGetCandidates(List *names, int nargs)
if (catlist->ordered) if (catlist->ordered)
{ {
if (memcmp(procform->proargtypes, resultList->args, if (nargs == resultList->nargs &&
memcmp(procform->proargtypes, resultList->args,
nargs * sizeof(Oid)) == 0) nargs * sizeof(Oid)) == 0)
prevResult = resultList; prevResult = resultList;
else else
@ -490,7 +501,8 @@ FuncnameGetCandidates(List *names, int nargs)
prevResult; prevResult;
prevResult = prevResult->next) prevResult = prevResult->next)
{ {
if (memcmp(procform->proargtypes, prevResult->args, if (nargs == prevResult->nargs &&
memcmp(procform->proargtypes, prevResult->args,
nargs * sizeof(Oid)) == 0) nargs * sizeof(Oid)) == 0)
break; break;
} }
@ -517,6 +529,7 @@ FuncnameGetCandidates(List *names, int nargs)
+ nargs * sizeof(Oid)); + nargs * sizeof(Oid));
newResult->pathpos = pathpos; newResult->pathpos = pathpos;
newResult->oid = proctup->t_data->t_oid; newResult->oid = proctup->t_data->t_oid;
newResult->nargs = nargs;
memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid)); memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
newResult->next = resultList; newResult->next = resultList;
@ -533,14 +546,17 @@ FuncnameGetCandidates(List *names, int nargs)
* Given a possibly-qualified operator name and operator kind, * Given a possibly-qualified operator name and operator kind,
* retrieve a list of the possible matches. * retrieve a list of the possible matches.
* *
* If oprkind is '\0', we return all operators matching the given name,
* regardless of arguments.
*
* We search a single namespace if the operator name is qualified, else * We search a single namespace if the operator name is qualified, else
* all namespaces in the search path. The return list will never contain * all namespaces in the search path. The return list will never contain
* multiple entries with identical argument types --- in the multiple- * multiple entries with identical argument lists --- in the multiple-
* namespace case, we arrange for entries in earlier namespaces to mask * namespace case, we arrange for entries in earlier namespaces to mask
* identical entries in later namespaces. * identical entries in later namespaces.
* *
* The returned items always have two args[] entries --- one or the other * The returned items always have two args[] entries --- one or the other
* will be InvalidOid for a prefix or postfix oprkind. * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
*/ */
FuncCandidateList FuncCandidateList
OpernameGetCandidates(List *names, char oprkind) OpernameGetCandidates(List *names, char oprkind)
@ -606,8 +622,8 @@ OpernameGetCandidates(List *names, char oprkind)
int pathpos = 0; int pathpos = 0;
FuncCandidateList newResult; FuncCandidateList newResult;
/* Ignore operators of wrong kind */ /* Ignore operators of wrong kind, if specific kind requested */
if (operform->oprkind != oprkind) if (oprkind && operform->oprkind != oprkind)
continue; continue;
if (OidIsValid(namespaceId)) if (OidIsValid(namespaceId))
@ -690,6 +706,7 @@ OpernameGetCandidates(List *names, char oprkind)
palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid)); palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid));
newResult->pathpos = pathpos; newResult->pathpos = pathpos;
newResult->oid = opertup->t_data->t_oid; newResult->oid = opertup->t_data->t_oid;
newResult->nargs = 2;
newResult->args[0] = operform->oprleft; newResult->args[0] = operform->oprleft;
newResult->args[1] = operform->oprright; newResult->args[1] = operform->oprright;
newResult->next = resultList; newResult->next = resultList;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.66 2002/04/16 23:08:10 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.67 2002/04/25 02:56:55 tgl Exp $
* *
* NOTES * NOTES
* these routines moved here from commands/define.c and somewhat cleaned up. * these routines moved here from commands/define.c and somewhat cleaned up.
@ -138,7 +138,7 @@ OperatorGet(const char *operatorName,
ObjectIdGetDatum(operatorNamespace)); ObjectIdGetDatum(operatorNamespace));
if (HeapTupleIsValid(tup)) if (HeapTupleIsValid(tup))
{ {
regproc oprcode = ((Form_pg_operator) GETSTRUCT(tup))->oprcode; RegProcedure oprcode = ((Form_pg_operator) GETSTRUCT(tup))->oprcode;
operatorObjectId = tup->t_data->t_oid; operatorObjectId = tup->t_data->t_oid;
*defined = RegProcedureIsValid(oprcode); *defined = RegProcedureIsValid(oprcode);
@ -168,7 +168,7 @@ OperatorLookup(List *operatorName,
bool *defined) bool *defined)
{ {
Oid operatorObjectId; Oid operatorObjectId;
regproc oprcode; RegProcedure oprcode;
operatorObjectId = LookupOperName(operatorName, leftObjectId, operatorObjectId = LookupOperName(operatorName, leftObjectId,
rightObjectId); rightObjectId);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.70 2002/04/11 20:00:00 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.71 2002/04/25 02:56:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -81,8 +81,7 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
if (!con->constisnull) if (!con->constisnull)
{ {
/* We know the source constant is really of type 'text' */ char *val = DatumGetCString(DirectFunctionCall1(unknownout,
char *val = DatumGetCString(DirectFunctionCall1(textout,
con->constvalue)); con->constvalue));
newcon->constvalue = stringTypeDatum(targetType, val, atttypmod); newcon->constvalue = stringTypeDatum(targetType, val, atttypmod);
@ -477,6 +476,11 @@ TypeCategory(Oid inType)
case (OIDOID): case (OIDOID):
case (REGPROCOID): case (REGPROCOID):
case (REGPROCEDUREOID):
case (REGOPEROID):
case (REGOPERATOROID):
case (REGCLASSOID):
case (REGTYPEOID):
case (INT2OID): case (INT2OID):
case (INT4OID): case (INT4OID):
case (INT8OID): case (INT8OID):
@ -540,38 +544,72 @@ TypeCategory(Oid inType)
* to allow for better type extensibility. * to allow for better type extensibility.
*/ */
#define TypeIsTextGroup(t) \
((t) == TEXTOID || \
(t) == BPCHAROID || \
(t) == VARCHAROID)
/* Notice OidGroup is a subset of Int4GroupA */
#define TypeIsOidGroup(t) \
((t) == OIDOID || \
(t) == REGPROCOID || \
(t) == REGPROCEDUREOID || \
(t) == REGOPEROID || \
(t) == REGOPERATOROID || \
(t) == REGCLASSOID || \
(t) == REGTYPEOID)
/* /*
* This macro describes hard-coded knowledge of binary compatibility * INT4 is binary-compatible with many types, but we don't want to allow
* for built-in types. * implicit coercion directly between, say, OID and AbsTime. So we subdivide
* the categories.
*/ */
#define IS_BINARY_COMPATIBLE(a,b) \ #define TypeIsInt4GroupA(t) \
(((a) == BPCHAROID && (b) == TEXTOID) \ ((t) == INT4OID || \
|| ((a) == BPCHAROID && (b) == VARCHAROID) \ TypeIsOidGroup(t))
|| ((a) == VARCHAROID && (b) == TEXTOID) \
|| ((a) == VARCHAROID && (b) == BPCHAROID) \ #define TypeIsInt4GroupB(t) \
|| ((a) == TEXTOID && (b) == BPCHAROID) \ ((t) == INT4OID || \
|| ((a) == TEXTOID && (b) == VARCHAROID) \ (t) == ABSTIMEOID)
|| ((a) == OIDOID && (b) == INT4OID) \
|| ((a) == OIDOID && (b) == REGPROCOID) \ #define TypeIsInt4GroupC(t) \
|| ((a) == INT4OID && (b) == OIDOID) \ ((t) == INT4OID || \
|| ((a) == INT4OID && (b) == REGPROCOID) \ (t) == RELTIMEOID)
|| ((a) == REGPROCOID && (b) == OIDOID) \
|| ((a) == REGPROCOID && (b) == INT4OID) \ #define TypeIsInetGroup(t) \
|| ((a) == ABSTIMEOID && (b) == INT4OID) \ ((t) == INETOID || \
|| ((a) == INT4OID && (b) == ABSTIMEOID) \ (t) == CIDROID)
|| ((a) == RELTIMEOID && (b) == INT4OID) \
|| ((a) == INT4OID && (b) == RELTIMEOID) \ #define TypeIsBitGroup(t) \
|| ((a) == INETOID && (b) == CIDROID) \ ((t) == BITOID || \
|| ((a) == CIDROID && (b) == INETOID) \ (t) == VARBITOID)
|| ((a) == BITOID && (b) == VARBITOID) \
|| ((a) == VARBITOID && (b) == BITOID))
static bool
DirectlyBinaryCompatible(Oid type1, Oid type2)
{
if (type1 == type2)
return true;
if (TypeIsTextGroup(type1) && TypeIsTextGroup(type2))
return true;
if (TypeIsInt4GroupA(type1) && TypeIsInt4GroupA(type2))
return true;
if (TypeIsInt4GroupB(type1) && TypeIsInt4GroupB(type2))
return true;
if (TypeIsInt4GroupC(type1) && TypeIsInt4GroupC(type2))
return true;
if (TypeIsInetGroup(type1) && TypeIsInetGroup(type2))
return true;
if (TypeIsBitGroup(type1) && TypeIsBitGroup(type2))
return true;
return false;
}
bool bool
IsBinaryCompatible(Oid type1, Oid type2) IsBinaryCompatible(Oid type1, Oid type2)
{ {
if (type1 == type2) if (DirectlyBinaryCompatible(type1, type2))
return true;
if (IS_BINARY_COMPATIBLE(type1, type2))
return true; return true;
/* /*
* Perhaps the types are domains; if so, look at their base types * Perhaps the types are domains; if so, look at their base types
@ -580,9 +618,7 @@ IsBinaryCompatible(Oid type1, Oid type2)
type1 = getBaseType(type1); type1 = getBaseType(type1);
if (OidIsValid(type2)) if (OidIsValid(type2))
type2 = getBaseType(type2); type2 = getBaseType(type2);
if (type1 == type2) if (DirectlyBinaryCompatible(type1, type2))
return true;
if (IS_BINARY_COMPATIBLE(type1, type2))
return true; return true;
return false; return false;
} }
@ -627,7 +663,7 @@ PreferredType(CATEGORY category, Oid type)
break; break;
case (NUMERIC_TYPE): case (NUMERIC_TYPE):
if (type == OIDOID) if (TypeIsOidGroup(type))
result = OIDOID; result = OIDOID;
else if (type == NUMERICOID) else if (type == NUMERICOID)
result = NUMERICOID; result = NUMERICOID;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.62 2002/04/16 23:08:11 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.63 2002/04/25 02:56:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -424,7 +424,8 @@ make_const(Value *value)
break; break;
case T_String: case T_String:
val = DirectFunctionCall1(textin, CStringGetDatum(strVal(value))); val = DirectFunctionCall1(unknownin,
CStringGetDatum(strVal(value)));
typeid = UNKNOWNOID; /* will be coerced later */ typeid = UNKNOWNOID; /* will be coerced later */
typelen = -1; /* variable len */ typelen = -1; /* variable len */

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
* back to source text * back to source text
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.98 2002/04/19 23:13:54 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.99 2002/04/25 02:56:55 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
@ -123,7 +123,7 @@ static void get_delete_query_def(Query *query, deparse_context *context);
static void get_utility_query_def(Query *query, deparse_context *context); static void get_utility_query_def(Query *query, deparse_context *context);
static void get_basic_select_query(Query *query, deparse_context *context); static void get_basic_select_query(Query *query, deparse_context *context);
static void get_setop_query(Node *setOp, Query *query, static void get_setop_query(Node *setOp, Query *query,
deparse_context *context, bool toplevel); deparse_context *context);
static void get_rule_sortgroupclause(SortClause *srt, List *tlist, static void get_rule_sortgroupclause(SortClause *srt, List *tlist,
bool force_colno, bool force_colno,
deparse_context *context); deparse_context *context);
@ -142,7 +142,6 @@ static void get_from_clause_item(Node *jtnode, Query *query,
static void get_opclass_name(Oid opclass, Oid actual_datatype, static void get_opclass_name(Oid opclass, Oid actual_datatype,
StringInfo buf); StringInfo buf);
static bool tleIsArrayAssign(TargetEntry *tle); static bool tleIsArrayAssign(TargetEntry *tle);
static char *quote_identifier(char *ident);
static char *get_relid_attribute_name(Oid relid, AttrNumber attnum); static char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
#define only_marker(rte) ((rte)->inh ? "" : "ONLY ") #define only_marker(rte) ((rte)->inh ? "" : "ONLY ")
@ -1109,7 +1108,7 @@ get_select_query_def(Query *query, deparse_context *context)
*/ */
if (query->setOperations) if (query->setOperations)
{ {
get_setop_query(query->setOperations, query, context, true); get_setop_query(query->setOperations, query, context);
/* ORDER BY clauses must be simple in this case */ /* ORDER BY clauses must be simple in this case */
force_colno = true; force_colno = true;
} }
@ -1266,8 +1265,7 @@ get_basic_select_query(Query *query, deparse_context *context)
} }
static void static void
get_setop_query(Node *setOp, Query *query, deparse_context *context, get_setop_query(Node *setOp, Query *query, deparse_context *context)
bool toplevel)
{ {
StringInfo buf = context->buf; StringInfo buf = context->buf;
@ -1284,33 +1282,29 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context,
{ {
SetOperationStmt *op = (SetOperationStmt *) setOp; SetOperationStmt *op = (SetOperationStmt *) setOp;
/* appendStringInfo(buf, "((");
* Must suppress parens at top level of a setop tree because of get_setop_query(op->larg, query, context);
* grammar limitations...
*/
if (!toplevel)
appendStringInfo(buf, "(");
get_setop_query(op->larg, query, context, false);
switch (op->op) switch (op->op)
{ {
case SETOP_UNION: case SETOP_UNION:
appendStringInfo(buf, " UNION "); appendStringInfo(buf, ") UNION ");
break; break;
case SETOP_INTERSECT: case SETOP_INTERSECT:
appendStringInfo(buf, " INTERSECT "); appendStringInfo(buf, ") INTERSECT ");
break; break;
case SETOP_EXCEPT: case SETOP_EXCEPT:
appendStringInfo(buf, " EXCEPT "); appendStringInfo(buf, ") EXCEPT ");
break; break;
default: default:
elog(ERROR, "get_setop_query: unexpected set op %d", elog(ERROR, "get_setop_query: unexpected set op %d",
(int) op->op); (int) op->op);
} }
if (op->all) if (op->all)
appendStringInfo(buf, "ALL "); appendStringInfo(buf, "ALL (");
get_setop_query(op->rarg, query, context, false); else
if (!toplevel) appendStringInfo(buf, "(");
appendStringInfo(buf, ")"); get_setop_query(op->rarg, query, context);
appendStringInfo(buf, "))");
} }
else else
{ {
@ -2585,8 +2579,8 @@ tleIsArrayAssign(TargetEntry *tle)
* space-wasteful but well worth it for notational simplicity. * space-wasteful but well worth it for notational simplicity.
* ---------- * ----------
*/ */
static char * const char *
quote_identifier(char *ident) quote_identifier(const char *ident)
{ {
/* /*
* Can avoid quoting if ident starts with a lowercase letter and * Can avoid quoting if ident starts with a lowercase letter and
@ -2603,7 +2597,7 @@ quote_identifier(char *ident)
safe = (ident[0] >= 'a' && ident[0] <= 'z'); safe = (ident[0] >= 'a' && ident[0] <= 'z');
if (safe) if (safe)
{ {
char *ptr; const char *ptr;
for (ptr = ident + 1; *ptr; ptr++) for (ptr = ident + 1; *ptr; ptr++)
{ {
@ -2628,7 +2622,7 @@ quote_identifier(char *ident)
* Note: ScanKeywordLookup() does case-insensitive comparison, but * Note: ScanKeywordLookup() does case-insensitive comparison, but
* that's fine, since we already know we have all-lower-case. * that's fine, since we already know we have all-lower-case.
*/ */
if (ScanKeywordLookup(ident) != NULL) if (ScanKeywordLookup((char *) ident) != NULL)
safe = false; safe = false;
} }
@ -2640,6 +2634,26 @@ quote_identifier(char *ident)
return result; return result;
} }
/* ----------
* quote_qualified_identifier - Quote a possibly-qualified identifier
*
* Return a name of the form namespace.ident, or just ident if namespace
* is NULL, quoting each component if necessary. The result is palloc'd.
* ----------
*/
char *
quote_qualified_identifier(const char *namespace,
const char *ident)
{
StringInfoData buf;
initStringInfo(&buf);
if (namespace)
appendStringInfo(&buf, "%s.", quote_identifier(namespace));
appendStringInfo(&buf, "%s", quote_identifier(ident));
return buf.data;
}
/* ---------- /* ----------
* get_relid_attribute_name * get_relid_attribute_name
* Get an attribute name by its relations Oid and its attnum * Get an attribute name by its relations Oid and its attnum

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.109 2002/04/21 19:48:13 thomas Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.110 2002/04/25 02:56:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1991,6 +1991,11 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
case NUMERICOID: case NUMERICOID:
case OIDOID: case OIDOID:
case REGPROCOID: case REGPROCOID:
case REGPROCEDUREOID:
case REGOPEROID:
case REGOPERATOROID:
case REGCLASSOID:
case REGTYPEOID:
*scaledvalue = convert_numeric_to_scalar(value, valuetypid); *scaledvalue = convert_numeric_to_scalar(value, valuetypid);
*scaledlobound = convert_numeric_to_scalar(lobound, boundstypid); *scaledlobound = convert_numeric_to_scalar(lobound, boundstypid);
*scaledhibound = convert_numeric_to_scalar(hibound, boundstypid); *scaledhibound = convert_numeric_to_scalar(hibound, boundstypid);
@ -2088,6 +2093,11 @@ convert_numeric_to_scalar(Datum value, Oid typid)
value)); value));
case OIDOID: case OIDOID:
case REGPROCOID: case REGPROCOID:
case REGPROCEDUREOID:
case REGOPEROID:
case REGOPERATOROID:
case REGCLASSOID:
case REGTYPEOID:
/* we can treat OIDs as integers... */ /* we can treat OIDs as integers... */
return (double) DatumGetObjectId(value); return (double) DatumGetObjectId(value);
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.84 2002/04/24 02:12:53 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.85 2002/04/25 02:56:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -21,6 +21,13 @@
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/pg_locale.h" #include "utils/pg_locale.h"
typedef struct varlena unknown;
#define DatumGetUnknownP(X) ((unknown *) PG_DETOAST_DATUM(X))
#define PG_GETARG_UNKNOWN_P(n) DatumGetUnknownP(PG_GETARG_DATUM(n))
#define PG_RETURN_UNKNOWN_P(x) PG_RETURN_POINTER(x)
static int text_cmp(text *arg1, text *arg2); static int text_cmp(text *arg1, text *arg2);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.94 2002/04/06 06:59:22 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.95 2002/04/25 02:56:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -136,8 +136,13 @@ GetCCHashFunc(Oid keytype)
return hashint4; return hashint4;
case TEXTOID: case TEXTOID:
return hashvarlena; return hashvarlena;
case REGPROCOID:
case OIDOID: case OIDOID:
case REGPROCOID:
case REGPROCEDUREOID:
case REGOPEROID:
case REGOPERATOROID:
case REGCLASSOID:
case REGTYPEOID:
return hashoid; return hashoid;
case OIDVECTOROID: case OIDVECTOROID:
return hashoidvector; return hashoidvector;

View File

@ -3,7 +3,7 @@
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.52 2002/04/24 06:17:04 petere Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.53 2002/04/25 02:56:56 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "describe.h" #include "describe.h"
@ -361,7 +361,7 @@ objectDescription(const char *object)
/* Operator descriptions (must get comment via associated function) */ /* Operator descriptions (must get comment via associated function) */
"UNION ALL\n" "UNION ALL\n"
" SELECT RegprocToOid(o.oprcode) as oid,\n" " SELECT CAST(o.oprcode AS oid) as oid,\n"
" (SELECT oid FROM pg_class WHERE relname = 'pg_proc') as tableoid,\n" " (SELECT oid FROM pg_class WHERE relname = 'pg_proc') as tableoid,\n"
" CAST(o.oprname AS text) as name, CAST('%s' AS text) as object\n" " CAST(o.oprname AS text) as name, CAST('%s' AS text) as object\n"
" FROM pg_operator o\n" " FROM pg_operator o\n"

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: c.h,v 1.118 2002/04/24 02:12:53 momjian Exp $ * $Id: c.h,v 1.119 2002/04/25 02:56:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -361,9 +361,12 @@ typedef double float8;
/* typedef Oid is in postgres_ext.h */ /* typedef Oid is in postgres_ext.h */
/* unfortunately, both regproc and RegProcedure are used */ /*
* regproc is the type name used in the include/catalog headers, but
* RegProcedure is the preferred name in C code.
*/
typedef Oid regproc; typedef Oid regproc;
typedef Oid RegProcedure; typedef regproc RegProcedure;
typedef uint32 TransactionId; typedef uint32 TransactionId;
@ -404,7 +407,6 @@ struct varlena
*/ */
typedef struct varlena bytea; typedef struct varlena bytea;
typedef struct varlena text; typedef struct varlena text;
typedef struct varlena unknown;
typedef struct varlena BpChar; /* blank-padded char, ie SQL char(n) */ typedef struct varlena BpChar; /* blank-padded char, ie SQL char(n) */
typedef struct varlena VarChar; /* var-length char, ie SQL varchar(n) */ typedef struct varlena VarChar; /* var-length char, ie SQL varchar(n) */

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: catversion.h,v 1.125 2002/04/24 05:23:14 momjian Exp $ * $Id: catversion.h,v 1.126 2002/04/25 02:56:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200204241 #define CATALOG_VERSION_NO 200204242
#endif #endif

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: namespace.h,v 1.9 2002/04/17 20:57:56 tgl Exp $ * $Id: namespace.h,v 1.10 2002/04/25 02:56:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -22,13 +22,13 @@
* found by namespace lookup. Each function/operator is identified * found by namespace lookup. Each function/operator is identified
* by OID and by argument types; the list must be pruned by type * by OID and by argument types; the list must be pruned by type
* resolution rules that are embodied in the parser, not here. * resolution rules that are embodied in the parser, not here.
* The number of arguments is assumed to be known a priori.
*/ */
typedef struct _FuncCandidateList typedef struct _FuncCandidateList
{ {
struct _FuncCandidateList *next; struct _FuncCandidateList *next;
int pathpos; /* for internal use of namespace lookup */ int pathpos; /* for internal use of namespace lookup */
Oid oid; /* the function or operator's OID */ Oid oid; /* the function or operator's OID */
int nargs; /* number of arg types returned */
Oid args[1]; /* arg types --- VARIABLE LENGTH ARRAY */ Oid args[1]; /* arg types --- VARIABLE LENGTH ARRAY */
} *FuncCandidateList; /* VARIABLE LENGTH STRUCT */ } *FuncCandidateList; /* VARIABLE LENGTH STRUCT */

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_namespace.h,v 1.5 2002/04/21 00:26:43 tgl Exp $ * $Id: pg_namespace.h,v 1.6 2002/04/25 02:56:56 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
@ -72,9 +72,9 @@ DESCR("System catalog namespace");
DATA(insert OID = 99 ( "pg_toast" PGUID "{=}" )); DATA(insert OID = 99 ( "pg_toast" PGUID "{=}" ));
DESCR("Reserved namespace for TOAST tables"); DESCR("Reserved namespace for TOAST tables");
#define PG_TOAST_NAMESPACE 99 #define PG_TOAST_NAMESPACE 99
DATA(insert OID = 2071 ( "public" PGUID "{=UC}" )); DATA(insert OID = 2200 ( "public" PGUID "{=UC}" ));
DESCR("Standard public namespace"); DESCR("Standard public namespace");
#define PG_PUBLIC_NAMESPACE 2071 #define PG_PUBLIC_NAMESPACE 2200
/* /*

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_operator.h,v 1.103 2002/04/21 19:48:23 thomas Exp $ * $Id: pg_operator.h,v 1.104 2002/04/25 02:56:56 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
@ -847,6 +847,33 @@ DATA(insert OID = 2066 ( "+" PGNSP PGUID 0 b t f 1114 1186 1114 0 0 0 0 0
DATA(insert OID = 2067 ( "-" PGNSP PGUID 0 b t f 1114 1114 1186 0 0 0 0 0 0 timestamp_mi - - )); DATA(insert OID = 2067 ( "-" PGNSP PGUID 0 b t f 1114 1114 1186 0 0 0 0 0 0 timestamp_mi - - ));
DATA(insert OID = 2068 ( "-" PGNSP PGUID 0 b t f 1114 1186 1114 0 0 0 0 0 0 timestamp_mi_span - - )); DATA(insert OID = 2068 ( "-" PGNSP PGUID 0 b t f 1114 1186 1114 0 0 0 0 0 0 timestamp_mi_span - - ));
/* array equality operators */
DATA(insert OID = 2222 ( "=" PGNSP PGUID 0 b t f 2207 2207 16 2222 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2223 ( "=" PGNSP PGUID 0 b t f 2208 2208 16 2223 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2224 ( "=" PGNSP PGUID 0 b t f 2209 2209 16 2224 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2225 ( "=" PGNSP PGUID 0 b t f 2210 2210 16 2225 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2226 ( "=" PGNSP PGUID 0 b t f 2211 2211 16 2226 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2227 ( "=" PGNSP PGUID 0 b t f 629 629 16 2227 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2228 ( "=" PGNSP PGUID 0 b t f 651 651 16 2228 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2229 ( "=" PGNSP PGUID 0 b t f 719 719 16 2229 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2230 ( "=" PGNSP PGUID 0 b t f 791 791 16 2230 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2231 ( "=" PGNSP PGUID 0 b t f 1014 1014 16 2231 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2232 ( "=" PGNSP PGUID 0 b t f 1015 1015 16 2232 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2233 ( "=" PGNSP PGUID 0 b t f 1016 1016 16 2233 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2234 ( "=" PGNSP PGUID 0 b t f 1040 1040 16 2234 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2235 ( "=" PGNSP PGUID 0 b t f 1041 1041 16 2235 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2236 ( "=" PGNSP PGUID 0 b t f 1115 1115 16 2236 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2237 ( "=" PGNSP PGUID 0 b t f 1182 1182 16 2237 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2238 ( "=" PGNSP PGUID 0 b t f 1183 1183 16 2238 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2239 ( "=" PGNSP PGUID 0 b t f 1185 1185 16 2239 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2240 ( "=" PGNSP PGUID 0 b t f 1187 1187 16 2240 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2241 ( "=" PGNSP PGUID 0 b t f 1231 1231 16 2241 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2242 ( "=" PGNSP PGUID 0 b t f 1270 1270 16 2242 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2243 ( "=" PGNSP PGUID 0 b t f 1561 1561 16 2243 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2244 ( "=" PGNSP PGUID 0 b t f 1563 1563 16 2244 0 0 0 0 0 array_eq eqsel eqjoinsel ));
DATA(insert OID = 2245 ( "=" PGNSP PGUID 0 b t f 2201 2201 16 2245 0 0 0 0 0 array_eq eqsel eqjoinsel ));
/* /*
* function prototypes * function prototypes

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_proc.h,v 1.232 2002/04/24 05:22:20 momjian Exp $ * $Id: pg_proc.h,v 1.233 2002/04/25 02:56:56 tgl Exp $
* *
* NOTES * NOTES
* The script catalog/genbki.sh reads this file and generates .bki * The script catalog/genbki.sh reads this file and generates .bki
@ -1216,8 +1216,6 @@ DESCR("closest point to line on box");
DATA(insert OID = 964 ( lo_unlink PGNSP PGUID 12 f t f t f v 1 23 "26" 100 0 0 100 lo_unlink - _null_ )); DATA(insert OID = 964 ( lo_unlink PGNSP PGUID 12 f t f t f v 1 23 "26" 100 0 0 100 lo_unlink - _null_ ));
DESCR("large object unlink(delete)"); DESCR("large object unlink(delete)");
DATA(insert OID = 972 ( regproctooid PGNSP PGUID 12 f t f t f i 1 26 "24" 100 0 0 100 regproctooid - _null_ ));
DESCR("get oid for regproc");
DATA(insert OID = 973 ( path_inter PGNSP PGUID 12 f t f t f i 2 16 "602 602" 100 0 0 100 path_inter - _null_ )); DATA(insert OID = 973 ( path_inter PGNSP PGUID 12 f t f t f i 2 16 "602 602" 100 0 0 100 path_inter - _null_ ));
DESCR("paths intersect?"); DESCR("paths intersect?");
@ -2930,6 +2928,28 @@ DATA(insert OID = 2158 ( stddev PGNSP PGUID 12 t t f f f i 1 701 "701" 100 0
DATA(insert OID = 2159 ( stddev PGNSP PGUID 12 t t f f f i 1 1700 "1700" 100 0 0 100 aggregate_dummy - _null_ )); DATA(insert OID = 2159 ( stddev PGNSP PGUID 12 t t f f f i 1 1700 "1700" 100 0 0 100 aggregate_dummy - _null_ ));
DATA(insert OID = 2212 ( regprocedurein PGNSP PGUID 12 f t f t f s 1 2202 "0" 100 0 0 100 regprocedurein - _null_ ));
DESCR("(internal)");
DATA(insert OID = 2213 ( regprocedureout PGNSP PGUID 12 f t f t f s 1 23 "0" 100 0 0 100 regprocedureout - _null_ ));
DESCR("(internal)");
DATA(insert OID = 2214 ( regoperin PGNSP PGUID 12 f t f t f s 1 2203 "0" 100 0 0 100 regoperin - _null_ ));
DESCR("(internal)");
DATA(insert OID = 2215 ( regoperout PGNSP PGUID 12 f t f t f s 1 23 "0" 100 0 0 100 regoperout - _null_ ));
DESCR("(internal)");
DATA(insert OID = 2216 ( regoperatorin PGNSP PGUID 12 f t f t f s 1 2204 "0" 100 0 0 100 regoperatorin - _null_ ));
DESCR("(internal)");
DATA(insert OID = 2217 ( regoperatorout PGNSP PGUID 12 f t f t f s 1 23 "0" 100 0 0 100 regoperatorout - _null_ ));
DESCR("(internal)");
DATA(insert OID = 2218 ( regclassin PGNSP PGUID 12 f t f t f s 1 2205 "0" 100 0 0 100 regclassin - _null_ ));
DESCR("(internal)");
DATA(insert OID = 2219 ( regclassout PGNSP PGUID 12 f t f t f s 1 23 "0" 100 0 0 100 regclassout - _null_ ));
DESCR("(internal)");
DATA(insert OID = 2220 ( regtypein PGNSP PGUID 12 f t f t f s 1 2206 "0" 100 0 0 100 regtypein - _null_ ));
DESCR("(internal)");
DATA(insert OID = 2221 ( regtypeout PGNSP PGUID 12 f t f t f s 1 23 "0" 100 0 0 100 regtypeout - _null_ ));
DESCR("(internal)");
/* /*
* Symbolic values for provolatile column: these indicate whether the result * Symbolic values for provolatile column: these indicate whether the result
* of a function is dependent *only* on the values of its explicit arguments, * of a function is dependent *only* on the values of its explicit arguments,

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_type.h,v 1.121 2002/04/24 02:12:53 momjian Exp $ * $Id: pg_type.h,v 1.122 2002/04/25 02:56:56 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
@ -274,7 +274,7 @@ DATA(insert OID = 23 ( int4 PGNSP PGUID 4 10 t b t \054 0 0 int4in int4ou
DESCR("-2 billion to 2 billion integer, 4-byte storage"); DESCR("-2 billion to 2 billion integer, 4-byte storage");
#define INT4OID 23 #define INT4OID 23
DATA(insert OID = 24 ( regproc PGNSP PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i p f 0 -1 0 _null_ _null_ )); DATA(insert OID = 24 ( regproc PGNSP PGUID 4 -1 t b t \054 0 0 regprocin regprocout regprocin regprocout i p f 0 -1 0 _null_ _null_ ));
DESCR("registered procedure"); DESCR("registered procedure");
#define REGPROCOID 24 #define REGPROCOID 24
@ -444,7 +444,7 @@ DESCR("hh:mm:ss, ANSI SQL time");
DATA(insert OID = 1114 ( timestamp PGNSP PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p f 0 -1 0 _null_ _null_ )); DATA(insert OID = 1114 ( timestamp PGNSP PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p f 0 -1 0 _null_ _null_ ));
DESCR("date and time"); DESCR("date and time");
#define TIMESTAMPOID 1114 #define TIMESTAMPOID 1114
DATA(insert OID = 1115 ( _timestamp PGNSP PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); DATA(insert OID = 1115 ( _timestamp PGNSP PGUID -1 -1 f b t \054 0 1114 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ ));
DATA(insert OID = 1182 ( _date PGNSP PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); DATA(insert OID = 1182 ( _date PGNSP PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ ));
DATA(insert OID = 1183 ( _time PGNSP PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); DATA(insert OID = 1183 ( _time PGNSP PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ ));
DATA(insert OID = 1184 ( timestamptz PGNSP PGUID 8 47 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p f 0 -1 0 _null_ _null_ )); DATA(insert OID = 1184 ( timestamptz PGNSP PGUID 8 47 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p f 0 -1 0 _null_ _null_ ));
@ -484,8 +484,34 @@ DATA(insert OID = 1790 ( refcursor PGNSP PGUID -1 -1 f b t \054 0 0 textin
DESCR("reference cursor (portal name)"); DESCR("reference cursor (portal name)");
#define REFCURSOROID 1790 #define REFCURSOROID 1790
/* OIDS 2000 - 2099 */ /* OIDS 2200 - 2299 */
DATA(insert OID = 2019 ( _refcursor PGNSP PGUID -1 -1 f b t \054 0 1790 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); DATA(insert OID = 2201 ( _refcursor PGNSP PGUID -1 -1 f b t \054 0 1790 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ ));
DATA(insert OID = 2202 ( regprocedure PGNSP PGUID 4 -1 t b t \054 0 0 regprocedurein regprocedureout regprocedurein regprocedureout i p f 0 -1 0 _null_ _null_ ));
DESCR("registered procedure (with args)");
#define REGPROCEDUREOID 2202
DATA(insert OID = 2203 ( regoper PGNSP PGUID 4 -1 t b t \054 0 0 regoperin regoperout regoperin regoperout i p f 0 -1 0 _null_ _null_ ));
DESCR("registered operator");
#define REGOPEROID 2203
DATA(insert OID = 2204 ( regoperator PGNSP PGUID 4 -1 t b t \054 0 0 regoperatorin regoperatorout regoperatorin regoperatorout i p f 0 -1 0 _null_ _null_ ));
DESCR("registered operator (with args)");
#define REGOPERATOROID 2204
DATA(insert OID = 2205 ( regclass PGNSP PGUID 4 -1 t b t \054 0 0 regclassin regclassout regclassin regclassout i p f 0 -1 0 _null_ _null_ ));
DESCR("registered class");
#define REGCLASSOID 2205
DATA(insert OID = 2206 ( regtype PGNSP PGUID 4 -1 t b t \054 0 0 regtypein regtypeout regtypein regtypeout i p f 0 -1 0 _null_ _null_ ));
DESCR("registered type");
#define REGTYPEOID 2206
DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 -1 f b t \054 0 2202 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ ));
DATA(insert OID = 2208 ( _regoper PGNSP PGUID -1 -1 f b t \054 0 2203 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ ));
DATA(insert OID = 2209 ( _regoperator PGNSP PGUID -1 -1 f b t \054 0 2204 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ ));
DATA(insert OID = 2210 ( _regclass PGNSP PGUID -1 -1 f b t \054 0 2205 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ ));
DATA(insert OID = 2211 ( _regtype PGNSP PGUID -1 -1 f b t \054 0 2206 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ ));
/* /*

View File

@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: fmgr.h,v 1.20 2002/04/24 02:12:53 momjian Exp $ * $Id: fmgr.h,v 1.21 2002/04/25 02:56:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -185,7 +185,6 @@ extern struct varlena *pg_detoast_datum_slice(struct varlena * datum,
/* DatumGetFoo macros for varlena types will typically look like this: */ /* DatumGetFoo macros for varlena types will typically look like this: */
#define DatumGetByteaP(X) ((bytea *) PG_DETOAST_DATUM(X)) #define DatumGetByteaP(X) ((bytea *) PG_DETOAST_DATUM(X))
#define DatumGetTextP(X) ((text *) PG_DETOAST_DATUM(X)) #define DatumGetTextP(X) ((text *) PG_DETOAST_DATUM(X))
#define DatumGetUnknownP(X) ((unknown *) PG_DETOAST_DATUM(X))
#define DatumGetBpCharP(X) ((BpChar *) PG_DETOAST_DATUM(X)) #define DatumGetBpCharP(X) ((BpChar *) PG_DETOAST_DATUM(X))
#define DatumGetVarCharP(X) ((VarChar *) PG_DETOAST_DATUM(X)) #define DatumGetVarCharP(X) ((VarChar *) PG_DETOAST_DATUM(X))
/* And we also offer variants that return an OK-to-write copy */ /* And we also offer variants that return an OK-to-write copy */
@ -201,7 +200,6 @@ extern struct varlena *pg_detoast_datum_slice(struct varlena * datum,
/* GETARG macros for varlena types will typically look like this: */ /* GETARG macros for varlena types will typically look like this: */
#define PG_GETARG_BYTEA_P(n) DatumGetByteaP(PG_GETARG_DATUM(n)) #define PG_GETARG_BYTEA_P(n) DatumGetByteaP(PG_GETARG_DATUM(n))
#define PG_GETARG_TEXT_P(n) DatumGetTextP(PG_GETARG_DATUM(n)) #define PG_GETARG_TEXT_P(n) DatumGetTextP(PG_GETARG_DATUM(n))
#define PG_GETARG_UNKNOWN_P(n) DatumGetUnknownP(PG_GETARG_DATUM(n))
#define PG_GETARG_BPCHAR_P(n) DatumGetBpCharP(PG_GETARG_DATUM(n)) #define PG_GETARG_BPCHAR_P(n) DatumGetBpCharP(PG_GETARG_DATUM(n))
#define PG_GETARG_VARCHAR_P(n) DatumGetVarCharP(PG_GETARG_DATUM(n)) #define PG_GETARG_VARCHAR_P(n) DatumGetVarCharP(PG_GETARG_DATUM(n))
/* And we also offer variants that return an OK-to-write copy */ /* And we also offer variants that return an OK-to-write copy */
@ -241,7 +239,6 @@ extern struct varlena *pg_detoast_datum_slice(struct varlena * datum,
/* RETURN macros for other pass-by-ref types will typically look like this: */ /* RETURN macros for other pass-by-ref types will typically look like this: */
#define PG_RETURN_BYTEA_P(x) PG_RETURN_POINTER(x) #define PG_RETURN_BYTEA_P(x) PG_RETURN_POINTER(x)
#define PG_RETURN_TEXT_P(x) PG_RETURN_POINTER(x) #define PG_RETURN_TEXT_P(x) PG_RETURN_POINTER(x)
#define PG_RETURN_UNKNOWN_P(x) PG_RETURN_POINTER(x)
#define PG_RETURN_BPCHAR_P(x) PG_RETURN_POINTER(x) #define PG_RETURN_BPCHAR_P(x) PG_RETURN_POINTER(x)
#define PG_RETURN_VARCHAR_P(x) PG_RETURN_POINTER(x) #define PG_RETURN_VARCHAR_P(x) PG_RETURN_POINTER(x)

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: builtins.h,v 1.178 2002/04/24 02:12:53 momjian Exp $ * $Id: builtins.h,v 1.179 2002/04/25 02:56:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -329,10 +329,16 @@ extern Datum texticregexne(PG_FUNCTION_ARGS);
/* regproc.c */ /* regproc.c */
extern Datum regprocin(PG_FUNCTION_ARGS); extern Datum regprocin(PG_FUNCTION_ARGS);
extern Datum regprocout(PG_FUNCTION_ARGS); extern Datum regprocout(PG_FUNCTION_ARGS);
extern Datum regproctooid(PG_FUNCTION_ARGS); extern Datum regprocedurein(PG_FUNCTION_ARGS);
extern Datum regprocedureout(PG_FUNCTION_ARGS);
/* define macro to replace mixed-case function call - tgl 97/04/27 */ extern Datum regoperin(PG_FUNCTION_ARGS);
#define RegprocToOid(rp) ((Oid) (rp)) extern Datum regoperout(PG_FUNCTION_ARGS);
extern Datum regoperatorin(PG_FUNCTION_ARGS);
extern Datum regoperatorout(PG_FUNCTION_ARGS);
extern Datum regclassin(PG_FUNCTION_ARGS);
extern Datum regclassout(PG_FUNCTION_ARGS);
extern Datum regtypein(PG_FUNCTION_ARGS);
extern Datum regtypeout(PG_FUNCTION_ARGS);
/* ruleutils.c */ /* ruleutils.c */
extern Datum pg_get_ruledef(PG_FUNCTION_ARGS); extern Datum pg_get_ruledef(PG_FUNCTION_ARGS);
@ -349,6 +355,9 @@ extern List *deparse_context_for_plan(int outer_varno, Node *outercontext,
extern Node *deparse_context_for_relation(const char *aliasname, Oid relid); extern Node *deparse_context_for_relation(const char *aliasname, Oid relid);
extern Node *deparse_context_for_subplan(const char *name, List *tlist, extern Node *deparse_context_for_subplan(const char *name, List *tlist,
List *rtable); List *rtable);
extern const char *quote_identifier(const char *ident);
extern char *quote_qualified_identifier(const char *namespace,
const char *ident);
/* tid.c */ /* tid.c */
extern void setLastTid(const ItemPointer tid); extern void setLastTid(const ItemPointer tid);

View File

@ -14,11 +14,6 @@
-- --
-- NB: run this test earlier than the create_operator test, because -- NB: run this test earlier than the create_operator test, because
-- that test creates some bogus operators... -- that test creates some bogus operators...
--
-- NOTE hardwired assumptions about standard types:
-- type bool has OID 16
-- type float8 has OID 701
--
-- **************** pg_proc **************** -- **************** pg_proc ****************
-- Look for illegal values in pg_proc fields. -- Look for illegal values in pg_proc fields.
-- NOTE: currently there are a few pg_proc entries that have prorettype = 0. -- NOTE: currently there are a few pg_proc entries that have prorettype = 0.
@ -26,7 +21,7 @@
SELECT p1.oid, p1.proname SELECT p1.oid, p1.proname
FROM pg_proc as p1 FROM pg_proc as p1
WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR
p1.pronargs < 0 OR p1.pronargs > 9) p1.pronargs < 0 OR p1.pronargs > 16)
AND p1.proname !~ '^pl[^_]+_call_handler$' AND p1.proname !~ '^pl[^_]+_call_handler$'
AND p1.proname !~ '^RI_FKey_' AND p1.proname !~ '^RI_FKey_'
AND p1.proname !~ 'costestimate$' AND p1.proname !~ 'costestimate$'
@ -196,7 +191,7 @@ WHERE p1.proimplicit AND
t.typname = p1.proname) OR t.typname = p1.proname) OR
NOT ((p1.pronargs = 1 AND p1.proargtypes[0] != prorettype) OR NOT ((p1.pronargs = 1 AND p1.proargtypes[0] != prorettype) OR
(p1.pronargs = 2 AND p1.proargtypes[0] = prorettype AND (p1.pronargs = 2 AND p1.proargtypes[0] = prorettype AND
p1.proargtypes[1] = 23))); p1.proargtypes[1] = 'int4'::regtype)));
oid | proname oid | proname
-----+--------- -----+---------
(0 rows) (0 rows)
@ -263,8 +258,8 @@ WHERE p1.oprnegate = p2.oid AND
(p1.oprkind != p2.oprkind OR (p1.oprkind != p2.oprkind OR
p1.oprleft != p2.oprleft OR p1.oprleft != p2.oprleft OR
p1.oprright != p2.oprright OR p1.oprright != p2.oprright OR
p1.oprresult != 16 OR p1.oprresult != 'bool'::regtype OR
p2.oprresult != 16 OR p2.oprresult != 'bool'::regtype OR
p1.oid != p2.oprnegate OR p1.oid != p2.oprnegate OR
p1.oid = p2.oid); p1.oid = p2.oid);
oid | oprcode | oid | oprcode oid | oprcode | oid | oprcode
@ -282,8 +277,8 @@ WHERE p1.oprlsortop = p2.oid AND
p1.oprkind != 'b' OR p2.oprkind != 'b' OR p1.oprkind != 'b' OR p2.oprkind != 'b' OR
p1.oprleft != p2.oprleft OR p1.oprleft != p2.oprleft OR
p1.oprleft != p2.oprright OR p1.oprleft != p2.oprright OR
p1.oprresult != 16 OR p1.oprresult != 'bool'::regtype OR
p2.oprresult != 16 OR p2.oprresult != 'bool'::regtype OR
p1.oprrsortop = 0); p1.oprrsortop = 0);
oid | oprcode | oid | oprcode oid | oprcode | oid | oprcode
-----+---------+-----+--------- -----+---------+-----+---------
@ -296,8 +291,8 @@ WHERE p1.oprrsortop = p2.oid AND
p1.oprkind != 'b' OR p2.oprkind != 'b' OR p1.oprkind != 'b' OR p2.oprkind != 'b' OR
p1.oprright != p2.oprleft OR p1.oprright != p2.oprleft OR
p1.oprright != p2.oprright OR p1.oprright != p2.oprright OR
p1.oprresult != 16 OR p1.oprresult != 'bool'::regtype OR
p2.oprresult != 16 OR p2.oprresult != 'bool'::regtype OR
p1.oprlsortop = 0); p1.oprlsortop = 0);
oid | oprcode | oid | oprcode oid | oprcode | oid | oprcode
-----+---------+-----+--------- -----+---------+-----+---------
@ -363,8 +358,8 @@ WHERE p1.oprlsortop != p1.oprrsortop AND
SELECT p1.oid, p1.oprname SELECT p1.oid, p1.oprname
FROM pg_operator AS p1 FROM pg_operator AS p1
WHERE p1.oprcanhash AND NOT WHERE p1.oprcanhash AND NOT
(p1.oprkind = 'b' AND p1.oprresult = 16 AND p1.oprleft = p1.oprright AND (p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND
p1.oprname = '=' AND p1.oprcom = p1.oid); p1.oprleft = p1.oprright AND p1.oprname = '=' AND p1.oprcom = p1.oid);
oid | oprname oid | oprname
------+--------- ------+---------
353 | = 353 | =
@ -448,11 +443,11 @@ WHERE p1.oprcode = p2.oid AND
SELECT p1.oid, p1.oprname, p2.oid, p2.proname SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2 FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprrest = p2.oid AND WHERE p1.oprrest = p2.oid AND
(p1.oprresult != 16 OR (p1.oprresult != 'bool'::regtype OR
p2.prorettype != 701 OR p2.proretset OR p2.prorettype != 'float8'::regtype OR p2.proretset OR
p2.pronargs != 4 OR p2.pronargs != 4 OR
p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 26 OR p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 'oid'::regtype OR
p2.proargtypes[2] != 0 OR p2.proargtypes[3] != 23); p2.proargtypes[2] != 0 OR p2.proargtypes[3] != 'int4'::regtype);
oid | oprname | oid | proname oid | oprname | oid | proname
-----+---------+-----+--------- -----+---------+-----+---------
(0 rows) (0 rows)
@ -464,10 +459,10 @@ WHERE p1.oprrest = p2.oid AND
SELECT p1.oid, p1.oprname, p2.oid, p2.proname SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2 FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprjoin = p2.oid AND WHERE p1.oprjoin = p2.oid AND
(p1.oprkind != 'b' OR p1.oprresult != 16 OR (p1.oprkind != 'b' OR p1.oprresult != 'bool'::regtype OR
p2.prorettype != 701 OR p2.proretset OR p2.prorettype != 'float8'::regtype OR p2.proretset OR
p2.pronargs != 3 OR p2.pronargs != 3 OR
p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 26 OR p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 'oid'::regtype OR
p2.proargtypes[2] != 0); p2.proargtypes[2] != 0);
oid | oprname | oid | proname oid | oprname | oid | proname
-----+---------+-----+--------- -----+---------+-----+---------
@ -611,7 +606,8 @@ WHERE p2.opcamid = p1.oid AND
SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
FROM pg_amop AS p1, pg_operator AS p2 FROM pg_amop AS p1, pg_operator AS p2
WHERE p1.amopopr = p2.oid AND WHERE p1.amopopr = p2.oid AND
(p2.oprkind != 'b' OR p2.oprresult != 16 OR p2.oprleft != p2.oprright); (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype OR
p2.oprleft != p2.oprright);
amopclaid | amopopr | oid | oprname amopclaid | amopopr | oid | oprname
-----------+---------+-----+--------- -----------+---------+-----+---------
(0 rows) (0 rows)

View File

@ -19,7 +19,9 @@ WHERE (p1.typlen <= 0 AND p1.typlen != -1) OR
(p1.typtype != 'b' AND p1.typtype != 'c') OR (p1.typtype != 'b' AND p1.typtype != 'c') OR
NOT p1.typisdefined OR NOT p1.typisdefined OR
(p1.typalign != 'c' AND p1.typalign != 's' AND (p1.typalign != 'c' AND p1.typalign != 's' AND
p1.typalign != 'i' AND p1.typalign != 'd'); p1.typalign != 'i' AND p1.typalign != 'd') OR
(p1.typstorage != 'p' AND p1.typstorage != 'x' AND
p1.typstorage != 'e' AND p1.typstorage != 'm');
oid | typname oid | typname
-----+--------- -----+---------
(0 rows) (0 rows)
@ -35,6 +37,15 @@ WHERE p1.typbyval AND
-----+--------- -----+---------
(0 rows) (0 rows)
-- Look for "toastable" types that aren't varlena.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typstorage != 'p' AND
(p1.typbyval OR p1.typlen != -1);
oid | typname
-----+---------
(0 rows)
-- Look for complex types that do not have a typrelid entry, -- Look for complex types that do not have a typrelid entry,
-- or basic types that do. -- or basic types that do.
SELECT p1.oid, p1.typname SELECT p1.oid, p1.typname
@ -45,6 +56,31 @@ WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
-----+--------- -----+---------
(0 rows) (0 rows)
-- Look for basic types that don't have an array type.
-- NOTE: as of 7.3, this check finds SET, smgr, and unknown.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typtype != 'c' AND p1.typname NOT LIKE '\\_%' AND NOT EXISTS
(SELECT 1 FROM pg_type as p2
WHERE p2.typname = ('_' || p1.typname)::name AND
p2.typelem = p1.oid);
oid | typname
-----+---------
32 | SET
210 | smgr
705 | unknown
(3 rows)
-- Look for array types that don't have an equality operator.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typtype != 'c' AND p1.typname LIKE '\\_%' AND NOT EXISTS
(SELECT 1 FROM pg_operator
WHERE oprname = '=' AND oprleft = p1.oid AND oprright = p1.oid);
oid | typname
-----+---------
(0 rows)
-- Conversion routines must be provided except in 'c' entries. -- Conversion routines must be provided except in 'c' entries.
SELECT p1.oid, p1.typname SELECT p1.oid, p1.typname
FROM pg_type as p1 FROM pg_type as p1
@ -63,7 +99,7 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2 FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typinput = p2.oid AND p1.typtype = 'b' AND WHERE p1.typinput = p2.oid AND p1.typtype = 'b' AND
(p2.pronargs != 1 OR p2.proretset) AND (p2.pronargs != 1 OR p2.proretset) AND
(p2.pronargs != 3 OR p2.proretset OR p2.proargtypes[2] != 23); (p2.pronargs != 3 OR p2.proretset OR p2.proargtypes[2] != 'int4'::regtype);
oid | typname | oid | proname oid | typname | oid | proname
-----+---------+-----+--------- -----+---------+-----+---------
(0 rows) (0 rows)
@ -89,7 +125,7 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2 FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typreceive = p2.oid AND p1.typtype = 'b' AND WHERE p1.typreceive = p2.oid AND p1.typtype = 'b' AND
(p2.pronargs != 1 OR p2.proretset) AND (p2.pronargs != 1 OR p2.proretset) AND
(p2.pronargs != 3 OR p2.proretset OR p2.proargtypes[2] != 23); (p2.pronargs != 3 OR p2.proretset OR p2.proargtypes[2] != 'int4'::regtype);
oid | typname | oid | proname oid | typname | oid | proname
-----+---------+-----+--------- -----+---------+-----+---------
(0 rows) (0 rows)
@ -154,12 +190,15 @@ WHERE p1.relnatts != (SELECT count(*) FROM pg_attribute AS p2
(0 rows) (0 rows)
-- Cross-check against pg_type entry -- Cross-check against pg_type entry
-- NOTE: we allow attstorage to be 'plain' even when typstorage is not;
-- this is mainly for toast tables.
SELECT p1.attrelid, p1.attname, p2.oid, p2.typname SELECT p1.attrelid, p1.attname, p2.oid, p2.typname
FROM pg_attribute AS p1, pg_type AS p2 FROM pg_attribute AS p1, pg_type AS p2
WHERE p1.atttypid = p2.oid AND WHERE p1.atttypid = p2.oid AND
(p1.attlen != p2.typlen OR (p1.attlen != p2.typlen OR
p1.attalign != p2.typalign OR p1.attalign != p2.typalign OR
p1.attbyval != p2.typbyval); p1.attbyval != p2.typbyval OR
(p1.attstorage != p2.typstorage AND p1.attstorage != 'p'));
attrelid | attname | oid | typname attrelid | attname | oid | typname
----------+---------+-----+--------- ----------+---------+-----+---------
(0 rows) (0 rows)

View File

@ -14,11 +14,6 @@
-- --
-- NB: run this test earlier than the create_operator test, because -- NB: run this test earlier than the create_operator test, because
-- that test creates some bogus operators... -- that test creates some bogus operators...
--
-- NOTE hardwired assumptions about standard types:
-- type bool has OID 16
-- type float8 has OID 701
--
-- **************** pg_proc **************** -- **************** pg_proc ****************
@ -29,7 +24,7 @@
SELECT p1.oid, p1.proname SELECT p1.oid, p1.proname
FROM pg_proc as p1 FROM pg_proc as p1
WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR
p1.pronargs < 0 OR p1.pronargs > 9) p1.pronargs < 0 OR p1.pronargs > 16)
AND p1.proname !~ '^pl[^_]+_call_handler$' AND p1.proname !~ '^pl[^_]+_call_handler$'
AND p1.proname !~ '^RI_FKey_' AND p1.proname !~ '^RI_FKey_'
AND p1.proname !~ 'costestimate$' AND p1.proname !~ 'costestimate$'
@ -158,7 +153,7 @@ WHERE p1.proimplicit AND
t.typname = p1.proname) OR t.typname = p1.proname) OR
NOT ((p1.pronargs = 1 AND p1.proargtypes[0] != prorettype) OR NOT ((p1.pronargs = 1 AND p1.proargtypes[0] != prorettype) OR
(p1.pronargs = 2 AND p1.proargtypes[0] = prorettype AND (p1.pronargs = 2 AND p1.proargtypes[0] = prorettype AND
p1.proargtypes[1] = 23))); p1.proargtypes[1] = 'int4'::regtype)));
-- **************** pg_operator **************** -- **************** pg_operator ****************
@ -216,8 +211,8 @@ WHERE p1.oprnegate = p2.oid AND
(p1.oprkind != p2.oprkind OR (p1.oprkind != p2.oprkind OR
p1.oprleft != p2.oprleft OR p1.oprleft != p2.oprleft OR
p1.oprright != p2.oprright OR p1.oprright != p2.oprright OR
p1.oprresult != 16 OR p1.oprresult != 'bool'::regtype OR
p2.oprresult != 16 OR p2.oprresult != 'bool'::regtype OR
p1.oid != p2.oprnegate OR p1.oid != p2.oprnegate OR
p1.oid = p2.oid); p1.oid = p2.oid);
@ -233,8 +228,8 @@ WHERE p1.oprlsortop = p2.oid AND
p1.oprkind != 'b' OR p2.oprkind != 'b' OR p1.oprkind != 'b' OR p2.oprkind != 'b' OR
p1.oprleft != p2.oprleft OR p1.oprleft != p2.oprleft OR
p1.oprleft != p2.oprright OR p1.oprleft != p2.oprright OR
p1.oprresult != 16 OR p1.oprresult != 'bool'::regtype OR
p2.oprresult != 16 OR p2.oprresult != 'bool'::regtype OR
p1.oprrsortop = 0); p1.oprrsortop = 0);
SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
@ -244,8 +239,8 @@ WHERE p1.oprrsortop = p2.oid AND
p1.oprkind != 'b' OR p2.oprkind != 'b' OR p1.oprkind != 'b' OR p2.oprkind != 'b' OR
p1.oprright != p2.oprleft OR p1.oprright != p2.oprleft OR
p1.oprright != p2.oprright OR p1.oprright != p2.oprright OR
p1.oprresult != 16 OR p1.oprresult != 'bool'::regtype OR
p2.oprresult != 16 OR p2.oprresult != 'bool'::regtype OR
p1.oprlsortop = 0); p1.oprlsortop = 0);
-- A mergejoinable = operator must have a commutator (usually itself) -- A mergejoinable = operator must have a commutator (usually itself)
@ -300,8 +295,8 @@ WHERE p1.oprlsortop != p1.oprrsortop AND
SELECT p1.oid, p1.oprname SELECT p1.oid, p1.oprname
FROM pg_operator AS p1 FROM pg_operator AS p1
WHERE p1.oprcanhash AND NOT WHERE p1.oprcanhash AND NOT
(p1.oprkind = 'b' AND p1.oprresult = 16 AND p1.oprleft = p1.oprright AND (p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND
p1.oprname = '=' AND p1.oprcom = p1.oid); p1.oprleft = p1.oprright AND p1.oprname = '=' AND p1.oprcom = p1.oid);
-- In 6.5 we accepted hashable array equality operators when the array element -- In 6.5 we accepted hashable array equality operators when the array element
-- type is hashable. However, what we actually need to make hashjoin work on -- type is hashable. However, what we actually need to make hashjoin work on
@ -372,11 +367,11 @@ WHERE p1.oprcode = p2.oid AND
SELECT p1.oid, p1.oprname, p2.oid, p2.proname SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2 FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprrest = p2.oid AND WHERE p1.oprrest = p2.oid AND
(p1.oprresult != 16 OR (p1.oprresult != 'bool'::regtype OR
p2.prorettype != 701 OR p2.proretset OR p2.prorettype != 'float8'::regtype OR p2.proretset OR
p2.pronargs != 4 OR p2.pronargs != 4 OR
p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 26 OR p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 'oid'::regtype OR
p2.proargtypes[2] != 0 OR p2.proargtypes[3] != 23); p2.proargtypes[2] != 0 OR p2.proargtypes[3] != 'int4'::regtype);
-- If oprjoin is set, the operator must be a binary boolean op, -- If oprjoin is set, the operator must be a binary boolean op,
-- and it must link to a proc with the right signature -- and it must link to a proc with the right signature
@ -386,10 +381,10 @@ WHERE p1.oprrest = p2.oid AND
SELECT p1.oid, p1.oprname, p2.oid, p2.proname SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2 FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprjoin = p2.oid AND WHERE p1.oprjoin = p2.oid AND
(p1.oprkind != 'b' OR p1.oprresult != 16 OR (p1.oprkind != 'b' OR p1.oprresult != 'bool'::regtype OR
p2.prorettype != 701 OR p2.proretset OR p2.prorettype != 'float8'::regtype OR p2.proretset OR
p2.pronargs != 3 OR p2.pronargs != 3 OR
p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 26 OR p2.proargtypes[0] != 0 OR p2.proargtypes[1] != 'oid'::regtype OR
p2.proargtypes[2] != 0); p2.proargtypes[2] != 0);
-- **************** pg_aggregate **************** -- **************** pg_aggregate ****************
@ -507,7 +502,8 @@ WHERE p2.opcamid = p1.oid AND
SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
FROM pg_amop AS p1, pg_operator AS p2 FROM pg_amop AS p1, pg_operator AS p2
WHERE p1.amopopr = p2.oid AND WHERE p1.amopopr = p2.oid AND
(p2.oprkind != 'b' OR p2.oprresult != 16 OR p2.oprleft != p2.oprright); (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype OR
p2.oprleft != p2.oprright);
-- Check that all operators linked to by opclass entries have selectivity -- Check that all operators linked to by opclass entries have selectivity
-- estimators. This is not absolutely required, but it seems a reasonable -- estimators. This is not absolutely required, but it seems a reasonable

View File

@ -22,7 +22,9 @@ WHERE (p1.typlen <= 0 AND p1.typlen != -1) OR
(p1.typtype != 'b' AND p1.typtype != 'c') OR (p1.typtype != 'b' AND p1.typtype != 'c') OR
NOT p1.typisdefined OR NOT p1.typisdefined OR
(p1.typalign != 'c' AND p1.typalign != 's' AND (p1.typalign != 'c' AND p1.typalign != 's' AND
p1.typalign != 'i' AND p1.typalign != 'd'); p1.typalign != 'i' AND p1.typalign != 'd') OR
(p1.typstorage != 'p' AND p1.typstorage != 'x' AND
p1.typstorage != 'e' AND p1.typstorage != 'm');
-- Look for "pass by value" types that can't be passed by value. -- Look for "pass by value" types that can't be passed by value.
@ -33,6 +35,13 @@ WHERE p1.typbyval AND
(p1.typlen != 2 OR p1.typalign != 's') AND (p1.typlen != 2 OR p1.typalign != 's') AND
(p1.typlen != 4 OR p1.typalign != 'i'); (p1.typlen != 4 OR p1.typalign != 'i');
-- Look for "toastable" types that aren't varlena.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typstorage != 'p' AND
(p1.typbyval OR p1.typlen != -1);
-- Look for complex types that do not have a typrelid entry, -- Look for complex types that do not have a typrelid entry,
-- or basic types that do. -- or basic types that do.
@ -41,6 +50,24 @@ FROM pg_type as p1
WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
(p1.typtype != 'c' AND p1.typrelid != 0); (p1.typtype != 'c' AND p1.typrelid != 0);
-- Look for basic types that don't have an array type.
-- NOTE: as of 7.3, this check finds SET, smgr, and unknown.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typtype != 'c' AND p1.typname NOT LIKE '\\_%' AND NOT EXISTS
(SELECT 1 FROM pg_type as p2
WHERE p2.typname = ('_' || p1.typname)::name AND
p2.typelem = p1.oid);
-- Look for array types that don't have an equality operator.
SELECT p1.oid, p1.typname
FROM pg_type as p1
WHERE p1.typtype != 'c' AND p1.typname LIKE '\\_%' AND NOT EXISTS
(SELECT 1 FROM pg_operator
WHERE oprname = '=' AND oprleft = p1.oid AND oprright = p1.oid);
-- Conversion routines must be provided except in 'c' entries. -- Conversion routines must be provided except in 'c' entries.
SELECT p1.oid, p1.typname SELECT p1.oid, p1.typname
@ -58,7 +85,7 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2 FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typinput = p2.oid AND p1.typtype = 'b' AND WHERE p1.typinput = p2.oid AND p1.typtype = 'b' AND
(p2.pronargs != 1 OR p2.proretset) AND (p2.pronargs != 1 OR p2.proretset) AND
(p2.pronargs != 3 OR p2.proretset OR p2.proargtypes[2] != 23); (p2.pronargs != 3 OR p2.proretset OR p2.proargtypes[2] != 'int4'::regtype);
-- Check for bogus typoutput routines -- Check for bogus typoutput routines
-- The first OR subclause detects bogus non-array cases, -- The first OR subclause detects bogus non-array cases,
@ -80,7 +107,7 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2 FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typreceive = p2.oid AND p1.typtype = 'b' AND WHERE p1.typreceive = p2.oid AND p1.typtype = 'b' AND
(p2.pronargs != 1 OR p2.proretset) AND (p2.pronargs != 1 OR p2.proretset) AND
(p2.pronargs != 3 OR p2.proretset OR p2.proargtypes[2] != 23); (p2.pronargs != 3 OR p2.proretset OR p2.proargtypes[2] != 'int4'::regtype);
-- Check for bogus typsend routines -- Check for bogus typsend routines
-- The first OR subclause detects bogus non-array cases, -- The first OR subclause detects bogus non-array cases,
@ -132,10 +159,13 @@ WHERE p1.relnatts != (SELECT count(*) FROM pg_attribute AS p2
WHERE p2.attrelid = p1.oid AND p2.attnum > 0); WHERE p2.attrelid = p1.oid AND p2.attnum > 0);
-- Cross-check against pg_type entry -- Cross-check against pg_type entry
-- NOTE: we allow attstorage to be 'plain' even when typstorage is not;
-- this is mainly for toast tables.
SELECT p1.attrelid, p1.attname, p2.oid, p2.typname SELECT p1.attrelid, p1.attname, p2.oid, p2.typname
FROM pg_attribute AS p1, pg_type AS p2 FROM pg_attribute AS p1, pg_type AS p2
WHERE p1.atttypid = p2.oid AND WHERE p1.atttypid = p2.oid AND
(p1.attlen != p2.typlen OR (p1.attlen != p2.typlen OR
p1.attalign != p2.typalign OR p1.attalign != p2.typalign OR
p1.attbyval != p2.typbyval); p1.attbyval != p2.typbyval OR
(p1.attstorage != p2.typstorage AND p1.attstorage != 'p'));