Patch level : 2.1 nopatch
Files correlati : ba0.exe ba8.exe Ricompilazione Demo : [ ] Commento : Aggiunta fantastica applicazione per la generazione di query SQL git-svn-id: svn://10.65.10.50/trunk@11804 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
bba17cc08e
commit
69c8f45fde
@ -850,7 +850,6 @@ bool TMenu_application::test_programs()
|
||||
test = prawin.get_bool("TestPrograms");
|
||||
}
|
||||
|
||||
TExternal_app app("ba1 -6");
|
||||
while (test)
|
||||
{
|
||||
TConfig install("install.ini", "Main");
|
||||
@ -871,7 +870,7 @@ bool TMenu_application::test_programs()
|
||||
{
|
||||
if (dongle().active(module))
|
||||
{
|
||||
const TString16 code = scan.token().left(2);
|
||||
const TString4 code = scan.token().left(2);
|
||||
TToken_string* mytok = (TToken_string*)my_modules.objptr(code);
|
||||
TToken_string* histok = (TToken_string*)his_modules.objptr(code);
|
||||
|
||||
@ -895,7 +894,12 @@ bool TMenu_application::test_programs()
|
||||
if (dangerous.empty() ||
|
||||
(!more && !yesno_box(TR("Si desidera aggiornare i moduli adesso?"))))
|
||||
break;
|
||||
|
||||
const TString16 old_user = user();
|
||||
user() = dongle().administrator(); // Divento temporaneamente amministratore
|
||||
TExternal_app app("ba1 -6");
|
||||
app.run();
|
||||
user() = old_user; // Ripristino utente normale
|
||||
more = TRUE; // ricontrolla
|
||||
}
|
||||
_menu.set_dangerous_modules(dangerous);
|
||||
@ -1123,6 +1127,13 @@ bool TMenu_application::choose_editors()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HIDDEN int dir_sort(const TObject** d1, const TObject** d2)
|
||||
{
|
||||
const TString& s1 = (const TString&)**d1;
|
||||
const TString& s2 = (const TString&)**d2;
|
||||
return stricmp(s1, s2);
|
||||
}
|
||||
|
||||
HIDDEN bool study_handler(TMask_field& f, KEY k)
|
||||
{
|
||||
bool ok = TRUE;
|
||||
@ -1160,7 +1171,7 @@ HIDDEN bool study_handler(TMask_field& f, KEY k)
|
||||
}
|
||||
xvt_slist_destroy(dirs);
|
||||
|
||||
sht.rows_array().sort();
|
||||
sht.rows_array().TArray::sort(dir_sort);
|
||||
if (sht.run() == K_ENTER)
|
||||
f.set(sht.row(-1)); // -1 = selected row
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ bool TMenuitem::perform_program() const
|
||||
TExternal_app a(_action);
|
||||
a.run(FALSE,3);
|
||||
|
||||
const bool maintenance_app = _action.compare("ba1 -0", 6, TRUE) == 0;
|
||||
const bool maintenance_app = _action.starts_with("ba1 -0", TRUE) == 0;
|
||||
if (maintenance_app)
|
||||
{
|
||||
char line1[16],line2[16];
|
||||
|
@ -7,10 +7,8 @@ int main(int argc, char** argv)
|
||||
const int n = argc > 1 ? atoi(argv[1]+1) : 0;
|
||||
switch (n)
|
||||
{
|
||||
case 0:
|
||||
default:
|
||||
ba8100(argc, argv);
|
||||
break;
|
||||
case 1: ba8200(argc, argv); break;
|
||||
default: ba8100(argc, argv); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
3
ba/ba8.h
3
ba/ba8.h
@ -1 +1,4 @@
|
||||
int ba8100(int argc, char* argv[]);
|
||||
int ba8200(int argc, char* argv[]);
|
||||
|
||||
|
||||
|
@ -327,7 +327,10 @@ void TSelector_app::main_loop()
|
||||
}
|
||||
|
||||
TMask m(mask_name);
|
||||
xvt_vobj_minimize(TASK_WIN);
|
||||
|
||||
TTemp_window tw(TASK_WIN);
|
||||
tw.minimize();
|
||||
|
||||
for (int f = m.fields()-1; f >= 0; f--)
|
||||
{
|
||||
TMask_field& field = m.fld(f);
|
||||
|
1182
ba/ba8200.cpp
Executable file
1182
ba/ba8200.cpp
Executable file
File diff suppressed because it is too large
Load Diff
19
ba/ba8200.h
Executable file
19
ba/ba8200.h
Executable file
@ -0,0 +1,19 @@
|
||||
#define F_CODICE 150
|
||||
#define F_DESCR 151
|
||||
#define F_SQL 152
|
||||
#define F_TABLES 200
|
||||
#define F_FIELDS 300
|
||||
#define F_SHEET 400
|
||||
#define F_ADDFILE 301
|
||||
#define F_EDITFILE 302
|
||||
#define F_ASTERISK 303
|
||||
#define F_GENSQL 304
|
||||
#define F_EDITQUERY 305
|
||||
#define F_EXPORT_HTML 306
|
||||
#define F_EXPORT_EXCEL 307
|
||||
#define F_EXPORT_TXT 308
|
||||
|
||||
#define F_FATHER 201
|
||||
#define F_FATHER_ALIAS 202
|
||||
#define F_SON 203
|
||||
#define F_SON_ALIAS 204
|
215
ba/ba8200a.uml
Executable file
215
ba/ba8200a.uml
Executable file
@ -0,0 +1,215 @@
|
||||
#include "ba8200.h"
|
||||
|
||||
TOOLBAR "" 0 -2 0 2
|
||||
|
||||
BUTTON DLG_SAVEREC 10 2
|
||||
BEGIN
|
||||
PROMPT -15 -11 ""
|
||||
PICTURE BMP_SAVEREC
|
||||
PICTURE BMP_SAVERECDN
|
||||
END
|
||||
|
||||
BUTTON DLG_NEWREC 10 2
|
||||
BEGIN
|
||||
PROMPT -25 -11 "~Nuovo"
|
||||
PICTURE BMP_NEWREC
|
||||
PICTURE BMP_NEWRECDN
|
||||
END
|
||||
|
||||
BUTTON DLG_DELREC 10 2
|
||||
BEGIN
|
||||
PROMPT -35 -11 ""
|
||||
PICTURE BMP_DELREC
|
||||
PICTURE BMP_DELRECDN
|
||||
END
|
||||
|
||||
BUTTON DLG_FINDREC 10 2
|
||||
BEGIN
|
||||
PROMPT -45 -11 "Ri~cerca"
|
||||
PICTURE BMP_FINDREC
|
||||
END
|
||||
|
||||
BUTTON DLG_QUIT 10 2
|
||||
BEGIN
|
||||
PROMPT -55 -11 ""
|
||||
END
|
||||
|
||||
ENDPAGE
|
||||
|
||||
PAGE "Query" -1 -1 78 23
|
||||
|
||||
STRING F_CODICE 16
|
||||
BEGIN
|
||||
PROMPT 1 0 "Codice "
|
||||
FLAGS "B"
|
||||
WARNING "E' necessario specificare il codice"
|
||||
CHECKTYPE REQUIRED
|
||||
END
|
||||
|
||||
STRING F_DESCR 50
|
||||
BEGIN
|
||||
PROMPT 29 0 ""
|
||||
END
|
||||
|
||||
TREE F_TABLES 30 8
|
||||
BEGIN
|
||||
PROMPT 1 1 ""
|
||||
END
|
||||
|
||||
SPREADSHEET F_FIELDS 30 10
|
||||
BEGIN
|
||||
PROMPT 34 1 ""
|
||||
ITEM "Nome@12F"
|
||||
ITEM "Dim."
|
||||
ITEM "Chiavi@6"
|
||||
ITEM "Descrizione@50"
|
||||
ITEM "Peso"
|
||||
END
|
||||
|
||||
BUTTON F_ADDFILE 10 2
|
||||
BEGIN
|
||||
PROMPT -16 11 "~Tabella"
|
||||
END
|
||||
|
||||
BUTTON F_EDITFILE 10 2
|
||||
BEGIN
|
||||
PROMPT -26 11 "~Edit"
|
||||
PICTURE BMP_EDIT
|
||||
END
|
||||
|
||||
BUTTON DLG_USER 10 2
|
||||
BEGIN
|
||||
PROMPT -46 11 "~Campo"
|
||||
END
|
||||
|
||||
BUTTON F_ASTERISK 10 2
|
||||
BEGIN
|
||||
PROMPT -56 11 "Campo ~*"
|
||||
END
|
||||
|
||||
BUTTON F_GENSQL 10 2
|
||||
BEGIN
|
||||
PROMPT -66 11 "~SQL"
|
||||
END
|
||||
|
||||
SPREADSHEET F_SHEET
|
||||
BEGIN
|
||||
PROMPT 0 13 ""
|
||||
ITEM "Tabella@12F"
|
||||
ITEM "Colonna@32F"
|
||||
ITEM "Condizione@50"
|
||||
END
|
||||
|
||||
ENDPAGE
|
||||
|
||||
PAGE "Sql" -1 -1 78 23
|
||||
|
||||
MEMO F_SQL 78 -3
|
||||
BEGIN
|
||||
PROMPT 1 1 "SQL query"
|
||||
END
|
||||
|
||||
BUTTON F_EDITQUERY 10 2
|
||||
BEGIN
|
||||
PROMPT -15 -1 ""
|
||||
PICTURE BMP_EDIT
|
||||
END
|
||||
|
||||
BUTTON F_EXPORT_HTML 10 2
|
||||
BEGIN
|
||||
PROMPT -25 -1 "~HTML"
|
||||
END
|
||||
|
||||
BUTTON F_EXPORT_EXCEL 10 2
|
||||
BEGIN
|
||||
PROMPT -35 -1 "~Excel"
|
||||
END
|
||||
|
||||
BUTTON F_EXPORT_TXT 10 2
|
||||
BEGIN
|
||||
PROMPT -45 -1 "~Testo+Tab"
|
||||
END
|
||||
|
||||
ENDPAGE
|
||||
|
||||
ENDMASK
|
||||
|
||||
PAGE "CampiFile" -1 -1 64 8
|
||||
|
||||
STRING 101 12
|
||||
BEGIN
|
||||
PROMPT 1 1 "Nome "
|
||||
END
|
||||
|
||||
NUMBER 102 2
|
||||
BEGIN
|
||||
PROMPT 35 1 "Dimensioni "
|
||||
END
|
||||
|
||||
STRING 103 20
|
||||
BEGIN
|
||||
PROMPT 1 2 "Chiavi "
|
||||
END
|
||||
|
||||
MEMO 104 60 3
|
||||
BEGIN
|
||||
PROMPT 1 3 "Descrizione "
|
||||
END
|
||||
|
||||
NUMBER 105 4
|
||||
BEGIN
|
||||
PROMPT 53 2 "Peso "
|
||||
END
|
||||
|
||||
|
||||
BUTTON DLG_CANCEL 10 2
|
||||
BEGIN
|
||||
PROMPT -12 -1 ""
|
||||
END
|
||||
|
||||
BUTTON DLG_USER 10 2
|
||||
BEGIN
|
||||
PROMPT -22 -1 "Aggiungi"
|
||||
END
|
||||
|
||||
ENDPAGE
|
||||
|
||||
ENDMASK
|
||||
|
||||
PAGE "CampiQuery" -1 -1 60 13
|
||||
|
||||
STRING 101 12
|
||||
BEGIN
|
||||
PROMPT 1 1 "Tabella "
|
||||
CHECKTYPE REQUIRED
|
||||
END
|
||||
|
||||
STRING 102 32
|
||||
BEGIN
|
||||
PROMPT 31 1 "Colonna "
|
||||
CHECKTYPE REQUIRED
|
||||
END
|
||||
|
||||
MEMO 103 54 8
|
||||
BEGIN
|
||||
PROMPT 1 2 "Condizione "
|
||||
END
|
||||
|
||||
BUTTON DLG_CANCEL 10 2
|
||||
BEGIN
|
||||
PROMPT -13 -1 ""
|
||||
END
|
||||
|
||||
BUTTON DLG_DELREC 10 2
|
||||
BEGIN
|
||||
PROMPT -23 -1 ""
|
||||
END
|
||||
|
||||
BUTTON DLG_OK 10 2
|
||||
BEGIN
|
||||
PROMPT -33 -1 ""
|
||||
END
|
||||
|
||||
ENDPAGE
|
||||
|
||||
ENDMASK
|
0
ba/ba8200b.h
Executable file
0
ba/ba8200b.h
Executable file
95
ba/ba8200b.uml
Executable file
95
ba/ba8200b.uml
Executable file
@ -0,0 +1,95 @@
|
||||
#include "ba8200.h"
|
||||
|
||||
PAGE "Nuova tabella" -1 -1 50 15
|
||||
|
||||
GROUP DLG_NULL 24 4
|
||||
BEGIN
|
||||
PROMPT 1 0 "@bTabella collegata"
|
||||
END
|
||||
|
||||
STRING F_SON 8
|
||||
BEGIN
|
||||
PROMPT 2 1 "Tabella "
|
||||
FLAGS "U"
|
||||
SHEET "Tabella|Num@3R|Descrizione archivio@70"
|
||||
INPUT F_SON
|
||||
OUTPUT F_SON
|
||||
CHECKTYPE REQUIRED
|
||||
END
|
||||
|
||||
STRING F_SON_ALIAS 12
|
||||
BEGIN
|
||||
PROMPT 2 2 "Alias "
|
||||
FLAGS "U"
|
||||
END
|
||||
|
||||
GROUP DLG_NULL 24 4
|
||||
BEGIN
|
||||
PROMPT 25 0 "@bTabella principale"
|
||||
END
|
||||
|
||||
STRING F_FATHER 8
|
||||
BEGIN
|
||||
PROMPT 26 1 "Tabella "
|
||||
FLAGS "D"
|
||||
END
|
||||
|
||||
STRING F_FATHER_ALIAS 12
|
||||
BEGIN
|
||||
PROMPT 26 2 "Alias "
|
||||
FLAGS "D"
|
||||
END
|
||||
|
||||
SPREADSHEET F_SHEET 0 -3
|
||||
BEGIN
|
||||
PROMPT 1 4 ""
|
||||
ITEM "Campo@16"
|
||||
ITEM "Campo@16"
|
||||
END
|
||||
|
||||
BUTTON DLG_OK 10 2
|
||||
BEGIN
|
||||
PROMPT -13 -1 ""
|
||||
END
|
||||
|
||||
BUTTON DLG_DELREC 10 2
|
||||
BEGIN
|
||||
PROMPT -23 -1 ""
|
||||
END
|
||||
|
||||
BUTTON DLG_CANCEL 10 2
|
||||
BEGIN
|
||||
PROMPT -33 -1 ""
|
||||
END
|
||||
|
||||
ENDPAGE
|
||||
|
||||
ENDMASK
|
||||
|
||||
PAGE "Fields" -1 -1 68 6
|
||||
|
||||
STRING 101 12
|
||||
BEGIN
|
||||
PROMPT 1 1 "Campo "
|
||||
FLAGS "D"
|
||||
END
|
||||
|
||||
STRING 102 12
|
||||
BEGIN
|
||||
PROMPT 1 2 "Campo "
|
||||
END
|
||||
|
||||
BUTTON DLG_OK 10 2
|
||||
BEGIN
|
||||
PROMPT -12 -1 ""
|
||||
END
|
||||
|
||||
BUTTON DLG_CANCEL 10 2
|
||||
BEGIN
|
||||
PROMPT -22 -1 ""
|
||||
END
|
||||
|
||||
ENDPAGE
|
||||
|
||||
ENDMASK
|
||||
|
692
ba/ba8201.cpp
Executable file
692
ba/ba8201.cpp
Executable file
@ -0,0 +1,692 @@
|
||||
#include <fstream.h>
|
||||
|
||||
#include <diction.h>
|
||||
#include <extcdecl.h>
|
||||
#include <progind.h>
|
||||
#include <relation.h>
|
||||
#include <utility.h>
|
||||
|
||||
#include "ba8201.h"
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Private interface
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
#include "../../sqlite/sources/sqlite.h"
|
||||
|
||||
class TSQLite : public TObject
|
||||
{
|
||||
sqlite* _handle;
|
||||
TFilename _currdb;
|
||||
TAssoc_array _names;
|
||||
|
||||
protected:
|
||||
void logicnum2name(int logicnum, TString& name) const;
|
||||
int name2logicnum(const TString& name) const;
|
||||
|
||||
TString& get_sql_value(const TRectype& curr, const RecFieldDes& fd, TString& tmp) const;
|
||||
|
||||
void build_curr_path(TFilename& name) const;
|
||||
void test_path();
|
||||
|
||||
bool export(const TRectype& rec, ostream& sql) const;
|
||||
bool create_dbf_times();
|
||||
long get_dbf_time(const TString& table);
|
||||
bool set_dbf_time(const TString& table, long last);
|
||||
bool import(int logicnum);
|
||||
|
||||
public:
|
||||
sqlite* open(const char* fname = NULL);
|
||||
bool exec(const char* sql, sqlite_callback callback = NULL, void* jolly = NULL, bool show_error = true);
|
||||
void close();
|
||||
|
||||
bool exists(const char* table);
|
||||
bool parse_select_from(const char* szSql);
|
||||
|
||||
TSQLite();
|
||||
virtual ~TSQLite();
|
||||
} _TheDataBase;
|
||||
|
||||
void TSQLite::build_curr_path(TFilename& name) const
|
||||
{
|
||||
name = firm2dir(-1);
|
||||
name.add("sql");
|
||||
if (!name.exist())
|
||||
make_dir(name);
|
||||
|
||||
TString16 firm;
|
||||
firm.format("%05ldA.sql", prefix().get_codditta());
|
||||
name.add(firm);
|
||||
}
|
||||
|
||||
sqlite* TSQLite::open(const char* fname)
|
||||
{
|
||||
close();
|
||||
_currdb = fname;
|
||||
char* errmsg = NULL;
|
||||
_handle = sqlite_open(_currdb, 0, &errmsg);
|
||||
if (errmsg != NULL)
|
||||
{
|
||||
error_box(errmsg);
|
||||
sqlite_freemem(errmsg);
|
||||
}
|
||||
|
||||
create_dbf_times();
|
||||
|
||||
return _handle;
|
||||
}
|
||||
|
||||
void TSQLite::test_path()
|
||||
{
|
||||
TFilename n;
|
||||
build_curr_path(n);
|
||||
if (n != _currdb)
|
||||
open(n);
|
||||
}
|
||||
|
||||
bool TSQLite::exec(const char* sql, sqlite_callback callback, void* jolly, bool show_error)
|
||||
{
|
||||
TWait_cursor hourglass;
|
||||
char* errmsg = NULL;
|
||||
const int rc = sqlite_exec(_handle, sql, callback, jolly, &errmsg);
|
||||
if (errmsg != NULL)
|
||||
{
|
||||
if (show_error)
|
||||
{
|
||||
TString msg;
|
||||
msg << sql;
|
||||
msg.cut(128);
|
||||
msg << '\n' << errmsg;
|
||||
error_box(msg);
|
||||
}
|
||||
sqlite_freemem(errmsg);
|
||||
}
|
||||
return rc == SQLITE_OK;
|
||||
}
|
||||
|
||||
void TSQLite::close()
|
||||
{
|
||||
if (_handle != NULL)
|
||||
{
|
||||
sqlite_close(_handle);
|
||||
_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char* const DBF_TIMES_TABLE = "DBF_TIMES";
|
||||
|
||||
bool TSQLite::create_dbf_times()
|
||||
{
|
||||
bool ok = exists(DBF_TIMES_TABLE);
|
||||
if (!ok)
|
||||
{
|
||||
TString sql;
|
||||
sql << "CREATE TABLE " << DBF_TIMES_TABLE << " (name,time);\n"
|
||||
<< "CREATE UNIQUE INDEX " << DBF_TIMES_TABLE << "_1 ON " << DBF_TIMES_TABLE << " (name);";
|
||||
ok = exec(sql);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool TSQLite::set_dbf_time(const TString& table, long last)
|
||||
{
|
||||
TString sql;
|
||||
// sql << "INSERT OR REPLACE INTO " << DBF_TIMES_TABLE << " VALUES("
|
||||
sql << "REPLACE INTO " << DBF_TIMES_TABLE << " VALUES("
|
||||
<< '\'' << table << "','" << last << "');";
|
||||
return exec(sql);
|
||||
}
|
||||
|
||||
static int dbf_time_callback(void* jolly, int argc, char** argv, char** columns)
|
||||
{
|
||||
long& last = *(long*)jolly;
|
||||
last = atol(argv[0]);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
long TSQLite::get_dbf_time(const TString& table)
|
||||
{
|
||||
TString sql;
|
||||
sql << "SELECT time FROM " << DBF_TIMES_TABLE << " WHERE name='" << table << "';";
|
||||
long last = 0;
|
||||
exec(sql, dbf_time_callback, &last);
|
||||
return last;
|
||||
}
|
||||
|
||||
void TSQLite::logicnum2name(int logicnum, TString& name) const
|
||||
{
|
||||
const FileDes& fd = prefix().get_filedes(logicnum);
|
||||
const TFilename n = fd.SysName;
|
||||
name = n.name(); name.upper();
|
||||
}
|
||||
|
||||
int TSQLite::name2logicnum(const TString& name) const
|
||||
{
|
||||
TString* cod = (TString*)_names.objptr(name);
|
||||
if (cod == NULL)
|
||||
{
|
||||
FileDes dir;
|
||||
CGetFile(LF_DIR, &dir, _nolock, NORDIR);
|
||||
const int nfiles = (int)dir.EOD;
|
||||
|
||||
TString8 n;
|
||||
for (int logic = LF_USER; logic < nfiles; logic++)
|
||||
{
|
||||
logicnum2name(logic, n);
|
||||
cod = new TString4; cod->format("%d", logic);
|
||||
((TAssoc_array&)_names).add(n, cod);
|
||||
}
|
||||
|
||||
cod = (TString*)_names.objptr(name);
|
||||
if (cod == NULL) // Continua ostinatamente a non esistere?
|
||||
return 0;
|
||||
}
|
||||
return atoi(*cod);
|
||||
}
|
||||
|
||||
TString& TSQLite::get_sql_value(const TRectype& curr, const RecFieldDes& fd, TString& tmp) const
|
||||
{
|
||||
tmp = curr.get(fd.Name);
|
||||
switch (fd.TypeF)
|
||||
{
|
||||
case _intfld:
|
||||
case _longfld:
|
||||
case _realfld:
|
||||
case _wordfld:
|
||||
if (real::is_null(tmp))
|
||||
tmp.cut(0);
|
||||
break;
|
||||
case _intzerofld:
|
||||
case _longzerofld:
|
||||
break;
|
||||
case _datefld:
|
||||
tmp = TDate(tmp).string(ANSI);
|
||||
break;
|
||||
case _boolfld:
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
if (tmp.find('\'') >= 0)
|
||||
{
|
||||
for (int i = 0; tmp[i]; i++)
|
||||
{
|
||||
if (tmp[i] == '\'')
|
||||
tmp.insert("'", i++);
|
||||
}
|
||||
}
|
||||
*/
|
||||
break;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static int exists_callback(void *jolly, int argc, char **argv, char **azColName)
|
||||
{
|
||||
bool& yes = *(bool*)jolly;
|
||||
yes = argc > 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
bool TSQLite::exists(const char* table)
|
||||
{
|
||||
TString sql;
|
||||
sql << "SELECT name FROM sqlite_master WHERE (type='table')AND(name='" << table << "');";
|
||||
bool yes = false;
|
||||
exec(sql, exists_callback, &yes, false);
|
||||
return yes;
|
||||
}
|
||||
|
||||
bool TSQLite::export(const TRectype& rec, ostream& sql) const
|
||||
{
|
||||
const RecDes& rd = *rec.rec_des();
|
||||
TString tmp;
|
||||
for (int i = 0; i < rd.NFields; i++)
|
||||
{
|
||||
if (i > 0) sql << '\t';
|
||||
if (rd.Fd[i].TypeF == _memofld)
|
||||
sql << "\\N";
|
||||
else
|
||||
sql << get_sql_value(rec, rd.Fd[i], tmp);
|
||||
}
|
||||
sql << '\n';
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TSQLite::import(int logicnum)
|
||||
{
|
||||
TString table; logicnum2name(logicnum, table);
|
||||
|
||||
long last = get_dbf_time(table);
|
||||
if (logicnum >= LF_USER) // Dummy test
|
||||
{
|
||||
TLocalisamfile file(logicnum);
|
||||
if (!file.is_changed_since(last))
|
||||
return true;
|
||||
}
|
||||
|
||||
const RecDes& rd = prefix().get_recdes(logicnum);
|
||||
|
||||
TString sql;
|
||||
if (exists(table))
|
||||
{
|
||||
// Drop old table
|
||||
sql.cut(0) << "DROP TABLE "<< table << ';';
|
||||
exec(sql);
|
||||
}
|
||||
|
||||
// Create new table
|
||||
sql.cut(0) << "CREATE TABLE "<< table << "\n(";
|
||||
for (int i = 0; i < rd.NFields; i++)
|
||||
{
|
||||
if (i > 0) sql << ',';
|
||||
sql << rd.Fd[i].Name;
|
||||
}
|
||||
sql << ");";
|
||||
if (!exec(sql))
|
||||
return false;
|
||||
|
||||
// Create main index
|
||||
// sql.cut(0) << "CREATE UNIQUE INDEX " << table << "_1 ON "<< table << "\n(";
|
||||
sql.cut(0) << "CREATE INDEX " << table << "_1 ON "<< table << "\n(";
|
||||
const KeyDes& kd = rd.Ky[0];
|
||||
for (int k = 0; k < kd.NkFields; k++)
|
||||
{
|
||||
if (k > 0) sql << ',';
|
||||
const int ndx = kd.FieldSeq[k] % MaxFields;
|
||||
sql << rd.Fd[ndx].Name;
|
||||
}
|
||||
sql << ");";
|
||||
if (!exec(sql))
|
||||
return false;
|
||||
|
||||
|
||||
TRelation rel(logicnum);
|
||||
TCursor cur(&rel);
|
||||
const TRecnotype items = cur.items();
|
||||
cur.freeze();
|
||||
const TRectype& curr = rel.curr();
|
||||
|
||||
TString msg;
|
||||
msg << TR("Esportazione tabella") << ' ' << table;
|
||||
msg << ": " << items << ' ' << TR("righe");
|
||||
TProgind pi(items, msg, true, true);
|
||||
|
||||
TFilename tmp; tmp.tempdir(); tmp.add("sql.txt");
|
||||
ofstream txt(tmp, ios::binary);
|
||||
|
||||
for (cur = 0; cur.pos() < items; ++cur)
|
||||
{
|
||||
export(curr, txt);
|
||||
pi.addstatus(1);
|
||||
if (pi.iscancelled())
|
||||
break;
|
||||
}
|
||||
|
||||
txt.close();
|
||||
|
||||
msg << '\n' << TR("Importazione tabella") << ' ' << table;
|
||||
msg << ": " << items << ' ' << TR("righe");
|
||||
pi.set_text(msg);
|
||||
|
||||
sql.cut(0) << "COPY " << table << " FROM '" << tmp << "';";
|
||||
if (exec(sql))
|
||||
set_dbf_time(table, last); // Aggiorna ora di ultima modifica
|
||||
|
||||
::remove(tmp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TSQLite::parse_select_from(const char* szSql)
|
||||
{
|
||||
test_path();
|
||||
|
||||
TString sql(szSql);
|
||||
sql.trim();
|
||||
if (!sql.starts_with("SELECT"))
|
||||
return false;
|
||||
|
||||
const int from = sql.find("FROM");
|
||||
if (from < 0)
|
||||
return false;
|
||||
|
||||
const int where = sql.find("WHERE", from);
|
||||
TToken_string tables(sql.sub(from+5, where), ',');
|
||||
TString table;
|
||||
FOR_EACH_TOKEN(tables, tok)
|
||||
{
|
||||
table = tok;
|
||||
table.trim();
|
||||
for (int i = 0; table[i]; i++)
|
||||
{
|
||||
if (table[i] <= ' ' || table[i] == ';')
|
||||
{ table.cut(i); break; }
|
||||
}
|
||||
const int logicnum = name2logicnum(table);
|
||||
if (logicnum > 0)
|
||||
import(logicnum);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TSQLite::TSQLite() : _handle(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
TSQLite::~TSQLite()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// TSQL_query
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
void TSQL_query::reset()
|
||||
{
|
||||
_firstrow = _items = 0;
|
||||
_pagesize = 256;
|
||||
_page.destroy();
|
||||
_column.destroy();
|
||||
}
|
||||
|
||||
int TSQL_query::on_get_items(int argc, char** values, char** columns)
|
||||
{
|
||||
if (_column.items() == 0)
|
||||
{
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
TSQL_column_info* info = new TSQL_column_info;
|
||||
info->_name = columns[i];
|
||||
info->_width = 1;
|
||||
info->_numeric = true;
|
||||
_column.add(info);
|
||||
}
|
||||
}
|
||||
if (_items < _pagesize)
|
||||
{
|
||||
for (int i = 0; i < argc; i++) if (values[i] && *values[i])
|
||||
{
|
||||
TSQL_column_info& info = (TSQL_column_info&)_column[i];
|
||||
const int len = strlen(values[i]);
|
||||
if (len > info._width)
|
||||
info._width = len;
|
||||
if (isalpha(*values[i]))
|
||||
info._numeric = false;
|
||||
}
|
||||
}
|
||||
|
||||
_items++;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int query_get_items(void* jolly, int argc, char** values, char** columns)
|
||||
{
|
||||
TSQL_query* q = (TSQL_query*)jolly;
|
||||
q->on_get_items(argc, values, columns);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
TRecnotype TSQL_query::items() const
|
||||
{
|
||||
if (_items == 0)
|
||||
_TheDataBase.exec(_sql, query_get_items, (TSQL_query*)this);
|
||||
return _items;
|
||||
}
|
||||
|
||||
unsigned int TSQL_query::columns() const
|
||||
{
|
||||
if (_column.items() == 0)
|
||||
items();
|
||||
return _column.items();
|
||||
}
|
||||
|
||||
const TSQL_column_info& TSQL_query::column_info(unsigned int c) const
|
||||
{
|
||||
return (const TSQL_column_info&)_column[c];
|
||||
}
|
||||
|
||||
static int query_get_rows(void* jolly, int argc, char** values, char** columns)
|
||||
{
|
||||
TArray& arr = *(TArray*)jolly;
|
||||
TString_array* a = new TString_array;
|
||||
for (int i = 0; i < argc; i++)
|
||||
a->add(values[i], i);
|
||||
arr.add(a);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
const TString_array* TSQL_query::row(TRecnotype n)
|
||||
{
|
||||
if (n < _firstrow || n >= _firstrow+_page.items())
|
||||
{
|
||||
TString sql = _sql;
|
||||
if (sql.find("LIMIT ") < 0)
|
||||
{
|
||||
const int semicolon = sql.rfind(';');
|
||||
if (semicolon >= 0)
|
||||
sql.cut(semicolon);
|
||||
sql.trim();
|
||||
_page.destroy();
|
||||
_firstrow = n;
|
||||
sql << "\nLIMIT " << _pagesize << " OFFSET " << _firstrow << ';';
|
||||
}
|
||||
_TheDataBase.exec(sql, query_get_rows, &_page);
|
||||
}
|
||||
|
||||
return (const TString_array*)_page.objptr(n-_firstrow);
|
||||
}
|
||||
|
||||
void TSQL_query::set(const char* sql)
|
||||
{
|
||||
reset();
|
||||
_sql = sql;
|
||||
if (_sql.find("SELECT") >= 0)
|
||||
_TheDataBase.parse_select_from(_sql);
|
||||
}
|
||||
|
||||
const TToken_string& TSQL_query::sheet_head() const
|
||||
{
|
||||
TToken_string& head = get_tmp_string();
|
||||
TToken_string tablefield(32, '.');
|
||||
for (unsigned int c = 0; c < columns(); c++)
|
||||
{
|
||||
const TSQL_column_info& ci = column_info(c);
|
||||
tablefield = ci._name;
|
||||
int maxlen = 0;
|
||||
FOR_EACH_TOKEN(tablefield, tok)
|
||||
{
|
||||
if (maxlen == 0)
|
||||
head.add(tok);
|
||||
else
|
||||
head << '\n' << tok;
|
||||
const int len = strlen(tok);
|
||||
if (len > maxlen)
|
||||
maxlen = len;
|
||||
}
|
||||
head << '@' << max(ci._width, maxlen);
|
||||
if (ci._numeric)
|
||||
head << 'R';
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
bool TSQL_query::save_as_html(const TFilename& path)
|
||||
{
|
||||
TProgind pi(items(), TR("Esportazione in corso..."), true, true);
|
||||
|
||||
ofstream out(path);
|
||||
out << "<html>" << endl;
|
||||
out << "<body>" << endl;
|
||||
out << "<table border=\"1\">" << endl;
|
||||
out << " <caption>" << _sql << "</caption>" << endl;
|
||||
|
||||
out << " <thead>";
|
||||
for (unsigned int c = 0; c < columns(); c++)
|
||||
{
|
||||
const TSQL_column_info& ci = column_info(c);
|
||||
TToken_string header(ci._name, '.');
|
||||
TString str;
|
||||
FOR_EACH_TOKEN(header, tok)
|
||||
{
|
||||
if (str.not_empty())
|
||||
str << "<br/>";
|
||||
str << tok;
|
||||
}
|
||||
out << " <th>" << str << "</th>" << endl;
|
||||
}
|
||||
out << " </thead>" << endl;
|
||||
|
||||
for (TRecnotype n = 0; n < items(); n++)
|
||||
{
|
||||
pi.addstatus(1);
|
||||
if (pi.iscancelled())
|
||||
break;
|
||||
const TString_array* arr = row(n);
|
||||
const int last = arr != NULL ? arr->last() : 0;
|
||||
out << " <tr>" << endl;
|
||||
for (int c = 0; c <= last; c++)
|
||||
{
|
||||
const TSQL_column_info& ci = column_info(c);
|
||||
out << " <td";
|
||||
if (ci._numeric)
|
||||
out << " align=\"right\"";
|
||||
out << ">";
|
||||
TString* val = (TString*)arr->objptr(c);
|
||||
if (val && !val->blank())
|
||||
{
|
||||
val->rtrim();
|
||||
out << *val;
|
||||
}
|
||||
out << " </td>" << endl;
|
||||
}
|
||||
out << " </tr>" << endl;
|
||||
}
|
||||
|
||||
out << "</table>" << endl;
|
||||
out << "</body>" << endl;
|
||||
out << "</html>" << endl;
|
||||
|
||||
return !pi.iscancelled();
|
||||
}
|
||||
|
||||
bool TSQL_query::save_as_silk(const TFilename& path)
|
||||
{
|
||||
TProgind pi(items(), TR("Esportazione in corso..."), true, true);
|
||||
|
||||
ofstream out(path);
|
||||
out << "ID;PWXL;N;E" << endl;
|
||||
|
||||
for (unsigned int c = 0; c < columns(); c++)
|
||||
{
|
||||
const TSQL_column_info& ci = column_info(c);
|
||||
out << "C;Y1;X" << (c+1) << ";K\"" << ci._name << '"' << endl;
|
||||
}
|
||||
for (TRecnotype n = 0; n < items(); n++)
|
||||
{
|
||||
pi.addstatus(1);
|
||||
if (pi.iscancelled())
|
||||
break;
|
||||
const TString_array* arr = row(n);
|
||||
const int last = arr != NULL ? arr->last() : 0;
|
||||
for (int c = 0; c <= last; c++)
|
||||
{
|
||||
out << "C;Y" << (n+2) << ";X" << (c+1) << ";K\"";
|
||||
TString* val = (TString*)arr->objptr(c);
|
||||
if (val && !val->blank())
|
||||
{
|
||||
val->rtrim();
|
||||
val->replace('"', '\'');
|
||||
out << *val;
|
||||
}
|
||||
out << '"' << endl;
|
||||
}
|
||||
}
|
||||
out << "E" << endl;
|
||||
|
||||
return !pi.iscancelled();
|
||||
}
|
||||
|
||||
bool TSQL_query::save_as_text(const TFilename& path)
|
||||
{
|
||||
TProgind pi(items(), TR("Esportazione in corso..."), true, true);
|
||||
|
||||
ofstream out(path);
|
||||
for (TRecnotype n = 0; n < items(); n++)
|
||||
{
|
||||
const TString_array* arr = row(n);
|
||||
const int last = arr != NULL ? arr->last() : 0;
|
||||
for (int c = 0; c <= last; c++)
|
||||
{
|
||||
TString* val = (TString*)arr->objptr(c);
|
||||
if (val && !val->blank())
|
||||
{
|
||||
val->rtrim();
|
||||
out << *val;
|
||||
}
|
||||
out << '\t';
|
||||
}
|
||||
out << endl;
|
||||
pi.addstatus(1);
|
||||
if (pi.iscancelled())
|
||||
break;
|
||||
}
|
||||
|
||||
return !pi.iscancelled();
|
||||
}
|
||||
|
||||
bool TSQL_query::save_as(const char* fn, TQueryExportFormat fmt)
|
||||
{
|
||||
TFilename path(fn);
|
||||
TString ext = path.ext(); ext.lower();
|
||||
if (fmt == fmt_unknown)
|
||||
{
|
||||
if (ext.starts_with("htm") || ext == "xml")
|
||||
fmt = fmt_html; else
|
||||
if (ext == "slk" || ext == "xls")
|
||||
fmt = fmt_slk; else
|
||||
if (ext == "txt")
|
||||
fmt = fmt_txt;
|
||||
}
|
||||
bool ok = fmt != fmt_unknown;
|
||||
switch (fmt)
|
||||
{
|
||||
case fmt_html: ok = save_as_html(path); break;
|
||||
case fmt_slk: ok = save_as_silk(path); break;
|
||||
case fmt_txt: ok = save_as_text(path); break;
|
||||
default: break;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
TSQL_query::TSQL_query(const char* sql)
|
||||
{
|
||||
set(sql);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// TQuery_sheet
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
void TQuery_sheet::get_row(long r, TToken_string& row)
|
||||
{
|
||||
row.separator('\t');
|
||||
row.cut(0);
|
||||
if (r >= 0 && r < items())
|
||||
{
|
||||
TString_array& arr = (TString_array&)*_query.row(r);
|
||||
FOR_EACH_ARRAY_ROW(arr, i, str)
|
||||
row.add(*str);
|
||||
}
|
||||
}
|
||||
|
||||
long TQuery_sheet::get_items() const
|
||||
{
|
||||
return _query.items();
|
||||
}
|
||||
|
||||
TQuery_sheet::TQuery_sheet(TSQL_query& query)
|
||||
: TSheet(-1, -1, -2, -4, "Query", query.sheet_head()), _query(query)
|
||||
{
|
||||
}
|
70
ba/ba8201.h
Executable file
70
ba/ba8201.h
Executable file
@ -0,0 +1,70 @@
|
||||
#ifndef __SQLITE_H
|
||||
#define __SQLITE_H
|
||||
|
||||
#ifndef __SHEET_H
|
||||
#include <sheet.h>
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// TSQL_query
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
struct TSQL_column_info : public TObject
|
||||
{
|
||||
TString _name;
|
||||
int _width;
|
||||
bool _numeric;
|
||||
};
|
||||
|
||||
enum TQueryExportFormat { fmt_unknown, fmt_html, fmt_txt, fmt_slk };
|
||||
|
||||
class TSQL_query : public TObject
|
||||
{
|
||||
TString _sql;
|
||||
|
||||
TRecnotype _firstrow, _pagesize, _items;
|
||||
TArray _column;
|
||||
TArray _page;
|
||||
|
||||
protected:
|
||||
void reset();
|
||||
bool save_as_html(const TFilename& path);
|
||||
bool save_as_silk(const TFilename& path);
|
||||
bool save_as_text(const TFilename& path);
|
||||
|
||||
public:
|
||||
void set(const char* sql);
|
||||
|
||||
virtual int on_get_items(int argc, char** values, char** columns);
|
||||
|
||||
TRecnotype items() const;
|
||||
const TString_array* row(TRecnotype n);
|
||||
|
||||
unsigned int columns() const;
|
||||
const TSQL_column_info& column_info(unsigned int c) const;
|
||||
const TToken_string& sheet_head() const;
|
||||
|
||||
bool save_as(const char* filename, TQueryExportFormat = fmt_unknown);
|
||||
|
||||
TSQL_query(const char* sql);
|
||||
virtual ~TSQL_query() { }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// TQuery_sheet
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
class TQuery_sheet : public TSheet
|
||||
{
|
||||
TSQL_query& _query;
|
||||
|
||||
protected:
|
||||
virtual void get_row(long r, TToken_string& row);
|
||||
virtual long get_items() const;
|
||||
|
||||
public:
|
||||
TQuery_sheet(TSQL_query& sql);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user