Convert oidvector and int2vector into variable-length arrays. This

change saves a great deal of space in pg_proc and its primary index,
and it eliminates the former requirement that INDEX_MAX_KEYS and
FUNC_MAX_ARGS have the same value.  INDEX_MAX_KEYS is still embedded
in the on-disk representation (because it affects index tuple header
size), but FUNC_MAX_ARGS is not.  I believe it would now be possible
to increase FUNC_MAX_ARGS at little cost, but haven't experimented yet.
There are still a lot of vestigial references to FUNC_MAX_ARGS, which
I will clean up in a separate pass.  However, getting rid of it
altogether would require changing the FunctionCallInfoData struct,
and I'm not sure I want to buy into that.
This commit is contained in:
Tom Lane 2005-03-29 00:17:27 +00:00
parent 119191609c
commit 70c9763d48
61 changed files with 819 additions and 581 deletions

View File

@ -74,13 +74,13 @@ static HTAB *createConnHash(void);
static void createNewConnection(const char *name, remoteConn * con);
static void deleteConnection(const char *name);
static char **get_pkey_attnames(Oid relid, int16 *numatts);
static char *get_sql_insert(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);
static char *get_sql_delete(Oid relid, int16 *pkattnums, int16 pknumatts, char **tgt_pkattvals);
static char *get_sql_update(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);
static char *get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);
static char *get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pkattvals);
static char *get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);
static char *quote_literal_cstr(char *rawstr);
static char *quote_ident_cstr(char *rawstr);
static int16 get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key);
static HeapTuple get_tuple_of_interest(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals);
static int16 get_attnum_pk_pos(int2vector *pkattnums, int16 pknumatts, int16 key);
static HeapTuple get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals);
static Oid get_relid_from_relname(text *relname_text);
static char *generate_relation_name(Oid relid);
@ -1094,7 +1094,7 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
{
Oid relid;
text *relname_text;
int16 *pkattnums;
int2vector *pkattnums;
int pknumatts_tmp;
int16 pknumatts = 0;
char **src_pkattvals;
@ -1126,7 +1126,7 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
errmsg("relation \"%s\" does not exist",
GET_STR(relname_text))));
pkattnums = (int16 *) PG_GETARG_POINTER(1);
pkattnums = (int2vector *) PG_GETARG_POINTER(1);
pknumatts_tmp = PG_GETARG_INT32(2);
if (pknumatts_tmp <= SHRT_MAX)
pknumatts = pknumatts_tmp;
@ -1246,7 +1246,7 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
{
Oid relid;
text *relname_text;
int16 *pkattnums;
int2vector *pkattnums;
int pknumatts_tmp;
int16 pknumatts = 0;
char **tgt_pkattvals;
@ -1273,7 +1273,7 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
errmsg("relation \"%s\" does not exist",
GET_STR(relname_text))));
pkattnums = (int16 *) PG_GETARG_POINTER(1);
pkattnums = (int2vector *) PG_GETARG_POINTER(1);
pknumatts_tmp = PG_GETARG_INT32(2);
if (pknumatts_tmp <= SHRT_MAX)
pknumatts = pknumatts_tmp;
@ -1363,7 +1363,7 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
{
Oid relid;
text *relname_text;
int16 *pkattnums;
int2vector *pkattnums;
int pknumatts_tmp;
int16 pknumatts = 0;
char **src_pkattvals;
@ -1395,7 +1395,7 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
errmsg("relation \"%s\" does not exist",
GET_STR(relname_text))));
pkattnums = (int16 *) PG_GETARG_POINTER(1);
pkattnums = (int2vector *) PG_GETARG_POINTER(1);
pknumatts_tmp = PG_GETARG_INT32(2);
if (pknumatts_tmp <= SHRT_MAX)
pknumatts = pknumatts_tmp;
@ -1552,16 +1552,13 @@ get_pkey_attnames(Oid relid, int16 *numatts)
/* we're only interested if it is the primary key */
if (index->indisprimary == TRUE)
{
i = 0;
while (index->indkey[i++] != 0)
(*numatts)++;
*numatts = index->indnatts;
if (*numatts > 0)
{
result = (char **) palloc(*numatts * sizeof(char *));
for (i = 0; i < *numatts; i++)
result[i] = SPI_fname(tupdesc, index->indkey[i]);
result[i] = SPI_fname(tupdesc, index->indkey.values[i]);
}
break;
}
@ -1574,7 +1571,7 @@ get_pkey_attnames(Oid relid, int16 *numatts)
}
static char *
get_sql_insert(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
{
Relation rel;
char *relname;
@ -1664,7 +1661,7 @@ get_sql_insert(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattval
}
static char *
get_sql_delete(Oid relid, int16 *pkattnums, int16 pknumatts, char **tgt_pkattvals)
get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pkattvals)
{
Relation rel;
char *relname;
@ -1688,7 +1685,7 @@ get_sql_delete(Oid relid, int16 *pkattnums, int16 pknumatts, char **tgt_pkattval
appendStringInfo(str, "DELETE FROM %s WHERE ", relname);
for (i = 0; i < pknumatts; i++)
{
int16 pkattnum = pkattnums[i];
int16 pkattnum = pkattnums->values[i];
if (i > 0)
appendStringInfo(str, " AND ");
@ -1720,7 +1717,7 @@ get_sql_delete(Oid relid, int16 *pkattnums, int16 pknumatts, char **tgt_pkattval
}
static char *
get_sql_update(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
{
Relation rel;
char *relname;
@ -1788,7 +1785,7 @@ get_sql_update(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattval
for (i = 0; i < pknumatts; i++)
{
int16 pkattnum = pkattnums[i];
int16 pkattnum = pkattnums->values[i];
if (i > 0)
appendStringInfo(str, " AND ");
@ -1855,7 +1852,7 @@ quote_ident_cstr(char *rawstr)
}
static int16
get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key)
get_attnum_pk_pos(int2vector *pkattnums, int16 pknumatts, int16 key)
{
int i;
@ -1863,14 +1860,14 @@ get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key)
* Not likely a long list anyway, so just scan for the value
*/
for (i = 0; i < pknumatts; i++)
if (key == pkattnums[i])
if (key == pkattnums->values[i])
return i;
return -1;
}
static HeapTuple
get_tuple_of_interest(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals)
get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals)
{
Relation rel;
char *relname;
@ -1907,7 +1904,7 @@ get_tuple_of_interest(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_p
for (i = 0; i < pknumatts; i++)
{
int16 pkattnum = pkattnums[i];
int16 pkattnum = pkattnums->values[i];
if (i > 0)
appendStringInfo(str, " AND ");

View File

@ -1,7 +1,7 @@
/****************************************************************************
* pending.c
* $Id: pending.c,v 1.20 2004/09/10 04:31:06 neilc Exp $
* $PostgreSQL: pgsql/contrib/dbmirror/pending.c,v 1.20 2004/09/10 04:31:06 neilc Exp $
* $Id: pending.c,v 1.21 2005/03/29 00:16:48 tgl Exp $
* $PostgreSQL: pgsql/contrib/dbmirror/pending.c,v 1.21 2005/03/29 00:16:48 tgl Exp $
*
* This file contains a trigger for Postgresql-7.x to record changes to tables
* to a pending table for mirroring.
@ -349,8 +349,8 @@ getPrimaryKey(Oid tblOid)
resDatum = SPI_getbinval(resTuple, SPI_tuptable->tupdesc, 1, &isNull);
tpResultKey = (int2vector *) DatumGetPointer(resDatum);
resultKey = SPI_palloc(sizeof(int2vector));
memcpy(resultKey, tpResultKey, sizeof(int2vector));
resultKey = SPI_palloc(VARSIZE(tpResultKey));
memcpy(resultKey, tpResultKey, VARSIZE(tpResultKey));
return resultKey;
}
@ -438,11 +438,8 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc, Oid tableOid,
}
if (tpPKeys != NULL)
{
debug_msg("dbmirror:packageData have primary keys");
}
cpDataBlock = SPI_palloc(BUFFER_SIZE);
iDataBlockSize = BUFFER_SIZE;
iUsedDataBlock = 0; /* To account for the null */
@ -462,11 +459,10 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc, Oid tableOid,
/* Determine if this is a primary key or not. */
iIsPrimaryKey = 0;
for (iPrimaryKeyIndex = 0;
(*tpPKeys)[iPrimaryKeyIndex] != 0;
iPrimaryKeyIndex < tpPKeys->dim1;
iPrimaryKeyIndex++)
{
if ((*tpPKeys)[iPrimaryKeyIndex]
== iColumnCounter)
if (tpPKeys->values[iPrimaryKeyIndex] == iColumnCounter)
{
iIsPrimaryKey = 1;
break;

View File

@ -1,6 +1,6 @@
<!--
Documentation of the system catalogs, directed toward PostgreSQL developers
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.97 2005/03/27 23:52:51 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.98 2005/03/29 00:16:49 tgl Exp $
-->
<chapter id="catalogs">
@ -2007,32 +2007,6 @@
<entry>The OID of the <structname>pg_class</> entry for the table this index is for</entry>
</row>
<row>
<entry><structfield>indkey</structfield></entry>
<entry><type>int2vector</type></entry>
<entry><literal><link linkend="catalog-pg-attribute"><structname>pg_attribute</structname></link>.attnum</literal></entry>
<entry>
This is an array of <structfield>indnatts</structfield> (up to
<symbol>INDEX_MAX_KEYS</symbol>) values that indicate which
table columns this index indexes. For example a value of
<literal>1 3</literal> would mean that the first and the third table
columns make up the index key. A zero in this array indicates that the
corresponding index attribute is an expression over the table columns,
rather than a simple column reference.
</entry>
</row>
<row>
<entry><structfield>indclass</structfield></entry>
<entry><type>oidvector</type></entry>
<entry><literal><link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link>.oid</literal></entry>
<entry>
For each column in the index key this contains the OID of
the operator class to use. See
<structname>pg_opclass</structname> for details.
</entry>
</row>
<row>
<entry><structfield>indnatts</structfield></entry>
<entry><type>int2</type></entry>
@ -2063,6 +2037,31 @@
<entry>If true, the table was last clustered on this index.</entry>
</row>
<row>
<entry><structfield>indkey</structfield></entry>
<entry><type>int2vector</type></entry>
<entry><literal><link linkend="catalog-pg-attribute"><structname>pg_attribute</structname></link>.attnum</literal></entry>
<entry>
This is an array of <structfield>indnatts</structfield> values that
indicate which table columns this index indexes. For example a value
of <literal>1 3</literal> would mean that the first and the third table
columns make up the index key. A zero in this array indicates that the
corresponding index attribute is an expression over the table columns,
rather than a simple column reference.
</entry>
</row>
<row>
<entry><structfield>indclass</structfield></entry>
<entry><type>oidvector</type></entry>
<entry><literal><link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link>.oid</literal></entry>
<entry>
For each column in the index key this contains the OID of
the operator class to use. See
<structname>pg_opclass</structname> for details.
</entry>
</row>
<row>
<entry><structfield>indexprs</structfield></entry>
<entry><type>text</type></entry>
@ -3637,7 +3636,7 @@
(<structfield>typlen</structfield> = -1),
but some fixed-length (<structfield>typlen</structfield> &gt; 0) types
also have nonzero <structfield>typelem</structfield>, for example
<type>name</type> and <type>oidvector</type>.
<type>name</type> and <type>point</type>.
If a fixed-length type has a <structfield>typelem</structfield> then
its internal representation must be some number of values of the
<structfield>typelem</structfield> data type with no other data.

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/trigger.sgml,v 1.41 2005/01/22 22:56:36 momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/trigger.sgml,v 1.42 2005/03/29 00:16:49 tgl Exp $
-->
<chapter id="triggers">
@ -453,7 +453,8 @@ typedef struct Trigger
bool tgdeferrable;
bool tginitdeferred;
int16 tgnargs;
int16 tgattr[FUNC_MAX_ARGS];
int16 tgnattr;
int16 *tgattr;
char **tgargs;
} Trigger;
</programlisting>

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hashfunc.c,v 1.42 2004/12/31 21:59:13 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/access/hash/hashfunc.c,v 1.43 2005/03/29 00:16:50 tgl Exp $
*
* NOTES
* These functions are stored in pg_amproc. For each operator class
@ -107,17 +107,17 @@ hashfloat8(PG_FUNCTION_ARGS)
Datum
hashoidvector(PG_FUNCTION_ARGS)
{
Oid *key = (Oid *) PG_GETARG_POINTER(0);
oidvector *key = (oidvector *) PG_GETARG_POINTER(0);
return hash_any((unsigned char *) key, INDEX_MAX_KEYS * sizeof(Oid));
return hash_any((unsigned char *) key->values, key->dim1 * sizeof(Oid));
}
Datum
hashint2vector(PG_FUNCTION_ARGS)
{
int16 *key = (int16 *) PG_GETARG_POINTER(0);
int2vector *key = (int2vector *) PG_GETARG_POINTER(0);
return hash_any((unsigned char *) key, INDEX_MAX_KEYS * sizeof(int16));
return hash_any((unsigned char *) key->values, key->dim1 * sizeof(int2));
}
Datum

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.45 2005/03/27 23:52:59 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.46 2005/03/29 00:16:51 tgl Exp $
*
* NOTES
* many of the old access method routines have been turned into
@ -219,7 +219,7 @@ systable_beginscan(Relation heapRelation,
*/
for (i = 0; i < nkeys; i++)
{
Assert(key[i].sk_attno == irel->rd_index->indkey[i]);
Assert(key[i].sk_attno == irel->rd_index->indkey.values[i]);
key[i].sk_attno = i + 1;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.50 2004/12/31 21:59:22 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.51 2005/03/29 00:16:52 tgl Exp $
*
* NOTES
*
@ -198,15 +198,19 @@ btoidcmp(PG_FUNCTION_ARGS)
Datum
btoidvectorcmp(PG_FUNCTION_ARGS)
{
Oid *a = (Oid *) PG_GETARG_POINTER(0);
Oid *b = (Oid *) PG_GETARG_POINTER(1);
oidvector *a = (oidvector *) PG_GETARG_POINTER(0);
oidvector *b = (oidvector *) PG_GETARG_POINTER(1);
int i;
for (i = 0; i < INDEX_MAX_KEYS; i++)
/* We arbitrarily choose to sort first by vector length */
if (a->dim1 != b->dim1)
PG_RETURN_INT32(a->dim1 - b->dim1);
for (i = 0; i < a->dim1; i++)
{
if (a[i] != b[i])
if (a->values[i] != b->values[i])
{
if (a[i] > b[i])
if (a->values[i] > b->values[i])
PG_RETURN_INT32(1);
else
PG_RETURN_INT32(-1);

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.90 2004/12/31 21:59:22 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.91 2005/03/29 00:16:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -684,7 +684,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
{
RegProcedure cmp_proc;
cmp_proc = get_opclass_proc(rel->rd_index->indclass[i],
cmp_proc = get_opclass_proc(rel->rd_indclass->values[i],
cur->sk_subtype,
BTORDER_PROC);
ScanKeyEntryInitialize(scankeys + i,

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/rtree/rtscan.c,v 1.57 2005/01/18 23:25:48 neilc Exp $
* $PostgreSQL: pgsql/src/backend/access/rtree/rtscan.c,v 1.58 2005/03/29 00:16:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -135,7 +135,7 @@ rtrescan(PG_FUNCTION_ARGS)
Oid int_oper;
RegProcedure int_proc;
opclass = s->indexRelation->rd_index->indclass[attno - 1];
opclass = s->indexRelation->rd_indclass->values[attno - 1];
int_strategy = RTMapToInternalOperator(s->keyData[i].sk_strategy);
int_oper = get_opclass_member(opclass,
s->keyData[i].sk_subtype,

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.199 2005/02/20 02:21:31 tgl Exp $
* $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.200 2005/03/29 00:16:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -139,9 +139,9 @@ static const struct typinfo TypInfo[] = {
F_XIDIN, F_XIDOUT},
{"cid", CIDOID, 0, 4, true, 'i', 'p',
F_CIDIN, F_CIDOUT},
{"int2vector", INT2VECTOROID, INT2OID, INDEX_MAX_KEYS * 2, false, 's', 'p',
{"int2vector", INT2VECTOROID, INT2OID, -1, false, 'i', 'p',
F_INT2VECTORIN, F_INT2VECTOROUT},
{"oidvector", OIDVECTOROID, OIDOID, INDEX_MAX_KEYS * 4, false, 'i', 'p',
{"oidvector", OIDVECTOROID, OIDOID, -1, false, 'i', 'p',
F_OIDVECTORIN, F_OIDVECTOROUT},
{"_int4", INT4ARRAYOID, INT4OID, -1, false, 'i', 'x',
F_ARRAY_IN, F_ARRAY_OUT},
@ -667,7 +667,6 @@ closerel(char *name)
void
DefineAttr(char *name, char *type, int attnum)
{
int attlen;
Oid typeoid;
if (boot_reldesc != NULL)
@ -689,7 +688,7 @@ DefineAttr(char *name, char *type, int attnum)
if (Typ != NULL)
{
attrtypes[attnum]->atttypid = Ap->am_oid;
attlen = attrtypes[attnum]->attlen = Ap->am_typ.typlen;
attrtypes[attnum]->attlen = Ap->am_typ.typlen;
attrtypes[attnum]->attbyval = Ap->am_typ.typbyval;
attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;
attrtypes[attnum]->attalign = Ap->am_typ.typalign;
@ -702,12 +701,13 @@ DefineAttr(char *name, char *type, int attnum)
else
{
attrtypes[attnum]->atttypid = TypInfo[typeoid].oid;
attlen = attrtypes[attnum]->attlen = TypInfo[typeoid].len;
attrtypes[attnum]->attlen = TypInfo[typeoid].len;
attrtypes[attnum]->attbyval = TypInfo[typeoid].byval;
attrtypes[attnum]->attstorage = TypInfo[typeoid].storage;
attrtypes[attnum]->attalign = TypInfo[typeoid].align;
/* if an array type, assume 1-dimensional attribute */
if (TypInfo[typeoid].elem != InvalidOid && attlen < 0)
if (TypInfo[typeoid].elem != InvalidOid &&
attrtypes[attnum]->attlen < 0)
attrtypes[attnum]->attndims = 1;
else
attrtypes[attnum]->attndims = 0;
@ -722,14 +722,22 @@ DefineAttr(char *name, char *type, int attnum)
* Mark as "not null" if type is fixed-width and prior columns are
* too. This corresponds to case where column can be accessed directly
* via C struct declaration.
*
* oidvector and int2vector are also treated as not-nullable, even
* though they are no longer fixed-width.
*/
if (attlen > 0)
#define MARKNOTNULL(att) \
((att)->attlen > 0 || \
(att)->atttypid == OIDVECTOROID || \
(att)->atttypid == INT2VECTOROID)
if (MARKNOTNULL(attrtypes[attnum]))
{
int i;
for (i = 0; i < attnum; i++)
{
if (attrtypes[i]->attlen <= 0)
if (!MARKNOTNULL(attrtypes[i]))
break;
}
if (i == attnum)

View File

@ -10,7 +10,7 @@
#
#
# IDENTIFICATION
# $PostgreSQL: pgsql/src/backend/catalog/genbki.sh,v 1.32 2004/01/04 05:57:21 tgl Exp $
# $PostgreSQL: pgsql/src/backend/catalog/genbki.sh,v 1.33 2005/03/29 00:16:55 tgl Exp $
#
# NOTES
# non-essential whitespace is removed from the generated file.
@ -113,15 +113,6 @@ for dir in $INCLUDE_DIRS; do
fi
done
# Get INDEX_MAX_KEYS from pg_config_manual.h
# (who needs consistency?)
for dir in $INCLUDE_DIRS; do
if [ -f "$dir/pg_config_manual.h" ]; then
INDEXMAXKEYS=`grep '^#define[ ]*INDEX_MAX_KEYS' $dir/pg_config_manual.h | $AWK '{ print $3 }'`
break
fi
done
# Get PG_CATALOG_NAMESPACE from catalog/pg_namespace.h
for dir in $INCLUDE_DIRS; do
if [ -f "$dir/catalog/pg_namespace.h" ]; then
@ -139,14 +130,6 @@ for dir in $INCLUDE_DIRS; do
done
export BKIOBJECTID
# NOTE: we assume here that FUNC_MAX_ARGS has the same value as
# INDEX_MAX_KEYS, and don't read it separately from
# pg_config_manual.h. This is OK because both of them must be equal
# to the length of oidvector.
INDEXMAXKEYS2=`expr $INDEXMAXKEYS '*' 2` || exit
INDEXMAXKEYS4=`expr $INDEXMAXKEYS '*' 4` || exit
touch ${OUTPUT_PREFIX}.description.$$
# ----------------
@ -181,12 +164,6 @@ sed -e "s/;[ ]*$//g" \
-e "s/PGUID/1/g" \
-e "s/NAMEDATALEN/$NAMEDATALEN/g" \
-e "s/PGNSP/$PG_CATALOG_NAMESPACE/g" \
-e "s/INDEX_MAX_KEYS\*2/$INDEXMAXKEYS2/g" \
-e "s/INDEX_MAX_KEYS\*4/$INDEXMAXKEYS4/g" \
-e "s/INDEX_MAX_KEYS/$INDEXMAXKEYS/g" \
-e "s/FUNC_MAX_ARGS\*2/$INDEXMAXKEYS2/g" \
-e "s/FUNC_MAX_ARGS\*4/$INDEXMAXKEYS4/g" \
-e "s/FUNC_MAX_ARGS/$INDEXMAXKEYS/g" \
| $AWK '
# ----------------
# now use awk to process remaining .h file..

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.249 2005/03/21 01:24:01 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.250 2005/03/29 00:16:55 tgl Exp $
*
*
* INTERFACE ROUTINES
@ -347,8 +347,8 @@ UpdateIndexRelation(Oid indexoid,
Oid *classOids,
bool primary)
{
int16 indkey[INDEX_MAX_KEYS];
Oid indclass[INDEX_MAX_KEYS];
int2vector *indkey;
oidvector *indclass;
Datum exprsDatum;
Datum predDatum;
Datum values[Natts_pg_index];
@ -358,15 +358,13 @@ UpdateIndexRelation(Oid indexoid,
int i;
/*
* Copy the index key and opclass info into zero-filled vectors
* Copy the index key and opclass info into arrays (should we make the
* caller pass them like this to start with?)
*/
MemSet(indkey, 0, sizeof(indkey));
MemSet(indclass, 0, sizeof(indclass));
indkey = buildint2vector(NULL, indexInfo->ii_NumIndexAttrs);
indclass = buildoidvector(classOids, indexInfo->ii_NumIndexAttrs);
for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
{
indkey[i] = indexInfo->ii_KeyAttrNumbers[i];
indclass[i] = classOids[i];
}
indkey->values[i] = indexInfo->ii_KeyAttrNumbers[i];
/*
* Convert the index expressions (if any) to a text datum
@ -411,12 +409,12 @@ UpdateIndexRelation(Oid indexoid,
values[Anum_pg_index_indexrelid - 1] = ObjectIdGetDatum(indexoid);
values[Anum_pg_index_indrelid - 1] = ObjectIdGetDatum(heapoid);
values[Anum_pg_index_indkey - 1] = PointerGetDatum(indkey);
values[Anum_pg_index_indclass - 1] = PointerGetDatum(indclass);
values[Anum_pg_index_indnatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexAttrs);
values[Anum_pg_index_indisunique - 1] = BoolGetDatum(indexInfo->ii_Unique);
values[Anum_pg_index_indisprimary - 1] = BoolGetDatum(primary);
values[Anum_pg_index_indisclustered - 1] = BoolGetDatum(false);
values[Anum_pg_index_indkey - 1] = PointerGetDatum(indkey);
values[Anum_pg_index_indclass - 1] = PointerGetDatum(indclass);
values[Anum_pg_index_indexprs - 1] = exprsDatum;
if (exprsDatum == (Datum) 0)
nulls[Anum_pg_index_indexprs - 1] = 'n';
@ -871,7 +869,7 @@ BuildIndexInfo(Relation index)
numKeys, RelationGetRelid(index));
ii->ii_NumIndexAttrs = numKeys;
for (i = 0; i < numKeys; i++)
ii->ii_KeyAttrNumbers[i] = indexStruct->indkey[i];
ii->ii_KeyAttrNumbers[i] = indexStruct->indkey.values[i];
/* fetch any expressions needed for expressional indexes */
ii->ii_Expressions = RelationGetIndexExpressions(index);

View File

@ -4,7 +4,7 @@
*
* Copyright (c) 2003-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.26 2005/01/01 20:44:14 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.27 2005/03/29 00:16:56 tgl Exp $
*/
/*
@ -30,13 +30,22 @@ SET search_path TO information_schema, public;
* A few supporting functions first ...
*/
/* This returns the integers from 1 to INDEX_MAX_KEYS/FUNC_MAX_ARGS */
CREATE FUNCTION _pg_keypositions() RETURNS SETOF integer
LANGUAGE sql
IMMUTABLE
AS 'select g.s
from generate_series(1,current_setting(''max_index_keys'')::int,1)
as g(s)';
/* Expand an oidvector or smallint[] into a set with integers 1..N */
CREATE TYPE _pg_expandoidvector_type AS (o oid, n int);
CREATE FUNCTION _pg_expandoidvector(oidvector)
RETURNS SETOF _pg_expandoidvector_type
LANGUAGE sql STRICT IMMUTABLE
AS 'select $1[s], s+1
from generate_series(0,array_upper($1,1),1) as g(s)';
CREATE TYPE _pg_expandsmallint_type AS (i smallint, n int);
CREATE FUNCTION _pg_expandsmallint(smallint[])
RETURNS SETOF _pg_expandsmallint_type
LANGUAGE sql STRICT IMMUTABLE
AS 'select $1[s], s
from generate_series(1,array_upper($1,1),1) as g(s)';
CREATE FUNCTION _pg_keyissubset(smallint[], smallint[]) RETURNS boolean
LANGUAGE sql
@ -501,12 +510,12 @@ CREATE VIEW constraint_column_usage AS
/* unique/primary key/foreign key constraints */
SELECT nr.nspname, r.relname, r.relowner, a.attname, nc.nspname, c.conname
FROM pg_namespace nr, pg_class r, pg_attribute a, pg_namespace nc,
pg_constraint c, _pg_keypositions() AS pos(n)
pg_constraint c
WHERE nr.oid = r.relnamespace
AND r.oid = a.attrelid
AND nc.oid = c.connamespace
AND (CASE WHEN c.contype = 'f' THEN r.oid = c.confrelid AND c.confkey[pos.n] = a.attnum
ELSE r.oid = c.conrelid AND c.conkey[pos.n] = a.attnum END)
AND (CASE WHEN c.contype = 'f' THEN r.oid = c.confrelid AND a.attnum = ANY (c.confkey)
ELSE r.oid = c.conrelid AND a.attnum = ANY (c.conkey) END)
AND NOT a.attisdropped
AND c.contype IN ('p', 'u', 'f')
AND r.relkind = 'r'
@ -707,26 +716,30 @@ GRANT SELECT ON enabled_roles TO PUBLIC;
CREATE VIEW key_column_usage AS
SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog,
CAST(nc.nspname AS sql_identifier) AS constraint_schema,
CAST(c.conname AS sql_identifier) AS constraint_name,
CAST(nc_nspname AS sql_identifier) AS constraint_schema,
CAST(conname AS sql_identifier) AS constraint_name,
CAST(current_database() AS sql_identifier) AS table_catalog,
CAST(nr.nspname AS sql_identifier) AS table_schema,
CAST(r.relname AS sql_identifier) AS table_name,
CAST(nr_nspname AS sql_identifier) AS table_schema,
CAST(relname AS sql_identifier) AS table_name,
CAST(a.attname AS sql_identifier) AS column_name,
CAST(pos.n AS cardinal_number) AS ordinal_position
CAST((ss.x).n AS cardinal_number) AS ordinal_position
FROM pg_namespace nr, pg_class r, pg_attribute a, pg_namespace nc,
pg_constraint c, pg_user u, _pg_keypositions() AS pos(n)
WHERE nr.oid = r.relnamespace
AND r.oid = a.attrelid
AND r.oid = c.conrelid
AND nc.oid = c.connamespace
AND c.conkey[pos.n] = a.attnum
AND NOT a.attisdropped
AND c.contype IN ('p', 'u', 'f')
AND r.relkind = 'r'
AND r.relowner = u.usesysid
AND u.usename = current_user;
FROM pg_attribute a,
(SELECT r.oid, nc.nspname AS nc_nspname, c.conname,
nr.nspname AS nr_nspname, r.relname,
_pg_expandsmallint(c.conkey) AS x
FROM pg_namespace nr, pg_class r, pg_namespace nc,
pg_constraint c, pg_user u
WHERE nr.oid = r.relnamespace
AND r.oid = c.conrelid
AND nc.oid = c.connamespace
AND c.contype IN ('p', 'u', 'f')
AND r.relkind = 'r'
AND r.relowner = u.usesysid
AND u.usename = current_user) AS ss
WHERE ss.oid = a.attrelid
AND a.attnum = (ss.x).i
AND NOT a.attisdropped;
GRANT SELECT ON key_column_usage TO PUBLIC;
@ -738,13 +751,13 @@ GRANT SELECT ON key_column_usage TO PUBLIC;
CREATE VIEW parameters AS
SELECT CAST(current_database() AS sql_identifier) AS specific_catalog,
CAST(n.nspname AS sql_identifier) AS specific_schema,
CAST(p.proname || '_' || CAST(p.oid AS text) AS sql_identifier) AS specific_name,
CAST(pos.n AS cardinal_number) AS ordinal_position,
CAST(n_nspname AS sql_identifier) AS specific_schema,
CAST(proname || '_' || CAST(p_oid AS text) AS sql_identifier) AS specific_name,
CAST((ss.x).n AS cardinal_number) AS ordinal_position,
CAST('IN' AS character_data) AS parameter_mode,
CAST('NO' AS character_data) AS is_result,
CAST('NO' AS character_data) AS as_locator,
CAST(NULLIF(p.proargnames[pos.n], '') AS sql_identifier) AS parameter_name,
CAST(NULLIF(proargnames[(ss.x).n], '') AS sql_identifier) AS parameter_name,
CAST(
CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY'
WHEN nt.nspname = 'pg_catalog' THEN format_type(t.oid, null)
@ -771,15 +784,17 @@ CREATE VIEW parameters AS
CAST(null AS sql_identifier) AS scope_schema,
CAST(null AS sql_identifier) AS scope_name,
CAST(null AS cardinal_number) AS maximum_cardinality,
CAST(pos.n AS sql_identifier) AS dtd_identifier
CAST((ss.x).n AS sql_identifier) AS dtd_identifier
FROM pg_namespace n, pg_proc p, pg_type t, pg_namespace nt, pg_user u,
_pg_keypositions() AS pos(n)
WHERE n.oid = p.pronamespace AND p.pronargs >= pos.n
AND p.proargtypes[pos.n-1] = t.oid AND t.typnamespace = nt.oid
AND p.proowner = u.usesysid
AND (u.usename = current_user OR has_function_privilege(p.oid, 'EXECUTE'));
FROM pg_type t, pg_namespace nt,
(SELECT n.nspname AS n_nspname, p.proname, p.oid AS p_oid,
p.proargnames, _pg_expandoidvector(p.proargtypes) AS x
FROM pg_namespace n, pg_proc p, pg_user u
WHERE n.oid = p.pronamespace
AND p.proowner = u.usesysid
AND (u.usename = current_user OR
has_function_privilege(p.oid, 'EXECUTE'))) AS ss
WHERE t.oid = (ss.x).o AND t.typnamespace = nt.oid;
GRANT SELECT ON parameters TO PUBLIC;
@ -1702,10 +1717,11 @@ CREATE VIEW element_types AS
UNION ALL
/* parameters */
SELECT p.pronamespace, CAST(p.proname || '_' || CAST(p.oid AS text) AS sql_identifier),
'ROUTINE'::text, pos.n, p.proargtypes[pos.n-1]
FROM pg_proc p, _pg_keypositions() AS pos(n)
WHERE p.pronargs >= pos.n
SELECT pronamespace, CAST(proname || '_' || CAST(oid AS text) AS sql_identifier),
'ROUTINE'::text, (ss.x).n, (ss.x).o
FROM (SELECT p.pronamespace, p.proname, p.oid,
_pg_expandoidvector(p.proargtypes) AS x
FROM pg_proc p) AS ss
UNION ALL

View File

@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.73 2004/12/31 21:59:38 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.74 2005/03/29 00:16:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -471,25 +471,22 @@ FuncnameGetCandidates(List *names, int nargs)
recomputeNamespacePath();
}
/* Search syscache by name and (optionally) nargs only */
if (nargs >= 0)
catlist = SearchSysCacheList(PROCNAMENSP, 2,
CStringGetDatum(funcname),
Int16GetDatum(nargs),
0, 0);
else
catlist = SearchSysCacheList(PROCNAMENSP, 1,
CStringGetDatum(funcname),
0, 0, 0);
/* Search syscache by name only */
catlist = SearchSysCacheList(PROCNAMEARGSNSP, 1,
CStringGetDatum(funcname),
0, 0, 0);
for (i = 0; i < catlist->n_members; i++)
{
HeapTuple proctup = &catlist->members[i]->tuple;
Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
int pronargs = procform->pronargs;
int pathpos = 0;
FuncCandidateList newResult;
nargs = procform->pronargs;
/* Ignore if it doesn't match requested argument count */
if (nargs >= 0 && pronargs != nargs)
continue;
if (OidIsValid(namespaceId))
{
@ -529,9 +526,10 @@ FuncnameGetCandidates(List *names, int nargs)
if (catlist->ordered)
{
if (nargs == resultList->nargs &&
memcmp(procform->proargtypes, resultList->args,
nargs * sizeof(Oid)) == 0)
if (pronargs == resultList->nargs &&
memcmp(procform->proargtypes.values,
resultList->args,
pronargs * sizeof(Oid)) == 0)
prevResult = resultList;
else
prevResult = NULL;
@ -542,9 +540,10 @@ FuncnameGetCandidates(List *names, int nargs)
prevResult;
prevResult = prevResult->next)
{
if (nargs == prevResult->nargs &&
memcmp(procform->proargtypes, prevResult->args,
nargs * sizeof(Oid)) == 0)
if (pronargs == prevResult->nargs &&
memcmp(procform->proargtypes.values,
prevResult->args,
pronargs * sizeof(Oid)) == 0)
break;
}
}
@ -567,11 +566,12 @@ FuncnameGetCandidates(List *names, int nargs)
*/
newResult = (FuncCandidateList)
palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
+ nargs * sizeof(Oid));
+ pronargs * sizeof(Oid));
newResult->pathpos = pathpos;
newResult->oid = HeapTupleGetOid(proctup);
newResult->nargs = nargs;
memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
newResult->nargs = pronargs;
memcpy(newResult->args, procform->proargtypes.values,
pronargs * sizeof(Oid));
newResult->next = resultList;
resultList = newResult;
@ -632,7 +632,7 @@ FunctionIsVisible(Oid funcid)
for (; clist; clist = clist->next)
{
if (memcmp(clist->args, procform->proargtypes,
if (memcmp(clist->args, procform->proargtypes.values,
nargs * sizeof(Oid)) == 0)
{
/* Found the expected entry; is it the right proc? */

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.123 2005/01/27 23:23:51 neilc Exp $
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.124 2005/03/29 00:16:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -78,7 +78,7 @@ ProcedureCreate(const char *procedureName,
char nulls[Natts_pg_proc];
Datum values[Natts_pg_proc];
char replaces[Natts_pg_proc];
Oid typev[FUNC_MAX_ARGS];
oidvector *proargtypes;
Datum namesarray;
Oid relid;
NameData procname;
@ -125,10 +125,9 @@ ProcedureCreate(const char *procedureName,
errdetail("A function returning \"anyarray\" or \"anyelement\" must have at least one argument of either type.")));
}
/* Make sure we have a zero-padded param type array */
MemSet(typev, 0, FUNC_MAX_ARGS * sizeof(Oid));
if (parameterCount > 0)
memcpy(typev, parameterTypes, parameterCount * sizeof(Oid));
/* Convert param types to oidvector */
/* (Probably we should make caller pass it this way to start with) */
proargtypes = buildoidvector(parameterTypes, parameterCount);
/* Process param names, if given */
namesarray = create_parameternames_array(parameterCount, parameterNames);
@ -137,13 +136,13 @@ ProcedureCreate(const char *procedureName,
* don't allow functions of complex types that have the same name as
* existing attributes of the type
*/
if (parameterCount == 1 && OidIsValid(typev[0]) &&
(relid = typeidTypeRelid(typev[0])) != InvalidOid &&
if (parameterCount == 1 && OidIsValid(parameterTypes[0]) &&
(relid = typeidTypeRelid(parameterTypes[0])) != InvalidOid &&
get_attnum(relid, procedureName) != InvalidAttrNumber)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_COLUMN),
errmsg("\"%s\" is already an attribute of type %s",
procedureName, format_type_be(typev[0]))));
procedureName, format_type_be(parameterTypes[0]))));
/*
* All seems OK; prepare the data to be inserted into pg_proc.
@ -162,15 +161,15 @@ ProcedureCreate(const char *procedureName,
values[i++] = ObjectIdGetDatum(procNamespace); /* pronamespace */
values[i++] = Int32GetDatum(GetUserId()); /* proowner */
values[i++] = ObjectIdGetDatum(languageObjectId); /* prolang */
values[i++] = BoolGetDatum(isAgg); /* proisagg */
values[i++] = BoolGetDatum(isAgg); /* proisagg */
values[i++] = BoolGetDatum(security_definer); /* prosecdef */
values[i++] = BoolGetDatum(isStrict); /* proisstrict */
values[i++] = BoolGetDatum(returnsSet); /* proretset */
values[i++] = CharGetDatum(volatility); /* provolatile */
values[i++] = UInt16GetDatum(parameterCount); /* pronargs */
values[i++] = ObjectIdGetDatum(returnType); /* prorettype */
values[i++] = PointerGetDatum(typev); /* proargtypes */
values[i++] = namesarray; /* proargnames */
values[i++] = PointerGetDatum(proargtypes); /* proargtypes */
values[i++] = namesarray; /* proargnames */
if (namesarray == PointerGetDatum(NULL))
nulls[Anum_pg_proc_proargnames - 1] = 'n';
values[i++] = DirectFunctionCall1(textin, /* prosrc */
@ -183,11 +182,11 @@ ProcedureCreate(const char *procedureName,
tupDesc = RelationGetDescr(rel);
/* Check for pre-existing definition */
oldtup = SearchSysCache(PROCNAMENSP,
oldtup = SearchSysCache(PROCNAMEARGSNSP,
PointerGetDatum(procedureName),
UInt16GetDatum(parameterCount),
PointerGetDatum(typev),
ObjectIdGetDatum(procNamespace));
PointerGetDatum(proargtypes),
ObjectIdGetDatum(procNamespace),
0);
if (HeapTupleIsValid(oldtup))
{
@ -290,7 +289,7 @@ ProcedureCreate(const char *procedureName,
for (i = 0; i < parameterCount; i++)
{
referenced.classId = RelOid_pg_type;
referenced.objectId = typev[i];
referenced.objectId = parameterTypes[i];
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
@ -492,16 +491,16 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
haspolyarg = false;
for (i = 0; i < proc->pronargs; i++)
{
if (get_typtype(proc->proargtypes[i]) == 'p')
if (get_typtype(proc->proargtypes.values[i]) == 'p')
{
if (proc->proargtypes[i] == ANYARRAYOID ||
proc->proargtypes[i] == ANYELEMENTOID)
if (proc->proargtypes.values[i] == ANYARRAYOID ||
proc->proargtypes.values[i] == ANYELEMENTOID)
haspolyarg = true;
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("SQL functions cannot have arguments of type %s",
format_type_be(proc->proargtypes[i]))));
format_type_be(proc->proargtypes.values[i]))));
}
}
@ -534,7 +533,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
if (!haspolyarg)
{
querytree_list = pg_parse_and_rewrite(prosrc,
proc->proargtypes,
proc->proargtypes.values,
proc->pronargs);
(void) check_sql_fn_retval(proc->prorettype, functyptype,
querytree_list, NULL);

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.22 2004/12/31 21:59:41 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.23 2005/03/29 00:16:57 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@ -246,11 +246,11 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
namespaceOid = procForm->pronamespace;
/* make sure the new name doesn't exist */
if (SearchSysCacheExists(PROCNAMENSP,
if (SearchSysCacheExists(PROCNAMEARGSNSP,
CStringGetDatum(newname),
Int16GetDatum(procForm->pronargs),
PointerGetDatum(procForm->proargtypes),
ObjectIdGetDatum(namespaceOid)))
PointerGetDatum(&procForm->proargtypes),
ObjectIdGetDatum(namespaceOid),
0))
{
if (basetypeOid == ANYOID)
ereport(ERROR,
@ -264,7 +264,7 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
errmsg("function %s already exists in schema \"%s\"",
funcname_signature_string(newname,
procForm->pronargs,
procForm->proargtypes),
procForm->proargtypes.values),
get_namespace_name(namespaceOid))));
}

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.133 2005/03/20 22:00:52 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.134 2005/03/29 00:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -347,7 +347,7 @@ check_index_is_clusterable(Relation OldHeap, Oid indexOid)
* at the first column; multicolumn-capable AMs are *required* to
* index nulls in columns after the first.
*/
colno = OldIndex->rd_index->indkey[0];
colno = OldIndex->rd_index->indkey.values[0];
if (colno > 0)
{
/* ordinary user attribute */

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.56 2005/03/14 00:19:36 neilc Exp $
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.57 2005/03/29 00:16:57 tgl Exp $
*
* DESCRIPTION
* These routines take the parse tree and pick out the
@ -716,18 +716,18 @@ RenameFunction(List *name, List *argtypes, const char *newname)
namespaceOid = procForm->pronamespace;
/* make sure the new name doesn't exist */
if (SearchSysCacheExists(PROCNAMENSP,
if (SearchSysCacheExists(PROCNAMEARGSNSP,
CStringGetDatum(newname),
Int16GetDatum(procForm->pronargs),
PointerGetDatum(procForm->proargtypes),
ObjectIdGetDatum(namespaceOid)))
PointerGetDatum(&procForm->proargtypes),
ObjectIdGetDatum(namespaceOid),
0))
{
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_FUNCTION),
errmsg("function %s already exists in schema \"%s\"",
funcname_signature_string(newname,
procForm->pronargs,
procForm->proargtypes),
procForm->proargtypes.values),
get_namespace_name(namespaceOid))));
}
@ -962,11 +962,11 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
procForm = (Form_pg_proc) GETSTRUCT(tup);
if (argIndex < 0 || argIndex >= procForm->pronargs ||
procForm->proargtypes[argIndex] != OPAQUEOID)
procForm->proargtypes.values[argIndex] != OPAQUEOID)
elog(ERROR, "function %u doesn't take OPAQUE", funcOid);
/* okay to overwrite copied tuple */
procForm->proargtypes[argIndex] = newArgType;
procForm->proargtypes.values[argIndex] = newArgType;
/* update the catalog and its indexes */
simple_heap_update(pg_proc_rel, &tup->t_self, tup);
@ -1064,15 +1064,15 @@ CreateCast(CreateCastStmt *stmt)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("cast function must take one to three arguments")));
if (procstruct->proargtypes[0] != sourcetypeid)
if (procstruct->proargtypes.values[0] != sourcetypeid)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("argument of cast function must match source data type")));
if (nargs > 1 && procstruct->proargtypes[1] != INT4OID)
if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("second argument of cast function must be type integer")));
if (nargs > 2 && procstruct->proargtypes[2] != BOOLOID)
if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("third argument of cast function must be type boolean")));

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.29 2004/12/31 21:59:41 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.30 2005/03/29 00:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -486,7 +486,7 @@ assignProcSubtype(Oid amoid, Oid typeoid, Oid procOid)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("btree procedures must return integer")));
if (procform->proargtypes[0] != typeoid)
if (procform->proargtypes.values[0] != typeoid)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("btree procedures must have index type as first input")));
@ -495,10 +495,10 @@ assignProcSubtype(Oid amoid, Oid typeoid, Oid procOid)
* The subtype is "default" (0) if second input type matches the
* operator class, otherwise it is the second input type.
*/
if (procform->proargtypes[1] == typeoid)
if (procform->proargtypes.values[1] == typeoid)
subtype = InvalidOid;
else
subtype = procform->proargtypes[1];
subtype = procform->proargtypes.values[1];
ReleaseSysCache(proctup);
return subtype;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.151 2005/03/25 18:04:34 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.152 2005/03/29 00:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1419,7 +1419,7 @@ renameatt(Oid myrelid,
for (i = 0; i < indexform->indnatts; i++)
{
if (attnum != indexform->indkey[i])
if (attnum != indexform->indkey.values[i])
continue;
/*
@ -1676,9 +1676,10 @@ update_ri_trigger_args(Oid relid,
* line; so does trigger.c ...
*/
tgnargs = pg_trigger->tgnargs;
val = (bytea *) fastgetattr(tuple,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull);
val = (bytea *)
DatumGetPointer(fastgetattr(tuple,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull));
if (isnull || tgnargs < RI_FIRST_ATTNAME_ARGNO ||
tgnargs > RI_MAX_ARGUMENTS)
{
@ -3202,7 +3203,7 @@ ATExecDropNotNull(Relation rel, const char *colName)
*/
for (i = 0; i < indexStruct->indnatts; i++)
{
if (indexStruct->indkey[i] == attnum)
if (indexStruct->indkey.values[i] == attnum)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("column \"%s\" is in a primary key",
@ -4096,6 +4097,9 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
ListCell *indexoidscan;
HeapTuple indexTuple = NULL;
Form_pg_index indexStruct = NULL;
Datum indclassDatum;
bool isnull;
oidvector *indclass;
int i;
/*
@ -4135,6 +4139,12 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
errmsg("there is no primary key for referenced table \"%s\"",
RelationGetRelationName(pkrel))));
/* Must get indclass the hard way */
indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
Anum_pg_index_indclass, &isnull);
Assert(!isnull);
indclass = (oidvector *) DatumGetPointer(indclassDatum);
/*
* Now build the list of PK attributes from the indkey definition (we
* assume a primary key cannot have expressional elements)
@ -4142,11 +4152,11 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
*attnamelist = NIL;
for (i = 0; i < indexStruct->indnatts; i++)
{
int pkattno = indexStruct->indkey[i];
int pkattno = indexStruct->indkey.values[i];
attnums[i] = pkattno;
atttypids[i] = attnumTypeId(pkrel, pkattno);
opclasses[i] = indexStruct->indclass[i];
opclasses[i] = indclass->values[i];
*attnamelist = lappend(*attnamelist,
makeString(pstrdup(NameStr(*attnumAttName(pkrel, pkattno)))));
}
@ -4205,6 +4215,16 @@ transformFkeyCheckAttrs(Relation pkrel,
heap_attisnull(indexTuple, Anum_pg_index_indpred) &&
heap_attisnull(indexTuple, Anum_pg_index_indexprs))
{
/* Must get indclass the hard way */
Datum indclassDatum;
bool isnull;
oidvector *indclass;
indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
Anum_pg_index_indclass, &isnull);
Assert(!isnull);
indclass = (oidvector *) DatumGetPointer(indclassDatum);
/*
* The given attnum list may match the index columns in any
* order. Check that each list is a subset of the other.
@ -4214,7 +4234,7 @@ transformFkeyCheckAttrs(Relation pkrel,
found = false;
for (j = 0; j < numattrs; j++)
{
if (attnums[i] == indexStruct->indkey[j])
if (attnums[i] == indexStruct->indkey.values[j])
{
found = true;
break;
@ -4230,9 +4250,9 @@ transformFkeyCheckAttrs(Relation pkrel,
found = false;
for (j = 0; j < numattrs; j++)
{
if (attnums[j] == indexStruct->indkey[i])
if (attnums[j] == indexStruct->indkey.values[i])
{
opclasses[j] = indexStruct->indclass[i];
opclasses[j] = indclass->values[i];
found = true;
break;
}

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.181 2005/03/25 21:57:58 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.182 2005/03/29 00:16:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -67,7 +67,7 @@ Oid
CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
{
int16 tgtype;
int16 tgattr[FUNC_MAX_ARGS];
int2vector *tgattr;
Datum values[Natts_pg_trigger];
char nulls[Natts_pg_trigger];
Relation rel;
@ -77,7 +77,7 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
ScanKeyData key;
Relation pgrel;
HeapTuple tuple;
Oid fargtypes[FUNC_MAX_ARGS];
Oid fargtypes[1]; /* dummy */
Oid funcoid;
Oid funcrettype;
Oid trigoid;
@ -275,7 +275,6 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
/*
* Find and validate the trigger function.
*/
MemSet(fargtypes, 0, FUNC_MAX_ARGS * sizeof(Oid));
funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
funcrettype = get_func_rettype(funcoid);
if (funcrettype != TRIGGEROID)
@ -359,7 +358,8 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
CStringGetDatum(""));
}
MemSet(tgattr, 0, FUNC_MAX_ARGS * sizeof(int16));
/* tgattr is currently always a zero-length array */
tgattr = buildint2vector(NULL, 0);
values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
tuple = heap_formtuple(tgrel->rd_att, values, nulls);
@ -774,8 +774,16 @@ RelationBuildTriggers(Relation relation)
build->tgdeferrable = pg_trigger->tgdeferrable;
build->tginitdeferred = pg_trigger->tginitdeferred;
build->tgnargs = pg_trigger->tgnargs;
memcpy(build->tgattr, &(pg_trigger->tgattr),
FUNC_MAX_ARGS * sizeof(int16));
/* tgattr is first var-width field, so OK to access directly */
build->tgnattr = pg_trigger->tgattr.dim1;
if (build->tgnattr > 0)
{
build->tgattr = (int2 *) palloc(build->tgnattr * sizeof(int2));
memcpy(build->tgattr, &(pg_trigger->tgattr.values),
build->tgnattr * sizeof(int2));
}
else
build->tgattr = NULL;
if (build->tgnargs > 0)
{
bytea *val;
@ -783,9 +791,10 @@ RelationBuildTriggers(Relation relation)
char *p;
int i;
val = (bytea *) fastgetattr(htup,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull);
val = (bytea *)
DatumGetPointer(fastgetattr(htup,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull));
if (isnull)
elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
RelationGetRelationName(relation));
@ -928,6 +937,15 @@ CopyTriggerDesc(TriggerDesc *trigdesc)
for (i = 0; i < trigdesc->numtriggers; i++)
{
trigger->tgname = pstrdup(trigger->tgname);
if (trigger->tgnattr > 0)
{
int2 *newattr;
newattr = (int2 *) palloc(trigger->tgnattr * sizeof(int2));
memcpy(newattr, trigger->tgattr,
trigger->tgnattr * sizeof(int2));
trigger->tgattr = newattr;
}
if (trigger->tgnargs > 0)
{
char **newargs;
@ -1031,6 +1049,8 @@ FreeTriggerDesc(TriggerDesc *trigdesc)
for (i = 0; i < trigdesc->numtriggers; i++)
{
pfree(trigger->tgname);
if (trigger->tgnattr > 0)
pfree(trigger->tgattr);
if (trigger->tgnargs > 0)
{
while (--(trigger->tgnargs) >= 0)
@ -1092,8 +1112,11 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
return false;
if (trig1->tgnargs != trig2->tgnargs)
return false;
if (memcmp(trig1->tgattr, trig2->tgattr,
sizeof(trig1->tgattr)) != 0)
if (trig1->tgnattr != trig2->tgnattr)
return false;
if (trig1->tgnattr > 0 &&
memcmp(trig1->tgattr, trig2->tgattr,
trig1->tgnattr * sizeof(int2)) != 0)
return false;
for (j = 0; j < trig1->tgnargs; j++)
if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.174 2005/03/22 20:13:06 tgl Exp $
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.175 2005/03/29 00:16:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -724,9 +724,17 @@ init_fcache(Oid foid, FuncExprState *fcache, MemoryContext fcacheCxt)
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(foid));
/* Safety check (should never fail, as parser should check sooner) */
/*
* Safety check on nargs. Under normal circumstances this should never
* fail, as parser should check sooner. But possibly it might fail
* if server has been compiled with FUNC_MAX_ARGS smaller than some
* functions declared in pg_proc?
*/
if (list_length(fcache->args) > FUNC_MAX_ARGS)
elog(ERROR, "too many arguments");
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg("cannot pass more than %d arguments to a function",
FUNC_MAX_ARGS)));
/* Set up the primary fmgr lookup information */
fmgr_info_cxt(foid, &(fcache->func), fcacheCxt);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.93 2005/03/25 21:57:58 tgl Exp $
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.94 2005/03/29 00:16:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -228,7 +228,7 @@ init_sql_fcache(FmgrInfo *finfo)
argOidVect = (Oid *) palloc(nargs * sizeof(Oid));
memcpy(argOidVect,
procedureStruct->proargtypes,
procedureStruct->proargtypes.values,
nargs * sizeof(Oid));
/* Resolve any polymorphic argument types */
for (argnum = 0; argnum < nargs; argnum++)

View File

@ -61,7 +61,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.131 2005/03/22 20:13:06 tgl Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.132 2005/03/29 00:16:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1300,15 +1300,16 @@ ExecInitAgg(Agg *node, EState *estate)
if (aggtranstype == ANYARRAYOID || aggtranstype == ANYELEMENTOID)
{
/* have to fetch the agg's declared input type... */
Oid agg_arg_types[FUNC_MAX_ARGS];
Oid *agg_arg_types;
int agg_nargs;
(void) get_func_signature(aggref->aggfnoid,
agg_arg_types, &agg_nargs);
&agg_arg_types, &agg_nargs);
Assert(agg_nargs == 1);
aggtranstype = resolve_generic_type(aggtranstype,
inputType,
agg_arg_types[0]);
pfree(agg_arg_types);
}
/* build expression trees using actual argument & result types */

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.190 2005/03/28 00:58:24 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.191 2005/03/29 00:17:02 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -421,15 +421,16 @@ count_agg_clauses_walker(Node *node, AggClauseCounts *counts)
if (aggtranstype == ANYARRAYOID || aggtranstype == ANYELEMENTOID)
{
/* have to fetch the agg's declared input type... */
Oid agg_arg_types[FUNC_MAX_ARGS];
Oid *agg_arg_types;
int agg_nargs;
(void) get_func_signature(aggref->aggfnoid,
agg_arg_types, &agg_nargs);
&agg_arg_types, &agg_nargs);
Assert(agg_nargs == 1);
aggtranstype = resolve_generic_type(aggtranstype,
inputType,
agg_arg_types[0]);
pfree(agg_arg_types);
}
/*
@ -2187,7 +2188,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
{
Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
bool polymorphic = false;
Oid argtypes[FUNC_MAX_ARGS];
Oid *argtypes;
char *src;
Datum tmp;
bool isNull;
@ -2220,22 +2221,6 @@ inline_function(Oid funcid, Oid result_type, List *args,
if (pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
return NULL;
/* Check for polymorphic arguments, and substitute actual arg types */
memcpy(argtypes, funcform->proargtypes, FUNC_MAX_ARGS * sizeof(Oid));
for (i = 0; i < funcform->pronargs; i++)
{
if (argtypes[i] == ANYARRAYOID ||
argtypes[i] == ANYELEMENTOID)
{
polymorphic = true;
argtypes[i] = exprType((Node *) list_nth(args, i));
}
}
if (funcform->prorettype == ANYARRAYOID ||
funcform->prorettype == ANYELEMENTOID)
polymorphic = true;
/*
* Setup error traceback support for ereport(). This is so that we
* can finger the function that bad information came from.
@ -2256,6 +2241,24 @@ inline_function(Oid funcid, Oid result_type, List *args,
ALLOCSET_DEFAULT_MAXSIZE);
oldcxt = MemoryContextSwitchTo(mycxt);
/* Check for polymorphic arguments, and substitute actual arg types */
argtypes = (Oid *) palloc(funcform->pronargs * sizeof(Oid));
memcpy(argtypes, funcform->proargtypes.values,
funcform->pronargs * sizeof(Oid));
for (i = 0; i < funcform->pronargs; i++)
{
if (argtypes[i] == ANYARRAYOID ||
argtypes[i] == ANYELEMENTOID)
{
polymorphic = true;
argtypes[i] = exprType((Node *) list_nth(args, i));
}
}
if (funcform->prorettype == ANYARRAYOID ||
funcform->prorettype == ANYELEMENTOID)
polymorphic = true;
/* Fetch and parse the function body */
tmp = SysCacheGetAttr(PROCOID,
func_tuple,

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.102 2005/03/27 06:29:42 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.103 2005/03/29 00:17:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -137,8 +137,8 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel)
for (i = 0; i < ncolumns; i++)
{
info->classlist[i] = index->indclass[i];
info->indexkeys[i] = index->indkey[i];
info->classlist[i] = indexRelation->rd_indclass->values[i];
info->indexkeys[i] = index->indkey.values[i];
}
info->relam = indexRelation->rd_rel->relam;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.67 2005/03/10 23:21:23 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.68 2005/03/29 00:17:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -367,14 +367,13 @@ build_aggregate_fnexprs(Oid agg_input_type,
Expr **transfnexpr,
Expr **finalfnexpr)
{
Oid transfn_arg_types[FUNC_MAX_ARGS];
int transfn_nargs;
Param *arg0;
Param *arg1;
List *args;
/* get the transition function signature (only need nargs) */
(void) get_func_signature(transfn_oid, transfn_arg_types, &transfn_nargs);
/* get the transition function arg count */
transfn_nargs = get_func_nargs(transfn_oid);
/*
* Build arg list to use in the transfn FuncExpr node. We really only

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.126 2004/12/31 22:00:27 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.127 2005/03/29 00:17:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -615,9 +615,9 @@ build_coercion_expression(Node *node, Oid funcId,
Assert(!procstruct->proisagg);
nargs = procstruct->pronargs;
Assert(nargs >= 1 && nargs <= 3);
/* Assert(procstruct->proargtypes[0] == exprType(node)); */
Assert(nargs < 2 || procstruct->proargtypes[1] == INT4OID);
Assert(nargs < 3 || procstruct->proargtypes[2] == BOOLOID);
/* Assert(procstruct->proargtypes.values[0] == exprType(node)); */
Assert(nargs < 2 || procstruct->proargtypes.values[1] == INT4OID);
Assert(nargs < 3 || procstruct->proargtypes.values[2] == BOOLOID);
ReleaseSysCache(tp);
@ -1672,11 +1672,21 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
* of array types. If so, and if the element types have a
* suitable cast, use array_type_coerce() or
* array_type_length_coerce().
*
* Hack: disallow coercions to oidvector and int2vector, which
* otherwise tend to capture coercions that should go to "real" array
* types. We want those types to be considered "real" arrays for many
* purposes, but not this one. (Also, array_type_coerce isn't
* guaranteed to produce an output that meets the restrictions of
* these datatypes, such as being 1-dimensional.)
*/
Oid targetElemType;
Oid sourceElemType;
Oid elemfuncid;
if (targetTypeId == OIDVECTOROID || targetTypeId == INT2VECTOROID)
return false;
if ((targetElemType = get_element_type(targetTypeId)) != InvalidOid &&
(sourceElemType = get_element_type(sourceTypeId)) != InvalidOid)
{
@ -1691,11 +1701,7 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
else
{
/* does the function take a typmod arg? */
Oid argtypes[FUNC_MAX_ARGS];
int nargs;
(void) get_func_signature(elemfuncid, argtypes, &nargs);
if (nargs > 1)
if (get_func_nargs(elemfuncid) > 1)
*funcid = F_ARRAY_TYPE_LENGTH_COERCE;
else
*funcid = F_ARRAY_TYPE_COERCE;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.77 2004/12/31 22:01:16 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.78 2005/03/29 00:17:05 tgl Exp $
*
* NOTES
* This cruft is the server side of PQfn.
@ -230,9 +230,14 @@ fetch_fp_info(Oid func_id, struct fp_info * fip)
errmsg("function with OID %u does not exist", func_id)));
pp = (Form_pg_proc) GETSTRUCT(func_htp);
/* watch out for catalog entries with more than FUNC_MAX_ARGS args */
if (pp->pronargs > FUNC_MAX_ARGS)
elog(ERROR, "function %s has more than %d arguments",
NameStr(pp->proname), FUNC_MAX_ARGS);
fip->namespace = pp->pronamespace;
fip->rettype = pp->prorettype;
memcpy(fip->argtypes, pp->proargtypes, FUNC_MAX_ARGS * sizeof(Oid));
memcpy(fip->argtypes, pp->proargtypes.values, pp->pronargs * sizeof(Oid));
ReleaseSysCache(func_htp);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.117 2005/03/24 21:50:37 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.118 2005/03/29 00:17:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -56,7 +56,7 @@
*
*
* There are also some "fixed-length array" datatypes, such as NAME and
* OIDVECTOR. These are simply a sequence of a fixed number of items each
* POINT. These are simply a sequence of a fixed number of items each
* of a fixed-length datatype, with no overhead; the item size must be
* a multiple of its alignment requirement, because we do no padding.
* We support subscripting on these types, but array_in() and array_out()

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.39 2004/12/31 22:01:21 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.40 2005/03/29 00:17:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -140,12 +140,15 @@ format_type_internal(Oid type_oid, int32 typemod,
/*
* Check if it's an array (and not a domain --- we don't want to show
* the substructure of a domain type). Fixed-length array types such
* as "name" shouldn't get deconstructed either.
* as "name" shouldn't get deconstructed either. As of Postgres 8.1,
* rather than checking typlen we check the toast property, and don't
* deconstruct "plain storage" array types --- this is because we don't
* want to show oidvector as oid[].
*/
array_base_type = typeform->typelem;
if (array_base_type != InvalidOid &&
typeform->typlen == -1 &&
typeform->typstorage != 'p' &&
typeform->typtype != 'd')
{
/* Switch our attention to the array element type */
@ -459,29 +462,17 @@ type_maximum_size(Oid type_oid, int32 typemod)
/*
* oidvectortypes - converts a vector of type OIDs to "typname" list
*
* The interface for this function is wrong: it should be told how many
* OIDs are significant in the input vector, so that trailing InvalidOid
* argument types can be recognized.
*/
Datum
oidvectortypes(PG_FUNCTION_ARGS)
{
Oid *oidArray = (Oid *) PG_GETARG_POINTER(0);
oidvector *oidArray = (oidvector *) PG_GETARG_POINTER(0);
char *result;
int numargs;
int numargs = oidArray->dim1;
int num;
size_t total;
size_t left;
/* Try to guess how many args there are :-( */
numargs = 0;
for (num = 0; num < FUNC_MAX_ARGS; num++)
{
if (oidArray[num] != InvalidOid)
numargs = num + 1;
}
total = 20 * numargs + 1;
result = palloc(total);
result[0] = '\0';
@ -489,7 +480,7 @@ oidvectortypes(PG_FUNCTION_ARGS)
for (num = 0; num < numargs; num++)
{
char *typename = format_type_internal(oidArray[num], -1,
char *typename = format_type_internal(oidArray->values[num], -1,
false, true);
size_t slen = strlen(typename);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.65 2005/02/27 08:31:30 neilc Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.66 2005/03/29 00:17:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -33,8 +33,10 @@
#include <ctype.h>
#include <limits.h>
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "utils/array.h"
#include "utils/builtins.h"
@ -47,6 +49,8 @@
#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
#define Int2VectorSize(n) (offsetof(int2vector, values) + (n) * sizeof(int2))
typedef struct
{
int32 current;
@ -109,20 +113,49 @@ int2send(PG_FUNCTION_ARGS)
}
/*
* int2vectorin - converts "num num ..." to internal form
* construct int2vector given a raw array of int2s
*
* Note: Fills any missing slots with zeroes.
* If int2s is NULL then caller must fill values[] afterward
*/
int2vector *
buildint2vector(const int2 *int2s, int n)
{
int2vector *result;
result = (int2vector *) palloc0(Int2VectorSize(n));
if (n > 0 && int2s)
memcpy(result->values, int2s, n * sizeof(int2));
/*
* Attach standard array header. For historical reasons, we set the
* index lower bound to 0 not 1.
*/
result->size = Int2VectorSize(n);
result->ndim = 1;
result->flags = 0;
result->elemtype = INT2OID;
result->dim1 = n;
result->lbound1 = 0;
return result;
}
/*
* int2vectorin - converts "num num ..." to internal form
*/
Datum
int2vectorin(PG_FUNCTION_ARGS)
{
char *intString = PG_GETARG_CSTRING(0);
int16 *result = (int16 *) palloc(sizeof(int16[INDEX_MAX_KEYS]));
int slot;
int2vector *result;
int n;
for (slot = 0; *intString && slot < INDEX_MAX_KEYS; slot++)
result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS));
for (n = 0; *intString && n < FUNC_MAX_ARGS; n++)
{
if (sscanf(intString, "%hd", &result[slot]) != 1)
if (sscanf(intString, "%hd", &result->values[n]) != 1)
break;
while (*intString && isspace((unsigned char) *intString))
intString++;
@ -136,8 +169,12 @@ int2vectorin(PG_FUNCTION_ARGS)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("int2vector has too many elements")));
while (slot < INDEX_MAX_KEYS)
result[slot++] = 0;
result->size = Int2VectorSize(n);
result->ndim = 1;
result->flags = 0;
result->elemtype = INT2OID;
result->dim1 = n;
result->lbound1 = 0;
PG_RETURN_POINTER(result);
}
@ -148,24 +185,19 @@ int2vectorin(PG_FUNCTION_ARGS)
Datum
int2vectorout(PG_FUNCTION_ARGS)
{
int16 *int2Array = (int16 *) PG_GETARG_POINTER(0);
int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
int num,
maxnum;
nnums = int2Array->dim1;
char *rp;
char *result;
/* find last non-zero value in vector */
for (maxnum = INDEX_MAX_KEYS - 1; maxnum >= 0; maxnum--)
if (int2Array[maxnum] != 0)
break;
/* assumes sign, 5 digits, ' ' */
rp = result = (char *) palloc((maxnum + 1) * 7 + 1);
for (num = 0; num <= maxnum; num++)
rp = result = (char *) palloc(nnums * 7 + 1);
for (num = 0; num < nnums; num++)
{
if (num != 0)
*rp++ = ' ';
pg_itoa(int2Array[num], rp);
pg_itoa(int2Array->values[num], rp);
while (*++rp != '\0')
;
}
@ -180,11 +212,19 @@ Datum
int2vectorrecv(PG_FUNCTION_ARGS)
{
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
int16 *result = (int16 *) palloc(sizeof(int16[INDEX_MAX_KEYS]));
int slot;
int2vector *result;
for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
result[slot] = (int16) pq_getmsgint(buf, sizeof(int16));
result = (int2vector *)
DatumGetPointer(DirectFunctionCall2(array_recv,
PointerGetDatum(buf),
ObjectIdGetDatum(INT2OID)));
/* sanity checks: int2vector must be 1-D, no nulls */
if (result->ndim != 1 ||
result->flags != 0 ||
result->elemtype != INT2OID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
errmsg("invalid int2vector data")));
PG_RETURN_POINTER(result);
}
@ -194,14 +234,7 @@ int2vectorrecv(PG_FUNCTION_ARGS)
Datum
int2vectorsend(PG_FUNCTION_ARGS)
{
int16 *int2Array = (int16 *) PG_GETARG_POINTER(0);
StringInfoData buf;
int slot;
pq_begintypsend(&buf);
for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
pq_sendint(&buf, int2Array[slot], sizeof(int16));
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
return array_send(fcinfo);
}
/*
@ -211,10 +244,12 @@ int2vectorsend(PG_FUNCTION_ARGS)
Datum
int2vectoreq(PG_FUNCTION_ARGS)
{
int16 *arg1 = (int16 *) PG_GETARG_POINTER(0);
int16 *arg2 = (int16 *) PG_GETARG_POINTER(1);
int2vector *a = (int2vector *) PG_GETARG_POINTER(0);
int2vector *b = (int2vector *) PG_GETARG_POINTER(1);
PG_RETURN_BOOL(memcmp(arg1, arg2, INDEX_MAX_KEYS * sizeof(int16)) == 0);
if (a->dim1 != b->dim1)
PG_RETURN_BOOL(false);
PG_RETURN_BOOL(memcmp(a->values, b->values, a->dim1 * sizeof(int2)) == 0);
}

View File

@ -8,20 +8,24 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.61 2005/02/11 04:08:58 neilc Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.62 2005/03/29 00:17:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include "catalog/pg_type.h"
#include "libpq/pqformat.h"
#include "utils/array.h"
#include "utils/builtins.h"
#define OidVectorSize(n) (offsetof(oidvector, values) + (n) * sizeof(Oid))
/*****************************************************************************
* USER I/O ROUTINES *
*****************************************************************************/
@ -151,27 +155,54 @@ oidsend(PG_FUNCTION_ARGS)
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
/*
* construct oidvector given a raw array of Oids
*
* If oids is NULL then caller must fill values[] afterward
*/
oidvector *
buildoidvector(const Oid *oids, int n)
{
oidvector *result;
result = (oidvector *) palloc0(OidVectorSize(n));
if (n > 0 && oids)
memcpy(result->values, oids, n * sizeof(Oid));
/*
* Attach standard array header. For historical reasons, we set the
* index lower bound to 0 not 1.
*/
result->size = OidVectorSize(n);
result->ndim = 1;
result->flags = 0;
result->elemtype = OIDOID;
result->dim1 = n;
result->lbound1 = 0;
return result;
}
/*
* oidvectorin - converts "num num ..." to internal form
*
* Note:
* Fills any unsupplied positions with InvalidOid.
*/
Datum
oidvectorin(PG_FUNCTION_ARGS)
{
char *oidString = PG_GETARG_CSTRING(0);
Oid *result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
int slot;
oidvector *result;
int n;
for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
result = (oidvector *) palloc0(OidVectorSize(FUNC_MAX_ARGS));
for (n = 0; n < FUNC_MAX_ARGS; n++)
{
while (*oidString && isspace((unsigned char) *oidString))
oidString++;
if (*oidString == '\0')
break;
result[slot] = oidin_subr("oidvectorin", oidString, &oidString);
result->values[n] = oidin_subr("oidvectorin", oidString, &oidString);
}
while (*oidString && isspace((unsigned char) *oidString))
oidString++;
@ -179,8 +210,13 @@ oidvectorin(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("oidvector has too many elements")));
while (slot < INDEX_MAX_KEYS)
result[slot++] = InvalidOid;
result->size = OidVectorSize(n);
result->ndim = 1;
result->flags = 0;
result->elemtype = OIDOID;
result->dim1 = n;
result->lbound1 = 0;
PG_RETURN_POINTER(result);
}
@ -191,24 +227,19 @@ oidvectorin(PG_FUNCTION_ARGS)
Datum
oidvectorout(PG_FUNCTION_ARGS)
{
Oid *oidArray = (Oid *) PG_GETARG_POINTER(0);
oidvector *oidArray = (oidvector *) PG_GETARG_POINTER(0);
int num,
maxnum;
nnums = oidArray->dim1;
char *rp;
char *result;
/* find last non-zero value in vector */
for (maxnum = INDEX_MAX_KEYS - 1; maxnum >= 0; maxnum--)
if (oidArray[maxnum] != 0)
break;
/* assumes sign, 10 digits, ' ' */
rp = result = (char *) palloc((maxnum + 1) * 12 + 1);
for (num = 0; num <= maxnum; num++)
rp = result = (char *) palloc(nnums * 12 + 1);
for (num = 0; num < nnums; num++)
{
if (num != 0)
*rp++ = ' ';
sprintf(rp, "%u", oidArray[num]);
sprintf(rp, "%u", oidArray->values[num]);
while (*++rp != '\0')
;
}
@ -223,11 +254,19 @@ Datum
oidvectorrecv(PG_FUNCTION_ARGS)
{
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
Oid *result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
int slot;
oidvector *result;
for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
result[slot] = (Oid) pq_getmsgint(buf, sizeof(Oid));
result = (oidvector *)
DatumGetPointer(DirectFunctionCall2(array_recv,
PointerGetDatum(buf),
ObjectIdGetDatum(OIDOID)));
/* sanity checks: oidvector must be 1-D, no nulls */
if (result->ndim != 1 ||
result->flags != 0 ||
result->elemtype != OIDOID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
errmsg("invalid oidvector data")));
PG_RETURN_POINTER(result);
}
@ -237,14 +276,7 @@ oidvectorrecv(PG_FUNCTION_ARGS)
Datum
oidvectorsend(PG_FUNCTION_ARGS)
{
Oid *oidArray = (Oid *) PG_GETARG_POINTER(0);
StringInfoData buf;
int slot;
pq_begintypsend(&buf);
for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
pq_sendint(&buf, oidArray[slot], sizeof(Oid));
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
return array_send(fcinfo);
}
@ -327,71 +359,49 @@ oidsmaller(PG_FUNCTION_ARGS)
Datum
oidvectoreq(PG_FUNCTION_ARGS)
{
Oid *arg1 = (Oid *) PG_GETARG_POINTER(0);
Oid *arg2 = (Oid *) PG_GETARG_POINTER(1);
int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
PG_RETURN_BOOL(memcmp(arg1, arg2, INDEX_MAX_KEYS * sizeof(Oid)) == 0);
PG_RETURN_BOOL(cmp == 0);
}
Datum
oidvectorne(PG_FUNCTION_ARGS)
{
Oid *arg1 = (Oid *) PG_GETARG_POINTER(0);
Oid *arg2 = (Oid *) PG_GETARG_POINTER(1);
int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
PG_RETURN_BOOL(memcmp(arg1, arg2, INDEX_MAX_KEYS * sizeof(Oid)) != 0);
PG_RETURN_BOOL(cmp != 0);
}
Datum
oidvectorlt(PG_FUNCTION_ARGS)
{
Oid *arg1 = (Oid *) PG_GETARG_POINTER(0);
Oid *arg2 = (Oid *) PG_GETARG_POINTER(1);
int i;
int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
for (i = 0; i < INDEX_MAX_KEYS; i++)
if (arg1[i] != arg2[i])
PG_RETURN_BOOL(arg1[i] < arg2[i]);
PG_RETURN_BOOL(false);
PG_RETURN_BOOL(cmp < 0);
}
Datum
oidvectorle(PG_FUNCTION_ARGS)
{
Oid *arg1 = (Oid *) PG_GETARG_POINTER(0);
Oid *arg2 = (Oid *) PG_GETARG_POINTER(1);
int i;
int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
for (i = 0; i < INDEX_MAX_KEYS; i++)
if (arg1[i] != arg2[i])
PG_RETURN_BOOL(arg1[i] <= arg2[i]);
PG_RETURN_BOOL(true);
PG_RETURN_BOOL(cmp <= 0);
}
Datum
oidvectorge(PG_FUNCTION_ARGS)
{
Oid *arg1 = (Oid *) PG_GETARG_POINTER(0);
Oid *arg2 = (Oid *) PG_GETARG_POINTER(1);
int i;
int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
for (i = 0; i < INDEX_MAX_KEYS; i++)
if (arg1[i] != arg2[i])
PG_RETURN_BOOL(arg1[i] >= arg2[i]);
PG_RETURN_BOOL(true);
PG_RETURN_BOOL(cmp >= 0);
}
Datum
oidvectorgt(PG_FUNCTION_ARGS)
{
Oid *arg1 = (Oid *) PG_GETARG_POINTER(0);
Oid *arg2 = (Oid *) PG_GETARG_POINTER(1);
int i;
int32 cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
for (i = 0; i < INDEX_MAX_KEYS; i++)
if (arg1[i] != arg2[i])
PG_RETURN_BOOL(arg1[i] > arg2[i]);
PG_RETURN_BOOL(false);
PG_RETURN_BOOL(cmp > 0);
}
Datum

View File

@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.92 2004/12/31 22:01:22 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.93 2005/03/29 00:17:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -98,7 +98,7 @@ regprocin(PG_FUNCTION_ARGS)
CStringGetDatum(pro_name_or_oid));
hdesc = heap_openr(ProcedureRelationName, AccessShareLock);
sysscan = systable_beginscan(hdesc, ProcedureNameNspIndex, true,
sysscan = systable_beginscan(hdesc, ProcedureNameArgsNspIndex, true,
SnapshotNow, 1, skey);
while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
@ -336,7 +336,7 @@ format_procedure(Oid procedure_oid)
quote_qualified_identifier(nspname, proname));
for (i = 0; i < nargs; i++)
{
Oid thisargtype = procform->proargtypes[i];
Oid thisargtype = procform->proargtypes.values[i];
if (i > 0)
appendStringInfoChar(&buf, ',');

View File

@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.188 2005/01/13 17:19:10 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.189 2005/03/29 00:17:08 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@ -553,9 +553,10 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
char *p;
int i;
val = (bytea *) fastgetattr(ht_trig,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull);
val = (bytea *)
DatumGetPointer(fastgetattr(ht_trig,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull));
if (isnull)
elog(ERROR, "tgargs is null for trigger %u", trigid);
p = (char *) VARDATA(val);
@ -637,6 +638,9 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
Oid indrelid;
int keyno;
Oid keycoltype;
Datum indclassDatum;
bool isnull;
oidvector *indclass;
StringInfoData buf;
char *str;
char *sep;
@ -654,6 +658,12 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
indrelid = idxrec->indrelid;
Assert(indexrelid == idxrec->indexrelid);
/* Must get indclass the hard way */
indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
Anum_pg_index_indclass, &isnull);
Assert(!isnull);
indclass = (oidvector *) DatumGetPointer(indclassDatum);
/*
* Fetch the pg_class tuple of the index relation
*/
@ -720,7 +730,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
sep = "";
for (keyno = 0; keyno < idxrec->indnatts; keyno++)
{
AttrNumber attnum = idxrec->indkey[keyno];
AttrNumber attnum = idxrec->indkey.values[keyno];
if (!colno)
appendStringInfo(&buf, sep);
@ -764,7 +774,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
* Add the operator class name
*/
if (!colno)
get_opclass_name(idxrec->indclass[keyno], keycoltype,
get_opclass_name(indclass->values[keyno], keycoltype,
&buf);
}
@ -3537,7 +3547,10 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
nargs = 0;
foreach(l, expr->args)
{
Assert(nargs < FUNC_MAX_ARGS);
if (nargs >= FUNC_MAX_ARGS)
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg("too many arguments")));
argtypes[nargs] = exprType((Node *) lfirst(l));
nargs++;
}

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.120 2005/01/27 23:36:12 neilc Exp $
* $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.121 2005/03/29 00:17:11 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@ -773,15 +773,36 @@ get_func_rettype(Oid funcid)
return result;
}
/*
* get_func_nargs
* Given procedure id, return the number of arguments.
*/
int
get_func_nargs(Oid funcid)
{
HeapTuple tp;
int result;
tp = SearchSysCache(PROCOID,
ObjectIdGetDatum(funcid),
0, 0, 0);
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for function %u", funcid);
result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
ReleaseSysCache(tp);
return result;
}
/*
* get_func_signature
* Given procedure id, return the function's argument and result types.
* (The return value is the result type.)
*
* argtypes must point to a vector of size FUNC_MAX_ARGS.
* The arguments are returned as a palloc'd array.
*/
Oid
get_func_signature(Oid funcid, Oid *argtypes, int *nargs)
get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
{
HeapTuple tp;
Form_pg_proc procstruct;
@ -796,8 +817,10 @@ get_func_signature(Oid funcid, Oid *argtypes, int *nargs)
procstruct = (Form_pg_proc) GETSTRUCT(tp);
result = procstruct->prorettype;
memcpy(argtypes, procstruct->proargtypes, FUNC_MAX_ARGS * sizeof(Oid));
*nargs = (int) procstruct->pronargs;
Assert(*nargs == procstruct->proargtypes.dim1);
*argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
ReleaseSysCache(tp);
return result;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.217 2005/03/28 00:58:26 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.218 2005/03/29 00:17:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -27,7 +27,6 @@
*/
#include "postgres.h"
#include <errno.h>
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
@ -81,6 +80,7 @@ static FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class};
static FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute};
static FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = {Schema_pg_proc};
static FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type};
static FormData_pg_attribute Desc_pg_index[Natts_pg_index] = {Schema_pg_index};
/*
* Hash tables that index the relation cache
@ -267,10 +267,11 @@ static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo,
Relation oldrelation);
static void RelationInitPhysicalAddr(Relation relation);
static TupleDesc GetPgIndexDescriptor(void);
static void AttrDefaultFetch(Relation relation);
static void CheckConstraintFetch(Relation relation);
static List *insert_ordered_oid(List *list, Oid datum);
static void IndexSupportInitialize(Form_pg_index iform,
static void IndexSupportInitialize(oidvector *indclass,
Oid *indexOperator,
RegProcedure *indexSupport,
StrategyNumber maxStrategyNumber,
@ -918,6 +919,8 @@ RelationInitIndexAccessInfo(Relation relation)
{
HeapTuple tuple;
Form_pg_am aform;
Datum indclassDatum;
bool isnull;
MemoryContext indexcxt;
MemoryContext oldcontext;
Oid *operator;
@ -945,6 +948,18 @@ RelationInitIndexAccessInfo(Relation relation)
MemoryContextSwitchTo(oldcontext);
ReleaseSysCache(tuple);
/*
* indclass cannot be referenced directly through the C struct, because
* it is after the variable-width indkey field. Therefore we extract
* the datum the hard way and provide a direct link in the relcache.
*/
indclassDatum = fastgetattr(relation->rd_indextuple,
Anum_pg_index_indclass,
GetPgIndexDescriptor(),
&isnull);
Assert(!isnull);
relation->rd_indclass = (oidvector *) DatumGetPointer(indclassDatum);
/*
* Make a copy of the pg_am entry for the index's access method
*/
@ -1014,7 +1029,7 @@ RelationInitIndexAccessInfo(Relation relation)
* Fill the operator and support procedure OID arrays. (supportinfo is
* left as zeroes, and is filled on-the-fly when used)
*/
IndexSupportInitialize(relation->rd_index,
IndexSupportInitialize(relation->rd_indclass,
operator, support,
amstrategies, amsupport, natts);
@ -1028,7 +1043,7 @@ RelationInitIndexAccessInfo(Relation relation)
/*
* IndexSupportInitialize
* Initializes an index's cached opclass information,
* given the index's pg_index tuple.
* given the index's pg_index.indclass entry.
*
* Data is returned into *indexOperator and *indexSupport, which are arrays
* allocated by the caller.
@ -1040,7 +1055,7 @@ RelationInitIndexAccessInfo(Relation relation)
* access method.
*/
static void
IndexSupportInitialize(Form_pg_index iform,
IndexSupportInitialize(oidvector *indclass,
Oid *indexOperator,
RegProcedure *indexSupport,
StrategyNumber maxStrategyNumber,
@ -1049,19 +1064,15 @@ IndexSupportInitialize(Form_pg_index iform,
{
int attIndex;
/*
* XXX note that the following assumes the INDEX tuple is well formed
* and that the *key and *class are 0 terminated.
*/
for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
{
OpClassCacheEnt *opcentry;
if (!OidIsValid(iform->indclass[attIndex]))
if (!OidIsValid(indclass->values[attIndex]))
elog(ERROR, "bogus pg_index tuple");
/* look up the info for this opclass, using a cache */
opcentry = LookupOpclassInfo(iform->indclass[attIndex],
opcentry = LookupOpclassInfo(indclass->values[attIndex],
maxStrategyNumber,
maxSupportNumber);
@ -2479,6 +2490,53 @@ RelationCacheInitializePhase3(void)
}
}
/*
* GetPgIndexDescriptor -- get a predefined tuple descriptor for pg_index
*
* We need this kluge because we have to be able to access non-fixed-width
* fields of pg_index before we have the standard catalog caches available.
* We use predefined data that's set up in just the same way as the
* bootstrapped reldescs used by formrdesc(). The resulting tupdesc is
* not 100% kosher: it does not have the correct relation OID in attrelid,
* nor does it have a TupleConstr field. But it's good enough for the
* purpose of extracting fields.
*/
static TupleDesc
GetPgIndexDescriptor(void)
{
static TupleDesc pgindexdesc = NULL;
MemoryContext oldcxt;
int i;
/* Already done? */
if (pgindexdesc)
return pgindexdesc;
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
pgindexdesc = CreateTemplateTupleDesc(Natts_pg_index, false);
pgindexdesc->tdtypeid = RECORDOID; /* not right, but we don't care */
pgindexdesc->tdtypmod = -1;
for (i = 0; i < Natts_pg_index; i++)
{
memcpy(pgindexdesc->attrs[i],
&Desc_pg_index[i],
ATTRIBUTE_TUPLE_SIZE);
/* make sure attcacheoff is valid */
pgindexdesc->attrs[i]->attcacheoff = -1;
}
/* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
pgindexdesc->attrs[0]->attcacheoff = 0;
/* Note: we don't bother to set up a TupleConstr entry */
MemoryContextSwitchTo(oldcxt);
return pgindexdesc;
}
static void
AttrDefaultFetch(Relation relation)
{
@ -2773,15 +2831,11 @@ RelationGetIndexExpressions(Relation relation)
* After successfully completing the work, we copy it into the
* relcache entry. This avoids problems if we get some sort of error
* partway through.
*
* We make use of the syscache's copy of pg_index's tupledesc to access
* the non-fixed fields of the tuple. We assume that the syscache
* will be initialized before any access of a partial index could
* occur. (This would probably fail if we were to allow partial
* indexes on system catalogs.)
*/
exprsDatum = SysCacheGetAttr(INDEXRELID, relation->rd_indextuple,
Anum_pg_index_indexprs, &isnull);
exprsDatum = heap_getattr(relation->rd_indextuple,
Anum_pg_index_indexprs,
GetPgIndexDescriptor(),
&isnull);
Assert(!isnull);
exprsString = DatumGetCString(DirectFunctionCall1(textout, exprsDatum));
result = (List *) stringToNode(exprsString);
@ -2845,15 +2899,11 @@ RelationGetIndexPredicate(Relation relation)
* After successfully completing the work, we copy it into the
* relcache entry. This avoids problems if we get some sort of error
* partway through.
*
* We make use of the syscache's copy of pg_index's tupledesc to access
* the non-fixed fields of the tuple. We assume that the syscache
* will be initialized before any access of a partial index could
* occur. (This would probably fail if we were to allow partial
* indexes on system catalogs.)
*/
predDatum = SysCacheGetAttr(INDEXRELID, relation->rd_indextuple,
Anum_pg_index_indpred, &isnull);
predDatum = heap_getattr(relation->rd_indextuple,
Anum_pg_index_indpred,
GetPgIndexDescriptor(),
&isnull);
Assert(!isnull);
predString = DatumGetCString(DirectFunctionCall1(textout, predDatum));
result = (List *) stringToNode(predString);
@ -2990,6 +3040,8 @@ load_relcache_init_file(void)
Relation rel;
Form_pg_class relform;
bool has_not_null;
Datum indclassDatum;
bool isnull;
/* first read the relation descriptor length */
if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
@ -3081,6 +3133,14 @@ load_relcache_init_file(void)
rel->rd_indextuple->t_data = (HeapTupleHeader) ((char *) rel->rd_indextuple + HEAPTUPLESIZE);
rel->rd_index = (Form_pg_index) GETSTRUCT(rel->rd_indextuple);
/* fix up indclass pointer too */
indclassDatum = fastgetattr(rel->rd_indextuple,
Anum_pg_index_indclass,
GetPgIndexDescriptor(),
&isnull);
Assert(!isnull);
rel->rd_indclass = (oidvector *) DatumGetPointer(indclassDatum);
/* next, read the access method tuple form */
if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
goto read_failed;
@ -3133,6 +3193,7 @@ load_relcache_init_file(void)
Assert(rel->rd_index == NULL);
Assert(rel->rd_indextuple == NULL);
Assert(rel->rd_indclass == NULL);
Assert(rel->rd_am == NULL);
Assert(rel->rd_indexcxt == NULL);
Assert(rel->rd_operator == NULL);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.96 2004/12/31 22:01:25 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.97 2005/03/29 00:17:12 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
@ -334,15 +334,15 @@ static const struct cachedesc cacheinfo[] = {
0,
0
}},
{ProcedureRelationName, /* PROCNAMENSP */
ProcedureNameNspIndex,
{ProcedureRelationName, /* PROCNAMEARGSNSP */
ProcedureNameArgsNspIndex,
0,
4,
3,
{
Anum_pg_proc_proname,
Anum_pg_proc_pronargs,
Anum_pg_proc_proargtypes,
Anum_pg_proc_pronamespace
Anum_pg_proc_pronamespace,
0
}},
{ProcedureRelationName, /* PROCOID */
ProcedureOidIndex,

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.90 2005/03/22 20:13:07 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.91 2005/03/29 00:17:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -344,7 +344,7 @@ fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
for (i = 0; i < procedureStruct->pronargs; i++)
{
fnextra->arg_toastable[i] =
TypeIsToastable(procedureStruct->proargtypes[i]);
TypeIsToastable(procedureStruct->proargtypes.values[i]);
}
break;
case 1:

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/c.h,v 1.180 2005/02/22 04:41:51 momjian Exp $
* $PostgreSQL: pgsql/src/include/c.h,v 1.181 2005/03/29 00:17:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -428,11 +428,36 @@ typedef struct varlena BpChar; /* blank-padded char, ie SQL char(n) */
typedef struct varlena VarChar; /* var-length char, ie SQL varchar(n) */
/*
* Fixed-length array types (these are not varlena's!)
* Specialized array types. These are physically laid out just the same
* as regular arrays (so that the regular array subscripting code works
* with them). They exist as distinct types mostly for historical reasons:
* they have nonstandard I/O behavior which we don't want to change for fear
* of breaking applications that look at the system catalogs. There is also
* an implementation issue for oidvector: it's part of the primary key for
* pg_proc, and we can't use the normal btree array support routines for that
* without circularity.
*/
typedef struct
{
int32 size; /* these fields must match ArrayType! */
int ndim;
int flags;
Oid elemtype;
int dim1;
int lbound1;
int2 values[1]; /* VARIABLE LENGTH ARRAY */
} int2vector; /* VARIABLE LENGTH STRUCT */
typedef int2 int2vector[INDEX_MAX_KEYS];
typedef Oid oidvector[INDEX_MAX_KEYS];
typedef struct
{
int32 size; /* these fields must match ArrayType! */
int ndim;
int flags;
Oid elemtype;
int dim1;
int lbound1;
Oid values[1]; /* VARIABLE LENGTH ARRAY */
} oidvector; /* VARIABLE LENGTH STRUCT */
/*
* We want NameData to have length NAMEDATALEN and int alignment,

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.260 2005/03/27 23:53:05 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.261 2005/03/29 00:17:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200503271
#define CATALOG_VERSION_NO 200503281
#endif

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.84 2004/12/31 22:03:24 pgsql Exp $
* $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.85 2005/03/29 00:17:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -63,7 +63,7 @@
#define OpclassOidIndex "pg_opclass_oid_index"
#define OperatorNameNspIndex "pg_operator_oprname_l_r_n_index"
#define OperatorOidIndex "pg_operator_oid_index"
#define ProcedureNameNspIndex "pg_proc_proname_args_nsp_index"
#define ProcedureNameArgsNspIndex "pg_proc_proname_args_nsp_index"
#define ProcedureOidIndex "pg_proc_oid_index"
#define RewriteOidIndex "pg_rewrite_oid_index"
#define RewriteRelRulenameIndex "pg_rewrite_rel_rulename_index"
@ -161,7 +161,7 @@ DECLARE_UNIQUE_INDEX(pg_opclass_oid_index on pg_opclass using btree(oid oid_ops)
DECLARE_UNIQUE_INDEX(pg_operator_oid_index on pg_operator using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
DECLARE_UNIQUE_INDEX(pg_proc_oid_index on pg_proc using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index on pg_proc using btree(proname name_ops, pronargs int2_ops, proargtypes oidvector_ops, pronamespace oid_ops));
DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index on pg_proc using btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
/* This following index is not used for a cache and is not unique */
DECLARE_UNIQUE_INDEX(pg_rewrite_oid_index on pg_rewrite using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index on pg_rewrite using btree(ev_class oid_ops, rulename name_ops));

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.113 2004/12/31 22:03:24 pgsql Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.114 2005/03/29 00:17:17 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -317,7 +317,7 @@ DATA(insert ( 1262 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
{ 1255, {"provolatile"}, 18, -1, 1, 9, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1255, {"pronargs"}, 21, -1, 2, 10, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1255, {"prorettype"}, 26, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1255, {"proargtypes"}, 30, -1, INDEX_MAX_KEYS*4, 12, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
{ 1255, {"proargtypes"}, 30, -1, -1, 12, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
{ 1255, {"proargnames"}, 1009, -1, -1, 13, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1255, {"prosrc"}, 25, -1, -1, 14, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1255, {"probin"}, 17, -1, -1, 15, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
@ -334,7 +334,7 @@ DATA(insert ( 1255 proretset 16 -1 1 8 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1255 provolatile 18 -1 1 9 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1255 pronargs 21 -1 2 10 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1255 prorettype 26 -1 4 11 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1255 proargtypes 30 -1 INDEX_MAX_KEYS*4 12 0 -1 -1 f p i t f f t 0));
DATA(insert ( 1255 proargtypes 30 -1 -1 12 1 -1 -1 f p i t f f t 0));
DATA(insert ( 1255 proargnames 1009 -1 -1 13 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1255 prosrc 25 -1 -1 14 0 -1 -1 f x i f f f t 0));
DATA(insert ( 1255 probin 17 -1 -1 15 0 -1 -1 f x i f f f t 0));
@ -511,6 +511,26 @@ DATA(insert ( 1213 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1213 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1213 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
/* ----------------
* pg_index
*
* pg_index is not bootstrapped in the same way as the other relations that
* have hardwired pg_attribute entries in this file. However, we do need
* a "Schema_xxx" macro for it --- see relcache.c.
* ----------------
*/
#define Schema_pg_index \
{ 0, {"indexrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 0, {"indrelid"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 0, {"indnatts"}, 21, -1, 2, 3, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 0, {"indisunique"}, 16, -1, 1, 4, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 0, {"indisprimary"}, 16, -1, 1, 5, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 0, {"indisclustered"}, 16, -1, 1, 6, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 0, {"indkey"}, 22, -1, -1, 7, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
{ 0, {"indclass"}, 30, -1, -1, 8, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
{ 0, {"indexprs"}, 25, -1, -1, 9, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 0, {"indpred"}, 25, -1, -1, 10, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
/* ----------------
* pg_xactlock - this is not a real relation, but is a placeholder
* to allow a relation OID to be used for transaction

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_index.h,v 1.35 2004/12/31 22:03:24 pgsql Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_index.h,v 1.36 2005/03/29 00:17:17 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -35,14 +35,14 @@ CATALOG(pg_index) BKI_WITHOUT_OIDS
{
Oid indexrelid; /* OID of the index */
Oid indrelid; /* OID of the relation it indexes */
int2vector indkey; /* column numbers of indexed cols, or 0 */
oidvector indclass; /* opclass identifiers */
int2 indnatts; /* number of columns in index */
bool indisunique; /* is this a unique index? */
bool indisprimary; /* is this index for primary key? */
bool indisclustered; /* is this the index last clustered by? */
/* VARIABLE LENGTH FIELDS: */
int2vector indkey; /* column numbers of indexed cols, or 0 */
oidvector indclass; /* opclass identifiers */
text indexprs; /* expression trees for index attributes
* that are not simple column references;
* one for each zero entry in indkey[] */
@ -64,12 +64,12 @@ typedef FormData_pg_index *Form_pg_index;
#define Natts_pg_index 10
#define Anum_pg_index_indexrelid 1
#define Anum_pg_index_indrelid 2
#define Anum_pg_index_indkey 3
#define Anum_pg_index_indclass 4
#define Anum_pg_index_indnatts 5
#define Anum_pg_index_indisunique 6
#define Anum_pg_index_indisprimary 7
#define Anum_pg_index_indisclustered 8
#define Anum_pg_index_indnatts 3
#define Anum_pg_index_indisunique 4
#define Anum_pg_index_indisprimary 5
#define Anum_pg_index_indisclustered 6
#define Anum_pg_index_indkey 7
#define Anum_pg_index_indclass 8
#define Anum_pg_index_indexprs 9
#define Anum_pg_index_indpred 10

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.354 2005/03/27 23:53:05 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.355 2005/03/29 00:17:17 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@ -48,7 +48,7 @@ CATALOG(pg_proc) BOOTSTRAP
char provolatile; /* see PROVOLATILE_ categories below */
int2 pronargs; /* number of arguments */
Oid prorettype; /* OID of result type */
oidvector proargtypes; /* OIDs of argument types */
oidvector proargtypes; /* VARIABLE LENGTH FIELD */
text proargnames[1]; /* VARIABLE LENGTH FIELD */
text prosrc; /* VARIABLE LENGTH FIELD */
bytea probin; /* VARIABLE LENGTH FIELD */

View File

@ -38,12 +38,12 @@ CATALOG(pg_trigger)
bool tgisconstraint; /* trigger is a RI constraint */
NameData tgconstrname; /* RI constraint name */
Oid tgconstrrelid; /* RI table of foreign key definition */
/* in the case of ON DELETE or ON UPDATE */
bool tgdeferrable; /* RI trigger is deferrable */
bool tginitdeferred; /* RI trigger is deferred initially */
int2 tgnargs; /* # of extra arguments in tgargs */
int2vector tgattr; /* UPDATE of attr1, attr2 ... (NI) */
/* VARIABLE LENGTH FIELDS: */
int2vector tgattr; /* reserved for column-specific triggers */
bytea tgargs; /* first\000second\000tgnargs\000 */
} FormData_pg_trigger;

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.158 2004/12/31 22:03:26 pgsql Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.159 2005/03/29 00:17:17 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -88,7 +88,7 @@ CATALOG(pg_type) BOOTSTRAP
* current type can then be subscripted like an array yielding values
* of type typelem. A non-zero typelem does not guarantee this type to
* be a "real" array type; some ordinary fixed-length types can also
* be subscripted (e.g., oidvector). Variable-length types can *not*
* be subscripted (e.g., name, point). Variable-length types can *not*
* be turned into pseudo-arrays like that. Hence, the way to determine
* whether a type is a "true" array type is if:
*
@ -268,8 +268,8 @@ DATA(insert OID = 21 ( int2 PGNSP PGUID 2 t b t \054 0 0 int2in int2out int2
DESCR("-32 thousand to 32 thousand, 2-byte storage");
#define INT2OID 21
DATA(insert OID = 22 ( int2vector PGNSP PGUID INDEX_MAX_KEYS*2 f b t \054 0 21 int2vectorin int2vectorout int2vectorrecv int2vectorsend - s p f 0 -1 0 _null_ _null_ ));
DESCR("array of INDEX_MAX_KEYS int2 integers, used in system tables");
DATA(insert OID = 22 ( int2vector PGNSP PGUID -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorrecv int2vectorsend - i p f 0 -1 0 _null_ _null_ ));
DESCR("array of int2, used in system tables");
#define INT2VECTOROID 22
DATA(insert OID = 23 ( int4 PGNSP PGUID 4 t b t \054 0 0 int4in int4out int4recv int4send - i p f 0 -1 0 _null_ _null_ ));
@ -300,8 +300,8 @@ DATA(insert OID = 29 ( cid PGNSP PGUID 4 t b t \054 0 0 cidin cidout cidrec
DESCR("command identifier type, sequence in transaction id");
#define CIDOID 29
DATA(insert OID = 30 ( oidvector PGNSP PGUID INDEX_MAX_KEYS*4 f b t \054 0 26 oidvectorin oidvectorout oidvectorrecv oidvectorsend - i p f 0 -1 0 _null_ _null_ ));
DESCR("array of INDEX_MAX_KEYS oids, used in system tables");
DATA(insert OID = 30 ( oidvector PGNSP PGUID -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorrecv oidvectorsend - i p f 0 -1 0 _null_ _null_ ));
DESCR("array of oids, used in system tables");
#define OIDVECTOROID 30
DATA(insert OID = 71 ( pg_type PGNSP PGUID -1 f c t \054 1247 0 record_in record_out record_recv record_send - d x f 0 -1 0 _null_ _null_ ));

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/array.h,v 1.53 2005/03/24 21:50:38 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/array.h,v 1.54 2005/03/29 00:17:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -22,6 +22,9 @@
/*
* Arrays are varlena objects, so must meet the varlena convention that
* the first int32 of the object contains the total object size in bytes.
*
* CAUTION: if you change the header for ordinary arrays you will also
* need to change the headers for oidvector and int2vector!
*/
typedef struct
{

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.253 2005/02/27 08:31:30 neilc Exp $
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.254 2005/03/29 00:17:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -185,6 +185,7 @@ extern Datum int2shl(PG_FUNCTION_ARGS);
extern Datum int2shr(PG_FUNCTION_ARGS);
extern Datum generate_series_int4(PG_FUNCTION_ARGS);
extern Datum generate_series_step_int4(PG_FUNCTION_ARGS);
extern int2vector *buildint2vector(const int2 *int2s, int n);
/* name.c */
extern Datum namein(PG_FUNCTION_ARGS);
@ -392,6 +393,7 @@ extern Datum oidvectorlt(PG_FUNCTION_ARGS);
extern Datum oidvectorle(PG_FUNCTION_ARGS);
extern Datum oidvectorge(PG_FUNCTION_ARGS);
extern Datum oidvectorgt(PG_FUNCTION_ARGS);
extern oidvector *buildoidvector(const Oid *oids, int n);
/* pseudotypes.c */
extern Datum cstring_in(PG_FUNCTION_ARGS);

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.94 2005/01/27 23:36:15 neilc Exp $
* $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.95 2005/03/29 00:17:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -64,7 +64,8 @@ extern RegProcedure get_oprrest(Oid opno);
extern RegProcedure get_oprjoin(Oid opno);
extern char *get_func_name(Oid funcid);
extern Oid get_func_rettype(Oid funcid);
extern Oid get_func_signature(Oid funcid, Oid *argtypes, int *nargs);
extern int get_func_nargs(Oid funcid);
extern Oid get_func_signature(Oid funcid, Oid **argtypes, int *nargs);
extern bool get_func_retset(Oid funcid);
extern bool func_strict(Oid funcid);
extern char func_volatile(Oid funcid);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.82 2005/01/10 20:02:24 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.83 2005/03/29 00:17:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -58,7 +58,8 @@ typedef struct Trigger
bool tgdeferrable;
bool tginitdeferred;
int16 tgnargs;
int16 tgattr[FUNC_MAX_ARGS];
int16 tgnattr;
int16 *tgattr;
char **tgargs;
} Trigger;
@ -137,6 +138,7 @@ typedef struct RelationData
Form_pg_index rd_index; /* pg_index tuple describing this index */
struct HeapTupleData *rd_indextuple; /* all of pg_index tuple */
/* "struct HeapTupleData *" avoids need to include htup.h here */
oidvector *rd_indclass; /* extracted pointer to rd_index field */
Form_pg_am rd_am; /* pg_am tuple for index's AM */
/*

View File

@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.58 2004/12/31 22:03:46 pgsql Exp $
* $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.59 2005/03/29 00:17:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -52,7 +52,7 @@
#define NAMESPACEOID 21
#define OPERNAMENSP 22
#define OPEROID 23
#define PROCNAMENSP 24
#define PROCNAMEARGSNSP 24
#define PROCOID 25
#define RELNAMENSP 26
#define RELOID 27

View File

@ -33,7 +33,7 @@
* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.69 2005/02/23 04:34:05 momjian Exp $
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.70 2005/03/29 00:17:20 tgl Exp $
*
**********************************************************************/
@ -1300,14 +1300,14 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
for (i = 0; i < prodesc->nargs; i++)
{
typeTup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(procStruct->proargtypes[i]),
ObjectIdGetDatum(procStruct->proargtypes.values[i]),
0, 0, 0);
if (!HeapTupleIsValid(typeTup))
{
free(prodesc->proname);
free(prodesc);
elog(ERROR, "cache lookup failed for type %u",
procStruct->proargtypes[i]);
procStruct->proargtypes.values[i]);
}
typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
@ -1319,7 +1319,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("plperl functions cannot take type %s",
format_type_be(procStruct->proargtypes[i]))));
format_type_be(procStruct->proargtypes.values[i]))));
}
if (typeStruct->typtype == 'c')

View File

@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.84 2005/02/22 07:18:24 neilc Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.85 2005/03/29 00:17:23 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@ -1843,7 +1843,7 @@ compute_function_hashkey(FunctionCallInfo fcinfo,
/* get the argument types */
for (i = 0; i < procStruct->pronargs; i++)
{
Oid argtypeid = procStruct->proargtypes[i];
Oid argtypeid = procStruct->proargtypes.values[i];
/*
* Check for polymorphic arguments. If found, use the actual

View File

@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.24 2005/02/22 07:18:24 neilc Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.25 2005/03/29 00:17:23 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@ -189,16 +189,16 @@ plpgsql_validator(PG_FUNCTION_ARGS)
haspolyarg = false;
for (i = 0; i < proc->pronargs; i++)
{
if (get_typtype(proc->proargtypes[i]) == 'p')
if (get_typtype(proc->proargtypes.values[i]) == 'p')
{
if (proc->proargtypes[i] == ANYARRAYOID ||
proc->proargtypes[i] == ANYELEMENTOID)
if (proc->proargtypes.values[i] == ANYARRAYOID ||
proc->proargtypes.values[i] == ANYELEMENTOID)
haspolyarg = true;
else
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("plpgsql functions cannot take type %s",
format_type_be(proc->proargtypes[i]))));
format_type_be(proc->proargtypes.values[i]))));
}
}

View File

@ -29,7 +29,7 @@
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.59 2005/03/24 17:22:34 tgl Exp $
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.60 2005/03/29 00:17:24 tgl Exp $
*
*********************************************************************
*/
@ -1082,11 +1082,11 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
Form_pg_type argTypeStruct;
argTypeTup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(procStruct->proargtypes[i]),
ObjectIdGetDatum(procStruct->proargtypes.values[i]),
0, 0, 0);
if (!HeapTupleIsValid(argTypeTup))
elog(ERROR, "cache lookup failed for type %u",
procStruct->proargtypes[i]);
procStruct->proargtypes.values[i]);
argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
/* Disallow pseudotype argument */
@ -1094,11 +1094,11 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("plpython functions cannot take type %s",
format_type_be(procStruct->proargtypes[i]))));
format_type_be(procStruct->proargtypes.values[i]))));
if (argTypeStruct->typtype != 'c')
PLy_input_datum_func(&(proc->args[i]),
procStruct->proargtypes[i],
procStruct->proargtypes.values[i],
argTypeTup);
else
proc->args[i].is_rowtype = 2; /* still need to set I/O

View File

@ -31,7 +31,7 @@
* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.94 2004/11/21 21:17:05 tgl Exp $
* $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.95 2005/03/29 00:17:25 tgl Exp $
*
**********************************************************************/
@ -1128,14 +1128,14 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid)
for (i = 0; i < prodesc->nargs; i++)
{
typeTup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(procStruct->proargtypes[i]),
ObjectIdGetDatum(procStruct->proargtypes.values[i]),
0, 0, 0);
if (!HeapTupleIsValid(typeTup))
{
free(prodesc->proname);
free(prodesc);
elog(ERROR, "cache lookup failed for type %u",
procStruct->proargtypes[i]);
procStruct->proargtypes.values[i]);
}
typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
@ -1147,7 +1147,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("pltcl functions cannot take type %s",
format_type_be(procStruct->proargtypes[i]))));
format_type_be(procStruct->proargtypes.values[i]))));
}
if (typeStruct->typtype == 'c')

View File

@ -33,23 +33,13 @@ create function physically_coercible(oid, oid) returns bool as
language sql;
-- **************** pg_proc ****************
-- Look for illegal values in pg_proc fields.
-- NOTE: in reality pronargs could be more than 10, but I'm too lazy to put
-- a larger number of proargtypes check clauses in here. If we ever have
-- more-than-10-arg functions in the standard catalogs, extend this query.
SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE p1.prolang = 0 OR p1.prorettype = 0 OR
p1.pronargs < 0 OR p1.pronargs > 10 OR
(p1.proargtypes[0] = 0 AND p1.pronargs > 0) OR
(p1.proargtypes[1] = 0 AND p1.pronargs > 1) OR
(p1.proargtypes[2] = 0 AND p1.pronargs > 2) OR
(p1.proargtypes[3] = 0 AND p1.pronargs > 3) OR
(p1.proargtypes[4] = 0 AND p1.pronargs > 4) OR
(p1.proargtypes[5] = 0 AND p1.pronargs > 5) OR
(p1.proargtypes[6] = 0 AND p1.pronargs > 6) OR
(p1.proargtypes[7] = 0 AND p1.pronargs > 7) OR
(p1.proargtypes[8] = 0 AND p1.pronargs > 8) OR
(p1.proargtypes[9] = 0 AND p1.pronargs > 9);
p1.pronargs < 0 OR
array_lower(p1.proargtypes, 1) != 0 OR
array_upper(p1.proargtypes, 1) != p1.pronargs-1 OR
0::oid = ANY (p1.proargtypes);
oid | proname
-----+---------
(0 rows)
@ -218,7 +208,7 @@ WHERE p1.oid != p2.oid AND
SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE p1.prorettype = 'internal'::regtype AND NOT
('(' || oidvectortypes(p1.proargtypes) || ')') ~ '[^a-z0-9_]internal[^a-z0-9_]';
'internal'::regtype = ANY (p1.proargtypes);
oid | proname
------+-------------
2304 | internal_in

View File

@ -106,14 +106,18 @@ ORDER BY 1;
(1 row)
-- Varlena array types will point to array_in
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.oid = 'array_in'::regproc);
oid | typname | oid | proname
-----+---------+-----+---------
(0 rows)
(p2.oid = 'array_in'::regproc)
ORDER BY 1;
oid | typname | oid | proname
-----+------------+-----+--------------
22 | int2vector | 40 | int2vectorin
30 | oidvector | 54 | oidvectorin
(2 rows)
-- Check for bogus typoutput routines
-- As of 8.0, this check finds refcursor, which is borrowing
@ -165,14 +169,18 @@ ORDER BY 1;
(1 row)
-- Varlena array types will point to array_recv
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.oid = 'array_recv'::regproc);
oid | typname | oid | proname
-----+---------+-----+---------
(0 rows)
(p2.oid = 'array_recv'::regproc)
ORDER BY 1;
oid | typname | oid | proname
-----+------------+------+----------------
22 | int2vector | 2410 | int2vectorrecv
30 | oidvector | 2420 | oidvectorrecv
(2 rows)
-- Check for bogus typsend routines
-- As of 7.4, this check finds refcursor, which is borrowing
@ -203,7 +211,7 @@ WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
-- Look for illegal values in pg_class fields
SELECT p1.oid, p1.relname
FROM pg_class as p1
WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 't', 'v');
WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 'c', 't', 'v');
oid | relname
-----+---------
(0 rows)

View File

@ -39,24 +39,14 @@ language sql;
-- **************** pg_proc ****************
-- Look for illegal values in pg_proc fields.
-- NOTE: in reality pronargs could be more than 10, but I'm too lazy to put
-- a larger number of proargtypes check clauses in here. If we ever have
-- more-than-10-arg functions in the standard catalogs, extend this query.
SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE p1.prolang = 0 OR p1.prorettype = 0 OR
p1.pronargs < 0 OR p1.pronargs > 10 OR
(p1.proargtypes[0] = 0 AND p1.pronargs > 0) OR
(p1.proargtypes[1] = 0 AND p1.pronargs > 1) OR
(p1.proargtypes[2] = 0 AND p1.pronargs > 2) OR
(p1.proargtypes[3] = 0 AND p1.pronargs > 3) OR
(p1.proargtypes[4] = 0 AND p1.pronargs > 4) OR
(p1.proargtypes[5] = 0 AND p1.pronargs > 5) OR
(p1.proargtypes[6] = 0 AND p1.pronargs > 6) OR
(p1.proargtypes[7] = 0 AND p1.pronargs > 7) OR
(p1.proargtypes[8] = 0 AND p1.pronargs > 8) OR
(p1.proargtypes[9] = 0 AND p1.pronargs > 9);
p1.pronargs < 0 OR
array_lower(p1.proargtypes, 1) != 0 OR
array_upper(p1.proargtypes, 1) != p1.pronargs-1 OR
0::oid = ANY (p1.proargtypes);
-- Look for conflicting proc definitions (same names and input datatypes).
-- (This test should be dead code now that we have the unique index
@ -179,7 +169,7 @@ WHERE p1.oid != p2.oid AND
SELECT p1.oid, p1.proname
FROM pg_proc as p1
WHERE p1.prorettype = 'internal'::regtype AND NOT
('(' || oidvectortypes(p1.proargtypes) || ')') ~ '[^a-z0-9_]internal[^a-z0-9_]';
'internal'::regtype = ANY (p1.proargtypes);
-- **************** pg_cast ****************

View File

@ -88,11 +88,13 @@ WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
ORDER BY 1;
-- Varlena array types will point to array_in
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.oid = 'array_in'::regproc);
(p2.oid = 'array_in'::regproc)
ORDER BY 1;
-- Check for bogus typoutput routines
@ -132,11 +134,13 @@ WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND NOT
ORDER BY 1;
-- Varlena array types will point to array_recv
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.oid = 'array_recv'::regproc);
(p2.oid = 'array_recv'::regproc)
ORDER BY 1;
-- Check for bogus typsend routines
@ -163,7 +167,7 @@ WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
SELECT p1.oid, p1.relname
FROM pg_class as p1
WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 't', 'v');
WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 'c', 't', 'v');
-- Indexes should have an access method, others not.