From 9bf716335f304eeafb56cad4b8f444ced8a6778a Mon Sep 17 00:00:00 2001 From: Alessandro Bonazzi Date: Mon, 16 Oct 2023 20:42:41 +0200 Subject: [PATCH] Patch level : 12.00 1286 Files correlati : sc0.exe Commento : Programma di esportazione partite --- src/include/array.cpp | 2 +- src/include/postman.cpp | 301 ++++++++++++++++++++++++++++++---------- src/include/strings.cpp | 6 +- src/include/textset.h | 6 +- 4 files changed, 232 insertions(+), 83 deletions(-) diff --git a/src/include/array.cpp b/src/include/array.cpp index 4539d4339..273661760 100755 --- a/src/include/array.cpp +++ b/src/include/array.cpp @@ -611,7 +611,7 @@ const char * TString_array::crow(int n) int TString_array::add(const char* s, int n) { - if (objptr(n) == NULL) + if (objptr(n) == nullptr) n = TArray::add(new TToken_string(s), n); else row(n) = s; diff --git a/src/include/postman.cpp b/src/include/postman.cpp index 90428fc1e..87292b267 100755 --- a/src/include/postman.cpp +++ b/src/include/postman.cpp @@ -13,6 +13,7 @@ #include #include +#include /////////////////////////////////////////////////////////// // TRecipient @@ -296,26 +297,36 @@ static int write_xml(TConfig& cfg, void* jolly) typedef enum { db_add, db_update, db_remove } db_op; -const TString & table_name(int logicnum) +const TString & table_name(int logicnum, bool mssql) { TString & name = get_tmp_string(); const int firm = prefix().get_codditta(); TDir d(logicnum); + if (mssql) + name << '['; if (d.is_firm()) - name << format("%05lda", firm) << '.'; + name << format("%05lda", firm); else - name << "COM."; + name << "COM"; + + if (mssql) + name << '.'; + else + name << '_'; name << logic2table(logicnum); + if (mssql) + name << ']'; return name; } HIDDEN bool create_table(TODBC_recordset & recset, int logicnum, const char * table_name, TTrec & recdef) { - TString sql = "CREATE TABLE ["; + TString sql = "CREATE TABLE "; int nfields = recdef.fields(); - - sql << table_name << "](\n"; + const bool mssql = recset.driver() == ODBC_mssql; + + sql << table_name << " (\n"; for (int i = 0; i < nfields; i++) { TToken_string def = recdef.fielddef(i); @@ -324,7 +335,8 @@ HIDDEN bool create_table(TODBC_recordset & recset, int logicnum, const char * ta if (i > 0) sql << ", "; - sql << "[" << field << "] "; + sql << field; + sql << ' '; switch (t) { case _charfld: @@ -332,7 +344,11 @@ HIDDEN bool create_table(TODBC_recordset & recset, int logicnum, const char * ta sql << "VARCHAR(" << def.get_int(2) << ")"; break; case _memofld: - sql << "VARCHAR(MAX)"; break; + if (mssql) + sql << "VARCHAR(MAX)"; + else + sql << "TEXT(65535)"; + break; case _datefld: sql << "DATE"; break; case _boolfld: @@ -345,7 +361,6 @@ HIDDEN bool create_table(TODBC_recordset & recset, int logicnum, const char * ta case _longzerofld: default: sql << "NUMERIC(" << def.get_int(2) << "," << def.get_int(3) << ")"; break; } - } sql << ");\n"; int err = recset.exec(sql); @@ -365,49 +380,84 @@ HIDDEN bool create_table(TODBC_recordset & recset, int logicnum, const char * ta key = key.left(pos); } sql = "CREATE "; - sql << (dupkeys ? "INDEX KEY" : "UNIQUE INDEX KEY") << k + 1 << " ON [" << table_name << "] ("; - - FOR_EACH_STR_TOKEN(key, field) + sql << (dupkeys ? "INDEX KEY" : "UNIQUE INDEX KEY") << k + 1 << " ON " << table_name << " ("; + if (mssql) { - if (el++ > 0) - sql << ','; - if (field.starts_with("UPPER")) + FOR_EACH_STR_TOKEN(key, field) { - field = field.mid(6, field.len() - 7); - sql << field << "_UPPER"; - TString alter = "ALTER TABLE ["; - - alter << table_name << "] ADD " << field << "_UPPER AS UPPER(" << field << ");"; - err = recset.exec(alter); - } - else - { - int pos = field.find("["); - - if (pos > 0) + if (el++ > 0) + sql << ','; + if (field.starts_with("UPPER")) { - TString fld = field.left(pos); + field = field.mid(6, field.len() - 7); + sql << field << "_UPPER"; - sql << fld << "_MID"; + TString alter = "ALTER TABLE "; - const int start = atoi(field.mid(pos + 1)); - - pos = field.find(",", pos + 1); - const int end = pos > 0 ? atoi(field.mid(pos + 1)) : 0; - - TString alter = "ALTER TABLE ["; - - alter << table_name << "] ADD " << fld << "_MID AS " << (recset.driver() == ODBC_mssql ? "SUBSTRING(" : "MID(") << fld << ',' << start; - - if (end > 0) - alter << ',' << end - start + 1; - alter << ");"; + alter << table_name << " ADD " << field << "_UPPER AS UPPER(" << field << ");"; err = recset.exec(alter); } else - sql << field; + { + int pos = field.find("["); + + if (pos > 0) + { + TString fld = field.left(pos); + + sql << fld << "_MID"; + + const int start = atoi(field.mid(pos + 1)); + + pos = field.find(",", pos + 1); + const int end = pos > 0 ? atoi(field.mid(pos + 1)) : 0; + + TString alter = "ALTER TABLE "; + + alter << table_name << " ADD " << fld << "_MID AS " << (mssql ? "SUBSTRING(" : "MID(") << fld << ',' << start; + if (end > 0) + alter << ',' << end - start + 1; + alter << ");"; + err = recset.exec(alter); + } + else + sql << field; + } } } + else + { + FOR_EACH_STR_TOKEN(key, field) + { + if (el++ > 0) + sql << ','; + + if (field.find("UPPER") >= 0) + sql << "( " << field << " )"; + else + { + int pos = field.find("["); + + if (pos > 0) + { + TString fld = field.left(pos); + const int start = atoi(field.mid(pos + 1)); + + pos = field.find(",", pos + 1); + + const int end = pos > 0 ? atoi(field.mid(pos + 1)) : 0; + + sql << "( SUBSTRING(" << fld << ',' << start; + if (end > 0) + sql << ',' << end - start + 1; + sql << " )"; + } + else + sql << field; + } + } + + } sql << ");\n"; int err = recset.exec(sql); @@ -417,13 +467,14 @@ HIDDEN bool create_table(TODBC_recordset & recset, int logicnum, const char * ta return err >= 0; } -HIDDEN const TString & build_statement(const db_op op, int logicnum, const char * table_name, const TString_array & keys, const TString_array & values) +HIDDEN const TString & build_statement(TODBC_recordset & recset, const db_op op, int logicnum, const char * table_name, const TString_array & keys, const TString_array & values) { TString & statement = get_tmp_string(); + const bool mssql = recset.driver() == ODBC_mssql; if (op == db_add) { - statement << "INSERT INTO [" << table_name << "] ("; + statement << "INSERT INTO " << table_name << " ("; FOR_EACH_ARRAY_ROW(values, r, row) { if (r > 0) @@ -433,6 +484,8 @@ HIDDEN const TString & build_statement(const db_op op, int logicnum, const char statement << ") VALUES ("; FOR_EACH_ARRAY_ROW(values, rk, rowk) { + const TString f = rowk->get(0); + if (rk > 0) statement << ", "; statement << rowk->get(1); @@ -442,65 +495,101 @@ HIDDEN const TString & build_statement(const db_op op, int logicnum, const char else if (op == db_update) { - statement << "UPDATE [" << table_name << "] SET "; + statement << "UPDATE " << table_name << " SET "; FOR_EACH_ARRAY_ROW(values, r, row) { if (r > 0) statement << ", "; - statement << *row; + statement << row->get(0) << '=' << row->get(1); } statement << " WHERE"; FOR_EACH_ARRAY_ROW(keys, rk, rowk) { if (rk > 0) statement << " AND"; - statement << ' ' << *rowk; + statement << ' ' << rowk->get(0) << '=' << rowk->get(1); } } else if (op == db_remove) { - statement << "DELETE FROM [" << table_name << "] WHERE "; + statement << "DELETE FROM " << table_name << " WHERE "; FOR_EACH_ARRAY_ROW(keys, rk, rowk) { if (rk > 0) statement << " AND"; - statement << ' ' << *rowk; + statement << ' ' << rowk->get(0) << '=' << rowk->get(1); } } statement << ';'; return statement; } -HIDDEN const char * make_val(const char * fld, TFieldtypes t, TString &src) +HIDDEN const char * make_val(const char * fld, TFieldtypes t, TODBC_driver driver, TString &src) { TString & val = get_tmp_string(); int pos = src.find("'"); + const bool mssql = driver == ODBC_mssql; - val << fld << '='; - while (pos > 0) + val << fld << '~'; + while (pos >= 0) { - src.insert("'", pos); + src.insert("\\", pos); pos = src.find("'", pos + 2); } switch (t) { case _alfafld: case _charfld: - case _datefld: case _memofld: - val << '\'' << src << '\''; + { + TString outval(src); + + outval = unesc(outval); + outval.rtrim(); + int p = 0; + int len = outval.len(); + + while ((p = outval.find("\\'", p)) >= 0) + outval[p] = '\''; + if (len == 1 && outval[0] == '\\') + outval << '\\'; + else + if (len > 1 && outval[len - 1] == '\\' && outval[len - 2] != '\\') + outval << '\\'; + val << '\'' << outval << '\''; + } + break; + case _datefld: + if (mssql) + val << '\'' << src << '\''; + else + { + TDate d(src); + + if (d.ok()) + val << '\'' << d.string(full, '-', full, full, amg_date) << '\''; + else + val << "NULL"; + } break; case _intfld: - case _longfld: - case _realfld: case _wordfld: case _intzerofld: + val << atoi(src); + break; + case _longfld: case _longzerofld: + val << atol(src); + break; + case _realfld: val << (src.blank() ? "0" : src); break; case _boolfld: - val << (src.blank() ? "'FALSE'" : "'TRUE'"); + if (mssql) + val << (src.blank() ? "'FALSE'" : "'TRUE'"); + else + val << (src.blank() ? 0 : 1); break; default: val << src; @@ -508,6 +597,10 @@ HIDDEN const char * make_val(const char * fld, TFieldtypes t, TString &src) } return val; } + +#define STOP_FLD (s, cf, fld, val, cv) if (s && cf == fld)\ + s = (val == cv); + HIDDEN bool popolate_table(TODBC_recordset & recset, int logicnum, const char * table_name, TTrec & recdef) { bool ok = false; @@ -527,13 +620,14 @@ HIDDEN bool popolate_table(TODBC_recordset & recset, int logicnum, const char * TString field(def.get(0)); TFieldtypes t = (TFieldtypes)def.get_int(1); TString str = c.curr().get(field); - TToken_string row(make_val(field, t, str), '='); + TToken_string row(make_val(field, t, recset.driver(), str), '~'); values.add(row); } TToken_string key(recdef.keydef(), '+'); int pos = key.find("|"); + bool stop = true; if (pos > 0) key = key.left(pos); @@ -557,19 +651,22 @@ HIDDEN bool popolate_table(TODBC_recordset & recset, int logicnum, const char * str = str.smid(start, pos > 0 ? pos : 0); } - TToken_string row(make_val(field, t, str), '='); + TToken_string row(make_val(field, t, recset.driver(), str), '~'); keys.add(row); +#ifdef DBG +// STOP_FLD(stop, fld, "CODNUM", str , "RIM") +#endif } - const TString & statement = build_statement(db_add, logicnum, table_name, keys, values); + const TString & statement = build_statement(recset, db_add, logicnum, table_name, keys, values); int err = recset.exec(statement); if (err <= 0) { - const TString & statement = build_statement( db_update, logicnum, table_name, keys, values); + const TString & update_statement = build_statement(recset, db_update, logicnum, table_name, keys, values); - err = recset.exec(statement); + err = recset.exec(update_statement); } if (err <= 0) error_box(FR("Errore n. %d invio file %d"), -err, logicnum); @@ -605,6 +702,9 @@ HIDDEN void odbc_send(const TString & dsn, int num, TAuto_token_string & elab_fi error_box(FR("Non posso connettermi a (%s)"), (const char *)odbc_str); return; } + + const bool mssql = recset.driver() == ODBC_mssql; + ini.list_paragraphs(files); FOR_EACH_ARRAY_ROW(files, i, row) { @@ -628,30 +728,73 @@ HIDDEN void odbc_send(const TString & dsn, int num, TAuto_token_string & elab_fi ini.set_paragraph(*row); TTrec wrk(curr_file_num); int nfields = wrk.fields(); - const TString name = table_name(curr_file_num); + const TString name = table_name(curr_file_num, mssql); TToken_string key(wrk.keydef(), '+'); - TString check_statement = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '"; + TString check_statement = "SHOW TABLE STATUS WHERE Name = '"; + + if (mssql) + { + TString sqlname = name.mid(1, name.len() - 2); - check_statement << name << "';"; + check_statement = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '"; + check_statement << sqlname << "';"; + } + else + check_statement << name << "';"; int err = recset.exec(check_statement); if (err <= 0) { create_table(recset, curr_file_num, name, wrk); popolate_table(recset, curr_file_num, name, wrk); - recset.exec("COMMIT;"); + recset.commit(); } else { + bool descr = false; + for (int i = 0; i < nfields; i++) { TToken_string def = wrk.fielddef(i); TString field(def.get(0)); TFieldtypes t = (TFieldtypes)def.get_int(1); TString str = ini.get(field); + + if (key.find(field) >= 0 && str.blank()) + { + ini.set_paragraph(main_file); + str = ini.get(field); + if (str.blank()) + str << rowkey.get(); + ini.set_paragraph(*row); + } str = str.strip("\""); if (key.find(field) >= 0 && str.blank()) - str << rowkey; - TToken_string row(make_val(field, t, str), '='); + str << rowkey; // qui max + + if (curr_file_num == LF_RIGHEDOC) + { + if (field == RDOC_DESCR && str.len() > 50) + { + TString v; + TString add_fld; + TToken_string row("", '~'); + + add_fld = RDOC_DESCLUNGA; + v = "X"; + row = make_val(add_fld, _boolfld, recset.driver(), v); + values.add(row); + add_fld = RDOC_DESCEST; + row = make_val(add_fld, _alfafld, recset.driver(), str.smid(50)); + values.add(row); + str = str.sleft(50).trim(); + descr = true; + } + else + if (descr && (field == RDOC_DESCLUNGA || field == RDOC_DESCEST)) + continue; + } + + TToken_string row(make_val(field, t, recset.driver(), str), '~'); values.add(row); } @@ -661,6 +804,7 @@ HIDDEN void odbc_send(const TString & dsn, int num, TAuto_token_string & elab_fi if (pos > 0) key = key.left(pos); pos = 0; + rowkey.restart(); FOR_EACH_STR_TOKEN(key, field) { TString fld = field; @@ -679,14 +823,14 @@ HIDDEN void odbc_send(const TString & dsn, int num, TAuto_token_string & elab_fi fld = fld.left(pos); } - TString str = ini.get(field); + TString str = ini.get(fld); if (str.blank()) { ini.set_paragraph(main_file); str = ini.get(fld); if (str.blank()) - str << rowkey; + str << rowkey.get(); ini.set_paragraph(*row); } str = str.strip("\""); @@ -703,7 +847,8 @@ HIDDEN void odbc_send(const TString & dsn, int num, TAuto_token_string & elab_fi fld << "_MID"; } - TToken_string row(make_val(fld, t, str), '='); + TToken_string row(make_val(fld, t, recset.driver(), str), '~'); + keys.add(row); } @@ -711,29 +856,31 @@ HIDDEN void odbc_send(const TString & dsn, int num, TAuto_token_string & elab_fi if (op < db_remove) { - statement << "SELECT * FROM [" << name << "] WHERE "; + statement << "SELECT * FROM " << name << " WHERE "; FOR_EACH_ARRAY_ROW(keys, rk, rowk) { if (rk > 0) statement << " AND"; - statement << ' ' << *rowk; + statement << ' ' << rowk->get(0) << "=" << rowk->get(1); } statement << ";"; + int err = recset.exec(statement); + if (err == 0 && op == db_update) op = db_add; else if (err > 0 && op == db_add) op = db_update; } - statement = build_statement(op, curr_file_num, name, keys, values); + statement = build_statement(recset, op, curr_file_num, name, keys, values); int err = recset.exec(statement); if (err < 0) error_box(FR("Errore n. %d invio file %d"), -err, curr_file_num); else - recset.exec("COMMIT;"); + recset.commit(); } } } @@ -903,7 +1050,7 @@ bool TPostman::dispatch_transaction(const TRectype& rec, odbc_files.restart(); FOR_EACH_TOKEN(odbc_dest, r) { - const TString & dsn = r; + const TString dsn = r; TAuto_token_string files = odbc_files.get(); diff --git a/src/include/strings.cpp b/src/include/strings.cpp index 35a60201f..c76ff21fa 100755 --- a/src/include/strings.cpp +++ b/src/include/strings.cpp @@ -107,13 +107,13 @@ int TString::make_room( return lun; } -TString::TString(const char* s) : _str(NULL), _size(0) +TString::TString(const char* s) : _str(nullptr), _size(0) { set(s); } -TString::TString(const TString& s) : _str(NULL), _size(0) +TString::TString(const TString& s) : _str(nullptr), _size(0) { set(s); } -TString::TString(int size, char c) : _str(NULL), _size(0) +TString::TString(int size, char c) : _str(nullptr), _size(0) { if (size > 0) fill(c, size); // Guy: Much simpler and faster (uses memset) diff --git a/src/include/textset.h b/src/include/textset.h index 3f3aa8887..c85747ef8 100755 --- a/src/include/textset.h +++ b/src/include/textset.h @@ -80,8 +80,10 @@ public: virtual TRecnotype new_rec(const char* buf = NULL); virtual bool set(unsigned int fld, const TVariant& var); virtual bool set(const char* fld, const TVariant& var) { return TText_recordset::set(fld, var); } - virtual bool set(const char* fld, const char * s) { const TVariant var(s); return TText_recordset::set(fld, var); } - virtual bool set(const char* fld, const TString & s) { const TVariant var(s); return TText_recordset::set(fld, var); } + virtual bool set(const char* fld, const char * s) { const TVariant var(s); return TText_recordset::set(fld, var); } + virtual bool set(const char* fld, int i) { const TVariant var((long)i); return TText_recordset::set(fld, var); } + virtual bool set(const char* fld, long l) { const TVariant var(l); return TText_recordset::set(fld, var); } + virtual bool set(const char* fld, const TString & s) { const TVariant var(s); return TText_recordset::set(fld, var); } virtual void destroy_column(const int ncol = -1, bool pack = true) { _trc.destroy(ncol, pack); } virtual void create_column(const char * name, TFieldtypes type = _alfafld); virtual bool load_file(const TFilename& n);