Patch level : 12.00 1286

Files correlati     : sc0.exe
Commento            :

Programma di esportazione partite
This commit is contained in:
Alessandro Bonazzi 2023-10-16 20:42:41 +02:00
parent 05bb21f443
commit 9bf716335f
4 changed files with 232 additions and 83 deletions

View File

@ -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;

View File

@ -13,6 +13,7 @@
#include <xml.h>
#include <user.h>
#include <rdoc.h>
///////////////////////////////////////////////////////////
// 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();

View File

@ -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)

View File

@ -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);