feb69c6dff
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
|