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);
{
Oid relid;
text *relname_text;
- int16 *pkattnums;
+ int2vector *pkattnums;
int pknumatts_tmp;
int16 pknumatts = 0;
char **src_pkattvals;
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;
{
Oid relid;
text *relname_text;
- int16 *pkattnums;
+ int2vector *pkattnums;
int pknumatts_tmp;
int16 pknumatts = 0;
char **tgt_pkattvals;
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;
{
Oid relid;
text *relname_text;
- int16 *pkattnums;
+ int2vector *pkattnums;
int pknumatts_tmp;
int16 pknumatts = 0;
char **src_pkattvals;
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;
/* 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;
}
}
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;
}
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;
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 ");
}
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;
for (i = 0; i < pknumatts; i++)
{
- int16 pkattnum = pkattnums[i];
+ int16 pkattnum = pkattnums->values[i];
if (i > 0)
appendStringInfo(str, " AND ");
}
static int16
-get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key)
+get_attnum_pk_pos(int2vector *pkattnums, int16 pknumatts, int16 key)
{
int i;
* 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;
for (i = 0; i < pknumatts; i++)
{
- int16 pkattnum = pkattnums[i];
+ int16 pkattnum = pkattnums->values[i];
if (i > 0)
appendStringInfo(str, " AND ");
/****************************************************************************
* 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.
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;
}
}
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 */
/* 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;
<!--
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">
<entry>The OID of the <structname>pg_class</> entry for the table this index is for</entry>
</row>
- <row>
- <entry><structfield>indkey</structfield></entry>
- <entry><type>int2vector</type></entry>
- <entry><literal><link linkend="catalog-pg-attribute"><structname>pg_attribute</structname></link>.attnum</literal></entry>
- <entry>
- This is an array of <structfield>indnatts</structfield> (up to
- <symbol>INDEX_MAX_KEYS</symbol>) values that indicate which
- table columns this index indexes. For example a value of
- <literal>1 3</literal> would mean that the first and the third table
- columns make up the index key. A zero in this array indicates that the
- corresponding index attribute is an expression over the table columns,
- rather than a simple column reference.
- </entry>
- </row>
-
- <row>
- <entry><structfield>indclass</structfield></entry>
- <entry><type>oidvector</type></entry>
- <entry><literal><link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link>.oid</literal></entry>
- <entry>
- For each column in the index key this contains the OID of
- the operator class to use. See
- <structname>pg_opclass</structname> for details.
- </entry>
- </row>
-
<row>
<entry><structfield>indnatts</structfield></entry>
<entry><type>int2</type></entry>
<entry>If true, the table was last clustered on this index.</entry>
</row>
+ <row>
+ <entry><structfield>indkey</structfield></entry>
+ <entry><type>int2vector</type></entry>
+ <entry><literal><link linkend="catalog-pg-attribute"><structname>pg_attribute</structname></link>.attnum</literal></entry>
+ <entry>
+ This is an array of <structfield>indnatts</structfield> values that
+ indicate which table columns this index indexes. For example a value
+ of <literal>1 3</literal> would mean that the first and the third table
+ columns make up the index key. A zero in this array indicates that the
+ corresponding index attribute is an expression over the table columns,
+ rather than a simple column reference.
+ </entry>
+ </row>
+
+ <row>
+ <entry><structfield>indclass</structfield></entry>
+ <entry><type>oidvector</type></entry>
+ <entry><literal><link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link>.oid</literal></entry>
+ <entry>
+ For each column in the index key this contains the OID of
+ the operator class to use. See
+ <structname>pg_opclass</structname> for details.
+ </entry>
+ </row>
+
<row>
<entry><structfield>indexprs</structfield></entry>
<entry><type>text</type></entry>
(<structfield>typlen</structfield> = -1),
but some fixed-length (<structfield>typlen</structfield> > 0) types
also have nonzero <structfield>typelem</structfield>, for example
- <type>name</type> and <type>oidvector</type>.
+ <type>name</type> and <type>point</type>.
If a fixed-length type has a <structfield>typelem</structfield> then
its internal representation must be some number of values of the
<structfield>typelem</structfield> data type with no other data.
<!--
-$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">
bool tgdeferrable;
bool tginitdeferred;
int16 tgnargs;
- int16 tgattr[FUNC_MAX_ARGS];
+ int16 tgnattr;
+ int16 *tgattr;
char **tgargs;
} Trigger;
</programlisting>
*
*
* 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
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
*
*
* 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
*/
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;
}
*
*
* 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
*
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);
* 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 $
*
*-------------------------------------------------------------------------
*/
{
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,
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
* 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 $
*
*-------------------------------------------------------------------------
*/
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},
void
DefineAttr(char *name, char *type, int attnum)
{
- int attlen;
Oid typeoid;
if (boot_reldesc != NULL)
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;
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;
* 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)
#
#
# 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.
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
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.$$
# ----------------
-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..
*
*
* 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
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];
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
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';
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);
*
* 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 $
*/
/*
* 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
/* 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'
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;
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)
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;
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
* 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 $
*
*-------------------------------------------------------------------------
*/
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))
{
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;
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;
}
}
*/
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;
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? */
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
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);
* 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.
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 */
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))
{
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);
}
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]))));
}
}
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);
*
*
* 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
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,
errmsg("function %s already exists in schema \"%s\"",
funcname_signature_string(newname,
procForm->pronargs,
- procForm->proargtypes),
+ procForm->proargtypes.values),
get_namespace_name(namespaceOid))));
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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 */
*
*
* 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
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))));
}
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);
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")));
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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")));
* 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;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
for (i = 0; i < indexform->indnatts; i++)
{
- if (attnum != indexform->indkey[i])
+ if (attnum != indexform->indkey.values[i])
continue;
/*
* 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)
{
*/
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",
ListCell *indexoidscan;
HeapTuple indexTuple = NULL;
Form_pg_index indexStruct = NULL;
+ Datum indclassDatum;
+ bool isnull;
+ oidvector *indclass;
int i;
/*
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)
*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)))));
}
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.
found = false;
for (j = 0; j < numattrs; j++)
{
- if (attnums[i] == indexStruct->indkey[j])
+ if (attnums[i] == indexStruct->indkey.values[j])
{
found = true;
break;
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;
}
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
ScanKeyData key;
Relation pgrel;
HeapTuple tuple;
- Oid fargtypes[FUNC_MAX_ARGS];
+ Oid fargtypes[1]; /* dummy */
Oid funcoid;
Oid funcrettype;
Oid trigoid;
/*
* 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)
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);
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;
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));
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;
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)
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)
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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++)
* 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 $
*
*-------------------------------------------------------------------------
*/
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 */
*
*
* 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
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);
}
/*
{
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;
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.
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,
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
* 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)
{
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;
*
*
* 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.
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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
*
*
* 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()
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* 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 */
/*
* 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';
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);
*
*
* 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"
#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
+#define Int2VectorSize(n) (offsetof(int2vector, values) + (n) * sizeof(int2))
+
typedef struct
{
int32 current;
}
/*
- * 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++;
(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);
}
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')
;
}
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);
}
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);
}
/*
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);
}
*
*
* 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 *
*****************************************************************************/
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++;
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);
}
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')
;
}
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);
}
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);
}
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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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)))
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, ',');
* 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.
*
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);
Oid indrelid;
int keyno;
Oid keycoltype;
+ Datum indclassDatum;
+ bool isnull;
+ oidvector *indclass;
StringInfoData buf;
char *str;
char *sep;
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
*/
sep = "";
for (keyno = 0; keyno < idxrec->indnatts; keyno++)
{
- AttrNumber attnum = idxrec->indkey[keyno];
+ AttrNumber attnum = idxrec->indkey.values[keyno];
if (!colno)
appendStringInfo(&buf, sep);
* Add the operator class name
*/
if (!colno)
- get_opclass_name(idxrec->indclass[keyno], keycoltype,
+ get_opclass_name(indclass->values[keyno], keycoltype,
&buf);
}
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++;
}
* 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.
return result;
}
+/*
+ * get_func_nargs
+ * Given procedure id, return the number of arguments.
+ */
+int
+get_func_nargs(Oid funcid)
+{
+ HeapTuple tp;
+ int result;
+
+ tp = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(funcid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tp))
+ elog(ERROR, "cache lookup failed for function %u", funcid);
+
+ result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
+ ReleaseSysCache(tp);
+ return result;
+}
+
/*
* get_func_signature
* Given procedure id, return the function's argument and result types.
* (The return value is the result type.)
*
- * argtypes must point to a vector of size FUNC_MAX_ARGS.
+ * The arguments are returned as a palloc'd array.
*/
Oid
-get_func_signature(Oid funcid, Oid *argtypes, int *nargs)
+get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
{
HeapTuple tp;
Form_pg_proc procstruct;
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
#include "postgres.h"
-#include <errno.h>
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
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
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,
{
HeapTuple tuple;
Form_pg_am aform;
+ Datum indclassDatum;
+ bool isnull;
MemoryContext indexcxt;
MemoryContext oldcontext;
Oid *operator;
MemoryContextSwitchTo(oldcontext);
ReleaseSysCache(tuple);
+ /*
+ * indclass cannot be referenced directly through the C struct, because
+ * it is after the variable-width indkey field. Therefore we extract
+ * the datum the hard way and provide a direct link in the relcache.
+ */
+ indclassDatum = fastgetattr(relation->rd_indextuple,
+ Anum_pg_index_indclass,
+ GetPgIndexDescriptor(),
+ &isnull);
+ Assert(!isnull);
+ relation->rd_indclass = (oidvector *) DatumGetPointer(indclassDatum);
+
/*
* Make a copy of the pg_am entry for the index's access method
*/
* 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);
/*
* 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.
* access method.
*/
static void
-IndexSupportInitialize(Form_pg_index iform,
+IndexSupportInitialize(oidvector *indclass,
Oid *indexOperator,
RegProcedure *indexSupport,
StrategyNumber maxStrategyNumber,
{
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);
}
}
+/*
+ * 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)
{
* 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);
* 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);
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))
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;
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);
*
*
* 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
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,
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
for (i = 0; i < procedureStruct->pronargs; i++)
{
fnextra->arg_toastable[i] =
- TypeIsToastable(procedureStruct->proargtypes[i]);
+ TypeIsToastable(procedureStruct->proargtypes.values[i]);
}
break;
case 1:
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200503271
+#define CATALOG_VERSION_NO 200503281
#endif
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
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));
* 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
{ 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 }, \
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));
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
* 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
{
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[] */
#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
* 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
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 */
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;
* 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
* 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:
*
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_ ));
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_ ));
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* 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
{
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
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);
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
* 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 $
*
*-------------------------------------------------------------------------
*/
bool tgdeferrable;
bool tginitdeferred;
int16 tgnargs;
- int16 tgattr[FUNC_MAX_ARGS];
+ int16 tgnattr;
+ int16 *tgattr;
char **tgargs;
} Trigger;
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 */
/*
* 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 $
*
*-------------------------------------------------------------------------
*/
#define NAMESPACEOID 21
#define OPERNAMENSP 22
#define OPEROID 23
-#define PROCNAMENSP 24
+#define PROCNAMEARGSNSP 24
#define PROCOID 25
#define RELNAMENSP 26
#define RELOID 27
* 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 $
*
**********************************************************************/
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);
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')
* 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.
*
/* 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
* 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.
*
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]))));
}
}
* 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 $
*
*********************************************************************
*/
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 */
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
* 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 $
*
**********************************************************************/
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);
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')
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)
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
(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
(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
-- 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)
-- **************** 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
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 ****************
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
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
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.