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,46 +1,13 @@
#include "xvtdb.h"
#include <sqlapi.h>
#include <string> // sprintf_s
#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 *
* TXvt_recordset *
* 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)
: _db(db), _usr(user), _psw(pass), _drv(tipoDb)
{
_con = new SAConnection;
if(xvt_create_connection(_con, db, user, pass, tipoDb) == NOERR)
if(connect(db, user, pass, tipoDb) == NOERR)
{
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()
{
try
{
if(_toDisconnect && _CON(_con)->isConnected())
if(_CON(_con)->isConnected())
_CON(_con)->Disconnect();
if(_con != NULL)
delete _con;
if(_recset != NULL)
delete _recset;
}
catch(...){}
catch (...) {}
}
/* PRIVATE FUNCTIONS **************************************************************************************************/
const bool TXvt_recordset::checkPermission()
{
bool err = isFreezed();
if(err)
{
_codeError = ERROR_FREEZED;
_stringError = "Il recordset è bloccato";
}
bool err = is_freezed();
if (err)
setErrorFreezed();
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)
{
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()
@ -172,6 +145,7 @@ void TXvt_recordset::disconnect()
bool TXvt_recordset::commit(bool autoRoll)
{
CHECK_FREEZED
try
{
_CON(_con)->Commit();
@ -191,6 +165,7 @@ bool TXvt_recordset::commit(bool autoRoll)
bool TXvt_recordset::rollback()
{
CHECK_FREEZED
try
{
_CON(_con)->Rollback();
@ -232,11 +207,11 @@ void TXvt_recordset::setVisibility(isoLvl vis)
_CON(_con)->setIsolationLevel((SAIsolationLevel_t)vis);
}
bool TXvt_recordset::isConnect()
const bool TXvt_recordset::isConnect() const
{
return _CON(_con)->isConnected();
}
bool TXvt_recordset::isAlive()
const bool TXvt_recordset::isAlive() const
{
return _CON(_con)->isAlive();
}
@ -265,14 +240,53 @@ long TXvt_recordset::getServerVN()
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 *
**************************************************************************************************/
bool TXvt_recordset::set(const char* query)
{
CHECK_FREEZED
try
{
_query = query;
_RCS(_recset)->setCommandText(query);
}
catch (SAException &x)
@ -286,6 +300,7 @@ bool TXvt_recordset::set(const char* query)
bool TXvt_recordset::exec(bool autoF)
{
CHECK_FREEZED
try
{
_RCS(_recset)->Execute();
@ -420,6 +435,11 @@ bool TXvt_recordset::go(int newPos)
return result;
}
const int TXvt_recordset::rowsAffected()
{
return _RCS(_recset)->RowsAffected();
}
int TXvt_recordset::get_int(const char* field)
{
try
@ -430,7 +450,6 @@ int TXvt_recordset::get_int(const char* field)
{
_codeError = x.ErrNativeCode();
_stringError = x.ErrMessage();
return -1;
}
}
@ -498,7 +517,7 @@ real TXvt_recordset::GetReal(const char * field)
return Get(field);
}
*/
const char* TXvt_recordset::getDate(const char * field)
const char* TXvt_recordset::get_date(const char * field)
{
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;
if (erase)
@ -551,10 +570,17 @@ long TXvt_recordset::getCodeError(bool erase)
return app;
}
const char* TXvt_recordset::getStringError(bool erase)
const char* TXvt_recordset::get_string_error(bool erase)
{
const char* app = _stringError;
if (erase)
_stringError = "";
return app;
}
}
const bool TXvt_recordset::setErrorFreezed()
{
_codeError = ERROR_FREEZED;
_stringError = ERROR_FREEZEDS;
return false;
}

View File

@ -3,19 +3,19 @@
#ifndef __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
DBDLL enum TT_driver
#define CHECK_FREEZED if (is_freezed()) { return setErrorFreezed(); }
enum TT_driver
{
//! DBMS client is not specified
TSDB_undefined,
@ -45,17 +45,12 @@ DBDLL enum TT_driver
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_COMM_VOID void *
/* Esempio parametri da passare con MSSQL:
* 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);
long xvt_rcs_get_items(P_CONN_VOID con, const char* query);
/******************************************************************************
* TXvt_recordset : DataBase redcordset *
* Wrapper base di SACommand e SAConnection, classe per l'esecuzione di query *
@ -67,15 +62,23 @@ protected:
/**< Recordset */
P_COMM_VOID _recset;
/**< 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 */
const char* _stringError;
/**< Ultimo codice di errore ricevuto */
long _codeError;
/**< Numero record corrente */
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 */
bool _freezed;
/**< Indica se il cursore è caricato */
@ -83,13 +86,15 @@ protected:
const bool checkPermission();
private:
// Disabilito il copy constructor
TXvt_recordset(const TXvt_recordset& nope);
public:
/**< Costruttore, crea un oggetto vuoto, PERICOLOSO!! Ricordarsi di inizializzarlo opportunamente con il metodo connect() e set() */
TXvt_recordset();
/**< 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);
/**< 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 */
~TXvt_recordset();
@ -99,7 +104,13 @@ public:
// 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);
/* Mi scollego */
void disconnect();
@ -122,9 +133,9 @@ public:
// Getters
/** Ritorna se la conessione è connessa */
bool isConnect();
const bool isConnect() const;
/**< Ritorna se la connessione è attiva */
bool isAlive();
const bool isAlive() const;
/** Ritorna la visibilità impostata */
int getVisibility();
/**< Ritorna se è attivo l'autocommit, true -> attivo, false -> disattivo o sconosciuto */
@ -137,7 +148,10 @@ public:
const char* getServerV();
/**< Ritorno la versione del Server che sto utilizzando in formato numerico */
long getServerVN();
/**< Ritorno se il recordset è carico */
bool isLoaded() const;
/** Ritorno il numero di elementi nella query */
long items();
/**************************************************************************************************
* Gestione Recordset *
@ -160,6 +174,8 @@ public:
bool last();
/**< Si sposta alla posizione n, in caso di esito negativo valorizza _stringError e _codeError */
bool go(int newPos);
/**< Ritorna il numero di righe affette dall'ultima query */
const int rowsAffected();
// Getters
/**< Ritorna il valore nel campo (field) in formato (int) */
@ -173,7 +189,7 @@ public:
/**< Ritorna il valore nel campo (field) in formato (bool) */
bool get_bool(const char* field);
/**< 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 *) */
const char* get(const char* field);
/**< Ritorna il valore nel campo (field) in formato (char) */
@ -182,20 +198,29 @@ public:
long pos() const { return _recno; }
// Error Handling
/**< Ritorno l'ultimo codice errore segnalato in formato /int) */
long getCodeError(bool erase = true);
/**< Ritorno l'ultimo codice errore segnalato in formato numerico) */
long get_code_error(bool erase = true);
/**< 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())); }
// Utilities
/**< Controlla se il cursore è bloccato */
const bool isFreezed() const { return _freezed; }
const bool is_freezed() const { return _freezed; }
/**< Congela il cursore */
void freeze() { _freezed = true; }
/**< Scongela il cursore */
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

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"