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:
parent
119191609c
commit
70c9763d48
@ -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 ");
|
||||
|
@ -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;
|
||||
|
@ -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> > 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.
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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..
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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? */
|
||||
|
@ -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);
|
||||
|
@ -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))));
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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")));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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++)
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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, ',');
|
||||
|
@ -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++;
|
||||
}
|
||||
|
31
src/backend/utils/cache/lsyscache.c
vendored
31
src/backend/utils/cache/lsyscache.c
vendored
@ -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;
|
||||
|
117
src/backend/utils/cache/relcache.c
vendored
117
src/backend/utils/cache/relcache.c
vendored
@ -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);
|
||||
|
12
src/backend/utils/cache/syscache.c
vendored
12
src/backend/utils/cache/syscache.c
vendored
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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_ ));
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|
@ -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]))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 ****************
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user