OSDN Git Service

Convert oidvector and int2vector into variable-length arrays. This
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 29 Mar 2005 00:17:27 +0000 (00:17 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 29 Mar 2005 00:17:27 +0000 (00:17 +0000)
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.

61 files changed:
contrib/dblink/dblink.c
contrib/dbmirror/pending.c
doc/src/sgml/catalogs.sgml
doc/src/sgml/trigger.sgml
src/backend/access/hash/hashfunc.c
src/backend/access/index/genam.c
src/backend/access/nbtree/nbtcompare.c
src/backend/access/nbtree/nbtsearch.c
src/backend/access/rtree/rtscan.c
src/backend/bootstrap/bootstrap.c
src/backend/catalog/genbki.sh
src/backend/catalog/index.c
src/backend/catalog/information_schema.sql
src/backend/catalog/namespace.c
src/backend/catalog/pg_proc.c
src/backend/commands/aggregatecmds.c
src/backend/commands/cluster.c
src/backend/commands/functioncmds.c
src/backend/commands/opclasscmds.c
src/backend/commands/tablecmds.c
src/backend/commands/trigger.c
src/backend/executor/execQual.c
src/backend/executor/functions.c
src/backend/executor/nodeAgg.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/plancat.c
src/backend/parser/parse_agg.c
src/backend/parser/parse_coerce.c
src/backend/tcop/fastpath.c
src/backend/utils/adt/arrayfuncs.c
src/backend/utils/adt/format_type.c
src/backend/utils/adt/int.c
src/backend/utils/adt/oid.c
src/backend/utils/adt/regproc.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/cache/relcache.c
src/backend/utils/cache/syscache.c
src/backend/utils/fmgr/fmgr.c
src/include/c.h
src/include/catalog/catversion.h
src/include/catalog/indexing.h
src/include/catalog/pg_attribute.h
src/include/catalog/pg_index.h
src/include/catalog/pg_proc.h
src/include/catalog/pg_trigger.h
src/include/catalog/pg_type.h
src/include/utils/array.h
src/include/utils/builtins.h
src/include/utils/lsyscache.h
src/include/utils/rel.h
src/include/utils/syscache.h
src/pl/plperl/plperl.c
src/pl/plpgsql/src/pl_comp.c
src/pl/plpgsql/src/pl_handler.c
src/pl/plpython/plpython.c
src/pl/tcl/pltcl.c
src/test/regress/expected/opr_sanity.out
src/test/regress/expected/type_sanity.out
src/test/regress/sql/opr_sanity.sql
src/test/regress/sql/type_sanity.sql

index 5de1514..75ce4c4 100644 (file)
@@ -74,13 +74,13 @@ static HTAB *createConnHash(void);
 static void createNewConnection(const char *name, remoteConn * con);
 static void deleteConnection(const char *name);
 static char **get_pkey_attnames(Oid relid, int16 *numatts);
-static char *get_sql_insert(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);
-static char *get_sql_delete(Oid relid, int16 *pkattnums, int16 pknumatts, char **tgt_pkattvals);
-static char *get_sql_update(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);
+static char *get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);
+static char *get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pkattvals);
+static char *get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);
 static char *quote_literal_cstr(char *rawstr);
 static char *quote_ident_cstr(char *rawstr);
-static int16 get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key);
-static HeapTuple get_tuple_of_interest(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals);
+static int16 get_attnum_pk_pos(int2vector *pkattnums, int16 pknumatts, int16 key);
+static HeapTuple get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals);
 static Oid     get_relid_from_relname(text *relname_text);
 static char *generate_relation_name(Oid relid);
 
@@ -1094,7 +1094,7 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
 {
        Oid                     relid;
        text       *relname_text;
-       int16      *pkattnums;
+       int2vector *pkattnums;
        int                     pknumatts_tmp;
        int16           pknumatts = 0;
        char      **src_pkattvals;
@@ -1126,7 +1126,7 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
                                 errmsg("relation \"%s\" does not exist",
                                                GET_STR(relname_text))));
 
-       pkattnums = (int16 *) PG_GETARG_POINTER(1);
+       pkattnums = (int2vector *) PG_GETARG_POINTER(1);
        pknumatts_tmp = PG_GETARG_INT32(2);
        if (pknumatts_tmp <= SHRT_MAX)
                pknumatts = pknumatts_tmp;
@@ -1246,7 +1246,7 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
 {
        Oid                     relid;
        text       *relname_text;
-       int16      *pkattnums;
+       int2vector *pkattnums;
        int                     pknumatts_tmp;
        int16           pknumatts = 0;
        char      **tgt_pkattvals;
@@ -1273,7 +1273,7 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
                                 errmsg("relation \"%s\" does not exist",
                                                GET_STR(relname_text))));
 
-       pkattnums = (int16 *) PG_GETARG_POINTER(1);
+       pkattnums = (int2vector *) PG_GETARG_POINTER(1);
        pknumatts_tmp = PG_GETARG_INT32(2);
        if (pknumatts_tmp <= SHRT_MAX)
                pknumatts = pknumatts_tmp;
@@ -1363,7 +1363,7 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
 {
        Oid                     relid;
        text       *relname_text;
-       int16      *pkattnums;
+       int2vector *pkattnums;
        int                     pknumatts_tmp;
        int16           pknumatts = 0;
        char      **src_pkattvals;
@@ -1395,7 +1395,7 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
                                 errmsg("relation \"%s\" does not exist",
                                                GET_STR(relname_text))));
 
-       pkattnums = (int16 *) PG_GETARG_POINTER(1);
+       pkattnums = (int2vector *) PG_GETARG_POINTER(1);
        pknumatts_tmp = PG_GETARG_INT32(2);
        if (pknumatts_tmp <= SHRT_MAX)
                pknumatts = pknumatts_tmp;
@@ -1552,16 +1552,13 @@ get_pkey_attnames(Oid relid, int16 *numatts)
                /* we're only interested if it is the primary key */
                if (index->indisprimary == TRUE)
                {
-                       i = 0;
-                       while (index->indkey[i++] != 0)
-                               (*numatts)++;
-
+                       *numatts = index->indnatts;
                        if (*numatts > 0)
                        {
                                result = (char **) palloc(*numatts * sizeof(char *));
 
                                for (i = 0; i < *numatts; i++)
-                                       result[i] = SPI_fname(tupdesc, index->indkey[i]);
+                                       result[i] = SPI_fname(tupdesc, index->indkey.values[i]);
                        }
                        break;
                }
@@ -1574,7 +1571,7 @@ get_pkey_attnames(Oid relid, int16 *numatts)
 }
 
 static char *
-get_sql_insert(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
+get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
 {
        Relation        rel;
        char       *relname;
@@ -1664,7 +1661,7 @@ get_sql_insert(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattval
 }
 
 static char *
-get_sql_delete(Oid relid, int16 *pkattnums, int16 pknumatts, char **tgt_pkattvals)
+get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pkattvals)
 {
        Relation        rel;
        char       *relname;
@@ -1688,7 +1685,7 @@ get_sql_delete(Oid relid, int16 *pkattnums, int16 pknumatts, char **tgt_pkattval
        appendStringInfo(str, "DELETE FROM %s WHERE ", relname);
        for (i = 0; i < pknumatts; i++)
        {
-               int16           pkattnum = pkattnums[i];
+               int16           pkattnum = pkattnums->values[i];
 
                if (i > 0)
                        appendStringInfo(str, " AND ");
@@ -1720,7 +1717,7 @@ get_sql_delete(Oid relid, int16 *pkattnums, int16 pknumatts, char **tgt_pkattval
 }
 
 static char *
-get_sql_update(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
+get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
 {
        Relation        rel;
        char       *relname;
@@ -1788,7 +1785,7 @@ get_sql_update(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattval
 
        for (i = 0; i < pknumatts; i++)
        {
-               int16           pkattnum = pkattnums[i];
+               int16           pkattnum = pkattnums->values[i];
 
                if (i > 0)
                        appendStringInfo(str, " AND ");
@@ -1855,7 +1852,7 @@ quote_ident_cstr(char *rawstr)
 }
 
 static int16
-get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key)
+get_attnum_pk_pos(int2vector *pkattnums, int16 pknumatts, int16 key)
 {
        int                     i;
 
@@ -1863,14 +1860,14 @@ get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key)
         * Not likely a long list anyway, so just scan for the value
         */
        for (i = 0; i < pknumatts; i++)
-               if (key == pkattnums[i])
+               if (key == pkattnums->values[i])
                        return i;
 
        return -1;
 }
 
 static HeapTuple
-get_tuple_of_interest(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals)
+get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pkattvals)
 {
        Relation        rel;
        char       *relname;
@@ -1907,7 +1904,7 @@ get_tuple_of_interest(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_p
 
        for (i = 0; i < pknumatts; i++)
        {
-               int16           pkattnum = pkattnums[i];
+               int16           pkattnum = pkattnums->values[i];
 
                if (i > 0)
                        appendStringInfo(str, " AND ");
index 48e91ac..3ed9d21 100644 (file)
@@ -1,7 +1,7 @@
 /****************************************************************************
  * pending.c
- * $Id: pending.c,v 1.20 2004/09/10 04:31:06 neilc Exp $
- * $PostgreSQL: pgsql/contrib/dbmirror/pending.c,v 1.20 2004/09/10 04:31:06 neilc Exp $
+ * $Id: pending.c,v 1.21 2005/03/29 00:16:48 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/dbmirror/pending.c,v 1.21 2005/03/29 00:16:48 tgl Exp $
  *
  * This file contains a trigger for Postgresql-7.x to record changes to tables
  * to a pending table for mirroring.
@@ -349,8 +349,8 @@ getPrimaryKey(Oid tblOid)
        resDatum = SPI_getbinval(resTuple, SPI_tuptable->tupdesc, 1, &isNull);
 
        tpResultKey = (int2vector *) DatumGetPointer(resDatum);
-       resultKey = SPI_palloc(sizeof(int2vector));
-       memcpy(resultKey, tpResultKey, sizeof(int2vector));
+       resultKey = SPI_palloc(VARSIZE(tpResultKey));
+       memcpy(resultKey, tpResultKey, VARSIZE(tpResultKey));
 
        return resultKey;
 }
@@ -438,11 +438,8 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc, Oid tableOid,
        }
 
        if (tpPKeys != NULL)
-       {
                debug_msg("dbmirror:packageData have primary keys");
 
-       }
-
        cpDataBlock = SPI_palloc(BUFFER_SIZE);
        iDataBlockSize = BUFFER_SIZE;
        iUsedDataBlock = 0;                     /* To account for the null */
@@ -462,11 +459,10 @@ packageData(HeapTuple tTupleData, TupleDesc tTupleDesc, Oid tableOid,
                        /* Determine if this is a primary key or not. */
                        iIsPrimaryKey = 0;
                        for (iPrimaryKeyIndex = 0;
-                                (*tpPKeys)[iPrimaryKeyIndex] != 0;
+                                iPrimaryKeyIndex < tpPKeys->dim1;
                                 iPrimaryKeyIndex++)
                        {
-                               if ((*tpPKeys)[iPrimaryKeyIndex]
-                                       == iColumnCounter)
+                               if (tpPKeys->values[iPrimaryKeyIndex] == iColumnCounter)
                                {
                                        iIsPrimaryKey = 1;
                                        break;
index 2dc8b30..946dd53 100644 (file)
@@ -1,6 +1,6 @@
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.97 2005/03/27 23:52:51 tgl Exp $
+ $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.98 2005/03/29 00:16:49 tgl Exp $
  -->
 
 <chapter id="catalogs">
      </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>
       <entry></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>
       <entry></entry>
        (<structfield>typlen</structfield> = -1),
        but some fixed-length (<structfield>typlen</structfield> &gt; 0) types
        also have nonzero <structfield>typelem</structfield>, for example
-       <type>name</type> and <type>oidvector</type>.
+       <type>name</type> and <type>point</type>.
        If a fixed-length type has a <structfield>typelem</structfield> then
        its internal representation must be some number of values of the
        <structfield>typelem</structfield> data type with no other data.
index 5960ff9..e6c8271 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/trigger.sgml,v 1.41 2005/01/22 22:56:36 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/trigger.sgml,v 1.42 2005/03/29 00:16:49 tgl Exp $
 -->
 
  <chapter id="triggers">
@@ -453,7 +453,8 @@ typedef struct Trigger
     bool        tgdeferrable;
     bool        tginitdeferred;
     int16       tgnargs;
-    int16       tgattr[FUNC_MAX_ARGS];
+    int16       tgnattr;
+    int16      *tgattr;
     char      **tgargs;
 } Trigger;
 </programlisting>
index 549dc32..46033b1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/hash/hashfunc.c,v 1.42 2004/12/31 21:59:13 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/hash/hashfunc.c,v 1.43 2005/03/29 00:16:50 tgl Exp $
  *
  * NOTES
  *       These functions are stored in pg_amproc.      For each operator class
@@ -107,17 +107,17 @@ hashfloat8(PG_FUNCTION_ARGS)
 Datum
 hashoidvector(PG_FUNCTION_ARGS)
 {
-       Oid                *key = (Oid *) PG_GETARG_POINTER(0);
+       oidvector  *key = (oidvector *) PG_GETARG_POINTER(0);
 
-       return hash_any((unsigned char *) key, INDEX_MAX_KEYS * sizeof(Oid));
+       return hash_any((unsigned char *) key->values, key->dim1 * sizeof(Oid));
 }
 
 Datum
 hashint2vector(PG_FUNCTION_ARGS)
 {
-       int16      *key = (int16 *) PG_GETARG_POINTER(0);
+       int2vector *key = (int2vector *) PG_GETARG_POINTER(0);
 
-       return hash_any((unsigned char *) key, INDEX_MAX_KEYS * sizeof(int16));
+       return hash_any((unsigned char *) key->values, key->dim1 * sizeof(int2));
 }
 
 Datum
index ceded59..74f5bb7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.45 2005/03/27 23:52:59 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.46 2005/03/29 00:16:51 tgl Exp $
  *
  * NOTES
  *       many of the old access method routines have been turned into
@@ -219,7 +219,7 @@ systable_beginscan(Relation heapRelation,
                 */
                for (i = 0; i < nkeys; i++)
                {
-                       Assert(key[i].sk_attno == irel->rd_index->indkey[i]);
+                       Assert(key[i].sk_attno == irel->rd_index->indkey.values[i]);
                        key[i].sk_attno = i + 1;
                }
 
index aa0f75e..a5c3fb5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.50 2004/12/31 21:59:22 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.51 2005/03/29 00:16:52 tgl Exp $
  *
  * NOTES
  *
@@ -198,15 +198,19 @@ btoidcmp(PG_FUNCTION_ARGS)
 Datum
 btoidvectorcmp(PG_FUNCTION_ARGS)
 {
-       Oid                *a = (Oid *) PG_GETARG_POINTER(0);
-       Oid                *b = (Oid *) PG_GETARG_POINTER(1);
+       oidvector  *a = (oidvector *) PG_GETARG_POINTER(0);
+       oidvector  *b = (oidvector *) PG_GETARG_POINTER(1);
        int                     i;
 
-       for (i = 0; i < INDEX_MAX_KEYS; i++)
+       /* We arbitrarily choose to sort first by vector length */
+       if (a->dim1 != b->dim1)
+               PG_RETURN_INT32(a->dim1 - b->dim1);
+
+       for (i = 0; i < a->dim1; i++)
        {
-               if (a[i] != b[i])
+               if (a->values[i] != b->values[i])
                {
-                       if (a[i] > b[i])
+                       if (a->values[i] > b->values[i])
                                PG_RETURN_INT32(1);
                        else
                                PG_RETURN_INT32(-1);
index df07134..17b3b0d 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.90 2004/12/31 21:59:22 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.91 2005/03/29 00:16:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -684,7 +684,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
                {
                        RegProcedure cmp_proc;
 
-                       cmp_proc = get_opclass_proc(rel->rd_index->indclass[i],
+                       cmp_proc = get_opclass_proc(rel->rd_indclass->values[i],
                                                                                cur->sk_subtype,
                                                                                BTORDER_PROC);
                        ScanKeyEntryInitialize(scankeys + i,
index e608cb4..f6656a2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/rtree/rtscan.c,v 1.57 2005/01/18 23:25:48 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/rtree/rtscan.c,v 1.58 2005/03/29 00:16:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -135,7 +135,7 @@ rtrescan(PG_FUNCTION_ARGS)
                        Oid                     int_oper;
                        RegProcedure int_proc;
 
-                       opclass = s->indexRelation->rd_index->indclass[attno - 1];
+                       opclass = s->indexRelation->rd_indclass->values[attno - 1];
                        int_strategy = RTMapToInternalOperator(s->keyData[i].sk_strategy);
                        int_oper = get_opclass_member(opclass,
                                                                                  s->keyData[i].sk_subtype,
index 279ceba..05d73e2 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.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)
index a961002..fdb4b6b 100644 (file)
@@ -10,7 +10,7 @@
 #
 #
 # IDENTIFICATION
-#    $PostgreSQL: pgsql/src/backend/catalog/genbki.sh,v 1.32 2004/01/04 05:57:21 tgl Exp $
+#    $PostgreSQL: pgsql/src/backend/catalog/genbki.sh,v 1.33 2005/03/29 00:16:55 tgl Exp $
 #
 # NOTES
 #    non-essential whitespace is removed from the generated file.
@@ -113,15 +113,6 @@ for dir in $INCLUDE_DIRS; do
     fi
 done
 
-# Get INDEX_MAX_KEYS from pg_config_manual.h
-# (who needs consistency?)
-for dir in $INCLUDE_DIRS; do
-    if [ -f "$dir/pg_config_manual.h" ]; then
-        INDEXMAXKEYS=`grep '^#define[  ]*INDEX_MAX_KEYS' $dir/pg_config_manual.h | $AWK '{ print $3 }'`
-        break
-    fi
-done
-
 # Get PG_CATALOG_NAMESPACE from catalog/pg_namespace.h
 for dir in $INCLUDE_DIRS; do
     if [ -f "$dir/catalog/pg_namespace.h" ]; then
@@ -139,14 +130,6 @@ for dir in $INCLUDE_DIRS; do
 done
 export BKIOBJECTID
 
-# NOTE: we assume here that FUNC_MAX_ARGS has the same value as
-# INDEX_MAX_KEYS, and don't read it separately from
-# pg_config_manual.h.  This is OK because both of them must be equal
-# to the length of oidvector.
-
-INDEXMAXKEYS2=`expr $INDEXMAXKEYS '*' 2` || exit
-INDEXMAXKEYS4=`expr $INDEXMAXKEYS '*' 4` || exit
-
 touch ${OUTPUT_PREFIX}.description.$$
 
 # ----------------
@@ -181,12 +164,6 @@ sed -e "s/;[       ]*$//g" \
     -e "s/PGUID/1/g" \
     -e "s/NAMEDATALEN/$NAMEDATALEN/g" \
     -e "s/PGNSP/$PG_CATALOG_NAMESPACE/g" \
-    -e "s/INDEX_MAX_KEYS\*2/$INDEXMAXKEYS2/g" \
-    -e "s/INDEX_MAX_KEYS\*4/$INDEXMAXKEYS4/g" \
-    -e "s/INDEX_MAX_KEYS/$INDEXMAXKEYS/g" \
-    -e "s/FUNC_MAX_ARGS\*2/$INDEXMAXKEYS2/g" \
-    -e "s/FUNC_MAX_ARGS\*4/$INDEXMAXKEYS4/g" \
-    -e "s/FUNC_MAX_ARGS/$INDEXMAXKEYS/g" \
 | $AWK '
 # ----------------
 #      now use awk to process remaining .h file..
index 2f6eb1b..ebe303e 100644 (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);
index d4e8a52..c9202b5 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Copyright (c) 2003-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.26 2005/01/01 20:44:14 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.27 2005/03/29 00:16:56 tgl Exp $
  */
 
 /*
@@ -30,13 +30,22 @@ SET search_path TO information_schema, public;
  * A few supporting functions first ...
  */
 
-/* This returns the integers from 1 to INDEX_MAX_KEYS/FUNC_MAX_ARGS */
-CREATE FUNCTION _pg_keypositions() RETURNS SETOF integer
-    LANGUAGE sql
-    IMMUTABLE
-    AS 'select g.s
-        from generate_series(1,current_setting(''max_index_keys'')::int,1)
-        as g(s)';
+/* Expand an oidvector or smallint[] into a set with integers 1..N */
+CREATE TYPE _pg_expandoidvector_type AS (o oid, n int);
+
+CREATE FUNCTION _pg_expandoidvector(oidvector)
+    RETURNS SETOF _pg_expandoidvector_type
+    LANGUAGE sql STRICT IMMUTABLE
+    AS 'select $1[s], s+1
+        from generate_series(0,array_upper($1,1),1) as g(s)';
+
+CREATE TYPE _pg_expandsmallint_type AS (i smallint, n int);
+
+CREATE FUNCTION _pg_expandsmallint(smallint[])
+    RETURNS SETOF _pg_expandsmallint_type
+    LANGUAGE sql STRICT IMMUTABLE
+    AS 'select $1[s], s
+        from generate_series(1,array_upper($1,1),1) as g(s)';
 
 CREATE FUNCTION _pg_keyissubset(smallint[], smallint[]) RETURNS boolean
     LANGUAGE sql
@@ -501,12 +510,12 @@ CREATE VIEW constraint_column_usage AS
         /* unique/primary key/foreign key constraints */
         SELECT nr.nspname, r.relname, r.relowner, a.attname, nc.nspname, c.conname
           FROM pg_namespace nr, pg_class r, pg_attribute a, pg_namespace nc,
-               pg_constraint c, _pg_keypositions() AS pos(n)
+               pg_constraint c
           WHERE nr.oid = r.relnamespace
             AND r.oid = a.attrelid
             AND nc.oid = c.connamespace
-            AND (CASE WHEN c.contype = 'f' THEN r.oid = c.confrelid AND c.confkey[pos.n] = a.attnum
-                      ELSE r.oid = c.conrelid AND c.conkey[pos.n] = a.attnum END)
+            AND (CASE WHEN c.contype = 'f' THEN r.oid = c.confrelid AND a.attnum = ANY (c.confkey)
+                      ELSE r.oid = c.conrelid AND a.attnum = ANY (c.conkey) END)
             AND NOT a.attisdropped
             AND c.contype IN ('p', 'u', 'f')
             AND r.relkind = 'r'
@@ -707,26 +716,30 @@ GRANT SELECT ON enabled_roles TO PUBLIC;
 
 CREATE VIEW key_column_usage AS
     SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog,
-           CAST(nc.nspname AS sql_identifier) AS constraint_schema,
-           CAST(c.conname AS sql_identifier) AS constraint_name,
+           CAST(nc_nspname AS sql_identifier) AS constraint_schema,
+           CAST(conname AS sql_identifier) AS constraint_name,
            CAST(current_database() AS sql_identifier) AS table_catalog,
-           CAST(nr.nspname AS sql_identifier) AS table_schema,
-           CAST(r.relname AS sql_identifier) AS table_name,
+           CAST(nr_nspname AS sql_identifier) AS table_schema,
+           CAST(relname AS sql_identifier) AS table_name,
            CAST(a.attname AS sql_identifier) AS column_name,
-           CAST(pos.n AS cardinal_number) AS ordinal_position
-
-    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;
+           CAST((ss.x).n AS cardinal_number) AS ordinal_position
+
+    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
-
-    FROM pg_namespace n, pg_proc p, pg_type t, pg_namespace nt, pg_user u,
-         _pg_keypositions() AS pos(n)
+           CAST((ss.x).n AS sql_identifier) AS dtd_identifier
 
-    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
 
index e7960b3..ac47d23 100644 (file)
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.73 2004/12/31 21:59:38 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.74 2005/03/29 00:16:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -471,25 +471,22 @@ FuncnameGetCandidates(List *names, int nargs)
                recomputeNamespacePath();
        }
 
-       /* Search syscache by name and (optionally) nargs only */
-       if (nargs >= 0)
-               catlist = SearchSysCacheList(PROCNAMENSP, 2,
-                                                                        CStringGetDatum(funcname),
-                                                                        Int16GetDatum(nargs),
-                                                                        0, 0);
-       else
-               catlist = SearchSysCacheList(PROCNAMENSP, 1,
-                                                                        CStringGetDatum(funcname),
-                                                                        0, 0, 0);
+       /* Search syscache by name only */
+       catlist = SearchSysCacheList(PROCNAMEARGSNSP, 1,
+                                                                CStringGetDatum(funcname),
+                                                                0, 0, 0);
 
        for (i = 0; i < catlist->n_members; i++)
        {
                HeapTuple       proctup = &catlist->members[i]->tuple;
                Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
+               int                     pronargs = procform->pronargs;
                int                     pathpos = 0;
                FuncCandidateList newResult;
 
-               nargs = procform->pronargs;
+               /* Ignore if it doesn't match requested argument count */
+               if (nargs >= 0 && pronargs != nargs)
+                       continue;
 
                if (OidIsValid(namespaceId))
                {
@@ -529,9 +526,10 @@ FuncnameGetCandidates(List *names, int nargs)
 
                                if (catlist->ordered)
                                {
-                                       if (nargs == resultList->nargs &&
-                                               memcmp(procform->proargtypes, resultList->args,
-                                                          nargs * sizeof(Oid)) == 0)
+                                       if (pronargs == resultList->nargs &&
+                                               memcmp(procform->proargtypes.values,
+                                                          resultList->args,
+                                                          pronargs * sizeof(Oid)) == 0)
                                                prevResult = resultList;
                                        else
                                                prevResult = NULL;
@@ -542,9 +540,10 @@ FuncnameGetCandidates(List *names, int nargs)
                                                 prevResult;
                                                 prevResult = prevResult->next)
                                        {
-                                               if (nargs == prevResult->nargs &&
-                                                 memcmp(procform->proargtypes, prevResult->args,
-                                                                nargs * sizeof(Oid)) == 0)
+                                               if (pronargs == prevResult->nargs &&
+                                                 memcmp(procform->proargtypes.values,
+                                                                prevResult->args,
+                                                                pronargs * sizeof(Oid)) == 0)
                                                        break;
                                        }
                                }
@@ -567,11 +566,12 @@ FuncnameGetCandidates(List *names, int nargs)
                 */
                newResult = (FuncCandidateList)
                        palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
-                                  + nargs * sizeof(Oid));
+                                  + pronargs * sizeof(Oid));
                newResult->pathpos = pathpos;
                newResult->oid = HeapTupleGetOid(proctup);
-               newResult->nargs = nargs;
-               memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid));
+               newResult->nargs = pronargs;
+               memcpy(newResult->args, procform->proargtypes.values,
+                          pronargs * sizeof(Oid));
 
                newResult->next = resultList;
                resultList = newResult;
@@ -632,7 +632,7 @@ FunctionIsVisible(Oid funcid)
 
                for (; clist; clist = clist->next)
                {
-                       if (memcmp(clist->args, procform->proargtypes,
+                       if (memcmp(clist->args, procform->proargtypes.values,
                                           nargs * sizeof(Oid)) == 0)
                        {
                                /* Found the expected entry; is it the right proc? */
index 01c67c2..2042d67 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.123 2005/01/27 23:23:51 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.124 2005/03/29 00:16:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -78,7 +78,7 @@ ProcedureCreate(const char *procedureName,
        char            nulls[Natts_pg_proc];
        Datum           values[Natts_pg_proc];
        char            replaces[Natts_pg_proc];
-       Oid                     typev[FUNC_MAX_ARGS];
+       oidvector  *proargtypes;
        Datum           namesarray;
        Oid                     relid;
        NameData        procname;
@@ -125,10 +125,9 @@ ProcedureCreate(const char *procedureName,
                                         errdetail("A function returning \"anyarray\" or \"anyelement\" must have at least one argument of either type.")));
        }
 
-       /* Make sure we have a zero-padded param type array */
-       MemSet(typev, 0, FUNC_MAX_ARGS * sizeof(Oid));
-       if (parameterCount > 0)
-               memcpy(typev, parameterTypes, parameterCount * sizeof(Oid));
+       /* Convert param types to oidvector */
+       /* (Probably we should make caller pass it this way to start with) */
+       proargtypes = buildoidvector(parameterTypes, parameterCount);
 
        /* Process param names, if given */
        namesarray = create_parameternames_array(parameterCount, parameterNames);
@@ -137,13 +136,13 @@ ProcedureCreate(const char *procedureName,
         * don't allow functions of complex types that have the same name as
         * existing attributes of the type
         */
-       if (parameterCount == 1 && OidIsValid(typev[0]) &&
-               (relid = typeidTypeRelid(typev[0])) != InvalidOid &&
+       if (parameterCount == 1 && OidIsValid(parameterTypes[0]) &&
+               (relid = typeidTypeRelid(parameterTypes[0])) != InvalidOid &&
                get_attnum(relid, procedureName) != InvalidAttrNumber)
                ereport(ERROR,
                                (errcode(ERRCODE_DUPLICATE_COLUMN),
                                 errmsg("\"%s\" is already an attribute of type %s",
-                                               procedureName, format_type_be(typev[0]))));
+                                               procedureName, format_type_be(parameterTypes[0]))));
 
        /*
         * All seems OK; prepare the data to be inserted into pg_proc.
@@ -162,15 +161,15 @@ ProcedureCreate(const char *procedureName,
        values[i++] = ObjectIdGetDatum(procNamespace);          /* pronamespace */
        values[i++] = Int32GetDatum(GetUserId());       /* proowner */
        values[i++] = ObjectIdGetDatum(languageObjectId);       /* prolang */
-       values[i++] = BoolGetDatum(isAgg);      /* proisagg */
+       values[i++] = BoolGetDatum(isAgg);                      /* proisagg */
        values[i++] = BoolGetDatum(security_definer);           /* prosecdef */
        values[i++] = BoolGetDatum(isStrict);           /* proisstrict */
        values[i++] = BoolGetDatum(returnsSet);         /* proretset */
        values[i++] = CharGetDatum(volatility);         /* provolatile */
        values[i++] = UInt16GetDatum(parameterCount);           /* pronargs */
        values[i++] = ObjectIdGetDatum(returnType); /* prorettype */
-       values[i++] = PointerGetDatum(typev);           /* proargtypes */
-       values[i++] = namesarray;       /* proargnames */
+       values[i++] = PointerGetDatum(proargtypes);     /* proargtypes */
+       values[i++] = namesarray;                                       /* proargnames */
        if (namesarray == PointerGetDatum(NULL))
                nulls[Anum_pg_proc_proargnames - 1] = 'n';
        values[i++] = DirectFunctionCall1(textin,       /* prosrc */
@@ -183,11 +182,11 @@ ProcedureCreate(const char *procedureName,
        tupDesc = RelationGetDescr(rel);
 
        /* Check for pre-existing definition */
-       oldtup = SearchSysCache(PROCNAMENSP,
+       oldtup = SearchSysCache(PROCNAMEARGSNSP,
                                                        PointerGetDatum(procedureName),
-                                                       UInt16GetDatum(parameterCount),
-                                                       PointerGetDatum(typev),
-                                                       ObjectIdGetDatum(procNamespace));
+                                                       PointerGetDatum(proargtypes),
+                                                       ObjectIdGetDatum(procNamespace),
+                                                       0);
 
        if (HeapTupleIsValid(oldtup))
        {
@@ -290,7 +289,7 @@ ProcedureCreate(const char *procedureName,
        for (i = 0; i < parameterCount; i++)
        {
                referenced.classId = RelOid_pg_type;
-               referenced.objectId = typev[i];
+               referenced.objectId = parameterTypes[i];
                referenced.objectSubId = 0;
                recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
        }
@@ -492,16 +491,16 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
        haspolyarg = false;
        for (i = 0; i < proc->pronargs; i++)
        {
-               if (get_typtype(proc->proargtypes[i]) == 'p')
+               if (get_typtype(proc->proargtypes.values[i]) == 'p')
                {
-                       if (proc->proargtypes[i] == ANYARRAYOID ||
-                               proc->proargtypes[i] == ANYELEMENTOID)
+                       if (proc->proargtypes.values[i] == ANYARRAYOID ||
+                               proc->proargtypes.values[i] == ANYELEMENTOID)
                                haspolyarg = true;
                        else
                                ereport(ERROR,
                                                (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                 errmsg("SQL functions cannot have arguments of type %s",
-                                               format_type_be(proc->proargtypes[i]))));
+                                               format_type_be(proc->proargtypes.values[i]))));
                }
        }
 
@@ -534,7 +533,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
                if (!haspolyarg)
                {
                        querytree_list = pg_parse_and_rewrite(prosrc,
-                                                                                                 proc->proargtypes,
+                                                                                                 proc->proargtypes.values,
                                                                                                  proc->pronargs);
                        (void) check_sql_fn_retval(proc->prorettype, functyptype,
                                                                           querytree_list, NULL);
index ea2a36f..7d4cbe3 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.22 2004/12/31 21:59:41 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.23 2005/03/29 00:16:57 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -246,11 +246,11 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
        namespaceOid = procForm->pronamespace;
 
        /* make sure the new name doesn't exist */
-       if (SearchSysCacheExists(PROCNAMENSP,
+       if (SearchSysCacheExists(PROCNAMEARGSNSP,
                                                         CStringGetDatum(newname),
-                                                        Int16GetDatum(procForm->pronargs),
-                                                        PointerGetDatum(procForm->proargtypes),
-                                                        ObjectIdGetDatum(namespaceOid)))
+                                                        PointerGetDatum(&procForm->proargtypes),
+                                                        ObjectIdGetDatum(namespaceOid),
+                                                        0))
        {
                if (basetypeOid == ANYOID)
                        ereport(ERROR,
@@ -264,7 +264,7 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
                                         errmsg("function %s already exists in schema \"%s\"",
                                                        funcname_signature_string(newname,
                                                                                                          procForm->pronargs,
-                                                                                                 procForm->proargtypes),
+                                                                                                 procForm->proargtypes.values),
                                                        get_namespace_name(namespaceOid))));
        }
 
index e9f364f..e29750c 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.133 2005/03/20 22:00:52 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.134 2005/03/29 00:16:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -347,7 +347,7 @@ check_index_is_clusterable(Relation OldHeap, Oid indexOid)
                 * at the first column; multicolumn-capable AMs are *required* to
                 * index nulls in columns after the first.
                 */
-               colno = OldIndex->rd_index->indkey[0];
+               colno = OldIndex->rd_index->indkey.values[0];
                if (colno > 0)
                {
                        /* ordinary user attribute */
index cbe14d1..069adf4 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.56 2005/03/14 00:19:36 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.57 2005/03/29 00:16:57 tgl Exp $
  *
  * DESCRIPTION
  *       These routines take the parse tree and pick out the
@@ -716,18 +716,18 @@ RenameFunction(List *name, List *argtypes, const char *newname)
        namespaceOid = procForm->pronamespace;
 
        /* make sure the new name doesn't exist */
-       if (SearchSysCacheExists(PROCNAMENSP,
+       if (SearchSysCacheExists(PROCNAMEARGSNSP,
                                                         CStringGetDatum(newname),
-                                                        Int16GetDatum(procForm->pronargs),
-                                                        PointerGetDatum(procForm->proargtypes),
-                                                        ObjectIdGetDatum(namespaceOid)))
+                                                        PointerGetDatum(&procForm->proargtypes),
+                                                        ObjectIdGetDatum(namespaceOid),
+                                                        0))
        {
                ereport(ERROR,
                                (errcode(ERRCODE_DUPLICATE_FUNCTION),
                                 errmsg("function %s already exists in schema \"%s\"",
                                                funcname_signature_string(newname,
                                                                                                  procForm->pronargs,
-                                                                                                 procForm->proargtypes),
+                                                                                                 procForm->proargtypes.values),
                                                get_namespace_name(namespaceOid))));
        }
 
@@ -962,11 +962,11 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
        procForm = (Form_pg_proc) GETSTRUCT(tup);
 
        if (argIndex < 0 || argIndex >= procForm->pronargs ||
-               procForm->proargtypes[argIndex] != OPAQUEOID)
+               procForm->proargtypes.values[argIndex] != OPAQUEOID)
                elog(ERROR, "function %u doesn't take OPAQUE", funcOid);
 
        /* okay to overwrite copied tuple */
-       procForm->proargtypes[argIndex] = newArgType;
+       procForm->proargtypes.values[argIndex] = newArgType;
 
        /* update the catalog and its indexes */
        simple_heap_update(pg_proc_rel, &tup->t_self, tup);
@@ -1064,15 +1064,15 @@ CreateCast(CreateCastStmt *stmt)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                          errmsg("cast function must take one to three arguments")));
-               if (procstruct->proargtypes[0] != sourcetypeid)
+               if (procstruct->proargtypes.values[0] != sourcetypeid)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                         errmsg("argument of cast function must match source data type")));
-               if (nargs > 1 && procstruct->proargtypes[1] != INT4OID)
+               if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                         errmsg("second argument of cast function must be type integer")));
-               if (nargs > 2 && procstruct->proargtypes[2] != BOOLOID)
+               if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                         errmsg("third argument of cast function must be type boolean")));
index 4778b95..9af0ae1 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.29 2004/12/31 21:59:41 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.30 2005/03/29 00:16:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -486,7 +486,7 @@ assignProcSubtype(Oid amoid, Oid typeoid, Oid procOid)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                 errmsg("btree procedures must return integer")));
-       if (procform->proargtypes[0] != typeoid)
+       if (procform->proargtypes.values[0] != typeoid)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                errmsg("btree procedures must have index type as first input")));
@@ -495,10 +495,10 @@ assignProcSubtype(Oid amoid, Oid typeoid, Oid procOid)
         * The subtype is "default" (0) if second input type matches the
         * operator class, otherwise it is the second input type.
         */
-       if (procform->proargtypes[1] == typeoid)
+       if (procform->proargtypes.values[1] == typeoid)
                subtype = InvalidOid;
        else
-               subtype = procform->proargtypes[1];
+               subtype = procform->proargtypes.values[1];
        ReleaseSysCache(proctup);
        return subtype;
 }
index b441b09..21655e7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.151 2005/03/25 18:04:34 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.152 2005/03/29 00:16:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1419,7 +1419,7 @@ renameatt(Oid myrelid,
 
                for (i = 0; i < indexform->indnatts; i++)
                {
-                       if (attnum != indexform->indkey[i])
+                       if (attnum != indexform->indkey.values[i])
                                continue;
 
                        /*
@@ -1676,9 +1676,10 @@ update_ri_trigger_args(Oid relid,
                 * line; so does trigger.c ...
                 */
                tgnargs = pg_trigger->tgnargs;
-               val = (bytea *) fastgetattr(tuple,
-                                                                       Anum_pg_trigger_tgargs,
-                                                                       tgrel->rd_att, &isnull);
+               val = (bytea *)
+                       DatumGetPointer(fastgetattr(tuple,
+                                                                               Anum_pg_trigger_tgargs,
+                                                                               tgrel->rd_att, &isnull));
                if (isnull || tgnargs < RI_FIRST_ATTNAME_ARGNO ||
                        tgnargs > RI_MAX_ARGUMENTS)
                {
@@ -3202,7 +3203,7 @@ ATExecDropNotNull(Relation rel, const char *colName)
                         */
                        for (i = 0; i < indexStruct->indnatts; i++)
                        {
-                               if (indexStruct->indkey[i] == attnum)
+                               if (indexStruct->indkey.values[i] == attnum)
                                        ereport(ERROR,
                                                        (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                                                         errmsg("column \"%s\" is in a primary key",
@@ -4096,6 +4097,9 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
        ListCell   *indexoidscan;
        HeapTuple       indexTuple = NULL;
        Form_pg_index indexStruct = NULL;
+       Datum           indclassDatum;
+       bool            isnull;
+       oidvector  *indclass;
        int                     i;
 
        /*
@@ -4135,6 +4139,12 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
                        errmsg("there is no primary key for referenced table \"%s\"",
                                   RelationGetRelationName(pkrel))));
 
+       /* Must get indclass the hard way */
+       indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
+                                                                       Anum_pg_index_indclass, &isnull);
+       Assert(!isnull);
+       indclass = (oidvector *) DatumGetPointer(indclassDatum);
+
        /*
         * Now build the list of PK attributes from the indkey definition (we
         * assume a primary key cannot have expressional elements)
@@ -4142,11 +4152,11 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
        *attnamelist = NIL;
        for (i = 0; i < indexStruct->indnatts; i++)
        {
-               int                     pkattno = indexStruct->indkey[i];
+               int                     pkattno = indexStruct->indkey.values[i];
 
                attnums[i] = pkattno;
                atttypids[i] = attnumTypeId(pkrel, pkattno);
-               opclasses[i] = indexStruct->indclass[i];
+               opclasses[i] = indclass->values[i];
                *attnamelist = lappend(*attnamelist,
                   makeString(pstrdup(NameStr(*attnumAttName(pkrel, pkattno)))));
        }
@@ -4205,6 +4215,16 @@ transformFkeyCheckAttrs(Relation pkrel,
                        heap_attisnull(indexTuple, Anum_pg_index_indpred) &&
                        heap_attisnull(indexTuple, Anum_pg_index_indexprs))
                {
+                       /* Must get indclass the hard way */
+                       Datum           indclassDatum;
+                       bool            isnull;
+                       oidvector  *indclass;
+
+                       indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
+                                                                                       Anum_pg_index_indclass, &isnull);
+                       Assert(!isnull);
+                       indclass = (oidvector *) DatumGetPointer(indclassDatum);
+
                        /*
                         * The given attnum list may match the index columns in any
                         * order.  Check that each list is a subset of the other.
@@ -4214,7 +4234,7 @@ transformFkeyCheckAttrs(Relation pkrel,
                                found = false;
                                for (j = 0; j < numattrs; j++)
                                {
-                                       if (attnums[i] == indexStruct->indkey[j])
+                                       if (attnums[i] == indexStruct->indkey.values[j])
                                        {
                                                found = true;
                                                break;
@@ -4230,9 +4250,9 @@ transformFkeyCheckAttrs(Relation pkrel,
                                        found = false;
                                        for (j = 0; j < numattrs; j++)
                                        {
-                                               if (attnums[j] == indexStruct->indkey[i])
+                                               if (attnums[j] == indexStruct->indkey.values[i])
                                                {
-                                                       opclasses[j] = indexStruct->indclass[i];
+                                                       opclasses[j] = indclass->values[i];
                                                        found = true;
                                                        break;
                                                }
index 277d874..a9e8bc9 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.181 2005/03/25 21:57:58 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.182 2005/03/29 00:16:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -67,7 +67,7 @@ Oid
 CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
 {
        int16           tgtype;
-       int16           tgattr[FUNC_MAX_ARGS];
+       int2vector *tgattr;
        Datum           values[Natts_pg_trigger];
        char            nulls[Natts_pg_trigger];
        Relation        rel;
@@ -77,7 +77,7 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
        ScanKeyData key;
        Relation        pgrel;
        HeapTuple       tuple;
-       Oid                     fargtypes[FUNC_MAX_ARGS];
+       Oid                     fargtypes[1];   /* dummy */
        Oid                     funcoid;
        Oid                     funcrettype;
        Oid                     trigoid;
@@ -275,7 +275,6 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
        /*
         * Find and validate the trigger function.
         */
-       MemSet(fargtypes, 0, FUNC_MAX_ARGS * sizeof(Oid));
        funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
        funcrettype = get_func_rettype(funcoid);
        if (funcrettype != TRIGGEROID)
@@ -359,7 +358,8 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
                values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
                                                                                                        CStringGetDatum(""));
        }
-       MemSet(tgattr, 0, FUNC_MAX_ARGS * sizeof(int16));
+       /* tgattr is currently always a zero-length array */
+       tgattr = buildint2vector(NULL, 0);
        values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
 
        tuple = heap_formtuple(tgrel->rd_att, values, nulls);
@@ -774,8 +774,16 @@ RelationBuildTriggers(Relation relation)
                build->tgdeferrable = pg_trigger->tgdeferrable;
                build->tginitdeferred = pg_trigger->tginitdeferred;
                build->tgnargs = pg_trigger->tgnargs;
-               memcpy(build->tgattr, &(pg_trigger->tgattr),
-                          FUNC_MAX_ARGS * sizeof(int16));
+               /* tgattr is first var-width field, so OK to access directly */
+               build->tgnattr = pg_trigger->tgattr.dim1;
+               if (build->tgnattr > 0)
+               {
+                       build->tgattr = (int2 *) palloc(build->tgnattr * sizeof(int2));
+                       memcpy(build->tgattr, &(pg_trigger->tgattr.values),
+                                  build->tgnattr * sizeof(int2));
+               }
+               else
+                       build->tgattr = NULL;
                if (build->tgnargs > 0)
                {
                        bytea      *val;
@@ -783,9 +791,10 @@ RelationBuildTriggers(Relation relation)
                        char       *p;
                        int                     i;
 
-                       val = (bytea *) fastgetattr(htup,
-                                                                               Anum_pg_trigger_tgargs,
-                                                                               tgrel->rd_att, &isnull);
+                       val = (bytea *)
+                               DatumGetPointer(fastgetattr(htup,
+                                                                                       Anum_pg_trigger_tgargs,
+                                                                                       tgrel->rd_att, &isnull));
                        if (isnull)
                                elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
                                         RelationGetRelationName(relation));
@@ -928,6 +937,15 @@ CopyTriggerDesc(TriggerDesc *trigdesc)
        for (i = 0; i < trigdesc->numtriggers; i++)
        {
                trigger->tgname = pstrdup(trigger->tgname);
+               if (trigger->tgnattr > 0)
+               {
+                       int2       *newattr;
+
+                       newattr = (int2 *) palloc(trigger->tgnattr * sizeof(int2));
+                       memcpy(newattr, trigger->tgattr,
+                                  trigger->tgnattr * sizeof(int2));
+                       trigger->tgattr = newattr;
+               }
                if (trigger->tgnargs > 0)
                {
                        char      **newargs;
@@ -1031,6 +1049,8 @@ FreeTriggerDesc(TriggerDesc *trigdesc)
        for (i = 0; i < trigdesc->numtriggers; i++)
        {
                pfree(trigger->tgname);
+               if (trigger->tgnattr > 0)
+                       pfree(trigger->tgattr);
                if (trigger->tgnargs > 0)
                {
                        while (--(trigger->tgnargs) >= 0)
@@ -1092,8 +1112,11 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
                                return false;
                        if (trig1->tgnargs != trig2->tgnargs)
                                return false;
-                       if (memcmp(trig1->tgattr, trig2->tgattr,
-                                          sizeof(trig1->tgattr)) != 0)
+                       if (trig1->tgnattr != trig2->tgnattr)
+                               return false;
+                       if (trig1->tgnattr > 0 &&
+                               memcmp(trig1->tgattr, trig2->tgattr,
+                                          trig1->tgnattr * sizeof(int2)) != 0)
                                return false;
                        for (j = 0; j < trig1->tgnargs; j++)
                                if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)
index 63a734e..9d915af 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.174 2005/03/22 20:13:06 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.175 2005/03/29 00:16:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -724,9 +724,17 @@ init_fcache(Oid foid, FuncExprState *fcache, MemoryContext fcacheCxt)
        if (aclresult != ACLCHECK_OK)
                aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(foid));
 
-       /* Safety check (should never fail, as parser should check sooner) */
+       /*
+        * Safety check on nargs.  Under normal circumstances this should never
+        * fail, as parser should check sooner.  But possibly it might fail
+        * if server has been compiled with FUNC_MAX_ARGS smaller than some
+        * functions declared in pg_proc?
+        */
        if (list_length(fcache->args) > FUNC_MAX_ARGS)
-               elog(ERROR, "too many arguments");
+               ereport(ERROR,
+                               (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
+                                errmsg("cannot pass more than %d arguments to a function",
+                                               FUNC_MAX_ARGS)));
 
        /* Set up the primary fmgr lookup information */
        fmgr_info_cxt(foid, &(fcache->func), fcacheCxt);
index fdbd610..2ddc614 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.93 2005/03/25 21:57:58 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.94 2005/03/29 00:16:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -228,7 +228,7 @@ init_sql_fcache(FmgrInfo *finfo)
 
                argOidVect = (Oid *) palloc(nargs * sizeof(Oid));
                memcpy(argOidVect,
-                          procedureStruct->proargtypes,
+                          procedureStruct->proargtypes.values,
                           nargs * sizeof(Oid));
                /* Resolve any polymorphic argument types */
                for (argnum = 0; argnum < nargs; argnum++)
index 1756f35..c5963a1 100644 (file)
@@ -61,7 +61,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.131 2005/03/22 20:13:06 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.132 2005/03/29 00:16:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1300,15 +1300,16 @@ ExecInitAgg(Agg *node, EState *estate)
                if (aggtranstype == ANYARRAYOID || aggtranstype == ANYELEMENTOID)
                {
                        /* have to fetch the agg's declared input type... */
-                       Oid                     agg_arg_types[FUNC_MAX_ARGS];
+                       Oid                *agg_arg_types;
                        int                     agg_nargs;
 
                        (void) get_func_signature(aggref->aggfnoid,
-                                                                         agg_arg_types, &agg_nargs);
+                                                                         &agg_arg_types, &agg_nargs);
                        Assert(agg_nargs == 1);
                        aggtranstype = resolve_generic_type(aggtranstype,
                                                                                                inputType,
                                                                                                agg_arg_types[0]);
+                       pfree(agg_arg_types);
                }
 
                /* build expression trees using actual argument & result types */
index 15418d4..76255de 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.190 2005/03/28 00:58:24 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.191 2005/03/29 00:17:02 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -421,15 +421,16 @@ count_agg_clauses_walker(Node *node, AggClauseCounts *counts)
                if (aggtranstype == ANYARRAYOID || aggtranstype == ANYELEMENTOID)
                {
                        /* have to fetch the agg's declared input type... */
-                       Oid                     agg_arg_types[FUNC_MAX_ARGS];
+                       Oid                *agg_arg_types;
                        int                     agg_nargs;
 
                        (void) get_func_signature(aggref->aggfnoid,
-                                                                         agg_arg_types, &agg_nargs);
+                                                                         &agg_arg_types, &agg_nargs);
                        Assert(agg_nargs == 1);
                        aggtranstype = resolve_generic_type(aggtranstype,
                                                                                                inputType,
                                                                                                agg_arg_types[0]);
+                       pfree(agg_arg_types);
                }
 
                /*
@@ -2187,7 +2188,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
 {
        Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
        bool            polymorphic = false;
-       Oid                     argtypes[FUNC_MAX_ARGS];
+       Oid                *argtypes;
        char       *src;
        Datum           tmp;
        bool            isNull;
@@ -2220,22 +2221,6 @@ inline_function(Oid funcid, Oid result_type, List *args,
        if (pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
                return NULL;
 
-       /* Check for polymorphic arguments, and substitute actual arg types */
-       memcpy(argtypes, funcform->proargtypes, FUNC_MAX_ARGS * sizeof(Oid));
-       for (i = 0; i < funcform->pronargs; i++)
-       {
-               if (argtypes[i] == ANYARRAYOID ||
-                       argtypes[i] == ANYELEMENTOID)
-               {
-                       polymorphic = true;
-                       argtypes[i] = exprType((Node *) list_nth(args, i));
-               }
-       }
-
-       if (funcform->prorettype == ANYARRAYOID ||
-               funcform->prorettype == ANYELEMENTOID)
-               polymorphic = true;
-
        /*
         * Setup error traceback support for ereport().  This is so that we
         * can finger the function that bad information came from.
@@ -2256,6 +2241,24 @@ inline_function(Oid funcid, Oid result_type, List *args,
                                                                  ALLOCSET_DEFAULT_MAXSIZE);
        oldcxt = MemoryContextSwitchTo(mycxt);
 
+       /* Check for polymorphic arguments, and substitute actual arg types */
+       argtypes = (Oid *) palloc(funcform->pronargs * sizeof(Oid));
+       memcpy(argtypes, funcform->proargtypes.values,
+                  funcform->pronargs * sizeof(Oid));
+       for (i = 0; i < funcform->pronargs; i++)
+       {
+               if (argtypes[i] == ANYARRAYOID ||
+                       argtypes[i] == ANYELEMENTOID)
+               {
+                       polymorphic = true;
+                       argtypes[i] = exprType((Node *) list_nth(args, i));
+               }
+       }
+
+       if (funcform->prorettype == ANYARRAYOID ||
+               funcform->prorettype == ANYELEMENTOID)
+               polymorphic = true;
+
        /* Fetch and parse the function body */
        tmp = SysCacheGetAttr(PROCOID,
                                                  func_tuple,
index 6099211..c64f2aa 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.102 2005/03/27 06:29:42 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.103 2005/03/29 00:17:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -137,8 +137,8 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel)
 
                        for (i = 0; i < ncolumns; i++)
                        {
-                               info->classlist[i] = index->indclass[i];
-                               info->indexkeys[i] = index->indkey[i];
+                               info->classlist[i] = indexRelation->rd_indclass->values[i];
+                               info->indexkeys[i] = index->indkey.values[i];
                        }
 
                        info->relam = indexRelation->rd_rel->relam;
index 4781a58..18a42c5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.67 2005/03/10 23:21:23 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.68 2005/03/29 00:17:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -367,14 +367,13 @@ build_aggregate_fnexprs(Oid agg_input_type,
                                                Expr **transfnexpr,
                                                Expr **finalfnexpr)
 {
-       Oid                     transfn_arg_types[FUNC_MAX_ARGS];
        int                     transfn_nargs;
        Param      *arg0;
        Param      *arg1;
        List       *args;
 
-       /* get the transition function signature (only need nargs) */
-       (void) get_func_signature(transfn_oid, transfn_arg_types, &transfn_nargs);
+       /* get the transition function arg count */
+       transfn_nargs = get_func_nargs(transfn_oid);
 
        /*
         * Build arg list to use in the transfn FuncExpr node. We really only
index 22f13fd..3245578 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.126 2004/12/31 22:00:27 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.127 2005/03/29 00:17:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -615,9 +615,9 @@ build_coercion_expression(Node *node, Oid funcId,
        Assert(!procstruct->proisagg);
        nargs = procstruct->pronargs;
        Assert(nargs >= 1 && nargs <= 3);
-       /* Assert(procstruct->proargtypes[0] == exprType(node)); */
-       Assert(nargs < 2 || procstruct->proargtypes[1] == INT4OID);
-       Assert(nargs < 3 || procstruct->proargtypes[2] == BOOLOID);
+       /* Assert(procstruct->proargtypes.values[0] == exprType(node)); */
+       Assert(nargs < 2 || procstruct->proargtypes.values[1] == INT4OID);
+       Assert(nargs < 3 || procstruct->proargtypes.values[2] == BOOLOID);
 
        ReleaseSysCache(tp);
 
@@ -1672,11 +1672,21 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
                 * of array types.      If so, and if the element types have a
                 * suitable cast, use array_type_coerce() or
                 * array_type_length_coerce().
+                *
+                * Hack: disallow coercions to oidvector and int2vector, which
+                * otherwise tend to capture coercions that should go to "real" array
+                * types.  We want those types to be considered "real" arrays for many
+                * purposes, but not this one.  (Also, array_type_coerce isn't
+                * guaranteed to produce an output that meets the restrictions of
+                * these datatypes, such as being 1-dimensional.)
                 */
                Oid                     targetElemType;
                Oid                     sourceElemType;
                Oid                     elemfuncid;
 
+               if (targetTypeId == OIDVECTOROID || targetTypeId == INT2VECTOROID)
+                       return false;
+
                if ((targetElemType = get_element_type(targetTypeId)) != InvalidOid &&
                 (sourceElemType = get_element_type(sourceTypeId)) != InvalidOid)
                {
@@ -1691,11 +1701,7 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
                                else
                                {
                                        /* does the function take a typmod arg? */
-                                       Oid                     argtypes[FUNC_MAX_ARGS];
-                                       int                     nargs;
-
-                                       (void) get_func_signature(elemfuncid, argtypes, &nargs);
-                                       if (nargs > 1)
+                                       if (get_func_nargs(elemfuncid) > 1)
                                                *funcid = F_ARRAY_TYPE_LENGTH_COERCE;
                                        else
                                                *funcid = F_ARRAY_TYPE_COERCE;
index b2c8903..f123e2f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.77 2004/12/31 22:01:16 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.78 2005/03/29 00:17:05 tgl Exp $
  *
  * NOTES
  *       This cruft is the server side of PQfn.
@@ -230,9 +230,14 @@ fetch_fp_info(Oid func_id, struct fp_info * fip)
                                 errmsg("function with OID %u does not exist", func_id)));
        pp = (Form_pg_proc) GETSTRUCT(func_htp);
 
+       /* watch out for catalog entries with more than FUNC_MAX_ARGS args */
+       if (pp->pronargs > FUNC_MAX_ARGS)
+               elog(ERROR, "function %s has more than %d arguments",
+                        NameStr(pp->proname), FUNC_MAX_ARGS);
+
        fip->namespace = pp->pronamespace;
        fip->rettype = pp->prorettype;
-       memcpy(fip->argtypes, pp->proargtypes, FUNC_MAX_ARGS * sizeof(Oid));
+       memcpy(fip->argtypes, pp->proargtypes.values, pp->pronargs * sizeof(Oid));
 
        ReleaseSysCache(func_htp);
 
index 3ceac9c..47edcc5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.117 2005/03/24 21:50:37 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.118 2005/03/29 00:17:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -56,7 +56,7 @@
  *
  *
  * There are also some "fixed-length array" datatypes, such as NAME and
- * OIDVECTOR.  These are simply a sequence of a fixed number of items each
+ * POINT.  These are simply a sequence of a fixed number of items each
  * of a fixed-length datatype, with no overhead; the item size must be
  * a multiple of its alignment requirement, because we do no padding.
  * We support subscripting on these types, but array_in() and array_out()
index 346b6a2..0280196 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.39 2004/12/31 22:01:21 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.40 2005/03/29 00:17:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -140,12 +140,15 @@ format_type_internal(Oid type_oid, int32 typemod,
        /*
         * Check if it's an array (and not a domain --- we don't want to show
         * the substructure of a domain type).  Fixed-length array types such
-        * as "name" shouldn't get deconstructed either.
+        * as "name" shouldn't get deconstructed either.  As of Postgres 8.1,
+        * rather than checking typlen we check the toast property, and don't
+        * deconstruct "plain storage" array types --- this is because we don't
+        * want to show oidvector as oid[].
         */
        array_base_type = typeform->typelem;
 
        if (array_base_type != InvalidOid &&
-               typeform->typlen == -1 &&
+               typeform->typstorage != 'p' &&
                typeform->typtype != 'd')
        {
                /* Switch our attention to the array element type */
@@ -459,29 +462,17 @@ type_maximum_size(Oid type_oid, int32 typemod)
 
 /*
  * oidvectortypes                      - converts a vector of type OIDs to "typname" list
- *
- * The interface for this function is wrong: it should be told how many
- * OIDs are significant in the input vector, so that trailing InvalidOid
- * argument types can be recognized.
  */
 Datum
 oidvectortypes(PG_FUNCTION_ARGS)
 {
-       Oid                *oidArray = (Oid *) PG_GETARG_POINTER(0);
+       oidvector  *oidArray = (oidvector *) PG_GETARG_POINTER(0);
        char       *result;
-       int                     numargs;
+       int                     numargs = oidArray->dim1;
        int                     num;
        size_t          total;
        size_t          left;
 
-       /* Try to guess how many args there are :-( */
-       numargs = 0;
-       for (num = 0; num < FUNC_MAX_ARGS; num++)
-       {
-               if (oidArray[num] != InvalidOid)
-                       numargs = num + 1;
-       }
-
        total = 20 * numargs + 1;
        result = palloc(total);
        result[0] = '\0';
@@ -489,7 +480,7 @@ oidvectortypes(PG_FUNCTION_ARGS)
 
        for (num = 0; num < numargs; num++)
        {
-               char       *typename = format_type_internal(oidArray[num], -1,
+               char       *typename = format_type_internal(oidArray->values[num], -1,
                                                                                                        false, true);
                size_t          slen = strlen(typename);
 
index db36ac9..d00a7d1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.65 2005/02/27 08:31:30 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.66 2005/03/29 00:17:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #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;
+
+       result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS));
 
-       for (slot = 0; *intString && slot < INDEX_MAX_KEYS; slot++)
+       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;
-
-       for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
-               result[slot] = (int16) pq_getmsgint(buf, sizeof(int16));
+       int2vector  *result;
+
+       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);
 }
 
 
index ababe64..4329f07 100644 (file)
@@ -8,20 +8,24 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.61 2005/02/11 04:08:58 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.62 2005/03/29 00:17:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
 #include <ctype.h>
-#include <errno.h>
 #include <limits.h>
 
+#include "catalog/pg_type.h"
 #include "libpq/pqformat.h"
+#include "utils/array.h"
 #include "utils/builtins.h"
 
 
+#define OidVectorSize(n)       (offsetof(oidvector, values) + (n) * sizeof(Oid))
+
+
 /*****************************************************************************
  *      USER I/O ROUTINES                                                                                                               *
  *****************************************************************************/
@@ -151,27 +155,54 @@ oidsend(PG_FUNCTION_ARGS)
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 }
 
+/*
+ * construct oidvector given a raw array of Oids
+ *
+ * If oids is NULL then caller must fill values[] afterward
+ */
+oidvector *
+buildoidvector(const Oid *oids, int n)
+{
+       oidvector  *result;
+
+       result = (oidvector *) palloc0(OidVectorSize(n));
+
+       if (n > 0 && oids)
+               memcpy(result->values, oids, n * sizeof(Oid));
+
+       /*
+        * Attach standard array header.  For historical reasons, we set the
+        * index lower bound to 0 not 1.
+        */
+       result->size = OidVectorSize(n);
+       result->ndim = 1;
+       result->flags = 0;
+       result->elemtype = OIDOID;
+       result->dim1 = n;
+       result->lbound1 = 0;
+
+       return result;
+}
 
 /*
  *             oidvectorin                     - converts "num num ..." to internal form
- *
- *             Note:
- *                             Fills any unsupplied positions with InvalidOid.
  */
 Datum
 oidvectorin(PG_FUNCTION_ARGS)
 {
        char       *oidString = PG_GETARG_CSTRING(0);
-       Oid                *result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
-       int                     slot;
+       oidvector  *result;
+       int                     n;
 
-       for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
+       result = (oidvector *) palloc0(OidVectorSize(FUNC_MAX_ARGS));
+
+       for (n = 0; n < FUNC_MAX_ARGS; n++)
        {
                while (*oidString && isspace((unsigned char) *oidString))
                        oidString++;
                if (*oidString == '\0')
                        break;
-               result[slot] = oidin_subr("oidvectorin", oidString, &oidString);
+               result->values[n] = oidin_subr("oidvectorin", oidString, &oidString);
        }
        while (*oidString && isspace((unsigned char) *oidString))
                oidString++;
@@ -179,8 +210,13 @@ oidvectorin(PG_FUNCTION_ARGS)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 errmsg("oidvector has too many elements")));
-       while (slot < INDEX_MAX_KEYS)
-               result[slot++] = InvalidOid;
+
+       result->size = OidVectorSize(n);
+       result->ndim = 1;
+       result->flags = 0;
+       result->elemtype = OIDOID;
+       result->dim1 = n;
+       result->lbound1 = 0;
 
        PG_RETURN_POINTER(result);
 }
@@ -191,24 +227,19 @@ oidvectorin(PG_FUNCTION_ARGS)
 Datum
 oidvectorout(PG_FUNCTION_ARGS)
 {
-       Oid                *oidArray = (Oid *) PG_GETARG_POINTER(0);
+       oidvector  *oidArray = (oidvector *) PG_GETARG_POINTER(0);
        int                     num,
-                               maxnum;
+                               nnums = oidArray->dim1;
        char       *rp;
        char       *result;
 
-       /* find last non-zero value in vector */
-       for (maxnum = INDEX_MAX_KEYS - 1; maxnum >= 0; maxnum--)
-               if (oidArray[maxnum] != 0)
-                       break;
-
        /* assumes sign, 10 digits, ' ' */
-       rp = result = (char *) palloc((maxnum + 1) * 12 + 1);
-       for (num = 0; num <= maxnum; num++)
+       rp = result = (char *) palloc(nnums * 12 + 1);
+       for (num = 0; num < nnums; num++)
        {
                if (num != 0)
                        *rp++ = ' ';
-               sprintf(rp, "%u", oidArray[num]);
+               sprintf(rp, "%u", oidArray->values[num]);
                while (*++rp != '\0')
                        ;
        }
@@ -223,11 +254,19 @@ Datum
 oidvectorrecv(PG_FUNCTION_ARGS)
 {
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
-       Oid                *result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
-       int                     slot;
-
-       for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
-               result[slot] = (Oid) pq_getmsgint(buf, sizeof(Oid));
+       oidvector  *result;
+
+       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;
-
-       for (i = 0; i < INDEX_MAX_KEYS; i++)
-               if (arg1[i] != arg2[i])
-                       PG_RETURN_BOOL(arg1[i] < arg2[i]);
-       PG_RETURN_BOOL(false);
+       int32           cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
+
+       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;
-
-       for (i = 0; i < INDEX_MAX_KEYS; i++)
-               if (arg1[i] != arg2[i])
-                       PG_RETURN_BOOL(arg1[i] <= arg2[i]);
-       PG_RETURN_BOOL(true);
+       int32           cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
+
+       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;
-
-       for (i = 0; i < INDEX_MAX_KEYS; i++)
-               if (arg1[i] != arg2[i])
-                       PG_RETURN_BOOL(arg1[i] >= arg2[i]);
-       PG_RETURN_BOOL(true);
+       int32           cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
+
+       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;
-
-       for (i = 0; i < INDEX_MAX_KEYS; i++)
-               if (arg1[i] != arg2[i])
-                       PG_RETURN_BOOL(arg1[i] > arg2[i]);
-       PG_RETURN_BOOL(false);
+       int32           cmp = DatumGetInt32(btoidvectorcmp(fcinfo));
+
+       PG_RETURN_BOOL(cmp > 0);
 }
 
 Datum
index a74d1fe..42fddeb 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.92 2004/12/31 22:01:22 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.93 2005/03/29 00:17:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -98,7 +98,7 @@ regprocin(PG_FUNCTION_ARGS)
                                        CStringGetDatum(pro_name_or_oid));
 
                hdesc = heap_openr(ProcedureRelationName, AccessShareLock);
-               sysscan = systable_beginscan(hdesc, ProcedureNameNspIndex, true,
+               sysscan = systable_beginscan(hdesc, ProcedureNameArgsNspIndex, true,
                                                                         SnapshotNow, 1, skey);
 
                while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
@@ -336,7 +336,7 @@ format_procedure(Oid procedure_oid)
                                                 quote_qualified_identifier(nspname, proname));
                for (i = 0; i < nargs; i++)
                {
-                       Oid                     thisargtype = procform->proargtypes[i];
+                       Oid                     thisargtype = procform->proargtypes.values[i];
 
                        if (i > 0)
                                appendStringInfoChar(&buf, ',');
index f3458a5..814deff 100644 (file)
@@ -3,7 +3,7 @@
  *                             back to source text
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.188 2005/01/13 17:19:10 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.189 2005/03/29 00:17:08 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -553,9 +553,10 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
                char       *p;
                int                     i;
 
-               val = (bytea *) fastgetattr(ht_trig,
-                                                                       Anum_pg_trigger_tgargs,
-                                                                       tgrel->rd_att, &isnull);
+               val = (bytea *)
+                       DatumGetPointer(fastgetattr(ht_trig,
+                                                                               Anum_pg_trigger_tgargs,
+                                                                               tgrel->rd_att, &isnull));
                if (isnull)
                        elog(ERROR, "tgargs is null for trigger %u", trigid);
                p = (char *) VARDATA(val);
@@ -637,6 +638,9 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
        Oid                     indrelid;
        int                     keyno;
        Oid                     keycoltype;
+       Datum           indclassDatum;
+       bool            isnull;
+       oidvector  *indclass;
        StringInfoData buf;
        char       *str;
        char       *sep;
@@ -654,6 +658,12 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
        indrelid = idxrec->indrelid;
        Assert(indexrelid == idxrec->indexrelid);
 
+       /* Must get indclass the hard way */
+       indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
+                                                                       Anum_pg_index_indclass, &isnull);
+       Assert(!isnull);
+       indclass = (oidvector *) DatumGetPointer(indclassDatum);
+
        /*
         * Fetch the pg_class tuple of the index relation
         */
@@ -720,7 +730,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
        sep = "";
        for (keyno = 0; keyno < idxrec->indnatts; keyno++)
        {
-               AttrNumber      attnum = idxrec->indkey[keyno];
+               AttrNumber      attnum = idxrec->indkey.values[keyno];
 
                if (!colno)
                        appendStringInfo(&buf, sep);
@@ -764,7 +774,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
                 * Add the operator class name
                 */
                if (!colno)
-                       get_opclass_name(idxrec->indclass[keyno], keycoltype,
+                       get_opclass_name(indclass->values[keyno], keycoltype,
                                                         &buf);
        }
 
@@ -3537,7 +3547,10 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
        nargs = 0;
        foreach(l, expr->args)
        {
-               Assert(nargs < FUNC_MAX_ARGS);
+               if (nargs >= FUNC_MAX_ARGS)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
+                                        errmsg("too many arguments")));
                argtypes[nargs] = exprType((Node *) lfirst(l));
                nargs++;
        }
index e417fcb..0b40a20 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.120 2005/01/27 23:36:12 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.121 2005/03/29 00:17:11 tgl Exp $
  *
  * NOTES
  *       Eventually, the index information should go through here, too.
@@ -774,14 +774,35 @@ get_func_rettype(Oid funcid)
 }
 
 /*
+ * 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;
index a6660fc..109a6e8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.217 2005/03/28 00:58:26 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.218 2005/03/29 00:17:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,7 +27,6 @@
  */
 #include "postgres.h"
 
-#include <errno.h>
 #include <sys/file.h>
 #include <fcntl.h>
 #include <unistd.h>
@@ -81,6 +80,7 @@ static FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class};
 static FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute};
 static FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = {Schema_pg_proc};
 static FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type};
+static FormData_pg_attribute Desc_pg_index[Natts_pg_index] = {Schema_pg_index};
 
 /*
  *             Hash tables that index the relation cache
@@ -267,10 +267,11 @@ static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
 static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo,
                                  Relation oldrelation);
 static void RelationInitPhysicalAddr(Relation relation);
+static TupleDesc GetPgIndexDescriptor(void);
 static void AttrDefaultFetch(Relation relation);
 static void CheckConstraintFetch(Relation relation);
 static List *insert_ordered_oid(List *list, Oid datum);
-static void IndexSupportInitialize(Form_pg_index iform,
+static void IndexSupportInitialize(oidvector *indclass,
                                           Oid *indexOperator,
                                           RegProcedure *indexSupport,
                                           StrategyNumber maxStrategyNumber,
@@ -918,6 +919,8 @@ RelationInitIndexAccessInfo(Relation relation)
 {
        HeapTuple       tuple;
        Form_pg_am      aform;
+       Datum           indclassDatum;
+       bool            isnull;
        MemoryContext indexcxt;
        MemoryContext oldcontext;
        Oid                *operator;
@@ -946,6 +949,18 @@ RelationInitIndexAccessInfo(Relation relation)
        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
         */
        tuple = SearchSysCache(AMOID,
@@ -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);
index 3435ac8..b7b7ec2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.96 2004/12/31 22:01:25 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.97 2005/03/29 00:17:12 tgl Exp $
  *
  * NOTES
  *       These routines allow the parser/planner/executor to perform
@@ -334,15 +334,15 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
        }},
-       {ProcedureRelationName,         /* PROCNAMENSP */
-               ProcedureNameNspIndex,
+       {ProcedureRelationName,         /* PROCNAMEARGSNSP */
+               ProcedureNameArgsNspIndex,
                0,
-               4,
+               3,
                {
                        Anum_pg_proc_proname,
-                       Anum_pg_proc_pronargs,
                        Anum_pg_proc_proargtypes,
-                       Anum_pg_proc_pronamespace
+                       Anum_pg_proc_pronamespace,
+                       0
        }},
        {ProcedureRelationName,         /* PROCOID */
                ProcedureOidIndex,
index e34a942..430cfef 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.90 2005/03/22 20:13:07 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.91 2005/03/29 00:17:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -344,7 +344,7 @@ fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
                        for (i = 0; i < procedureStruct->pronargs; i++)
                        {
                                fnextra->arg_toastable[i] =
-                                       TypeIsToastable(procedureStruct->proargtypes[i]);
+                                       TypeIsToastable(procedureStruct->proargtypes.values[i]);
                        }
                        break;
                case 1:
index 58fe0f9..ebed0ab 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/c.h,v 1.180 2005/02/22 04:41:51 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/c.h,v 1.181 2005/03/29 00:17:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -428,11 +428,36 @@ typedef struct varlena BpChar;    /* blank-padded char, ie SQL char(n) */
 typedef struct varlena VarChar; /* var-length char, ie SQL varchar(n) */
 
 /*
- * Fixed-length array types (these are not varlena's!)
+ * Specialized array types.  These are physically laid out just the same
+ * as regular arrays (so that the regular array subscripting code works
+ * with them).  They exist as distinct types mostly for historical reasons:
+ * they have nonstandard I/O behavior which we don't want to change for fear
+ * of breaking applications that look at the system catalogs.  There is also
+ * an implementation issue for oidvector: it's part of the primary key for
+ * pg_proc, and we can't use the normal btree array support routines for that
+ * without circularity.
  */
+typedef struct
+{
+       int32           size;                   /* these fields must match ArrayType! */
+       int                     ndim;
+       int                     flags;
+       Oid                     elemtype;
+       int                     dim1;
+       int                     lbound1;
+       int2            values[1];              /* VARIABLE LENGTH ARRAY */
+} int2vector;                                  /* VARIABLE LENGTH STRUCT */
 
-typedef int2 int2vector[INDEX_MAX_KEYS];
-typedef Oid oidvector[INDEX_MAX_KEYS];
+typedef struct
+{
+       int32           size;                   /* these fields must match ArrayType! */
+       int                     ndim;
+       int                     flags;
+       Oid                     elemtype;
+       int                     dim1;
+       int                     lbound1;
+       Oid                     values[1];              /* VARIABLE LENGTH ARRAY */
+} oidvector;                                   /* VARIABLE LENGTH STRUCT */
 
 /*
  * We want NameData to have length NAMEDATALEN and int alignment,
index ba64007..2441187 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.260 2005/03/27 23:53:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.261 2005/03/29 00:17:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200503271
+#define CATALOG_VERSION_NO     200503281
 
 #endif
index 7e80496..5b0a63c 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.84 2004/12/31 22:03:24 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.85 2005/03/29 00:17:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,7 +63,7 @@
 #define OpclassOidIndex                                "pg_opclass_oid_index"
 #define OperatorNameNspIndex           "pg_operator_oprname_l_r_n_index"
 #define OperatorOidIndex                       "pg_operator_oid_index"
-#define ProcedureNameNspIndex          "pg_proc_proname_args_nsp_index"
+#define ProcedureNameArgsNspIndex      "pg_proc_proname_args_nsp_index"
 #define ProcedureOidIndex                      "pg_proc_oid_index"
 #define RewriteOidIndex                                "pg_rewrite_oid_index"
 #define RewriteRelRulenameIndex                "pg_rewrite_rel_rulename_index"
@@ -161,7 +161,7 @@ DECLARE_UNIQUE_INDEX(pg_opclass_oid_index on pg_opclass using btree(oid oid_ops)
 DECLARE_UNIQUE_INDEX(pg_operator_oid_index on pg_operator using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
 DECLARE_UNIQUE_INDEX(pg_proc_oid_index on pg_proc using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index on pg_proc using btree(proname name_ops, pronargs int2_ops, proargtypes oidvector_ops, pronamespace oid_ops));
+DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index on pg_proc using btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
 /* This following index is not used for a cache and is not unique */
 DECLARE_UNIQUE_INDEX(pg_rewrite_oid_index on pg_rewrite using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index on pg_rewrite using btree(ev_class oid_ops, rulename name_ops));
index 068f551..2094f75 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.113 2004/12/31 22:03:24 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.114 2005/03/29 00:17:17 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -317,7 +317,7 @@ DATA(insert ( 1262 tableoid                 26 0  4  -7 0 -1 -1 t p i t f f t 0));
 { 1255, {"provolatile"},               18, -1, 1,      9, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
 { 1255, {"pronargs"},                  21, -1, 2, 10, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
 { 1255, {"prorettype"},                        26, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
-{ 1255, {"proargtypes"},               30, -1, INDEX_MAX_KEYS*4, 12, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
+{ 1255, {"proargtypes"},               30, -1, -1, 12, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
 { 1255, {"proargnames"},         1009, -1, -1, 13, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
 { 1255, {"prosrc"},                            25, -1, -1, 14, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
 { 1255, {"probin"},                            17, -1, -1, 15, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
@@ -334,7 +334,7 @@ DATA(insert ( 1255 proretset                16 -1 1   8 0 -1 -1 t p c t f f t 0));
 DATA(insert ( 1255 provolatile         18 -1 1   9 0 -1 -1 t p c t f f t 0));
 DATA(insert ( 1255 pronargs                    21 -1 2  10 0 -1 -1 t p s t f f t 0));
 DATA(insert ( 1255 prorettype          26 -1 4  11 0 -1 -1 t p i t f f t 0));
-DATA(insert ( 1255 proargtypes         30 -1 INDEX_MAX_KEYS*4 12 0 -1 -1 f p i t f f t 0));
+DATA(insert ( 1255 proargtypes         30 -1 -1 12 1 -1 -1 f p i t f f t 0));
 DATA(insert ( 1255 proargnames   1009 -1 -1 13 1 -1 -1 f x i f f f t 0));
 DATA(insert ( 1255 prosrc                      25 -1 -1 14 0 -1 -1 f x i f f f t 0));
 DATA(insert ( 1255 probin                      17 -1 -1 15 0 -1 -1 f x i f f f t 0));
@@ -512,6 +512,26 @@ 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
  *                               waits.  We need a pg_xactlock entry in pg_class only to
index 4c27a01..8ed1e29 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_index.h,v 1.35 2004/12/31 22:03:24 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_index.h,v 1.36 2005/03/29 00:17:17 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -35,14 +35,14 @@ CATALOG(pg_index) BKI_WITHOUT_OIDS
 {
        Oid                     indexrelid;             /* OID of the index */
        Oid                     indrelid;               /* OID of the relation it indexes */
-       int2vector      indkey;                 /* column numbers of indexed cols, or 0 */
-       oidvector       indclass;               /* opclass identifiers */
        int2            indnatts;               /* number of columns in index */
        bool            indisunique;    /* is this a unique index? */
        bool            indisprimary;   /* is this index for primary key? */
        bool            indisclustered; /* is this the index last clustered by? */
 
        /* VARIABLE LENGTH FIELDS: */
+       int2vector      indkey;                 /* column numbers of indexed cols, or 0 */
+       oidvector       indclass;               /* opclass identifiers */
        text            indexprs;               /* expression trees for index attributes
                                                                 * that are not simple column references;
                                                                 * one for each zero entry in indkey[] */
@@ -64,12 +64,12 @@ typedef FormData_pg_index *Form_pg_index;
 #define Natts_pg_index                                 10
 #define Anum_pg_index_indexrelid               1
 #define Anum_pg_index_indrelid                 2
-#define Anum_pg_index_indkey                   3
-#define Anum_pg_index_indclass                 4
-#define Anum_pg_index_indnatts                 5
-#define Anum_pg_index_indisunique              6
-#define Anum_pg_index_indisprimary             7
-#define Anum_pg_index_indisclustered   8
+#define Anum_pg_index_indnatts                 3
+#define Anum_pg_index_indisunique              4
+#define Anum_pg_index_indisprimary             5
+#define Anum_pg_index_indisclustered   6
+#define Anum_pg_index_indkey                   7
+#define Anum_pg_index_indclass                 8
 #define Anum_pg_index_indexprs                 9
 #define Anum_pg_index_indpred                  10
 
index 63a339e..7477dca 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.354 2005/03/27 23:53:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.355 2005/03/29 00:17:17 tgl Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -48,7 +48,7 @@ CATALOG(pg_proc) BOOTSTRAP
        char            provolatile;    /* see PROVOLATILE_ categories below */
        int2            pronargs;               /* number of arguments */
        Oid                     prorettype;             /* OID of result type */
-       oidvector       proargtypes;    /* OIDs of argument types */
+       oidvector       proargtypes;    /* VARIABLE LENGTH FIELD */
        text            proargnames[1]; /* VARIABLE LENGTH FIELD */
        text            prosrc;                 /* VARIABLE LENGTH FIELD */
        bytea           probin;                 /* VARIABLE LENGTH FIELD */
index a59ecec..3f1754c 100644 (file)
@@ -38,12 +38,12 @@ CATALOG(pg_trigger)
        bool            tgisconstraint; /* trigger is a RI constraint */
        NameData        tgconstrname;   /* RI constraint name */
        Oid                     tgconstrrelid;  /* RI table of foreign key definition */
-
-       /* in the case of ON DELETE or ON UPDATE */
        bool            tgdeferrable;   /* RI trigger is deferrable */
        bool            tginitdeferred; /* RI trigger is deferred initially */
        int2            tgnargs;                /* # of extra arguments in tgargs */
-       int2vector      tgattr;                 /* UPDATE of attr1, attr2 ... (NI) */
+
+       /* VARIABLE LENGTH FIELDS: */
+       int2vector      tgattr;                 /* reserved for column-specific triggers */
        bytea           tgargs;                 /* first\000second\000tgnargs\000 */
 } FormData_pg_trigger;
 
index db7426b..7b6bd6a 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.158 2004/12/31 22:03:26 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.159 2005/03/29 00:17:17 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -88,7 +88,7 @@ CATALOG(pg_type) BOOTSTRAP
         * current type can then be subscripted like an array yielding values
         * of type typelem. A non-zero typelem does not guarantee this type to
         * be a "real" array type; some ordinary fixed-length types can also
-        * be subscripted (e.g., oidvector). Variable-length types can *not*
+        * be subscripted (e.g., name, point). Variable-length types can *not*
         * be turned into pseudo-arrays like that. Hence, the way to determine
         * whether a type is a "true" array type is if:
         *
@@ -268,8 +268,8 @@ DATA(insert OID = 21 (      int2       PGNSP PGUID  2 t b t \054 0   0 int2in int2out int2
 DESCR("-32 thousand to 32 thousand, 2-byte storage");
 #define INT2OID                        21
 
-DATA(insert OID = 22 ( int2vector PGNSP PGUID INDEX_MAX_KEYS*2 f b t \054 0  21 int2vectorin int2vectorout int2vectorrecv int2vectorsend - s p f 0 -1 0 _null_ _null_ ));
-DESCR("array of INDEX_MAX_KEYS int2 integers, used in system tables");
+DATA(insert OID = 22 ( int2vector PGNSP PGUID -1 f b t \054 0  21 int2vectorin int2vectorout int2vectorrecv int2vectorsend - i p f 0 -1 0 _null_ _null_ ));
+DESCR("array of int2, used in system tables");
 #define INT2VECTOROID  22
 
 DATA(insert OID = 23 ( int4       PGNSP PGUID  4 t b t \054 0   0 int4in int4out int4recv int4send - i p f 0 -1 0 _null_ _null_ ));
@@ -300,8 +300,8 @@ DATA(insert OID = 29 (      cid                PGNSP PGUID  4 t b t \054 0   0 cidin cidout cidrec
 DESCR("command identifier type, sequence in transaction id");
 #define CIDOID 29
 
-DATA(insert OID = 30 ( oidvector  PGNSP PGUID INDEX_MAX_KEYS*4 f b t \054 0  26 oidvectorin oidvectorout oidvectorrecv oidvectorsend - i p f 0 -1 0 _null_ _null_ ));
-DESCR("array of INDEX_MAX_KEYS oids, used in system tables");
+DATA(insert OID = 30 ( oidvector  PGNSP PGUID -1 f b t \054 0  26 oidvectorin oidvectorout oidvectorrecv oidvectorsend - i p f 0 -1 0 _null_ _null_ ));
+DESCR("array of oids, used in system tables");
 #define OIDVECTOROID   30
 
 DATA(insert OID = 71 ( pg_type                 PGNSP PGUID -1 f c t \054 1247 0 record_in record_out record_recv record_send - d x f 0 -1 0 _null_ _null_ ));
index df5cd28..92ff21b 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/array.h,v 1.53 2005/03/24 21:50:38 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/array.h,v 1.54 2005/03/29 00:17:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,6 +22,9 @@
 /*
  * Arrays are varlena objects, so must meet the varlena convention that
  * the first int32 of the object contains the total object size in bytes.
+ *
+ * CAUTION: if you change the header for ordinary arrays you will also
+ * need to change the headers for oidvector and int2vector!
  */
 typedef struct
 {
index 26edd72..4caa5b4 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.253 2005/02/27 08:31:30 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.254 2005/03/29 00:17:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -185,6 +185,7 @@ extern Datum int2shl(PG_FUNCTION_ARGS);
 extern Datum int2shr(PG_FUNCTION_ARGS);
 extern Datum generate_series_int4(PG_FUNCTION_ARGS);
 extern Datum generate_series_step_int4(PG_FUNCTION_ARGS);
+extern int2vector *buildint2vector(const int2 *int2s, int n);
 
 /* name.c */
 extern Datum namein(PG_FUNCTION_ARGS);
@@ -392,6 +393,7 @@ extern Datum oidvectorlt(PG_FUNCTION_ARGS);
 extern Datum oidvectorle(PG_FUNCTION_ARGS);
 extern Datum oidvectorge(PG_FUNCTION_ARGS);
 extern Datum oidvectorgt(PG_FUNCTION_ARGS);
+extern oidvector *buildoidvector(const Oid *oids, int n);
 
 /* pseudotypes.c */
 extern Datum cstring_in(PG_FUNCTION_ARGS);
index 100d6d1..1c5398a 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.94 2005/01/27 23:36:15 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.95 2005/03/29 00:17:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,7 +64,8 @@ extern RegProcedure get_oprrest(Oid opno);
 extern RegProcedure get_oprjoin(Oid opno);
 extern char *get_func_name(Oid funcid);
 extern Oid     get_func_rettype(Oid funcid);
-extern Oid     get_func_signature(Oid funcid, Oid *argtypes, int *nargs);
+extern int     get_func_nargs(Oid funcid);
+extern Oid     get_func_signature(Oid funcid, Oid **argtypes, int *nargs);
 extern bool get_func_retset(Oid funcid);
 extern bool func_strict(Oid funcid);
 extern char func_volatile(Oid funcid);
index 536651b..b6a1712 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.82 2005/01/10 20:02:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.83 2005/03/29 00:17:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,7 +58,8 @@ typedef struct Trigger
        bool            tgdeferrable;
        bool            tginitdeferred;
        int16           tgnargs;
-       int16           tgattr[FUNC_MAX_ARGS];
+       int16           tgnattr;
+       int16      *tgattr;
        char      **tgargs;
 } Trigger;
 
@@ -137,6 +138,7 @@ typedef struct RelationData
        Form_pg_index rd_index;         /* pg_index tuple describing this index */
        struct HeapTupleData *rd_indextuple;            /* all of pg_index tuple */
        /* "struct HeapTupleData *" avoids need to include htup.h here  */
+       oidvector  *rd_indclass;        /* extracted pointer to rd_index field */
        Form_pg_am      rd_am;                  /* pg_am tuple for index's AM */
 
        /*
index efc00c0..976788f 100644 (file)
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.58 2004/12/31 22:03:46 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.59 2005/03/29 00:17:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -52,7 +52,7 @@
 #define NAMESPACEOID   21
 #define OPERNAMENSP            22
 #define OPEROID                        23
-#define PROCNAMENSP            24
+#define PROCNAMEARGSNSP        24
 #define PROCOID                        25
 #define RELNAMENSP             26
 #define RELOID                 27
index 620448b..f9adb68 100644 (file)
@@ -33,7 +33,7 @@
  *       ENHANCEMENTS, OR MODIFICATIONS.
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.69 2005/02/23 04:34:05 momjian Exp $
+ *       $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.70 2005/03/29 00:17:20 tgl Exp $
  *
  **********************************************************************/
 
@@ -1300,14 +1300,14 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
                        for (i = 0; i < prodesc->nargs; i++)
                        {
                                typeTup = SearchSysCache(TYPEOID,
-                                                       ObjectIdGetDatum(procStruct->proargtypes[i]),
+                                                       ObjectIdGetDatum(procStruct->proargtypes.values[i]),
                                                                                 0, 0, 0);
                                if (!HeapTupleIsValid(typeTup))
                                {
                                        free(prodesc->proname);
                                        free(prodesc);
                                        elog(ERROR, "cache lookup failed for type %u",
-                                                procStruct->proargtypes[i]);
+                                                procStruct->proargtypes.values[i]);
                                }
                                typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
 
@@ -1319,7 +1319,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
                                        ereport(ERROR,
                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                                   errmsg("plperl functions cannot take type %s",
-                                                  format_type_be(procStruct->proargtypes[i]))));
+                                                  format_type_be(procStruct->proargtypes.values[i]))));
                                }
 
                                if (typeStruct->typtype == 'c')
index 6ae93b7..4d23062 100644 (file)
@@ -3,7 +3,7 @@
  *                       procedural language
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.84 2005/02/22 07:18:24 neilc Exp $
+ *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.85 2005/03/29 00:17:23 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -1843,7 +1843,7 @@ compute_function_hashkey(FunctionCallInfo fcinfo,
        /* get the argument types */
        for (i = 0; i < procStruct->pronargs; i++)
        {
-               Oid                     argtypeid = procStruct->proargtypes[i];
+               Oid                     argtypeid = procStruct->proargtypes.values[i];
 
                /*
                 * Check for polymorphic arguments. If found, use the actual
index 06e7342..c20efe7 100644 (file)
@@ -3,7 +3,7 @@
  *                       procedural language
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.24 2005/02/22 07:18:24 neilc Exp $
+ *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.25 2005/03/29 00:17:23 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -189,16 +189,16 @@ plpgsql_validator(PG_FUNCTION_ARGS)
        haspolyarg = false;
        for (i = 0; i < proc->pronargs; i++)
        {
-               if (get_typtype(proc->proargtypes[i]) == 'p')
+               if (get_typtype(proc->proargtypes.values[i]) == 'p')
                {
-                       if (proc->proargtypes[i] == ANYARRAYOID ||
-                               proc->proargtypes[i] == ANYELEMENTOID)
+                       if (proc->proargtypes.values[i] == ANYARRAYOID ||
+                               proc->proargtypes.values[i] == ANYELEMENTOID)
                                haspolyarg = true;
                        else
                                ereport(ERROR,
                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                                 errmsg("plpgsql functions cannot take type %s",
-                                                               format_type_be(proc->proargtypes[i]))));
+                                                               format_type_be(proc->proargtypes.values[i]))));
                }
        }
 
index 431396d..9fb4e11 100644 (file)
@@ -29,7 +29,7 @@
  * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * IDENTIFICATION
- *     $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.59 2005/03/24 17:22:34 tgl Exp $
+ *     $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.60 2005/03/29 00:17:24 tgl Exp $
  *
  *********************************************************************
  */
@@ -1082,11 +1082,11 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
                        Form_pg_type argTypeStruct;
 
                        argTypeTup = SearchSysCache(TYPEOID,
-                                                       ObjectIdGetDatum(procStruct->proargtypes[i]),
+                                                       ObjectIdGetDatum(procStruct->proargtypes.values[i]),
                                                                                0, 0, 0);
                        if (!HeapTupleIsValid(argTypeTup))
                                elog(ERROR, "cache lookup failed for type %u",
-                                        procStruct->proargtypes[i]);
+                                        procStruct->proargtypes.values[i]);
                        argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
 
                        /* Disallow pseudotype argument */
@@ -1094,11 +1094,11 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
                                ereport(ERROR,
                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                                 errmsg("plpython functions cannot take type %s",
-                                                               format_type_be(procStruct->proargtypes[i]))));
+                                                               format_type_be(procStruct->proargtypes.values[i]))));
 
                        if (argTypeStruct->typtype != 'c')
                                PLy_input_datum_func(&(proc->args[i]),
-                                                                        procStruct->proargtypes[i],
+                                                                        procStruct->proargtypes.values[i],
                                                                         argTypeTup);
                        else
                                proc->args[i].is_rowtype = 2;   /* still need to set I/O
index a953447..0bbd20f 100644 (file)
@@ -31,7 +31,7 @@
  *       ENHANCEMENTS, OR MODIFICATIONS.
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.94 2004/11/21 21:17:05 tgl Exp $
+ *       $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.95 2005/03/29 00:17:25 tgl Exp $
  *
  **********************************************************************/
 
@@ -1128,14 +1128,14 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid)
                        for (i = 0; i < prodesc->nargs; i++)
                        {
                                typeTup = SearchSysCache(TYPEOID,
-                                                       ObjectIdGetDatum(procStruct->proargtypes[i]),
+                                                       ObjectIdGetDatum(procStruct->proargtypes.values[i]),
                                                                                 0, 0, 0);
                                if (!HeapTupleIsValid(typeTup))
                                {
                                        free(prodesc->proname);
                                        free(prodesc);
                                        elog(ERROR, "cache lookup failed for type %u",
-                                                procStruct->proargtypes[i]);
+                                                procStruct->proargtypes.values[i]);
                                }
                                typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
 
@@ -1147,7 +1147,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid)
                                        ereport(ERROR,
                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                                         errmsg("pltcl functions cannot take type %s",
-                                                  format_type_be(procStruct->proargtypes[i]))));
+                                                  format_type_be(procStruct->proargtypes.values[i]))));
                                }
 
                                if (typeStruct->typtype == 'c')
index 937f179..8740b0e 100644 (file)
@@ -33,23 +33,13 @@ create function physically_coercible(oid, oid) returns bool as
 language sql;
 -- **************** pg_proc ****************
 -- Look for illegal values in pg_proc fields.
--- NOTE: in reality pronargs could be more than 10, but I'm too lazy to put
--- a larger number of proargtypes check clauses in here.  If we ever have
--- more-than-10-arg functions in the standard catalogs, extend this query.
 SELECT p1.oid, p1.proname
 FROM pg_proc as p1
 WHERE p1.prolang = 0 OR p1.prorettype = 0 OR
-       p1.pronargs < 0 OR p1.pronargs > 10 OR
-       (p1.proargtypes[0] = 0 AND p1.pronargs > 0) OR
-       (p1.proargtypes[1] = 0 AND p1.pronargs > 1) OR
-       (p1.proargtypes[2] = 0 AND p1.pronargs > 2) OR
-       (p1.proargtypes[3] = 0 AND p1.pronargs > 3) OR
-       (p1.proargtypes[4] = 0 AND p1.pronargs > 4) OR
-       (p1.proargtypes[5] = 0 AND p1.pronargs > 5) OR
-       (p1.proargtypes[6] = 0 AND p1.pronargs > 6) OR
-       (p1.proargtypes[7] = 0 AND p1.pronargs > 7) OR
-       (p1.proargtypes[8] = 0 AND p1.pronargs > 8) OR
-       (p1.proargtypes[9] = 0 AND p1.pronargs > 9);
+       p1.pronargs < 0 OR
+       array_lower(p1.proargtypes, 1) != 0 OR
+       array_upper(p1.proargtypes, 1) != p1.pronargs-1 OR
+       0::oid = ANY (p1.proargtypes);
  oid | proname 
 -----+---------
 (0 rows)
@@ -218,7 +208,7 @@ WHERE p1.oid != p2.oid AND
 SELECT p1.oid, p1.proname
 FROM pg_proc as p1
 WHERE p1.prorettype = 'internal'::regtype AND NOT
-    ('(' || oidvectortypes(p1.proargtypes) || ')') ~ '[^a-z0-9_]internal[^a-z0-9_]';
+    'internal'::regtype = ANY (p1.proargtypes);
  oid  |   proname   
 ------+-------------
  2304 | internal_in
index 58b8dc6..881220b 100644 (file)
@@ -106,14 +106,18 @@ ORDER BY 1;
 (1 row)
 
 -- Varlena array types will point to array_in
+-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
 SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND
     (p1.typelem != 0 AND p1.typlen < 0) AND NOT
-    (p2.oid = 'array_in'::regproc);
- oid | typname | oid | proname 
------+---------+-----+---------
-(0 rows)
+    (p2.oid = 'array_in'::regproc)
+ORDER BY 1;
+ oid |  typname   | oid |   proname    
+-----+------------+-----+--------------
+  22 | int2vector |  40 | int2vectorin
+  30 | oidvector  |  54 | oidvectorin
+(2 rows)
 
 -- Check for bogus typoutput routines
 -- As of 8.0, this check finds refcursor, which is borrowing
@@ -165,14 +169,18 @@ ORDER BY 1;
 (1 row)
 
 -- Varlena array types will point to array_recv
+-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
 SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND
     (p1.typelem != 0 AND p1.typlen < 0) AND NOT
-    (p2.oid = 'array_recv'::regproc);
- oid | typname | oid | proname 
------+---------+-----+---------
-(0 rows)
+    (p2.oid = 'array_recv'::regproc)
+ORDER BY 1;
+ oid |  typname   | oid  |    proname     
+-----+------------+------+----------------
+  22 | int2vector | 2410 | int2vectorrecv
+  30 | oidvector  | 2420 | oidvectorrecv
+(2 rows)
 
 -- Check for bogus typsend routines
 -- As of 7.4, this check finds refcursor, which is borrowing
@@ -203,7 +211,7 @@ WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
 -- Look for illegal values in pg_class fields
 SELECT p1.oid, p1.relname
 FROM pg_class as p1
-WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 't', 'v');
+WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 'c', 't', 'v');
  oid | relname 
 -----+---------
 (0 rows)
index 567eb89..84e9b9f 100644 (file)
@@ -39,24 +39,14 @@ language sql;
 -- **************** pg_proc ****************
 
 -- Look for illegal values in pg_proc fields.
--- NOTE: in reality pronargs could be more than 10, but I'm too lazy to put
--- a larger number of proargtypes check clauses in here.  If we ever have
--- more-than-10-arg functions in the standard catalogs, extend this query.
 
 SELECT p1.oid, p1.proname
 FROM pg_proc as p1
 WHERE p1.prolang = 0 OR p1.prorettype = 0 OR
-       p1.pronargs < 0 OR p1.pronargs > 10 OR
-       (p1.proargtypes[0] = 0 AND p1.pronargs > 0) OR
-       (p1.proargtypes[1] = 0 AND p1.pronargs > 1) OR
-       (p1.proargtypes[2] = 0 AND p1.pronargs > 2) OR
-       (p1.proargtypes[3] = 0 AND p1.pronargs > 3) OR
-       (p1.proargtypes[4] = 0 AND p1.pronargs > 4) OR
-       (p1.proargtypes[5] = 0 AND p1.pronargs > 5) OR
-       (p1.proargtypes[6] = 0 AND p1.pronargs > 6) OR
-       (p1.proargtypes[7] = 0 AND p1.pronargs > 7) OR
-       (p1.proargtypes[8] = 0 AND p1.pronargs > 8) OR
-       (p1.proargtypes[9] = 0 AND p1.pronargs > 9);
+       p1.pronargs < 0 OR
+       array_lower(p1.proargtypes, 1) != 0 OR
+       array_upper(p1.proargtypes, 1) != p1.pronargs-1 OR
+       0::oid = ANY (p1.proargtypes);
 
 -- Look for conflicting proc definitions (same names and input datatypes).
 -- (This test should be dead code now that we have the unique index
@@ -179,7 +169,7 @@ WHERE p1.oid != p2.oid AND
 SELECT p1.oid, p1.proname
 FROM pg_proc as p1
 WHERE p1.prorettype = 'internal'::regtype AND NOT
-    ('(' || oidvectortypes(p1.proargtypes) || ')') ~ '[^a-z0-9_]internal[^a-z0-9_]';
+    'internal'::regtype = ANY (p1.proargtypes);
 
 
 -- **************** pg_cast ****************
index 3e42112..81f8352 100644 (file)
@@ -88,11 +88,13 @@ WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
 ORDER BY 1;
 
 -- Varlena array types will point to array_in
+-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
 SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND
     (p1.typelem != 0 AND p1.typlen < 0) AND NOT
-    (p2.oid = 'array_in'::regproc);
+    (p2.oid = 'array_in'::regproc)
+ORDER BY 1;
 
 -- Check for bogus typoutput routines
 
@@ -132,11 +134,13 @@ WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND NOT
 ORDER BY 1;
 
 -- Varlena array types will point to array_recv
+-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
 SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND
     (p1.typelem != 0 AND p1.typlen < 0) AND NOT
-    (p2.oid = 'array_recv'::regproc);
+    (p2.oid = 'array_recv'::regproc)
+ORDER BY 1;
 
 -- Check for bogus typsend routines
 
@@ -163,7 +167,7 @@ WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
 
 SELECT p1.oid, p1.relname
 FROM pg_class as p1
-WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 't', 'v');
+WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 'c', 't', 'v');
 
 -- Indexes should have an access method, others not.