#include "xvtdb.h" #include #define _CON(a) ((SAConnection *)a) #define _RCS(a) ((SACommand *)a) #define _ERR(a) ((SAException *)a) // Funzione per la connessione, utilizzando un DBMS devo controllare sempre int xvt_create_connection(P_CONN_VOID con, const char* db, const char* user, const char* pass, TT_driver tipoDb) { if(con != NULL) { // Se è già connesso lo scollego if(_CON(con)->isConnected()) _CON(con)->Disconnect(); SAString dbAddress = db; SAString usr = user; SAString psw = pass; SAClient_t dbDriver = (SAClient_t)tipoDb; if (dbAddress.IsEmpty() || usr.IsEmpty()) { return NOT_INITIALIZED; } try { // Mi collego _CON(con)->Connect(dbAddress, usr, psw, dbDriver); // Imposto che non si possono vedere i record non committati _CON(con)->setIsolationLevel(SA_ReadCommitted); } catch (SAException &x) { return x.ErrNativeCode(); } return NOERR; } return NOT_INITIALIZED; } /****************************************************************************** * TXvt_recordset * * Classe per esecuzioni di query temporanee (wrapper semplice per SACommand) * ******************************************************************************/ TXvt_recordset::TXvt_recordset() { _con = new SAConnection; _recset = new SACommand; try { _RCS(_recset)->setConnection(_CON(_con)); } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); } } TXvt_recordset::TXvt_recordset(const char* db, const char* user, const char* pass, TT_driver tipoDb, const char * query, const bool ex, const bool freezed) { _con = new SAConnection; if(xvt_create_connection(_con, db, user, pass, tipoDb) == NOERR) { try { _recset = new SACommand; _RCS(_recset)->setConnection(_CON(_con)); // if (query[0] != '\0') if (query && *query) { set(query); if (ex) { exec(); // Terribile da vedere, ma ho fatto una funzione apposta e la voglio usare per Diana! if(freezed) freeze(); } } } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); } } } TXvt_recordset::TXvt_recordset(P_CONN_VOID c, const char * query, bool ex) { _toDisconnect = true; //_con = c; memcpy(_con, c, sizeof(c)); if (!_CON(_con)->isConnected()) bool tolla = true; _recno = -1; try { _recset = new SACommand; _RCS(_recset)->setConnection(_CON(_con)); // if (query[0] != '\0') if (query && *query) { set(query); if (ex) { exec(); } } } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); } } TXvt_recordset::~TXvt_recordset() { try { if(_toDisconnect && _CON(_con)->isConnected()) _CON(_con)->Disconnect(); if(_con != NULL) delete _con; if(_recset != NULL) delete _recset; } catch(...){} } /* PRIVATE FUNCTIONS **************************************************************************************************/ const bool TXvt_recordset::checkPermission() { bool err = isFreezed(); if(err) { _codeError = ERROR_FREEZED; _stringError = "Il recordset è bloccato"; } return !err; } /* PUBLIC FUNCTIONS **************************************************************************************************/ /************************************************************************************************** * Gestione Connection * **************************************************************************************************/ int TXvt_recordset::connect(const char* db, const char* user, const char* pass, TT_driver tipoDb) { return xvt_create_connection(_con, db, user, pass, tipoDb); } void TXvt_recordset::disconnect() { try { _CON(_con)->Disconnect(); } catch(SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); } } bool TXvt_recordset::commit(bool autoRoll) { try { _CON(_con)->Commit(); } catch (SAException &x) { if (autoRoll) { rollback(); } _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); return false; } return true; } bool TXvt_recordset::rollback() { try { _CON(_con)->Rollback(); } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); return false; } return true; } void TXvt_recordset::setClient(TT_driver client) { _CON(_con)->setClient((SAClient_t) client); } void TXvt_recordset::setConOption(const char* opt) { _CON(_con)->setOption(opt); } void TXvt_recordset::setAutocommit(bool ac) { _CON(_con)->setAutoCommit(ac ? SA_AutoCommitOn : SA_AutoCommitOff); } void TXvt_recordset::setVisibility(isoLvl vis) { /* La libreria attuale supporta diversi tipi di visibilità, per mantenere una compatibilità massima * (evitando inutili seghe mentali) consiglio di usare i primi due, di default la classe imposta "Read committed" * Tipi di isolazione: * 0 -> Read uncommitted. * 1 -> Read committed. * 2 -> Repeatable read. * 3 -> Serializable. */ _CON(_con)->setIsolationLevel((SAIsolationLevel_t)vis); } bool TXvt_recordset::isConnect() { return _CON(_con)->isConnected(); } bool TXvt_recordset::isAlive() { return _CON(_con)->isAlive(); } int TXvt_recordset::getVisibility() { return (isoLvl)_CON(_con)->IsolationLevel(); } bool TXvt_recordset::getAutocommit() { return _CON(_con)->AutoCommit() == SA_AutoCommitOn; } const char* TXvt_recordset::getOption(const char* opt) { return _CON(_con)->Option(opt); } long TXvt_recordset::getClientV() { return _CON(_con)->ClientVersion(); } const char* TXvt_recordset::getServerV() { return _CON(_con)->ServerVersionString(); } long TXvt_recordset::getServerVN() { return _CON(_con)->ServerVersion(); } /************************************************************************************************** * Gestione Recordset * **************************************************************************************************/ bool TXvt_recordset::set(const char* query) { try { _RCS(_recset)->setCommandText(query); } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); return false; } return true; } bool TXvt_recordset::exec(bool autoF) { try { _RCS(_recset)->Execute(); _recno = -1; if (autoF) { next(); } } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); return false; } return true; } bool TXvt_recordset::next() { bool fetched = false; try { if(_RCS(_recset)->FetchNext()) { fetched = true; _recno++; } } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); } return fetched; } bool TXvt_recordset::prev() { bool fetched = false; try { if (_RCS(_recset)->FetchPrior()) { fetched = true; _recno--; } } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); } return fetched; } bool TXvt_recordset::first() { bool fetched = false; try { if (_RCS(_recset)->FetchFirst()) { fetched = true; _recno = 0; } } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); } return fetched; } bool TXvt_recordset::last() { /* La vita sarebbe molto bella se potessi chiamare la funzione FetchLast(), // siccome non so la posizione del record eseguo ciclicamente Next // _RCS(_recset)->FetchLast(); while (Next()) { _recno++; } */ bool fetched = false; try { if (_RCS(_recset)->FetchLast()) { fetched = true; _recno = 0; } } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); } return fetched; } bool TXvt_recordset::go(int newPos) { // Controllo che la nuova posizione non sia fuori dal limite inferiore (Non so quanto è grande il recordset) bool result = newPos >= 0 ? true : false; // Se la posizione è minore mi sposto indietro while (newPos < _recno && result) { result = prev(); } // Se la posizione è maggiore mi sposto in avanti while (newPos > _recno && result) { result = next(); } /* // Controllo finale per prevenire errori if (newPos == _recno) return true; else return false; */ return result; } int TXvt_recordset::get_int(const char* field) { try { return static_cast(_RCS(_recset)->Field(field).asLong()); } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); return -1; } } short TXvt_recordset::get_short(const char* field) { try { return _RCS(_recset)->Field(field).asShort(); } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); return -1; } } long TXvt_recordset::get_long(const char* field) { try { return _RCS(_recset)->Field(field).asLong(); } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); return -1; } } double TXvt_recordset::get_double(const char* field) { try { return _RCS(_recset)->Field(field).asDouble(); } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); return -1; } } bool TXvt_recordset::get_bool(const char* field) { try { return _RCS(_recset)->Field(field).asBool(); } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); return false; } } /* real TXvt_recordset::GetReal(const char * field) { return Get(field); } */ const char* TXvt_recordset::getDate(const char * field) { try { SADateTime app = _RCS(_recset)->Field(field).asDateTime(); char date[10]; sprintf_s(date, (size_t)10, "%d-%d-%d", app.GetDay(), app.GetMonth(), app.GetYear()); return date; } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); return NULL; } } const char* TXvt_recordset::get(const char* field) { try { return static_cast(_RCS(_recset)->Field(field).asString()); } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); return ""; } } char TXvt_recordset::get_char(const char* field) { try { return _RCS(_recset)->Field(field).asString()[0]; } catch (SAException &x) { _codeError = x.ErrNativeCode(); _stringError = x.ErrMessage(); return '\0'; } } long TXvt_recordset::getCodeError(bool erase) { long app = _codeError; if (erase) _codeError = NOERR; return app; } const char* TXvt_recordset::getStringError(bool erase) { const char* app = _stringError.c_str(); if (erase) _stringError.erase(); return app; }