Patch level : 12.0 no-patch

Files correlati     : 
Commento            : 
Modifica programma esportazione:
- Separata creazione e sportazione delle tabelle di campo dalle tabelle gen.
- Aggiunta creazione degli indici con [COLONNA],...,[_ID_] per ottimizzare le chiamate a database
- Spostata funzione di creazione degli indici solo se ricreate le tabelle di campo

git-svn-id: svn://10.65.10.50/branches/R_10_00@23500 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
mtollari 2017-01-09 16:47:24 +00:00
parent 45f28a5232
commit 7322cf44f0
3 changed files with 229 additions and 59 deletions

View File

@ -5,9 +5,12 @@
#include <relation.h>
#include <utility.h>
#include <extcdecl.h>
#include <real.h>
#include "ba2900.h"
#define TABELLE_CAMPO 171
class TMSSQLExport_msk : public TAutomask
{
protected:
@ -48,6 +51,10 @@ TMSSQLExport_msk::TMSSQLExport_msk() : TAutomask("ba2900a")
set(F_DSN, ini_get_string(CONFIG_DITTA, "Campo_MSSQL_Export", "DSN"));
set(F_USR, ini_get_string(CONFIG_DITTA, "Campo_MSSQL_Export", "User"));
set(F_PWD, ini_get_string(CONFIG_DITTA, "Campo_MSSQL_Export", "Password"));
set(CHK_CREATEGEN, "X");
set(CHK_CREATETABLES, "X");
set(CHK_EXPORTGEN, "X");
set(CHK_EXPORTTABLES, "X");
}
class TMSSQLExport_app : public TSkeleton_application
@ -60,8 +67,11 @@ protected:
const TString queryToNull (TString val) const; // Da una query sostituisce tutti i valori vuoti ('') con null
//*****************************************************************
bool emptyTables() const;
bool esporta() const;
bool createAll() const;
bool exportGen() const;
bool exportTables() const;
bool createGen() const;
bool createTables() const;
bool createIndexes() const;
// Funzioni di esportazione
bool dir_gen() const;
bool trc_gen() const;
@ -102,9 +112,19 @@ const TString TMSSQLExport_app::queryToNull(TString val) const
lastpos++;
val[lastpos] = ' ';
val[lastpos+1] = ' ';
val.insert("null", lastpos);
val.insert("NULL", lastpos);
lastpos = val.find(",\'\'", lastpos);
}
lastpos = val.find(",\'\'", 0); // Devo trovarne uno tra virgole
while(lastpos != -1)
{
lastpos++;
val[lastpos] = ' ';
val[lastpos+1] = ' ';
val.insert("NULL", lastpos);
lastpos = val.find(",\'\'", lastpos);
}
return val;
}
@ -159,8 +179,7 @@ bool TMSSQLExport_app::testFieldSeq(int val, int arr[]) const
}
// Main Program *****************************************************************************************************************************************************************
bool TMSSQLExport_app::createAll() const
bool TMSSQLExport_app::createGen() const
{
TODBC_recordset sqlset("");
// Controllo la connessione di nuovo per essere scrupolosi
@ -190,7 +209,18 @@ bool TMSSQLExport_app::createAll() const
message_box(msg);
return false;
}
// Committo la creazione iniziale delle tabelle custom fondamentali per il passaggio a DB di Campo
return sqlset.commit() != -1;
}
bool TMSSQLExport_app::createTables() const
{
TODBC_recordset sqlset("");
// Controllo la connessione di nuovo per essere scrupolosi
if (!sqlset.connect(DSN, usr, psw))
return false;
ifstream queryFile; // stream dei files con le query
// Le tabelle comuni
TFilename studio("sql\\studiosql.sql");
queryFile.open(studio);
@ -209,7 +239,7 @@ bool TMSSQLExport_app::createAll() const
}
else
{
TString msg("Errore apertura file "); msg << gen;
TString msg("Errore apertura file "); msg << studio;
message_box(msg);
return false;
}
@ -222,6 +252,12 @@ bool TMSSQLExport_app::createAll() const
TFilename ditta("sql\\dittesql.sql");
TString appsql;
queryFile.open(ditta);
// Creo il cursore delle ditte
TRelation relTDitte(LF_NDITTE);
TCursor curDitte(&relTDitte);
int itemsDitte = curDitte.items();
if(queryFile.is_open())
{
while(!queryFile.eof())
@ -230,11 +266,7 @@ bool TMSSQLExport_app::createAll() const
queryFile.getline(aganaye, 10000); // Sei stronzo se fai una riga con più di 10.000 caratteri
appsql << aganaye;
}
// Guardo le ditte che ci sono
TRelation relTDitte(LF_NDITTE);
TCursor curDitte(&relTDitte);
int itemsDitte = curDitte.items();
for(;curDitte.pos() < curDitte.items(); ++curDitte)
for(curDitte = 0; curDitte.pos() < curDitte.items(); ++curDitte)
{
TRectype dittaCurr = curDitte.curr();
TString nomeDitta(dittaCurr.get("CODDITTA"));
@ -260,18 +292,113 @@ bool TMSSQLExport_app::createAll() const
}
else
{
TString msg("Errore apertura file "); msg << gen;
TString msg("Errore apertura file "); msg << ditta;
message_box(msg);
return false;
}
// Committo la creazione iniziale delle tabelle custom fondamentali per il passaggio a DB di Campo
return sqlset.commit() == -1 ? false : true;
return sqlset.commit() != -1 && createIndexes();
}
bool TMSSQLExport_app::esporta() const
/*
* Creatore di indici NON CLUSTER per campo
* Sintassi: CREATE NONCLUSTERED INDEX nome_indice ON nome_tabella (colonna1 [ASC | DESC], colonna2 [ASC | DESC][,...n])
*
*/
bool TMSSQLExport_app::createIndexes() const
{
TODBC_recordset sqlset("");
if (!sqlset.connect(DSN, usr, psw))
return "Connessione fallita!";
int items = TABELLE_CAMPO; // Numero totale di tabelle
COpenDir((int)_manulock, NORDIR); // Apro dir.gen
// Creo il cursore delle ditte per i nomi delle tabelle
TRelation relTDitte(LF_NDITTE);
TCursor curDitte(&relTDitte);
int itemsDitte = curDitte.items();
TProgress_monitor p(items, "Creazione indici");
for (int i = 2; i < items; i++)
{
if (!p.add_status())
break;
if (i > 30 && i != 171) continue;
FileDes d;
CGetFile(i, &d, _nolock, NORDIR);
RecDes r;
CGetRec(i, &r, NORDIR);
for (int k = 0; k < r.NKeys; k++)
{
KeyDes key = r.Ky[k];
// Precarico le chiavi
TString columns;
for(int j = 0; j < key.NkFields; j++)
{
// Trovo il numero del campo
int field = (int)key.FieldSeq[j];
// Controllo se è upper
bool upper = false;
if (field > 100)
{
field -= 100;
upper = true;
}
// Lo vado a trovare in RecFieldDes
RecFieldDes fDes = r.Fd[field];
columns << (false ? "UPPER (" : "") << fDes.Name << (false ? ")," : ","); // Disabilitato upper
}
columns << "_ID_";
TString sqlQuery(""); // Inizio la creazione dell'indice
TString indexName;
if(d.SysName[0] == '%')
{
indexName << "CI_" << TString(d.SysName + 1).upper() << "_K" << k + 1;
TString tableName; tableName << "[" << d.SysName + 1 << "]";
//Creo la query
sqlQuery << "CREATE NONCLUSTERED INDEX " << indexName << " ON [" << d.SysName + 1 << "] (" << columns << ");";
}
else
{
// Ciclo per ogni azienda
for(curDitte = 0; curDitte.pos() < curDitte.items(); ++curDitte)
{
TRectype dittaCurr = curDitte.curr();
TString nomeDitta(dittaCurr.get("CODDITTA"));
for (int i = 0, applen = nomeDitta.len(); i < 5 - applen; i++)
nomeDitta.insert("0");
indexName = TString("CI_") << nomeDitta << "A_" << TString(d.SysName + 1).upper() << "_K" << k + 1;
TString tableName; tableName << "[" << nomeDitta << "A_" << d.SysName + 1 << "]";
// Aggiungo alla query
sqlQuery << "CREATE NONCLUSTERED INDEX " <<indexName << " ON "<< tableName << " (" << columns << ");";
}
}
if(sqlset.exec(queryToNull(sqlQuery)) != 1)
{
return false;
}
}
if(sqlset.commit() == -1)
{
return false;
}
}
return true;
}
bool TMSSQLExport_app::exportGen() const
{
return dir_gen() && trc_gen();
}
bool TMSSQLExport_app::exportTables() const
{
// Funzione disabilitata di debug
// Innanzitutto svuoto le tabelle
if(!emptyTables()) return false;
@ -282,15 +409,8 @@ bool TMSSQLExport_app::esporta() const
{
bool wat = false;
// Inizio con dir.gen
if(!dir_gen()) //throw "ERRORE DIR.GEN";
wat = true;
if(!trc_gen()) //throw "ERRORE TRC.GEN";
wat = true;
TString generalErrors;
if(!exportManager(generalErrors))
wat = true;
//throw generalErrors;
//if(!o01a("O01")) throw "ERRORE TABELLA: O01A";
exportManager(generalErrors);
}
catch (TString orrore)
{
@ -306,7 +426,7 @@ bool TMSSQLExport_app::dir_gen() const
// Controllo la connessione
if (!sqlset.connect(DSN, usr, psw))
return false;
int items = 171; // Numero totale di tabelle
int items = TABELLE_CAMPO; // Numero totale di tabelle
TString msg("Esportazione elenco directory");
COpenDir((int)_manulock, NORDIR); // Apro dir.gen
TProgress_monitor p(items, msg);
@ -340,7 +460,7 @@ bool TMSSQLExport_app::trc_gen() const
// Controllo la connessione
if (!sqlset.connect(DSN, usr, psw))
return false;
int items = 171; // Numero totale di tabelle
int items = TABELLE_CAMPO; // Numero totale di tabelle
TString msg("Esportazione tracciati record");
COpenDir((int)_manulock, NORDIR); // Apro dir.gen
TProgress_monitor p(items-1, msg);
@ -398,13 +518,9 @@ bool TMSSQLExport_app::trc_gen() const
// siccome i valori possono essere sporchi (mannaggina) controllo che dopo la prima chiave (must have) le altre celle non abbiano un valore fuori range o != 0
TToken_string FieldSeq("");
int appFS = 0, vappFS[MKFields] = { 0 };
do
{
vappFS[appFS] = k.FieldSeq[appFS];
FieldSeq.add((int)k.FieldSeq[appFS]);
appFS++;
} while (appFS < MKFields && testFieldSeq((int)k.FieldSeq[appFS], vappFS) && k.FieldSeq[appFS] < 200);
// Metto tanti valori quanti ne sono presenti in NkFields
for(int i = 0; i < k.NkFields; i++)
FieldSeq.add((int)k.FieldSeq[i]);
// FromCh, ToCh
TToken_string FromCh(""), ToCh("");
int app = 0;
@ -439,15 +555,15 @@ bool TMSSQLExport_app::exportManager(TString generalErrors) const
return false;
COpenDir((int)_manulock, NORDIR); // Apro dir.gen
int items = 171; // Numero totale di tabelle
int items = TABELLE_CAMPO; // Numero totale di tabelle
TString msg("Esportazione Tabelle");
TProgress_monitor p(items-1, msg);
for (int i = 2; i <= items && !p.is_cancelled(); i++)
{
//if (!p.add_status())
//break;
if (i != 2 && i != 4 && i != 6 && i != 9 && i != 10 && i != 11 && i != 13 && i != 3) continue;
if (!p.add_status())
break;
if (i > 30 && i != 171) continue;
FileDes fd;
CGetFile(i, &fd, _nolock, NORDIR); // Informazioni per il nome tabella
@ -458,16 +574,16 @@ bool TMSSQLExport_app::exportManager(TString generalErrors) const
TCursor curTable(&relTable);
int itemsTable = curTable.items();
TString msgTable; msgTable << "Esportazione tabella " << fd.SysName;
TProgress_monitor pTable(itemsTable, msg);
TProgress_monitor pTable(itemsTable, msgTable);
for(int j = curTable.pos(); curTable.pos() < itemsTable; j++, ++curTable)
{
//if (!pTable.add_status()) Sputtana a caso
//break;
if (!pTable.add_status())
break;
TRectype rowTable = curTable.curr();
// Creo la query con due stringhe
TString queryF, queryV;
queryF << "INSERT INTO [dbo].[" << fd.SysName + 1 << "] ("; // Tolgo il simbolo iniziale
TString prefix(fd.SysName[0] == '$' ? "00001A_" : "");
queryF << "INSERT INTO [dbo].[" << prefix << fd.SysName + 1 << "] ("; // Tolgo il simbolo iniziale
queryV << "(";
for(int k = 0; k < rd.NFields; k++)
@ -478,15 +594,49 @@ bool TMSSQLExport_app::exportManager(TString generalErrors) const
queryV << "''";
else
{
if(rd.Fd[k].TypeF == 5) // É di tipo data
switch (rd.Fd[k].TypeF)
{
// Int
case 2:
case 6:
queryV << "'" << atoi(rowTable.get(rd.Fd[k].Name)) << "'";
break;
// Long
case 3:
queryV << "'" << atol(rowTable.get(rd.Fd[k].Name)) << "'";
break;
// Real
case 4:
queryV << "'" << real(rowTable.get(rd.Fd[k].Name)) << "'";
break;
case 5:
queryV << "'" << toDate(rowTable.get(rd.Fd[k].Name)) << "'";
else if(rd.Fd[k].TypeF == 8) // É di tipo bool
break;
case 8:
if(rowTable.get(rd.Fd[k].Name) == "X")
queryV << "'True'";
else
queryV << "'False'";
else
break;
// Int zerof
case 9:
queryV << "'" << atoi(rowTable.get(rd.Fd[k].Name)) << "'";
break;
// Long zerof
case 10:
queryV << "'" << atol(rowTable.get(rd.Fd[k].Name)) << "'";
break;
default:
queryV << "'" << toEscape(rowTable.get(rd.Fd[k].Name)) << "'";
break;
}
}
if( k+1 < rd.NFields ) // Modo più comodo
{
@ -524,10 +674,19 @@ void TMSSQLExport_app::main_loop()
if(checkParameters(DSN, usr, psw))
{
// Per comodità utilizzo gli AND short circuits, solo se i bool danno true eseguo la funzione dopo!
if(m.get_bool(CHK_CREATEALL) && createAll())
message_box("Create ok!");
if(m.get_bool(CHK_LOAD) && esporta())
message_box("Migrazione effettuata correttamente!");
if(m.get_bool(CHK_CREATEGEN))
if(!createGen())
message_box("ERROR: Creazione tabelle gen fallita");
if(m.get_bool(CHK_CREATETABLES))
if(!createTables())
message_box("ERROR: Creazione tabelle campo fallita");
if(m.get_bool(CHK_EXPORTGEN))
if (!exportGen())
message_box("CERROR: Esportazione tabelle gen fallita");
if(m.get_bool(CHK_EXPORTTABLES))
if(!exportTables())
message_box("ERROR: Esportazione tabelle campo fallita");
message_box("Migrazione effettuata correttamente!");
}
else
message_box("Fallita connessione");

View File

@ -1,6 +1,7 @@
#define F_DSN 250
#define F_USR 251
#define F_PWD 252
#define CHK_CREATEALL 253
#define CHK_LOAD 254
#define F_DSN 250
#define F_USR 251
#define F_PWD 252
#define CHK_CREATEGEN 253
#define CHK_CREATETABLES 254
#define CHK_EXPORTGEN 255
#define CHK_EXPORTTABLES 256

View File

@ -27,14 +27,24 @@ BEGIN
FLAGS "*"
END
BOOLEAN CHK_CREATEALL
BOOLEAN CHK_CREATEGEN
BEGIN
PROMPT 1 5 "Elimina e ricrea tutte le tabelle, Attenzione! I dati presenti verranno eliminati!"
PROMPT 1 5 "Elimina e ricrea tutte le tabelle gen, Attenzione! I dati presenti verranno eliminati!"
END
BOOLEAN CHK_LOAD
BOOLEAN CHK_CREATETABLES
BEGIN
PROMPT 1 6 "Carica tutti i dati nel DB"
PROMPT 1 6 "Elimina e ricrea tutte le tabelle campo, Attenzione! I dati presenti verranno eliminati!"
END
BOOLEAN CHK_EXPORTGEN
BEGIN
PROMPT 1 7 "Esporta tabelle gen"
END
BOOLEAN CHK_EXPORTTABLES
BEGIN
PROMPT 1 8 "Esporta tabelle dati"
END
END