#ifndef CB6 #include #include #include #include #include #include #include #include #include #include class TDB_table : public TObject { TString _study, _firm, _name; int _logicnum; int _mode, _index; int _rec_len; long _rec_count; TString _query; TString _query_name; long _recno; // 0 = bof; 1 = first record; 2 second record TXmlItem _record; TString _record_buf, _key_buf; protected: void build_soap_method(const char* strMethod, TXmlItem& method) const; int fill_record(const TXmlItem* res); public: virtual bool ok() const { return rec_len() > 0; } int select_tag(int t); int tag() const { return _index; } int rec_len() const; long rec_count() const; bool bof() const { return _recno <= 0; } bool eof() const { return _recno > rec_count(); } char* get_record(); char* get_key(); long recno() const { return _recno; } int go_to(long recno); int skip_to(long recno, long offset); int seek(const char* key); TDB_table(const char* file, int mode, int index); }; class TDB_manager : public TSocketClient { TString _server; TArray _table; int _error; protected: public: TCodeb_handle open(const char* name, int mode, int index); int close(TCodeb_handle h); TDB_table& table(TCodeb_handle h) const; int set_error(int e) { return _error = e; } int get_error() const { return _error; } TXmlItem* call_soap(const TXmlItem& method, TXmlItem& answer); TDB_manager(); ~TDB_manager(); }; static TDB_manager* _db = NULL; /////////////////////////////////////////////////////////// // TDB_table /////////////////////////////////////////////////////////// void TDB_table::build_soap_method(const char* strMethod, TXmlItem& method) const { CHECKS(strMethod[0] == 'm' && strMethod[1] == ':', "Missing m: in SOAP method", strMethod); method.Destroy(); method.SetTag(strMethod); method.AddSoapString("Study", _study); method.AddSoapString("Firm", _firm); method.AddSoapString("Table", _name); method.AddSoapInt("Index", _index); } long TDB_table::rec_count() const { if (_rec_count <= 0) { TXmlItem method, answer; build_soap_method("m:TableRows", method); const TXmlItem* res = _db->call_soap(method, answer); if (res != NULL) { TString16 str; res->GetEnclosedText(str); (long&)_rec_count = atol(str); } } return _rec_count; } int TDB_table::fill_record(const TXmlItem* res) { if (res != NULL) { const TXmlItem* rec = res->FindFirst("Record"); _recno = atol(rec->GetAttr("RecNo")); if (_recno > _rec_count) _rec_count = _recno; const RecDes& rd = prefix().get_recdes(_logicnum); TString16 name; TString value; for (int i = 0; i < rec->GetChildren(); i++) { const TXmlItem& fld = *rec->GetChild(i); name = fld.GetAttr("Name"); name.upper(); const int index = findfld(&rd, name); if (index != FIELDERR) { fld.GetEnclosedText(value); switch (rd.Fd[index].TypeF) { case _boolfld: value = value[0] == '1' ? "Y" : "N"; break; case _intfld: case _longfld: case _intzerofld: case _longzerofld: value.right_just(rd.Fd[index].Len); break; case _memofld: value.cut(0); break; default: break; } _record_buf.overwrite(value, rd.Fd[index].RecOff); } } return NOERR; } _recno = _rec_count*4+1; // EOF return _db->set_error(5); } int TDB_table::go_to(long recno) { if (recno == _recno) return NOERR; TXmlItem method; build_soap_method("m:GetRecord", method); method.AddSoapInt("RecNo", recno); const TXmlItem* res = _db->call_soap(method, _record); return fill_record(res); } int TDB_table::skip_to(long recno, long offset) { TXmlItem method; build_soap_method("m:SkipRecord", method); method.AddSoapInt("RecNo", recno); method.AddSoapInt("Offset", offset); const TXmlItem* res = _db->call_soap(method, _record); return fill_record(res); } char* TDB_table::get_record() { return _record_buf.get_buffer(); } char* TDB_table::get_key() { _key_buf.cut(0); if (_logicnum > 0 && _index > 0 && _recno > 0 && _recno <= rec_count()) { const TXmlItem* rec = _record.FindFirst("Record"); if (rec != NULL) { const RecDes& rd = prefix().get_recdes(_logicnum); const KeyDes& kd = rd.Ky[_index-1]; // Elenco dei campi della chiave TString str; for (int i = 0; i < kd.NkFields; i++) { const int nf = kd.FieldSeq[i] % MaxFields; const RecFieldDes& rf = rd.Fd[nf]; for (int i = 0; i < rec->GetChildren(); i++) { const TXmlItem& fld = *rec->GetChild(i); if (fld.GetAttr("Name").compare(rf.Name, -1, true) == 0) { fld.GetEnclosedText(str); switch (rf.TypeF) { case _intfld: case _longfld: case _intzerofld: case _longzerofld: str.right_just(rf.Len); break; default: str.rpad(rf.Len); break; } _key_buf << str; break; } } } } } return _key_buf.get_buffer(); } int TDB_table::seek(const char* key) { /* TXmlItem method; build_soap_method("m:SeekRecord", method); method.AddSoapString("Key", key); const TXmlItem* res = _db->call_soap(method, _record); return fill_record(res); */ return skip_to(0, 0); } int TDB_table::rec_len() const { if (_rec_len <= 0) { TXmlItem method, answer; build_soap_method("m:GetRecordLength", method); const TXmlItem* res = _db->call_soap(method, answer); if (res != NULL) { TString16 str; if (res->GetEnclosedText(str)) (int&)_rec_len = atoi(str)+1; // Add deleted flag (1 byte) } } return _rec_len; } int TDB_table::select_tag(int t) { int err = NOERR; if (t != _index) { _index = t; if (ok()) { TXmlItem method, answer; build_soap_method("m:CreateIndex", method); const RecDes& rd = prefix().get_recdes(_logicnum); const KeyDes& kd = rd.Ky[_index-1]; // Elenco dei campi della chiave for (int i = 0; i < kd.NkFields; i++) { const int nf = kd.FieldSeq[i] % MaxFields; const RecFieldDes& rf = rd.Fd[nf]; TXmlItem& fld = method.AddChild("Field"); fld.SetAttr("Name", rf.Name); if (kd.FieldSeq[i] >= MaxFields) fld.SetAttr("Upper", "1"); } TString16 str; const TXmlItem* res = _db->call_soap(method, answer); if (res != NULL) res->GetEnclosedText(str); if (str != "1") err = _db->set_error(883); // ??? } } return err; } TDB_table::TDB_table(const char* file, int mode, int index) : _mode(mode), _index(index), _recno(-1), _rec_count(-1), _rec_len(-1), _logicnum(0) { TToken_string tok(file, '/' ); const int dot = tok.rfind('.'); if (dot > 0) tok.cut(dot); tok.replace('\\', '/'); tok.upper(); const int items = tok.items(); tok.get(items-1, _name); tok.get(items-2, _firm); tok.get(items-3, _study); FileDes filedes; memset(&filedes, 0, sizeof(filedes)); for (int i = LF_USER; i < 100; i++) { CGetFile(i, &filedes, _nolock, _nordir); if (_name.compare(filedes.SysName+1, -1, true) == 0) { _logicnum = i; break; } } } /////////////////////////////////////////////////////////// // TDB_manager /////////////////////////////////////////////////////////// TCodeb_handle TDB_manager::open(const char* name, int mode, int index) { TCodeb_handle h = -1; // Inizializzo handle non valido // Crea tabella TDB_table* t = new TDB_table(name, mode, index); if (t->ok()) { // Cerca primo handle disponibile for (h = 0; _table.objptr(h) != NULL; h++); _table.add(t, h); } else delete t; return h; } int TDB_manager::close(TCodeb_handle h) { const int err = _table.destroy(h) ? 0 : 2; return err; } TDB_table& TDB_manager::table(TCodeb_handle h) const { TDB_table* t = (TDB_table*)_table.objptr(h); CHECKD(t != NULL, "Invalid TABLE handle ", h); return *t; } TXmlItem* TDB_manager::call_soap(const TXmlItem& method, TXmlItem& answer) { TXmlItem* result = NULL; CONNID conn = 0; for (int i = 0; conn == 0 && i < 5; i++) conn = QueryConnection("", _server); if (conn != 0) { TString str(8192); method.AsString(str); if (HttpSoap(conn, str)) { size_t size; char* buf = (char*)GetBuffer(size); istrstream inf(buf, size); if (answer.Read(inf)) { str = method.GetTag(); str << "Result"; result = answer.FindFirst(str); } } else error_box(FR("Impossible eseguire '%s' sul soap server '%s'"), (const char*)method.GetTag(), (const char*)_server); RemoveConnection(conn); } else error_box(FR("Impossible connettersi al soap server '%s'"), (const char*)_server); return result; } TDB_manager::TDB_manager() { TConfig ini(CONFIG_INSTALL, "Server"); _server = ini.get("DataBase", NULL, -1, "127.0.0.1:3885"); } TDB_manager::~TDB_manager() { } /////////////////////////////////////////////////////////// // codeb.h implementation /////////////////////////////////////////////////////////// void DB_init(void) { DB_exit(); _db = new TDB_manager(); } void DB_exit(void) { if (_db != NULL) { delete _db; _db = NULL; } } TCodeb_handle DB_open(const char *filename, int mode, int index) { return _db->open(filename, mode, index); } int DB_close(TCodeb_handle handle) { return _db->close(handle); } char* DB_getrecord(int handle) { return _db->table(handle).get_record(); } int DB_reclen(int handle) { return _db->table(handle).rec_len(); } int DB_keylen(int handle) { return 0; } long DB_recno(int handle) { return _db->table(handle).recno(); } long int DB_reccount(int handle) { return _db->table(handle).rec_count(); } int DB_tagselect(int handle,int index_no) { return _db->table(handle).select_tag(index_no); } int DB_tagget(int handle) { return _db->table(handle).tag(); } int DB_first(int handle) { return _db->table(handle).skip_to(0, 0); } int DB_last(int handle) { return _db->table(handle).skip_to(-1, 0); } int DB_next(int handle) { return DB_skip(handle, +1); } int DB_prev(int handle) { return DB_skip(handle, -1); } int DB_skip(int handle,long offset) { TDB_table& tab = _db->table(handle); return tab.skip_to(tab.recno(), offset); } int DB_lock(int handle) { return 0; } int DB_unlock(int handle) { return 0; } int DB_seek(int handle,char *key) { return _db->table(handle).seek(key); } int DB_eof(int handle) { return _db->table(handle).eof(); } int DB_bof(int handle) { return _db->table(handle).bof(); } int DB_go(int handle,long recno) { return _db->table(handle).go_to(recno); } int DB_delete(int handle) { return 0; } int DB_recall(int handle) { return 0; } int DB_delkey(int handle, char* key, long recno) { return 0; } int DB_flush(int handle) { return 0; } int DB_rewrite(int handle) { return 0; } bool DB_has_memo(int handle) { return false; } int DB_add(int handle) { return 0; } int DB_lockfile(int handle) { return 0; } int DB_packfile(short vis, const char * filename, long eod) { return 0; } int DB_packmemo(short vis, const char * filename) { return 0; } int DB_packindex(short vis, const char * filename, RecDes *r, long *peod, bool ask ) { return 0; } int DB_build(const char * filename, RecDes *r) { return 0; } int DB_recinfo(const char * filename, FileDes *d, RecDes *r, char* keys) { return 0; } int DB_get_error(void) { return _db->get_error(); } void DB_zero_error(void) { _db->set_error(0); } int DB_index_seek(int handle, char* from) { return DB_seek(handle, from); } long DB_index_recno(int handle) { return DB_recno(handle); } long DB_index_next(int handle) { return DB_next(handle); } char* DB_index_getkey(int handle) { return _db->table(handle).get_key(); } int DB_index_go(int handle, const char * key, long recno) { return DB_go(handle, recno); } char* DB_memoptr(const int handle, const char * fieldname ) { return 0; } int DB_memowrite(const int handle, const char * fieldname, const char * data ) { return 0; } int DB_index_eof(int handle) { return DB_eof(handle); } int DB_lock_rec(int handle,long nrec) { return 0; } int DB_file_locked(int handle) { return 0; } int DB_rec_locked(int handle,long nrec) { return 0; } long DB_getconf() { return 0; } long DB_changed(int handle) { return 0; } #endif