📄 query.h
字号:
//-< QUERY.H >-------------------------------------------------------*--------*
// FastDB Version 1.0 (c) 1999 GARRET * ? *
// (Main Memory Database Management System) * /\| *
// * / \ *
// Created: 20-Nov-98 K.A. Knizhnik * / [] \ *
// Last update: 10-Dec-98 K.A. Knizhnik * GARRET *
//-------------------------------------------------------------------*--------*
// Constructing and hashing database query statements
//-------------------------------------------------------------------*--------*
#ifndef __QUERY_H__
#define __QUERY_H__
BEGIN_FASTDB_NAMESPACE
/**
* Element of the query
*/
class FASTDB_DLL_ENTRY dbQueryElement {
friend class dbQuery;
friend class dbCompiler;
friend class dbQueryExpression;
friend class dbQueryElementAllocator;
friend class dbCLI;
public:
enum ElementType {
qExpression, // part of SQL expression
qVarBool,
qVarInt1,
qVarInt2,
qVarInt4,
qVarInt8,
qVarReal4,
qVarReal8,
qVarString,
qVarStringPtr,
qVarReference,
qVarRectangle,
qVarArrayOfRef,
qVarArrayOfInt4,
qVarArrayOfInt8,
qVarArrayOfRefPtr,
qVarArrayOfInt4Ptr,
qVarArrayOfInt8Ptr,
qVarRawData,
#ifdef USE_STD_STRING
qVarStdString,
#endif
qVarUnknown
};
ElementType getType() const { return type; }
dbQueryElement* nextElement() const { return next; }
void* operator new (size_t size EXTRA_DEBUG_NEW_PARAMS);
void operator delete(void* p EXTRA_DEBUG_NEW_PARAMS);
char* dump(char* buf);
char* dumpValues(char* buf);
dbQueryElement(ElementType t, void const* p,
dbTableDescriptor* table = NULL)
{
type = t;
ptr = p;
ref = table;
next = NULL;
}
private:
dbQueryElement* next;
void const* ptr;
ElementType type;
dbTableDescriptor* ref;
};
/**
* Allocator of query elements. This class links deallocated elements in the list of free elements,
* and reused them in future. So number of system memory allocator invocations is dramatically reduced.
* Cleanup of free elements lst is performed by <code>dbDatabase::cleanup()</code> method
*/
class FASTDB_DLL_ENTRY dbQueryElementAllocator {
friend class dbDatabase;
dbMutex mutex;
dbQueryElement* freeChain;
public:
void deallocate(dbQueryElement* first, dbQueryElement** lastNext) {
dbCriticalSection cs(mutex);
if (first != NULL) {
*lastNext = freeChain;
freeChain = first;
}
}
void* allocate(size_t size);
dbQueryElementAllocator();
~dbQueryElementAllocator();
void reset();
static dbQueryElementAllocator instance;
};
/**
* This class represents component of the structure.
* It is mostly needed for implementation of application specific database types. For example, look at
* <code>dbDate</code> class. It contains <code>int4 jday</code> component which stores time in seconds sinse 1970.
* This class defines its own comparison methods:
* <PRE>
* dbQueryExpression operator == (char const* field) {
* dbQueryExpression expr;
* expr = dbComponent(field,"jday"),"=",jday;
* return expr;
* }
* </PRE>
* Making it possible to sepcify queries like this (assume that record has column "released" with type dbDate:
* <PRE>
* dbQuery q;
* dbDate date;
* q = date == "released";
* </PRE>
*/
class FASTDB_DLL_ENTRY dbComponent {
public:
char const* structure;
char const* field;
dbComponent(char const* s, char const* f=NULL) : structure(s), field(f) {}
};
/**
* Class representing SubSQL expression.
* It is mostly needed for implementation of application specific database types.
* Look at the example in dbComponent class.
* The effect of addeing dbExpression to the query is the same as if this expresion is enclosed in parenthesis.
*/
class FASTDB_DLL_ENTRY dbQueryExpression {
friend class dbQuery;
dbQueryElement* first;
dbQueryElement** last;
bool operand;
public:
dbQueryExpression& add(dbQueryElement::ElementType type, void const* ptr, dbTableDescriptor* table = NULL) {
last = &(*last = new dbQueryElement(type, ptr, table))->next;
operand = (type == dbQueryElement::qExpression);
return *this;
}
dbQueryExpression& operator = (char const* ptr) {
first = NULL, last = &first;
return add(dbQueryElement::qExpression, ptr);
}
dbQueryExpression& operator = (dbComponent const& comp);
dbQueryExpression& operator = (dbQueryExpression const& expr);
dbQueryExpression& operator,(int1 const& ptr) {
return add(dbQueryElement::qVarInt1, &ptr);
}
dbQueryExpression& operator,(int2 const& ptr) {
return add(dbQueryElement::qVarInt2, &ptr);
}
dbQueryExpression& operator,(int4 const& ptr) {
return add(dbQueryElement::qVarInt4, &ptr);
}
dbQueryExpression& operator,(db_int8 const& ptr) {
return add(dbQueryElement::qVarInt8, &ptr);
}
dbQueryExpression& operator,(nat1 const& ptr) {
return add(dbQueryElement::qVarInt1, &ptr);
}
dbQueryExpression& operator,(nat2 const& ptr) {
return add(dbQueryElement::qVarInt2, &ptr);
}
dbQueryExpression& operator,(nat4 const& ptr) {
return add(dbQueryElement::qVarInt4, &ptr);
}
dbQueryExpression& operator,(db_nat8 const& ptr) {
return add(dbQueryElement::qVarInt8, &ptr);
}
#if SIZEOF_LONG != 8
dbQueryExpression& operator,(long const& ptr) {
return add(sizeof(long) == 4 ? dbQueryElement::qVarInt4 : dbQueryElement::qVarInt8, &ptr);
}
dbQueryExpression& operator,(unsigned long const& ptr) {
return add(sizeof(long) == 4 ? dbQueryElement::qVarInt4 : dbQueryElement::qVarInt8, &ptr);
}
#endif
dbQueryExpression& operator,(real4 const& ptr) {
return add(dbQueryElement::qVarReal4, &ptr);
}
dbQueryExpression& operator,(real8 const& ptr) {
return add(dbQueryElement::qVarReal8, &ptr);
}
dbQueryExpression& operator,(bool const& ptr) {
return add(dbQueryElement::qVarBool, &ptr);
}
dbQueryExpression& operator,(char const* ptr) {
return add(operand ? dbQueryElement::qVarString
: dbQueryElement::qExpression, ptr);
}
dbQueryExpression& operator,(char const** ptr) {
return add(dbQueryElement::qVarStringPtr, ptr);
}
dbQueryExpression& operator,(char** ptr) {
return add(dbQueryElement::qVarStringPtr, ptr);
}
dbQueryExpression& operator,(void const* ptr) {
return add(dbQueryElement::qVarRawData, ptr);
}
dbQueryExpression& operator,(rectangle const& rect) {
return add(dbQueryElement::qVarRectangle, &rect);
}
#ifdef USE_STD_STRING
dbQueryExpression& operator,(std::string const& str) {
return add(dbQueryElement::qVarStdString, &str);
}
#endif
dbQueryExpression& operator,(dbQueryExpression const& expr) {
*last = new dbQueryElement(dbQueryElement::qExpression, "(");
(*last)->next = expr.first;
last = expr.last;
*last = new dbQueryElement(dbQueryElement::qExpression, ")");
last = &(*last)->next;
operand = false;
return *this;
}
dbQueryExpression& operator,(dbComponent const& comp) {
add(dbQueryElement::qExpression, comp.structure);
if (comp.field != NULL) {
add(dbQueryElement::qExpression, ".");
add(dbQueryElement::qExpression, comp.field);
}
operand = false;
return *this;
}
dbQueryExpression& operator += (dbComponent const& comp) {
return *this,comp;
}
dbQueryExpression& operator += (char const* ptr) {
return add(dbQueryElement::qExpression, ptr);
}
#ifndef NO_MEMBER_TEMPLATES
template<class T>
dbQueryExpression& operator,(dbReference<T> const& value) {
return add(dbQueryElement::qVarReference, &value, &T::dbDescriptor);
}
template<class T>
inline dbQueryExpression& operator,(dbArray< dbReference<T> > const& value) {
return add(dbQueryElement::qVarArrayOfRef, &value, &T::dbDescriptor);
}
template<class T>
inline dbQueryExpression& operator,(dbArray< dbReference<T> >const* const& value) {
return add(dbQueryElement::qVarArrayOfRefPtr, &value, &T::dbDescriptor);
}
#endif
#if !defined(_MSC_VER) || _MSC_VER+0 >= 1300
inline dbQueryExpression& operator,(dbArray<db_int4> const& value) {
return add(dbQueryElement::qVarArrayOfInt4, &value);
}
inline dbQueryExpression& operator,(dbArray<db_int4>const* const& value) {
return add(dbQueryElement::qVarArrayOfInt4Ptr, &value);
}
inline dbQueryExpression& operator,(dbArray<db_int8> const& value) {
return add(dbQueryElement::qVarArrayOfInt8, &value);
}
inline dbQueryExpression& operator,(dbArray<db_int8>const* const& value) {
return add(dbQueryElement::qVarArrayOfInt8Ptr, &value);
}
#endif
};
class dbOrderByNode;
class dbFollowByNode;
/**
* Class used for precompiled queries
*/
class FASTDB_DLL_ENTRY dbCompiledQuery {
public:
dbExprNode* tree;
dbOrderByNode* order;
dbFollowByNode* follow;
dbTableDescriptor* table;
int schemeVersion;
size_t stmtLimitStart;
size_t stmtLimitLen;
int4* stmtLimitStartPtr;
int4* stmtLimitLenPtr;
bool limitSpecified;
enum IteratorInit {
StartFromAny,
StartFromFirst,
StartFromLast,
StartFromRef,
StartFromArray,
StartFromArrayPtr
};
IteratorInit startFrom;
void const* root;
void destroy();
bool compiled() { return tree != NULL; }
bool compileError() { return !compiled(); }
dbCompiledQuery() {
tree = NULL;
order = NULL;
follow = NULL;
table = NULL;
startFrom = StartFromAny;
limitSpecified = false;
}
};
/**
* Query class. It is derived from <code>dbCompiledQuery</code> class because each query is compiled only once - when
* it is executed first time. All subsequent executions of query used precompiled tree.
*/
class FASTDB_DLL_ENTRY dbQuery : public dbCompiledQuery {
friend class dbCompiler;
friend class dbDatabase;
friend class dbSubSql;
friend class dbCLI;
private:
dbMutex mutex;
dbQueryElement* elements;
dbQueryElement** nextElement;
bool operand;
bool mutexLocked;
//
// Prohibite query copying
//
dbQuery(dbQuery const&) : dbCompiledQuery() {}
dbQuery& operator =(dbQuery const&) { return *this; }
public:
int pos; // position of condition in statement
char* dump(char* buf) {
char* p = buf;
for (dbQueryElement* elem = elements; elem != NULL; elem = elem->next) {
p = elem->dump(p);
}
return buf;
}
char* dumpValues(char* buf) {
char* p = buf;
for (dbQueryElement* elem = elements; elem != NULL; elem = elem->next) {
p = elem->dumpValues(p);
}
return buf;
}
dbQuery& append(dbQueryElement::ElementType type, void const* ptr,
dbTableDescriptor* table = NULL)
{
nextElement = &(*nextElement=new dbQueryElement(type,ptr,table))->next;
operand = (type == dbQueryElement::qExpression);
return *this;
}
dbQuery& reset();
//
// Redefined operator = and , make it possible to specify query in the
// following way:
// int x, y;
// dbDataTime dt;
// dbQuery q;
// dbCursor<record> cursor;
// q = "x=",x,"and y=",y,"and",dt == "date";
// for (x = 0; x < max_x; x++) {
// for (y = 0; y < max_y; y++) {
// cursor.select(q);
// ...
// }
// }
dbQuery& add(dbQueryExpression const& expr);
dbQuery& And(dbQueryExpression const& expr) {
if (elements != NULL) {
append(dbQueryElement::qExpression, "and");
}
return add(expr);
}
dbQuery& Or(dbQueryExpression const& expr) {
if (elements != NULL) {
append(dbQueryElement::qExpression, "or");
}
return add(expr);
}
dbQuery& And(char const* str) {
if (elements != NULL) {
append(dbQueryElement::qExpression, "and");
}
return append(dbQueryElement::qExpression, str);
}
dbQuery& Or(char const* str) {
if (elements != NULL) {
append(dbQueryElement::qExpression, "or");
}
return append(dbQueryElement::qExpression, str);
}
dbQuery& add(char const* str) {
return append(operand ? dbQueryElement::qVarString
: dbQueryElement::qExpression, str);
}
dbQuery& add(char const** str) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -