Figure 4: Record-oriented data structures
//  Record buffer element
struct DbRecordField {
public :
    long length;
    short nullind;
    short reserved;
    char text[1];
    DbRecordField& operator=(SQLVAR* var);
};

class DbRecord : public Dump {
public :
    int nField;

    DbRecord() { nField = 0; used = 0; }
    void create(SQLDA* sqlda);
    DbRecordField* get(int i);
    DbRecord& operator<<(SQLVAR* var);
    void clear();

    int used;
    DbRecordField* extend(int delta);
};


#define AVG_FIELD_SIZE \
        (sizeof(DbRecordField)+8)
#define FIELD_GRAN  16

DbRecordField& 
DbRecordField::operator=(SQLVAR* var) {
    length = 
        sizeof(DbRecordField) + 
            var->sqllen;
    if (var->sqlind)
        nullind = *var->sqlind;
    else
        nullind = 0;
    if (var->sqldata && nullind != 
            Query::nullind)
        memcpy(text,var->sqldata,
            var->sqllen);
    text[var->sqllen] = 0;
    return *this;
}

DbRecordField* 
DbRecord::extend(int delta) {
    int last = used;
    used += delta;
    if (used <= size) {}
    else if (size > 0) {
        Dump swap(*this);
        Dump::create(
          used +
          FIELD_GRAN*AVG_FIELD_SIZE);
        memcpy(data,swap.data,swap.size);
    }
    else
        Dump::create(
          used +
          FIELD_GRAN*AVG_FIELD_SIZE);
    return (DbRecordField*)(data+last);
}

void DbRecord::create(SQLDA* sqlda) {
    nField = sqlda->sqld;
    int size = 
        sizeof(DbRecordField)*sqlda->sqld;
    for (int i = 0; i < sqlda->sqld; i++)
        size += sqlda->sqlvar[i].sqllen;
    extend(size);
    int offset = 0;
    for (i = 0; i < sqlda->sqld; i++) {
        SQLVAR* var = &sqlda->sqlvar[i];
        DbRecordField* field = 
            (DbRecordField*)(data+offset);
        *field = var;
        offset += field->length;
    }
}

DbRecordField* DbRecord::get(int i) {
    int offset = 0, count = 0;;
    while (count < nField) {
        DbRecordField* field = 
            (DbRecordField*)(data+offset);
        if (count == i)
            return field;
        offset += field->length;
        count++;
    }
    return 0;
}

DbRecord& 
DbRecord::operator<<(SQLVAR* var) {
    int need = 
        sizeof(DbRecordField) + 
            var->sqllen;
    DbRecordField* field = extend(need);
    nField++;
    *field = var;
    return *this;
}

void DbRecord::clear() {
    destroy();
    used = 0;
    nField = 0;
}

/* End of File */