From: Tom Lane Date: Mon, 26 Aug 2002 17:54:02 +0000 (+0000) Subject: Modify array operations to include array's element type OID in the X-Git-Tag: REL7_3~777 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5cabcfccce4b8b826c9b30828f3012b7926a6946;p=postgresql Modify array operations to include array's element type OID in the array header, and to compute sizing and alignment of array elements the same way normal tuple access operations do --- viz, using the tupmacs.h macros att_addlength and att_align. This makes the world safe for arrays of cstrings or intervals, and should make it much easier to write array-type-polymorphic functions; as examples see the cleanups of array_out and contrib/array_iterator. By Joe Conway and Tom Lane. --- diff --git a/contrib/array/README.array_iterator b/contrib/array/README.array_iterator index b072ebe397..b9e037ed85 100644 --- a/contrib/array/README.array_iterator +++ b/contrib/array/README.array_iterator @@ -41,9 +41,9 @@ attribute equal to a given value or matching a regular expression: The scheme is quite general, each operator which operates on a base type can be iterated over the elements of an array. It seem to work well but -defining each new operators requires writing a different C function. -Furthermore in each function there are two hardcoded OIDs which reference -a base type and a procedure. Not very portable. Can anyone suggest a -better and more portable way to do it ? +defining each new operator requires writing a different C function. +This is tedious, and error-prone since one must take care that the correct +datatypes are associated with the selected underlying function. +Can anyone suggest a better and more portable way to do it ? See also array_iterator.sql for an example on how to use this module. diff --git a/contrib/array/array_iterator.c b/contrib/array/array_iterator.c index 5616350b3a..d2a9a3271e 100644 --- a/contrib/array/array_iterator.c +++ b/contrib/array/array_iterator.c @@ -27,6 +27,7 @@ #include "miscadmin.h" #include "utils/array.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" #include "utils/memutils.h" #include "utils/lsyscache.h" @@ -34,10 +35,12 @@ static int32 -array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value) +array_iterator(Oid proc, int and, ArrayType *array, Datum value) { + Oid elemtype; int16 typlen; bool typbyval; + char typalign; int nitems, i; Datum result; @@ -63,7 +66,8 @@ array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value) return (0); /* Lookup element type information */ - get_typlenbyval(elemtype, &typlen, &typbyval); + elemtype = ARR_ELEMTYPE(array); + get_typlenbyvalalign(elemtype, &typlen, &typbyval, &typalign); /* Lookup the function entry point */ fmgr_info(proc, &finfo); @@ -82,10 +86,8 @@ array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value) itemvalue = fetch_att(p, typbyval, typlen); - if (typlen > 0) - p += typlen; - else - p += INTALIGN(*(int32 *) p); + p = att_addlength(p, typlen, PointerGetDatum(p)); + p = (char *) att_align(p, typalign); result = FunctionCall2(&finfo, itemvalue, value); @@ -112,37 +114,33 @@ array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value) */ int32 -array_texteq(ArrayType *array, char *value) +array_texteq(ArrayType *array, void *value) { - return array_iterator((Oid) 25, /* text */ - (Oid) 67, /* texteq */ + return array_iterator(F_TEXTEQ, 0, /* logical or */ array, (Datum) value); } int32 -array_all_texteq(ArrayType *array, char *value) +array_all_texteq(ArrayType *array, void *value) { - return array_iterator((Oid) 25, /* text */ - (Oid) 67, /* texteq */ + return array_iterator(F_TEXTEQ, 1, /* logical and */ array, (Datum) value); } int32 -array_textregexeq(ArrayType *array, char *value) +array_textregexeq(ArrayType *array, void *value) { - return array_iterator((Oid) 25, /* text */ - (Oid) 1254, /* textregexeq */ + return array_iterator(F_TEXTREGEXEQ, 0, /* logical or */ array, (Datum) value); } int32 -array_all_textregexeq(ArrayType *array, char *value) +array_all_textregexeq(ArrayType *array, void *value) { - return array_iterator((Oid) 25, /* text */ - (Oid) 1254, /* textregexeq */ + return array_iterator(F_TEXTREGEXEQ, 1, /* logical and */ array, (Datum) value); } @@ -153,37 +151,33 @@ array_all_textregexeq(ArrayType *array, char *value) */ int32 -array_varchareq(ArrayType *array, char *value) +array_varchareq(ArrayType *array, void *value) { - return array_iterator((Oid) 1043, /* varchar */ - (Oid) 1070, /* varchareq */ + return array_iterator(F_VARCHAREQ, 0, /* logical or */ array, (Datum) value); } int32 -array_all_varchareq(ArrayType *array, char *value) +array_all_varchareq(ArrayType *array, void *value) { - return array_iterator((Oid) 1043, /* varchar */ - (Oid) 1070, /* varchareq */ + return array_iterator(F_VARCHAREQ, 1, /* logical and */ array, (Datum) value); } int32 -array_varcharregexeq(ArrayType *array, char *value) +array_varcharregexeq(ArrayType *array, void *value) { - return array_iterator((Oid) 1043, /* varchar */ - (Oid) 1254, /* textregexeq */ + return array_iterator(F_TEXTREGEXEQ, 0, /* logical or */ array, (Datum) value); } int32 -array_all_varcharregexeq(ArrayType *array, char *value) +array_all_varcharregexeq(ArrayType *array, void *value) { - return array_iterator((Oid) 1043, /* varchar */ - (Oid) 1254, /* textregexeq */ + return array_iterator(F_TEXTREGEXEQ, 1, /* logical and */ array, (Datum) value); } @@ -194,37 +188,33 @@ array_all_varcharregexeq(ArrayType *array, char *value) */ int32 -array_bpchareq(ArrayType *array, char *value) +array_bpchareq(ArrayType *array, void *value) { - return array_iterator((Oid) 1042, /* bpchar */ - (Oid) 1048, /* bpchareq */ + return array_iterator(F_BPCHAREQ, 0, /* logical or */ array, (Datum) value); } int32 -array_all_bpchareq(ArrayType *array, char *value) +array_all_bpchareq(ArrayType *array, void *value) { - return array_iterator((Oid) 1042, /* bpchar */ - (Oid) 1048, /* bpchareq */ + return array_iterator(F_BPCHAREQ, 1, /* logical and */ array, (Datum) value); } int32 -array_bpcharregexeq(ArrayType *array, char *value) +array_bpcharregexeq(ArrayType *array, void *value) { - return array_iterator((Oid) 1042, /* bpchar */ - (Oid) 1254, /* textregexeq */ + return array_iterator(F_TEXTREGEXEQ, 0, /* logical or */ array, (Datum) value); } int32 -array_all_bpcharregexeq(ArrayType *array, char *value) +array_all_bpcharregexeq(ArrayType *array, void *value) { - return array_iterator((Oid) 1042, /* bpchar */ - (Oid) 1254, /* textregexeq */ + return array_iterator(F_TEXTREGEXEQ, 1, /* logical and */ array, (Datum) value); } @@ -236,8 +226,7 @@ array_all_bpcharregexeq(ArrayType *array, char *value) int32 array_int4eq(ArrayType *array, int4 value) { - return array_iterator((Oid) 23, /* int4 */ - (Oid) 65, /* int4eq */ + return array_iterator(F_INT4EQ, 0, /* logical or */ array, (Datum) value); } @@ -245,8 +234,7 @@ array_int4eq(ArrayType *array, int4 value) int32 array_all_int4eq(ArrayType *array, int4 value) { - return array_iterator((Oid) 23, /* int4 */ - (Oid) 65, /* int4eq */ + return array_iterator(F_INT4EQ, 1, /* logical and */ array, (Datum) value); } @@ -254,8 +242,7 @@ array_all_int4eq(ArrayType *array, int4 value) int32 array_int4ne(ArrayType *array, int4 value) { - return array_iterator((Oid) 23, /* int4 */ - (Oid) 144, /* int4ne */ + return array_iterator(F_INT4NE, 0, /* logical or */ array, (Datum) value); } @@ -263,8 +250,7 @@ array_int4ne(ArrayType *array, int4 value) int32 array_all_int4ne(ArrayType *array, int4 value) { - return array_iterator((Oid) 23, /* int4 */ - (Oid) 144, /* int4ne */ + return array_iterator(F_INT4NE, 1, /* logical and */ array, (Datum) value); } @@ -272,8 +258,7 @@ array_all_int4ne(ArrayType *array, int4 value) int32 array_int4gt(ArrayType *array, int4 value) { - return array_iterator((Oid) 23, /* int4 */ - (Oid) 147, /* int4gt */ + return array_iterator(F_INT4GT, 0, /* logical or */ array, (Datum) value); } @@ -281,8 +266,7 @@ array_int4gt(ArrayType *array, int4 value) int32 array_all_int4gt(ArrayType *array, int4 value) { - return array_iterator((Oid) 23, /* int4 */ - (Oid) 147, /* int4gt */ + return array_iterator(F_INT4GT, 1, /* logical and */ array, (Datum) value); } @@ -290,8 +274,7 @@ array_all_int4gt(ArrayType *array, int4 value) int32 array_int4ge(ArrayType *array, int4 value) { - return array_iterator((Oid) 23, /* int4 */ - (Oid) 150, /* int4ge */ + return array_iterator(F_INT4GE, 0, /* logical or */ array, (Datum) value); } @@ -299,8 +282,7 @@ array_int4ge(ArrayType *array, int4 value) int32 array_all_int4ge(ArrayType *array, int4 value) { - return array_iterator((Oid) 23, /* int4 */ - (Oid) 150, /* int4ge */ + return array_iterator(F_INT4GE, 1, /* logical and */ array, (Datum) value); } @@ -308,8 +290,7 @@ array_all_int4ge(ArrayType *array, int4 value) int32 array_int4lt(ArrayType *array, int4 value) { - return array_iterator((Oid) 23, /* int4 */ - (Oid) 66, /* int4lt */ + return array_iterator(F_INT4LT, 0, /* logical or */ array, (Datum) value); } @@ -317,8 +298,7 @@ array_int4lt(ArrayType *array, int4 value) int32 array_all_int4lt(ArrayType *array, int4 value) { - return array_iterator((Oid) 23, /* int4 */ - (Oid) 66, /* int4lt */ + return array_iterator(F_INT4LT, 1, /* logical and */ array, (Datum) value); } @@ -326,8 +306,7 @@ array_all_int4lt(ArrayType *array, int4 value) int32 array_int4le(ArrayType *array, int4 value) { - return array_iterator((Oid) 23, /* int4 */ - (Oid) 149, /* int4le */ + return array_iterator(F_INT4LE, 0, /* logical or */ array, (Datum) value); } @@ -335,8 +314,7 @@ array_int4le(ArrayType *array, int4 value) int32 array_all_int4le(ArrayType *array, int4 value) { - return array_iterator((Oid) 23, /* int4 */ - (Oid) 149, /* int4le */ + return array_iterator(F_INT4LE, 1, /* logical and */ array, (Datum) value); } @@ -346,8 +324,7 @@ array_all_int4le(ArrayType *array, int4 value) int32 array_oideq(ArrayType *array, Oid value) { - return array_iterator((Oid) 26, /* oid */ - (Oid) 184, /* oideq */ + return array_iterator(F_OIDEQ, 0, /* logical or */ array, (Datum) value); } @@ -355,52 +332,39 @@ array_oideq(ArrayType *array, Oid value) int32 array_all_oidne(ArrayType *array, Oid value) { - return array_iterator((Oid) 26, /* int4 */ - (Oid) 185, /* oidne */ + return array_iterator(F_OIDNE, 1, /* logical and */ array, (Datum) value); } int32 -array_ineteq(ArrayType *array, Oid value) +array_ineteq(ArrayType *array, void *value) { - return array_iterator((Oid) 869, /* inet */ - (Oid) 920, /* network_eq */ + return array_iterator(F_NETWORK_EQ, 0, /* logical or */ array, (Datum) value); } int32 -array_all_ineteq(ArrayType *array, Oid value) +array_all_ineteq(ArrayType *array, void *value) { - return array_iterator((Oid) 869, /* inet */ - (Oid) 920, /* network_eq */ + return array_iterator(F_NETWORK_EQ, 1, /* logical and */ array, (Datum) value); } int32 -array_inetne(ArrayType *array, Oid value) +array_inetne(ArrayType *array, void *value) { - return array_iterator((Oid) 869, /* inet */ - (Oid) 925, /* network_ne */ + return array_iterator(F_NETWORK_NE, 0, /* logical and */ array, (Datum) value); } int32 -array_all_inetne(ArrayType *array, Oid value) +array_all_inetne(ArrayType *array, void *value) { - return array_iterator((Oid) 869, /* inet */ - (Oid) 925, /* network_ne */ + return array_iterator(F_NETWORK_NE, 1, /* logical and */ array, (Datum) value); } - -/* - * Local Variables: - * tab-width: 4 - * c-indent-level: 4 - * c-basic-offset: 4 - * End: - */ diff --git a/contrib/array/array_iterator.h b/contrib/array/array_iterator.h index f959f09c7c..c85d68f27a 100644 --- a/contrib/array/array_iterator.h +++ b/contrib/array/array_iterator.h @@ -1,23 +1,23 @@ #ifndef ARRAY_ITERATOR_H #define ARRAY_ITERATOR_H -static int32 array_iterator(Oid elemtype, Oid proc, int and, +static int32 array_iterator(Oid proc, int and, ArrayType *array, Datum value); -int32 array_texteq(ArrayType *array, char *value); -int32 array_all_texteq(ArrayType *array, char *value); -int32 array_textregexeq(ArrayType *array, char *value); -int32 array_all_textregexeq(ArrayType *array, char *value); +int32 array_texteq(ArrayType *array, void *value); +int32 array_all_texteq(ArrayType *array, void *value); +int32 array_textregexeq(ArrayType *array, void *value); +int32 array_all_textregexeq(ArrayType *array, void *value); -int32 array_varchareq(ArrayType *array, char *value); -int32 array_all_varchareq(ArrayType *array, char *value); -int32 array_varcharregexeq(ArrayType *array, char *value); -int32 array_all_varcharregexeq(ArrayType *array, char *value); +int32 array_varchareq(ArrayType *array, void *value); +int32 array_all_varchareq(ArrayType *array, void *value); +int32 array_varcharregexeq(ArrayType *array, void *value); +int32 array_all_varcharregexeq(ArrayType *array, void *value); -int32 array_bpchareq(ArrayType *array, char *value); -int32 array_all_bpchareq(ArrayType *array, char *value); -int32 array_bpcharregexeq(ArrayType *array, char *value); -int32 array_all_bpcharregexeq(ArrayType *array, char *value); +int32 array_bpchareq(ArrayType *array, void *value); +int32 array_all_bpchareq(ArrayType *array, void *value); +int32 array_bpcharregexeq(ArrayType *array, void *value); +int32 array_all_bpcharregexeq(ArrayType *array, void *value); int32 array_int4eq(ArrayType *array, int4 value); int32 array_all_int4eq(ArrayType *array, int4 value); @@ -35,16 +35,9 @@ int32 array_all_int4le(ArrayType *array, int4 value); int32 array_oideq(ArrayType *array, Oid value); int32 array_all_oidne(ArrayType *array, Oid value); -int32 array_ineteq(ArrayType *array, Oid value); -int32 array_all_ineteq(ArrayType *array, Oid value); -int32 array_inetne(ArrayType *array, Oid value); -int32 array_all_inetne(ArrayType *array, Oid value); -#endif +int32 array_ineteq(ArrayType *array, void *value); +int32 array_all_ineteq(ArrayType *array, void *value); +int32 array_inetne(ArrayType *array, void *value); +int32 array_all_inetne(ArrayType *array, void *value); -/* - * Local Variables: - * tab-width: 4 - * c-indent-level: 4 - * c-basic-offset: 4 - * End: - */ +#endif diff --git a/contrib/array/array_iterator.sql.in b/contrib/array/array_iterator.sql.in index 806d010e72..342d728f9a 100644 --- a/contrib/array/array_iterator.sql.in +++ b/contrib/array/array_iterator.sql.in @@ -4,19 +4,19 @@ -- create or replace function array_texteq(_text, text) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_texteq(_text, text) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_textregexeq(_text, text) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_textregexeq(_text, text) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create operator *= ( leftarg=_text, @@ -45,19 +45,19 @@ create operator **~ ( -- create or replace function array_varchareq(_varchar, varchar) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_varchareq(_varchar, varchar) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_varcharregexeq(_varchar, varchar) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_varcharregexeq(_varchar, varchar) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create operator *= ( leftarg=_varchar, @@ -84,19 +84,19 @@ create operator **~ ( -- create or replace function array_bpchareq(_bpchar, bpchar) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_bpchareq(_bpchar, bpchar) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_bpcharregexeq(_bpchar, bpchar) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_bpcharregexeq(_bpchar, bpchar) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create operator *= ( leftarg=_bpchar, @@ -123,51 +123,51 @@ create operator **~ ( -- create or replace function array_int4eq(_int4, int4) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_int4eq(_int4, int4) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_int4ne(_int4, int4) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_int4ne(_int4, int4) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_int4gt(_int4, int4) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_int4gt(_int4, int4) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_int4ge(_int4, int4) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_int4ge(_int4, int4) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_int4lt(_int4, int4) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_int4lt(_int4, int4) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_int4le(_int4, int4) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_int4le(_int4, int4) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create operator *= ( leftarg=_int4, @@ -233,11 +233,11 @@ create operator **<= ( -- create or replace function array_oideq(_oid, oid) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_oidne(_oid, oid) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create operator *= ( leftarg=_oid, @@ -253,19 +253,19 @@ create operator **<> ( create or replace function array_ineteq(_inet, inet) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_ineteq(_inet, inet) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_inetne(_inet, inet) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create or replace function array_all_inetne(_inet, inet) returns bool as 'MODULE_PATHNAME' - language 'c'; + language C with (isStrict); create operator *= ( leftarg=_inet, diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index d396f070dd..0401e06f4f 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -502,6 +502,7 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS) /* * get array of pointers to c-strings from the input source array */ + Assert(ARR_ELEMTYPE(src_pkattvals_arry) == TEXTOID); src_pkattvals = (char **) palloc(src_nitems * sizeof(char *)); ptr = ARR_DATA_PTR(src_pkattvals_arry); for (i = 0; i < src_nitems; i++) @@ -527,6 +528,7 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS) /* * get array of pointers to c-strings from the input target array */ + Assert(ARR_ELEMTYPE(tgt_pkattvals_arry) == TEXTOID); tgt_pkattvals = (char **) palloc(tgt_nitems * sizeof(char *)); ptr = ARR_DATA_PTR(tgt_pkattvals_arry); for (i = 0; i < tgt_nitems; i++) @@ -621,6 +623,7 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS) /* * get array of pointers to c-strings from the input target array */ + Assert(ARR_ELEMTYPE(tgt_pkattvals_arry) == TEXTOID); tgt_pkattvals = (char **) palloc(tgt_nitems * sizeof(char *)); ptr = ARR_DATA_PTR(tgt_pkattvals_arry); for (i = 0; i < tgt_nitems; i++) @@ -725,6 +728,7 @@ dblink_build_sql_update(PG_FUNCTION_ARGS) /* * get array of pointers to c-strings from the input source array */ + Assert(ARR_ELEMTYPE(src_pkattvals_arry) == TEXTOID); src_pkattvals = (char **) palloc(src_nitems * sizeof(char *)); ptr = ARR_DATA_PTR(src_pkattvals_arry); for (i = 0; i < src_nitems; i++) @@ -750,6 +754,7 @@ dblink_build_sql_update(PG_FUNCTION_ARGS) /* * get array of pointers to c-strings from the input target array */ + Assert(ARR_ELEMTYPE(tgt_pkattvals_arry) == TEXTOID); tgt_pkattvals = (char **) palloc(tgt_nitems * sizeof(char *)); ptr = ARR_DATA_PTR(tgt_pkattvals_arry); for (i = 0; i < tgt_nitems; i++) diff --git a/contrib/intagg/int_aggregate.c b/contrib/intagg/int_aggregate.c index 6e8d17b747..3801a3d91a 100644 --- a/contrib/intagg/int_aggregate.c +++ b/contrib/intagg/int_aggregate.c @@ -38,9 +38,9 @@ #include "utils/lsyscache.h" -/* This is actually a postgres version of a one dimentional array */ +/* This is actually a postgres version of a one dimensional array */ -typedef struct agg +typedef struct { ArrayType a; int items; @@ -95,8 +95,9 @@ static PGARRAY * GetPGArray(int4 state, int fAdd) } p->a.size = cb; - p->a.ndim= 0; + p->a.ndim = 0; p->a.flags = 0; + p->a.elmtype = INT4OID; p->items = 0; p->lower= START_NUM; } @@ -149,6 +150,7 @@ static PGARRAY *ShrinkPGArray(PGARRAY *p) pnew->a.size = cb; pnew->a.ndim=1; pnew->a.flags = 0; + pnew->a.elmtype = INT4OID; pnew->lower = 0; } else diff --git a/contrib/ltree/_ltree_gist.c b/contrib/ltree/_ltree_gist.c index 8b7420e6d9..27bd057a56 100644 --- a/contrib/ltree/_ltree_gist.c +++ b/contrib/ltree/_ltree_gist.c @@ -59,7 +59,7 @@ _ltree_compress(PG_FUNCTION_ARGS) { if ( entry->leafkey ) { /* ltree */ ltree_gist *key; - ArrayType *val = (ArrayType*)DatumGetPointer(PG_DETOAST_DATUM(entry->key)); + ArrayType *val = DatumGetArrayTypeP(entry->key); int4 len = LTG_HDRSIZE + ASIGLEN; int num=ArrayGetNItems( ARR_NDIM(val), ARR_DIMS(val) ); ltree *item = (ltree*)ARR_DATA_PTR(val); diff --git a/contrib/ltree/_ltree_op.c b/contrib/ltree/_ltree_op.c index cc7a16c27e..336b83820c 100644 --- a/contrib/ltree/_ltree_op.c +++ b/contrib/ltree/_ltree_op.c @@ -61,7 +61,7 @@ array_iterator( ArrayType *la, PGCALL2 callback, void* param, ltree ** found) { Datum _ltree_isparent(PG_FUNCTION_ARGS) { - ArrayType *la = (ArrayType *)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0))); + ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); ltree *query = PG_GETARG_LTREE(1); bool res = array_iterator( la, ltree_isparent, (void*)query, NULL ); PG_FREE_IF_COPY(la,0); @@ -79,7 +79,7 @@ _ltree_r_isparent(PG_FUNCTION_ARGS) { Datum _ltree_risparent(PG_FUNCTION_ARGS) { - ArrayType *la = (ArrayType *)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0))); + ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); ltree *query = PG_GETARG_LTREE(1); bool res = array_iterator( la, ltree_risparent, (void*)query, NULL ); PG_FREE_IF_COPY(la,0); @@ -97,7 +97,7 @@ _ltree_r_risparent(PG_FUNCTION_ARGS) { Datum _ltq_regex(PG_FUNCTION_ARGS) { - ArrayType *la = (ArrayType *)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0))); + ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); lquery *query = PG_GETARG_LQUERY(1); bool res = array_iterator( la, ltq_regex, (void*)query, NULL ); PG_FREE_IF_COPY(la,0); @@ -115,7 +115,7 @@ _ltq_rregex(PG_FUNCTION_ARGS) { Datum _ltxtq_exec(PG_FUNCTION_ARGS) { - ArrayType *la = (ArrayType *)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0))); + ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); ltxtquery *query = PG_GETARG_LTXTQUERY(1); bool res = array_iterator( la, ltxtq_exec, (void*)query, NULL ); PG_FREE_IF_COPY(la,0); @@ -134,7 +134,7 @@ _ltxtq_rexec(PG_FUNCTION_ARGS) { Datum _ltree_extract_isparent(PG_FUNCTION_ARGS) { - ArrayType *la = (ArrayType *)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0))); + ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); ltree *query = PG_GETARG_LTREE(1); ltree *found,*item; @@ -154,7 +154,7 @@ _ltree_extract_isparent(PG_FUNCTION_ARGS) { Datum _ltree_extract_risparent(PG_FUNCTION_ARGS) { - ArrayType *la = (ArrayType *)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0))); + ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); ltree *query = PG_GETARG_LTREE(1); ltree *found,*item; @@ -174,7 +174,7 @@ _ltree_extract_risparent(PG_FUNCTION_ARGS) { Datum _ltq_extract_regex(PG_FUNCTION_ARGS) { - ArrayType *la = (ArrayType *)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0))); + ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); lquery *query = PG_GETARG_LQUERY(1); ltree *found,*item; @@ -194,7 +194,7 @@ _ltq_extract_regex(PG_FUNCTION_ARGS) { Datum _ltxtq_extract_exec(PG_FUNCTION_ARGS) { - ArrayType *la = (ArrayType *)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0))); + ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); ltxtquery *query = PG_GETARG_LTXTQUERY(1); ltree *found,*item; @@ -214,7 +214,7 @@ _ltxtq_extract_exec(PG_FUNCTION_ARGS) { Datum _lca(PG_FUNCTION_ARGS) { - ArrayType *la = (ArrayType *)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0))); + ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); int num=ArrayGetNItems( ARR_NDIM(la), ARR_DIMS(la)); ltree *item = (ltree*)ARR_DATA_PTR(la); ltree **a,*res; diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 1ac4edbf0b..85ca6eab64 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.4 2002/08/05 03:29:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.5 2002/08/26 17:53:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,7 @@ #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/pg_constraint.h" +#include "catalog/pg_type.h" #include "miscadmin.h" #include "utils/array.h" #include "utils/builtins.h" @@ -83,7 +84,7 @@ CreateConstraintEntry(const char *constraintName, for (i = 0; i < constraintNKeys; i++) conkey[i] = Int16GetDatum(constraintKey[i]); conkeyArray = construct_array(conkey, constraintNKeys, - true, 2, 's'); + INT2OID, 2, true, 's'); } else conkeyArray = NULL; @@ -96,7 +97,7 @@ CreateConstraintEntry(const char *constraintName, for (i = 0; i < foreignNKeys; i++) confkey[i] = Int16GetDatum(foreignKey[i]); confkeyArray = construct_array(confkey, foreignNKeys, - true, 2, 's'); + INT2OID, 2, true, 's'); } else confkeyArray = NULL; diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index c7dbe44f78..0d3173e9b3 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.43 2002/08/24 15:00:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.44 2002/08/26 17:53:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1731,7 +1731,8 @@ update_attstats(Oid relid, int natts, VacAttrStats **vacattrstats) numdatums[n] = Float4GetDatum(stats->stanumbers[k][n]); /* XXX knows more than it should about type float4: */ arry = construct_array(numdatums, nnum, - false, sizeof(float4), 'i'); + FLOAT4OID, + sizeof(float4), false, 'i'); values[i++] = PointerGetDatum(arry); /* stanumbersN */ } else @@ -1767,7 +1768,8 @@ update_attstats(Oid relid, int natts, VacAttrStats **vacattrstats) } /* XXX knows more than it should about type text: */ arry = construct_array(txtdatums, ntxt, - false, -1, 'i'); + TEXTOID, + -1, false, 'i'); values[i++] = PointerGetDatum(arry); /* stavaluesN */ } else diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index f74f8f1b41..e481ea1159 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.100 2002/07/20 05:16:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.101 2002/08/26 17:53:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -219,35 +219,38 @@ ExecEvalArrayRef(ArrayRef *arrayRef, resultArray = array_set(array_source, i, upper.indx, sourceData, - arrayRef->refelembyval, - arrayRef->refelemlength, arrayRef->refattrlength, + arrayRef->refelemlength, + arrayRef->refelembyval, + arrayRef->refelemalign, isNull); else resultArray = array_set_slice(array_source, i, upper.indx, lower.indx, (ArrayType *) DatumGetPointer(sourceData), - arrayRef->refelembyval, - arrayRef->refelemlength, arrayRef->refattrlength, + arrayRef->refelemlength, + arrayRef->refelembyval, + arrayRef->refelemalign, isNull); return PointerGetDatum(resultArray); } if (lIndex == NULL) - return array_ref(array_source, i, - upper.indx, - arrayRef->refelembyval, - arrayRef->refelemlength, + return array_ref(array_source, i, upper.indx, arrayRef->refattrlength, + arrayRef->refelemlength, + arrayRef->refelembyval, + arrayRef->refelemalign, isNull); else { resultArray = array_get_slice(array_source, i, upper.indx, lower.indx, - arrayRef->refelembyval, - arrayRef->refelemlength, arrayRef->refattrlength, + arrayRef->refelemlength, + arrayRef->refelembyval, + arrayRef->refelemalign, isNull); return PointerGetDatum(resultArray); } diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 49af1f90c8..4de9ba5b8d 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.205 2002/08/24 15:00:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.206 2002/08/26 17:53:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1056,10 +1056,11 @@ _copyArrayRef(ArrayRef *from) /* * copy remainder of node */ + newnode->refrestype = from->refrestype; newnode->refattrlength = from->refattrlength; newnode->refelemlength = from->refelemlength; - newnode->refelemtype = from->refelemtype; newnode->refelembyval = from->refelembyval; + newnode->refelemalign = from->refelemalign; Node_Copy(from, newnode, refupperindexpr); Node_Copy(from, newnode, reflowerindexpr); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 9990a04622..c96389f1e8 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -20,7 +20,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.153 2002/08/19 15:08:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.154 2002/08/26 17:53:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -258,7 +258,7 @@ _equalSubLink(SubLink *a, SubLink *b) static bool _equalArrayRef(ArrayRef *a, ArrayRef *b) { - if (a->refelemtype != b->refelemtype) + if (a->refrestype != b->refrestype) return false; if (a->refattrlength != b->refattrlength) return false; @@ -266,13 +266,17 @@ _equalArrayRef(ArrayRef *a, ArrayRef *b) return false; if (a->refelembyval != b->refelembyval) return false; + if (a->refelemalign != b->refelemalign) + return false; if (!equal(a->refupperindexpr, b->refupperindexpr)) return false; if (!equal(a->reflowerindexpr, b->reflowerindexpr)) return false; if (!equal(a->refexpr, b->refexpr)) return false; - return equal(a->refassgnexpr, b->refassgnexpr); + if (!equal(a->refassgnexpr, b->refassgnexpr)) + return false; + return true; } static bool diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 1a610b7c7c..3a40775339 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.168 2002/08/19 15:08:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.169 2002/08/26 17:53:58 tgl Exp $ * * NOTES * Every (plan) node in POSTGRES has an associated "out" routine which @@ -831,16 +831,18 @@ static void _outArrayRef(StringInfo str, ArrayRef *node) { appendStringInfo(str, - " ARRAYREF :refelemtype %u :refattrlength %d :refelemlength %d ", - node->refelemtype, + " ARRAYREF :refrestype %u :refattrlength %d :refelemlength %d ", + node->refrestype, node->refattrlength, node->refelemlength); - appendStringInfo(str, " :refelembyval %c :refupperindex ", - node->refelembyval ? 't' : 'f'); + appendStringInfo(str, + ":refelembyval %s :refelemalign %c :refupperindexpr ", + booltostr(node->refelembyval), + node->refelemalign); _outNode(str, node->refupperindexpr); - appendStringInfo(str, " :reflowerindex "); + appendStringInfo(str, " :reflowerindexpr "); _outNode(str, node->reflowerindexpr); appendStringInfo(str, " :refexpr "); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index fbf959931e..b54a70159c 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.128 2002/08/10 20:44:48 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.129 2002/08/26 17:53:58 tgl Exp $ * * NOTES * Most of the read functions for plan nodes are tested. (In fact, they @@ -992,9 +992,9 @@ _readArrayRef(void) local_node = makeNode(ArrayRef); - token = pg_strtok(&length); /* eat :refelemtype */ - token = pg_strtok(&length); /* get refelemtype */ - local_node->refelemtype = atooid(token); + token = pg_strtok(&length); /* eat :refrestype */ + token = pg_strtok(&length); /* get refrestype */ + local_node->refrestype = atooid(token); token = pg_strtok(&length); /* eat :refattrlength */ token = pg_strtok(&length); /* get refattrlength */ @@ -1008,10 +1008,14 @@ _readArrayRef(void) token = pg_strtok(&length); /* get refelembyval */ local_node->refelembyval = strtobool(token); - token = pg_strtok(&length); /* eat :refupperindex */ + token = pg_strtok(&length); /* eat :refelemalign */ + token = pg_strtok(&length); /* get refelemalign */ + local_node->refelemalign = token[0]; + + token = pg_strtok(&length); /* eat :refupperindexpr */ local_node->refupperindexpr = nodeRead(true); - token = pg_strtok(&length); /* eat :reflowerindex */ + token = pg_strtok(&length); /* eat :reflowerindexpr */ local_node->reflowerindexpr = nodeRead(true); token = pg_strtok(&length); /* eat :refexpr */ diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 85cdc431a0..1a7acd2252 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.125 2002/08/08 01:44:30 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.126 2002/08/26 17:53:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -877,7 +877,7 @@ exprType(Node *expr) type = ((Const *) expr)->consttype; break; case T_ArrayRef: - type = ((ArrayRef *) expr)->refelemtype; + type = ((ArrayRef *) expr)->refrestype; break; case T_Aggref: type = ((Aggref *) expr)->aggtype; diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index 652ab54d2a..33ee300fb2 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.66 2002/06/20 20:29:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.67 2002/08/26 17:53:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -343,11 +343,12 @@ transformArraySubscripts(ParseState *pstate, * Ready to build the ArrayRef node. */ aref = makeNode(ArrayRef); + aref->refrestype = resultType; /* XXX should save element type + * too */ aref->refattrlength = type_struct_array->typlen; aref->refelemlength = type_struct_element->typlen; - aref->refelemtype = resultType; /* XXX should save element type - * too */ aref->refelembyval = type_struct_element->typbyval; + aref->refelemalign = type_struct_element->typalign; aref->refupperindexpr = upperIndexpr; aref->reflowerindexpr = lowerIndexpr; aref->refexpr = arrayBase; diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 95ab639d0a..e526ffefd6 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.105 2002/08/02 18:15:07 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.106 2002/08/26 17:53:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -381,8 +381,8 @@ process_matched_tle(TargetEntry *src_tle, ((ArrayRef *) src_tle->expr)->refassgnexpr == NULL || prior_tle->expr == NULL || !IsA(prior_tle->expr, ArrayRef) || ((ArrayRef *) prior_tle->expr)->refassgnexpr == NULL || - ((ArrayRef *) src_tle->expr)->refelemtype != - ((ArrayRef *) prior_tle->expr)->refelemtype) + ((ArrayRef *) src_tle->expr)->refrestype != + ((ArrayRef *) prior_tle->expr)->refrestype) elog(ERROR, "Multiple assignments to same attribute \"%s\"", resdom->resname); diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 494a262f0b..05493033d3 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.75 2002/08/09 16:45:14 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.76 2002/08/26 17:53:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,7 @@ #include "catalog/namespace.h" #include "catalog/pg_shadow.h" +#include "catalog/pg_type.h" #include "commands/dbcommands.h" #include "miscadmin.h" #include "utils/acl.h" @@ -252,6 +253,7 @@ makeacl(int n) new_acl->size = size; new_acl->ndim = 1; new_acl->flags = 0; + new_acl->elemtype = ACLITEMOID; ARR_LBOUND(new_acl)[0] = 0; ARR_DIMS(new_acl)[0] = n; return new_acl; diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 30c2793192..53a4c83d63 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.78 2002/06/20 20:29:36 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.79 2002/08/26 17:53:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -24,21 +24,37 @@ #include "utils/syscache.h" -/* - * An array has the following internal structure: - * - total number of bytes +/*---------- + * A standard varlena array has the following internal structure: + * - total number of bytes (also, TOAST info flags) * - number of dimensions of the array * - bit mask of flags - * - size of each array axis - * - lower boundary of each dimension + * - element type OID + * - size of each array axis (C array of int) + * - lower boundary of each dimension (C array of int) * - whatever is the stored data - * The actual data starts on a MAXALIGN boundary. + * The actual data starts on a MAXALIGN boundary. Individual items in the + * array are aligned as specified by the array element type. * * NOTE: it is important that array elements of toastable datatypes NOT be * toasted, since the tupletoaster won't know they are there. (We could * support compressed toasted items; only out-of-line items are dangerous. * However, it seems preferable to store such items uncompressed and allow * the toaster to compress the whole array as one input.) + * + * There is currently no support for NULL elements in arrays, either. + * A reasonable (and backwards-compatible) way to add support would be to + * add a nulls bitmap following the array, which would be present + * if needed; and its presence would be signaled by a bit in the flags word. + * + * + * 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 + * 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() + * only work with varlena arrays. + *---------- */ @@ -54,28 +70,37 @@ static int ArrayCount(char *str, int *dim, char typdelim); static Datum *ReadArrayStr(char *arrayStr, int nitems, int ndim, int *dim, FmgrInfo *inputproc, Oid typelem, int32 typmod, - char typdelim, int typlen, bool typbyval, - char typalign, int *nbytes); + char typdelim, + int typlen, bool typbyval, char typalign, + int *nbytes); static void CopyArrayEls(char *p, Datum *values, int nitems, - bool typbyval, int typlen, char typalign, + int typlen, bool typbyval, char typalign, bool freedata); static void system_cache_lookup(Oid element_type, bool input, int *typlen, bool *typbyval, char *typdelim, Oid *typelem, Oid *proc, char *typalign); static Datum ArrayCast(char *value, bool byval, int len); -static int ArrayCastAndSet(Datum src, bool typbyval, int typlen, char *dest); -static int array_nelems_size(char *ptr, int eltsize, int nitems); -static char *array_seek(char *ptr, int eltsize, int nitems); -static int array_copy(char *destptr, int eltsize, int nitems, char *srcptr); +static int ArrayCastAndSet(Datum src, + int typlen, bool typbyval, char typalign, + char *dest); +static int array_nelems_size(char *ptr, int nitems, + int typlen, bool typbyval, char typalign); +static char *array_seek(char *ptr, int nitems, + int typlen, bool typbyval, char typalign); +static int array_copy(char *destptr, int nitems, char *srcptr, + int typlen, bool typbyval, char typalign); static int array_slice_size(int ndim, int *dim, int *lb, char *arraydataptr, - int eltsize, int *st, int *endp); + int *st, int *endp, + int typlen, bool typbyval, char typalign); static void array_extract_slice(int ndim, int *dim, int *lb, - char *arraydataptr, int eltsize, - int *st, int *endp, char *destPtr); + char *arraydataptr, + int *st, int *endp, char *destPtr, + int typlen, bool typbyval, char typalign); static void array_insert_slice(int ndim, int *dim, int *lb, - char *origPtr, int origdatasize, - char *destPtr, int eltsize, - int *st, int *endp, char *srcPtr); + char *origPtr, int origdatasize, + char *destPtr, + int *st, int *endp, char *srcPtr, + int typlen, bool typbyval, char typalign); /*--------------------------------------------------------------------- @@ -212,6 +237,7 @@ array_in(PG_FUNCTION_ARGS) retval = (ArrayType *) palloc(sizeof(ArrayType)); MemSet(retval, 0, sizeof(ArrayType)); retval->size = sizeof(ArrayType); + retval->elemtype = element_type; PG_RETURN_ARRAYTYPE_P(retval); } @@ -226,13 +252,14 @@ array_in(PG_FUNCTION_ARGS) MemSet(retval, 0, nbytes); retval->size = nbytes; retval->ndim = ndim; + retval->elemtype = element_type; memcpy((char *) ARR_DIMS(retval), (char *) dim, ndim * sizeof(int)); memcpy((char *) ARR_LBOUND(retval), (char *) lBound, ndim * sizeof(int)); CopyArrayEls(ARR_DATA_PTR(retval), dataPtr, nitems, - typbyval, typlen, typalign, true); + typlen, typbyval, typalign, true); pfree(dataPtr); pfree(string_save); PG_RETURN_ARRAYTYPE_P(retval); @@ -336,7 +363,7 @@ ArrayCount(char *str, int *dim, char typdelim) * internal format. The external format expected is like C array * declaration. Unspecified elements are initialized to zero for fixed length * base types and to empty varlena structures for variable length base - * types. + * types. (This is pretty bogus; NULL would be much safer.) * result : * returns a palloc'd array of Datum representations of the array elements. * If element type is pass-by-ref, the Datums point to palloc'd values. @@ -482,7 +509,7 @@ ReadArrayStr(char *arrayStr, */ if (typlen > 0) { - *nbytes = nitems * typlen; + *nbytes = nitems * att_align(typlen, typalign); if (!typbyval) for (i = 0; i < nitems; i++) if (values[i] == (Datum) 0) @@ -493,23 +520,34 @@ ReadArrayStr(char *arrayStr, } else { + Assert(!typbyval); *nbytes = 0; for (i = 0; i < nitems; i++) { if (values[i] != (Datum) 0) { /* let's just make sure data is not toasted */ - values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i])); - if (typalign == 'd') - *nbytes += MAXALIGN(VARSIZE(DatumGetPointer(values[i]))); - else - *nbytes += INTALIGN(VARSIZE(DatumGetPointer(values[i]))); + if (typlen == -1) + values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i])); + *nbytes = att_addlength(*nbytes, typlen, values[i]); + *nbytes = att_align(*nbytes, typalign); } - else + else if (typlen == -1) { - *nbytes += sizeof(int32); + /* dummy varlena value (XXX bogus, see notes above) */ values[i] = PointerGetDatum(palloc(sizeof(int32))); VARATT_SIZEP(DatumGetPointer(values[i])) = sizeof(int32); + *nbytes += sizeof(int32); + *nbytes = att_align(*nbytes, typalign); + } + else + { + /* dummy cstring value */ + Assert(typlen == -2); + values[i] = PointerGetDatum(palloc(1)); + *((char *) DatumGetPointer(values[i])) = '\0'; + *nbytes += 1; + *nbytes = att_align(*nbytes, typalign); } } } @@ -536,21 +574,19 @@ static void CopyArrayEls(char *p, Datum *values, int nitems, - bool typbyval, int typlen, + bool typbyval, char typalign, bool freedata) { int i; - int inc; if (typbyval) freedata = false; for (i = 0; i < nitems; i++) { - inc = ArrayCastAndSet(values[i], typbyval, typlen, p); - p += inc; + p += ArrayCastAndSet(values[i], typlen, typbyval, typalign, p); if (freedata) pfree(DatumGetPointer(values[i])); } @@ -566,7 +602,7 @@ Datum array_out(PG_FUNCTION_ARGS) { ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); - Oid element_type = PG_GETARG_OID(1); + Oid element_type; int typlen; bool typbyval; char typdelim; @@ -588,9 +624,11 @@ array_out(PG_FUNCTION_ARGS) int ndim, *dim; + element_type = ARR_ELEMTYPE(v); system_cache_lookup(element_type, false, &typlen, &typbyval, &typdelim, &typelem, &typoutput, &typalign); fmgr_info(typoutput, &outputproc); + ndim = ARR_NDIM(v); dim = ARR_DIMS(v); nitems = ArrayGetNItems(ndim, dim); @@ -620,10 +658,8 @@ array_out(PG_FUNCTION_ARGS) itemvalue, ObjectIdGetDatum(typelem), Int32GetDatum(-1))); - if (typlen > 0) - p += typlen; - else - p += INTALIGN(*(int32 *) p); + p = att_addlength(p, typlen, PointerGetDatum(p)); + p = (char *) att_align(p, typalign); /* count data plus backslashes; detect chars needing quotes */ nq = (values[i][0] == '\0'); /* force quotes for empty string */ @@ -774,9 +810,10 @@ Datum array_ref(ArrayType *array, int nSubscripts, int *indx, - bool elmbyval, - int elmlen, int arraylen, + int elmlen, + bool elmbyval, + char elmalign, bool *isNull) { int i, @@ -806,7 +843,7 @@ array_ref(ArrayType *array, } else { - /* detoast input if necessary */ + /* detoast input array if necessary */ array = DatumGetArrayTypeP(PointerGetDatum(array)); ndim = ARR_NDIM(array); @@ -829,7 +866,7 @@ array_ref(ArrayType *array, */ offset = ArrayGetOffset(nSubscripts, dim, lb, indx); - retptr = array_seek(arraydataptr, elmlen, offset); + retptr = array_seek(arraydataptr, offset, elmlen, elmbyval, elmalign); *isNull = false; return ArrayCast(retptr, elmbyval, elmlen); @@ -850,9 +887,10 @@ array_get_slice(ArrayType *array, int nSubscripts, int *upperIndx, int *lowerIndx, - bool elmbyval, - int elmlen, int arraylen, + int elmlen, + bool elmbyval, + char elmalign, bool *isNull) { int i, @@ -882,6 +920,7 @@ array_get_slice(ArrayType *array, /* * fixed-length arrays -- these are assumed to be 1-d, 0-based + * XXX where would we get the correct ELEMTYPE from? */ ndim = 1; fixedDim[0] = arraylen / elmlen; @@ -892,7 +931,7 @@ array_get_slice(ArrayType *array, } else { - /* detoast input if necessary */ + /* detoast input array if necessary */ array = DatumGetArrayTypeP(PointerGetDatum(array)); ndim = ARR_NDIM(array); @@ -931,13 +970,15 @@ array_get_slice(ArrayType *array, mda_get_range(ndim, span, lowerIndx, upperIndx); bytes = array_slice_size(ndim, dim, lb, arraydataptr, - elmlen, lowerIndx, upperIndx); + lowerIndx, upperIndx, + elmlen, elmbyval, elmalign); bytes += ARR_OVERHEAD(ndim); newarray = (ArrayType *) palloc(bytes); newarray->size = bytes; newarray->ndim = ndim; newarray->flags = 0; + newarray->elemtype = ARR_ELEMTYPE(array); memcpy(ARR_DIMS(newarray), span, ndim * sizeof(int)); /* * Lower bounds of the new array are set to 1. Formerly (before 7.3) @@ -947,8 +988,9 @@ array_get_slice(ArrayType *array, for (i = 0; i < ndim; i++) newlb[i] = 1; - array_extract_slice(ndim, dim, lb, arraydataptr, elmlen, - lowerIndx, upperIndx, ARR_DATA_PTR(newarray)); + array_extract_slice(ndim, dim, lb, arraydataptr, + lowerIndx, upperIndx, ARR_DATA_PTR(newarray), + elmlen, elmbyval, elmalign); return newarray; } @@ -976,9 +1018,10 @@ array_set(ArrayType *array, int nSubscripts, int *indx, Datum dataValue, - bool elmbyval, - int elmlen, int arraylen, + int elmlen, + bool elmbyval, + char elmalign, bool *isNull) { int i, @@ -1014,15 +1057,15 @@ array_set(ArrayType *array, newarray = (ArrayType *) palloc(arraylen); memcpy(newarray, array, arraylen); elt_ptr = (char *) newarray + indx[0] * elmlen; - ArrayCastAndSet(dataValue, elmbyval, elmlen, elt_ptr); + ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, elt_ptr); return newarray; } /* make sure item to be inserted is not toasted */ - if (elmlen < 0) + if (elmlen == -1) dataValue = PointerGetDatum(PG_DETOAST_DATUM(dataValue)); - /* detoast input if necessary */ + /* detoast input array if necessary */ array = DatumGetArrayTypeP(PointerGetDatum(array)); ndim = ARR_NDIM(array); @@ -1081,19 +1124,16 @@ array_set(ArrayType *array, else { offset = ArrayGetOffset(nSubscripts, dim, lb, indx); - elt_ptr = array_seek(ARR_DATA_PTR(array), elmlen, offset); + elt_ptr = array_seek(ARR_DATA_PTR(array), offset, + elmlen, elmbyval, elmalign); lenbefore = (int) (elt_ptr - ARR_DATA_PTR(array)); - if (elmlen > 0) - olditemlen = elmlen; - else - olditemlen = INTALIGN(*(int32 *) elt_ptr); + olditemlen = att_addlength(0, elmlen, PointerGetDatum(elt_ptr)); + olditemlen = att_align(olditemlen, elmalign); lenafter = (int) (olddatasize - lenbefore - olditemlen); } - if (elmlen > 0) - newitemlen = elmlen; - else - newitemlen = INTALIGN(*(int32 *) DatumGetPointer(dataValue)); + newitemlen = att_addlength(0, elmlen, dataValue); + newitemlen = att_align(newitemlen, elmalign); newsize = overheadlen + lenbefore + newitemlen + lenafter; @@ -1104,6 +1144,7 @@ array_set(ArrayType *array, newarray->size = newsize; newarray->ndim = ndim; newarray->flags = 0; + newarray->elemtype = ARR_ELEMTYPE(array); memcpy(ARR_DIMS(newarray), dim, ndim * sizeof(int)); memcpy(ARR_LBOUND(newarray), lb, ndim * sizeof(int)); memcpy((char *) newarray + overheadlen, @@ -1113,7 +1154,7 @@ array_set(ArrayType *array, (char *) array + overheadlen + lenbefore + olditemlen, lenafter); - ArrayCastAndSet(dataValue, elmbyval, elmlen, + ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, (char *) newarray + overheadlen + lenbefore); return newarray; @@ -1143,9 +1184,10 @@ array_set_slice(ArrayType *array, int *upperIndx, int *lowerIndx, ArrayType *srcArray, - bool elmbyval, - int elmlen, int arraylen, + int elmlen, + bool elmbyval, + char elmalign, bool *isNull) { int i, @@ -1240,8 +1282,8 @@ array_set_slice(ArrayType *array, * Compute space occupied by new entries, space occupied by replaced * entries, and required space for new array. */ - newitemsize = array_nelems_size(ARR_DATA_PTR(srcArray), elmlen, - nsrcitems); + newitemsize = array_nelems_size(ARR_DATA_PTR(srcArray), nsrcitems, + elmlen, elmbyval, elmalign); overheadlen = ARR_OVERHEAD(ndim); olddatasize = ARR_SIZE(array) - overheadlen; if (ndim > 1) @@ -1251,7 +1293,8 @@ array_set_slice(ArrayType *array, * would be a lot more complicated if we had to do so... */ olditemsize = array_slice_size(ndim, dim, lb, ARR_DATA_PTR(array), - elmlen, lowerIndx, upperIndx); + lowerIndx, upperIndx, + elmlen, elmbyval, elmalign); lenbefore = lenafter = 0; /* keep compiler quiet */ } else @@ -1266,15 +1309,14 @@ array_set_slice(ArrayType *array, int sliceub = Min(oldub, upperIndx[0]); char *oldarraydata = ARR_DATA_PTR(array); - lenbefore = array_nelems_size(oldarraydata, - elmlen, - slicelb - oldlb); + lenbefore = array_nelems_size(oldarraydata, slicelb - oldlb, + elmlen, elmbyval, elmalign); if (slicelb > sliceub) olditemsize = 0; else olditemsize = array_nelems_size(oldarraydata + lenbefore, - elmlen, - sliceub - slicelb + 1); + sliceub - slicelb + 1, + elmlen, elmbyval, elmalign); lenafter = olddatasize - lenbefore - olditemsize; } @@ -1284,6 +1326,7 @@ array_set_slice(ArrayType *array, newarray->size = newsize; newarray->ndim = ndim; newarray->flags = 0; + newarray->elemtype = ARR_ELEMTYPE(array); memcpy(ARR_DIMS(newarray), dim, ndim * sizeof(int)); memcpy(ARR_LBOUND(newarray), lb, ndim * sizeof(int)); @@ -1294,8 +1337,9 @@ array_set_slice(ArrayType *array, * would be a lot more complicated if we had to do so... */ array_insert_slice(ndim, dim, lb, ARR_DATA_PTR(array), olddatasize, - ARR_DATA_PTR(newarray), elmlen, - lowerIndx, upperIndx, ARR_DATA_PTR(srcArray)); + ARR_DATA_PTR(newarray), + lowerIndx, upperIndx, ARR_DATA_PTR(srcArray), + elmlen, elmbyval, elmalign); } else { @@ -1352,12 +1396,13 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType) int nbytes = 0; int inp_typlen; bool inp_typbyval; + char inp_typalign; int typlen; bool typbyval; + char typalign; char typdelim; Oid typelem; Oid proc; - char typalign; char *s; /* Get input array */ @@ -1367,6 +1412,8 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType) elog(ERROR, "array_map: null input array"); v = PG_GETARG_ARRAYTYPE_P(0); + Assert(ARR_ELEMTYPE(v) == inpType); + ndim = ARR_NDIM(v); dim = ARR_DIMS(v); nitems = ArrayGetNItems(ndim, dim); @@ -1377,7 +1424,7 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType) /* Lookup source and result types. Unneeded variables are reused. */ system_cache_lookup(inpType, false, &inp_typlen, &inp_typbyval, - &typdelim, &typelem, &proc, &typalign); + &typdelim, &typelem, &proc, &inp_typalign); system_cache_lookup(retType, false, &typlen, &typbyval, &typdelim, &typelem, &proc, &typalign); @@ -1391,10 +1438,8 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType) /* Get source element */ elt = fetch_att(s, inp_typbyval, inp_typlen); - if (inp_typlen > 0) - s += inp_typlen; - else - s += INTALIGN(*(int32 *) s); + s = att_addlength(s, inp_typlen, PointerGetDatum(s)); + s = (char *) att_align(s, inp_typalign); /* * Apply the given function to source elt and extra args. @@ -1410,14 +1455,13 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType) if (fcinfo->isnull) elog(ERROR, "array_map: cannot handle NULL in array"); - /* Ensure data is not toasted, and update total result size */ - if (typbyval || typlen > 0) - nbytes += typlen; - else - { + /* Ensure data is not toasted */ + if (typlen == -1) values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i])); - nbytes += INTALIGN(VARSIZE(DatumGetPointer(values[i]))); - } + + /* Update total result size */ + nbytes = att_addlength(nbytes, typlen, values[i]); + nbytes = att_align(nbytes, typalign); } /* Allocate and initialize the result array */ @@ -1427,6 +1471,7 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType) result->size = nbytes; result->ndim = ndim; + result->elemtype = retType; memcpy(ARR_DIMS(result), ARR_DIMS(v), 2 * ndim * sizeof(int)); /* @@ -1434,7 +1479,7 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType) * function */ CopyArrayEls(ARR_DATA_PTR(result), values, nitems, - typbyval, typlen, typalign, false); + typlen, typbyval, typalign, false); pfree(values); PG_RETURN_ARRAYTYPE_P(result); @@ -1445,34 +1490,43 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType) * * elems: array of Datum items to become the array contents * nelems: number of items - * elmbyval, elmlen, elmalign: info for the datatype of the items + * elmtype, elmlen, elmbyval, elmalign: info for the datatype of the items * * A palloc'd 1-D array object is constructed and returned. Note that * elem values will be copied into the object even if pass-by-ref type. * NULL element values are not supported. + * + * NOTE: it would be cleaner to look up the elmlen/elmbval/elmalign info + * from the system catalogs, given the elmtype. However, in most current + * uses the type is hard-wired into the caller and so we can save a lookup + * cycle by hard-wiring the type info as well. *---------- */ ArrayType * construct_array(Datum *elems, int nelems, - bool elmbyval, int elmlen, char elmalign) + Oid elmtype, + int elmlen, bool elmbyval, char elmalign) { ArrayType *result; int nbytes; int i; + /* compute required space */ if (elmlen > 0) { - /* XXX what about alignment? */ - nbytes = elmlen * nelems; + nbytes = nelems * att_align(elmlen, elmalign); } else { - /* varlena type ... make sure it is untoasted */ + Assert(!elmbyval); nbytes = 0; for (i = 0; i < nelems; i++) { - elems[i] = PointerGetDatum(PG_DETOAST_DATUM(elems[i])); - nbytes += INTALIGN(VARSIZE(DatumGetPointer(elems[i]))); + /* make sure data is not toasted */ + if (elmlen == -1) + elems[i] = PointerGetDatum(PG_DETOAST_DATUM(elems[i])); + nbytes = att_addlength(nbytes, elmlen, elems[i]); + nbytes = att_align(nbytes, elmalign); } } @@ -1483,11 +1537,12 @@ construct_array(Datum *elems, int nelems, result->size = nbytes; result->ndim = 1; result->flags = 0; + result->elemtype = elmtype; ARR_DIMS(result)[0] = nelems; ARR_LBOUND(result)[0] = 1; CopyArrayEls(ARR_DATA_PTR(result), elems, nelems, - elmbyval, elmlen, elmalign, false); + elmlen, elmbyval, elmalign, false); return result; } @@ -1496,17 +1551,23 @@ construct_array(Datum *elems, int nelems, * deconstruct_array --- simple method for extracting data from an array * * array: array object to examine (must not be NULL) - * elmbyval, elmlen, elmalign: info for the datatype of the items + * elmtype, elmlen, elmbyval, elmalign: info for the datatype of the items * elemsp: return value, set to point to palloc'd array of Datum values * nelemsp: return value, set to number of extracted values * * If array elements are pass-by-ref data type, the returned Datums will * be pointers into the array object. + * + * NOTE: it would be cleaner to look up the elmlen/elmbval/elmalign info + * from the system catalogs, given the elmtype. However, in most current + * uses the type is hard-wired into the caller and so we can save a lookup + * cycle by hard-wiring the type info as well. *---------- */ void deconstruct_array(ArrayType *array, - bool elmbyval, int elmlen, char elmalign, + Oid elmtype, + int elmlen, bool elmbyval, char elmalign, Datum **elemsp, int *nelemsp) { Datum *elems; @@ -1514,6 +1575,8 @@ deconstruct_array(ArrayType *array, char *p; int i; + Assert(ARR_ELEMTYPE(array) == elmtype); + nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); if (nelems <= 0) { @@ -1528,10 +1591,8 @@ deconstruct_array(ArrayType *array, for (i = 0; i < nelems; i++) { elems[i] = fetch_att(p, elmbyval, elmlen); - if (elmlen > 0) - p += elmlen; - else - p += INTALIGN(VARSIZE(p)); + p = att_addlength(p, elmlen, PointerGetDatum(p)); + p = (char *) att_align(p, elmalign); } } @@ -1586,8 +1647,7 @@ system_cache_lookup(Oid element_type, ObjectIdGetDatum(element_type), 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) - elog(ERROR, "array_out: Cache lookup failed for type %u", - element_type); + elog(ERROR, "cache lookup failed for type %u", element_type); typeStruct = (Form_pg_type) GETSTRUCT(typeTuple); *typlen = typeStruct->typlen; @@ -1613,13 +1673,12 @@ ArrayCast(char *value, bool byval, int len) /* * Copy datum to *dest and return total space used (including align padding) - * - * XXX this routine needs to be told typalign too! */ static int ArrayCastAndSet(Datum src, - bool typbyval, int typlen, + bool typbyval, + char typalign, char *dest) { int inc; @@ -1627,24 +1686,17 @@ ArrayCastAndSet(Datum src, if (typlen > 0) { if (typbyval) - { store_att_byval(dest, src, typlen); - /* For by-val types, assume no alignment padding is needed */ - inc = typlen; - } else - { memmove(dest, DatumGetPointer(src), typlen); - /* XXX WRONG: need to consider type's alignment requirement */ - inc = typlen; - } + inc = att_align(typlen, typalign); } else { - /* varlena type */ - memmove(dest, DatumGetPointer(src), VARSIZE(DatumGetPointer(src))); - /* XXX WRONG: should use MAXALIGN or type's alignment requirement */ - inc = INTALIGN(VARSIZE(DatumGetPointer(src))); + Assert(!typbyval); + inc = att_addlength(0, typlen, src); + memmove(dest, DatumGetPointer(src), inc); + inc = att_align(inc, typalign); } return inc; @@ -1652,22 +1704,25 @@ ArrayCastAndSet(Datum src, /* * Compute total size of the nitems array elements starting at *ptr - * - * XXX should consider alignment spec for fixed-length types */ static int -array_nelems_size(char *ptr, int eltsize, int nitems) +array_nelems_size(char *ptr, int nitems, + int typlen, bool typbyval, char typalign) { char *origptr; int i; /* fixed-size elements? */ - if (eltsize > 0) - return eltsize * nitems; - /* else assume they are varlena items */ + if (typlen > 0) + return nitems * att_align(typlen, typalign); + + Assert(!typbyval); origptr = ptr; for (i = 0; i < nitems; i++) - ptr += INTALIGN(*(int32 *) ptr); + { + ptr = att_addlength(ptr, typlen, PointerGetDatum(ptr)); + ptr = (char *) att_align(ptr, typalign); + } return ptr - origptr; } @@ -1675,9 +1730,11 @@ array_nelems_size(char *ptr, int eltsize, int nitems) * Advance ptr over nitems array elements */ static char * -array_seek(char *ptr, int eltsize, int nitems) +array_seek(char *ptr, int nitems, + int typlen, bool typbyval, char typalign) { - return ptr + array_nelems_size(ptr, eltsize, nitems); + return ptr + array_nelems_size(ptr, nitems, + typlen, typbyval, typalign); } /* @@ -1686,9 +1743,11 @@ array_seek(char *ptr, int eltsize, int nitems) * Returns number of bytes copied */ static int -array_copy(char *destptr, int eltsize, int nitems, char *srcptr) +array_copy(char *destptr, int nitems, char *srcptr, + int typlen, bool typbyval, char typalign) { - int numbytes = array_nelems_size(srcptr, eltsize, nitems); + int numbytes = array_nelems_size(srcptr, nitems, + typlen, typbyval, typalign); memmove(destptr, srcptr, numbytes); return numbytes; @@ -1701,7 +1760,8 @@ array_copy(char *destptr, int eltsize, int nitems, char *srcptr) */ static int array_slice_size(int ndim, int *dim, int *lb, char *arraydataptr, - int eltsize, int *st, int *endp) + int *st, int *endp, + int typlen, bool typbyval, char typalign) { int st_pos, span[MAXDIM], @@ -1717,12 +1777,13 @@ array_slice_size(int ndim, int *dim, int *lb, char *arraydataptr, mda_get_range(ndim, span, st, endp); /* Pretty easy for fixed element length ... */ - if (eltsize > 0) - return ArrayGetNItems(ndim, span) * eltsize; + if (typlen > 0) + return ArrayGetNItems(ndim, span) * att_align(typlen, typalign); /* Else gotta do it the hard way */ st_pos = ArrayGetOffset(ndim, dim, lb, st); - ptr = array_seek(arraydataptr, eltsize, st_pos); + ptr = array_seek(arraydataptr, st_pos, + typlen, typbyval, typalign); mda_get_prod(ndim, dim, prod); mda_get_offset_values(ndim, dist, prod, span); for (i = 0; i < ndim; i++) @@ -1730,8 +1791,10 @@ array_slice_size(int ndim, int *dim, int *lb, char *arraydataptr, j = ndim - 1; do { - ptr = array_seek(ptr, eltsize, dist[j]); - inc = INTALIGN(*(int32 *) ptr); + ptr = array_seek(ptr, dist[j], + typlen, typbyval, typalign); + inc = att_addlength(0, typlen, PointerGetDatum(ptr)); + inc = att_align(inc, typalign); ptr += inc; count += inc; } while ((j = mda_next_tuple(ndim, indx, span)) != -1); @@ -1749,10 +1812,12 @@ array_extract_slice(int ndim, int *dim, int *lb, char *arraydataptr, - int eltsize, int *st, int *endp, - char *destPtr) + char *destPtr, + int typlen, + bool typbyval, + char typalign) { int st_pos, prod[MAXDIM], @@ -1765,7 +1830,8 @@ array_extract_slice(int ndim, inc; st_pos = ArrayGetOffset(ndim, dim, lb, st); - srcPtr = array_seek(arraydataptr, eltsize, st_pos); + srcPtr = array_seek(arraydataptr, st_pos, + typlen, typbyval, typalign); mda_get_prod(ndim, dim, prod); mda_get_range(ndim, span, st, endp); mda_get_offset_values(ndim, dist, prod, span); @@ -1774,8 +1840,10 @@ array_extract_slice(int ndim, j = ndim - 1; do { - srcPtr = array_seek(srcPtr, eltsize, dist[j]); - inc = array_copy(destPtr, eltsize, 1, srcPtr); + srcPtr = array_seek(srcPtr, dist[j], + typlen, typbyval, typalign); + inc = array_copy(destPtr, 1, srcPtr, + typlen, typbyval, typalign); destPtr += inc; srcPtr += inc; } while ((j = mda_next_tuple(ndim, indx, span)) != -1); @@ -1801,10 +1869,12 @@ array_insert_slice(int ndim, char *origPtr, int origdatasize, char *destPtr, - int eltsize, int *st, int *endp, - char *srcPtr) + char *srcPtr, + int typlen, + bool typbyval, + char typalign) { int st_pos, prod[MAXDIM], @@ -1817,7 +1887,8 @@ array_insert_slice(int ndim, inc; st_pos = ArrayGetOffset(ndim, dim, lb, st); - inc = array_copy(destPtr, eltsize, st_pos, origPtr); + inc = array_copy(destPtr, st_pos, origPtr, + typlen, typbyval, typalign); destPtr += inc; origPtr += inc; mda_get_prod(ndim, dim, prod); @@ -1829,15 +1900,18 @@ array_insert_slice(int ndim, do { /* Copy/advance over elements between here and next part of slice */ - inc = array_copy(destPtr, eltsize, dist[j], origPtr); + inc = array_copy(destPtr, dist[j], origPtr, + typlen, typbyval, typalign); destPtr += inc; origPtr += inc; /* Copy new element at this slice position */ - inc = array_copy(destPtr, eltsize, 1, srcPtr); + inc = array_copy(destPtr, 1, srcPtr, + typlen, typbyval, typalign); destPtr += inc; srcPtr += inc; /* Advance over old element at this slice position */ - origPtr = array_seek(origPtr, eltsize, 1); + origPtr = array_seek(origPtr, 1, + typlen, typbyval, typalign); } while ((j = mda_next_tuple(ndim, indx, span)) != -1); /* don't miss any data at the end */ diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index 84233ebd1c..5edea787af 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.79 2002/06/20 20:29:37 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.80 2002/08/26 17:53:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -61,6 +61,7 @@ #include #endif +#include "catalog/pg_type.h" #include "fmgr.h" #include "utils/array.h" #include "utils/builtins.h" @@ -1480,9 +1481,9 @@ check_float8_array(ArrayType *transarray, const char *caller) * don't need to use deconstruct_array() since the array data is just * going to look like a C array of 3 float8 values. */ - if (ARR_SIZE(transarray) != (ARR_OVERHEAD(1) + 3 * sizeof(float8)) || - ARR_NDIM(transarray) != 1 || - ARR_DIMS(transarray)[0] != 3) + if (ARR_NDIM(transarray) != 1 || + ARR_DIMS(transarray)[0] != 3 || + ARR_ELEMTYPE(transarray) != FLOAT8OID) elog(ERROR, "%s: expected 3-element float8 array", caller); return (float8 *) ARR_DATA_PTR(transarray); } @@ -1513,7 +1514,8 @@ float8_accum(PG_FUNCTION_ARGS) transdatums[2] = Float8GetDatumFast(sumX2); result = construct_array(transdatums, 3, - false /* float8 byval */ , sizeof(float8), 'd'); + FLOAT8OID, + sizeof(float8), false /*float8 byval*/, 'd'); PG_RETURN_ARRAYTYPE_P(result); } @@ -1548,7 +1550,8 @@ float4_accum(PG_FUNCTION_ARGS) transdatums[2] = Float8GetDatumFast(sumX2); result = construct_array(transdatums, 3, - false /* float8 byval */ , sizeof(float8), 'd'); + FLOAT8OID, + sizeof(float8), false /*float8 byval*/, 'd'); PG_RETURN_ARRAYTYPE_P(result); } diff --git a/src/backend/utils/adt/name.c b/src/backend/utils/adt/name.c index de3f04a7df..41eca445f6 100644 --- a/src/backend/utils/adt/name.c +++ b/src/backend/utils/adt/name.c @@ -12,13 +12,14 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/name.c,v 1.39 2002/06/20 20:29:37 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/name.c,v 1.40 2002/08/26 17:53:58 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "catalog/namespace.h" +#include "catalog/pg_type.h" #include "miscadmin.h" #include "utils/array.h" #include "utils/builtins.h" @@ -271,8 +272,9 @@ current_schemas(PG_FUNCTION_ARGS) } array = construct_array(names, nnames, - false, /* Name is not by-val */ + NAMEOID, NAMEDATALEN, /* sizeof(Name) */ + false, /* Name is not by-val */ 'i'); /* alignment of Name */ PG_RETURN_POINTER(array); diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index 1af7402fb3..99ef1327e4 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -5,7 +5,7 @@ * * 1998 Jan Wieck * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.50 2002/02/18 14:25:40 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.51 2002/08/26 17:53:58 tgl Exp $ * * ---------- */ @@ -18,6 +18,7 @@ #include #include +#include "catalog/pg_type.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/int8.h" @@ -1734,7 +1735,7 @@ do_numeric_accum(ArrayType *transarray, Numeric newval) /* We assume the input is array of numeric */ deconstruct_array(transarray, - false, -1, 'i', + NUMERICOID, -1, false, 'i', &transdatums, &ndatums); if (ndatums != 3) elog(ERROR, "do_numeric_accum: expected 3-element numeric array"); @@ -1755,7 +1756,7 @@ do_numeric_accum(ArrayType *transarray, Numeric newval) transdatums[2] = sumX2; result = construct_array(transdatums, 3, - false, -1, 'i'); + NUMERICOID, -1, false, 'i'); return result; } @@ -1825,7 +1826,7 @@ numeric_avg(PG_FUNCTION_ARGS) /* We assume the input is array of numeric */ deconstruct_array(transarray, - false, -1, 'i', + NUMERICOID, -1, false, 'i', &transdatums, &ndatums); if (ndatums != 3) elog(ERROR, "numeric_avg: expected 3-element numeric array"); @@ -1861,7 +1862,7 @@ numeric_variance(PG_FUNCTION_ARGS) /* We assume the input is array of numeric */ deconstruct_array(transarray, - false, -1, 'i', + NUMERICOID, -1, false, 'i', &transdatums, &ndatums); if (ndatums != 3) elog(ERROR, "numeric_variance: expected 3-element numeric array"); @@ -1940,7 +1941,7 @@ numeric_stddev(PG_FUNCTION_ARGS) /* We assume the input is array of numeric */ deconstruct_array(transarray, - false, -1, 'i', + NUMERICOID, -1, false, 'i', &transdatums, &ndatums); if (ndatums != 3) elog(ERROR, "numeric_stddev: expected 3-element numeric array"); diff --git a/src/backend/utils/adt/pseudotypes.c b/src/backend/utils/adt/pseudotypes.c index cb374e8f93..63f585fe32 100644 --- a/src/backend/utils/adt/pseudotypes.c +++ b/src/backend/utils/adt/pseudotypes.c @@ -16,12 +16,13 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/pseudotypes.c,v 1.2 2002/08/24 15:00:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/pseudotypes.c,v 1.3 2002/08/26 17:53:58 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include "utils/array.h" #include "utils/builtins.h" @@ -112,13 +113,13 @@ anyarray_in(PG_FUNCTION_ARGS) /* * anyarray_out - output routine for pseudo-type ANYARRAY. + * + * We may as well allow this, since array_out will in fact work. */ Datum anyarray_out(PG_FUNCTION_ARGS) { - elog(ERROR, "Cannot display a value of type %s", "ANYARRAY"); - - PG_RETURN_VOID(); /* keep compiler quiet */ + return array_out(fcinfo); } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 0f5d0fca86..1011636456 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * back to source text * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.117 2002/08/18 09:36:25 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.118 2002/08/26 17:53:58 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -725,7 +725,7 @@ decompile_column_index_array(Datum column_index_array, Oid relId, /* Extract data from array of int16 */ deconstruct_array(DatumGetArrayTypeP(column_index_array), - true, 2, 's', + INT2OID, 2, true, 's', &keys, &nKeys); for (j = 0; j < nKeys; j++) diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 5be34e6199..1b2553ec94 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.69 2002/08/04 06:44:47 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.70 2002/08/26 17:53:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -24,6 +24,7 @@ #include "access/hash.h" #include "access/xact.h" +#include "catalog/pg_type.h" #include "miscadmin.h" #include "utils/array.h" #include "utils/builtins.h" @@ -1917,7 +1918,7 @@ interval_accum(PG_FUNCTION_ARGS) /* We assume the input is array of interval */ deconstruct_array(transarray, - false, 12, 'd', + INTERVALOID, 12, false, 'd', &transdatums, &ndatums); if (ndatums != 2) elog(ERROR, "interval_accum: expected 2-element interval array"); @@ -1943,7 +1944,7 @@ interval_accum(PG_FUNCTION_ARGS) transdatums[1] = IntervalPGetDatum(&N); result = construct_array(transdatums, 2, - false, 12, 'd'); + INTERVALOID, 12, false, 'd'); PG_RETURN_ARRAYTYPE_P(result); } @@ -1959,7 +1960,7 @@ interval_avg(PG_FUNCTION_ARGS) /* We assume the input is array of interval */ deconstruct_array(transarray, - false, 12, 'd', + INTERVALOID, 12, false, 'd', &transdatums, &ndatums); if (ndatums != 2) elog(ERROR, "interval_avg: expected 2-element interval array"); diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index 8779acddb4..97c3567f1a 100644 --- a/src/backend/utils/adt/varbit.c +++ b/src/backend/utils/adt/varbit.c @@ -9,7 +9,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.23 2002/08/04 06:33:48 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.24 2002/08/26 17:53:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -226,7 +226,7 @@ bit(PG_FUNCTION_ARGS) Datum _bit(PG_FUNCTION_ARGS) { - ArrayType *v = (ArrayType *) PG_GETARG_VARLENA_P(0); + ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); int32 len = PG_GETARG_INT32(1); FunctionCallInfoData locfcinfo; @@ -439,7 +439,7 @@ varbit(PG_FUNCTION_ARGS) Datum _varbit(PG_FUNCTION_ARGS) { - ArrayType *v = (ArrayType *) PG_GETARG_VARLENA_P(0); + ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); int32 len = PG_GETARG_INT32(1); FunctionCallInfoData locfcinfo; diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index 2520d415d5..cdf5c301d2 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.90 2002/06/20 20:29:38 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.91 2002/08/26 17:53:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -283,7 +283,7 @@ bpchar(PG_FUNCTION_ARGS) Datum _bpchar(PG_FUNCTION_ARGS) { - ArrayType *v = (ArrayType *) PG_GETARG_VARLENA_P(0); + ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); int32 len = PG_GETARG_INT32(1); FunctionCallInfoData locfcinfo; @@ -533,7 +533,7 @@ varchar(PG_FUNCTION_ARGS) Datum _varchar(PG_FUNCTION_ARGS) { - ArrayType *v = (ArrayType *) PG_GETARG_VARLENA_P(0); + ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); int32 len = PG_GETARG_INT32(1); FunctionCallInfoData locfcinfo; diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index a916dc9401..079ba2152a 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.79 2002/08/22 00:01:44 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.80 2002/08/26 17:53:59 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -885,6 +885,30 @@ get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval) ReleaseSysCache(tp); } +/* + * get_typlenbyvalalign + * + * A three-fer: given the type OID, return typlen, typbyval, typalign. + */ +void +get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, + char *typalign) +{ + HeapTuple tp; + Form_pg_type typtup; + + tp = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typid), + 0, 0, 0); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for type %u", typid); + typtup = (Form_pg_type) GETSTRUCT(tp); + *typlen = typtup->typlen; + *typbyval = typtup->typbyval; + *typalign = typtup->typalign; + ReleaseSysCache(tp); +} + #ifdef NOT_USED char get_typalign(Oid typid) @@ -1287,7 +1311,9 @@ get_attstatsslot(HeapTuple statstuple, * Do initial examination of the array. This produces a list of * text Datums --- ie, pointers into the text array value. */ - deconstruct_array(statarray, false, -1, 'i', values, nvalues); + deconstruct_array(statarray, + TEXTOID, -1, false, 'i', + values, nvalues); narrayelem = *nvalues; /* @@ -1346,8 +1372,8 @@ get_attstatsslot(HeapTuple statstuple, */ narrayelem = ARR_DIMS(statarray)[0]; if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 || - ARR_SIZE(statarray) != (ARR_OVERHEAD(1) + narrayelem * sizeof(float4))) - elog(ERROR, "get_attstatsslot: stanumbers is bogus"); + ARR_ELEMTYPE(statarray) != FLOAT4OID) + elog(ERROR, "get_attstatsslot: stanumbers is not a 1-D float4 array"); *numbers = (float4 *) palloc(narrayelem * sizeof(float4)); memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4)); *nnumbers = narrayelem; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index a759b3f527..b73118289f 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -5,7 +5,7 @@ * command, configuration file, and command line options. * See src/backend/utils/misc/README for more information. * - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.83 2002/08/18 03:03:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.84 2002/08/26 17:53:59 tgl Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut . @@ -2680,6 +2680,7 @@ assign_defaultxactisolevel(const char *newval, bool doit, bool interactive) /* * Handle options fetched from pg_database.datconfig or pg_shadow.useconfig. + * The array parameter must be an array of TEXT. */ void ProcessGUCArray(ArrayType *array, GucSource source) @@ -2687,6 +2688,9 @@ ProcessGUCArray(ArrayType *array, GucSource source) int i; Assert(array != NULL); + Assert(ARR_ELEMTYPE(array) == TEXTOID); + Assert(ARR_NDIM(array) == 1); + Assert(ARR_LBOUND(array)[0] == 1); Assert(source == PGC_S_DATABASE || source == PGC_S_USER); for (i = 1; i <= ARR_DIMS(array)[0]; i++) @@ -2698,9 +2702,10 @@ ProcessGUCArray(ArrayType *array, GucSource source) char *value; d = array_ref(array, 1, &i, - false /*notbyvalue*/, - -1 /*varlenelem*/, -1 /*varlenarray*/, + -1 /*TEXT's typlen*/, + false /*TEXT's typbyval*/, + 'i' /*TEXT's typalign*/, &isnull); if (isnull) @@ -2756,6 +2761,10 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value) bool isnull; int i; + Assert(ARR_ELEMTYPE(array) == TEXTOID); + Assert(ARR_NDIM(array) == 1); + Assert(ARR_LBOUND(array)[0] == 1); + index = ARR_DIMS(array)[0] + 1; /* add after end */ for (i = 1; i <= ARR_DIMS(array)[0]; i++) @@ -2764,10 +2773,13 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value) char *current; d = array_ref(array, 1, &i, - false /*notbyvalue*/, - -1 /*varlenelem*/, -1 /*varlenarray*/, + -1 /*TEXT's typlen*/, + false /*TEXT's typbyval*/, + 'i' /*TEXT's typalign*/, &isnull); + if (isnull) + continue; current = DatumGetCString(DirectFunctionCall1(textout, d)); if (strncmp(current, newval, strlen(name) + 1)==0) { @@ -2777,10 +2789,18 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value) } isnull = false; - a = array_set(array, 1, &index, datum, false/*notbyval*/, -1, -1, &isnull); + a = array_set(array, 1, &index, + datum, + -1 /*varlenarray*/, + -1 /*TEXT's typlen*/, + false /*TEXT's typbyval*/, + 'i' /*TEXT's typalign*/, + &isnull); } else - a = construct_array(&datum, 1, false, -1, 'i'); + a = construct_array(&datum, 1, + TEXTOID, + -1, false, 'i'); return a; } @@ -2802,7 +2822,9 @@ GUCArrayDelete(ArrayType *array, const char *name) superuser() ? PGC_SUSET : PGC_USERSET, PGC_S_SESSION, false, false); - newarray = construct_array(NULL, 0, false, -1, 'i'); + newarray = construct_array(NULL, 0, + TEXTOID, + -1, false, 'i'); index = 1; for (i = 1; i <= ARR_DIMS(array)[0]; i++) @@ -2812,10 +2834,13 @@ GUCArrayDelete(ArrayType *array, const char *name) bool isnull; d = array_ref(array, 1, &i, - false /*notbyvalue*/, - -1 /*varlenelem*/, -1 /*varlenarray*/, + -1 /*TEXT's typlen*/, + false /*TEXT's typbyval*/, + 'i' /*TEXT's typalign*/, &isnull); + if (isnull) + continue; val = DatumGetCString(DirectFunctionCall1(textout, d)); if (strncmp(val, name, strlen(name))==0 @@ -2823,7 +2848,13 @@ GUCArrayDelete(ArrayType *array, const char *name) continue; isnull = false; - newarray = array_set(newarray, 1, &index, d, false/*notbyval*/, -1, -1, &isnull); + newarray = array_set(newarray, 1, &index, + d, + -1 /*varlenarray*/, + -1 /*TEXT's typlen*/, + false /*TEXT's typbyval*/, + 'i' /*TEXT's typalign*/, + &isnull); index++; } diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index a45b775dc7..4656f2ee97 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catversion.h,v 1.152 2002/08/24 15:00:46 tgl Exp $ + * $Id: catversion.h,v 1.153 2002/08/26 17:53:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200208231 +#define CATALOG_VERSION_NO 200208251 #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 4129ea73b4..1e0c775b53 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_proc.h,v 1.264 2002/08/23 16:41:37 tgl Exp $ + * $Id: pg_proc.h,v 1.265 2002/08/26 17:53:59 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -985,9 +985,9 @@ DESCR("session user name"); DATA(insert OID = 747 ( array_dims PGNSP PGUID 12 f f t f i 1 25 "2277" array_dims - _null_ )); DESCR("array dimensions"); -DATA(insert OID = 750 ( array_in PGNSP PGUID 12 f f t f i 3 2277 "2275 26 23" array_in - _null_ )); +DATA(insert OID = 750 ( array_in PGNSP PGUID 12 f f t f s 3 2277 "2275 26 23" array_in - _null_ )); DESCR("array"); -DATA(insert OID = 751 ( array_out PGNSP PGUID 12 f f t f i 2 2275 "2281 26" array_out - _null_ )); +DATA(insert OID = 751 ( array_out PGNSP PGUID 12 f f t f s 1 2275 "2277" array_out - _null_ )); DESCR("array"); DATA(insert OID = 760 ( smgrin PGNSP PGUID 12 f f t f s 1 210 "2275" smgrin - _null_ )); @@ -3083,7 +3083,7 @@ DATA(insert OID = 2295 ( any_out PGNSP PGUID 12 f f t f i 1 2275 "2276" any_o DESCR("(internal)"); DATA(insert OID = 2296 ( anyarray_in PGNSP PGUID 12 f f t f i 1 2277 "2275" anyarray_in - _null_ )); DESCR("(internal)"); -DATA(insert OID = 2297 ( anyarray_out PGNSP PGUID 12 f f t f i 1 2275 "2277" anyarray_out - _null_ )); +DATA(insert OID = 2297 ( anyarray_out PGNSP PGUID 12 f f t f s 1 2275 "2277" anyarray_out - _null_ )); DESCR("(internal)"); DATA(insert OID = 2298 ( void_in PGNSP PGUID 12 f f t f i 1 2278 "2275" void_in - _null_ )); DESCR("(internal)"); diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index e72a9c4c84..8efb6c07a3 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_type.h,v 1.129 2002/08/24 15:00:46 tgl Exp $ + * $Id: pg_type.h,v 1.130 2002/08/26 17:54:01 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -413,6 +413,7 @@ DATA(insert OID = 1025 ( _tinterval PGNSP PGUID -1 f b t \054 0 704 array_in ar DATA(insert OID = 1027 ( _polygon PGNSP PGUID -1 f b t \054 0 604 array_in array_out d x f 0 -1 0 _null_ _null_ )); DATA(insert OID = 1033 ( aclitem PGNSP PGUID 8 f b t \054 0 0 aclitemin aclitemout i p f 0 -1 0 _null_ _null_ )); DESCR("access control list"); +#define ACLITEMOID 1033 DATA(insert OID = 1034 ( _aclitem PGNSP PGUID -1 f b t \054 0 1033 array_in array_out i x f 0 -1 0 _null_ _null_ )); DATA(insert OID = 1040 ( _macaddr PGNSP PGUID -1 f b t \054 0 829 array_in array_out i x f 0 -1 0 _null_ _null_ )); DATA(insert OID = 1041 ( _inet PGNSP PGUID -1 f b t \054 0 869 array_in array_out i x f 0 -1 0 _null_ _null_ )); diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 647ff8bb39..8fbb9442b4 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: primnodes.h,v 1.65 2002/07/04 15:24:11 thomas Exp $ + * $Id: primnodes.h,v 1.66 2002/08/26 17:54:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -397,20 +397,20 @@ typedef struct SubLink * varlena structures and have refattrlength = -1. In any case, * an array type is never pass-by-value. * - * Note: currently, refelemtype is NOT the element type, but the array type, - * when doing subarray fetch or either type of store. It would be cleaner - * to add more fields so we can distinguish the array element type from the - * result type of the ArrayRef operator... + * Note: refrestype is NOT the element type, but the array type, + * when doing subarray fetch or either type of store. It might be a good + * idea to include a refelemtype field as well. * ---------------- */ typedef struct ArrayRef { NodeTag type; + Oid refrestype; /* type of the result of the ArrayRef + * operation */ int refattrlength; /* typlen of array type */ int refelemlength; /* typlen of the array element type */ - Oid refelemtype; /* type of the result of the ArrayRef - * operation */ bool refelembyval; /* is the element type pass-by-value? */ + char refelemalign; /* typalign of the element type */ List *refupperindexpr;/* expressions that evaluate to upper * array indexes */ List *reflowerindexpr;/* expressions that evaluate to lower diff --git a/src/include/utils/array.h b/src/include/utils/array.h index 459d2caaff..b0920c70d9 100644 --- a/src/include/utils/array.h +++ b/src/include/utils/array.h @@ -10,13 +10,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: array.h,v 1.32 2002/06/20 20:29:52 momjian Exp $ - * - * NOTES - * XXX the data array should be MAXALIGN'd -- currently we only INTALIGN - * which is NOT good enough for, eg, arrays of Interval. Changing this - * will break existing user tables so hold off until we have some other - * reason to break user tables (like WAL). + * $Id: array.h,v 1.33 2002/08/26 17:54:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -35,6 +29,7 @@ typedef struct int ndim; /* # of dimensions */ int flags; /* implementation flags */ /* flags field is currently unused, always zero. */ + Oid elemtype; /* element type OID */ } ArrayType; /* @@ -61,6 +56,7 @@ typedef struct */ #define ARR_SIZE(a) (((ArrayType *) (a))->size) #define ARR_NDIM(a) (((ArrayType *) (a))->ndim) +#define ARR_ELEMTYPE(a) (((ArrayType *) (a))->elemtype) #define ARR_DIMS(a) \ ((int *) (((char *) (a)) + sizeof(ArrayType))) @@ -90,29 +86,31 @@ extern Datum array_eq(PG_FUNCTION_ARGS); extern Datum array_dims(PG_FUNCTION_ARGS); extern Datum array_ref(ArrayType *array, int nSubscripts, int *indx, - bool elmbyval, int elmlen, - int arraylen, bool *isNull); + int arraylen, int elmlen, bool elmbyval, char elmalign, + bool *isNull); extern ArrayType *array_set(ArrayType *array, int nSubscripts, int *indx, Datum dataValue, - bool elmbyval, int elmlen, - int arraylen, bool *isNull); + int arraylen, int elmlen, bool elmbyval, char elmalign, + bool *isNull); extern ArrayType *array_get_slice(ArrayType *array, int nSubscripts, int *upperIndx, int *lowerIndx, - bool elmbyval, int elmlen, - int arraylen, bool *isNull); + int arraylen, int elmlen, bool elmbyval, char elmalign, + bool *isNull); extern ArrayType *array_set_slice(ArrayType *array, int nSubscripts, int *upperIndx, int *lowerIndx, ArrayType *srcArray, - bool elmbyval, int elmlen, - int arraylen, bool *isNull); + int arraylen, int elmlen, bool elmbyval, char elmalign, + bool *isNull); extern Datum array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType); extern ArrayType *construct_array(Datum *elems, int nelems, - bool elmbyval, int elmlen, char elmalign); + Oid elmtype, + int elmlen, bool elmbyval, char elmalign); extern void deconstruct_array(ArrayType *array, - bool elmbyval, int elmlen, char elmalign, - Datum **elemsp, int *nelemsp); + Oid elmtype, + int elmlen, bool elmbyval, char elmalign, + Datum **elemsp, int *nelemsp); /* diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index ccd385b777..78d0990865 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: lsyscache.h,v 1.58 2002/08/22 00:01:49 tgl Exp $ + * $Id: lsyscache.h,v 1.59 2002/08/26 17:54:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,6 +49,8 @@ extern bool get_typisdefined(Oid typid); extern int16 get_typlen(Oid typid); extern bool get_typbyval(Oid typid); extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval); +extern void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, + char *typalign); extern char get_typstorage(Oid typid); extern Node *get_typdefault(Oid typid); extern char get_typtype(Oid typid); diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out index 7f606ec976..50000afcf9 100644 --- a/src/test/regress/expected/type_sanity.out +++ b/src/test/regress/expected/type_sanity.out @@ -132,7 +132,7 @@ FROM pg_type AS p1, pg_proc AS p2 WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT ((p2.pronargs = 1 AND p2.proargtypes[0] = p1.oid) OR (p2.oid = 'array_out'::regproc AND - p1.typelem != 0)); + p1.typelem != 0 AND p1.typlen = -1)); oid | typname | oid | proname ------+-----------+-----+------------ 32 | SET | 110 | unknownout diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql index 7bea3058b4..3b297b3694 100644 --- a/src/test/regress/sql/type_sanity.sql +++ b/src/test/regress/sql/type_sanity.sql @@ -108,7 +108,7 @@ FROM pg_type AS p1, pg_proc AS p2 WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT ((p2.pronargs = 1 AND p2.proargtypes[0] = p1.oid) OR (p2.oid = 'array_out'::regproc AND - p1.typelem != 0)); + p1.typelem != 0 AND p1.typlen = -1)); SELECT p1.oid, p1.typname, p2.oid, p2.proname FROM pg_type AS p1, pg_proc AS p2