Patch level : 12.0 no-patch
Files correlati : include Commento : Spostato TDB_recordset in odbcrset
This commit is contained in:
parent
d1d737041b
commit
de20a9ad8f
@ -724,6 +724,387 @@ TODBC_recordset::TODBC_recordset(const char* sql, const bool freezed) : _freezed
|
|||||||
TODBC_recordset::~TODBC_recordset()
|
TODBC_recordset::~TODBC_recordset()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// TDB_recordset
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void TDB_recordset::reset()
|
||||||
|
{
|
||||||
|
_current_row = -1;
|
||||||
|
_is_loaded = false;
|
||||||
|
_items = 0;
|
||||||
|
_row.destroy();
|
||||||
|
_column.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* La query può iniziare con la stringa di connessione così fatta:
|
||||||
|
* CONNECT(server, user, psw, driver = "MSSQL") il driver può essere omesso.
|
||||||
|
* Se c'è la estraggo, setto la connessione e prendo la vera query.
|
||||||
|
* Se no setto direttamente la query.
|
||||||
|
* Ritorno false se non mi sono mai connesso a niente e non passo
|
||||||
|
* la stringa di connessione.
|
||||||
|
*/
|
||||||
|
bool TDB_recordset::set(const char* sql)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
TString real_query = "";
|
||||||
|
// Posso modificare oppure non posso ma _sql è vuota
|
||||||
|
if (!_freezed || _sql.empty())
|
||||||
|
{
|
||||||
|
if (_sql.empty() || !_freezed && !_sql.empty())
|
||||||
|
{
|
||||||
|
// Guardo se la query inizia con la stringa di connessione
|
||||||
|
if (TString(sql).starts_with("CONNECT(", true))
|
||||||
|
{
|
||||||
|
TString query(sql);
|
||||||
|
int pos_EOCon = query.find(')'); // End Of Conn
|
||||||
|
const TString& conn_str = query.sub(0, ++pos_EOCon);
|
||||||
|
ok = set_connection(conn_str);
|
||||||
|
if (!ok)
|
||||||
|
return false;
|
||||||
|
real_query << query.sub(pos_EOCon);
|
||||||
|
}
|
||||||
|
else if (!is_connected())
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
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?
|
||||||
|
if (!_freezed || _sql != sql)
|
||||||
|
reset();
|
||||||
|
|
||||||
|
_sql.cut(0) << real_query;
|
||||||
|
if (_sql.find("SELECT") >= 0 || _sql.find("select") >= 0)
|
||||||
|
find_and_reset_vars();
|
||||||
|
|
||||||
|
bool is_set;
|
||||||
|
if ((is_set = _rec->sq_set(_sql))) {
|
||||||
|
unset_loaded();
|
||||||
|
}
|
||||||
|
return is_set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parso la stringa di connessione ed estraggo i dati.
|
||||||
|
* Se il numero di dati è sufficiente eseguo la connessione.
|
||||||
|
* Ritorno false se non riesco a connettermi o il numero di dati è sbagliato
|
||||||
|
*/
|
||||||
|
bool TDB_recordset::set_connection(const char* conn_str) const
|
||||||
|
{
|
||||||
|
TString pn(conn_str);
|
||||||
|
TString srv = "", usr = "", pwd = "", drv = "";
|
||||||
|
|
||||||
|
int first_pos = pn.find("(", 0);
|
||||||
|
int last_pos = pn.find(",", first_pos);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; last_pos != -1; i++) {
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
srv = pn.sub(first_pos + 1, last_pos);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
usr = pn.sub(first_pos + 1, last_pos);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
pwd = pn.sub(first_pos + 1, last_pos);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
drv = pn.sub(first_pos + 1, last_pos);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
last_pos = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
// Se non valorizzo l'ultimo come default: MSSQL Server
|
||||||
|
if (i == 3)
|
||||||
|
return connect(srv.ltrim(), usr.ltrim(), pwd.ltrim(), TSDB_MSSQL);
|
||||||
|
if (i == 4)
|
||||||
|
return connect(srv.ltrim(), usr.ltrim(), pwd.ltrim(), str_to_driver(drv.ltrim()));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ritorna true se si connette
|
||||||
|
bool TDB_recordset::connect(const char * db, const char * user, const char * pass, const TT_driver tipo_db) const
|
||||||
|
{
|
||||||
|
const bool connected = _rec->sq_connect(db, user, pass, tipo_db) == NOERR;
|
||||||
|
// Nel dubbio setto entrambi
|
||||||
|
_rec->sq_set_con_option("UseDynamicCursor", "True");
|
||||||
|
_rec->sq_set_con_option("Scrollable", "True");
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
TT_driver TDB_recordset::str_to_driver(const char* tipo_db)
|
||||||
|
{
|
||||||
|
if (_stricmp(tipo_db, "") == 0)
|
||||||
|
return TSDB_undefined;
|
||||||
|
//! ODBC
|
||||||
|
if (_stricmp(tipo_db, "ODBC") == 0)
|
||||||
|
return TSDB_ODBC;
|
||||||
|
//! Oracle
|
||||||
|
if (_stricmp(tipo_db, "Oracle") == 0)
|
||||||
|
return TSDB_Oracle;
|
||||||
|
//! Microsoft SQL Server
|
||||||
|
if (_stricmp(tipo_db, "MSSQL") == 0)
|
||||||
|
return TSDB_MSSQL;
|
||||||
|
//! InterBase or Firebird
|
||||||
|
if (_stricmp(tipo_db, "InterBase") == 0)
|
||||||
|
return TSDB_InterBase;
|
||||||
|
//! SQLBase
|
||||||
|
if (_stricmp(tipo_db, "SQLBase") == 0)
|
||||||
|
return TSDB_SQLBase;
|
||||||
|
//! IBM DB2
|
||||||
|
if (_stricmp(tipo_db, "DB2") == 0)
|
||||||
|
return TSDB_DB2;
|
||||||
|
//! Informix
|
||||||
|
if (_stricmp(tipo_db, "Informix") == 0)
|
||||||
|
return TSDB_Informix;
|
||||||
|
//! Sybase ASE
|
||||||
|
if (_stricmp(tipo_db, "Sybase") == 0)
|
||||||
|
return TSDB_Sybase;
|
||||||
|
//! MySQL
|
||||||
|
if (_stricmp(tipo_db, "MySQL") == 0)
|
||||||
|
return TSDB_MySQL;
|
||||||
|
//! PostgreSQL
|
||||||
|
if (_stricmp(tipo_db, "PostgreSQL") == 0)
|
||||||
|
return TSDB_PostgreSQL;
|
||||||
|
//! SQLite
|
||||||
|
if (_stricmp(tipo_db, "SQLite") == 0)
|
||||||
|
return TSDB_SQLite;
|
||||||
|
//! SQL Anywere
|
||||||
|
if (_stricmp(tipo_db, "SQLAnywhere") == 0)
|
||||||
|
return TSDB_SQLAnywhere;
|
||||||
|
return TSDB_undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TDB_recordset::set_loaded()
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
if (!_sql.empty() && _rec->sq_exec(false))
|
||||||
|
{
|
||||||
|
ok = _is_loaded = true;
|
||||||
|
_items = _rec->sq_items();
|
||||||
|
_ncolumns = _rec->sq_get_num_fields();
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
return _rec->sq_connect(db, user, pass, str_to_driver(tipo_db)) == NOERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRecnotype TDB_recordset::items() const
|
||||||
|
{
|
||||||
|
if (_is_loaded)
|
||||||
|
return _items;
|
||||||
|
return _rec->sq_items();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TDB_recordset::move_to(TRecnotype pos)
|
||||||
|
{
|
||||||
|
const TRecnotype tot = items();
|
||||||
|
TRecnotype row = pos;
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
if (pos < 0)
|
||||||
|
row = 0;
|
||||||
|
if (pos > tot)
|
||||||
|
row = tot;
|
||||||
|
|
||||||
|
if (!_is_loaded)
|
||||||
|
ok = set_loaded();
|
||||||
|
|
||||||
|
if (ok && ((ok = _rec->sq_go(row))))
|
||||||
|
_current_row = pos;
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TDB_recordset::move_next()
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
if (!_is_loaded)
|
||||||
|
ok = set_loaded();
|
||||||
|
|
||||||
|
if (ok && _rec->sq_next())
|
||||||
|
{
|
||||||
|
_current_row = _rec->sq_pos();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TString_array TDB_recordset::get_next_row()
|
||||||
|
{
|
||||||
|
if (move_next())
|
||||||
|
return get_row();
|
||||||
|
return TString_array();
|
||||||
|
}
|
||||||
|
|
||||||
|
const TString_array TDB_recordset::get_row(TRecnotype n)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
_row.destroy();
|
||||||
|
for (unsigned i = 0; i < ncol; i++)
|
||||||
|
_row.add(TString(_rec->sq_get(i, false)));
|
||||||
|
return _row;
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
_row.destroy();
|
||||||
|
return _row;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDB_recordset::requery()
|
||||||
|
{
|
||||||
|
_items = 0;
|
||||||
|
_current_row = -1;
|
||||||
|
_row.destroy();
|
||||||
|
_column.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned TDB_recordset::columns() const
|
||||||
|
{
|
||||||
|
if (!_is_loaded)
|
||||||
|
{
|
||||||
|
TDB_recordset* my_self = const_cast<TDB_recordset*>(this);
|
||||||
|
my_self->set_loaded();
|
||||||
|
}
|
||||||
|
return _ncolumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TRecordset_column_info& TDB_recordset::column_info(const unsigned column) const
|
||||||
|
{
|
||||||
|
static TRecordset_column_info info;
|
||||||
|
if (_is_loaded)
|
||||||
|
{
|
||||||
|
info._name = _rec->sq_get_name_field(column); // TString
|
||||||
|
info._width = _rec->sq_get_width_field(column); // int
|
||||||
|
info._type = _rec->sq_get_type_field(column); // TFieldtypes
|
||||||
|
info._pos = column;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
static TVariant field = NULL_VARIANT;
|
||||||
|
static unsigned int last_get = 0;
|
||||||
|
if (!_freezed || column != last_get || field == NULL_VARIANT)
|
||||||
|
{
|
||||||
|
last_get = column;
|
||||||
|
field = _rec->sq_get(column);
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TVariant& TDB_recordset::get(const char* name) const
|
||||||
|
{
|
||||||
|
return TRecordset::get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TDB_recordset::is_connected() const
|
||||||
|
{
|
||||||
|
return _rec->sq_is_connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
const TVariant& TDB_recordset::active_connection() const
|
||||||
|
{
|
||||||
|
static TVariant conn = NULL_VARIANT;
|
||||||
|
conn.add(_dsn);
|
||||||
|
conn.add(_usr);
|
||||||
|
conn.add(_drv);
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TDB_recordset::exec(const char* sql)
|
||||||
|
{
|
||||||
|
bool exec = false;
|
||||||
|
if ((exec = _rec->sq_set_exec(sql))) {
|
||||||
|
_is_loaded = true;
|
||||||
|
_items = _rec->sq_items();
|
||||||
|
}
|
||||||
|
return exec;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TDB_recordset::commit() const
|
||||||
|
{
|
||||||
|
return _rec->sq_commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
TDB_recordset::TDB_recordset(const char* sql, const bool freezed) : _freezed(freezed)
|
||||||
|
{
|
||||||
|
_current_row = -1;
|
||||||
|
_rec = new SSimple_query();
|
||||||
|
//_rec->sq_set_autocommit(true);
|
||||||
|
_sql.cut(0);
|
||||||
|
_is_loaded = false;
|
||||||
|
_items = 0;
|
||||||
|
_ncolumns = 0;
|
||||||
|
freeze(freezed);
|
||||||
|
set(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
TDB_recordset::~TDB_recordset()
|
||||||
|
{
|
||||||
|
delete _rec;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
// Creazione "intelligente" del recordset appropriato in base alla query
|
// Creazione "intelligente" del recordset appropriato in base alla query
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
#include <recset.h>
|
#include <recset.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __TSDB_H
|
||||||
|
#include <tsdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
enum TODBC_driver {
|
enum TODBC_driver {
|
||||||
ODBC_generic,
|
ODBC_generic,
|
||||||
ODBC_mssql,
|
ODBC_mssql,
|
||||||
@ -72,4 +76,55 @@ public:
|
|||||||
virtual ~TODBC_recordset();
|
virtual ~TODBC_recordset();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TDB_recordset : public TRecordset
|
||||||
|
{
|
||||||
|
SSimple_query * _rec;
|
||||||
|
TString _sql;
|
||||||
|
TString _dsn, _usr, _pwd, _drv;
|
||||||
|
|
||||||
|
bool _freezed;
|
||||||
|
TRecnotype _current_row;
|
||||||
|
TString_array _row, _column;
|
||||||
|
bool _is_loaded;
|
||||||
|
TRecnotype _items;
|
||||||
|
unsigned _ncolumns;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Parsa la stringa di connessione contenuta nella query
|
||||||
|
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 char * tipo_db) const;
|
||||||
|
static TT_driver str_to_driver(const char* tipo_db);
|
||||||
|
bool set_loaded();
|
||||||
|
void unset_loaded();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void freeze(const bool on = true);
|
||||||
|
void reset();
|
||||||
|
bool set(const char* sql);
|
||||||
|
bool move_to(TRecnotype pos) override; // Pure
|
||||||
|
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
|
||||||
|
const TString_array get_row(TRecnotype n = -1);
|
||||||
|
const TString_array get_next_row();
|
||||||
|
const TString& query_text() const override { return _sql; }
|
||||||
|
const TString& driver_version() const override { return _rec->sq_get_client_v(); };
|
||||||
|
const TVariant& get(unsigned int column) const override; // Pure
|
||||||
|
const TVariant& get(const char* name) const override; // Pure
|
||||||
|
const TRecordset_column_info& column_info(unsigned int column) const override; // Pure
|
||||||
|
|
||||||
|
// Ritorna la connessione attuale
|
||||||
|
const TVariant& active_connection() const;
|
||||||
|
bool exec(const char* sql);
|
||||||
|
bool commit() const;
|
||||||
|
|
||||||
|
TDB_recordset(const char * sql, bool freezed = false);
|
||||||
|
~TDB_recordset();
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -107,380 +107,3 @@ const char* SSimple_query::sq_get_token_text_error(const int token, const bool e
|
|||||||
TToken_string errors(sq_get_text_error(erase), '\n');
|
TToken_string errors(sq_get_text_error(erase), '\n');
|
||||||
return errors.get(token);
|
return errors.get(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TDB_recordset::reset()
|
|
||||||
{
|
|
||||||
_current_row = -1;
|
|
||||||
_is_loaded = false;
|
|
||||||
_items = 0;
|
|
||||||
_row.destroy();
|
|
||||||
_column.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* La query può iniziare con la stringa di connessione così fatta:
|
|
||||||
* CONNECT(server, user, psw, driver = "MSSQL") il driver può essere omesso.
|
|
||||||
* Se c'è la estraggo, setto la connessione e prendo la vera query.
|
|
||||||
* Se no setto direttamente la query.
|
|
||||||
* Ritorno false se non mi sono mai connesso a niente e non passo
|
|
||||||
* la stringa di connessione.
|
|
||||||
*/
|
|
||||||
bool TDB_recordset::set(const char* sql)
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
TString real_query = "";
|
|
||||||
// Posso modificare oppure non posso ma _sql è vuota
|
|
||||||
if(!_freezed || _sql.empty())
|
|
||||||
{
|
|
||||||
if (_sql.empty() || !_freezed && !_sql.empty())
|
|
||||||
{
|
|
||||||
// Guardo se la query inizia con la stringa di connessione
|
|
||||||
if (TString(sql).starts_with("CONNECT(", true))
|
|
||||||
{
|
|
||||||
TString query(sql);
|
|
||||||
int pos_EOCon = query.find(')'); // End Of Conn
|
|
||||||
const TString& conn_str = query.sub(0, ++pos_EOCon);
|
|
||||||
ok = set_connection(conn_str);
|
|
||||||
if (!ok)
|
|
||||||
return false;
|
|
||||||
real_query << query.sub(pos_EOCon);
|
|
||||||
}
|
|
||||||
else if (!is_connected())
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
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?
|
|
||||||
if (!_freezed || _sql != sql)
|
|
||||||
reset();
|
|
||||||
|
|
||||||
_sql.cut(0) << real_query;
|
|
||||||
if (_sql.find("SELECT") >= 0 || _sql.find("select") >= 0)
|
|
||||||
find_and_reset_vars();
|
|
||||||
|
|
||||||
bool is_set;
|
|
||||||
if ((is_set = _rec->sq_set(_sql))) {
|
|
||||||
unset_loaded();
|
|
||||||
}
|
|
||||||
return is_set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parso la stringa di connessione ed estraggo i dati.
|
|
||||||
* Se il numero di dati è sufficiente eseguo la connessione.
|
|
||||||
* Ritorno false se non riesco a connettermi o il numero di dati è sbagliato
|
|
||||||
*/
|
|
||||||
bool TDB_recordset::set_connection(const char* conn_str) const
|
|
||||||
{
|
|
||||||
TString pn(conn_str);
|
|
||||||
TString srv = "", usr = "", pwd = "", drv = "";
|
|
||||||
|
|
||||||
int first_pos = pn.find("(", 0);
|
|
||||||
int last_pos = pn.find(",", first_pos);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; last_pos != -1; i++) {
|
|
||||||
switch (i)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
srv = pn.sub(first_pos + 1, last_pos);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
usr = pn.sub(first_pos + 1, last_pos);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
pwd = pn.sub(first_pos + 1, last_pos);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
drv = pn.sub(first_pos + 1, last_pos);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
last_pos = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
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
|
|
||||||
// Se non valorizzo l'ultimo come default: MSSQL Server
|
|
||||||
if (i == 3)
|
|
||||||
return connect(srv.ltrim(), usr.ltrim(), pwd.ltrim(), TSDB_MSSQL);
|
|
||||||
if(i == 4)
|
|
||||||
return connect(srv.ltrim(), usr.ltrim(), pwd.ltrim(), str_to_driver(drv.ltrim()));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ritorna true se si connette
|
|
||||||
bool TDB_recordset::connect(const char * db, const char * user, const char * pass, const TT_driver tipo_db) const
|
|
||||||
{
|
|
||||||
const bool connected = _rec->sq_connect(db, user, pass, tipo_db) == NOERR;
|
|
||||||
// Nel dubbio setto entrambi
|
|
||||||
_rec->sq_set_con_option("UseDynamicCursor", "True");
|
|
||||||
_rec->sq_set_con_option("Scrollable", "True");
|
|
||||||
return connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
TT_driver TDB_recordset::str_to_driver(const char* tipo_db)
|
|
||||||
{
|
|
||||||
if (_stricmp(tipo_db, "") == 0)
|
|
||||||
return TSDB_undefined;
|
|
||||||
//! ODBC
|
|
||||||
if (_stricmp(tipo_db, "ODBC") == 0)
|
|
||||||
return TSDB_ODBC;
|
|
||||||
//! Oracle
|
|
||||||
if (_stricmp(tipo_db, "Oracle") == 0)
|
|
||||||
return TSDB_Oracle;
|
|
||||||
//! Microsoft SQL Server
|
|
||||||
if (_stricmp(tipo_db, "MSSQL") == 0)
|
|
||||||
return TSDB_MSSQL;
|
|
||||||
//! InterBase or Firebird
|
|
||||||
if (_stricmp(tipo_db, "InterBase") == 0)
|
|
||||||
return TSDB_InterBase;
|
|
||||||
//! SQLBase
|
|
||||||
if (_stricmp(tipo_db, "SQLBase") == 0)
|
|
||||||
return TSDB_SQLBase;
|
|
||||||
//! IBM DB2
|
|
||||||
if (_stricmp(tipo_db, "DB2") == 0)
|
|
||||||
return TSDB_DB2;
|
|
||||||
//! Informix
|
|
||||||
if (_stricmp(tipo_db, "Informix") == 0)
|
|
||||||
return TSDB_Informix;
|
|
||||||
//! Sybase ASE
|
|
||||||
if (_stricmp(tipo_db, "Sybase") == 0)
|
|
||||||
return TSDB_Sybase;
|
|
||||||
//! MySQL
|
|
||||||
if (_stricmp(tipo_db, "MySQL") == 0)
|
|
||||||
return TSDB_MySQL;
|
|
||||||
//! PostgreSQL
|
|
||||||
if (_stricmp(tipo_db, "PostgreSQL") == 0)
|
|
||||||
return TSDB_PostgreSQL;
|
|
||||||
//! SQLite
|
|
||||||
if (_stricmp(tipo_db, "SQLite") == 0)
|
|
||||||
return TSDB_SQLite;
|
|
||||||
//! SQL Anywere
|
|
||||||
if (_stricmp(tipo_db, "SQLAnywhere") == 0)
|
|
||||||
return TSDB_SQLAnywhere;
|
|
||||||
return TSDB_undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TDB_recordset::set_loaded()
|
|
||||||
{
|
|
||||||
bool ok = false;
|
|
||||||
if (!_sql.empty() && _rec->sq_exec(false))
|
|
||||||
{
|
|
||||||
ok = _is_loaded = true;
|
|
||||||
_items = _rec->sq_items();
|
|
||||||
_ncolumns = _rec->sq_get_num_fields();
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
return _rec->sq_connect(db, user, pass, str_to_driver(tipo_db)) == NOERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRecnotype TDB_recordset::items() const
|
|
||||||
{
|
|
||||||
if (_is_loaded)
|
|
||||||
return _items;
|
|
||||||
return _rec->sq_items();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TDB_recordset::move_to(TRecnotype pos)
|
|
||||||
{
|
|
||||||
const TRecnotype tot = items();
|
|
||||||
TRecnotype row = pos;
|
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
if (pos < 0)
|
|
||||||
row = 0;
|
|
||||||
if (pos > tot)
|
|
||||||
row = tot;
|
|
||||||
|
|
||||||
if (!_is_loaded)
|
|
||||||
ok = set_loaded();
|
|
||||||
|
|
||||||
if( ok && ((ok = _rec->sq_go(row))) )
|
|
||||||
_current_row = pos;
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TDB_recordset::move_next()
|
|
||||||
{
|
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
if (!_is_loaded)
|
|
||||||
ok = set_loaded();
|
|
||||||
|
|
||||||
if (ok && _rec->sq_next())
|
|
||||||
{
|
|
||||||
_current_row = _rec->sq_pos();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TString_array TDB_recordset::get_next_row()
|
|
||||||
{
|
|
||||||
if (move_next())
|
|
||||||
return get_row();
|
|
||||||
return TString_array();
|
|
||||||
}
|
|
||||||
|
|
||||||
const TString_array TDB_recordset::get_row(TRecnotype n)
|
|
||||||
{
|
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
_row.destroy();
|
|
||||||
for (unsigned i = 0; i < ncol; i++)
|
|
||||||
_row.add(TString(_rec->sq_get(i, false)));
|
|
||||||
return _row;
|
|
||||||
}
|
|
||||||
// else
|
|
||||||
_row.destroy();
|
|
||||||
return _row;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TDB_recordset::requery()
|
|
||||||
{
|
|
||||||
_items = 0;
|
|
||||||
_current_row = -1;
|
|
||||||
_row.destroy();
|
|
||||||
_column.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned TDB_recordset::columns() const
|
|
||||||
{
|
|
||||||
if (!_is_loaded)
|
|
||||||
{
|
|
||||||
TDB_recordset* my_self = const_cast<TDB_recordset*>(this);
|
|
||||||
my_self->set_loaded();
|
|
||||||
}
|
|
||||||
return _ncolumns;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TRecordset_column_info& TDB_recordset::column_info(const unsigned column) const
|
|
||||||
{
|
|
||||||
static TRecordset_column_info info;
|
|
||||||
if (_is_loaded)
|
|
||||||
{
|
|
||||||
info._name = _rec->sq_get_name_field(column); // TString
|
|
||||||
info._width = _rec->sq_get_width_field(column); // int
|
|
||||||
info._type = _rec->sq_get_type_field(column); // TFieldtypes
|
|
||||||
info._pos = column;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
|
||||||
static TVariant field = NULL_VARIANT;
|
|
||||||
static unsigned int last_get = 0;
|
|
||||||
if(!_freezed || column != last_get || field == NULL_VARIANT)
|
|
||||||
{
|
|
||||||
last_get = column;
|
|
||||||
field = _rec->sq_get(column);
|
|
||||||
}
|
|
||||||
return field;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TVariant& TDB_recordset::get(const char* name) const
|
|
||||||
{
|
|
||||||
return TRecordset::get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TDB_recordset::is_connected() const
|
|
||||||
{
|
|
||||||
return _rec->sq_is_connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
const TVariant& TDB_recordset::active_connection() const
|
|
||||||
{
|
|
||||||
static TVariant conn = NULL_VARIANT;
|
|
||||||
conn.add(_dsn);
|
|
||||||
conn.add(_usr);
|
|
||||||
conn.add(_drv);
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TDB_recordset::exec(const char* sql)
|
|
||||||
{
|
|
||||||
bool exec = false;
|
|
||||||
if ((exec = _rec->sq_set_exec(sql))) {
|
|
||||||
_is_loaded = true;
|
|
||||||
_items = _rec->sq_items();
|
|
||||||
}
|
|
||||||
return exec;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TDB_recordset::commit() const
|
|
||||||
{
|
|
||||||
return _rec->sq_commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
TDB_recordset::TDB_recordset(const char* sql, const bool freezed) : _freezed(freezed)
|
|
||||||
{
|
|
||||||
_current_row = -1;
|
|
||||||
_rec = new SSimple_query();
|
|
||||||
//_rec->sq_set_autocommit(true);
|
|
||||||
_sql.cut(0);
|
|
||||||
_is_loaded = false;
|
|
||||||
_items = 0;
|
|
||||||
_ncolumns = 0;
|
|
||||||
freeze(freezed);
|
|
||||||
set(sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
TDB_recordset::~TDB_recordset()
|
|
||||||
{
|
|
||||||
delete _rec;
|
|
||||||
}
|
|
||||||
|
@ -206,55 +206,4 @@ public:
|
|||||||
virtual ~SSimple_query() = default;
|
virtual ~SSimple_query() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TDB_recordset : public TRecordset
|
|
||||||
{
|
|
||||||
SSimple_query * _rec;
|
|
||||||
TString _sql;
|
|
||||||
TString _dsn, _usr, _pwd, _drv;
|
|
||||||
|
|
||||||
bool _freezed;
|
|
||||||
TRecnotype _current_row;
|
|
||||||
TString_array _row, _column;
|
|
||||||
bool _is_loaded;
|
|
||||||
TRecnotype _items;
|
|
||||||
unsigned _ncolumns;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Parsa la stringa di connessione contenuta nella query
|
|
||||||
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 char * tipo_db) const;
|
|
||||||
static TT_driver str_to_driver(const char* tipo_db);
|
|
||||||
bool set_loaded();
|
|
||||||
void unset_loaded();
|
|
||||||
|
|
||||||
public:
|
|
||||||
void freeze(const bool on = true);
|
|
||||||
void reset();
|
|
||||||
bool set(const char* sql);
|
|
||||||
bool move_to(TRecnotype pos) override; // Pure
|
|
||||||
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
|
|
||||||
const TString_array get_row(TRecnotype n = -1);
|
|
||||||
const TString_array get_next_row();
|
|
||||||
const TString& query_text() const override { return _sql; }
|
|
||||||
const TString& driver_version() const override { return _rec->sq_get_client_v(); };
|
|
||||||
const TVariant& get(unsigned int column) const override; // Pure
|
|
||||||
const TVariant& get(const char* name) const override; // Pure
|
|
||||||
const TRecordset_column_info& column_info(unsigned int column) const override; // Pure
|
|
||||||
|
|
||||||
// Ritorna la connessione attuale
|
|
||||||
const TVariant& active_connection() const;
|
|
||||||
bool exec(const char* sql);
|
|
||||||
bool commit() const;
|
|
||||||
|
|
||||||
TDB_recordset(const char * sql, bool freezed = false);
|
|
||||||
~TDB_recordset();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
x
Reference in New Issue
Block a user