📄 cursor.cpp
字号:
}
return selection.nRows;
}
int dbAnyCursor::seek(oid_t oid)
{
int pos = 0;
if (gotoFirst()) {
do {
if (currId == oid) {
if (prefetch) {
fetch();
}
return pos;
}
pos += 1;
} while (gotoNext());
}
return -1;
}
bool dbAnyCursor::skip(int n) {
while (n > 0) {
if (!gotoNext()) {
return false;
}
n -= 1;
}
while (n < 0) {
if (!gotoPrev()) {
return false;
}
n += 1;
}
if (prefetch) {
fetch();
}
return true;
}
int dbAnyCursor::selectByKeyRange(char const* key, void const* minValue,
void const* maxValue)
{
dbFieldDescriptor* field = table->find(key);
assert(field != NULL);
assert(field->tTree != 0);
reset();
db->beginTransaction(type == dbCursorForUpdate
? dbDatabase::dbExclusiveLock : dbDatabase::dbSharedLock);
db->threadContext.get()->cursors.link(this);
dbSearchContext sc;
sc.db = db;
sc.probes = 0;
sc.offs = field->dbsOffs;
sc.cursor = this;
sc.condition = NULL;
sc.prefixLength = 0;
sc.firstKey = (char*)minValue;
sc.lastKey = (char*)maxValue;
sc.firstKeyInclusion = sc.lastKeyInclusion = true;
sc.comparator = field->comparator;
sc.sizeofType = field->dbsSize;
sc.type = field->type;
dbTtree::find(db, field->tTree, sc);
if (gotoFirst() && prefetch) {
fetch();
}
return selection.nRows;
}
void dbAnyCursor::remove()
{
oid_t removedId = currId;
lastRecordWasDeleted = false;
if (removedId == 0) {
db->handleError(dbDatabase::NullReferenceError, "Attempt to remove unexisted record");
}
assert(type == dbCursorForUpdate && removedId != 0);
if (allRecords) {
dbRecord* rec = db->getRow(removedId);
oid_t nextId = rec->next;
oid_t prevId = rec->prev;
if (nextId != 0) {
if (currId == firstId) {
firstId = currId = nextId;
} else {
currId = nextId;
}
} else {
lastRecordWasDeleted = true;
if (removedId == firstId) {
firstId = lastId = currId = 0;
} else {
lastId = currId = prevId;
}
}
} else {
if (selection.curr != NULL) {
if (--selection.curr->nRows == 0 || selection.pos == selection.curr->nRows) {
dbSelection::segment* next = selection.curr->next;
dbSelection::segment* prev = selection.curr->prev;
if (selection.curr->nRows == 0) {
if (prev != NULL) {
prev->next = next;
} else {
selection.first = next;
}
if (next != NULL) {
next->prev = prev;
} else {
selection.last = prev;
}
delete selection.curr;
}
if (next != NULL) {
currId = next->rows[0];
selection.curr = next;
selection.pos = 0;
} else {
lastRecordWasDeleted = true;
if ((selection.curr = selection.last) != NULL) {
selection.pos = selection.curr->nRows-1;
currId = selection.curr->rows[selection.pos];
} else {
currId = 0;
}
}
} else {
memcpy(selection.curr->rows + selection.pos,
selection.curr->rows + selection.pos + 1,
(selection.curr->nRows - selection.pos)
*sizeof(oid_t));
currId = selection.curr->rows[selection.pos];
}
} else {
currId = 0;
}
}
byte* saveRecord = record;
record = NULL;
db->remove(table, removedId);
record = saveRecord;
removed = true;
if (currId != 0 && prefetch) {
fetch();
}
}
void dbAnyCursor::removeAllSelected()
{
assert(type == dbCursorForUpdate);
byte* saveRecord = record;
record = NULL;
if (allRecords) {
removeAll();
} else if (selection.first != NULL) {
dbSelection::segment* curr;
for (curr = selection.first; curr != NULL; curr = curr->next) {
for (int i = 0, n = curr->nRows; i < n; i++) {
db->remove(table, curr->rows[i]);
}
}
reset();
} else if (currId != 0) {
db->remove(table, currId);
currId = 0;
}
record = saveRecord;
}
bool dbAnyCursor::hasNext() const
{
return allRecords
? currId != 0 && db->getRow(currId)->next != 0
: selection.curr != NULL && (selection.pos+1 < selection.curr->nRows || selection.curr->next != NULL);
}
byte* dbAnyCursor::fetchNext()
{
if (!removed) {
if (gotoNext()) {
fetch();
return record;
}
} else {
removed = false;
if (currId != 0 && !lastRecordWasDeleted) {
if (!prefetch) {
fetch();
}
return record;
}
}
return NULL;
}
byte* dbAnyCursor::fetchPrev()
{
if (removed) {
removed = false;
if (lastRecordWasDeleted) {
if (currId != 0) {
if (!prefetch) {
fetch();
}
return record;
}
return NULL;
}
}
if (gotoPrev()) {
fetch();
return record;
}
return NULL;
}
bool dbAnyCursor::moveNext()
{
if (!removed) {
return gotoNext();
} else {
removed = false;
return !lastRecordWasDeleted;
}
}
bool dbAnyCursor::movePrev()
{
if (!removed) {
return gotoPrev();
} else {
removed = false;
return lastRecordWasDeleted ? (currId != 0) : gotoPrev();
}
}
bool dbAnyCursor::gotoNext()
{
removed = false;
if (allRecords) {
if (currId != 0) {
oid_t next = db->getRow(currId)->next;
if (next != 0) {
currId = next;
return true;
}
}
} else if (selection.curr != NULL) {
if (++selection.pos == selection.curr->nRows) {
if (selection.curr->next == NULL) {
selection.pos -= 1;
return false;
}
selection.pos = 0;
selection.curr = selection.curr->next;
}
currId = selection.curr->rows[selection.pos];
return true;
}
return false;
}
bool dbAnyCursor::isLast() const
{
if (allRecords) {
if (currId != 0) {
return db->getRow(currId)->next == 0;
}
} else if (selection.curr != NULL) {
return selection.pos+1 == selection.curr->nRows
&& selection.curr->next == NULL;
}
return false;
}
bool dbAnyCursor::isFirst() const
{
if (allRecords) {
if (currId != 0) {
return db->getRow(currId)->prev == 0;
}
} else if (selection.curr != NULL) {
return selection.pos == 0
&& selection.curr->prev == NULL;
}
return false;
}
bool dbAnyCursor::gotoPrev()
{
removed = false;
if (allRecords) {
if (currId != 0) {
oid_t prev = db->getRow(currId)->prev;
if (prev != 0) {
currId = prev;
return true;
}
}
} else if (selection.curr != NULL) {
if (selection.pos == 0) {
if (selection.curr->prev == NULL) {
return false;
}
selection.curr = selection.curr->prev;
selection.pos = selection.curr->nRows;
}
currId = selection.curr->rows[--selection.pos];
return true;
}
return false;
}
bool dbAnyCursor::gotoFirst()
{
removed = false;
if (allRecords) {
currId = firstId;
return (currId != 0);
} else {
selection.curr = selection.first;
selection.pos = 0;
if (selection.curr == NULL) {
return (currId != 0);
} else {
currId = selection.curr->rows[0];
return true;
}
}
}
bool dbAnyCursor::gotoLast()
{
removed = false;
if (allRecords) {
currId = lastId;
return (currId != 0);
} else {
selection.curr = selection.last;
if (selection.curr == NULL) {
return (currId != 0);
} else {
selection.pos = selection.curr->nRows-1;
currId = selection.curr->rows[selection.pos];
return true;
}
}
}
#define BUILD_BITMAP_THRESHOLD 100
bool dbAnyCursor::isInSelection(oid_t oid)
{
dbSelection::segment* curr;
if (eliminateDuplicates) {
return isMarked(oid);
} else if (selection.nRows > BUILD_BITMAP_THRESHOLD) {
checkForDuplicates();
for (curr = selection.first; curr != NULL; curr = curr->next) {
for (int i = 0, n = curr->nRows; i < n; i++) {
oid_t o = curr->rows[i];
bitmap[o >> 5] |= 1 << (o & 31);
}
}
return isMarked(oid);
} else {
for (curr = selection.first; curr != NULL; curr = curr->next) {
for (int i = 0, n = curr->nRows; i < n; i++) {
if (curr->rows[i] == oid) {
return true;
}
}
}
return false;
}
}
void dbAnyCursor::reset()
{
if (db == NULL) {
db = table->db;
assert(((void)"cursor associated with online database table",
table->tableId != 0));
} else if (table->db != db) {
table = db->lookupTable(table);
}
unlink();
selection.reset();
eliminateDuplicates = false;
allRecords = false;
currId = 0;
removed = false;
}
void dbAnyCursor::freeze()
{
unlink();
}
void dbAnyCursor::unfreeze()
{
db->beginTransaction(type == dbCursorForUpdate
? dbDatabase::dbExclusiveLock : dbDatabase::dbSharedLock);
db->threadContext.get()->cursors.link(this);
if (currId != 0 && prefetch) {
fetch();
}
}
dbAnyCursor::~dbAnyCursor()
{
selection.reset();
delete[] bitmap;
}
void dbParallelQueryContext::search(int i)
{
int nThreads = db->parThreads;
oid_t oid = firstRow;
int j;
for (j = i; --j >= 0;) {
oid = db->getRow(oid)->next;
}
while (oid != 0) {
if (db->evaluate(query->tree, oid, table, cursor)) {
selection[i].add(oid);
}
oid = db->getRow(oid)->next;
for (j = nThreads; --j > 0 && oid != 0;) {
oid = db->getRow(oid)->next;
}
}
if (query->order != NULL) {
selection[i].sort(db, query->order);
}
}
char* strupper(char* s)
{
byte* p = (byte*)s;
while (*p != '\0') {
*p = toupper(*p);
p += 1;
}
return s;
}
char* strlower(char* s)
{
byte* p = (byte*)s;
while (*p != '\0') {
*p = (byte)tolower(*p);
p += 1;
}
return s;
}
END_FASTDB_NAMESPACE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -