func FormHeapTuple(values []system.Datum, tupdesc *TupleDesc) *HeapTuple { natts := len(tupdesc.Attrs) hasnull := false for _, value := range values { if value == nil { hasnull = true //} else if att.attlen == -1 // TODO: flatten toast value } } length := unsafe.Offsetof(HeapTupleHeader{}.bits) if hasnull { length += uintptr(bitmapLength(natts)) } if tupdesc.hasOid { length += unsafe.Sizeof(system.Oid(0)) } length = system.MaxAlign(length) hoff := uint8(length) data_len := computeHeapDataSize(values, tupdesc) length += data_len tuple_data := make([]byte, length) tuple := &HeapTuple{ tupdesc: tupdesc, tableOid: system.InvalidOid, } tuple.SetData(tuple_data, system.InvalidItemPointer) td := tuple.data td.SetNatts(system.AttrNumber(natts)) td.hoff = hoff if tupdesc.hasOid { td.infomask = heapHasOid } bits := []byte(nil) if hasnull { bits = tuple.bytes[unsafe.Offsetof(td.bits):hoff] } data := tuple.bytes[hoff:] td.fill(values, tupdesc, bits, data) return tuple }
func (tuple *HeapTuple) Fetch(attnum system.AttrNumber) system.Datum { if attnum <= 0 { switch attnum { case system.CtidAttrNumber: return system.Datum(tuple.self) case system.OidAttrNumber: return system.Datum(tuple.data.Oid()) case system.XminAttrNumber: //return system.Datum(tuple.data.Xmin()) case system.CminAttrNumber: // TODO: case system.XmaxAttrNumber: //return system.Datum(tuple.data.Xmax()) case system.CmaxAttrNumber: // TODO: case system.TableOidAttrNumber: return system.Datum(tuple.tableOid) } } else { td := tuple.data if td.IsNull(attnum) { return nil } // TODO: attcache offset := int(td.hoff) for i := system.AttrNumber(1); i < attnum; i++ { if td.IsNull(i) { continue } attr := tuple.tupdesc.Attrs[i-1] if attr.Type.IsVarlen() { // TODO: } else { offset += int(attr.Type.Len) } } reader := bytes.NewReader(tuple.bytes[offset:]) return system.DatumFromBytes(reader, tuple.tupdesc.Attrs[attnum-1].TypeId) } return nil }
func (s *MySuite) TestHeapTuple(c *C) { values := []system.Datum{ system.Int4(1), system.Oid(999990), nil, system.Name("fooname"), } tupdesc := &TupleDesc{ Attrs: []*Attribute{ { Name: "col1", TypeId: system.Int4Type, }, { Name: "col2", TypeId: system.OidType, }, { Name: "col3nil", TypeId: system.NameType, }, { Name: "col4", TypeId: system.NameType, }, }, } initTupleDesc(tupdesc) htuple := FormHeapTuple(values, tupdesc) c.Check(htuple.Fetch(1), Equals, values[0]) c.Check(htuple.Fetch(2), Equals, values[1]) c.Check(htuple.Fetch(3), Equals, values[2]) c.Check(htuple.Fetch(4), Equals, values[3]) c.Check(htuple.data.Oid(), Equals, system.InvalidOid) c.Check(htuple.data.HasNulls(), Equals, true) c.Check(htuple.data.Natts(), Equals, system.AttrNumber(4)) }
func (htup *HeapTupleHeader) Natts() system.AttrNumber { return system.AttrNumber(htup.infomask2 & uint16(heapNattsMask)) }