1102 lines
33 KiB
C
Executable File
1102 lines
33 KiB
C
Executable File
/*
|
|
Attenzione!. Per costruire la DLL accertarsi che siano attivati i seguenti switch:
|
|
1) S4DLL_BUILD definito da command line del compilatore
|
|
2) Uno solo tra S4FOX S4CLIPPER S4NDX e S4MDX, definito in d4all.h
|
|
|
|
Gli altri switch di configurazione generale sono a piacere (S4DEBUG, S4ERROR_HOOK, ecc.)
|
|
|
|
Per costruire WINUNO.LIB Accertarsi che d4all.h non abbia definito S4DLL o S4UNIX,
|
|
e tanto meno S4DLL_BUILD, altrimenti per costruire la library di UNIX e' necessario
|
|
cambiare ogni volta. La definizione di tali simboli avviene qui dentro.
|
|
Inoltre deve essere attivo uno solo degli switch di selezione formato database
|
|
(S4FOX, S4MDX ecc.); nel caso si faccia uso della DLL non importa quale si e' definito.
|
|
E' importante solo in caso di utilizzo di una static Library.
|
|
|
|
Per costruire l'aga.fll e' necessario togliere le funzioni progind* e definire S4DLL.
|
|
|
|
*/
|
|
#if XVT_OS == XVT_OS_SCOUNIX
|
|
#define S4UNIX
|
|
#else
|
|
#define S4DLL
|
|
#endif
|
|
|
|
#ifdef XVT /* This not recommended in Unix!*/
|
|
#undef S4UNIX
|
|
#define S4DLL
|
|
#endif
|
|
|
|
#ifdef FOXPRO
|
|
#undef S4UNIX
|
|
#define S4DLL
|
|
#endif
|
|
|
|
#include <d4all.h>
|
|
#include <x4filter.h>
|
|
#include <i4chang.h>
|
|
#include <codeb.h>
|
|
#include <rectypes.h>
|
|
#include <progind.h>
|
|
#define MAXLEN 128 /* Lunghezza massima chiave */
|
|
|
|
extern char* CUpString(char *);
|
|
|
|
static CODE4 code_base;
|
|
static DATA4 *dbdata[CB4FILES];
|
|
static X4FILTER xdb[CB4FILES];
|
|
|
|
|
|
static char * find_slash_backslash(char * str)
|
|
{
|
|
int l=strlen(str);
|
|
static char * xstr ;
|
|
xstr = str + l;
|
|
|
|
while (xstr-- && l--)
|
|
if (*xstr == '\\' || *xstr == '/')
|
|
break;
|
|
if (l == 0)
|
|
return NULL;
|
|
else
|
|
return xstr;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------
|
|
funzione di filtro usata su tutti i database
|
|
--------------------------------------------------------------------------*/
|
|
int S4CALL notdelete(void *fd)
|
|
{
|
|
if(d4deleted(fd)) return r4ignore;
|
|
else return r4keep;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
inizializzazione di CodeBase e delle variabili necessarie
|
|
questa funzione deve essere chiamata SOLO una volta all'interno
|
|
di ciascun eseguibile
|
|
--------------------------------------------------------------------------*/
|
|
void DB_init(void)
|
|
{
|
|
int i;
|
|
for(i=0;i<CB4FILES;i++) {
|
|
dbdata[i]=(DATA4 *) 0;
|
|
}
|
|
d4init(&code_base);
|
|
code_base.read_lock=0;
|
|
code_base.default_unique_error=e4unique;
|
|
code_base.safety=0;
|
|
code_base.lock_attempts=1;
|
|
// code_base.optimize_write = 0;
|
|
u4ncpy(code_base.date_format,"CCYYMMDD",sizeof(code_base.date_format));
|
|
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
reset di CodeBase
|
|
questa funzione dovrebbe essere chiamata prima di uscire da un eseguibile
|
|
per una questione di correttezza formale. Non usandola comunque non acca-
|
|
de niente di drammatico
|
|
--------------------------------------------------------------------------*/
|
|
void DB_exit(void)
|
|
{
|
|
d4init_undo(&code_base);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
apertura del file 'filename'. Il parametro mode consente se != 0 l'apertura
|
|
esclusiva
|
|
--------------------------------------------------------------------------*/
|
|
int DB_open(const char *filename,int mode)
|
|
{
|
|
int i,found;
|
|
|
|
if (mode) code_base.exclusive=1;
|
|
/* cerca il primo posto libero nel vettore dbdata */
|
|
found=-1;
|
|
for(i=0;i<CB4FILES;i++) {
|
|
if(dbdata[i]==(DATA4 *) 0) {
|
|
found=i;
|
|
break;
|
|
}
|
|
}
|
|
/* se non ci sono posti liberi torna -1 */
|
|
if(found==-1) return(found);
|
|
code_base.error_code=0;
|
|
dbdata[found]=d4open(&code_base,(char*)filename);
|
|
if(dbdata[found]==0) return(-1);
|
|
x4init(&xdb[found],dbdata[found],notdelete,dbdata[found]);
|
|
code_base.exclusive=0;
|
|
d4tag_select(dbdata[found],d4tag_default(dbdata[found]));
|
|
if (d4reccount(dbdata[found]) > 0)
|
|
x4top(&xdb[found]);
|
|
return(found);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
chiusura del database inviduato da handle
|
|
torna -1 se il database non puo essere chiuso
|
|
--------------------------------------------------------------------------*/
|
|
int DB_close(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
d4close(dbdata[handle]);
|
|
dbdata[handle]=(DATA4 *) 0;
|
|
code_base.error_code=0;
|
|
return(0);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
torna il puntatore al buffer del record del database individuato da
|
|
handle. In caso di errore torna (char *) 0
|
|
--------------------------------------------------------------------------*/
|
|
char *DB_getrecord(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return((char *) 0);
|
|
return(d4record(dbdata[handle]));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
torna la lunghezza del record
|
|
--------------------------------------------------------------------------*/
|
|
int DB_reclen(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return((int) d4record_width(dbdata[handle]));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
torna la lunghezza della chiave corrente
|
|
--------------------------------------------------------------------------*/
|
|
|
|
int DB_keylen(int handle)
|
|
{
|
|
TAG4 *t;
|
|
|
|
if (dbdata[handle]==0) return(-1);
|
|
if ((t=d4tag_default(dbdata[handle]))== NULL) return (-1);
|
|
return(expr4key_len(t->expr));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
torna il numero del record attuale
|
|
--------------------------------------------------------------------------*/
|
|
long int DB_recno(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1L);
|
|
return(d4recno(dbdata[handle]));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
torna il numero complessivo dei records presenti nell'archivio
|
|
--------------------------------------------------------------------------*/
|
|
long int DB_reccount(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1L);
|
|
return(d4reccount(dbdata[handle]));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
seleziona un indice sul database specificato
|
|
torna -1 se errore, altrimenti 0
|
|
--------------------------------------------------------------------------*/
|
|
int DB_tagselect(int handle,int index_no)
|
|
{
|
|
TAG4 *tt;
|
|
int i;
|
|
|
|
if(dbdata[handle]==0) return(-1);
|
|
/* si posiziona sul primo indice */
|
|
tt=d4tag_next(dbdata[handle],NULL);
|
|
if(tt==NULL) return(-1);
|
|
for(i=1;i<index_no;i++) {
|
|
tt=d4tag_next(dbdata[handle],tt);
|
|
if(tt==NULL) return(-1);
|
|
}
|
|
d4tag_select(dbdata[handle],tt);
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
torna il numero dell'indice selezionato
|
|
torna -1 se errore
|
|
--------------------------------------------------------------------------*/
|
|
int DB_tagget(int handle)
|
|
{
|
|
TAG4 *tt,*tt1;
|
|
int i;
|
|
|
|
if(dbdata[handle]==0) return(-1);
|
|
/* si posiziona sul primo indice */
|
|
tt=d4tag_selected(dbdata[handle]);
|
|
if(tt==NULL) return(-1);
|
|
|
|
tt1=d4tag_next(dbdata[handle],NULL);
|
|
i=1;
|
|
while(tt!=tt1 && tt1!=NULL) {
|
|
tt1=d4tag_next(dbdata[handle],tt1);
|
|
i++;
|
|
}
|
|
return(i);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
si posiziona sul primo record
|
|
torna -1 se errore
|
|
--------------------------------------------------------------------------*/
|
|
int DB_first(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return(x4top(&xdb[handle]));
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
si posiziona sull'ultimorecord
|
|
torna -1 se errore
|
|
--------------------------------------------------------------------------*/
|
|
int DB_last(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return(x4bottom(&xdb[handle]));
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
skip avanti di un record
|
|
--------------------------------------------------------------------------*/
|
|
int DB_next(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return(x4skip(&xdb[handle],1L));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
skip indietro di un record
|
|
--------------------------------------------------------------------------*/
|
|
int DB_prev(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return(x4skip(&xdb[handle],-1L));
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
skip di n records
|
|
--------------------------------------------------------------------------*/
|
|
int DB_skip(int handle,long int recno)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return(x4skip(&xdb[handle],recno));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
locka il record attuale
|
|
--------------------------------------------------------------------------*/
|
|
int DB_lock(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return(d4lock(dbdata[handle],d4recno(dbdata[handle])));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
slocka il record attuale
|
|
--------------------------------------------------------------------------*/
|
|
int DB_unlock(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return(d4unlock(dbdata[handle]));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
cerca la chiave, torna r4after se not found ma si e' posizionato sul record
|
|
successivo, se torna r4eof e' su eof
|
|
--------------------------------------------------------------------------*/
|
|
int DB_seek(int handle,char *key)
|
|
{
|
|
int rc, len;
|
|
TAG4 * tt;
|
|
char * k;
|
|
|
|
if(dbdata[handle]==0) return(-1);
|
|
rc = x4seek(&xdb[handle],key);
|
|
if (rc)
|
|
return rc;
|
|
tt = d4tag_selected(dbdata[handle]);
|
|
len = expr4key_len(tt->expr);
|
|
k = t4key(tt);
|
|
while (len > 0 && k[len-1] == ' ') len--;
|
|
rc = strncmp(key, k, len);
|
|
if (rc == 0)
|
|
return 0;
|
|
else
|
|
if (rc < 0)
|
|
return r4after;
|
|
else
|
|
return r4eof;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
torna 1 se eof, 0 altrimenti
|
|
--------------------------------------------------------------------------*/
|
|
int DB_eof(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return(d4eof(dbdata[handle]));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
torna 1 se tof, 0 altrimenti
|
|
--------------------------------------------------------------------------*/
|
|
int DB_bof(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return(d4bof(dbdata[handle]));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
legge un record per numero record
|
|
--------------------------------------------------------------------------*/
|
|
int DB_go(int handle,long int recno)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return(x4go(&xdb[handle],recno));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
cancella il record attuale. Non cancella le chiavi.
|
|
--------------------------------------------------------------------------*/
|
|
int DB_delete(int handle)
|
|
{
|
|
|
|
if(dbdata[handle]==0) return(-1);
|
|
d4delete(dbdata[handle]);
|
|
return(0);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
ripristina il record attuale
|
|
--------------------------------------------------------------------------*/
|
|
int DB_recall(int handle)
|
|
{
|
|
|
|
if(dbdata[handle]==0) return(-1);
|
|
d4recall(dbdata[handle]);
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
cancella dall'indice corrente la chiave specificata
|
|
--------------------------------------------------------------------------*/
|
|
int DB_delkey(int handle, char* key, long recno)
|
|
{
|
|
INDEX4* i;
|
|
TAG4* t;
|
|
int rt=0;
|
|
int is_locked = 0; /* Diverso da 0 se il file e' bloccato in modo esclusivo */
|
|
/* (dati o indice) da me stesso*/
|
|
char fn[64];
|
|
|
|
if(dbdata[handle]==0) return(-1);
|
|
t=d4tag_default(dbdata[handle]);
|
|
|
|
if (u4switch() & 2 || u4switch() & 8) /* Clipper & DBIII */
|
|
u4name_piece(fn,64,dbdata[handle]->file.name,0,0);
|
|
else
|
|
strcpy(fn,dbdata[handle]->file.name);
|
|
if ((i=d4index(dbdata[handle],fn)) == NULL)
|
|
return(e4index);
|
|
is_locked = DB_file_locked(handle);
|
|
if (is_locked == 0) /* Se non e' stato bloccato in modo esclusivo */
|
|
{
|
|
while ((rt=i4lock(i)) == r4locked)
|
|
#ifdef DBG
|
|
yesnofatal_box("Sono in attesa nella DB_delkeys");
|
|
#else
|
|
u4delay_sec();
|
|
#endif
|
|
}
|
|
if (rt == 0)
|
|
rt=t4remove_calc(t,recno);
|
|
if (is_locked == 0) /* Siccome ho fatto il lock dell'indice, devo anche sbloccarlo */
|
|
i4unlock(i);
|
|
return(rt);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
cancella dall'indice corrente la chiave specificata
|
|
--------------------------------------------------------------------------*/
|
|
int DB_flush(int handle)
|
|
{
|
|
int rt;
|
|
|
|
while ((rt = d4flush(dbdata[handle])) == r4locked)
|
|
#ifdef DBG
|
|
yesnofatal_box("Sono in attesa nella DB_flush");
|
|
#else
|
|
u4delay_sec();
|
|
#endif
|
|
return rt;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
riscrive il record attuale
|
|
--------------------------------------------------------------------------*/
|
|
int DB_rewrite(int handle)
|
|
{
|
|
int rt;
|
|
if(dbdata[handle]==0) return(-1);
|
|
while ((rt=d4write(dbdata[handle],d4recno(dbdata[handle]))) == r4locked)
|
|
#ifdef DBG
|
|
yesnofatal_box("Sono in attesa nella DB_rewrite");
|
|
#else
|
|
u4delay_sec();
|
|
#endif
|
|
if (rt == 0)
|
|
{
|
|
while ((rt = d4flush(dbdata[handle])) == r4locked)
|
|
#ifdef DBG
|
|
yesnofatal_box("Sono in attesa nella DB_rewrite (d4flush)");
|
|
#else
|
|
u4delay_sec();
|
|
#endif
|
|
}
|
|
if (rt == e4unique)
|
|
{
|
|
DB_get_error();
|
|
fatal_box("Errore in DB_rewrite(): chiav duplicata nell' indice %ld, file %s",
|
|
dbdata[handle]->rec_num + 1, dbdata[handle]->file.name);
|
|
}
|
|
rt=DB_unlock(handle);
|
|
return (rt);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
appende il record attuale
|
|
--------------------------------------------------------------------------*/
|
|
int DB_add(int handle)
|
|
{
|
|
int rt;
|
|
int is_locked = 0;
|
|
DATA4 * data = dbdata[handle];
|
|
|
|
if (data==0) return(-1);
|
|
is_locked = DB_file_locked(handle);
|
|
if (is_locked == 0) /* Se non e' stato gia' bloccato in modo esclusivo */
|
|
{
|
|
while (file4lock(&data->file, L4LOCK_POS_OLD, 1L) == r4locked)
|
|
#ifdef DBG
|
|
yesnofatal_box("Sono in attesa nella DB_add");
|
|
#else
|
|
u4delay_sec();
|
|
#endif
|
|
}
|
|
while ((rt = d4append_start(data,0)) == r4locked)
|
|
#ifdef DBG
|
|
yesnofatal_box("Sono in attesa nella DB_add (d4append_start)");
|
|
#else
|
|
u4delay_sec();
|
|
#endif
|
|
if (rt == 0)
|
|
{
|
|
d4recall(data);
|
|
while ((rt = d4append(data)) == r4locked)
|
|
#ifdef DBG
|
|
yesnofatal_box("Sono in attesa nella DB_add (d4append)");
|
|
#else
|
|
u4delay_sec();
|
|
#endif
|
|
if (rt == e4unique)
|
|
{
|
|
DB_get_error();
|
|
if (data->rec_num > 0)
|
|
fatal_box("Errore in DB_add(): chiave duplicata nell' indice %ld, file %s",
|
|
data->rec_num + 1, data->file.name);
|
|
else
|
|
rt = _isreinsert;
|
|
}
|
|
else
|
|
if (rt == 0)
|
|
{
|
|
while ((rt = d4flush(data)) == r4locked)
|
|
#ifdef DBG
|
|
yesnofatal_box("Sono in attesa nella DB_add (d4flush)");
|
|
#else
|
|
u4delay_sec();
|
|
#endif
|
|
}
|
|
}
|
|
DB_unlock(handle);
|
|
if (is_locked == 0)
|
|
{
|
|
file4unlock(&data->file, L4LOCK_POS_OLD, 1L);
|
|
}
|
|
return(rt);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Blocca in modo esclusivo il file dati ed indice
|
|
--------------------------------------------------------------------------*/
|
|
int DB_lockfile(int handle)
|
|
{
|
|
int rt;
|
|
|
|
if(dbdata[handle]==0) return(-1);
|
|
rt = d4lock_file(dbdata[handle]);
|
|
if (rt==0) rt=d4lock_index(dbdata[handle]);
|
|
return(rt);
|
|
}
|
|
|
|
HIDDEN int is_inkey(RecDes *r, int numfield)
|
|
{
|
|
int found=0,i,j;
|
|
|
|
for (i=0; ((i < MaxKeys) && (i < r->NKeys) && !found); i++)
|
|
for (j=0; ((j < r->Ky[i].NkFields) && !found); j++)
|
|
if (numfield == r->Ky[i].FieldSeq[j])
|
|
found=1;
|
|
return(found);
|
|
}
|
|
|
|
HIDDEN void do_key(char *fname, RecDes *r, TAG4INFO *tag_info)
|
|
{
|
|
int i,j;
|
|
char tiname[9]; /* Tag name, max 8 characters long! */
|
|
|
|
strcpy(tiname,fname);
|
|
CUpString(tiname);
|
|
for (i=0; ((i < MaxKeys) && (i < r->NKeys)); i++)
|
|
{
|
|
tag_info[i].name=(char *)u4alloc(9);
|
|
tag_info[i].expression=(char *)u4alloc(128);
|
|
tag_info[i].filter=(char*)u4alloc(20);
|
|
tag_info[i].descending=0;
|
|
if (r->Ky[i].DupKeys)
|
|
tag_info[i].unique=0;
|
|
else
|
|
tag_info[i].unique=e4unique;
|
|
strcpy(tag_info[i].filter,".NOT. DELETED()"); /* Not available for DBIII and CLIPPER */
|
|
strcpy(tag_info[i].name,tiname) ;
|
|
if (strlen(tiname) < 8)
|
|
strcat(tag_info[i].name," ");
|
|
tag_info[i].name[strlen(tag_info[i].name)-1] = '0' + i + 1;
|
|
for (j=0; j < r->Ky[i].NkFields; j++)
|
|
{
|
|
int nf= r->Ky[i].FieldSeq[j];
|
|
if (nf > MaxFields) /* When Upper field is specified */
|
|
{
|
|
nf -= MaxFields;
|
|
strcat(tag_info[i].expression,"UPPER(");
|
|
}
|
|
if (r->Ky[i].FromCh[j] != 255) /* When partial field is specified */
|
|
strcat(tag_info[i].expression,"SUBSTR(");
|
|
|
|
switch (r->Fd[nf].TypeF) /* When numeric field in key is specified */
|
|
{
|
|
case _intfld:
|
|
case _longfld:
|
|
case _realfld:
|
|
case _wordfld:
|
|
case _intzerofld:
|
|
case _longzerofld:
|
|
strcat(tag_info[i].expression,"STR(");
|
|
break;
|
|
case _datefld:
|
|
strcat(tag_info[i].expression,"DTOS(");
|
|
break;
|
|
case _boolfld:
|
|
strcat(tag_info[i].expression,"IIF("); /* Logical fields are in key too.. */
|
|
break;
|
|
default: /* It's a non sense to keep _realfld in key... */
|
|
break; /* however it's possible to have it... */
|
|
} /* Le chiavi composte da campi data non necessitano di funzioni di traduzione. */
|
|
|
|
strcat(tag_info[i].expression,r->Fd[nf].Name); /* Append field name */
|
|
|
|
if (r->Ky[i].FromCh[j] != 255) /* If partial field was specified */
|
|
{ /* add parameters to SUBSTR */
|
|
char ts[8];
|
|
|
|
strcat(tag_info[i].expression,",");
|
|
sprintf(ts,"%d",r->Ky[i].FromCh[j]);
|
|
strcat(tag_info[i].expression,ts);
|
|
strcat(tag_info[i].expression,",");
|
|
sprintf(ts,"%d",r->Ky[i].ToCh[j] - r->Ky[i].FromCh[j] + 1);
|
|
strcat(tag_info[i].expression,ts);
|
|
strcat(tag_info[i].expression,")");
|
|
}
|
|
|
|
switch (r->Fd[nf].TypeF) /* If numeric field was specified */
|
|
{ /* add parameters to STR */
|
|
case _intfld:
|
|
case _longfld:
|
|
case _realfld: /* Questo tipo di campo(real) non ha senso in un a chiave... */
|
|
case _wordfld:
|
|
case _intzerofld:
|
|
case _longzerofld:
|
|
{
|
|
char ts[8];
|
|
strcat(tag_info[i].expression,",");
|
|
sprintf(ts,"%d",r->Fd[nf].Len);
|
|
strcat(tag_info[i].expression,ts);
|
|
strcat(tag_info[i].expression,",0)");
|
|
}
|
|
break;
|
|
case _boolfld:
|
|
strcat(tag_info[i].expression,",\"T\",\"F\")");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* Close parentheses if UPPER or DTOS operators were used: */
|
|
if (r->Ky[i].FieldSeq[j] > MaxFields || (r->Fd[nf].TypeF == _datefld))
|
|
strcat(tag_info[i].expression,")");
|
|
/* If there's another field in key adds "+" operator: */
|
|
if ((j < (r->Ky[i].NkFields-1)) && (strlen(r->Fd[nf].Name) > 0))
|
|
strcat(tag_info[i].expression,"+");
|
|
}
|
|
}
|
|
tag_info[i].name=NULL;
|
|
tag_info[i].expression=NULL;
|
|
tag_info[i].filter=NULL;
|
|
tag_info[i].unique=0;
|
|
tag_info[i].descending=0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Compatta il file dati
|
|
--------------------------------------------------------------------------*/
|
|
int DB_packfile(short vis, const char * filename, long eod)
|
|
{
|
|
int rt=0,handle;
|
|
|
|
/*
|
|
if(dbdata[handle]==0) return(-1);
|
|
codebase.auto_open = 0 cosi' non apre gli indici
|
|
*/
|
|
code_base.auto_open = 0;
|
|
handle=DB_open(filename,1); /* Exclusive mode open! */
|
|
if (handle > -1)
|
|
{
|
|
char s[81];
|
|
|
|
if (vis)
|
|
{
|
|
strcpy(s,"Compattamento dati file : ");
|
|
strcat(s,(char*)filename);
|
|
#ifndef FOXPRO
|
|
progind_create(10L,s,1,1,1);
|
|
#endif
|
|
}
|
|
if (eod < d4reccount(dbdata[handle]))
|
|
{
|
|
rt=d4zap(dbdata[handle],++eod,d4reccount(dbdata[handle]));
|
|
} else
|
|
rt=d4pack(dbdata[handle]);
|
|
if (vis)
|
|
{
|
|
#ifndef FOXPRO
|
|
progind_set_status((long)10);
|
|
progind_destroy();
|
|
#endif
|
|
}
|
|
DB_close(handle);
|
|
}
|
|
else
|
|
rt=code_base.error_code;
|
|
code_base.auto_open = 1;
|
|
return rt;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Compatta il file dati
|
|
--------------------------------------------------------------------------*/
|
|
int DB_packmemo(short vis, const char * filename)
|
|
{
|
|
int rt=0,handle;
|
|
|
|
code_base.auto_open = 0;
|
|
handle=DB_open(filename,1); /* Exclusive mode open! */
|
|
if (handle > -1)
|
|
{
|
|
char s[81];
|
|
|
|
if (vis)
|
|
{
|
|
strcpy(s,"Compattamento memo file : ");
|
|
strcat(s,(char*)filename);
|
|
#ifndef FOXPRO
|
|
progind_create(10L,s,1,1,1);
|
|
#endif
|
|
}
|
|
rt=d4memo_compress(dbdata[handle]);
|
|
if (vis)
|
|
{
|
|
#ifndef FOXPRO
|
|
progind_set_status((long)10);
|
|
progind_destroy();
|
|
#endif
|
|
}
|
|
DB_close(handle);
|
|
}
|
|
else
|
|
rt=code_base.error_code;
|
|
code_base.auto_open = 1;
|
|
return rt;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Compatta gli indici
|
|
--------------------------------------------------------------------------*/
|
|
int DB_packindex(short vis, const char * filename, RecDes *r, long *peod)
|
|
{
|
|
int rt=0,handle;
|
|
TAG4INFO tags[MaxKeys+1];
|
|
char s[82];
|
|
|
|
strcpy(s,"Ricostruzione indici file : ");
|
|
strcat(s,filename);
|
|
|
|
/* codebase.auto_open = 0 cosi' non apre gli indici */
|
|
code_base.auto_open=0 ;
|
|
handle=DB_open(filename,1); /* Exclusive mode open */
|
|
if (handle > -1)
|
|
{
|
|
int i;
|
|
char *ff = find_slash_backslash((char *)filename);
|
|
if (vis)
|
|
{
|
|
#ifndef FOXPRO
|
|
progind_create((long)r->NKeys,s,1,1,1);
|
|
#endif
|
|
}
|
|
if ((ff == NULL) || *ff == '\0')
|
|
ff = (char *)filename;
|
|
else
|
|
ff++;
|
|
do_key(ff,r,tags);
|
|
if (u4switch() &2 || u4switch() & 8) /* Clipper and DBIII */
|
|
{
|
|
INDEX4 * w = i4create(dbdata[handle],(char*)filename,tags);
|
|
#ifndef FOXPRO
|
|
progind_set_status((long)r->NKeys);
|
|
#endif
|
|
if (w != NULL && code_base.error_code==0)
|
|
{
|
|
FILE *fp;
|
|
char cgp[81];
|
|
|
|
strcpy(cgp,filename);
|
|
strcat(cgp,".CGP");
|
|
if ((fp=fopen(cgp,"w"))!=NULL)
|
|
{
|
|
int j;
|
|
|
|
for (j=0; j<r->NKeys;j++)
|
|
fprintf(fp,"%s\n",tags[j].name);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
}
|
|
if (u4switch() & 1 || u4switch() & 4) /* FOXPRO and DBIV */
|
|
{
|
|
INDEX4 * w = i4create(dbdata[handle],NULL,tags);
|
|
if (w == NULL) rt = code_base.error_code;
|
|
#ifndef FOXPRO
|
|
progind_set_status((long)r->NKeys);
|
|
#endif
|
|
}
|
|
for (i=0; ((i < MaxKeys) && (i < r->NKeys)); i++)
|
|
{
|
|
u4free(tags[i].name);
|
|
u4free(tags[i].expression);
|
|
u4free(tags[i].filter);
|
|
}
|
|
if (vis)
|
|
{
|
|
#ifndef FOXPRO
|
|
progind_destroy();
|
|
#endif
|
|
}
|
|
*peod=DB_reccount(handle);
|
|
DB_close(handle);
|
|
}
|
|
code_base.auto_open = 1;
|
|
return(code_base.error_code);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
costruisce il file filename
|
|
--------------------------------------------------------------------------*/
|
|
|
|
int DB_build(const char * filename, RecDes *r)
|
|
{
|
|
|
|
FIELD4INFO field_info[MaxFields+1]; /* Numero di campi in un record */
|
|
TAG4INFO tag_info[MaxKeys+1]; /* Numero di chiavi in un file */
|
|
DATA4 *dbuilded;
|
|
int rt=0,i;
|
|
char *ff = find_slash_backslash((char *)filename);
|
|
|
|
|
|
for (i=0; ((i<r->NFields) && (i<MaxFields)); i++) /* Construct field_info */
|
|
{
|
|
field_info[i].name = (char*)u4alloc(12);
|
|
strcpy(field_info[i].name,r->Fd[i].Name);
|
|
field_info[i].len = r->Fd[i].Len;
|
|
field_info[i].dec = r->Fd[i].Dec;
|
|
switch (r->Fd[i].TypeF)
|
|
{
|
|
case _intfld:
|
|
case _longfld:
|
|
case _realfld: /* It's a non sense to keep this in key! */
|
|
case _wordfld:
|
|
case _intzerofld:
|
|
case _longzerofld:
|
|
field_info[i].type=r4num;
|
|
break;
|
|
case _boolfld:
|
|
field_info[i].type=r4log;
|
|
break;
|
|
case _datefld:
|
|
field_info[i].type=r4date;
|
|
break;
|
|
case _memofld:
|
|
field_info[i].type=r4memo;
|
|
field_info[i].len = 10;
|
|
field_info[i].dec = 0;
|
|
break;
|
|
case _charfld:
|
|
default:
|
|
field_info[i].type=r4str;
|
|
break;
|
|
}
|
|
}
|
|
field_info[i].name=NULL;
|
|
field_info[i].type=0;
|
|
field_info[i].len=0;
|
|
field_info[i].dec=0;
|
|
|
|
if (ff == NULL || *ff == '\0')
|
|
ff = (char *) filename;
|
|
else
|
|
ff++;
|
|
do_key(ff,r,tag_info);
|
|
|
|
if ((dbuilded=d4create(&code_base, (char *)filename, field_info, tag_info))==0) /* deve solo creare il file dati vuoto */
|
|
rt=code_base.error_code;
|
|
else
|
|
rt=d4close(dbuilded);
|
|
if (u4switch() & 2 || u4switch() & 8) /* Rebuild filename.cgp for CLIPPER AND DBIII only */
|
|
{
|
|
FILE* fp;
|
|
char xx[81];
|
|
|
|
strcpy(xx,(char*)filename);
|
|
|
|
strcat(xx,".cgp");
|
|
if ((fp=fopen(xx,"w"))!=NULL)
|
|
{
|
|
int j;
|
|
for (j=0; tag_info[j].name ; j++)
|
|
fprintf(fp,"%s\n",tag_info[j].name);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
if (rt!=0)
|
|
rt=code_base.error_code;
|
|
for (i=0; ((i < MaxFields) && (i < r->NFields)); i++)
|
|
u4free(field_info[i].name);
|
|
for (i=0; ((i < MaxKeys) && (i < r->NKeys)); i++)
|
|
{
|
|
u4free(tag_info[i].name);
|
|
u4free(tag_info[i].expression);
|
|
u4free(tag_info[i].filter);
|
|
}
|
|
return(rt) ;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
ritorna l'ultimo errore
|
|
--------------------------------------------------------------------------*/
|
|
|
|
int DB_get_error(void)
|
|
{
|
|
int rt = code_base.error_code;
|
|
code_base.error_code=0;
|
|
return (rt);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Azzera la viarabile globale d'errore
|
|
--------------------------------------------------------------------------*/
|
|
|
|
void DB_zero_error(void)
|
|
{
|
|
code_base.error_code=0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Si posiziona sull'indice attivo alla chiave indicata, restituisce
|
|
la prima chiave che trova >= a from. (TCusrsor)
|
|
--------------------------------------------------------------------------*/
|
|
|
|
int DB_index_seek(int handle, char* from)
|
|
{
|
|
TAG4 *t;
|
|
|
|
if(dbdata[handle]==0) return(-1);
|
|
if ((t=d4tag_default(dbdata[handle]))==NULL) return(-1);
|
|
|
|
if (t4seek(t,from,strlen(from)) < 0) return(DB_get_error());
|
|
return(0);
|
|
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Ritorna il numero di record corrispondente alla chiave corrente
|
|
--------------------------------------------------------------------------*/
|
|
|
|
long DB_index_recno(int handle)
|
|
{
|
|
TAG4 *t;
|
|
|
|
if(dbdata[handle]==0) return(-1);
|
|
if ((t=d4tag_default(dbdata[handle]))==NULL) return(-1);
|
|
|
|
return(t4recno(t));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Si posiziona sulla chiave successiva dell'indice corrente
|
|
--------------------------------------------------------------------------*/
|
|
long DB_index_next(int handle)
|
|
{
|
|
TAG4 *t;
|
|
|
|
if(dbdata[handle]==0) return(-1);
|
|
if ((t=d4tag_default(dbdata[handle]))==NULL) return(-1);
|
|
|
|
return(t4skip(t,1L));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Restituisce la chiave corrente
|
|
--------------------------------------------------------------------------*/
|
|
|
|
char* DB_index_getkey(int handle)
|
|
{
|
|
TAG4 *t;
|
|
static char key[MAXLEN];
|
|
int klen;
|
|
|
|
if(dbdata[handle]==0) return(NULL);
|
|
if ((t=d4tag_default(dbdata[handle]))==NULL) return(NULL);
|
|
klen=expr4key_len(t->expr);
|
|
if (klen > (MAXLEN-1)) klen=MAXLEN-1;
|
|
memcpy(key,t4key(t),klen); /* t4key non restituisce una null terminated string */
|
|
key[klen]='\0';
|
|
return(key);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Restituisce vero se l'indice e' alla fine
|
|
--------------------------------------------------------------------------*/
|
|
|
|
int DB_index_eof(int handle)
|
|
{
|
|
TAG4 *t;
|
|
|
|
if(dbdata[handle]==0) return(-1);
|
|
if ((t=d4tag_default(dbdata[handle]))==NULL) return(-1);
|
|
return(t4eof(t));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Blocca il record indicato
|
|
--------------------------------------------------------------------------*/
|
|
|
|
int DB_lock_rec(int handle,long nrec)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
if(d4lock(dbdata[handle],nrec)==r4locked) return(-1);
|
|
else return(0);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Ritorna vero(non zero) se il file dati od indice sono stati bloccati
|
|
in modo esclusivo dalla presente applicazione, non da altri programmi!!!
|
|
--------------------------------------------------------------------------*/
|
|
|
|
|
|
int DB_file_locked(int handle)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return(d4lock_test_file(dbdata[handle]) + d4lock_test_index(dbdata[handle]));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Ritorna vero se il record nrec e' bloccato dalla presente applicazione,
|
|
non da altri programmi!!!
|
|
--------------------------------------------------------------------------*/
|
|
|
|
int DB_rec_locked(int handle,long nrec)
|
|
{
|
|
if(dbdata[handle]==0) return(-1);
|
|
return(d4lock_test(dbdata[handle],nrec));
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
restituisce la configurazione della libreria
|
|
--------------------------------------------------------------------------*/
|
|
|
|
long DB_getconf()
|
|
{
|
|
return(u4switch());
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
Restituisce il numero di versione scritto sull'header dell'indice
|
|
--------------------------------------------------------------------------*/
|
|
|
|
long DB_changed(int handle)
|
|
{
|
|
INDEX4 *i;
|
|
char fn[64];
|
|
|
|
if(dbdata[handle]==0) return(-1);
|
|
if (u4switch() & 2 || u4switch() & 8) /* Clipper & DBIII */
|
|
u4name_piece(fn,64,dbdata[handle]->file.name,0,0);
|
|
else
|
|
strcpy(fn,dbdata[handle]->file.name);
|
|
i=d4index(dbdata[handle],fn);
|
|
if (i == NULL) return(-1);
|
|
|
|
return(i4changed(i));
|
|
}
|
|
|
|
char* DB_memoptr( const int handle, const char * fieldname )
|
|
{
|
|
FIELD4 * f;
|
|
f = d4field( dbdata[ handle ], ( char *)fieldname );
|
|
return f4memo_ptr( f );
|
|
}
|
|
|
|
int DB_memowrite( const int handle, const char * fieldname, const char * data )
|
|
{
|
|
int ret;
|
|
|
|
FIELD4 * f;
|
|
f = d4field( dbdata[ handle ], fieldname );
|
|
ret = f4memo_assign( f, ( char * )data );
|
|
d4flush_data( dbdata[ handle ] );
|
|
return ret;
|
|
}
|
|
|