1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

Convert oidvector and int2vector into variable-length arrays. This

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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