Patch level : 12.0 no-patch

Files correlati     : 
Commento            : 
- Aggiunta la possibilità di generare DLL o libreria
- tolti identificatori che generavano warnings per TT_driver e isoLvl
- tolta xvt_create_connection, la connection viene creata nella classe e non più condivisa
- Disabilitato il copy contructor: se quelli di sqlapi li hanno fatto avranno le loro buone ragioni
- rese const isConnect() e isAlive()
- Creato files per contenere i codici di errore

git-svn-id: svn://10.65.10.50/branches/R_10_00@24361 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
mtollari 2018-02-09 13:29:55 +00:00
parent dbbd6bddcc
commit 34ceaffc52
3 changed files with 169 additions and 111 deletions

View File

@ -1,44 +1,11 @@
#include "xvtdb.h" #include "xvtdb.h"
#include <sqlapi.h> #include <sqlapi.h>
#include <string> // sprintf_s
#define _CON(a) ((SAConnection *)a) #define _CON(a) ((SAConnection *)a)
#define _RCS(a) ((SACommand *)a) #define _RCS(a) ((SACommand *)a)
#define _ERR(a) ((SAException *)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 * * TXvt_recordset *
* Classe per esecuzioni di query temporanee (wrapper semplice per SACommand) * * Classe per esecuzioni di query temporanee (wrapper semplice per SACommand) *
@ -61,9 +28,10 @@ TXvt_recordset::TXvt_recordset()
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) 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)
: _db(db), _usr(user), _psw(pass), _drv(tipoDb)
{ {
_con = new SAConnection; _con = new SAConnection;
if(xvt_create_connection(_con, db, user, pass, tipoDb) == NOERR) if(connect(db, user, pass, tipoDb) == NOERR)
{ {
try try
{ {
@ -90,59 +58,27 @@ TXvt_recordset::TXvt_recordset(const char* db, const char* user, const char* pas
} }
} }
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() TXvt_recordset::~TXvt_recordset()
{ {
try try
{ {
if(_toDisconnect && _CON(_con)->isConnected()) if(_CON(_con)->isConnected())
_CON(_con)->Disconnect(); _CON(_con)->Disconnect();
if(_con != NULL) if(_con != NULL)
delete _con; delete _con;
if(_recset != NULL) if(_recset != NULL)
delete _recset; delete _recset;
} }
catch(...){} catch (...) {}
} }
/* PRIVATE FUNCTIONS **************************************************************************************************/ /* PRIVATE FUNCTIONS **************************************************************************************************/
const bool TXvt_recordset::checkPermission() const bool TXvt_recordset::checkPermission()
{ {
bool err = isFreezed(); bool err = is_freezed();
if(err) if (err)
{ setErrorFreezed();
_codeError = ERROR_FREEZED;
_stringError = "Il recordset è bloccato";
}
return !err; return !err;
} }
@ -154,7 +90,44 @@ const bool TXvt_recordset::checkPermission()
int TXvt_recordset::connect(const char* db, const char* user, const char* pass, TT_driver tipoDb) 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); 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())
{
_codeError = NOT_INITIALIZED;
_stringError = NOT_INITIALIZEDS;
}
else
{
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);
return NOERR;
}
catch (SAException &x)
{
_codeError = x.ErrNativeCode();
_stringError = x.ErrMessage();
}
}
}
else
{
_codeError = NOT_INITIALIZED;
_stringError = NOT_INITIALIZEDS;
}
return _codeError;
} }
void TXvt_recordset::disconnect() void TXvt_recordset::disconnect()
@ -172,6 +145,7 @@ void TXvt_recordset::disconnect()
bool TXvt_recordset::commit(bool autoRoll) bool TXvt_recordset::commit(bool autoRoll)
{ {
CHECK_FREEZED
try try
{ {
_CON(_con)->Commit(); _CON(_con)->Commit();
@ -191,6 +165,7 @@ bool TXvt_recordset::commit(bool autoRoll)
bool TXvt_recordset::rollback() bool TXvt_recordset::rollback()
{ {
CHECK_FREEZED
try try
{ {
_CON(_con)->Rollback(); _CON(_con)->Rollback();
@ -232,11 +207,11 @@ void TXvt_recordset::setVisibility(isoLvl vis)
_CON(_con)->setIsolationLevel((SAIsolationLevel_t)vis); _CON(_con)->setIsolationLevel((SAIsolationLevel_t)vis);
} }
bool TXvt_recordset::isConnect() const bool TXvt_recordset::isConnect() const
{ {
return _CON(_con)->isConnected(); return _CON(_con)->isConnected();
} }
bool TXvt_recordset::isAlive() const bool TXvt_recordset::isAlive() const
{ {
return _CON(_con)->isAlive(); return _CON(_con)->isAlive();
} }
@ -265,14 +240,53 @@ long TXvt_recordset::getServerVN()
return _CON(_con)->ServerVersion(); return _CON(_con)->ServerVersion();
} }
bool TXvt_recordset::isLoaded() const
{
return _loaded;
}
long TXvt_recordset::items()
{
// Per non creare casini utilizzo una funzione apposita che mi ritorna il numero
P_CONN_VOID conn = new SAConnection;
char q[500];
long items;
// Connetto la nuova istanza
_CON(conn)->Connect(_db, _usr, _psw, (SAClient_t)_drv);
// Controllo sia tutto a posto
// Creo la query
strcat_s(q, sizeof(q), "SELECT COUNT(*) ");
strcat_s(q, sizeof(q), (strstr(_query, "FROM") != NULL ? strstr(_query, "FROM") : strstr(_query, "from"))); // Serve?
items = xvt_rcs_get_items(conn, q);
if(conn != _con)
delete conn;
return items;
}
long xvt_rcs_get_items(P_CONN_VOID con, const char* query)
{
P_COMM_VOID rcs = new SACommand(_CON(con));
_RCS(rcs)->setCommandText(query);
long r = 0;
for(bool ok = _RCS(rcs)->FetchFirst(); ok; ok = _RCS(rcs)->FetchNext())
r++;
delete rcs;
return r;
}
/************************************************************************************************** /**************************************************************************************************
* Gestione Recordset * * Gestione Recordset *
**************************************************************************************************/ **************************************************************************************************/
bool TXvt_recordset::set(const char* query) bool TXvt_recordset::set(const char* query)
{ {
CHECK_FREEZED
try try
{ {
_query = query;
_RCS(_recset)->setCommandText(query); _RCS(_recset)->setCommandText(query);
} }
catch (SAException &x) catch (SAException &x)
@ -286,6 +300,7 @@ bool TXvt_recordset::set(const char* query)
bool TXvt_recordset::exec(bool autoF) bool TXvt_recordset::exec(bool autoF)
{ {
CHECK_FREEZED
try try
{ {
_RCS(_recset)->Execute(); _RCS(_recset)->Execute();
@ -420,6 +435,11 @@ bool TXvt_recordset::go(int newPos)
return result; return result;
} }
const int TXvt_recordset::rowsAffected()
{
return _RCS(_recset)->RowsAffected();
}
int TXvt_recordset::get_int(const char* field) int TXvt_recordset::get_int(const char* field)
{ {
try try
@ -430,7 +450,6 @@ int TXvt_recordset::get_int(const char* field)
{ {
_codeError = x.ErrNativeCode(); _codeError = x.ErrNativeCode();
_stringError = x.ErrMessage(); _stringError = x.ErrMessage();
return -1; return -1;
} }
} }
@ -498,7 +517,7 @@ real TXvt_recordset::GetReal(const char * field)
return Get(field); return Get(field);
} }
*/ */
const char* TXvt_recordset::getDate(const char * field) const char* TXvt_recordset::get_date(const char * field)
{ {
try try
{ {
@ -543,7 +562,7 @@ char TXvt_recordset::get_char(const char* field)
} }
} }
long TXvt_recordset::getCodeError(bool erase) long TXvt_recordset::get_code_error(bool erase)
{ {
long app = _codeError; long app = _codeError;
if (erase) if (erase)
@ -551,10 +570,17 @@ long TXvt_recordset::getCodeError(bool erase)
return app; return app;
} }
const char* TXvt_recordset::getStringError(bool erase) const char* TXvt_recordset::get_string_error(bool erase)
{ {
const char* app = _stringError; const char* app = _stringError;
if (erase) if (erase)
_stringError = ""; _stringError = "";
return app; return app;
} }
const bool TXvt_recordset::setErrorFreezed()
{
_codeError = ERROR_FREEZED;
_stringError = ERROR_FREEZEDS;
return false;
}

View File

@ -3,19 +3,19 @@
#ifndef __XVTDB_H #ifndef __XVTDB_H
#define __XVTDB_H #define __XVTDB_H
#include <string> #include "xvtdb_errors.h"
#define DBDLL __declspec(dllexport) #if defined(DBDLL_EXPORT)
# define DBDLL __declspec(dllexport)
#else
# define DBDLL __declspec(dllimport)
#endif // DBDLL_EXPORT
#ifndef NOERR
#define NOERR 0
#endif
#define NOT_INITIALIZED -86552
#define ERROR_FREEZED -883
#define SQLAPIV "SQLAPI++ 4.1.5" // Da tenere aggiornato #define SQLAPIV "SQLAPI++ 4.1.5" // Da tenere aggiornato
DBDLL enum TT_driver #define CHECK_FREEZED if (is_freezed()) { return setErrorFreezed(); }
enum TT_driver
{ {
//! DBMS client is not specified //! DBMS client is not specified
TSDB_undefined, TSDB_undefined,
@ -45,17 +45,12 @@ DBDLL enum TT_driver
TSDB_SQLAnywhere TSDB_SQLAnywhere
}; };
DBDLL enum isoLvl { unknown = -1, uncommitted, committed, rr, serializable }; enum isoLvl { unknown = -1, uncommitted, committed, rr, serializable };
#define P_CONN_VOID void * #define P_CONN_VOID void *
#define P_COMM_VOID void * #define P_COMM_VOID void *
/* Esempio parametri da passare con MSSQL: long xvt_rcs_get_items(P_CONN_VOID con, const char* query);
* db = SERVER@DATABASE (NBKDELLI7TOLLAR\MSSQLSERVER14@project_vahlalla)
*/
DBDLL int xvt_create_connection(P_CONN_VOID con, const char* db, const char* user, const char* pass, TT_driver tipoDb);
/****************************************************************************** /******************************************************************************
* TXvt_recordset : DataBase redcordset * * TXvt_recordset : DataBase redcordset *
* Wrapper base di SACommand e SAConnection, classe per l'esecuzione di query * * Wrapper base di SACommand e SAConnection, classe per l'esecuzione di query *
@ -67,15 +62,23 @@ protected:
/**< Recordset */ /**< Recordset */
P_COMM_VOID _recset; P_COMM_VOID _recset;
/**< Oggetto della connessione */ /**< Oggetto della connessione */
P_COMM_VOID _con; P_CONN_VOID _con;
/**< Database */
const char* _db;
/**< Utente */
const char* _usr;
/**< Password */
const char* _psw;
/**< Driver */
TT_driver _drv;
/**< Query */
const char* _query;
/**< Ultima stringa con codice di errore ricevuto */ /**< Ultima stringa con codice di errore ricevuto */
const char* _stringError; const char* _stringError;
/**< Ultimo codice di errore ricevuto */ /**< Ultimo codice di errore ricevuto */
long _codeError; long _codeError;
/**< Numero record corrente */ /**< Numero record corrente */
long _recno; long _recno;
/**< Indica se va disconnessa la classe durante la chiusura */
bool _toDisconnect;
/**< Indica se l'oggetto è bloccato, in tal caso non si possono fare set/exec */ /**< Indica se l'oggetto è bloccato, in tal caso non si possono fare set/exec */
bool _freezed; bool _freezed;
/**< Indica se il cursore è caricato */ /**< Indica se il cursore è caricato */
@ -83,13 +86,15 @@ protected:
const bool checkPermission(); const bool checkPermission();
private:
// Disabilito il copy constructor
TXvt_recordset(const TXvt_recordset& nope);
public: public:
/**< Costruttore, crea un oggetto vuoto, PERICOLOSO!! Ricordarsi di inizializzarlo opportunamente con il metodo connect() e set() */ /**< Costruttore, crea un oggetto vuoto, PERICOLOSO!! Ricordarsi di inizializzarlo opportunamente con il metodo connect() e set() */
TXvt_recordset(); TXvt_recordset();
/**< Costruttore, crea un oggetto dai parametri di connessione passati */ /**< Costruttore, crea un oggetto dai parametri di connessione passati */
TXvt_recordset(const char* db, const char* user, const char* pass, TT_driver tipoDb, const char * query = "", const bool ex = false, const bool freezed = false); TXvt_recordset(const char* db, const char* user, const char* pass, TT_driver tipoDb, const char * query = "", const bool ex = false, const bool freezed = false);
/**< Costruttore, accetta in ingresso una connessione, volendo è anche possibile impostare una query ed eseguirla. Attenzione! Non risponde se la query ha avuto un esito positivo o negativo! */
TXvt_recordset(P_CONN_VOID c, const char * query = "", bool ex = false);
/**< Distruttore */ /**< Distruttore */
~TXvt_recordset(); ~TXvt_recordset();
@ -99,7 +104,13 @@ public:
// Funzioni fondamentali // Funzioni fondamentali
/**< Eseguo la connessione */ /**< Eseguo la connessione
* Esempio parametri da passare con MSSQL:
* db = SERVER@DATABASE (NBKDELLI7TOLLAR\MSSQLSERVER14@project_vahlalla)
* user = Piero
* pass = Angela
* driver = TSDB_MSSQL
*/
int connect(const char* db, const char* user, const char* pass, TT_driver tipoDb); int connect(const char* db, const char* user, const char* pass, TT_driver tipoDb);
/* Mi scollego */ /* Mi scollego */
void disconnect(); void disconnect();
@ -122,9 +133,9 @@ public:
// Getters // Getters
/** Ritorna se la conessione è connessa */ /** Ritorna se la conessione è connessa */
bool isConnect(); const bool isConnect() const;
/**< Ritorna se la connessione è attiva */ /**< Ritorna se la connessione è attiva */
bool isAlive(); const bool isAlive() const;
/** Ritorna la visibilità impostata */ /** Ritorna la visibilità impostata */
int getVisibility(); int getVisibility();
/**< Ritorna se è attivo l'autocommit, true -> attivo, false -> disattivo o sconosciuto */ /**< Ritorna se è attivo l'autocommit, true -> attivo, false -> disattivo o sconosciuto */
@ -137,7 +148,10 @@ public:
const char* getServerV(); const char* getServerV();
/**< Ritorno la versione del Server che sto utilizzando in formato numerico */ /**< Ritorno la versione del Server che sto utilizzando in formato numerico */
long getServerVN(); long getServerVN();
/**< Ritorno se il recordset è carico */
bool isLoaded() const;
/** Ritorno il numero di elementi nella query */
long items();
/************************************************************************************************** /**************************************************************************************************
* Gestione Recordset * * Gestione Recordset *
@ -160,6 +174,8 @@ public:
bool last(); bool last();
/**< Si sposta alla posizione n, in caso di esito negativo valorizza _stringError e _codeError */ /**< Si sposta alla posizione n, in caso di esito negativo valorizza _stringError e _codeError */
bool go(int newPos); bool go(int newPos);
/**< Ritorna il numero di righe affette dall'ultima query */
const int rowsAffected();
// Getters // Getters
/**< Ritorna il valore nel campo (field) in formato (int) */ /**< Ritorna il valore nel campo (field) in formato (int) */
@ -173,7 +189,7 @@ public:
/**< Ritorna il valore nel campo (field) in formato (bool) */ /**< Ritorna il valore nel campo (field) in formato (bool) */
bool get_bool(const char* field); bool get_bool(const char* field);
/**< Ritorna il valore nel campo (field) in formato (const char *)->(DD-MM-YYYY) */ /**< Ritorna il valore nel campo (field) in formato (const char *)->(DD-MM-YYYY) */
const char* getDate(const char* field); const char* get_date(const char* field);
/**< Ritorna il valore nel campo (field) passato in formato (const char *) */ /**< Ritorna il valore nel campo (field) passato in formato (const char *) */
const char* get(const char* field); const char* get(const char* field);
/**< Ritorna il valore nel campo (field) in formato (char) */ /**< Ritorna il valore nel campo (field) in formato (char) */
@ -182,20 +198,29 @@ public:
long pos() const { return _recno; } long pos() const { return _recno; }
// Error Handling // Error Handling
/**< Ritorno l'ultimo codice errore segnalato in formato /int) */ /**< Ritorno l'ultimo codice errore segnalato in formato numerico) */
long getCodeError(bool erase = true); long get_code_error(bool erase = true);
/**< Ritorno l'ultima stringa di errore segnalato in formato (const char *) */ /**< Ritorno l'ultima stringa di errore segnalato in formato (const char *) */
const char* getStringError(bool erase = true); const char* get_string_error(bool erase = true);
//char * getCharPointer(const char * field) { return const_cast<char*>(static_cast<const char*>(recset.Field(field).asString())); } //char * getCharPointer(const char * field) { return const_cast<char*>(static_cast<const char*>(recset.Field(field).asString())); }
// Utilities // Utilities
/**< Controlla se il cursore è bloccato */ /**< Controlla se il cursore è bloccato */
const bool isFreezed() const { return _freezed; } const bool is_freezed() const { return _freezed; }
/**< Congela il cursore */ /**< Congela il cursore */
void freeze() { _freezed = true; } void freeze() { _freezed = true; }
/**< Scongela il cursore */ /**< Scongela il cursore */
void defrost() { _freezed = false; } void defrost() { _freezed = false; }
/* Funzioni tenute per compatibiltà: */
/**< Scongela il cursore */
void unfreeze() { defrost(); }
/**< Ritornano se è congelato o meno, attenzione: i valori di ritorno non sono const!*/
bool frozen() const { return is_freezed(); }
bool not_frozen() const { return !is_freezed(); }
/**< Imposta l'errore di record congelato */
const bool setErrorFreezed();
}; };
#endif #endif

7
src/xvtdb/xvtdb_errors.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#define NOERR 0
#define NOT_INITIALIZED -86552
#define NOT_INITIALIZEDS "ERROR: Recordset not initialized"
#define ERROR_FREEZED -883
#define ERROR_FREEZEDS "ERROR: Recordset on ice"