#include "wxinc.h" #include "xvt.h" #include "../wxSqlite3/wxSqlite3.h" class XVT_SQLDataBase { public: virtual bool Open(const char* dsn, const char* usr, const char* pwd, const char* dir) = 0; virtual bool Close() = 0 { return false; } virtual bool IsOk() const = 0 { return false; } virtual ULONG Execute(const char* sql, ODBC_CALLBACK cb, void* jolly) = 0; virtual SLIST ListFields(const char* table) const = 0; virtual SLIST ListTables() const = 0; virtual wxString FindField(const char* strTable, const char* strField) const = 0; virtual bool TableExists(const char* name) const; virtual bool Begin() const { return false; } virtual bool Commit() const { return false; } virtual bool Rollback() const { return false; } virtual ~XVT_SQLDataBase() { Close(); } }; bool XVT_SQLDataBase::TableExists(const char* name) const { bool yes = false; SLIST list = ListTables(); for (SLIST_ELT e = xvt_slist_get_first(list); e != NULL && !yes; e = xvt_slist_get_next(list, e)) { const char* table = xvt_slist_get(list, e, NULL); yes = xvt_str_same(name, table) != 0; } xvt_slist_destroy(list); return yes; } class XVT_SQLDB_SQLite3 : public XVT_SQLDataBase { wxSQLite3Database* m_pDB; protected: virtual bool Open(const char* dsn, const char* usr, const char* pwd, const char* dir); virtual bool Close(); virtual bool IsOk() const { return m_pDB != NULL && m_pDB->IsOpen(); } virtual ULONG Execute(const char* sql, ODBC_CALLBACK cb, void* jolly); virtual SLIST ListFields(const char* table) const; virtual SLIST ListTables() const; virtual wxString FindField(const char* strTable, const char* strField) const; virtual bool TableExists(const char* name) const; public: virtual bool Begin() const; virtual bool Commit() const; virtual bool Rollback() const; XVT_SQLDB_SQLite3() : m_pDB(NULL) {} }; bool XVT_SQLDB_SQLite3::Open(const char* dsn, const char*, const char*, const char*) { Close(); m_pDB = new wxSQLite3Database; if (dsn == NULL || *dsn <= ' ') dsn = ":memory:"; try { m_pDB->Open(dsn); } catch(wxSQLite3Exception& e) { xvt_dm_post_error(e.GetMessage()); return false; } return true; } bool XVT_SQLDB_SQLite3::Close() { if (IsOk()) { delete m_pDB; m_pDB = NULL; } return true; } bool XVT_SQLDB_SQLite3::Begin() const { bool bDone = IsOk(); if (bDone) { try { m_pDB->Begin(); } catch(wxSQLite3Exception& e) { xvt_dm_post_error(e.GetMessage()); bDone = false; } } return bDone; } bool XVT_SQLDB_SQLite3::Commit() const { bool bDone = IsOk(); if (bDone) { try { m_pDB->Commit(); } catch(wxSQLite3Exception& e) { xvt_dm_post_error(e.GetMessage()); bDone = false; } } return bDone; } bool XVT_SQLDB_SQLite3::Rollback() const { bool bDone = IsOk(); if (bDone) { try { m_pDB->Rollback(); } catch(wxSQLite3Exception& e) { xvt_dm_post_error(e.GetMessage()); bDone = false; } } return bDone; } ULONG XVT_SQLDB_SQLite3::Execute(const char* sql, ODBC_CALLBACK cb, void* jolly) { ULONG nRows = 0; if (!IsOk()) return nRows; if (cb != NULL) // Ho una vera callback? { try { wxSQLite3ResultSet rs = m_pDB->ExecuteQuery(sql); short numcols = rs.GetColumnCount(); if (numcols > 0) { wxArrayString aNames, aValues; const short nMaxCols = 256; char* values[nMaxCols]; // Lista dei valori del record corrente memset(values, 0, sizeof(values)); char* names[2*nMaxCols]; // Lista dei nomi dei campi e dei tipi memset(names, 0, sizeof(names)); if (numcols > nMaxCols) numcols = nMaxCols; short c; for (c = 0; c < numcols; c++) { aNames.Add(rs.GetColumnName(c)); names[c] = (char*)(const char*)aNames[c]; switch (rs.GetColumnType(c)) { case WXSQLITE_INTEGER: case WXSQLITE_FLOAT: names[c+numcols] = "NUMERIC"; break; default: names[c+numcols] = "VARCHAR"; break; } } while (rs.NextRow()) { aValues.Empty(); for (c = 0; c < numcols; c++) { aValues.Add(rs.GetAsString(c)); values[c] = (char*)(const char*)aValues[c]; } if (cb(jolly, numcols, values, names) != 0) break; nRows++; } } } catch(wxSQLite3Exception& e) { xvt_dm_post_error(e.GetMessage() + "\n" + sql); } } else nRows = m_pDB->ExecuteUpdate(sql); return nRows; } SLIST XVT_SQLDB_SQLite3::ListTables() const { wxASSERT(m_pDB != NULL); SLIST list = xvt_slist_create(); const wxString strQuery = wxT("SELECT name FROM sqlite_master WHERE type = 'table'"); try { wxSQLite3ResultSet rs = m_pDB->ExecuteQuery(strQuery); while (rs.NextRow()) xvt_slist_add_at_elt(list, NULL, rs.GetAsString(0), 0L); } catch(wxSQLite3Exception& e) { xvt_dm_post_error(e.GetMessage() + "\n" + strQuery); } return list; } SLIST XVT_SQLDB_SQLite3::ListFields(const char* strTable) const { SLIST list = NULL; if (TableExists(strTable)) { list = xvt_slist_create(); wxString strQuery; strQuery << "PRAGMA table_info(" << (const char*)strTable << ");"; try { wxSQLite3ResultSet rs = m_pDB->ExecuteQuery(strQuery); while (rs.NextRow()) { const wxString strField = rs.GetAsString(1); const wxString strType = rs.GetAsString(2); if (strType == "INTEGER") xvt_slist_add_at_elt(list, NULL, strField, 2L); // intfld if (strType == "NUMERIC") xvt_slist_add_at_elt(list, NULL, strField, 5L); // realfld else xvt_slist_add_at_elt(list, NULL, strField, 1L); // alfafld } } catch(wxSQLite3Exception& e) { xvt_dm_post_error(e.GetMessage() + "\n" + strQuery); } } return list; } wxString XVT_SQLDB_SQLite3::FindField(const char* strTable, const char* strField) const { wxString strType; if (TableExists(strTable)) { wxString strQuery; strQuery << "PRAGMA table_info(" << (const char*)strTable << ");"; try { wxSQLite3ResultSet rs = m_pDB->ExecuteQuery(strQuery); while (rs.NextRow()) { const wxString strFieldFound = rs.GetAsString(1); if (strFieldFound == strField) strType = rs.GetAsString(2); } } catch (wxSQLite3Exception& e) { xvt_dm_post_error(e.GetMessage() + "\n" + strQuery); } } return strType; } bool XVT_SQLDB_SQLite3::TableExists(const char* name) const { return m_pDB != NULL && name && *name && m_pDB->TableExists(name); } /////////////////////////////////////////////////////////// // xvt_sql_... /////////////////////////////////////////////////////////// XVT_SQLDB xvt_sql_open(const char* dsn, const char* usr, const char* pwd, const char* dir) { XVT_SQLDataBase* db = new XVT_SQLDB_SQLite3; db->Open(dsn, usr, pwd, dir); return (XVT_SQLDB)db; } BOOLEAN xvt_sql_close(XVT_SQLDB handle) { BOOLEAN ok = handle != NULL; if (ok) { XVT_SQLDataBase* db = (XVT_SQLDataBase*)handle; if (db != NULL) delete db; } return ok; } BOOLEAN xvt_sql_begin(XVT_SQLDB handle) { BOOLEAN ok = handle != NULL; if (ok) { XVT_SQLDataBase* db = (XVT_SQLDataBase*)handle; if (db != NULL) ok = db->Begin(); } return ok; } BOOLEAN xvt_sql_commit(XVT_SQLDB handle) { BOOLEAN ok = handle != NULL; if (ok) { XVT_SQLDataBase* db = (XVT_SQLDataBase*)handle; if (db != NULL) ok = db->Commit(); } return ok; } BOOLEAN xvt_sql_rollback(XVT_SQLDB handle) { BOOLEAN ok = handle != NULL; if (ok) { XVT_SQLDataBase* db = (XVT_SQLDataBase*)handle; if (db != NULL) ok = db->Rollback(); } return ok; } ULONG xvt_sql_execute(XVT_SQLDB handle, const char* sql, ODBC_CALLBACK cb, void* jolly) { ULONG n = 0; if (handle && sql && *sql) { XVT_SQLDataBase* db = (XVT_SQLDataBase*)handle; if (db->IsOk()) { try { n = db->Execute(sql, cb, jolly); } catch(wxSQLite3Exception& e) { xvt_dm_post_error(e.GetMessage() + "\n" + sql); n = ~0; } } } return n; } SLIST xvt_sql_list_fields(XVT_SQLDB handle, const char* table) { SLIST list = NULL; XVT_SQLDataBase* db = (XVT_SQLDataBase*)handle; if (table && *table && db != NULL && db->IsOk()) list = db->ListFields(table); return list; } SLIST xvt_sql_list_tables(XVT_SQLDB handle) { SLIST list = NULL; XVT_SQLDataBase* db = (XVT_SQLDataBase*)handle; if (db != NULL && db->IsOk()) list = db->ListTables(); return list; } XVTDLL const char * xvt_sql_field_type(XVT_SQLDB handle, const char* table, const char* field) { XVT_SQLDataBase* db = (XVT_SQLDataBase*)handle; static wxString strType; strType = ""; if (db != NULL && db->IsOk()) strType = db->FindField(table, field); return strType; } BOOLEAN xvt_sql_table_exists(XVT_SQLDB handle, const char* name) { BOOLEAN yes = FALSE; if (handle && name && *name) { const XVT_SQLDataBase* db = (XVT_SQLDataBase*)handle; if (db->IsOk()) yes = db->TableExists(name); } return yes; } BOOLEAN xvt_sql_driver(XVT_SQLDB handle, char* str, int max_size) { if (str != NULL && max_size > 8) { if (handle != NULL) wxStrncpy(str, "SQLite 3", max_size); else wxStrncpy(str, "ODBC 2.0", max_size); } return handle != NULL; }