/* * Sets the binding length according to the following binding's alignment. * Adds the aligned length into the array holding the space saved from null attributes. * Returns true if the binding length is aligned to the following binding's alignment. */ static inline bool add_null_save_aligned(MemTupleAttrBinding *bind, short *null_save_aligned, int i, char next_attr_align) { Assert(bind); Assert(bind->len > 0); Assert(null_save_aligned); Assert(i >= 0); bind->len_aligned = att_align(bind->len, next_attr_align); add_null_save(null_save_aligned, i, bind->len_aligned); return (bind->len == bind->len_aligned); }
/* Create columns binding, depends on islarge, using 2 or 4 bytes for offset_len */ static void create_col_bind(MemTupleBindingCols *colbind, bool islarge, TupleDesc tupdesc, int col_align) { int i = 0; int physical_col = 0; int pass = 0; uint32 cur_offset = (tupdesc->tdhasoid || col_align == 8) ? 8 : 4; uint32 null_save_entries = compute_null_save_entries(tupdesc->natts); /* alloc null save entries. Zero it */ colbind->null_saves = (short *) palloc0(sizeof(short) * null_save_entries); colbind->null_saves_aligned = (short *) palloc0(sizeof(short) * null_save_entries); colbind->has_null_saves_alignment_mismatch = false; colbind->has_dropped_attr_alignment_mismatch = false; /* alloc bindings, no need to zero because we will fill them out */ colbind->bindings = (MemTupleAttrBinding *) palloc(sizeof(MemTupleAttrBinding) * tupdesc->natts); /* * The length of each binding is determined according to the alignment * of the physically following binding. Use this pointer to keep track * of the previously processed binding. */ MemTupleAttrBinding *previous_bind = NULL; /* * First pass, do 8 bytes aligned, native type. * Sencond pass, do 4 bytes aligned, native type. * Third pass, do 2 bytes aligned, native type. * Finall, do 1 bytes aligned native type. * * depends on islarge, varlena types are either handled in the * second pass (is large, varoffset using 4 bytes), or in the * third pass (not large, varoffset using 2 bytes). */ for(pass =0; pass < 4; ++pass) { for(i=0; i<tupdesc->natts; ++i) { Form_pg_attribute attr = tupdesc->attrs[i]; MemTupleAttrBinding *bind = &colbind->bindings[i]; if(pass == 0 && attr->attlen > 0 && attr->attalign == 'd') { bind->offset = att_align_nominal(cur_offset, attr->attalign); bind->len = attr->attlen; add_null_save(colbind->null_saves, physical_col, attr->attlen); if (physical_col) { /* Set the aligned length of the previous binding according to current alignment. */ if (add_null_save_aligned(previous_bind, colbind->null_saves_aligned, physical_col - 1, 'd')) { colbind->has_null_saves_alignment_mismatch = true; if (attr->attisdropped) { colbind->has_dropped_attr_alignment_mismatch = true; } } } bind->flag = attr->attbyval ? MTB_ByVal_Native : MTB_ByVal_Ptr; bind->null_byte = physical_col >> 3; bind->null_mask = 1 << (physical_col-(bind->null_byte << 3)); physical_col += 1; cur_offset = bind->offset + bind->len; previous_bind = bind; } else if (pass == 1 &&( (attr->attlen > 0 && attr->attalign == 'i') || ( islarge && att_bind_as_varoffset(attr)) ) ) { bind->offset = att_align_nominal(cur_offset, 'i'); bind->len = attr->attlen > 0 ? attr->attlen : 4; add_null_save(colbind->null_saves, physical_col, bind->len); if (physical_col) { /* Set the aligned length of the previous binding according to current alignment. */ if (add_null_save_aligned(previous_bind, colbind->null_saves_aligned, physical_col - 1, 'i')) { colbind->has_null_saves_alignment_mismatch = true; if (attr->attisdropped) { colbind->has_dropped_attr_alignment_mismatch = true; } } } if(attr->attlen > 0) bind->flag = attr->attbyval ? MTB_ByVal_Native : MTB_ByVal_Ptr; else if(attr->attlen == -1) bind->flag = MTB_ByRef; else { Assert(attr->attlen == -2); bind->flag = MTB_ByRef_CStr; } bind->null_byte = physical_col >> 3; bind->null_mask = 1 << (physical_col-(bind->null_byte << 3)); physical_col += 1; cur_offset = bind->offset + bind->len; previous_bind = bind; }