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
This commit is contained in:
angelo 1997-07-22 09:49:11 +00:00
parent e1dd361cd3
commit 6ebc12bbb2
6 changed files with 401 additions and 20 deletions

View File

@ -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; ((i<num_fields) && (i<MaxFields)); i++)
{
strcpy(r->Fd[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;

View File

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

View File

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

View File

@ -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<items; i++) // scorre i campi dell'espressione
{
ws = k.get(i); // Primo campo
const bool is_upper = ws.find("UPPER") >= 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 <p name>
// % 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; i<max; i++)
if (ext_files[i]==NULL)
{
_logicnum = _isamfile->ln = 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 <c TLocalisamfile>
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);

View File

@ -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. <p Name> 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. <p Name> indica il file esterno da aprire (vedi <c TBaseisamfile>).
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. <p exclusive> 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. <p exclusive> 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

View File

@ -19,6 +19,7 @@
#include <codeb.h>
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();