Patch level : 12.0 no-patch

Files correlati     : tsdb, xvtdb
Commento            : Implementazione TDb_recordset
This commit is contained in:
Simone Palacino 2019-03-19 12:37:55 +01:00
parent ee493c3790
commit 7d64a38c20
3 changed files with 171 additions and 67 deletions

View File

@ -98,7 +98,10 @@ TFieldtypes SSimple_query::sq_get_type_field(const unsigned column) const
void TDB_recordset::reset() void TDB_recordset::reset()
{ {
_current_row = -1; _current_row = -1;
_columns_loaded = false; _is_loaded = false;
_items = 0;
_row.destroy();
_column.destroy();
} }
/* La query può iniziare con la stringa di connessione così fatta: /* La query può iniziare con la stringa di connessione così fatta:
@ -128,11 +131,19 @@ bool TDB_recordset::set(const char* sql)
return false; return false;
real_query << query.sub(pos_EOCon); real_query << query.sub(pos_EOCon);
} }
else if (!_connected) else if (!is_connected())
return false; return false;
else else
real_query << sql; real_query << sql;
// Non sto facendo una select
if(real_query.find("SELECT") == -1 && real_query.find("select") == -1)
{
_sql.cut(0);
reset();
return false;
}
// Serve? // Serve?
if (!_freezed || _sql != sql) if (!_freezed || _sql != sql)
reset(); reset();
@ -141,7 +152,11 @@ bool TDB_recordset::set(const char* sql)
if (_sql.find("SELECT") >= 0 || _sql.find("select") >= 0) if (_sql.find("SELECT") >= 0 || _sql.find("select") >= 0)
find_and_reset_vars(); find_and_reset_vars();
return _rec->sq_set(_sql); bool is_set;
if ((is_set = _rec->sq_set(_sql))) {
unset_loaded();
}
return is_set;
} }
} }
return false; return false;
@ -160,7 +175,7 @@ bool TDB_recordset::set_connection(const char* conn_str) const
int last_pos = pn.find(",", first_pos); int last_pos = pn.find(",", first_pos);
int i; int i;
for (i = 0; last_pos != -1; last_pos = pn.find(",", first_pos + 1), i++) { for (i = 0; last_pos != -1; i++) {
switch (i) switch (i)
{ {
case 0: case 0:
@ -174,17 +189,22 @@ bool TDB_recordset::set_connection(const char* conn_str) const
break; break;
case 3: case 3:
drv = pn.sub(first_pos + 1, last_pos); drv = pn.sub(first_pos + 1, last_pos);
break;
default: default:
last_pos = -1;
break; break;
} }
first_pos = last_pos; first_pos = last_pos;
last_pos = pn.find(",", first_pos + 1);
if( last_pos == -1 )
last_pos = pn.find(")", first_pos + 1);
} }
// Guardo se ho valorizzato almeno i primi 3 elementi della connect // Guardo se ho valorizzato almeno i primi 3 elementi della connect
// Se non valorizzo l'ultimo come default: MSSQL Server // Se non valorizzo l'ultimo come default: MSSQL Server
if (i == 2) if (i == 3)
return connect(srv.ltrim(), usr.ltrim(), pwd.ltrim(), TSDB_MSSQL); return connect(srv.ltrim(), usr.ltrim(), pwd.ltrim(), TSDB_MSSQL);
if(i == 3) if(i == 4)
return connect(srv.ltrim(), usr.ltrim(), pwd.ltrim(), str_to_driver(drv.ltrim())); return connect(srv.ltrim(), usr.ltrim(), pwd.ltrim(), str_to_driver(drv.ltrim()));
return false; return false;
@ -198,7 +218,7 @@ bool TDB_recordset::connect(const char * db, const char * user, const char * pas
TT_driver TDB_recordset::str_to_driver(const char* tipo_db) TT_driver TDB_recordset::str_to_driver(const char* tipo_db)
{ {
if (_stricmp(tipo_db, "") != 0) if (_stricmp(tipo_db, "") == 0)
return TSDB_undefined; return TSDB_undefined;
//! ODBC //! ODBC
if (_stricmp(tipo_db, "ODBC") == 0) if (_stricmp(tipo_db, "ODBC") == 0)
@ -239,6 +259,30 @@ TT_driver TDB_recordset::str_to_driver(const char* tipo_db)
return TSDB_undefined; return TSDB_undefined;
} }
void TDB_recordset::set_loaded()
{
_is_loaded = true;
_items = _rec->sq_items();
_ncolumns = _rec->sq_get_num_fields();
}
void TDB_recordset::unset_loaded()
{
_is_loaded = false;
_items = 0;
_ncolumns = 0;
_current_row = 0;
}
void TDB_recordset::freeze(const bool on)
{
if (on)
_rec->freeze();
else
_rec->defrost();
_freezed = on;
}
bool TDB_recordset::connect(const char* db, const char* user, const char* pass, const char* tipo_db) const bool TDB_recordset::connect(const char* db, const char* user, const char* pass, const char* tipo_db) const
{ {
return _rec->sq_connect(db, user, pass, str_to_driver(tipo_db)) == NOERR; return _rec->sq_connect(db, user, pass, str_to_driver(tipo_db)) == NOERR;
@ -246,21 +290,28 @@ bool TDB_recordset::connect(const char* db, const char* user, const char* pass,
TRecnotype TDB_recordset::items() const TRecnotype TDB_recordset::items() const
{ {
return static_cast<TRecnotype>(_rec->sq_items()); if (_is_loaded)
return _items;
return _rec->sq_items();
} }
bool TDB_recordset::move_to(TRecnotype pos) bool TDB_recordset::move_to(TRecnotype pos)
{ {
const TRecnotype tot = items(); const TRecnotype tot = items();
TRecnotype row = pos; TRecnotype row = pos;
bool ok; bool ok = true;
if (pos < 0) if (pos < 0)
row = 0; row = 0;
if (pos > tot) if (pos > tot)
row = tot; row = tot;
if( (ok = _rec->sq_go(row)) ) if (!_is_loaded) {
if (!_sql.empty() && ((ok = _rec->sq_exec())))
set_loaded();
}
if( ok && ((ok = _rec->sq_go(row))) )
_current_row = pos; _current_row = pos;
return ok; return ok;
@ -268,7 +319,14 @@ bool TDB_recordset::move_to(TRecnotype pos)
bool TDB_recordset::move_next() bool TDB_recordset::move_next()
{ {
if (_rec->sq_next()) bool ok = true;
if (!_is_loaded) {
if (!_sql.empty() && ((ok = _rec->sq_exec())))
set_loaded();
}
if (ok && _rec->sq_next())
{ {
_current_row = _rec->sq_pos(); _current_row = _rec->sq_pos();
return true; return true;
@ -276,31 +334,30 @@ bool TDB_recordset::move_next()
return false; return false;
} }
const TArray TDB_recordset::get_next_row() const TString_array TDB_recordset::get_next_row()
{ {
if (move_next()) if (move_next())
return get_row(); return get_row();
return TArray().destroy(); return TArray().destroy();
} }
const TArray TDB_recordset::get_row(TRecnotype n) const TString_array TDB_recordset::get_row(TRecnotype n)
{ {
bool ok; bool ok = true;
// Get della riga attuale
if(n == -1)
{
n = current_row();
ok = true;
}
else
ok = _rec->sq_is_loaded() && move_to(n); // Non faccio la move se non e` caricato
if (_rec->sq_is_loaded() && ok) // Get della riga attuale
if (n == -1)
n = current_row();
else if (_current_row != n)
ok = move_to(n); // Solo se non sono già su quella riga
if (ok)
{ {
const unsigned ncol = _rec->sq_get_num_fields(); const unsigned ncol = _rec->sq_get_num_fields();
_row.destroy(); _row.destroy();
for (unsigned i = 0; i < ncol; i++) for (unsigned i = 0; i < ncol; i++)
_row.add(_rec->sq_get(i, false)); _row.add(TString(_rec->sq_get(i, false)));
return _row; return _row;
} }
// else // else
@ -315,16 +372,26 @@ void TDB_recordset::requery()
unsigned TDB_recordset::columns() const unsigned TDB_recordset::columns() const
{ {
return _rec->sq_get_num_fields(); if(!_is_loaded)
return _rec->sq_get_num_fields();
return _ncolumns;
} }
const TRecordset_column_info& TDB_recordset::column_info(const unsigned column) const const TRecordset_column_info& TDB_recordset::column_info(const unsigned column) const
{ {
static TRecordset_column_info* info = new TRecordset_column_info; static TRecordset_column_info info;
info->_name = _rec->sq_get_name_field(column); // TString if (_is_loaded)
info->_width = _rec->sq_get_width_field(column); // int {
info->_type = _rec->sq_get_type_field(column); // TFieldtypes info._name = _rec->sq_get_name_field(column); // TString
return *info; info._width = _rec->sq_get_width_field(column); // int
info._type = _rec->sq_get_type_field(column); // TFieldtypes
return info;
}
info._name.cut(0); // TString
info._width = 0; // int
info._type = _alfafld; // TFieldtypes
info._pos = 0;
return info;
} }
const TVariant& TDB_recordset::get(unsigned int column) const const TVariant& TDB_recordset::get(unsigned int column) const
@ -340,6 +407,11 @@ const TVariant& TDB_recordset::get(unsigned int column) const
return field; return field;
} }
bool TDB_recordset::is_connected() const
{
return _rec->sq_is_connect();
}
const TVariant& TDB_recordset::active_connection() const const TVariant& TDB_recordset::active_connection() const
{ {
static TVariant conn = NULL_VARIANT; static TVariant conn = NULL_VARIANT;
@ -349,12 +421,17 @@ const TVariant& TDB_recordset::active_connection() const
return conn; return conn;
} }
const bool TDB_recordset::exec(const char* sql) const bool TDB_recordset::exec(const char* sql)
{ {
return _rec->sq_set_exec(sql); bool exec = false;
if ((exec = _rec->sq_set_exec(sql))) {
_is_loaded = true;
_items = _rec->sq_items();
}
return exec;
} }
const bool TDB_recordset::commit() const bool TDB_recordset::commit() const
{ {
return _rec->sq_commit(); return _rec->sq_commit();
} }
@ -363,8 +440,12 @@ TDB_recordset::TDB_recordset(const char* sql, const bool freezed) : _freezed(fre
{ {
_current_row = -1; _current_row = -1;
_rec = new SSimple_query(); _rec = new SSimple_query();
_rec->sq_set_autocommit(true); //_rec->sq_set_autocommit(true);
_sql.cut(0); _sql.cut(0);
_is_loaded = false;
_items = 0;
_ncolumns = 0;
freeze(freezed);
set(sql); set(sql);
} }

View File

@ -211,37 +211,45 @@ class TDB_recordset : public TRecordset
TString _sql; TString _sql;
TString _dsn, _usr, _pwd, _drv; TString _dsn, _usr, _pwd, _drv;
bool _freezed{}, _columns_loaded{}, _auto_commit{}, _connected{}; bool _freezed;
TRecnotype _current_row; TRecnotype _current_row;
TArray _row, _column; TString_array _row, _column;
bool _is_loaded;
TRecnotype _items;
unsigned _ncolumns;
protected: protected:
void reset();
bool set(const char* sql);
// Parsa la stringa di connessione contenuta nella query // Parsa la stringa di connessione contenuta nella query
bool set_connection(const char * conn_str) const; bool set_connection(const char * conn_str) const;
bool connect(const char * db, const char * user, const char * pass, const TT_driver tipo_db) const; bool connect(const char * db, const char * user, const char * pass, const TT_driver tipo_db) const;
bool connect(const char * db, const char * user, const char * pass, const char * tipo_db) const; bool connect(const char * db, const char * user, const char * pass, const char * tipo_db) const;
static TT_driver str_to_driver(const char* tipo_db); static TT_driver str_to_driver(const char* tipo_db);
void set_loaded();
void unset_loaded();
public: public:
TRecnotype items() const override; // Pure void freeze(const bool on = true);;
bool move_to(TRecnotype pos) override; // Pure void reset();
bool move_next() override; bool set(const char* sql);
TRecnotype current_row() const override { return _current_row; } // Pure bool move_to(TRecnotype pos) override; // Pure
const TArray get_next_row(); bool move_next() override;
void requery() override; // da impl. Pure
bool is_connected() const;
unsigned columns() const override; // Pure
TRecnotype items() const override; // Pure
TRecnotype current_row() const override { return _current_row; } // Pure
// Con il valore di default viene restituita la riga alla pos. attuale // Con il valore di default viene restituita la riga alla pos. attuale
const TArray get_row(TRecnotype n = -1); const TString_array get_row(TRecnotype n = -1);
void requery() override; // da impl. Pure const TString_array get_next_row();
const TString& query_text() const override { return _sql; } const TString& query_text() const override { return _sql; }
unsigned int columns() const override; // Pure
const TRecordset_column_info& column_info(unsigned int column) const override; // Pure
const TVariant& get(unsigned int column) const override; // Pure const TVariant& get(unsigned int column) const override; // Pure
const TRecordset_column_info& column_info(unsigned int column) const override; // Pure
// Ritorna la connessione attuale
const TVariant& active_connection() const; const TVariant& active_connection() const;
const bool exec(const char* sql) const; bool exec(const char* sql);
const bool commit() const; bool commit() const;
TDB_recordset(const char * sql, bool freezed = false); TDB_recordset(const char * sql, bool freezed = false);
~TDB_recordset(); ~TDB_recordset();

View File

@ -195,6 +195,10 @@ int TXvt_recordset::connect(const char* db, const char* user, const char* pass,
_CON(_con)->Connect(dbAddress, usr, psw, dbDriver); _CON(_con)->Connect(dbAddress, usr, psw, dbDriver);
// Imposto che non si possono vedere i record non committati // Imposto che non si possono vedere i record non committati
_CON(_con)->setIsolationLevel(SA_ReadCommitted); _CON(_con)->setIsolationLevel(SA_ReadCommitted);
_CPY_STR(db, _db);
_CPY_STR(user, _usr);
_CPY_STR(pass, _psw);
_drv = tipo_db;
return NOERR; return NOERR;
} }
catch (SAException &x) catch (SAException &x)
@ -335,21 +339,25 @@ long TXvt_recordset::items()
{ {
// Per non creare casini utilizzo una funzione apposita che mi ritorna il numero // Per non creare casini utilizzo una funzione apposita che mi ritorna il numero
P_CONN_VOID conn = new SAConnection; P_CONN_VOID conn = new SAConnection;
char q[500]; SAString q;
long items; long items = -1;
// Connetto la nuova istanza // Connetto la nuova istanza
_CON(conn)->Connect(_db, _usr, _psw, (SAClient_t)_drv); try
{
// Controllo sia tutto a posto _CON(conn)->Connect(_db, _usr, _psw, (SAClient_t)_drv);
items = xvt_rcs_get_items(conn, _query);
// Creo la query if (conn != _con)
strcat_s(q, sizeof(q), "SELECT COUNT(*) "); delete conn;
strcat_s(q, sizeof(q), (strstr(_query, "FROM") != NULL ? strstr(_query, "FROM") : strstr(_query, "from"))); // Serve? }
catch(SAException &x)
items = xvt_rcs_get_items(conn, q); {
if(conn != _con) _code_error = x.ErrNativeCode();
delete conn; _GET_ERROR(x.ErrMessage(), _string_error);
_GET_ERROR(x.ErrText(), _string_error_full_text);
return false;
}
return items; return items;
} }
@ -357,8 +365,9 @@ long xvt_rcs_get_items(P_CONN_VOID con, const char* query)
{ {
P_COMM_VOID rcs = new SACommand(_CON(con)); P_COMM_VOID rcs = new SACommand(_CON(con));
_RCS(rcs)->setCommandText(query); _RCS(rcs)->setCommandText(query);
_RCS(rcs)->Execute();
long r = 0; long r = 0;
for(bool ok = _RCS(rcs)->FetchFirst(); ok; ok = _RCS(rcs)->FetchNext()) while(_RCS(rcs)->FetchNext())
r++; r++;
delete rcs; delete rcs;
return r; return r;
@ -374,6 +383,7 @@ bool TXvt_recordset::set(const char* query)
{ {
_query = query; _query = query;
_RCS(_recset)->setCommandText(query); _RCS(_recset)->setCommandText(query);
_loaded = false;
} }
catch (SAException &x) catch (SAException &x)
{ {
@ -392,6 +402,7 @@ bool TXvt_recordset::exec(bool autoF)
try try
{ {
_RCS(_recset)->Execute(); _RCS(_recset)->Execute();
_loaded = true;
_recno = -1; _recno = -1;
// Se trovo almeno un "select" faccio l'autofetch // Se trovo almeno un "select" faccio l'autofetch
SAString s = _RCS(_recset)->CommandText(); s.MakeUpper(); SAString s = _RCS(_recset)->CommandText(); s.MakeUpper();
@ -653,7 +664,9 @@ const char* TXvt_recordset::get(unsigned int field)
{ {
try try
{ {
return _RCS(_recset)->Field(field).asString(); static SAString str;
str = _RCS(_recset)->Field(field + 1).asString();
return str;
} }
catch(SAException &x) catch(SAException &x)
{ {
@ -717,6 +730,8 @@ const char* TXvt_recordset::get_type_field(const unsigned column) const
return "dtNumeric"; return "dtNumeric";
case SA_dtDateTime: case SA_dtDateTime:
return "dtDateTime"; return "dtDateTime";
case SA_dtString:
return "dtString";
case SA_dtInterval: case SA_dtInterval:
return "dtString"; return "dtString";
case SA_dtBytes: case SA_dtBytes: