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.
This commit is contained in:
parent
8009c27592
commit
5cabcfccce
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ");
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
* <nbytes> - total number of bytes
|
||||
/*----------
|
||||
* A standard varlena array has the following internal structure:
|
||||
* <size> - total number of bytes (also, TOAST info flags)
|
||||
* <ndim> - number of dimensions of the array
|
||||
* <flags> - bit mask of flags
|
||||
* <dim> - size of each array axis
|
||||
* <dim_lower> - lower boundary of each dimension
|
||||
* <elemtype> - element type OID
|
||||
* <dim> - size of each array axis (C array of int)
|
||||
* <dim_lower> - lower boundary of each dimension (C array of int)
|
||||
* <actual data> - 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 <dim_lower> 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 if (typlen == -1)
|
||||
{
|
||||
/* 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
|
||||
{
|
||||
*nbytes += sizeof(int32);
|
||||
values[i] = PointerGetDatum(palloc(sizeof(int32)));
|
||||
VARATT_SIZEP(DatumGetPointer(values[i])) = sizeof(int32);
|
||||
/* 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 */
|
||||
|
|
|
@ -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 <ieeefp.h>
|
||||
#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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <peter_e@gmx.net>.
|
||||
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)");
|
||||
|
|
|
@ -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_ ));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue