class Query {
friend class StackOfQuery;
friend class StoredQuery;
public :
Query(const char* name = 0);
virtual void setName(const char* name);
virtual Result release();
virtual ~Query() {};
virtual Result
prepare(char* queryText,
Bool useAsIs = FALSE);
virtual Bool unprepare();
virtual Result
open(char* queryText, ...);
virtual Result
execute(char* queryText, ...);
virtual Result read(char* format,...);
virtual Bool fetch();
virtual Bool fetch(char* format,...);
virtual Result close() = 0;
virtual Result drop() = 0;
static Result
dropQuery(const char* name);
static Result
dropStack(const char* name);
// Field access methods
virtual char* getFieldName(int fldNo);
virtual int
getFieldNo(const char *fldName);
// ...
protected:
char queryName[QNAME_LEN];
short format[MAX_FIELDS_IN_QUERY];
short state;
DbSQLDA in;
DbSQLDA out;
SQLDA* out_sqlda;
DynArray* fieldByNameAccelerator;
static short nullind;
static short
typeToShort(char* ptr, int& size);
void getFormat(char* queryText);
// cache related functions
// ...
_read(char* format, va_list ap);
virtual Result openCursor() = 0;
char*
preRead(short& fieldNo, short& type,
char* ptr);
void
fillSQLDA(DbSQLDA& sqlda, va_list& ap);
virtual Result
setArg(MemBuf& dest, short type,
SQLVAR* var, va_list& ap);
virtual Result
getArg(DbSQLDA& sqlda, void* data,
short type, int i);
};
// === Implementation of Query class ===
// === storage methods ===
Result Query::store(char* text) {
return stackOfQuery.Add(*this,text);
}
// === Common Query methods ===
Query::Query(const char *name) {
state = 0;
if (name && *name)
setName(name);
else
sprintf(queryName,"_%p", this);
out_sqlda = NULL;
format[0] = Ft_Undefine;
fieldByNameAccelerator = 0;
// Accelerator will be created
// during first <getFieldNo> call
}
// === Query handling methods ===
Result Query::prepare(char* queryText,
Bool useAsIs) {
Bool needToBeStored = FALSE;
if (state & DQS_PREPARED)
return OK;
MemBuf clearQuery;
if (!useAsIs && queryText) {
clearQuery << queryText;
::getFormat(format,clearQuery);
queryText = clearQuery.getBuf();
}
else
format[0] = Ft_Stop;
if (state & DQS_CACHED)
switch (restore(queryText)) {
case FAIL : return FAIL;
case TRUE : return OK;
default : needToBeStored = TRUE;
}
if (_prepare(queryText) == FAIL)
return FAIL;
if (needToBeStored)
if (store(queryText) == FAIL)
return FAIL;
return OK;
}
Result Query::open(
char* queryText, ...) {
if (queryText)
getFormat(queryText);
va_list ap;
va_start(ap, queryText);
in.clear();
fillSQLDA(in,ap);
va_end(ap);
in.synchronize();
if (close() == FAIL)
return FAIL;
if (prepare(queryText) == FAIL)
return FAIL;
return _open(in,0);
}
Result Query::execute(
char* queryText, ...) {
if (prepare(queryText) == FAIL)
return FAIL;
va_list ap;
va_start(ap, queryText);
in.clear();
fillSQLDA(in,ap);
va_end(ap);
in.synchronize();
return _execute(in);
}
Bool Query::fetch(char* format, ...) {
Bool result = _fetch();
if (result == TRUE) {
va_list ap;
va_start(ap, format);
if (_read(format,ap) == FAIL)
result = FAIL;
va_end(ap);
}
return result;
}
Bool Query::fetch() {
return _fetch();
}
Result Query::read(char* format,...) {
va_list ap;
va_start(ap, format);
Result result = _read(format,ap);
va_end( ap );
return result;
}
// === Parameters treatment ===
void Query::fillSQLDA(DbSQLDA& sqlda,
va_list& ap) {
// Calculate number of input parameters
for (int argc = 0;
format[argc] != Ft_Stop; argc++);
sqlda.extend(argc);
SQLVAR var;
MemBuf dest(MemBuf::DATABASE_MODE);
for (argc = 0;
format[argc] != Ft_Stop;argc++) {
dest.flush();
var.sqlind = 0;
setArg(dest, format[argc], &var, ap);
var.sqllen = (var.sqlind == &nullind)
? 0 : dest.getLength();
if (var.sqllen > 0 &&
(var.sqltype & ~1) == SQL_FIXCHAR
&& format[argc] != Ft_Binary_)
var.sqllen--;
var.sqldata = dest.getBuf();
sqlda << &var;
}
}
Result Query::_read(char* format,
va_list ap) {
short fieldNo = -1;
for (char* ptr = strchr(format,'%');
ptr; ptr = strchr(ptr,'%')) {
short type = 0;
ptr = preRead(fieldNo,type,ptr);
void* data = va_arg(ap,void*);
if (getArg(out,data,type,fieldNo) ==
FAIL)
return FAIL;
}
return OK;
}
// === Format parsing system ===
char* Query::preRead(short& fieldNo,
short& type, char* ptr) {
fieldNo++; // Next field no by default
type = 0;
// Try to extract type
if (ptr[1] != '#' && ptr[1] != '('
&& ptr[1] != '%') {
int toSqueeze = 0;
type = typeToShort(ptr+1,toSqueeze);
ptr += toSqueeze;
}
switch (ptr[1]) {
case '#' : // pointed by ordinal
// number
sscanf(ptr+2,"%d",&fieldNo);
break;
case '(' : { // pointed by field name
char* tail = strchr(ptr+2,')');
char name[MAXSTR];
strncpy(name,ptr+2,
(int)(tail-ptr-2));
name[(int)(tail-ptr-2)] = 0;
fieldNo = getFieldNo(name);
break;
}
}
ptr++;
// Now we have fieldNo
if (type == 0)
switch (getFieldType(fieldNo)) {
case SQL_SHORT:
type = Ft_short_;
break;
case SQL_LONG:
type = Ft_long_;
break;
case SQL_FLOAT:
type = Ft_float_;
break;
case SQL_DOUBLE:
type = Ft_double_;
break;
case SQL_DATE:
type = Ft_Date_;
break;
default :
type = Ft_FString_;
break;
}
return ptr;
}
// === Common SQLDA access methods ===
// ...
//End of File