diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-03-29 00:17:27 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-03-29 00:17:27 +0000 |
commit | 70c9763d4815ac847f0f7694f43eb6a59a236868 (patch) | |
tree | 7d8aa05f668f1ef7809ff521b6c1e12d31125fd7 /src/backend/utils/adt/int.c | |
parent | 119191609c507528b20d74c59be69f2129127575 (diff) | |
download | postgresql-70c9763d4815ac847f0f7694f43eb6a59a236868.tar.gz postgresql-70c9763d4815ac847f0f7694f43eb6a59a236868.zip |
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.
Diffstat (limited to 'src/backend/utils/adt/int.c')
-rw-r--r-- | src/backend/utils/adt/int.c | 105 |
1 files changed, 70 insertions, 35 deletions
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c index db36ac963e1..d00a7d166ae 100644 --- a/src/backend/utils/adt/int.c +++ b/src/backend/utils/adt/int.c @@ -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; + + result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS)); - for (slot = 0; *intString && slot < INDEX_MAX_KEYS; slot++) + for (n = 0; *intString && n < FUNC_MAX_ARGS; n++) { - if (sscanf(intString, "%hd", &result[slot]) != 1) + if (sscanf(intString, "%hd", &result->values[n]) != 1) break; while (*intString && isspace((unsigned char) *intString)) intString++; @@ -136,8 +169,12 @@ int2vectorin(PG_FUNCTION_ARGS) (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("int2vector has too many elements"))); - while (slot < INDEX_MAX_KEYS) - result[slot++] = 0; + result->size = Int2VectorSize(n); + result->ndim = 1; + result->flags = 0; + result->elemtype = INT2OID; + result->dim1 = n; + result->lbound1 = 0; PG_RETURN_POINTER(result); } @@ -148,24 +185,19 @@ int2vectorin(PG_FUNCTION_ARGS) Datum int2vectorout(PG_FUNCTION_ARGS) { - int16 *int2Array = (int16 *) PG_GETARG_POINTER(0); + int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0); int num, - maxnum; + nnums = int2Array->dim1; char *rp; char *result; - /* find last non-zero value in vector */ - for (maxnum = INDEX_MAX_KEYS - 1; maxnum >= 0; maxnum--) - if (int2Array[maxnum] != 0) - break; - /* assumes sign, 5 digits, ' ' */ - rp = result = (char *) palloc((maxnum + 1) * 7 + 1); - for (num = 0; num <= maxnum; num++) + rp = result = (char *) palloc(nnums * 7 + 1); + for (num = 0; num < nnums; num++) { if (num != 0) *rp++ = ' '; - pg_itoa(int2Array[num], rp); + pg_itoa(int2Array->values[num], rp); while (*++rp != '\0') ; } @@ -180,11 +212,19 @@ Datum int2vectorrecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); - int16 *result = (int16 *) palloc(sizeof(int16[INDEX_MAX_KEYS])); - int slot; - - for (slot = 0; slot < INDEX_MAX_KEYS; slot++) - result[slot] = (int16) pq_getmsgint(buf, sizeof(int16)); + int2vector *result; + + result = (int2vector *) + DatumGetPointer(DirectFunctionCall2(array_recv, + PointerGetDatum(buf), + ObjectIdGetDatum(INT2OID))); + /* sanity checks: int2vector must be 1-D, no nulls */ + if (result->ndim != 1 || + result->flags != 0 || + result->elemtype != INT2OID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("invalid int2vector data"))); PG_RETURN_POINTER(result); } @@ -194,14 +234,7 @@ int2vectorrecv(PG_FUNCTION_ARGS) Datum int2vectorsend(PG_FUNCTION_ARGS) { - int16 *int2Array = (int16 *) PG_GETARG_POINTER(0); - StringInfoData buf; - int slot; - - pq_begintypsend(&buf); - for (slot = 0; slot < INDEX_MAX_KEYS; slot++) - pq_sendint(&buf, int2Array[slot], sizeof(int16)); - PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); + return array_send(fcinfo); } /* @@ -211,10 +244,12 @@ int2vectorsend(PG_FUNCTION_ARGS) Datum int2vectoreq(PG_FUNCTION_ARGS) { - int16 *arg1 = (int16 *) PG_GETARG_POINTER(0); - int16 *arg2 = (int16 *) PG_GETARG_POINTER(1); + int2vector *a = (int2vector *) PG_GETARG_POINTER(0); + int2vector *b = (int2vector *) PG_GETARG_POINTER(1); - PG_RETURN_BOOL(memcmp(arg1, arg2, INDEX_MAX_KEYS * sizeof(int16)) == 0); + if (a->dim1 != b->dim1) + PG_RETURN_BOOL(false); + PG_RETURN_BOOL(memcmp(a->values, b->values, a->dim1 * sizeof(int2)) == 0); } |