From 6ebc12bbb2bf6e4ad547200e679e574175932dda Mon Sep 17 00:00:00 2001 From: angelo Date: Tue, 22 Jul 1997 09:49:11 +0000 Subject: [PATCH] Modifiche alla libreria ISAM per leggere files esterni (files non compresi in TRC): aggiunta classe TExternisamfile git-svn-id: svn://10.65.10.50/trunk@4878 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- include/codeb.c | 97 ++++++++++++++- include/codeb.h | 1 + include/files.cpp | 2 + include/isam.cpp | 274 ++++++++++++++++++++++++++++++++++++++++--- include/isam.h | 43 +++++++ include/stdtypes.cpp | 4 + 6 files changed, 401 insertions(+), 20 deletions(-) diff --git a/include/codeb.c b/include/codeb.c index 47344bd76..6fd52d7f2 100755 --- a/include/codeb.c +++ b/include/codeb.c @@ -878,7 +878,7 @@ int DB_packindex(short vis, const char * filename, RecDes *r, long *peod, bool a if (rt == e4unique || rt == r4unique) { rt = 0; - if (!ask || yesno_box("Sono stati rilevati alcuni record duplicati devo eliminarli ?")) + if (!ask || yesno_box("Sono stati rilevati alcuni records duplicati nel file %s. Devo eliminarli ?",filename)) rt = DB_clean_file(handle, (char*) filename, ff, r, vis); else tags[0].unique = r4unique_continue; @@ -1029,6 +1029,99 @@ int DB_build(const char * filename, RecDes *r) return(rt) ; } +/*------------------------------------------------------------------------- + reperisce il tracciato record e la stringa di definizione delle chiavi + Stringa di definizione chiavi: + expression1|unique1$expression2|unique2$expression3|unique3 + --------------------------------------------------------------------------*/ + +int DB_recinfo(const char * filename, FileDes *d, RecDes *r, char* keys) +{ + /* filename must not have extension since it's used to search index name too*/ + FIELD4INFO *field_info; /* Definizione del tracciato record */ + TAG4INFO *tag_info; /* Definizione delle chiavi */ + INDEX4 *index_file; + DATA4 *data_file; + int rt=0,num_fields,i; + + data_file = d4open(&code_base, (char*)filename); + if (data_file != NULL) + { + field_info = d4field_info(data_file); + index_file = d4index(data_file,(char*)filename); + if (index_file == NULL) + fatal_box("Il file %s e' senza indici.",filename); + tag_info = i4tag_info(index_file); + d->EOD = d->EOX = d4reccount(data_file); + d->LenR = (word)d4record_width(data_file); + d->Flags = 0L; + strcpy(d->Des,"File esterno"); + strcpy(d->FCalc,""); + strcpy(d->GenPrompt,""); + if (field_info != NULL && tag_info != NULL) + { + /* Compile field information */ + num_fields = d4num_fields(data_file); + r->NFields = num_fields; + for (i=0; ((iFd[i].Name,field_info[i].name); + CUpString(r->Fd[i].Name); + r->Fd[i].Len = field_info[i].len; + r->Fd[i].Dec = field_info[i].dec; + switch(field_info[i].type) + { + case r4str: + if (r->Fd[i].Len > 1) + r->Fd[i].TypeF = _alfafld; + else + r->Fd[i].TypeF = _charfld; + break; + case r4log: + r->Fd[i].TypeF = _boolfld; + break; + case r4date: + r->Fd[i].TypeF = _datefld; + break; + case r4memo: + r->Fd[i].TypeF = _memofld; + break; + case r4num: + if (r->Fd[i].Dec > 0) + r->Fd[i].TypeF = _realfld; + else + r->Fd[i].TypeF = r->Fd[i].Len < 6 ? _intfld : _longfld; + break; + default: + break; + } + } + + strcpy(keys,""); + /* Compile key definition */ + for (i=0; i < MaxKeys; i++) /* Browse all tags */ + { + if (tag_info[i].name == NULL) + break; + strcat(keys,tag_info[i].expression); + /* Tell me if you're unique my Boy... */ + strcat(keys,"|"); + strcat(keys,tag_info[i].unique == 0 ? "X" : " "); + strcat(keys,"$"); + } + r->NKeys = i; + u4free(field_info); + u4free(tag_info); + } + else + rt = code_base.error_code; + d4close(data_file); + } + else + rt = code_base.error_code; + return (rt); +} + /*------------------------------------------------------------------------- ritorna l'ultimo errore --------------------------------------------------------------------------*/ @@ -1200,7 +1293,7 @@ int DB_memowrite( const int handle, const char * fieldname, const char * data ) int ret; FIELD4 * f; - f = d4field( dbdata[ handle ], fieldname ); + f = d4field( dbdata[ handle ], (char*)fieldname ); ret = f4memo_assign( f, ( char * )data ); d4flush_data( dbdata[ handle ] ); return ret; diff --git a/include/codeb.h b/include/codeb.h index e87cd07ba..d86fd43da 100755 --- a/include/codeb.h +++ b/include/codeb.h @@ -55,6 +55,7 @@ extern "C" { int DB_packmemo(short vis, const char * filename); int DB_packindex(short vis, const char * filename, RecDes *r, long *peod, bool ask ); int DB_build(const char * filename, RecDes *r); + int DB_recinfo(const char * filename, FileDes *d, RecDes *r, char* keys); int DB_get_error(void); void DB_zero_error(void); int DB_index_seek(int handle, char* from); diff --git a/include/files.cpp b/include/files.cpp index 848a54f86..60a5de2c4 100755 --- a/include/files.cpp +++ b/include/files.cpp @@ -606,6 +606,8 @@ void TTrec::update_keydef (int key, const char *desc) { const char * dup = s.get(); _rec->Ky[key].DupKeys = (dup && *dup != ' '); + if (key == 0 && _rec->Ky[key].DupKeys) + fatal_box("L'indice numero 1 non puo' avere chiavi duplicate."); TCodearray & c = expr.code (); c.begin (); int n = 0; diff --git a/include/isam.cpp b/include/isam.cpp index 8d043fca0..fbecc170f 100755 --- a/include/isam.cpp +++ b/include/isam.cpp @@ -34,7 +34,9 @@ #define RECLOCKTYPES 0xFF00 #define READTYPES 0x00FF #define INVFLD 255 +#define EXTERNAL_FILE 1000 // Files with id >= are considered to be externals +isfdptr* ext_files; isfdptr* openf; Str80 cprefix; @@ -322,9 +324,68 @@ HIDDEN void browse_null(char *start, int nc) if (start[i] == '\0') start[i] = ' '; } +HIDDEN const char * translate_key(const char* key) // Traduce l'espressione chiave di CodeBase +{ + // Trasforma l'espressione + static TToken_string t; + t = key; + TToken_string k(t.get(0),'+'); + TToken_string range("",','); + TString ws; + const bool is_dup = t.get(1)[0] == 'X'; + const int items = k.items(); + t = ""; + for (int i = 0; i= 0; + const bool is_sub = ws.find("SUBSTR") >= 0; + int paren1 = ws.find('('); // Trova la prima parentesi aperta + int paren2,last,from,to; + + if (paren1 >= 0 && is_sub && is_upper) + paren1 = ws.find('('); // Trova la seconda parentesi (in questo caso c'e' per forza) + + if (paren1 >= 0) // Trova la prima virgola o parentesi chiusa (per qualsiasi espressione) + { + paren2 = ws.find(','); + if (paren2 == -1) // se non ci sono virgole trova la parentesi chiusa + paren2 = ws.find(')'); + CHECK(paren2 > paren1,"Something wrong happened translating CodeBase expressions."); + if (is_sub) // Se e' una sottostringa estrae i campi DA e A + { + range = ws; + last = ws.find(')'); + range.sub(paren2,last); // dalla virgola alla parentesi + from = range.get_int(0); + to = range.get_int(1); + } + ws = ws.sub(paren1+1,paren2); // Nome del campo pulito pulito + } + + if (is_upper) + t << "UPPER("; + + t << ws; // aggiunge il nome del campo + + if (is_sub) + { + t << "["; + t << from << ","; + t << to << "]"; + } + if (is_upper) + t << ")"; + t << '+'; + } + t.rtrim(1); // Toglie il + in piu' + t.add(is_dup ? "X" : " "); + return t; +} HIDDEN void getisfd(isfdptr & isfd, int logicnum) { + CHECK(logicnum < EXTERNAL_FILE, "Incorrect use of getisfd() with external file definition"); isfd = new isdef ; isfd->r = new RecDes ; isfd->d = new FileDes ; @@ -339,6 +400,48 @@ HIDDEN void getisfd(isfdptr & isfd, int logicnum) isfd->ln = logicnum; } +HIDDEN void getisfd(isfdptr & isfd, const char* name) +{ +// For External file definition only + TTrec rec; + int err; + char* cb_keys = new char[256*MaxKeys]; + + isfd = new isdef ; + isfd->r = new RecDes ; + isfd->d = new FileDes ; + isfd->ln = -1; + + if (!fexist(name)) + fatal_box("Il file %s non esiste.",(const char*)name); + TFilename n(name); + n.ext(""); // Remove extension + err = DB_recinfo(n,isfd->d,rec.rec(),cb_keys); + if (err == NOERR) + { + strncpy(isfd->d->SysName, name,40); + isfd->d->SysName[41] = '\0'; + isfd->fhnd = 0; + isfd->RecNo = -1; + isfd->ft = 0; + isfd->knum = 0; + rec.rehash(); + const int num_keys = rec.keys(); + TToken_string keys(cb_keys,'$'); + + for (int i=0; i< num_keys; i++) + rec.update_keydef(i,translate_key(keys.get(i))); // Traduce l'espressione chiave di CodeBase + memcpy(isfd->r,rec.rec(),sizeof(RecDes)); + } + else + { + if (err == -60) // This because existance of file is checked before + fatal_box("File %s aperto in modo esclusivo da un'altra applicazione.",name); + else + fatal_box("Apertura file %s : errore n. %d ",name,err); + } + delete cb_keys; +} HIDDEN void relisfd(isfdptr & isfd) { @@ -621,14 +724,59 @@ TBaseisamfile::TBaseisamfile(int logicnum, bool linkrecinst) _current = openrec[_logicnum - 1]; _delrec = FALSE; } - - // _historicfile = ((r.field(RFLD_SYS_DATE) != FIELDERR) && // (r.field(RFLD_SYS_FIRST) != FIELDERR) && // (r.field(RFLD_SYS_LAST) != FIELDERR)); _historicfile = FALSE; } +// @doc EXTERNAL + +// @mfunc Reperisce il tracciato dal file stesso. +// +TBaseisamfile::TBaseisamfile( + const char* name) // @parm Indica il nome del file +// @comm Esiste la possibilita' di codificare i valori di pathpref e prefix in

+// % si riferisce ai dati comuni +// $ si riferisce ai dati di ditta corrente +// # si riferisce al direttorio indicato da PATHPREF.INI +{ + _isamfile = NULL; + _lasterr = NOERR; + _delopenrec = FALSE; + _logicnum = -1; + TFilename n(name); + CHECK(n.not_empty(),"Must define the file to open!"); + +// Espande il nome! + const char c = n[0]; + if (c == '%' || c == '$') + n = CAddPref((char*)(const char*)n); + else + if (c == '#') + { + n.ltrim(1); + n.format("%s/%s",__ptprf,(const char*)n); + } + + n.ext("dbf"); + getisfd (_isamfile, n); // Importa il tracciato dal file + TDir d; + d.get(1); + const int max = (int) d.eod(); + for (int i=0; iln = i+EXTERNAL_FILE; // Primo slot libero + ext_files[i] = _isamfile; + break; + } + if (_logicnum == -1) + fatal_box("Raggiunto il numero massimo di files esterni apribili."); + _current = new TRectype(this); + _delrec = TRUE; + _historicfile = FALSE; +} TBaseisamfile::~TBaseisamfile() @@ -658,7 +806,7 @@ const char* TBaseisamfile::name() const const char* TBaseisamfile::filename() const { - if (_isamfile == NULL) + if (_isamfile == NULL && num() < EXTERNAL_FILE) { TDir d; d.get(num()); @@ -674,7 +822,7 @@ const char* TBaseisamfile::filename() const const char* TBaseisamfile::description() const { - if (_isamfile == NULL) + if (_isamfile == NULL && num() < EXTERNAL_FILE) { TDir d; d.get(num()); @@ -1290,6 +1438,15 @@ TLocalisamfile::TLocalisamfile( else _was_open = FALSE; } +// @mfunc Costruttore +// +// @rdesc Ritorna l'oggetto +TLocalisamfile::TLocalisamfile( + const char* name) // @parm Nome del file esterno da aprire +: TBaseisamfile(name) +{ + _was_open = FALSE; +} TLocalisamfile::~TLocalisamfile() { @@ -1310,7 +1467,7 @@ int TLocalisamfile::close() else { if (_isamfile) - { + { TRecnotype n = DB_reccount(filehnd()->fhnd); TDir d; d.get(num(),_nolock,_nordir,_sysdirop); @@ -1606,7 +1763,82 @@ int TIsamtempfile::close() } /////////////////////////////////////////////////////////// -// TSystemsamfile +// TExternisamfile +/////////////////////////////////////////////////////////// +TExternisamfile::TExternisamfile(const char* name, bool exclusive) +: TLocalisamfile(name) +{ + _name = name; + _name.ext("dbf"); +// Espande il nome! + const char c = _name[0]; + if (c == '%' || c == '$') + _name = CAddPref((char*)(const char*)_name); + else + if (c == '#') + { + _name.ltrim(1); + _name.format("%s/%s",__ptprf,(const char*)_name); + } + open(exclusive); +} + +TExternisamfile::~TExternisamfile() +{ + close(); +} + +int TExternisamfile::open(bool exclusive) +{ + int err=NOERR; + + filehnd()->fhnd = DB_open(_name, exclusive); + if (filehnd()->fhnd < 0) + err = get_error(filehnd()->fhnd); + if (err != NOERR) + { + relisfd(_isamfile); + if (err == -60) + { + if (access(_name,0)) // check for existance + fatal_box("Apertura file %s : errore n. %d. File non esistente.",(const char*) _name,err); + else + fatal_box("Apertura file %s : errore n. %d. File aperto in uso esclusivo da un'altra applicazione.",(const char*) _name,err); + } + else + fatal_box("Apertura file %s : errore n. %d ",(const char*) _name,err); + } + else + filehnd()->knum = 1; + _recno = RECORD_NON_FISICO; + setstatus(err); + return err; +} + +int TExternisamfile::close() +{ + CHECKS(filehnd() != NULL, "File already closed", (const char*)_name); + int err; + err=DB_close(filehnd()->fhnd); + if (err != NOERR) err = get_error(err); + if (err == NOERR) + { + ext_files[_isamfile->ln - EXTERNAL_FILE] = NULL; + relisfd(_isamfile); + clearfilehnd(); + } + setstatus(err); + return err; +} + +const char* TExternisamfile::name() const +{ + sprintf(_isam_string, "%s", (const char*)_name); + return _isam_string; +} + +/////////////////////////////////////////////////////////// +// TSystemisamfile /////////////////////////////////////////////////////////// int TSystemisamfile::build(TRecnotype eox, const TTrec& r) @@ -2408,21 +2640,27 @@ TRectype::TRectype(const TBaseisamfile* i) bool has_memo_fld = FALSE; _logicnum = i->num(); - if (i->filehnd() != NULL) + if (i->filehnd() != NULL && _logicnum < EXTERNAL_FILE) { _length = DB_reclen(i->filehnd()->fhnd); has_memo_fld = rec_has_memo(rec_des()); } else - { - TDir wdir; - - wdir.get(_logicnum, _nolock, _nordir, _sysdirop); - if (wdir.is_com()) - wdir.get(_logicnum, _nolock, _comdir, _sysdirop); - _length = wdir.len(); - has_memo_fld = _length > 0 && lf_has_memo(_logicnum); - } + if (_logicnum >= EXTERNAL_FILE) + { + _length = i->filehnd()->d->LenR; + has_memo_fld = rec_has_memo(i->filehnd()->r); + } + else + { + TDir wdir; + + wdir.get(_logicnum, _nolock, _nordir, _sysdirop); + if (wdir.is_com()) + wdir.get(_logicnum, _nolock, _comdir, _sysdirop); + _length = wdir.len(); + has_memo_fld = _length > 0 && lf_has_memo(_logicnum); + } *_tab = '\0'; _rec = new char [ _length ]; if (_length) @@ -2597,8 +2835,8 @@ HIDDEN int fld_cmp(const char* a, const char* b, int len, bool number) /////////////////////////////////////////////////////////// RecDes* TRectype::rec_des() const -{ - const isdef* i = openf[_logicnum-1]; +{ + const isdef* i = _logicnum < EXTERNAL_FILE ? openf[_logicnum-1] : ext_files[_logicnum - EXTERNAL_FILE]; CHECKD(i, "Can't use a record of closed file ", _logicnum); RecDes* r = i->r; CHECKD(r, "Missing record description of file", _logicnum); diff --git a/include/isam.h b/include/isam.h index dce2bad9e..39b1bad92 100755 --- a/include/isam.h +++ b/include/isam.h @@ -73,6 +73,8 @@ class TRectype : public TSortable friend class TLocalisamfile; // @cfriend TIsamtempfile friend class TIsamtempfile; + // @cfriend TExternisamfile + friend class TExternisamfile; // @access:(INTERNAL) Private Member @@ -290,6 +292,8 @@ class TBaseisamfile : public TObject friend class TIsamfile; // @cfriend TIsamtempfile friend class TIsamtempfile; + // @cfriend TExternisamfile + friend class TExternisamfile; // @cfriend TRecfield friend class TRecfield; // friend class TCursor; @@ -351,6 +355,9 @@ protected: // @cmember Ritorna il nome del file aperto const char* filename() const; + // @cmember Costruttore per derivare TExternisamfile.

indica il file esterno da aprire. + TBaseisamfile(const char* name); + // @access Public Member public: // @cmember Sostituisce il record corrente del del file @@ -658,6 +665,8 @@ protected: int open(unsigned int mode = _manulock); // @cmember Chiude il file aperto int close() ; + // @cmember Costruttore per derivare TExternisamfile.

indica il file esterno da aprire (vedi ). + TLocalisamfile(const char* name); // @access Public Member public: @@ -714,6 +723,40 @@ public: virtual ~TIsamtempfile(); }; + +// @doc EXTERNAL + +// @class TExternisamfile | Classe per la definizione del file isam esterno +// +// @base public | TLocalisamfile +class TExternisamfile : public TLocalisamfile + +// @author:(INTERNAL) Angelo +{ + +// @access:(INTERNAL) Private Member + + //@cmember:(INTERNAL) Indica il nome del file col quale e' stata instanziata la classe + TFilename _name; + +// @access Protected Member +protected: + // @cmember Apre il file.

indica se aprire il file in modo esclusivo + int open(bool exclusive); + // @cmember Chiude il file + int close(); + +// @access Public Member +public: + // @cmember Ritorna il nome del file sotto forma di stringa + virtual const char* name() const; + // @cmember Costruttore.

indica se aprire il file in modo esclusivo. + TExternisamfile(const char* name, bool exclusive = FALSE); + // @cmember Distruttore + virtual ~TExternisamfile(); +}; + + // @doc EXTERNAL // @class TRec_array | Classe per la definizione un array di record diff --git a/include/stdtypes.cpp b/include/stdtypes.cpp index 6563115ba..9de90215c 100755 --- a/include/stdtypes.cpp +++ b/include/stdtypes.cpp @@ -19,6 +19,7 @@ #include extern isfdptr *openf; +extern isfdptr *ext_files; HIDDEN long _stdlevel = 0; // @doc INTERNAL @@ -102,11 +103,13 @@ void init_global_vars() openf = new isfdptr[maxfdir]; openrec = new TRectype*[maxfdir]; + ext_files = new isfdptr[maxfdir]; for (long i = 0; i < maxfdir; i++) { openf[i] = NULL; openrec[i] = NULL; + ext_files[i] = NULL; } DB_init(); @@ -127,6 +130,7 @@ void free_global_vars() { delete openf; delete openrec; + delete ext_files; prefix_destroy(); } DB_exit();