📄 cursor.h
字号:
/**
* Set destination for selected record
* rec - buffer to which fields of current record will be fetched
*/
void setRecord(void* rec) {
record = (byte*)rec;
}
/**
* Get pointer to the location where fields of the current record are fetched
* @return pointer to the memory location set by cursor constructor or setRecord method
*/
void* getRecord() {
return record;
}
/**
* Check if record with specified OID is in selection
* @return <code>true</code> if record with such OID was selected
*/
bool isInSelection(oid_t oid);
/**
* Fetch current record.
* You should use this method only if prefetch mode is disabled
*/
void fetch() {
assert(!(db->currIndex[currId]
& (dbInternalObjectMarker|dbFreeHandleMarker)));
table->columns->fetchRecordFields(record,
(byte*)db->getRow(currId));
}
/**
* Check if there is more records in the selection
*/
bool hasNext() const;
protected:
dbDatabase* db;
dbTableDescriptor* table;
dbCursorType type;
dbCursorType defaultType;
dbSelection selection;
bool allRecords;
oid_t firstId;
oid_t lastId;
oid_t currId;
byte* record;
size_t limit;
int4* bitmap; // bitmap to avoid duplicates
size_t bitmapSize;
bool eliminateDuplicates;
bool checkForDuplicatedIsEnabled;
bool prefetch;
bool removed; // current record was removed
bool lastRecordWasDeleted; //last record was deleted
size_t stmtLimitStart;
size_t stmtLimitLen;
size_t nSkipped;
void* paramBase;
void checkForDuplicates();
void deallocateBitmap();
bool isMarked(oid_t oid) {
return bitmap != NULL && (bitmap[oid >> 5] & (1 << (oid & 31))) != 0;
}
void setStatementLimit(dbQuery const& q) {
stmtLimitStart = q.stmtLimitStartPtr != NULL ? (nat4)*q.stmtLimitStartPtr : q.stmtLimitStart;
stmtLimitLen = q.stmtLimitLenPtr != NULL ? (nat4)*q.stmtLimitLenPtr : q.stmtLimitLen;
}
void truncateSelection() {
selection.truncate(stmtLimitStart, stmtLimitLen);
}
void mark(oid_t oid) {
if (bitmap != NULL) {
bitmap[oid >> 5] |= 1 << (oid & 31);
}
}
bool add(oid_t oid) {
if (selection.nRows < limit && selection.nRows < stmtLimitLen) {
if (nSkipped < stmtLimitStart) {
nSkipped += 1;
return true;
}
if (eliminateDuplicates) {
if (bitmap[oid >> 5] & (1 << (oid & 31))) {
return true;
}
bitmap[oid >> 5] |= 1 << (oid & 31);
}
selection.add(oid);
return selection.nRows < limit;
}
return false;
}
byte* fetchNext();
byte* fetchPrev();
bool gotoNext();
bool gotoPrev();
bool gotoFirst();
bool gotoLast();
bool moveNext();
bool movePrev();
void setCurrent(dbAnyReference const& ref);
void adjustReferences(size_t base, size_t size, long shift) {
if (currId != 0 && record != NULL) {
table->columns->adjustReferences(record, base, size, shift);
}
}
dbAnyCursor(dbTableDescriptor& aTable, dbCursorType aType, byte* rec)
: table(&aTable),type(aType),defaultType(aType),
allRecords(false),currId(0),record(rec)
{
db = aTable.db;
limit = dbDefaultSelectionLimit;
prefetch = rec != NULL;
removed = false;
bitmap = NULL;
bitmapSize = 0;
eliminateDuplicates = false;
checkForDuplicatedIsEnabled = true;
paramBase = NULL;
stmtLimitLen = dbDefaultSelectionLimit;
stmtLimitStart = 0;
nSkipped = 0;
}
public:
dbAnyCursor()
: table(NULL),type(dbCursorViewOnly),defaultType(dbCursorViewOnly),
allRecords(false),currId(0),record(NULL)
{
limit = dbDefaultSelectionLimit;
prefetch = false;
removed = false;
bitmap = NULL;
bitmapSize = 0;
eliminateDuplicates = false;
checkForDuplicatedIsEnabled = true;
db = NULL;
paramBase = NULL;
stmtLimitLen = dbDefaultSelectionLimit;
stmtLimitStart = 0;
nSkipped = 0;
}
~dbAnyCursor();
};
/**
* Cursor template parameterized by table class
*/
template<class T>
class dbCursor : public dbAnyCursor {
private:
// It is not possible to copy cursors
dbCursor<T> operator = (dbCursor<T> const& src) {
return *this;
}
// StoreAge (Itay): block this too
dbCursor(dbCursor<T> const& src) {assert(0);}
protected:
T record;
public:
/**
* Cursor constructor
* @param type cursor type (dbCursorViewOnly by default)
*/
dbCursor(dbCursorType type = dbCursorViewOnly)
: dbAnyCursor(T::dbDescriptor, type, (byte*)&record) {}
/**
* Cursor constructor with explicit specification of database.
* This cursor should be used for unassigned tables.
* @param aDb database in which table lookup is performed
* @param type cursor type (dbCursorViewOnly by default)
*/
dbCursor(dbDatabase* aDb, dbCursorType type = dbCursorViewOnly)
: dbAnyCursor(T::dbDescriptor, type, (byte*)&record)
{
db = aDb;
dbTableDescriptor* theTable = db->lookupTable(table);
if (theTable != NULL) {
table = theTable;
}
}
/**
* Get pointer to the current record
* @return pointer to the current record or <code>NULL</code> if there is no current record
*/
T* get() {
return currId == 0 ? (T*)NULL : &record;
}
/**
* Get next record
* @return pointer to the next record or <code>NULL</code> if there is no next record
*/
T* next() {
return (T*)fetchNext();
}
/**
* Get previous record
* @return pointer to the previous record or <code>NULL</code> if there is no previous record
*/
T* prev() {
return (T*)fetchPrev();
}
/**
* Get pointer to the first record
* @return pointer to the first record or <code>NULL</code> if no records were selected
*/
T* first() {
if (gotoFirst()) {
fetch();
return &record;
}
return NULL;
}
/**
* Get pointer to the last record
* @return pointer to the last record or <code>NULL</code> if no records were selected
*/
T* last() {
if (gotoLast()) {
fetch();
return &record;
}
return NULL;
}
/**
* Position cursor on the record with the specified OID
* @param ref reference to the object
* @return poistion of the record in the selection or -1 if record with such OID is not in selection
*/
int seek(dbReference<T> const& ref) {
return dbAnyCursor::seek(ref.getOid());
}
/**
* Overloaded operator for accessing components of the current record
* @return pointer to the current record
*/
T* operator ->() {
assert(currId != 0);
return &record;
}
/**
* Select record by reference
* @param ref reference to the record
* @return pointer to the referenced record
*/
T* at(dbReference<T> const& ref) {
setCurrent(ref);
return &record;
}
/**
* Convert selection to array of reference
* @param arr [OUT] array of refeences in which references to selected recrods will be placed
*/
void toArray(dbArray< dbReference<T> >& arr) const {
arr.resize(selection.nRows);
toArrayOfOid((oid_t*)arr.base());
}
/**
* Get current object idenitifer
* @return reference to the current record
*/
dbReference<T> currentId() const {
return dbReference<T>(currId);
}
/**
* Check if record with specified OID is in selection
* @return <code>true</code> if record with such OID was selected
*/
bool isInSelection(dbReference<T>& ref) {
return dbAnyCursor::isInSelection(ref.getOid());
}
};
class dbParallelQueryContext {
public:
dbDatabase* const db;
dbCompiledQuery* const query;
oid_t firstRow;
dbTable* table;
dbAnyCursor* cursor;
dbSelection selection[dbMaxParallelSearchThreads];
void search(int i);
dbParallelQueryContext(dbDatabase* aDb, dbTable* aTable,
dbCompiledQuery* aQuery, dbAnyCursor* aCursor)
: db(aDb), query(aQuery), firstRow(aTable->firstRow), table(aTable), cursor(aCursor) {}
};
extern char* strupper(char* s);
extern char* strlower(char* s);
END_FASTDB_NAMESPACE
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -