mirror of
https://github.com/postgres/postgres.git
synced 2026-04-15 22:10:45 -04:00
Refactor att_align_nominal() to improve performance.
Separate att_align_nominal() into two macros, similarly to what was already done with att_align_datum() and att_align_pointer(). The inner macro att_nominal_alignby() is really just TYPEALIGN(), while att_align_nominal() retains its previous API by mapping TYPALIGN_xxx values to numbers of bytes to align to and then calling att_nominal_alignby(). In support of this, split out tupdesc.c's logic to do that mapping into a publicly visible function typalign_to_alignby(). Having done that, we can replace performance-critical uses of att_align_nominal() with att_nominal_alignby(), where the typalign_to_alignby() mapping is done just once outside the loop. In most places I settled for doing typalign_to_alignby() once per function. We could in many places pass the alignby value in from the caller if we wanted to change function APIs for this purpose; but I'm a bit loath to do that, especially for exported APIs that extensions might call. Replacing a char typalign argument by a uint8 typalignby argument would be an API change that compilers would fail to warn about, thus silently breaking code in hard-to-debug ways. I did revise the APIs of array_iter_setup and array_iter_next, moving the element type attribute arguments to the former; if any external code uses those, the argument-count change will cause visible compile failures. Performance testing shows that ExecEvalScalarArrayOp is sped up by about 10% by this change, when using a simple per-element function such as int8eq. I did not check any of the other loops optimized here, but it's reasonable to expect similar gains. Although the motivation for creating this patch was to avoid a performance loss if we add some more typalign values, it evidently is worth doing whether that patch lands or not. Discussion: https://postgr.es/m/1127261.1769649624@sss.pgh.pa.us
This commit is contained in:
parent
0c9f46c428
commit
da7a1dc0d6
10 changed files with 166 additions and 119 deletions
|
|
@ -2069,6 +2069,7 @@ get_text_array_contents(ArrayType *array, int *numitems)
|
|||
int16 typlen;
|
||||
bool typbyval;
|
||||
char typalign;
|
||||
uint8 typalignby;
|
||||
char **values;
|
||||
char *ptr;
|
||||
bits8 *bitmap;
|
||||
|
|
@ -2081,6 +2082,7 @@ get_text_array_contents(ArrayType *array, int *numitems)
|
|||
|
||||
get_typlenbyvalalign(ARR_ELEMTYPE(array),
|
||||
&typlen, &typbyval, &typalign);
|
||||
typalignby = typalign_to_alignby(typalign);
|
||||
|
||||
values = palloc_array(char *, nitems);
|
||||
|
||||
|
|
@ -2098,7 +2100,7 @@ get_text_array_contents(ArrayType *array, int *numitems)
|
|||
{
|
||||
values[i] = TextDatumGetCString(PointerGetDatum(ptr));
|
||||
ptr = att_addlength_pointer(ptr, typlen, ptr);
|
||||
ptr = (char *) att_align_nominal(ptr, typalign);
|
||||
ptr = (char *) att_nominal_alignby(ptr, typalignby);
|
||||
}
|
||||
|
||||
/* advance bitmap pointer if any */
|
||||
|
|
|
|||
|
|
@ -86,25 +86,8 @@ populate_compact_attribute_internal(Form_pg_attribute src,
|
|||
IsCatalogRelationOid(src->attrelid) ? ATTNULLABLE_VALID :
|
||||
ATTNULLABLE_UNKNOWN;
|
||||
|
||||
switch (src->attalign)
|
||||
{
|
||||
case TYPALIGN_INT:
|
||||
dst->attalignby = ALIGNOF_INT;
|
||||
break;
|
||||
case TYPALIGN_CHAR:
|
||||
dst->attalignby = sizeof(char);
|
||||
break;
|
||||
case TYPALIGN_DOUBLE:
|
||||
dst->attalignby = ALIGNOF_DOUBLE;
|
||||
break;
|
||||
case TYPALIGN_SHORT:
|
||||
dst->attalignby = ALIGNOF_SHORT;
|
||||
break;
|
||||
default:
|
||||
dst->attalignby = 0;
|
||||
elog(ERROR, "invalid attalign value: %c", src->attalign);
|
||||
break;
|
||||
}
|
||||
/* Compute numeric alignment requirement, too */
|
||||
dst->attalignby = typalign_to_alignby(src->attalign);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -4032,6 +4032,7 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
|
|||
int16 typlen;
|
||||
bool typbyval;
|
||||
char typalign;
|
||||
uint8 typalignby;
|
||||
char *s;
|
||||
bits8 *bitmap;
|
||||
int bitmask;
|
||||
|
|
@ -4086,6 +4087,7 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
|
|||
typlen = op->d.scalararrayop.typlen;
|
||||
typbyval = op->d.scalararrayop.typbyval;
|
||||
typalign = op->d.scalararrayop.typalign;
|
||||
typalignby = typalign_to_alignby(typalign);
|
||||
|
||||
/* Initialize result appropriately depending on useOr */
|
||||
result = BoolGetDatum(!useOr);
|
||||
|
|
@ -4111,7 +4113,7 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
|
|||
{
|
||||
elt = fetch_att(s, typbyval, typlen);
|
||||
s = att_addlength_pointer(s, typlen, s);
|
||||
s = (char *) att_align_nominal(s, typalign);
|
||||
s = (char *) att_nominal_alignby(s, typalignby);
|
||||
fcinfo->args[1].value = elt;
|
||||
fcinfo->args[1].isnull = false;
|
||||
}
|
||||
|
|
@ -4255,6 +4257,7 @@ ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op, ExprContext *eco
|
|||
int16 typlen;
|
||||
bool typbyval;
|
||||
char typalign;
|
||||
uint8 typalignby;
|
||||
int nitems;
|
||||
bool has_nulls = false;
|
||||
char *s;
|
||||
|
|
@ -4272,6 +4275,7 @@ ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op, ExprContext *eco
|
|||
&typlen,
|
||||
&typbyval,
|
||||
&typalign);
|
||||
typalignby = typalign_to_alignby(typalign);
|
||||
|
||||
oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
|
||||
|
||||
|
|
@ -4318,7 +4322,7 @@ ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op, ExprContext *eco
|
|||
|
||||
element = fetch_att(s, typbyval, typlen);
|
||||
s = att_addlength_pointer(s, typlen, s);
|
||||
s = (char *) att_align_nominal(s, typalign);
|
||||
s = (char *) att_nominal_alignby(s, typalignby);
|
||||
|
||||
saophash_insert(elements_tab->hashtab, element, &hashfound);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,6 +238,7 @@ EA_get_flat_size(ExpandedObjectHeader *eohptr)
|
|||
Datum *dvalues;
|
||||
bool *dnulls;
|
||||
Size nbytes;
|
||||
uint8 typalignby;
|
||||
int i;
|
||||
|
||||
Assert(eah->ea_magic == EA_MAGIC);
|
||||
|
|
@ -261,12 +262,13 @@ EA_get_flat_size(ExpandedObjectHeader *eohptr)
|
|||
dvalues = eah->dvalues;
|
||||
dnulls = eah->dnulls;
|
||||
nbytes = 0;
|
||||
typalignby = typalign_to_alignby(eah->typalign);
|
||||
for (i = 0; i < nelems; i++)
|
||||
{
|
||||
if (dnulls && dnulls[i])
|
||||
continue;
|
||||
nbytes = att_addlength_datum(nbytes, eah->typlen, dvalues[i]);
|
||||
nbytes = att_align_nominal(nbytes, eah->typalign);
|
||||
nbytes = att_nominal_alignby(nbytes, typalignby);
|
||||
/* check for overflow of total request */
|
||||
if (!AllocSizeIsValid(nbytes))
|
||||
ereport(ERROR,
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ typedef struct ArrayIteratorData
|
|||
int16 typlen; /* element type's length */
|
||||
bool typbyval; /* element type's byval property */
|
||||
char typalign; /* element type's align property */
|
||||
uint8 typalignby; /* typalign mapped to numeric alignment */
|
||||
|
||||
/* information about the requested slice size */
|
||||
int slice_ndim; /* slice dimension, or 0 if not slicing */
|
||||
|
|
@ -123,7 +124,7 @@ static bool array_get_isnull(const bits8 *nullbitmap, int offset);
|
|||
static void array_set_isnull(bits8 *nullbitmap, int offset, bool isNull);
|
||||
static Datum ArrayCast(char *value, bool byval, int len);
|
||||
static int ArrayCastAndSet(Datum src,
|
||||
int typlen, bool typbyval, char typalign,
|
||||
int typlen, bool typbyval, uint8 typalignby,
|
||||
char *dest);
|
||||
static char *array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems,
|
||||
int typlen, bool typbyval, char typalign);
|
||||
|
|
@ -187,6 +188,7 @@ array_in(PG_FUNCTION_ARGS)
|
|||
int typlen;
|
||||
bool typbyval;
|
||||
char typalign;
|
||||
uint8 typalignby;
|
||||
char typdelim;
|
||||
Oid typioparam;
|
||||
char *p;
|
||||
|
|
@ -232,6 +234,7 @@ array_in(PG_FUNCTION_ARGS)
|
|||
typlen = my_extra->typlen;
|
||||
typbyval = my_extra->typbyval;
|
||||
typalign = my_extra->typalign;
|
||||
typalignby = typalign_to_alignby(typalign);
|
||||
typdelim = my_extra->typdelim;
|
||||
typioparam = my_extra->typioparam;
|
||||
|
||||
|
|
@ -328,7 +331,7 @@ array_in(PG_FUNCTION_ARGS)
|
|||
if (typlen == -1)
|
||||
values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
|
||||
nbytes = att_addlength_datum(nbytes, typlen, values[i]);
|
||||
nbytes = att_align_nominal(nbytes, typalign);
|
||||
nbytes = att_nominal_alignby(nbytes, typalignby);
|
||||
/* check for overflow of total request */
|
||||
if (!AllocSizeIsValid(nbytes))
|
||||
ereturn(escontext, (Datum) 0,
|
||||
|
|
@ -972,6 +975,7 @@ CopyArrayEls(ArrayType *array,
|
|||
bits8 *bitmap = ARR_NULLBITMAP(array);
|
||||
int bitval = 0;
|
||||
int bitmask = 1;
|
||||
uint8 typalignby = typalign_to_alignby(typalign);
|
||||
int i;
|
||||
|
||||
if (typbyval)
|
||||
|
|
@ -988,7 +992,7 @@ CopyArrayEls(ArrayType *array,
|
|||
else
|
||||
{
|
||||
bitval |= bitmask;
|
||||
p += ArrayCastAndSet(values[i], typlen, typbyval, typalign, p);
|
||||
p += ArrayCastAndSet(values[i], typlen, typbyval, typalignby, p);
|
||||
if (freedata)
|
||||
pfree(DatumGetPointer(values[i]));
|
||||
}
|
||||
|
|
@ -1112,7 +1116,7 @@ array_out(PG_FUNCTION_ARGS)
|
|||
needquotes = (bool *) palloc(nitems * sizeof(bool));
|
||||
overall_length = 0;
|
||||
|
||||
array_iter_setup(&iter, v);
|
||||
array_iter_setup(&iter, v, typlen, typbyval, typalign);
|
||||
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
|
|
@ -1121,8 +1125,7 @@ array_out(PG_FUNCTION_ARGS)
|
|||
bool needquote;
|
||||
|
||||
/* Get source element, checking for NULL */
|
||||
itemvalue = array_iter_next(&iter, &isnull, i,
|
||||
typlen, typbyval, typalign);
|
||||
itemvalue = array_iter_next(&iter, &isnull, i);
|
||||
|
||||
if (isnull)
|
||||
{
|
||||
|
|
@ -1468,6 +1471,7 @@ ReadArrayBinary(StringInfo buf,
|
|||
int i;
|
||||
bool hasnull;
|
||||
int32 totbytes;
|
||||
uint8 typalignby = typalign_to_alignby(typalign);
|
||||
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
|
|
@ -1526,7 +1530,7 @@ ReadArrayBinary(StringInfo buf,
|
|||
if (typlen == -1)
|
||||
values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
|
||||
totbytes = att_addlength_datum(totbytes, typlen, values[i]);
|
||||
totbytes = att_align_nominal(totbytes, typalign);
|
||||
totbytes = att_nominal_alignby(totbytes, typalignby);
|
||||
/* check for overflow of total request */
|
||||
if (!AllocSizeIsValid(totbytes))
|
||||
ereport(ERROR,
|
||||
|
|
@ -1614,7 +1618,7 @@ array_send(PG_FUNCTION_ARGS)
|
|||
}
|
||||
|
||||
/* Send the array elements using the element's own sendproc */
|
||||
array_iter_setup(&iter, v);
|
||||
array_iter_setup(&iter, v, typlen, typbyval, typalign);
|
||||
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
|
|
@ -1622,8 +1626,7 @@ array_send(PG_FUNCTION_ARGS)
|
|||
bool isnull;
|
||||
|
||||
/* Get source element, checking for NULL */
|
||||
itemvalue = array_iter_next(&iter, &isnull, i,
|
||||
typlen, typbyval, typalign);
|
||||
itemvalue = array_iter_next(&iter, &isnull, i);
|
||||
|
||||
if (isnull)
|
||||
{
|
||||
|
|
@ -2231,6 +2234,7 @@ array_set_element(Datum arraydatum,
|
|||
addedafter,
|
||||
lenbefore,
|
||||
lenafter;
|
||||
uint8 elmalignby = typalign_to_alignby(elmalign);
|
||||
|
||||
if (arraytyplen > 0)
|
||||
{
|
||||
|
|
@ -2258,7 +2262,7 @@ array_set_element(Datum arraydatum,
|
|||
resultarray = (char *) palloc(arraytyplen);
|
||||
memcpy(resultarray, DatumGetPointer(arraydatum), arraytyplen);
|
||||
elt_ptr = resultarray + indx[0] * elmlen;
|
||||
ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign, elt_ptr);
|
||||
ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalignby, elt_ptr);
|
||||
return PointerGetDatum(resultarray);
|
||||
}
|
||||
|
||||
|
|
@ -2416,7 +2420,7 @@ array_set_element(Datum arraydatum,
|
|||
else
|
||||
{
|
||||
olditemlen = att_addlength_pointer(0, elmlen, elt_ptr);
|
||||
olditemlen = att_align_nominal(olditemlen, elmalign);
|
||||
olditemlen = att_nominal_alignby(olditemlen, elmalignby);
|
||||
}
|
||||
lenafter = olddatasize - lenbefore - olditemlen;
|
||||
}
|
||||
|
|
@ -2426,7 +2430,7 @@ array_set_element(Datum arraydatum,
|
|||
else
|
||||
{
|
||||
newitemlen = att_addlength_datum(0, elmlen, dataValue);
|
||||
newitemlen = att_align_nominal(newitemlen, elmalign);
|
||||
newitemlen = att_nominal_alignby(newitemlen, elmalignby);
|
||||
}
|
||||
|
||||
newsize = overheadlen + lenbefore + newitemlen + lenafter;
|
||||
|
|
@ -2449,7 +2453,7 @@ array_set_element(Datum arraydatum,
|
|||
(char *) array + oldoverheadlen,
|
||||
lenbefore);
|
||||
if (!isNull)
|
||||
ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalign,
|
||||
ArrayCastAndSet(dataValue, elmlen, elmbyval, elmalignby,
|
||||
(char *) newarray + overheadlen + lenbefore);
|
||||
memcpy((char *) newarray + overheadlen + lenbefore + newitemlen,
|
||||
(char *) array + oldoverheadlen + lenbefore + olditemlen,
|
||||
|
|
@ -3221,6 +3225,7 @@ array_map(Datum arrayd,
|
|||
int typlen;
|
||||
bool typbyval;
|
||||
char typalign;
|
||||
uint8 typalignby;
|
||||
array_iter iter;
|
||||
ArrayMetaState *inp_extra;
|
||||
ArrayMetaState *ret_extra;
|
||||
|
|
@ -3270,21 +3275,21 @@ array_map(Datum arrayd,
|
|||
typlen = ret_extra->typlen;
|
||||
typbyval = ret_extra->typbyval;
|
||||
typalign = ret_extra->typalign;
|
||||
typalignby = typalign_to_alignby(typalign);
|
||||
|
||||
/* Allocate temporary arrays for new values */
|
||||
values = (Datum *) palloc(nitems * sizeof(Datum));
|
||||
nulls = (bool *) palloc(nitems * sizeof(bool));
|
||||
|
||||
/* Loop over source data */
|
||||
array_iter_setup(&iter, v);
|
||||
array_iter_setup(&iter, v, inp_typlen, inp_typbyval, inp_typalign);
|
||||
hasnulls = false;
|
||||
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
/* Get source element, checking for NULL */
|
||||
*transform_source =
|
||||
array_iter_next(&iter, transform_source_isnull, i,
|
||||
inp_typlen, inp_typbyval, inp_typalign);
|
||||
array_iter_next(&iter, transform_source_isnull, i);
|
||||
|
||||
/* Apply the given expression to source element */
|
||||
values[i] = ExecEvalExpr(exprstate, econtext, &nulls[i]);
|
||||
|
|
@ -3298,7 +3303,7 @@ array_map(Datum arrayd,
|
|||
values[i] = PointerGetDatum(PG_DETOAST_DATUM(values[i]));
|
||||
/* Update total result size */
|
||||
nbytes = att_addlength_datum(nbytes, typlen, values[i]);
|
||||
nbytes = att_align_nominal(nbytes, typalign);
|
||||
nbytes = att_nominal_alignby(nbytes, typalignby);
|
||||
/* check for overflow of total request */
|
||||
if (!AllocSizeIsValid(nbytes))
|
||||
ereport(ERROR,
|
||||
|
|
@ -3505,6 +3510,7 @@ construct_md_array(Datum *elems,
|
|||
int32 dataoffset;
|
||||
int i;
|
||||
int nelems;
|
||||
uint8 elmalignby = typalign_to_alignby(elmalign);
|
||||
|
||||
if (ndims < 0) /* we do allow zero-dimension arrays */
|
||||
ereport(ERROR,
|
||||
|
|
@ -3538,7 +3544,7 @@ construct_md_array(Datum *elems,
|
|||
if (elmlen == -1)
|
||||
elems[i] = PointerGetDatum(PG_DETOAST_DATUM(elems[i]));
|
||||
nbytes = att_addlength_datum(nbytes, elmlen, elems[i]);
|
||||
nbytes = att_align_nominal(nbytes, elmalign);
|
||||
nbytes = att_nominal_alignby(nbytes, elmalignby);
|
||||
/* check for overflow of total request */
|
||||
if (!AllocSizeIsValid(nbytes))
|
||||
ereport(ERROR,
|
||||
|
|
@ -3641,6 +3647,7 @@ deconstruct_array(const ArrayType *array,
|
|||
bits8 *bitmap;
|
||||
int bitmask;
|
||||
int i;
|
||||
uint8 elmalignby = typalign_to_alignby(elmalign);
|
||||
|
||||
Assert(ARR_ELEMTYPE(array) == elmtype);
|
||||
|
||||
|
|
@ -3673,7 +3680,7 @@ deconstruct_array(const ArrayType *array,
|
|||
{
|
||||
elems[i] = fetch_att(p, elmbyval, elmlen);
|
||||
p = att_addlength_pointer(p, elmlen, p);
|
||||
p = (char *) att_align_nominal(p, elmalign);
|
||||
p = (char *) att_nominal_alignby(p, elmalignby);
|
||||
}
|
||||
|
||||
/* advance bitmap pointer if any */
|
||||
|
|
@ -3878,8 +3885,8 @@ array_eq(PG_FUNCTION_ARGS)
|
|||
|
||||
/* Loop over source data */
|
||||
nitems = ArrayGetNItems(ndims1, dims1);
|
||||
array_iter_setup(&it1, array1);
|
||||
array_iter_setup(&it2, array2);
|
||||
array_iter_setup(&it1, array1, typlen, typbyval, typalign);
|
||||
array_iter_setup(&it2, array2, typlen, typbyval, typalign);
|
||||
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
|
|
@ -3890,10 +3897,8 @@ array_eq(PG_FUNCTION_ARGS)
|
|||
bool oprresult;
|
||||
|
||||
/* Get elements, checking for NULL */
|
||||
elt1 = array_iter_next(&it1, &isnull1, i,
|
||||
typlen, typbyval, typalign);
|
||||
elt2 = array_iter_next(&it2, &isnull2, i,
|
||||
typlen, typbyval, typalign);
|
||||
elt1 = array_iter_next(&it1, &isnull1, i);
|
||||
elt2 = array_iter_next(&it2, &isnull2, i);
|
||||
|
||||
/*
|
||||
* We consider two NULLs equal; NULL and not-NULL are unequal.
|
||||
|
|
@ -4042,8 +4047,8 @@ array_cmp(FunctionCallInfo fcinfo)
|
|||
|
||||
/* Loop over source data */
|
||||
min_nitems = Min(nitems1, nitems2);
|
||||
array_iter_setup(&it1, array1);
|
||||
array_iter_setup(&it2, array2);
|
||||
array_iter_setup(&it1, array1, typlen, typbyval, typalign);
|
||||
array_iter_setup(&it2, array2, typlen, typbyval, typalign);
|
||||
|
||||
for (i = 0; i < min_nitems; i++)
|
||||
{
|
||||
|
|
@ -4054,8 +4059,8 @@ array_cmp(FunctionCallInfo fcinfo)
|
|||
int32 cmpresult;
|
||||
|
||||
/* Get elements, checking for NULL */
|
||||
elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
|
||||
elt2 = array_iter_next(&it2, &isnull2, i, typlen, typbyval, typalign);
|
||||
elt1 = array_iter_next(&it1, &isnull1, i);
|
||||
elt2 = array_iter_next(&it2, &isnull2, i);
|
||||
|
||||
/*
|
||||
* We consider two NULLs equal; NULL > not-NULL.
|
||||
|
|
@ -4238,7 +4243,7 @@ hash_array(PG_FUNCTION_ARGS)
|
|||
|
||||
/* Loop over source data */
|
||||
nitems = ArrayGetNItems(ndims, dims);
|
||||
array_iter_setup(&iter, array);
|
||||
array_iter_setup(&iter, array, typlen, typbyval, typalign);
|
||||
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
|
|
@ -4247,7 +4252,7 @@ hash_array(PG_FUNCTION_ARGS)
|
|||
uint32 elthash;
|
||||
|
||||
/* Get element, checking for NULL */
|
||||
elt = array_iter_next(&iter, &isnull, i, typlen, typbyval, typalign);
|
||||
elt = array_iter_next(&iter, &isnull, i);
|
||||
|
||||
if (isnull)
|
||||
{
|
||||
|
|
@ -4328,7 +4333,7 @@ hash_array_extended(PG_FUNCTION_ARGS)
|
|||
|
||||
/* Loop over source data */
|
||||
nitems = ArrayGetNItems(ndims, dims);
|
||||
array_iter_setup(&iter, array);
|
||||
array_iter_setup(&iter, array, typlen, typbyval, typalign);
|
||||
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
|
|
@ -4337,7 +4342,7 @@ hash_array_extended(PG_FUNCTION_ARGS)
|
|||
uint64 elthash;
|
||||
|
||||
/* Get element, checking for NULL */
|
||||
elt = array_iter_next(&iter, &isnull, i, typlen, typbyval, typalign);
|
||||
elt = array_iter_next(&iter, &isnull, i);
|
||||
|
||||
if (isnull)
|
||||
{
|
||||
|
|
@ -4451,7 +4456,7 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation,
|
|||
|
||||
/* Loop over source data */
|
||||
nelems1 = ArrayGetNItems(AARR_NDIM(array1), AARR_DIMS(array1));
|
||||
array_iter_setup(&it1, array1);
|
||||
array_iter_setup(&it1, array1, typlen, typbyval, typalign);
|
||||
|
||||
for (i = 0; i < nelems1; i++)
|
||||
{
|
||||
|
|
@ -4459,7 +4464,7 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation,
|
|||
bool isnull1;
|
||||
|
||||
/* Get element, checking for NULL */
|
||||
elt1 = array_iter_next(&it1, &isnull1, i, typlen, typbyval, typalign);
|
||||
elt1 = array_iter_next(&it1, &isnull1, i);
|
||||
|
||||
/*
|
||||
* We assume that the comparison operator is strict, so a NULL can't
|
||||
|
|
@ -4626,6 +4631,7 @@ array_create_iterator(ArrayType *arr, int slice_ndim, ArrayMetaState *mstate)
|
|||
&iterator->typlen,
|
||||
&iterator->typbyval,
|
||||
&iterator->typalign);
|
||||
iterator->typalignby = typalign_to_alignby(iterator->typalign);
|
||||
|
||||
/*
|
||||
* Remember the slicing parameters.
|
||||
|
|
@ -4700,7 +4706,7 @@ array_iterate(ArrayIterator iterator, Datum *value, bool *isnull)
|
|||
|
||||
/* Move our data pointer forward to the next element */
|
||||
p = att_addlength_pointer(p, iterator->typlen, p);
|
||||
p = (char *) att_align_nominal(p, iterator->typalign);
|
||||
p = (char *) att_nominal_alignby(p, iterator->typalignby);
|
||||
iterator->data_ptr = p;
|
||||
}
|
||||
}
|
||||
|
|
@ -4730,7 +4736,7 @@ array_iterate(ArrayIterator iterator, Datum *value, bool *isnull)
|
|||
|
||||
/* Move our data pointer forward to the next element */
|
||||
p = att_addlength_pointer(p, iterator->typlen, p);
|
||||
p = (char *) att_align_nominal(p, iterator->typalign);
|
||||
p = (char *) att_nominal_alignby(p, iterator->typalignby);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4828,7 +4834,7 @@ static int
|
|||
ArrayCastAndSet(Datum src,
|
||||
int typlen,
|
||||
bool typbyval,
|
||||
char typalign,
|
||||
uint8 typalignby,
|
||||
char *dest)
|
||||
{
|
||||
int inc;
|
||||
|
|
@ -4839,14 +4845,14 @@ ArrayCastAndSet(Datum src,
|
|||
store_att_byval(dest, src, typlen);
|
||||
else
|
||||
memmove(dest, DatumGetPointer(src), typlen);
|
||||
inc = att_align_nominal(typlen, typalign);
|
||||
inc = att_nominal_alignby(typlen, typalignby);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert(!typbyval);
|
||||
inc = att_addlength_datum(0, typlen, src);
|
||||
memmove(dest, DatumGetPointer(src), inc);
|
||||
inc = att_align_nominal(inc, typalign);
|
||||
inc = att_nominal_alignby(inc, typalignby);
|
||||
}
|
||||
|
||||
return inc;
|
||||
|
|
@ -4867,12 +4873,13 @@ static char *
|
|||
array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems,
|
||||
int typlen, bool typbyval, char typalign)
|
||||
{
|
||||
uint8 typalignby = typalign_to_alignby(typalign);
|
||||
int bitmask;
|
||||
int i;
|
||||
|
||||
/* easy if fixed-size elements and no NULLs */
|
||||
if (typlen > 0 && !nullbitmap)
|
||||
return ptr + nitems * ((Size) att_align_nominal(typlen, typalign));
|
||||
return ptr + nitems * ((Size) att_nominal_alignby(typlen, typalignby));
|
||||
|
||||
/* seems worth having separate loops for NULL and no-NULLs cases */
|
||||
if (nullbitmap)
|
||||
|
|
@ -4885,7 +4892,7 @@ array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems,
|
|||
if (*nullbitmap & bitmask)
|
||||
{
|
||||
ptr = att_addlength_pointer(ptr, typlen, ptr);
|
||||
ptr = (char *) att_align_nominal(ptr, typalign);
|
||||
ptr = (char *) att_nominal_alignby(ptr, typalignby);
|
||||
}
|
||||
bitmask <<= 1;
|
||||
if (bitmask == 0x100)
|
||||
|
|
@ -4900,7 +4907,7 @@ array_seek(char *ptr, int offset, bits8 *nullbitmap, int nitems,
|
|||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
ptr = att_addlength_pointer(ptr, typlen, ptr);
|
||||
ptr = (char *) att_align_nominal(ptr, typalign);
|
||||
ptr = (char *) att_nominal_alignby(ptr, typalignby);
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
|
|
@ -5050,12 +5057,13 @@ array_slice_size(char *arraydataptr, bits8 *arraynullsptr,
|
|||
j,
|
||||
inc;
|
||||
int count = 0;
|
||||
uint8 typalignby = typalign_to_alignby(typalign);
|
||||
|
||||
mda_get_range(ndim, span, st, endp);
|
||||
|
||||
/* Pretty easy for fixed element length without nulls ... */
|
||||
if (typlen > 0 && !arraynullsptr)
|
||||
return ArrayGetNItems(ndim, span) * att_align_nominal(typlen, typalign);
|
||||
return ArrayGetNItems(ndim, span) * att_nominal_alignby(typlen, typalignby);
|
||||
|
||||
/* Else gotta do it the hard way */
|
||||
src_offset = ArrayGetOffset(ndim, dim, lb, st);
|
||||
|
|
@ -5077,7 +5085,7 @@ array_slice_size(char *arraydataptr, bits8 *arraynullsptr,
|
|||
if (!array_get_isnull(arraynullsptr, src_offset))
|
||||
{
|
||||
inc = att_addlength_pointer(0, typlen, ptr);
|
||||
inc = att_align_nominal(inc, typalign);
|
||||
inc = att_nominal_alignby(inc, typalignby);
|
||||
ptr += inc;
|
||||
count += inc;
|
||||
}
|
||||
|
|
@ -6096,6 +6104,7 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs,
|
|||
int16 elmlen;
|
||||
bool elmbyval;
|
||||
char elmalign;
|
||||
uint8 elmalignby;
|
||||
ArrayMetaState *my_extra;
|
||||
|
||||
/*
|
||||
|
|
@ -6190,6 +6199,7 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs,
|
|||
elmlen = my_extra->typlen;
|
||||
elmbyval = my_extra->typbyval;
|
||||
elmalign = my_extra->typalign;
|
||||
elmalignby = typalign_to_alignby(elmalign);
|
||||
|
||||
/* compute required space */
|
||||
if (!isnull)
|
||||
|
|
@ -6204,7 +6214,7 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs,
|
|||
value = PointerGetDatum(PG_DETOAST_DATUM(value));
|
||||
|
||||
nbytes = att_addlength_datum(0, elmlen, value);
|
||||
nbytes = att_align_nominal(nbytes, elmalign);
|
||||
nbytes = att_nominal_alignby(nbytes, elmalignby);
|
||||
Assert(nbytes > 0);
|
||||
|
||||
totbytes = nbytes * nitems;
|
||||
|
|
@ -6228,7 +6238,7 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs,
|
|||
|
||||
p = ARR_DATA_PTR(result);
|
||||
for (i = 0; i < nitems; i++)
|
||||
p += ArrayCastAndSet(value, elmlen, elmbyval, elmalign, p);
|
||||
p += ArrayCastAndSet(value, elmlen, elmbyval, elmalignby, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -6259,9 +6269,6 @@ array_unnest(PG_FUNCTION_ARGS)
|
|||
array_iter iter;
|
||||
int nextelem;
|
||||
int numelems;
|
||||
int16 elmlen;
|
||||
bool elmbyval;
|
||||
char elmalign;
|
||||
} array_unnest_fctx;
|
||||
|
||||
FuncCallContext *funcctx;
|
||||
|
|
@ -6272,6 +6279,9 @@ array_unnest(PG_FUNCTION_ARGS)
|
|||
if (SRF_IS_FIRSTCALL())
|
||||
{
|
||||
AnyArrayType *arr;
|
||||
int16 elmlen;
|
||||
bool elmbyval;
|
||||
char elmalign;
|
||||
|
||||
/* create a function context for cross-call persistence */
|
||||
funcctx = SRF_FIRSTCALL_INIT();
|
||||
|
|
@ -6293,23 +6303,24 @@ array_unnest(PG_FUNCTION_ARGS)
|
|||
/* allocate memory for user context */
|
||||
fctx = palloc_object(array_unnest_fctx);
|
||||
|
||||
/* initialize state */
|
||||
array_iter_setup(&fctx->iter, arr);
|
||||
fctx->nextelem = 0;
|
||||
fctx->numelems = ArrayGetNItems(AARR_NDIM(arr), AARR_DIMS(arr));
|
||||
|
||||
/* get element-type data */
|
||||
if (VARATT_IS_EXPANDED_HEADER(arr))
|
||||
{
|
||||
/* we can just grab the type data from expanded array */
|
||||
fctx->elmlen = arr->xpn.typlen;
|
||||
fctx->elmbyval = arr->xpn.typbyval;
|
||||
fctx->elmalign = arr->xpn.typalign;
|
||||
elmlen = arr->xpn.typlen;
|
||||
elmbyval = arr->xpn.typbyval;
|
||||
elmalign = arr->xpn.typalign;
|
||||
}
|
||||
else
|
||||
get_typlenbyvalalign(AARR_ELEMTYPE(arr),
|
||||
&fctx->elmlen,
|
||||
&fctx->elmbyval,
|
||||
&fctx->elmalign);
|
||||
&elmlen,
|
||||
&elmbyval,
|
||||
&elmalign);
|
||||
|
||||
/* initialize state */
|
||||
array_iter_setup(&fctx->iter, arr, elmlen, elmbyval, elmalign);
|
||||
fctx->nextelem = 0;
|
||||
fctx->numelems = ArrayGetNItems(AARR_NDIM(arr), AARR_DIMS(arr));
|
||||
|
||||
funcctx->user_fctx = fctx;
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
|
|
@ -6324,8 +6335,7 @@ array_unnest(PG_FUNCTION_ARGS)
|
|||
int offset = fctx->nextelem++;
|
||||
Datum elem;
|
||||
|
||||
elem = array_iter_next(&fctx->iter, &fcinfo->isnull, offset,
|
||||
fctx->elmlen, fctx->elmbyval, fctx->elmalign);
|
||||
elem = array_iter_next(&fctx->iter, &fcinfo->isnull, offset);
|
||||
|
||||
SRF_RETURN_NEXT(funcctx, elem);
|
||||
}
|
||||
|
|
@ -6401,6 +6411,7 @@ array_replace_internal(ArrayType *array,
|
|||
int typlen;
|
||||
bool typbyval;
|
||||
char typalign;
|
||||
uint8 typalignby;
|
||||
char *arraydataptr;
|
||||
bits8 *bitmap;
|
||||
int bitmask;
|
||||
|
|
@ -6445,6 +6456,7 @@ array_replace_internal(ArrayType *array,
|
|||
typlen = typentry->typlen;
|
||||
typbyval = typentry->typbyval;
|
||||
typalign = typentry->typalign;
|
||||
typalignby = typalign_to_alignby(typalign);
|
||||
|
||||
/*
|
||||
* Detoast values if they are toasted. The replacement value must be
|
||||
|
|
@ -6506,7 +6518,7 @@ array_replace_internal(ArrayType *array,
|
|||
isNull = false;
|
||||
elt = fetch_att(arraydataptr, typbyval, typlen);
|
||||
arraydataptr = att_addlength_datum(arraydataptr, typlen, elt);
|
||||
arraydataptr = (char *) att_align_nominal(arraydataptr, typalign);
|
||||
arraydataptr = (char *) att_nominal_alignby(arraydataptr, typalignby);
|
||||
|
||||
if (search_isnull)
|
||||
{
|
||||
|
|
@ -6553,7 +6565,7 @@ array_replace_internal(ArrayType *array,
|
|||
{
|
||||
/* Update total result size */
|
||||
nbytes = att_addlength_datum(nbytes, typlen, values[nresult]);
|
||||
nbytes = att_align_nominal(nbytes, typalign);
|
||||
nbytes = att_nominal_alignby(nbytes, typalignby);
|
||||
/* check for overflow of total request */
|
||||
if (!AllocSizeIsValid(nbytes))
|
||||
ereport(ERROR,
|
||||
|
|
@ -6860,6 +6872,7 @@ width_bucket_array_variable(Datum operand,
|
|||
int typlen = typentry->typlen;
|
||||
bool typbyval = typentry->typbyval;
|
||||
char typalign = typentry->typalign;
|
||||
uint8 typalignby = typalign_to_alignby(typalign);
|
||||
int left;
|
||||
int right;
|
||||
|
||||
|
|
@ -6883,7 +6896,7 @@ width_bucket_array_variable(Datum operand,
|
|||
for (i = left; i < mid; i++)
|
||||
{
|
||||
ptr = att_addlength_pointer(ptr, typlen, ptr);
|
||||
ptr = (char *) att_align_nominal(ptr, typalign);
|
||||
ptr = (char *) att_nominal_alignby(ptr, typalignby);
|
||||
}
|
||||
|
||||
locfcinfo->args[0].value = operand;
|
||||
|
|
@ -6908,7 +6921,7 @@ width_bucket_array_variable(Datum operand,
|
|||
* ensures we do only O(N) array indexing work, not O(N^2).
|
||||
*/
|
||||
ptr = att_addlength_pointer(ptr, typlen, ptr);
|
||||
thresholds_data = (char *) att_align_nominal(ptr, typalign);
|
||||
thresholds_data = (char *) att_nominal_alignby(ptr, typalignby);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -572,21 +572,22 @@ multirange_size_estimate(TypeCacheEntry *rangetyp, int32 range_count,
|
|||
RangeType **ranges)
|
||||
{
|
||||
char elemalign = rangetyp->rngelemtype->typalign;
|
||||
uint8 elemalignby = typalign_to_alignby(elemalign);
|
||||
Size size;
|
||||
int32 i;
|
||||
|
||||
/*
|
||||
* Count space for MultirangeType struct, items and flags.
|
||||
*/
|
||||
size = att_align_nominal(sizeof(MultirangeType) +
|
||||
Max(range_count - 1, 0) * sizeof(uint32) +
|
||||
range_count * sizeof(uint8), elemalign);
|
||||
size = att_nominal_alignby(sizeof(MultirangeType) +
|
||||
Max(range_count - 1, 0) * sizeof(uint32) +
|
||||
range_count * sizeof(uint8), elemalignby);
|
||||
|
||||
/* Count space for range bounds */
|
||||
for (i = 0; i < range_count; i++)
|
||||
size += att_align_nominal(VARSIZE(ranges[i]) -
|
||||
sizeof(RangeType) -
|
||||
sizeof(char), elemalign);
|
||||
size += att_nominal_alignby(VARSIZE(ranges[i]) -
|
||||
sizeof(RangeType) -
|
||||
sizeof(char), elemalignby);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
|
@ -605,6 +606,7 @@ write_multirange_data(MultirangeType *multirange, TypeCacheEntry *rangetyp,
|
|||
const char *begin;
|
||||
char *ptr;
|
||||
char elemalign = rangetyp->rngelemtype->typalign;
|
||||
uint8 elemalignby = typalign_to_alignby(elemalign);
|
||||
|
||||
items = MultirangeGetItemsPtr(multirange);
|
||||
flags = MultirangeGetFlagsPtr(multirange);
|
||||
|
|
@ -630,7 +632,7 @@ write_multirange_data(MultirangeType *multirange, TypeCacheEntry *rangetyp,
|
|||
flags[i] = *((char *) ranges[i] + VARSIZE(ranges[i]) - sizeof(char));
|
||||
len = VARSIZE(ranges[i]) - sizeof(RangeType) - sizeof(char);
|
||||
memcpy(ptr, ranges[i] + 1, len);
|
||||
ptr += att_align_nominal(len, elemalign);
|
||||
ptr += att_nominal_alignby(len, elemalignby);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3898,6 +3898,7 @@ array_to_text_internal(FunctionCallInfo fcinfo, ArrayType *v,
|
|||
int typlen;
|
||||
bool typbyval;
|
||||
char typalign;
|
||||
uint8 typalignby;
|
||||
StringInfoData buf;
|
||||
bool printed = false;
|
||||
char *p;
|
||||
|
|
@ -3947,6 +3948,7 @@ array_to_text_internal(FunctionCallInfo fcinfo, ArrayType *v,
|
|||
typlen = my_extra->typlen;
|
||||
typbyval = my_extra->typbyval;
|
||||
typalign = my_extra->typalign;
|
||||
typalignby = typalign_to_alignby(typalign);
|
||||
|
||||
p = ARR_DATA_PTR(v);
|
||||
bitmap = ARR_NULLBITMAP(v);
|
||||
|
|
@ -3983,7 +3985,7 @@ array_to_text_internal(FunctionCallInfo fcinfo, ArrayType *v,
|
|||
printed = true;
|
||||
|
||||
p = att_addlength_pointer(p, typlen, p);
|
||||
p = (char *) att_align_nominal(p, typalign);
|
||||
p = (char *) att_nominal_alignby(p, typalignby);
|
||||
}
|
||||
|
||||
/* advance bitmap pointer if any */
|
||||
|
|
|
|||
|
|
@ -71,6 +71,43 @@ fetch_att(const void *T, bool attbyval, int attlen)
|
|||
}
|
||||
#endif /* FRONTEND */
|
||||
|
||||
/*
|
||||
* typalign_to_alignby: map a TYPALIGN_xxx value to the numeric alignment
|
||||
* value it represents. (We store TYPALIGN_xxx codes not the real alignment
|
||||
* values mainly so that initial catalog contents can be machine-independent.)
|
||||
*/
|
||||
static inline uint8
|
||||
typalign_to_alignby(char typalign)
|
||||
{
|
||||
uint8 alignby;
|
||||
|
||||
switch (typalign)
|
||||
{
|
||||
case TYPALIGN_CHAR:
|
||||
alignby = sizeof(char);
|
||||
break;
|
||||
case TYPALIGN_SHORT:
|
||||
alignby = ALIGNOF_SHORT;
|
||||
break;
|
||||
case TYPALIGN_INT:
|
||||
alignby = ALIGNOF_INT;
|
||||
break;
|
||||
case TYPALIGN_DOUBLE:
|
||||
alignby = ALIGNOF_DOUBLE;
|
||||
break;
|
||||
default:
|
||||
#ifndef FRONTEND
|
||||
elog(ERROR, "invalid typalign value: %c", typalign);
|
||||
#else
|
||||
fprintf(stderr, "invalid typalign value: %c\n", typalign);
|
||||
exit(1);
|
||||
#endif
|
||||
alignby = 0;
|
||||
break;
|
||||
}
|
||||
return alignby;
|
||||
}
|
||||
|
||||
/*
|
||||
* att_align_datum aligns the given offset as needed for a datum of alignment
|
||||
* requirement attalign and typlen attlen. attdatum is the Datum variable
|
||||
|
|
@ -139,19 +176,11 @@ fetch_att(const void *T, bool attbyval, int attlen)
|
|||
* * within arrays and multiranges, we unconditionally align varlenas (XXX this
|
||||
* should be revisited, probably).
|
||||
*
|
||||
* The attalign cases are tested in what is hopefully something like their
|
||||
* frequency of occurrence.
|
||||
* In performance-critical loops, avoid using this macro; instead use
|
||||
* att_nominal_alignby with a pre-computed alignby value.
|
||||
*/
|
||||
#define att_align_nominal(cur_offset, attalign) \
|
||||
( \
|
||||
((attalign) == TYPALIGN_INT) ? INTALIGN(cur_offset) : \
|
||||
(((attalign) == TYPALIGN_CHAR) ? (uintptr_t) (cur_offset) : \
|
||||
(((attalign) == TYPALIGN_DOUBLE) ? DOUBLEALIGN(cur_offset) : \
|
||||
( \
|
||||
AssertMacro((attalign) == TYPALIGN_SHORT), \
|
||||
SHORTALIGN(cur_offset) \
|
||||
))) \
|
||||
)
|
||||
att_nominal_alignby(cur_offset, typalign_to_alignby(attalign))
|
||||
|
||||
/*
|
||||
* Similar to att_align_nominal, but accepts a number of bytes, typically from
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@
|
|||
* Functions for iterating through elements of a flat or expanded array.
|
||||
* These require a state struct "array_iter iter".
|
||||
*
|
||||
* Use "array_iter_setup(&iter, arrayptr);" to prepare to iterate, and
|
||||
* "datumvar = array_iter_next(&iter, &isnullvar, index, ...);" to fetch
|
||||
* Use "array_iter_setup(&iter, arrayptr, ...);" to prepare to iterate,
|
||||
* and "datumvar = array_iter_next(&iter, &isnullvar, index);" to fetch
|
||||
* the next element into datumvar/isnullvar.
|
||||
* "index" must be the zero-origin element number; we make caller provide
|
||||
* this since caller is generally counting the elements anyway. Despite
|
||||
|
|
@ -42,11 +42,17 @@ typedef struct array_iter
|
|||
char *dataptr; /* Current spot in the data area */
|
||||
bits8 *bitmapptr; /* Current byte of the nulls bitmap, or NULL */
|
||||
int bitmask; /* mask for current bit in nulls bitmap */
|
||||
|
||||
/* Fields used in both cases: data about array's element type */
|
||||
int elmlen;
|
||||
bool elmbyval;
|
||||
uint8 elmalignby;
|
||||
} array_iter;
|
||||
|
||||
|
||||
static inline void
|
||||
array_iter_setup(array_iter *it, AnyArrayType *a)
|
||||
array_iter_setup(array_iter *it, AnyArrayType *a,
|
||||
int elmlen, bool elmbyval, char elmalign)
|
||||
{
|
||||
if (VARATT_IS_EXPANDED_HEADER(a))
|
||||
{
|
||||
|
|
@ -75,11 +81,13 @@ array_iter_setup(array_iter *it, AnyArrayType *a)
|
|||
it->bitmapptr = ARR_NULLBITMAP((ArrayType *) a);
|
||||
}
|
||||
it->bitmask = 1;
|
||||
it->elmlen = elmlen;
|
||||
it->elmbyval = elmbyval;
|
||||
it->elmalignby = typalign_to_alignby(elmalign);
|
||||
}
|
||||
|
||||
static inline Datum
|
||||
array_iter_next(array_iter *it, bool *isnull, int i,
|
||||
int elmlen, bool elmbyval, char elmalign)
|
||||
array_iter_next(array_iter *it, bool *isnull, int i)
|
||||
{
|
||||
Datum ret;
|
||||
|
||||
|
|
@ -98,10 +106,11 @@ array_iter_next(array_iter *it, bool *isnull, int i,
|
|||
else
|
||||
{
|
||||
*isnull = false;
|
||||
ret = fetch_att(it->dataptr, elmbyval, elmlen);
|
||||
it->dataptr = att_addlength_pointer(it->dataptr, elmlen,
|
||||
ret = fetch_att(it->dataptr, it->elmbyval, it->elmlen);
|
||||
it->dataptr = att_addlength_pointer(it->dataptr, it->elmlen,
|
||||
it->dataptr);
|
||||
it->dataptr = (char *) att_align_nominal(it->dataptr, elmalign);
|
||||
it->dataptr = (char *) att_nominal_alignby(it->dataptr,
|
||||
it->elmalignby);
|
||||
}
|
||||
it->bitmask <<= 1;
|
||||
if (it->bitmask == 0x100)
|
||||
|
|
|
|||
|
|
@ -735,6 +735,7 @@ PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim,
|
|||
char *dataptr = *dataptr_p;
|
||||
bits8 *bitmap = *bitmap_p;
|
||||
int bitmask = *bitmask_p;
|
||||
uint8 typalignby = typalign_to_alignby(elm->typalign);
|
||||
|
||||
for (i = 0; i < dims[dim]; i++)
|
||||
{
|
||||
|
|
@ -751,7 +752,7 @@ PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim,
|
|||
itemvalue = fetch_att(dataptr, elm->typbyval, elm->typlen);
|
||||
PyList_SetItem(list, i, elm->func(elm, itemvalue));
|
||||
dataptr = att_addlength_pointer(dataptr, elm->typlen, dataptr);
|
||||
dataptr = (char *) att_align_nominal(dataptr, elm->typalign);
|
||||
dataptr = (char *) att_nominal_alignby(dataptr, typalignby);
|
||||
}
|
||||
|
||||
/* advance bitmap pointer if any */
|
||||
|
|
|
|||
Loading…
Reference in a new issue