From 5cabcfccce4b8b826c9b30828f3012b7926a6946 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 26 Aug 2002 17:54:02 +0000 Subject: [PATCH] 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. --- contrib/array/README.array_iterator | 8 +- contrib/array/array_iterator.c | 144 ++++----- contrib/array/array_iterator.h | 43 ++- contrib/array/array_iterator.sql.in | 60 ++-- contrib/dblink/dblink.c | 5 + contrib/intagg/int_aggregate.c | 8 +- contrib/ltree/_ltree_gist.c | 2 +- contrib/ltree/_ltree_op.c | 18 +- src/backend/catalog/pg_constraint.c | 7 +- src/backend/commands/analyze.c | 8 +- src/backend/executor/execQual.c | 25 +- src/backend/nodes/copyfuncs.c | 5 +- src/backend/nodes/equalfuncs.c | 10 +- src/backend/nodes/outfuncs.c | 14 +- src/backend/nodes/readfuncs.c | 16 +- src/backend/parser/parse_expr.c | 4 +- src/backend/parser/parse_node.c | 7 +- src/backend/rewrite/rewriteHandler.c | 6 +- src/backend/utils/adt/acl.c | 4 +- src/backend/utils/adt/arrayfuncs.c | 372 +++++++++++++--------- src/backend/utils/adt/float.c | 15 +- src/backend/utils/adt/name.c | 6 +- src/backend/utils/adt/numeric.c | 13 +- src/backend/utils/adt/pseudotypes.c | 9 +- src/backend/utils/adt/ruleutils.c | 4 +- src/backend/utils/adt/timestamp.c | 9 +- src/backend/utils/adt/varbit.c | 6 +- src/backend/utils/adt/varchar.c | 6 +- src/backend/utils/cache/lsyscache.c | 34 +- src/backend/utils/misc/guc.c | 53 ++- src/include/catalog/catversion.h | 4 +- src/include/catalog/pg_proc.h | 8 +- src/include/catalog/pg_type.h | 3 +- src/include/nodes/primnodes.h | 14 +- src/include/utils/array.h | 34 +- src/include/utils/lsyscache.h | 4 +- src/test/regress/expected/type_sanity.out | 2 +- src/test/regress/sql/type_sanity.sql | 2 +- 38 files changed, 558 insertions(+), 434 deletions(-) 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 -- GitLab