From 0c1651902737c258d48d0efdbb26e3bbc0808070 Mon Sep 17 00:00:00 2001 From: Simone Palacino Date: Tue, 12 Mar 2019 17:38:18 +0100 Subject: [PATCH] Patch level : 12.0 no-patch Files correlati : tsdb, xvtdb Commento : Inizio implementazione TD_recordset per SQLAPI --- src/include/odbcrset.cpp | 3 + src/include/tsdb.cpp | 155 +++++++++++++++++++++++++++++++++++++++ src/include/tsdb.h | 48 +++++++++++- src/xvtdb/xvtdb.cpp | 75 +++++++++++++++++++ src/xvtdb/xvtdb.h | 3 + 5 files changed, 281 insertions(+), 3 deletions(-) diff --git a/src/include/odbcrset.cpp b/src/include/odbcrset.cpp index 5c3f70548..a1073d141 100755 --- a/src/include/odbcrset.cpp +++ b/src/include/odbcrset.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "tsdb.h" /////////////////////////////////////////////////////////// // TODBC_connections @@ -740,6 +741,8 @@ TRecordset* create_recordset(const TString& sql) rex = new TCSV_recordset(sql); else if (sql.starts_with("AS400", true)) rex = new TAS400_recordset(sql); + if (sql.starts_with("CONNECT", true)) + rex = new TDB_recordset(sql); else rex = new TSQL_recordset(sql); } diff --git a/src/include/tsdb.cpp b/src/include/tsdb.cpp index 129ee790b..461b38e72 100644 --- a/src/include/tsdb.cpp +++ b/src/include/tsdb.cpp @@ -1,4 +1,5 @@ #include +#include /****************************************************************************** @@ -36,3 +37,157 @@ TString SSimple_query::sq_get(TString& field, bool rtrim) { return sq_get(static_cast(field), rtrim); } + +void TDB_recordset::reset() +{ + _first_row = 0; + _items = 0; + _current_row = -1; + _pagesize = 512; + _page.destroy(); + _column.destroy(); + _columns_loaded = false; +} + +/* 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 + */ +void TDB_recordset::set(const char* sql) +{ + TString real_query = ""; + + // 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 + TString conn_str = query.sub(0, ++pos_EOCon); + set_connection(conn_str); + + real_query << query.sub(pos_EOCon); + } + else + real_query << sql; + + if (!_freezed || _sql != sql) + reset(); + _sql.cut(0) << real_query; + if (_sql.find("SELECT") >= 0 || _sql.find("select") >= 0) + find_and_reset_vars(); + _rec.sq_set(_sql); +} + +void TDB_recordset::set_connection(const char* conn_str) +{ + 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; last_pos = pn.find(",", first_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); + default: + break; + } + first_pos = last_pos; + } + + // Guardo se ho valorizzato almeno i primi 3 elementi della connect + // Se non valorizzo l'ultimo metto come default MSSQL Server + if (i == 2) + connect(srv.ltrim(), usr.ltrim(), pwd.ltrim(), TSDB_MSSQL); + else if(i == 3) + connect(srv.ltrim(), usr.ltrim(), pwd.ltrim(), str_to_driver(drv.ltrim())); +} + +int TDB_recordset::connect(const char * db, const char * user, const char * pass, const TT_driver tipo_db) +{ + return _rec.sq_connect(db, user, pass, tipo_db); +} + +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; +} + +int TDB_recordset::connect(const char* db, const char* user, const char* pass, const char* tipo_db) +{ + return _rec.sq_connect(db, user, pass, str_to_driver(tipo_db)); +} + +TRecnotype TDB_recordset::items() const +{ + /* + if(!_rec.sq_is_loaded() && _items == 0) + { + _rec.exec() + } + return static_cast(_rec.sq_items()); + return _items; + */ +} + +bool TDB_recordset::move_to(TRecnotype pos) +{ + return _rec.sq_go(pos); +} + +TDB_recordset::TDB_recordset(const char* sql, bool freezed) : _freezed(freezed), _loaded(false) +{ + _items = 0; + set(sql); +} diff --git a/src/include/tsdb.h b/src/include/tsdb.h index 88fd226c6..c17eac773 100644 --- a/src/include/tsdb.h +++ b/src/include/tsdb.h @@ -20,7 +20,7 @@ * Descrizione: * * La seguente libreria ha due scopi: * * - Implementare una serie di funzioni che emulino interamente il funzionamento attuale di campo in Visual FoxPro su MSQL * - * - Creare delle nuove API per gestire il database in MSQL con cui verranno riscritti i programmi * + * - Creare delle nuove API per gestire il database in MSSQL con cui verranno riscritti i programmi * * Librerie esterne utilizzate: * * - SQLAPI++ (Permette la gestione dei più famosi DB attualmente esistenti) * ********************************************************************************************************************************/ @@ -28,8 +28,8 @@ #ifndef __TSDB_H #define __TSDB_H -#ifndef __XVTDB_H -#include +#ifndef __XVTDB_H +#include #endif @@ -51,6 +51,7 @@ #endif // !__REAL_H #define CHIAVE_ID_ "_ID_" +#include "recset.h" /******************************************************************************** * SSimpleQuery (Sirio Simple Query) * @@ -183,6 +184,47 @@ public: const char* sq_get_string_error(const bool erase = true) { return _rec.get_string_error(erase); } /**< Ritorno l'ultima stringa di errore segnalato in formato (const char *) */ const char* sq_get_text_error(const bool erase = true) { return _rec.get_text_error(erase); } + + // Gestione freeze + /**< Controlla se il cursore è bloccato */ + const bool is_freezed() const { return _rec.is_freezed(); } + /**< Congela il cursore */ + void freeze() { _rec.freeze(); } + /**< Scongela il cursore */ + void defrost() { _rec.defrost(); } +}; + +class TDB_recordset : public TRecordset +{ + SSimple_query _rec; + TString _sql; + TString _dsn, _usr, _pwd, _drv; + + bool _freezed, _loaded, _columns_loaded; + TRecnotype _first_row, _pagesize, _items, _current_row; + TArray _page, _column; + +protected: + void reset(); + void set(const char* sql); + // Parsa la stringa di connessione contenuta nella query + void set_connection(const char * conn_str); + int connect(const char * db, const char * user, const char * pass, const TT_driver tipo_db); + int connect(const char * db, const char * user, const char * pass, const char * tipo_db); + static TT_driver str_to_driver(const char* tipo_db); + +public: + TRecnotype items() const override; // Pure + bool move_to(TRecnotype pos) override; // Pure + virtual TRecnotype current_row() const; // Pure + virtual void requery(); // Pure + virtual const TString& query_text() const { return _sql; }; + + virtual unsigned int columns() const; // Pure + virtual const TRecordset_column_info& column_info(unsigned int column) const; // Pure + virtual const TVariant& get(unsigned int column) const; // Pure + + TDB_recordset(const char * sql, bool freezed = false); }; #endif \ No newline at end of file diff --git a/src/xvtdb/xvtdb.cpp b/src/xvtdb/xvtdb.cpp index 5d150a3bf..a32971871 100644 --- a/src/xvtdb/xvtdb.cpp +++ b/src/xvtdb/xvtdb.cpp @@ -65,6 +65,81 @@ TXvt_recordset::TXvt_recordset(const char* db, const char* user, const char* pas } } +TT_driver TXvt_recordset::str_to_driver(const char* tipo_db) +{ + TT_driver tipoDb_driver = TSDB_undefined; + //! DBMS client is not specified + if (_stricmp(tipo_db, "") != 0) + tipoDb_driver = TSDB_undefined; + //! ODBC + else if (_stricmp(tipo_db, "ODBC") == 0) + tipoDb_driver = TSDB_ODBC; + //! Oracle + else if (_stricmp(tipo_db, "Oracle") == 0) + tipoDb_driver = TSDB_Oracle; + //! Microsoft SQL Server + else if (_stricmp(tipo_db, "MSSQL") == 0) + tipoDb_driver = TSDB_MSSQL; + //! InterBase or Firebird + else if (_stricmp(tipo_db, "InterBase") == 0) + tipoDb_driver = TSDB_InterBase; + //! SQLBase + else if (_stricmp(tipo_db, "SQLBase") == 0) + tipoDb_driver = TSDB_SQLBase; + //! IBM DB2 + else if (_stricmp(tipo_db, "DB2") == 0) + tipoDb_driver = TSDB_DB2; + //! Informix + else if (_stricmp(tipo_db, "Informix") == 0) + tipoDb_driver = TSDB_Informix; + //! Sybase ASE + else if (_stricmp(tipo_db, "Sybase") == 0) + tipoDb_driver = TSDB_Sybase; + //! MySQL + else if (_stricmp(tipo_db, "MySQL") == 0) + tipoDb_driver = TSDB_MySQL; + //! PostgreSQL + else if (_stricmp(tipo_db, "PostgreSQL") == 0) + tipoDb_driver = TSDB_PostgreSQL; + //! SQLite + else if (_stricmp(tipo_db, "SQLite") == 0) + tipoDb_driver = TSDB_SQLite; + //! SQL Anywere + else if (_stricmp(tipo_db, "SQLAnywhere") == 0) + tipoDb_driver = TSDB_SQLAnywhere; + return tipoDb_driver; +} + +int strcmp_ins(const char* str1, const char* str2) +{ + int len1 = strlen(str1) + 1; + int len2 = strlen(str2) + 1; + char * str1_up = new char[len1]; + char * str2_up = new char[len2]; + + strcpy_s(str1_up, len1, str1); + strcpy_s(str2_up, len2, str2); + + char *p = str1_up; + char *q = str2_up; + while (*p != '\0') + { + *p = toupper(*p); + p++; + } + while (*q != '\0') + { + *q = toupper(*q); + q++; + } + return strcmp(str1_up, str2_up); +} + +TXvt_recordset::TXvt_recordset(const char* db, const char* user, const char* pass, const char* tipoDb, + const char* query, const bool ex, const bool freezed) : TXvt_recordset(db, user, pass, str_to_driver(tipoDb), query, ex, freezed) +{ +} + TXvt_recordset::~TXvt_recordset() { try diff --git a/src/xvtdb/xvtdb.h b/src/xvtdb/xvtdb.h index c6b62676b..26664d76b 100644 --- a/src/xvtdb/xvtdb.h +++ b/src/xvtdb/xvtdb.h @@ -95,6 +95,9 @@ public: 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); + static TT_driver str_to_driver(const char* tipo_db); + /**< Costruttore, crea un oggetto dai parametri di connessione passati, chiama costruttore con TT_driver */ + TXvt_recordset(const char* db, const char* user, const char* pass, const char* tipoDb, const char * query = "", const bool ex = false, const bool freezed = false); /**< Distruttore */ ~TXvt_recordset();