Patch level : 12.00 1262

Files correlati     :
Commento            :
nvio postino con ODBC
This commit is contained in:
Alessandro Bonazzi 2023-05-28 12:12:51 +02:00
parent 850dbf6978
commit 6664b94657
2 changed files with 308 additions and 99 deletions

View File

@ -73,7 +73,7 @@ bool TODBC_recordset::connect(const char* dsn, const char* usr, const char* pwd,
if (name.starts_with("ACEODB"))
_driver = ODBC_access;
else
if (name.starts_with("SQLSRV"))
if (name.starts_with("SQLSRV") || name.starts_with("sqlncl"))
_driver = ODBC_mssql;
else
if (name.starts_with("MYSQL??"))

View File

@ -4,6 +4,7 @@
#include <golem.h>
#include <netsock.h>
#include <odbcrset.h>
#include <progind.h>
#include <recarray.h>
#include <relation.h>
#include <scanner.h>
@ -295,15 +296,131 @@ static int write_xml(TConfig& cfg, void* jolly)
typedef enum { db_add, db_update, db_remove } db_op;
HIDDEN const TString & build_statement(const db_op op, int logicnum, const TString_array & keys, const TString_array & values)
const TString & table_name(int logicnum)
{
TString & name = get_tmp_string();
const int firm = prefix().get_codditta();
TDir d(logicnum);
if (d.is_firm())
name << format("%05lda", firm) << '.';
else
name << "COM.";
name << logic2table(logicnum);
return name;
}
HIDDEN bool create_table(TODBC_recordset & recset, int logicnum, const char * table_name, TTrec & recdef)
{
TString sql = "CREATE TABLE [";
int nfields = recdef.fields();
sql << table_name << "](\n";
for (int i = 0; i < nfields; i++)
{
TToken_string def = recdef.fielddef(i);
TString field(def.get(0));
TFieldtypes t = (TFieldtypes)def.get_int(1);
if (i > 0)
sql << ", ";
sql << "[" << field << "] ";
switch (t)
{
case _charfld:
case _alfafld:
sql << "VARCHAR(" << def.get_int(2) << ")";
break;
case _memofld:
sql << "VARCHAR(MAX)"; break;
case _datefld:
sql << "DATE"; break;
case _boolfld:
sql << "BIT DEFAULT 0"; break;
case _realfld:
case _wordfld:
case _intfld:
case _longfld:
case _intzerofld:
case _longzerofld:
default: sql << "NUMERIC(" << def.get_int(2) << "," << def.get_int(3) << ")"; break;
}
}
sql << ");\n";
int err = recset.exec(sql);
if (err < 0)
return false;
for (int k = 0; k < recdef.keys(); k++)
{
TToken_string key(recdef.keydef(k), '+');
bool dupkeys = false;
int pos = key.find("|");
int el = 0;
if (pos > 0)
{
dupkeys = key.mid(pos + 1).full();
key = key.left(pos);
}
sql = "CREATE ";
sql << (dupkeys ? "INDEX KEY" : "UNIQUE INDEX KEY") << k + 1 << " ON [" << table_name << "] (";
FOR_EACH_STR_TOKEN(key, field)
{
if (el++ > 0)
sql << ',';
if (field.starts_with("UPPER"))
{
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)
{
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 " << (recset.driver() == ODBC_mssql ? "SUBSTRING(" : "MID(") << fld << ',' << start;
if (end > 0)
alter << ',' << end - start + 1;
alter << ");";
err = recset.exec(alter);
}
else
sql << field;
}
}
sql << ");\n";
int err = recset.exec(sql);
if (err < 0)
return false;
}
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)
{
TString & statement = get_tmp_string();
TString table_name;
const int firm = prefix().get_codditta();
if (firm > 0)
table_name << format("%05lda", firm) << '_';
table_name << logic2table(logicnum);
if (op == db_add)
{
statement << "INSERT INTO [" << table_name << "] (";
@ -355,6 +472,111 @@ HIDDEN const TString & build_statement(const db_op op, int logicnum, const TStri
return statement;
}
HIDDEN const char * make_val(const char * fld, TFieldtypes t, TString &src)
{
TString & val = get_tmp_string();
int pos = src.find("'");
val << fld << '=';
while (pos > 0)
{
src.insert("'", pos);
pos = src.find("'", pos + 2);
}
switch (t)
{
case _alfafld:
case _charfld:
case _datefld:
case _memofld:
val << '\'' << src << '\'';
break;
case _intfld:
case _longfld:
case _realfld:
case _wordfld:
case _intzerofld:
case _longzerofld:
val << (src.blank() ? "0" : src);
break;
case _boolfld:
val << (src.blank() ? "'FALSE'" : "'TRUE'");
break;
default:
val << src;
break;
}
return val;
}
HIDDEN bool popolate_table(TODBC_recordset & recset, int logicnum, const char * table_name, TTrec & recdef)
{
bool ok = false;
int nfields = recdef.fields();
TCursor c(new TRelation(logicnum));
const long items = c.items();
TProgress_monitor pi(items, format(TR("caricamento tabella %s"), table_name));
for (c.pos() = 0; pi.addstatus() && c.pos() < items; ++c)
{
TString_array values;
TString_array keys;
for (int i = 0; i < nfields; i++)
{
TToken_string def = recdef.fielddef(i);
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), '=');
values.add(row);
}
TToken_string key(recdef.keydef(), '+');
int pos = key.find("|");
if (pos > 0)
key = key.left(pos);
FOR_EACH_STR_TOKEN(key, field)
{
TString fld = field;
int pos = fld.find("[");
if (pos > 0)
fld = fld.left(pos);
TToken_string def = recdef.fielddef(recdef.field(fld));
TFieldtypes t = (TFieldtypes)def.get_int(1);
TString str = c.curr().get(fld);
if (pos > 0)
{
int start = atoi(field.mid(pos));
pos = field.find(',', pos);
str = str.smid(start, pos > 0 ? pos : 0);
}
TToken_string row(make_val(field, t, str), '=');
keys.add(row);
}
const TString & statement = build_statement(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);
err = recset.exec(statement);
}
if (err <= 0)
error_box(FR("Errore n. %d invio file %d"), logicnum, err);
}
return ok;
}
HIDDEN void odbc_send(const TString & dsn, int num, TAuto_token_string & elab_files, const TFilename & name)
{
TODBC_recordset recset;
@ -406,111 +628,96 @@ 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);
for (int i = 0; i < nfields; i++)
TString check_statement = "SELECT TOP 1 * FROM [";
check_statement << name << "];";
if (recset.exec(check_statement) < 0)
{
TToken_string def = wrk.fielddef(i);
TString field(def.get(0));
TFieldtypes t = (TFieldtypes)def.get_int(1);
TToken_string row(field, '=');
TString str = ini.get(field);
TString val;
str.strip("\"");
switch (t)
{
case _alfafld:
case _charfld:
case _datefld:
case _memofld:
val << '\'' << str << '\'';
break;
case _intfld:
case _longfld:
case _realfld:
case _wordfld:
case _intzerofld:
case _longzerofld:
val = str.blank() ? "0" : str;
break;
case _boolfld:
val = str.blank() ? "'FALSE'" : "'TRUE'";
break;
default:
val = str;
break;
}
row.add(val);
values.add(row);
create_table(recset, num, name, wrk);
popolate_table(recset, num, name, wrk);
recset.exec("COMMIT;");
}
TToken_string key(wrk.keydef(), '+');
int pos = key.find("|");
if (pos > 0)
key = key.left(pos);
FOR_EACH_STR_TOKEN(key, field)
else
{
TToken_string row(field, '=');
int pos = field.find("[");
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);
str = str.strip("\"");
TToken_string row(make_val(field, t, str), '=');
values.add(row);
}
TToken_string key(wrk.keydef(), '+');
int pos = key.find("|");
if (pos > 0)
field = field.left(pos);
TString str = ini.get(field);
if (str.blank())
key = key.left(pos);
pos = 0;
FOR_EACH_STR_TOKEN(key, field)
{
ini.set_paragraph(main_file);
str = ini.get(field);
TString fld = field;
if (fld.starts_with("UPPER"))
{
fld = fld.smid(7);
fld.rtrim(1);
fld << "_UPPER";
}
else
{
pos = fld.find("[");
if (pos > 0)
fld = fld.left(pos);
}
TString str = ini.get(field);
if (str.blank())
str << rowkey.get();
ini.set_paragraph(*row);
{
ini.set_paragraph(main_file);
str = ini.get(fld);
if (str.blank())
str << rowkey.get();
ini.set_paragraph(*row);
}
str = str.strip("\"");
TToken_string def = wrk.fielddef(wrk.field(fld));
TFieldtypes t = (TFieldtypes)def.get_int(1);
if (pos > 0)
{
int start = atoi(field.mid(pos + 1));
pos = field.find(',', pos + 1);
str = str.smid(start, pos > 0 ? atoi(field.mid(pos + 1)) : 0);
fld << "_MID";
}
TToken_string row(make_val(fld, t, str), '=');
keys.add(row);
}
const TString & statement = build_statement(op, curr_file_num, name, keys, values);
int err = recset.exec(statement);
TToken_string def = wrk.fielddef(wrk.field(field));
TFieldtypes t = (TFieldtypes)def.get_int(1);
TString val;
str.strip("\"");
switch (t)
if (op < db_remove && err <= 0)
{
case _alfafld:
case _charfld:
case _datefld:
case _memofld:
val << '\'' << str << '\'';
break;
case _intfld:
case _longfld:
case _realfld:
case _wordfld:
case _intzerofld:
case _longzerofld:
val = str.blank() ? "0" : str;
break;
case _boolfld:
val = str.blank() ? "'FALSE'" : "'TRUE'";
break;
default:
val = str;
break;
const TString & statement = build_statement(op == db_add ? db_update : db_add, curr_file_num, name, keys, values);
err = recset.exec(statement);
}
row.add(val);
keys.add(row);
if (err <= 0)
error_box(FR("Errore n. %d invio file %d"), curr_file_num, err);
else
recset.exec("COMMIT;");
}
const TString & statement = build_statement(op, curr_file_num, keys, values);
int err = recset.exec(statement);
if (op < db_remove && err <= 0)
{
const TString & statement = build_statement(op == db_add ? db_update : db_add, curr_file_num, keys, values);
err = recset.exec(statement);
}
if (err <= 0)
error_box(FR("Errore file %d invio n. %d"), curr_file_num, err);
}
}
}
@ -680,8 +887,10 @@ bool TPostman::dispatch_transaction(const TRectype& rec,
FOR_EACH_TOKEN(odbc_dest, r)
{
const TString & dsn = r;
TAuto_token_string files = odbc_files.get();
::odbc_send(dsn, rec.num(), files, name);
}
remove_file(name);