Aggiunto supporto logging transazioni ODBC

git-svn-id: svn://10.65.10.50/branches/R_10_00@23026 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
guy 2014-12-10 16:17:23 +00:00
parent 4eb316df66
commit 07a1b81dad
2 changed files with 261 additions and 229 deletions

View File

@ -498,6 +498,7 @@ XVTDLL XVT_ODBC xvt_odbc_get_connection(const char* dsn, const char* usr, const
XVTDLL BOOLEAN xvt_odbc_free_connection(XVT_ODBC handle); XVTDLL BOOLEAN xvt_odbc_free_connection(XVT_ODBC handle);
XVTDLL ULONG xvt_odbc_execute(XVT_ODBC handle, const char* sql, ODBC_CALLBACK cb, void* jolly); XVTDLL ULONG xvt_odbc_execute(XVT_ODBC handle, const char* sql, ODBC_CALLBACK cb, void* jolly);
XVTDLL BOOLEAN xvt_odbc_driver(XVT_ODBC handle, char* str, int max_size); XVTDLL BOOLEAN xvt_odbc_driver(XVT_ODBC handle, char* str, int max_size);
XVTDLL BOOLEAN xvt_odbc_log_file(XVT_ODBC handle, const char* str);
XVTDLL BOOLEAN xvt_sql_begin(XVT_SQLDB handle); XVTDLL BOOLEAN xvt_sql_begin(XVT_SQLDB handle);
XVTDLL BOOLEAN xvt_sql_close(XVT_SQLDB handle); XVTDLL BOOLEAN xvt_sql_close(XVT_SQLDB handle);

View File

@ -1,229 +1,260 @@
#include "wxinc.h" #include "wxinc.h"
#include "xvt.h" #include "xvt.h"
#include <wx/db.h> #include <wx/db.h>
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// TwxConnectionDlg // TwxConnectionDlg
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
class TwxConnectionDlg : public wxDialog class TwxConnectionDlg : public wxDialog
{ {
protected: protected:
wxTextCtrl* AddString(wxSizer* ctlSizer, int id, const char* label, wxString* str); wxTextCtrl* AddString(wxSizer* ctlSizer, int id, const char* label, wxString* str);
public: public:
wxString _strDsn, _strUsr, _strPwd, _strDir; wxString _strDsn, _strUsr, _strPwd, _strDir;
TwxConnectionDlg(); TwxConnectionDlg();
}; };
wxTextCtrl* TwxConnectionDlg::AddString(wxSizer* ctlSizer, int id, const char* label, wxString* str) wxTextCtrl* TwxConnectionDlg::AddString(wxSizer* ctlSizer, int id, const char* label, wxString* str)
{ {
wxStaticText* lbl = new wxStaticText(this, wxID_ANY, label); wxStaticText* lbl = new wxStaticText(this, wxID_ANY, label);
const int k = 20, b = k/10; const int k = 20, b = k/10;
wxTextCtrl* txt = new wxTextCtrl(this, id, wxEmptyString, wxDefaultPosition, wxSize(20*k, k), wxTextCtrl* txt = new wxTextCtrl(this, id, wxEmptyString, wxDefaultPosition, wxSize(20*k, k),
0, wxTextValidator(wxFILTER_ASCII, str)); 0, wxTextValidator(wxFILTER_ASCII, str));
ctlSizer->Add(lbl, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, b); ctlSizer->Add(lbl, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, b);
ctlSizer->Add(txt, 1, wxALIGN_LEFT | wxALL, b); ctlSizer->Add(txt, 1, wxALIGN_LEFT | wxALL, b);
return txt; return txt;
} }
TwxConnectionDlg::TwxConnectionDlg() : wxDialog(NULL, wxID_ANY, "ODBC", TwxConnectionDlg::TwxConnectionDlg() : wxDialog(NULL, wxID_ANY, "ODBC",
wxDefaultPosition, wxDefaultSize, wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE) wxDEFAULT_DIALOG_STYLE)
{ {
wxSizer* ctlTextSizer = new wxFlexGridSizer(4, 2, 8, 8); wxSizer* ctlTextSizer = new wxFlexGridSizer(4, 2, 8, 8);
AddString(ctlTextSizer, 1001, "Dsn", &_strDsn); AddString(ctlTextSizer, 1001, "Dsn", &_strDsn);
AddString(ctlTextSizer, 1002, "User", &_strUsr); AddString(ctlTextSizer, 1002, "User", &_strUsr);
AddString(ctlTextSizer, 1003, "Password", &_strPwd); AddString(ctlTextSizer, 1003, "Password", &_strPwd);
AddString(ctlTextSizer, 1004, "Directory", &_strDir); AddString(ctlTextSizer, 1004, "Directory", &_strDir);
wxSizer* ctlButtonSizer = CreateButtonSizer(wxOK | wxCANCEL); wxSizer* ctlButtonSizer = CreateButtonSizer(wxOK | wxCANCEL);
wxBoxSizer* ctlTopSizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer* ctlTopSizer = new wxBoxSizer(wxVERTICAL);
ctlTopSizer->Add(ctlTextSizer, 0, wxALIGN_CENTER); ctlTopSizer->Add(ctlTextSizer, 0, wxALIGN_CENTER);
ctlTopSizer->Add(ctlButtonSizer, 0, wxALIGN_CENTER); ctlTopSizer->Add(ctlButtonSizer, 0, wxALIGN_CENTER);
SetSizer(ctlTopSizer); SetSizer(ctlTopSizer);
ctlTopSizer->SetSizeHints(this); ctlTopSizer->SetSizeHints(this);
} }
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// xvt_odbc_... // xvt_odbc_...
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
XVT_ODBC xvt_odbc_get_connection(const char* dsn, const char* usr, const char* pwd, const char* dir) XVT_ODBC xvt_odbc_get_connection(const char* dsn, const char* usr, const char* pwd, const char* dir)
{ {
static wxDbConnectInf* ci = NULL; static wxDbConnectInf* ci = NULL;
if (ci == NULL) if (ci == NULL)
{ {
ci = new wxDbConnectInf; ci = new wxDbConnectInf;
ci->AllocHenv(); ci->AllocHenv();
} }
wxString strDsn(dsn), strUsr(usr), strPwd(pwd), strDir(dir); wxString strDsn(dsn), strUsr(usr), strPwd(pwd), strDir(dir);
if (strDsn.IsEmpty()) if (strDsn.IsEmpty())
{ {
TwxConnectionDlg* dlg = new TwxConnectionDlg; TwxConnectionDlg* dlg = new TwxConnectionDlg;
if (dlg->ShowModal() == wxID_OK) if (dlg->ShowModal() == wxID_OK)
{ {
strDsn = dlg->_strDsn; strDsn = dlg->_strDsn;
strUsr = dlg->_strUsr; strUsr = dlg->_strUsr;
strPwd = dlg->_strPwd; strPwd = dlg->_strPwd;
strDir = dlg->_strDir; strDir = dlg->_strDir;
} }
dlg->Destroy(); dlg->Destroy();
if (strDsn.IsEmpty()) if (strDsn.IsEmpty())
return NULL; return NULL;
} }
bool bSuccess = false; bool bSuccess = false;
wxDb* db = new wxDb(ci->GetHenv(), true); wxDb* db = new wxDb(ci->GetHenv(), true);
if (strDsn.Find(';') > 0) if (strDsn.Find(';') > 0)
bSuccess = db->Open(strDsn); // Use connection string bSuccess = db->Open(strDsn); // Use connection string
else else
bSuccess = db->Open(strDsn, strUsr, strPwd, true); // Use DSN, user and password bSuccess = db->Open(strDsn, strUsr, strPwd, true); // Use DSN, user and password
if (!bSuccess) if (!bSuccess)
{ {
delete db; delete db;
db = NULL; db = NULL;
} }
return (XVT_ODBC)db; return (XVT_ODBC)db;
} }
BOOLEAN xvt_odbc_free_connection(XVT_ODBC handle) BOOLEAN xvt_odbc_free_connection(XVT_ODBC handle)
{ {
BOOLEAN ok = handle != NULL; BOOLEAN ok = handle != NULL;
if (ok) if (ok)
{ {
wxDb* db = (wxDb*)handle; wxDb* db = (wxDb*)handle;
db->CommitTrans(); db->CommitTrans();
db->Close(); db->Close();
delete db; delete db;
} }
return ok; return ok;
} }
ULONG xvt_odbc_execute(XVT_ODBC handle, const char* sql, ODBC_CALLBACK cb, void* jolly) BOOLEAN xvt_odbc_log_file(XVT_ODBC handle, const char* str)
{ {
ULONG nCount = 0; BOOLEAN ok = handle != NULL;
if (ok)
if (handle && sql && *sql) {
{ wxDb* db = (wxDb*)handle;
wxDb* db = (wxDb*)handle; if (str && *str)
if (cb != NULL) // Ho una vera callback? ok = db->SetSqlLogging(sqlLogON, wxString(str));
{ else
wxDbColInf* columns = NULL; db->SetSqlLogging(sqlLogOFF, wxEmptyString);
short numcols = 0; }
return ok;
if (db->ExecSql(sql, &columns, numcols) && numcols > 0) }
{
const size_t BUF_SIZE = 1024*64; ULONG xvt_odbc_execute(XVT_ODBC handle, const char* sql, ODBC_CALLBACK cb, void* jolly)
char* buffer = new char[BUF_SIZE]; // Valore di un singolo campo {
ULONG nCount = 0;
char** values = new char*[numcols]; // Lista dei valori del record corrente
memset(values, 0, numcols*sizeof(char*)); if (handle && sql && *sql)
{
char** names = new char*[numcols*2]; // Lista dei nomi dei campi e dei tipi wxDb* db = (wxDb*)handle;
memset(names, 0, numcols*2*sizeof(char*));
if (cb != NULL) // Ho una vera callback?
short c; {
for (c = 0; c < numcols; c++) wxDbColInf* columns = NULL;
{ short numcols = 0;
const wxDbColInf& info = columns[c];
names[c] = (char*)info.colName; if (db->ExecSql(sql, &columns, numcols) && numcols > 0)
switch (info.dbDataType) {
{ const size_t BUF_SIZE = 1024*64;
case DB_DATA_TYPE_INTEGER: char* buffer = new char[BUF_SIZE]; // Valore di un singolo campo
case DB_DATA_TYPE_FLOAT:
names[c+numcols] = "NUMERIC"; break; char** values = new char*[numcols]; // Lista dei valori del record corrente
case DB_DATA_TYPE_DATE: memset(values, 0, numcols*sizeof(char*));
names[c+numcols] = "DATE"; break;
default: char** names = new char*[numcols*2]; // Lista dei nomi dei campi e dei tipi
names[c+numcols] = "VARCHAR"; break; memset(names, 0, numcols*2*sizeof(char*));
}
} short c;
for (c = 0; c < numcols; c++)
wxArrayString data; {
for (nCount = 0; db->GetNext(); nCount++) const wxDbColInf& info = columns[c];
{ names[c] = (char*)info.colName;
data.Empty(); // Svuota l'array switch (info.dbDataType)
for (c = 0; c < numcols; c++) {
{ case DB_DATA_TYPE_INTEGER:
const wxDbColInf& info = columns[c]; case DB_DATA_TYPE_FLOAT:
names[c+numcols] = "NUMERIC"; break;
try case DB_DATA_TYPE_DATE:
{ names[c+numcols] = "DATE"; break;
SDWORD cbReturned = SQL_NULL_DATA; default:
names[c+numcols] = "VARCHAR"; break;
switch (info.dbDataType) }
{ }
case DB_DATA_TYPE_DATE:
{ wxArrayString data;
db->GetData(c+1, SQL_C_CHAR, buffer, BUF_SIZE, &cbReturned); for (nCount = 0; db->GetNext(); nCount++)
int d = 0, m = 0, y = 0; {
int n = sscanf(buffer, "%04d-%02d-%02d", &y, &m, &d); data.Empty(); // Svuota l'array
if (n == 3 && d > 0) for (c = 0; c < numcols; c++)
sprintf(buffer, "%04d%02d%02d", y, m, d); {
else const wxDbColInf& info = columns[c];
buffer[0] = '\0';
} try
break; {
default: SDWORD cbReturned = SQL_NULL_DATA;
db->GetData(c+1, SQL_C_CHAR, buffer, BUF_SIZE, &cbReturned);
break; switch (info.dbDataType)
} {
if (cbReturned == SQL_NULL_DATA) case DB_DATA_TYPE_DATE:
buffer[0] = '\0'; {
data.Add(buffer); db->GetData(c+1, SQL_C_CHAR, buffer, BUF_SIZE, &cbReturned);
} int d = 0, m = 0, y = 0;
catch (...) int n = sscanf(buffer, "%04d-%02d-%02d", &y, &m, &d);
{ if (n == 3 && d > 0)
break; sprintf(buffer, "%04d%02d%02d", y, m, d);
} else
} buffer[0] = '\0';
for (c = 0; c < (short)data.GetCount(); c++) }
values[c] = (char*)data[c].c_str(); break;
const int err = cb(jolly, numcols, values, names); default:
if (err != 0) db->GetData(c+1, SQL_C_CHAR, buffer, BUF_SIZE, &cbReturned);
break; break;
} }
if (cbReturned == SQL_NULL_DATA)
delete values; // butta la lista dei valori buffer[0] = '\0';
delete names; // butta la lista dei nomi data.Add(buffer);
delete buffer; // butta il buffer temporaneo }
} catch (...)
} {
else break;
{ }
// Senza callback mi limito a contare i records }
if (db->ExecSql(sql)) for (c = 0; c < (short)data.GetCount(); c++)
{ values[c] = (char*)data[c].c_str();
for (nCount = 0; db->GetNext(); nCount++); const int err = cb(jolly, numcols, values, names);
} if (err != 0)
} break;
} }
return nCount; delete values; // butta la lista dei valori
} delete names; // butta la lista dei nomi
delete buffer; // butta il buffer temporaneo
BOOLEAN xvt_odbc_driver(XVT_ODBC handle, char* str, int max_size) }
{ }
if (str != NULL && max_size > 8) else
{ {
if (handle != NULL) wxString cmd(sql); cmd.MakeUpper();
{
const wxDb* db = (const wxDb*)handle; if (cmd.StartsWith("BEGIN"))
wxStrncpy(str, db->dbInf.driverName, max_size); /* DO NOTHING! */; else
} if (cmd.StartsWith("COMMIT"))
else db->CommitTrans(); else
wxStrncpy(str, "ODBC 2.0", max_size); if (cmd.StartsWith("SELECT"))
} {
return handle != NULL; // Senza callback mi limito a contare i records
} if (db->ExecSql(sql))
for (nCount = 0; db->GetNext(); nCount++);
}
else
{
db->SetDebugErrorMessages(true);
if (db->ExecSql(sql))
nCount = 1;
else
nCount = -db->nativeError;
db->SetDebugErrorMessages(false);
}
}
}
return nCount;
}
BOOLEAN xvt_odbc_driver(XVT_ODBC handle, char* str, int max_size)
{
if (str != NULL && max_size > 8)
{
if (handle != NULL)
{
const wxDb* db = (const wxDb*)handle;
wxStrncpy(str, db->dbInf.driverName, max_size);
}
else
wxStrncpy(str, "ODBC 2.0", max_size);
}
return handle != NULL;
}