#include /////////////////////////////////////////////////////////// // TText_recordset /////////////////////////////////////////////////////////// bool TText_recordset::destroy(TRecnotype r) { const bool ok = _rec.destroy(r, true); if (ok && (_curr == r || _curr > _rec.items())) _curr = -1; return ok; } const TRecordset_column_info& TText_recordset::column_info(const char* column) const { return column_info(find_column(column)); } TRecnotype TText_recordset::new_rec(const char* rec) { _curr = _rec.add(rec); const int l = row(_curr).size(); // Forse sarebbe piu' sicuro len() if (l > _info._width) _info._width = l; return _curr; } TToken_string& TText_recordset::row(TRecnotype n) const { if (n < 0) n = current_row(); if (n < 0 || n >= items()) n = ((TText_recordset*)this)->new_rec(); // Clausola di salvaguardia return (TToken_string&)_rec.row(n); } TRecnotype TText_recordset::items() const { TRecnotype n = _rec.items(); if (n == 0 && _query.full() && _query.find("CREATE ") < 0) { ((TText_recordset*)this)->exec(_query); n = _rec.items(); } return n; } bool TText_recordset::move_to(TRecnotype pos) { const bool ok = pos >= 0 && pos < items(); _curr = pos; return ok; } void TText_recordset::requery() { } bool TText_recordset::load_file(const TFilename& n) { TString str(4096); char* buf = str.get_buffer(); ifstream f(n); while (f) { f.getline(buf, str.size()); new_rec(buf); } return _rec.items() > 0; } int TText_recordset::find_column(const char* column) const { int n = 0; if (column && *column) { if (real::is_natural(column)) n = atoi(column); else { for (const char* c = column; isalpha(*c); c++) { n *= 26; n += toupper(*c)-'A'; } } } return n; } const TVariant& TText_recordset::get(unsigned int column) const { const TRecnotype n = current_row(); if (column == 0 && n >= 0 && n < items()) { TVariant& var = get_tmp_var(); var.set(((TText_recordset*)this)->row(n)); return var; } return NULL_VARIANT; } bool TText_recordset::set(unsigned int column, const TVariant& var) { const bool ok = column == 0; if (ok) row() = var.as_string(); return ok; } bool TText_recordset::set(const char* column, const TVariant& var) { return set(find_column(column), var); } TQuery_type TText_recordset::parse_query(const char* query, TFilename& table) { TQuery_type qt = _qt_none; TString q(query); q.trim(); const int ct = q.find("CREATE TABLE "); if (ct >= 0) { const TToken_string t(q.mid(ct), ' '); t.get(2, table); // Furbastro: prendo la terza parola della query table.trim(); if (table.not_empty()) qt = _qt_create; } else { const int se = q.find("SELECT "); if (se >= 0) { int n = q.find("FROM ", se); table = q.mid(n+5); n = table.find("WHERE"); if (n > 0) table.cut(n-1); n = table.find(','); if (n > 0) table.cut(n); } else { table = query; } table.trim(); if (table.not_empty()) qt = _qt_select; } return qt; } bool TText_recordset::exec(const char* query) { TFilename name; const TQuery_type qt = parse_query(query, name); if (qt != _qt_none) { _query = query; _query.trim(); if (qt == _qt_select) { destroy(); load_file(name); } } return qt != _qt_none; } bool TText_recordset::save_as_text(const char* path) { bool ok = path && *path; if (ok) { ofstream out(path); for (bool ok = move_first(); ok; ok = move_next()) out << row() << endl; } return ok; } bool TText_recordset::save_as(const char* path, TRecordsetExportFormat fmt) { if (fmt == fmt_text || fmt == fmt_unknown) { TFilename n = path; if (n.blank()) parse_query(_query, n); if (n.full()) return save_as_text(n); } return TRecordset::save_as(path, fmt); } void TText_recordset::sort(COMPARE_FUNCTION f) { if (f == NULL) _rec.sort(true); // Ordina alfabeticamante else _rec.TArray::sort(f); // Usa la funzione definita dall'utente } TText_recordset::TText_recordset(const char* query) : _query(query), _curr(-1) { _info._name = "A"; _info._pos = _info._width = 0; _info._type = _alfafld; } /////////////////////////////////////////////////////////// // TCSV_recordset /////////////////////////////////////////////////////////// TQuery_type TCSV_recordset::parse_query(const char* query, TFilename& table) { TString q(query); if (q.starts_with("CSV(", true)) { const int apici = q.find('"'); if (apici > 0) _separator = q[apici+1]; else _separator = ','; q = q.after(')'); q.trim(); } return TText_recordset::parse_query(q, table); } unsigned int TCSV_recordset::columns() const { unsigned int c = _trc.items(); if (c == 0) { items(); c = _trc.items(); } return c; } const TRecordset_column_info& TCSV_recordset::column_info(unsigned int column) const { if (column >= 0 && column < columns()) { TRecordset_column_info* ci = (TRecordset_column_info*)_trc.objptr(column); if (ci != NULL) return *ci; } return TText_recordset::column_info(column); } TRecnotype TCSV_recordset::new_rec(const char* rec) { const TRecnotype n = TText_recordset::new_rec(rec); if (n >= 0) row(n).separator(_separator); return n; } bool TCSV_recordset::load_file(const TFilename& n) { if (!TText_recordset::load_file(n)) return false; _trc.destroy(); int cols = 1; int i; for (i = items()-1; i >= 0; i--) { const TToken_string& r = row(i); const int c = r.items(); if (c > cols) cols = c; } for (i = 0; i < cols; i++) _trc.add(new TRecordset_column_info); TString val; for (i = items()-1; i >= 0; i--) { const TToken_string& r = row(i); for (int c = r.items()-1; c >= 0; c--) { r.get(c, val); if (val.full()) { TRecordset_column_info& ci = *(TRecordset_column_info*)_trc.objptr(c); const int l = val.len(); if (l > ci._width) { ci._width = l; if (l == 8 || l == 10 && TDate::isdate(val)) ci._type = _datefld; else { if (!real::is_null(val)) { if (real::is_natural(val)) ci._type = _intfld; else ci._type = _realfld; } } } } } } return true; } bool TCSV_recordset::set(unsigned int column, const TVariant& var) { TToken_string& r = row(); r.add(var.as_string(), column); return true; } const TVariant& TCSV_recordset::get(unsigned int column) const { const TRecnotype n = current_row(); if (n >= 0 && n < items()) { const char* val = row(n).get(column); if (val != NULL) { TVariant& var = get_tmp_var(); var.set(val); return var; } } return NULL_VARIANT; } TCSV_recordset::TCSV_recordset(const char* query) : TText_recordset(query), _separator(',') { TFilename n; if (parse_query(query, n) == _qt_select && n.exist()) load_file(n); } /////////////////////////////////////////////////////////// // TAS400_recordset /////////////////////////////////////////////////////////// bool TAS400_recordset::load_file(const TFilename& n) { TString row(record_length(), ' '); ifstream f(n, ios::binary); char* buf = row.get_buffer(); TRecnotype r = -1; while (f) { *buf = '\0'; f.read(buf, record_length()); if (*buf) r = new_rec(buf); else break; } return r >= 0; } TQuery_type TAS400_recordset::parse_query(const char* query, TFilename& table) { TString q(query); if (q.find("AS400(") >= 0) { const int da = q.find('('); const int al = q.find(')', da); TToken_string k(q.sub(da+1, al), ','); _info._width = k.get_int(0); _key._width = k.get_int(); _key._pos = k.get_int(); q = q.mid(al+1); q.trim(); } return TText_recordset::parse_query(q, table); } bool TAS400_recordset::set_field(const TAS400_column_info& fi, const TVariant& var) { TToken_string& r = row(); switch (fi._type) { case _intfld: case _longfld: { TString80 str; if (fi._width > 8 && var.is_real()) str = var.as_real().string(fi._width, 0, ' '); else str.format("%*ld", fi._width, var.as_int()); r.overwrite(str, fi._pos); } break; case _intzerofld: case _longzerofld: { TString80 str; if (fi._width > 8 && var.is_real()) str = var.as_real().string(fi._width, 0, '0'); else str.format("%0*ld", fi._width, var.as_int()); r.overwrite(str, fi._pos); } break; case _realfld: { const char* str = var.as_real().string(fi._width); r.overwrite(str, fi._pos); } break; case _datefld: if (fi._width == 8) { TString8 str; str << var.as_date().date2ansi(); r.overwrite(str, fi._pos, fi._width); break; } // fall down to default default: r.overwrite(var.as_string(), fi._pos, fi._width); break; } bool ok = true; if (fi._required && var.is_empty()) ok = false; return ok; } TAS400_column_info* TAS400_recordset::parse_field(const char* column, int& c, bool create) { CHECK(column && *column > ' ', "NULL field name"); TAS400_column_info* ci = NULL; TString16 trc; TString80 fld(column); const int dot = fld.find('.'); if (dot > 0) { trc = fld.left(dot); fld.ltrim(dot+1); } else trc = rec_type(); TArray* info = (TArray*)_trc.objptr(trc); if (info == NULL && create) { info = new TArray; _trc.add(trc, info); } if (info != NULL) { if (create) { ci = new TAS400_column_info; ci->_name = fld; if (info->items() > 0) { const TAS400_column_info& last = *(const TAS400_column_info*)info->objptr(info->last()); ci->_pos = last._pos+last._width; } c = info->add(ci); } else { for (c = info->last(); c >= 0; c--) { TAS400_column_info* aci = (TAS400_column_info*)info->objptr(c); if (aci->_name == fld) { ci = aci; break; } } } } return ci; } unsigned int TAS400_recordset::columns() const { const TArray* info = (const TArray*)_trc.objptr(rec_type()); if (info) return info->items(); return TText_recordset::columns(); } const TRecordset_column_info& TAS400_recordset::column_info(unsigned int c) const { const TArray* info = (const TArray*)_trc.objptr(rec_type()); if (info) { TRecordset_column_info* i = (TRecordset_column_info*)info->objptr(c); if (i != NULL) return *i; } return TText_recordset::column_info(c); } int TAS400_recordset::find_column(const char* column) const { int c = -1; ((TAS400_recordset*)this)->parse_field(column, c, false); return c; } const TRecordset_column_info& TAS400_recordset::column_info(const char* column) const { int c = -1; TRecordset_column_info* ci = ((TAS400_recordset*)this)->parse_field(column, c, false); if (ci != NULL) { return *ci; } return TText_recordset::column_info(column); } const TVariant& TAS400_recordset::get_field(const TAS400_column_info& ci) const { const TRecnotype n = current_row(); if (n >= 0 && n < items()) { const TString& str = row(n).mid(ci._pos, ci._width); TVariant& var = get_tmp_var(); var.set(str); var.convert_to(ci._type); return var; } return ci._default; } const TVariant& TAS400_recordset::get(unsigned int column) const { const TArray* info = (const TArray*)_trc.objptr(rec_type()); if (info) { const TAS400_column_info* ci = (const TAS400_column_info*)info->objptr(column); if (ci != NULL) return get_field(*ci); } return TText_recordset::get(column); } const TVariant& TAS400_recordset::get(const char* column) const { int c = -1; if (column && column[1] != '\0') { const TAS400_column_info* ci = ((TAS400_recordset*)this)->parse_field(column, c, false); if (ci != NULL) return get_field(*ci); } c = TText_recordset::find_column(column); return TText_recordset::get(c); } TRecnotype TAS400_recordset::new_rec(const char* trc) { CHECK(record_length() > 0, "Lunghezza record nulla"); if (trc && (int)strlen(trc) == record_length()) return TText_recordset::new_rec(trc); else { const TString str(record_length(), ' '); const TRecnotype n = TText_recordset::new_rec(str); if (trc && (int)strlen(trc) == key_length()) { TArray* info = (TArray*)_trc.objptr(trc); if (info != NULL) // Se il tracciato e' noto, riempio di zeri i campi opportuni { FOR_EACH_ARRAY_ITEM_BACK((*info), i, obj) { const TAS400_column_info& ci = *(const TAS400_column_info*)obj; if (ci._default.is_null()) { if (ci._type == _intzerofld || ci._type == _longzerofld) set_field(ci, NULL_VARIANT); } else set_field(ci, ci._default); } } row(n).overwrite(trc, key_position(), key_length()); } return n; } } const TString& TAS400_recordset::rec_type(TRecnotype r) const { if (key_length() > 0) { const TToken_string& riga = row(r); return riga.mid(key_position(), key_length()); } return EMPTY_STRING; } bool TAS400_recordset::create_field(const char* nam, int pos, int len, TFieldtypes typ, bool req, const TVariant& def) { CHECK(nam && *nam > ' ', "Null field name"); int c = -1; TAS400_column_info* ci = parse_field(nam, c, true); const bool ok = ci != NULL; if (ok) { if (pos >= 0) // Se l'utente fissa una posizione impostala, altrimenti tieni quella automatica ci->_pos = pos; ci->_width = len; ci->_type = typ; ci->_required = req; ci->_default = def; CHECKS(ci->_pos >= 0 && ci->_pos < record_length(), "Invalid position for field ", nam); CHECKS(ci->_width > 0 && ci->_pos+ci->_width <= record_length(), "Invalid lenght for field ", nam); } return ok; } bool TAS400_recordset::set(const char* column, const TVariant& var) { int c = -1; TAS400_column_info* ci = parse_field(column, c, false); bool ok = ci != NULL; if (ok) ok = set_field(*ci, var); return ok; } bool TAS400_recordset::save_as_text(const char* path) { bool valid = path && *path; if (valid) { ofstream out(path, ios::binary); for (bool ok = move_first(); ok; ok = move_next()) out << row(); // NON mettere << endl } return valid; } TAS400_recordset::TAS400_recordset(const char* query) : TText_recordset(query) { TFilename n; if (parse_query(query, n) == _qt_select && n.exist()) load_file(n); }