Richiesta 95/5.
Aggiunta classe TSorted_cursor git-svn-id: svn://10.65.10.50/trunk@1671 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
da954db822
commit
348d8cf9a1
@ -1,4 +1,4 @@
|
||||
// $Id: relation.cpp,v 1.54 1995-07-13 09:48:22 guy Exp $
|
||||
// $Id: relation.cpp,v 1.55 1995-08-03 14:55:26 angelo Exp $
|
||||
// relation.cpp
|
||||
// fv 12/8/93
|
||||
// relation class for isam files
|
||||
@ -909,7 +909,8 @@ TRecnotype TCursor::update()
|
||||
{
|
||||
main_app().begin_wait();
|
||||
|
||||
file().setkey(_nkey);
|
||||
file().setkey(_nkey);
|
||||
if (file().curr().empty()) file().curr().zero();
|
||||
file().read(_isgteq);
|
||||
const TRecnotype totrec = buildcursor(file().recno());
|
||||
|
||||
@ -1163,6 +1164,263 @@ bool TCursor::is_first_match(int ln)
|
||||
(_pos == 0 && file().good()) : (_if->is_first_match(ln));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// TSorted_cursor
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct {
|
||||
char f[512];
|
||||
TRecnotype p;
|
||||
} El_To_Sort;
|
||||
|
||||
bool TSorted_cursor::check_expr(TString& s)
|
||||
// Controlla la validita' dell'espressione ritornando un bool
|
||||
// Modifica l'espressione in modo da avere una valido parametro per TFieldref!
|
||||
// Es. UPPER(20->RAGSOC[1,40]+) ==> 20->RAGSOC[1,40]+
|
||||
// N.B. : la direzione dell'ordinamento va messa indicata sempre dopo la definizione del campo, mai
|
||||
// dopo l'operatore UPPER(). E' a cura delle altre funzioni esterne che utilizzano la check_expr()
|
||||
// discriminare il segno + o - che sia
|
||||
{
|
||||
int p=s.find('(');
|
||||
int p1=s.find(')');
|
||||
int rt=TRUE;
|
||||
|
||||
if (p>-1 && p1>-1)
|
||||
if (s.find("UPPER") == -1)
|
||||
{
|
||||
error_box("Only UPPER() operator is allowed");
|
||||
rt=FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
s=s.mid(6,s.len()-7);
|
||||
p=s.find('(');
|
||||
p1=s.find(')');
|
||||
if (p>-1 || p1 >-1)
|
||||
{
|
||||
error_box("Too many parentheses!");
|
||||
rt=FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((p>-1 && p1==-1) || (p==-1 && p1>-1))
|
||||
{
|
||||
error_box("Unbalanced parentheses in expression");
|
||||
rt=FALSE;
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
bool TSorted_cursor::is_upper(TString& s)
|
||||
// Controlla se nell'espressione esiste l'operatore UPPER()
|
||||
{
|
||||
bool rt=TRUE;
|
||||
if (s.find("UPPER")>-1)
|
||||
rt=check_expr(s);
|
||||
else
|
||||
rt=FALSE;
|
||||
return rt;
|
||||
}
|
||||
|
||||
TRecnotype TSorted_cursor::buildcursor(TRecnotype rp)
|
||||
{
|
||||
TRecnotype oldrecno=0,pos,ap = 0;
|
||||
int abspos=0,junk, l, pagecnt = 0;
|
||||
const bool filtered = has_filter();
|
||||
TString s;
|
||||
El_To_Sort * Element;
|
||||
|
||||
_order_expr.restart();
|
||||
while ((s=_order_expr.get()) && s.not_empty())
|
||||
{
|
||||
check_expr(s); // Toglie l'eventuale operatore UPPER(), in modo che l'ultimo carattere
|
||||
// indichi eventualmente la direzione dell'ordinamento
|
||||
char versus = (s.right(1)=="-") ? 'd' : 'a';
|
||||
if (s.right(1) == "-" || s.right(1) == "+")
|
||||
s.cut(s.len()-1);
|
||||
TFieldref f(s,0);
|
||||
// Il controllo del file e' automatico in f.len()
|
||||
_sort->addsortkey(abspos+f.from(),f.len(relation()->curr()),versus);
|
||||
CHECKS(f.len(relation()->curr())!=0,"Field can not have null length: ",(const char *) s);
|
||||
int lf = (f.file()!=0 ? f.file() : file().num());
|
||||
TRectype r(lf);
|
||||
abspos+=r.length(f.name());
|
||||
CHECKD(abspos<=512,"Cannot exceed 512 bytes-key %d",abspos);
|
||||
}
|
||||
|
||||
_sort->init();
|
||||
|
||||
FILE* _f = open_index(TRUE);
|
||||
|
||||
if (DB_reccount(file().filehnd()->fhnd) == 0)
|
||||
{
|
||||
fclose(_f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fseek(_f, 0L, SEEK_SET);
|
||||
|
||||
l = strlen(to());
|
||||
junk=DB_index_seek(file().filehnd()->fhnd, (char*)(const char*) from());
|
||||
if (junk < 0) junk=get_error(junk);
|
||||
if (junk == _iseof) return 0;
|
||||
|
||||
TRecnotype* page = new TRecnotype [CMAXELPAGE];
|
||||
pos = DB_index_recno(file().filehnd()->fhnd);
|
||||
TCursor::pos()=-1;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (DB_index_eof(file().filehnd()->fhnd)) break;
|
||||
const char* s0 = DB_index_getkey(file().filehnd()->fhnd);
|
||||
const TRecnotype recno = DB_index_recno(file().filehnd()->fhnd);
|
||||
if (l && (strncmp(to(), s0, l) < 0)) break;
|
||||
if (recno == oldrecno) break; // means that no more keys are available
|
||||
oldrecno=recno;
|
||||
if (pagecnt == CMAXELPAGE)
|
||||
{
|
||||
pagecnt = filtercursor(pagecnt,page);
|
||||
for (int i= 0; i< pagecnt; i++)
|
||||
if (page[i] == rp)
|
||||
{
|
||||
TCursor::pos() = ap + i;
|
||||
break;
|
||||
}
|
||||
ap += pagecnt;
|
||||
pagecnt = 0;
|
||||
}
|
||||
page[pagecnt++] = recno;
|
||||
DB_index_next(file().filehnd()->fhnd);
|
||||
int rt=get_error(-1);
|
||||
if (rt != NOERR)
|
||||
fatal_box("Can't read index n. %d - file n. %d",DB_tagget(file().filehnd()->fhnd),file().filehnd()->ln);
|
||||
} // while
|
||||
if (pagecnt)
|
||||
{
|
||||
pagecnt = filtercursor(pagecnt, page);
|
||||
for (int i = 0; i < pagecnt; i++)
|
||||
if (page[i] == rp)
|
||||
{
|
||||
TCursor::pos() = ap + i;
|
||||
break;
|
||||
}
|
||||
ap += pagecnt;
|
||||
}
|
||||
_sort->endsort();
|
||||
pagecnt=0;
|
||||
while ((Element=(El_To_Sort *)_sort->retrieve()) != NULL)
|
||||
{
|
||||
page[pagecnt++]=Element->p;
|
||||
if (pagecnt==CMAXELPAGE)
|
||||
{
|
||||
fwrite(page,sizeof(TRecnotype),pagecnt,_f);
|
||||
pagecnt=0;
|
||||
}
|
||||
}
|
||||
if (pagecnt)
|
||||
fwrite(page,sizeof(TRecnotype),pagecnt,_f);
|
||||
if (TCursor::pos() == -1) pos=0;
|
||||
delete page;
|
||||
fclose (_f);
|
||||
return ap;
|
||||
}
|
||||
|
||||
int TSorted_cursor::filtercursor(int pagecnt, TRecnotype* page)
|
||||
{
|
||||
|
||||
int np=0, handle=file().filehnd()->fhnd;
|
||||
TRectype& rec=file().curr();
|
||||
TString s;
|
||||
El_To_Sort Element;
|
||||
|
||||
for (int i=0; i< pagecnt; i++)
|
||||
{
|
||||
file().readat(rec,page[i]);
|
||||
if (update_relation()) relation()->update();
|
||||
if ((filterfunction() ? filterfunction()(relation()) : TRUE ) &&
|
||||
(expression() ? __evalcondition(relation(), expression()) : TRUE))
|
||||
{
|
||||
if (np < i) page[np] = page[i];
|
||||
np++;
|
||||
|
||||
_order_expr.restart();
|
||||
strcpy(Element.f,"");
|
||||
while ((s=_order_expr.get()) && s.not_empty())
|
||||
{
|
||||
bool is_up=is_upper(s);
|
||||
int p=s.find('[');// Qui estrae il nome del campo:
|
||||
if (p>-1) // rimane solo l'indicazione del file (eventuale)
|
||||
s.cut(p); // ed il nome del campo:
|
||||
else // UPPER(20->RAGSOC[1,30]+) ===>> 20->RAGSOC
|
||||
if (s.right(1) == "-" || s.right(1) == "+")
|
||||
s.cut(s.len()-1);
|
||||
TFieldref f(s,0);
|
||||
TString sf=f.read(relation());
|
||||
bool is_date = file(f.file()).curr().type(s) ==_datefld;
|
||||
if (is_date) // Se il campo e' di tipo data, la converte in ANSI!
|
||||
{
|
||||
TDate d(sf);
|
||||
sf=d.string(ANSI);
|
||||
}
|
||||
if (is_up) sf.upper();
|
||||
TString fmt;
|
||||
fmt.format("%%-%ds",f.len(rec));
|
||||
strcat(Element.f,(const char*)sf.format((const char *)fmt,(const char *)sf));
|
||||
}
|
||||
Element.p=page[i];
|
||||
_sort->sort((char *) &Element);
|
||||
}
|
||||
}
|
||||
|
||||
return np;
|
||||
}
|
||||
|
||||
bool TSorted_cursor::changed()
|
||||
{
|
||||
bool rt;
|
||||
|
||||
if (_is_valid_expr)
|
||||
{
|
||||
rt = TCursor::changed();
|
||||
if (!rt) rt=_is_changed_expr;
|
||||
_is_changed_expr = FALSE;
|
||||
} else
|
||||
{
|
||||
error_box("Can't perform changed() while expression ain't valid!");
|
||||
rt=FALSE;
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
|
||||
void TSorted_cursor::change_order(const char* order_expr)
|
||||
{
|
||||
if (order_expr && *order_expr && order_expr != _order_expr)
|
||||
{
|
||||
TString s;
|
||||
_order_expr = order_expr;
|
||||
_order_expr.restart();
|
||||
while ((s=_order_expr.get()) && s.not_empty() && (_is_valid_expr=check_expr(s))) ;
|
||||
if (_is_valid_expr)
|
||||
_is_changed_expr=TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
TSorted_cursor::TSorted_cursor(TRelation *f, const char * order_expr, const char * filter, int key, const TRectype* from, const TRectype* to)
|
||||
: TCursor(f,filter,key,from,to)
|
||||
{
|
||||
change_order(order_expr);
|
||||
_sort = new TSort(sizeof(El_To_Sort));
|
||||
}
|
||||
|
||||
TSorted_cursor::~TSorted_cursor()
|
||||
{
|
||||
if (_sort) delete _sort;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// TFieldRef
|
||||
///////////////////////////////////////////////////////////
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: relation.h,v 1.22 1995-07-03 07:49:25 angelo Exp $ */
|
||||
/* $Id: relation.h,v 1.23 1995-08-03 14:55:31 angelo Exp $ */
|
||||
// join.h
|
||||
// fv 12/8/93
|
||||
// join class for isam files
|
||||
@ -10,6 +10,10 @@
|
||||
#include <isam.h>
|
||||
#endif
|
||||
|
||||
#ifndef __SORT_H
|
||||
#include <sort.h>
|
||||
#endif
|
||||
|
||||
class TRelation : public TObject
|
||||
{
|
||||
friend class TRelationdef;
|
||||
@ -256,6 +260,38 @@ public:
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Classe TSorted_cursor. Costruisce e gestisce un cursore ordinato per chiavi diverse da quelle specificate nel file.
|
||||
// Il formato dell'espressione deve essere: [LF->]FIELDNAME[[from,to]][+|-]... Inoltre tutta l'espressione puo' essere racchiusa
|
||||
// dall'operatore UPPER(), per controlli non case-sensitive.
|
||||
// FIELDNAME e' il nome del campo per quale si vuole effettuare il sort, LF indica il numero logico del file(appartenente alla relazione!).
|
||||
// from e to sono parametri opzionali usati per specificare un sottocampo. Per default prende l'intera lunghezza.
|
||||
// + e - sono parametri opzionali usati per specificare il tipo di ordinamento: + significa crescente, - significa
|
||||
// decrescente. Per default l'ordinamento e' +(crescente). E' cosi' possibile creare chiavi con campi non appartententi al
|
||||
// file principale della relazione.
|
||||
// Es. "CODCF-|TIPOCF|SOTTOCONTO+|UPPER(20->RAGSOC[1,40]-)"
|
||||
|
||||
class TSorted_cursor : public TCursor
|
||||
{
|
||||
TToken_string _order_expr;
|
||||
TSort *_sort;
|
||||
bool _is_changed_expr;
|
||||
bool _is_valid_expr;
|
||||
|
||||
protected:
|
||||
bool check_expr(TString& s); // Controlla il formato della singola espressione di un campo di sort
|
||||
bool is_upper(TString& s); // Controlla se la singola espressione contiene l'operatore UPPER(), ritornandone l'argomento
|
||||
virtual TRecnotype buildcursor(TRecnotype rp); // Vedi i TCursor
|
||||
virtual int filtercursor(int pagecnt, TRecnotype* page); // Vedi i TCursor
|
||||
virtual bool changed(); // Vedi i TCursor
|
||||
|
||||
public:
|
||||
void change_order(const char * order_expr); // Permette di cambiare l'ordinamento del cursore.
|
||||
TSorted_cursor(TRelation *f,const char * order_expr, const char * filter = "", int key = 1, const TRectype* from = NULL, const TRectype* to = NULL);
|
||||
virtual ~TSorted_cursor();
|
||||
};
|
||||
|
||||
|
||||
// Classe TFieldref : public TObject
|
||||
|
||||
class TFieldref : public TObject
|
||||
|
Loading…
x
Reference in New Issue
Block a user