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