Files correlati : Ricompilazione Demo : [ ] Commento : Aggiunti files per supporto ODBC via XML git-svn-id: svn://10.65.10.50/trunk@11403 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			653 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			653 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #ifndef CB6
 | |
| 
 | |
| #include <xvt.h>
 | |
| #include <codeb.h>
 | |
| 
 | |
| #include <config.h>
 | |
| #include <diction.h>
 | |
| #include <extcdecl.h>
 | |
| #include <lffiles.h>
 | |
| #include <netsock.h>
 | |
| #include <prefix.h>
 | |
| #include <xml.h>
 | |
| 
 | |
| #include <strstrea.h>
 | |
| 
 | |
| 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
 |