/* Skip non-varlena values, but update offset first */
if (thisatt->attlen != -1)
{
- ctx->offset = att_align_nominal(ctx->offset, thisatt->attalign);
+ ctx->offset = att_nominal_alignby(ctx->offset, thisatt->attalignby);
ctx->offset = att_addlength_pointer(ctx->offset, thisatt->attlen,
tp + ctx->offset);
if (ctx->tuphdr->t_hoff + ctx->offset > ctx->lp_len)
}
/* Ok, we're looking at a varlena attribute. */
- ctx->offset = att_align_pointer(ctx->offset, thisatt->attalign, -1,
- tp + ctx->offset);
+ ctx->offset = att_pointer_alignby(ctx->offset, thisatt->attalignby, -1,
+ tp + ctx->offset);
/* Get the (possibly corrupt) varlena datum */
attdatum = fetchatt(thisatt, tp + ctx->offset);
if (attr->attlen == -1)
{
- off = att_align_pointer(off, attr->attalign, -1,
- tupdata + off);
+ off = att_pointer_alignby(off, attr->attalignby, -1,
+ tupdata + off);
/*
* As VARSIZE_ANY throws an exception if it can't properly
}
else
{
- off = att_align_nominal(off, attr->attalign);
+ off = att_nominal_alignby(off, attr->attalignby);
len = attr->attlen;
}
if (thisatt->attlen == -1)
{
- off = att_align_pointer(off, thisatt->attalign, -1,
- tp + off);
+ off = att_pointer_alignby(off,
+ thisatt->attalignby,
+ -1,
+ tp + off);
}
else
{
- /* not varlena, so safe to use att_align_nominal */
- off = att_align_nominal(off, thisatt->attalign);
+ /* not varlena, so safe to use att_nominal_alignby */
+ off = att_nominal_alignby(off, thisatt->attalignby);
}
values[stored++] = fetchatt(thisatt, tp + off);
/*
* If it's a dropped column and the corresponding input column is also
- * dropped, we don't need a conversion. However, attlen and attalign
- * must agree.
+ * dropped, we don't need a conversion. However, attlen and
+ * attalignby must agree.
*/
if (attrMap->attnums[i] == 0 &&
inatt->attisdropped &&
inatt->attlen == outatt->attlen &&
- inatt->attalign == outatt->attalign)
+ inatt->attalignby == outatt->attalignby)
continue;
return false;
* we want to flatten the expanded value so that the constructed
* tuple doesn't depend on it
*/
- data_length = att_align_nominal(data_length, atti->attalign);
+ data_length = att_nominal_alignby(data_length, atti->attalignby);
data_length += EOH_get_flat_size(DatumGetEOHP(val));
}
else
{
- data_length = att_align_datum(data_length, atti->attalign,
- atti->attlen, val);
+ data_length = att_datum_alignby(data_length, atti->attalignby,
+ atti->attlen, val);
data_length = att_addlength_datum(data_length, atti->attlen,
val);
}
}
/*
- * XXX we use the att_align macros on the pointer value itself, not on an
- * offset. This is a bit of a hack.
+ * XXX we use the att_nominal_alignby macro on the pointer value itself,
+ * not on an offset. This is a bit of a hack.
*/
if (att->attbyval)
{
/* pass-by-value */
- data = (char *) att_align_nominal(data, att->attalign);
+ data = (char *) att_nominal_alignby(data, att->attalignby);
store_att_byval(data, datum, att->attlen);
data_length = att->attlen;
}
*/
ExpandedObjectHeader *eoh = DatumGetEOHP(datum);
- data = (char *) att_align_nominal(data,
- att->attalign);
+ data = (char *) att_nominal_alignby(data, att->attalignby);
data_length = EOH_get_flat_size(eoh);
EOH_flatten_into(eoh, data, data_length);
}
else
{
/* full 4-byte header varlena */
- data = (char *) att_align_nominal(data,
- att->attalign);
+ data = (char *) att_nominal_alignby(data, att->attalignby);
data_length = VARSIZE(val);
memcpy(data, val, data_length);
}
{
/* cstring ... never needs alignment */
*infomask |= HEAP_HASVARWIDTH;
- Assert(att->attalign == TYPALIGN_CHAR);
+ Assert(att->attalignby == sizeof(char));
data_length = strlen(DatumGetCString(datum)) + 1;
memcpy(data, DatumGetPointer(datum), data_length);
}
else
{
/* fixed-length pass-by-reference */
- data = (char *) att_align_nominal(data, att->attalign);
+ data = (char *) att_nominal_alignby(data, att->attalignby);
Assert(att->attlen > 0);
data_length = att->attlen;
memcpy(data, DatumGetPointer(datum), data_length);
if (att->attlen <= 0)
break;
- off = att_align_nominal(off, att->attalign);
+ off = att_nominal_alignby(off, att->attalignby);
att->attcacheoff = off;
* either an aligned or unaligned value.
*/
if (usecache &&
- off == att_align_nominal(off, att->attalign))
+ off == att_nominal_alignby(off, att->attalignby))
att->attcacheoff = off;
else
{
- off = att_align_pointer(off, att->attalign, -1,
- tp + off);
+ off = att_pointer_alignby(off, att->attalignby, -1,
+ tp + off);
usecache = false;
}
}
else
{
- /* not varlena, so safe to use att_align_nominal */
- off = att_align_nominal(off, att->attalign);
+ /* not varlena, so safe to use att_nominal_alignby */
+ off = att_nominal_alignby(off, att->attalignby);
if (usecache)
att->attcacheoff = off;
{
CompactAttribute *att = TupleDescCompactAttr(tupleDesc, attnum);
- targetDataLen = att_align_datum(targetDataLen,
- att->attalign,
- att->attlen,
- attrmiss[attnum].am_value);
+ targetDataLen = att_datum_alignby(targetDataLen,
+ att->attalignby,
+ att->attlen,
+ attrmiss[attnum].am_value);
targetDataLen = att_addlength_pointer(targetDataLen,
att->attlen,
* an aligned or unaligned value.
*/
if (!slow &&
- off == att_align_nominal(off, thisatt->attalign))
+ off == att_nominal_alignby(off, thisatt->attalignby))
thisatt->attcacheoff = off;
else
{
- off = att_align_pointer(off, thisatt->attalign, -1,
- tp + off);
+ off = att_pointer_alignby(off, thisatt->attalignby, -1,
+ tp + off);
slow = true;
}
}
else
{
- /* not varlena, so safe to use att_align_nominal */
- off = att_align_nominal(off, thisatt->attalign);
+ /* not varlena, so safe to use att_nominal_alignby */
+ off = att_nominal_alignby(off, thisatt->attalignby);
if (!slow)
thisatt->attcacheoff = off;
if (att->attlen <= 0)
break;
- off = att_align_nominal(off, att->attalign);
+ off = att_nominal_alignby(off, att->attalignby);
att->attcacheoff = off;
* either an aligned or unaligned value.
*/
if (usecache &&
- off == att_align_nominal(off, att->attalign))
+ off == att_nominal_alignby(off, att->attalignby))
att->attcacheoff = off;
else
{
- off = att_align_pointer(off, att->attalign, -1,
- tp + off);
+ off = att_pointer_alignby(off, att->attalignby, -1,
+ tp + off);
usecache = false;
}
}
else
{
- /* not varlena, so safe to use att_align_nominal */
- off = att_align_nominal(off, att->attalign);
+ /* not varlena, so safe to use att_nominal_alignby */
+ off = att_nominal_alignby(off, att->attalignby);
if (usecache)
att->attcacheoff = off;
* an aligned or unaligned value.
*/
if (!slow &&
- off == att_align_nominal(off, thisatt->attalign))
+ off == att_nominal_alignby(off, thisatt->attalignby))
thisatt->attcacheoff = off;
else
{
- off = att_align_pointer(off, thisatt->attalign, -1,
- tp + off);
+ off = att_pointer_alignby(off, thisatt->attalignby, -1,
+ tp + off);
slow = true;
}
}
else
{
- /* not varlena, so safe to use att_align_nominal */
- off = att_align_nominal(off, thisatt->attalign);
+ /* not varlena, so safe to use att_nominal_alignby */
+ off = att_nominal_alignby(off, thisatt->attalignby);
if (!slow)
thisatt->attcacheoff = off;
dst->attgenerated = (src->attgenerated != '\0');
dst->attnotnull = src->attnotnull;
- dst->attalign = src->attalign;
+ 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;
+ }
}
/*
if (slot->tts_isnull[i])
continue; /* null is always okay */
if (vattr->attlen != sattr->attlen ||
- vattr->attalign != sattr->attalign)
+ vattr->attalignby != sattr->attalignby)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("table row type and query-specified row type do not match"),
* We want to flatten the expanded value so that the materialized
* slot doesn't depend on it.
*/
- sz = att_align_nominal(sz, att->attalign);
+ sz = att_nominal_alignby(sz, att->attalignby);
sz += EOH_get_flat_size(DatumGetEOHP(val));
}
else
{
- sz = att_align_nominal(sz, att->attalign);
+ sz = att_nominal_alignby(sz, att->attalignby);
sz = att_addlength_datum(sz, att->attlen, val);
}
}
*/
ExpandedObjectHeader *eoh = DatumGetEOHP(val);
- data = (char *) att_align_nominal(data,
- att->attalign);
+ data = (char *) att_nominal_alignby(data,
+ att->attalignby);
data_length = EOH_get_flat_size(eoh);
EOH_flatten_into(eoh, data, data_length);
{
Size data_length = 0;
- data = (char *) att_align_nominal(data, att->attalign);
+ data = (char *) att_nominal_alignby(data, att->attalignby);
data_length = att_addlength_datum(data_length, att->attlen, val);
memcpy(data, DatumGetPointer(val), data_length);
* an aligned or unaligned value.
*/
if (!slow &&
- off == att_align_nominal(off, thisatt->attalign))
+ off == att_nominal_alignby(off, thisatt->attalignby))
thisatt->attcacheoff = off;
else
{
- off = att_align_pointer(off, thisatt->attalign, -1,
- tp + off);
+ off = att_pointer_alignby(off, thisatt->attalignby, -1,
+ tp + off);
slow = true;
}
}
else
{
- /* not varlena, so safe to use att_align_nominal */
- off = att_align_nominal(off, thisatt->attalign);
+ /* not varlena, so safe to use att_nominal_alignby */
+ off = att_nominal_alignby(off, thisatt->attalignby);
if (!slow)
thisatt->attcacheoff = off;
{
CompactAttribute *att = TupleDescCompactAttr(desc, attnum);
LLVMValueRef v_incby;
- int alignto;
+ int alignto = att->attalignby;
LLVMValueRef l_attno = l_int16_const(lc, attnum);
LLVMValueRef v_attdatap;
LLVMValueRef v_resultp;
}
LLVMPositionBuilderAtEnd(b, attcheckalignblocks[attnum]);
- /* determine required alignment */
- if (att->attalign == TYPALIGN_INT)
- alignto = ALIGNOF_INT;
- else if (att->attalign == TYPALIGN_CHAR)
- alignto = 1;
- else if (att->attalign == TYPALIGN_DOUBLE)
- alignto = ALIGNOF_DOUBLE;
- else if (att->attalign == TYPALIGN_SHORT)
- alignto = ALIGNOF_SHORT;
- else
- {
- elog(ERROR, "unknown alignment");
- alignto = 0;
- }
-
/* ------
* Even if alignment is required, we can skip doing it if provably
* unnecessary:
bool attisdropped; /* as FormData_pg_attribute.attisdropped */
bool attgenerated; /* FormData_pg_attribute.attgenerated != '\0' */
bool attnotnull; /* as FormData_pg_attribute.attnotnull */
- char attalign; /* alignment requirement */
+ uint8 attalignby; /* alignment requirement in bytes */
} CompactAttribute;
/*
att_align_nominal(cur_offset, attalign) \
)
+/*
+ * Similar to att_align_datum, but accepts a number of bytes, typically from
+ * CompactAttribute.attalignby to align the Datum by.
+ */
+#define att_datum_alignby(cur_offset, attalignby, attlen, attdatum) \
+ ( \
+ ((attlen) == -1 && VARATT_IS_SHORT(DatumGetPointer(attdatum))) ? \
+ (uintptr_t) (cur_offset) : \
+ TYPEALIGN(attalignby, cur_offset))
+
/*
* att_align_pointer performs the same calculation as att_align_datum,
* but is used when walking a tuple. attptr is the current actual data
att_align_nominal(cur_offset, attalign) \
)
+/*
+ * Similar to att_align_pointer, but accepts a number of bytes, typically from
+ * CompactAttribute.attalignby to align the pointer by.
+ */
+#define att_pointer_alignby(cur_offset, attalignby, attlen, attptr) \
+ ( \
+ ((attlen) == -1 && VARATT_NOT_PAD_BYTE(attptr)) ? \
+ (uintptr_t) (cur_offset) : \
+ TYPEALIGN(attalignby, cur_offset))
+
/*
* att_align_nominal aligns the given offset as needed for a datum of alignment
* requirement attalign, ignoring any consideration of packed varlena datums.
))) \
)
+/*
+ * Similar to att_align_nominal, but accepts a number of bytes, typically from
+ * CompactAttribute.attalignby to align the offset by.
+ */
+#define att_nominal_alignby(cur_offset, attalignby) \
+ TYPEALIGN(attalignby, cur_offset)
+
/*
* att_addlength_datum increments the given offset by the space needed for
* the given Datum variable. attdatum is only accessed if we are dealing