cursor.cpp

来自「FastDb是高效的内存数据库系统」· C++ 代码 · 共 1,098 行 · 第 1/2 页

CPP
1,098
字号
      {
        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.offs = field->dbsOffs;
  sc.cursor = this;
  sc.condition = NULL;
  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 (prefetch && gotoFirst())
  {
    fetch();
  }

  return selection.nRows;
}


void dbAnyCursor::remove
  ()
{
  oid_t removedId = currId;
  assert(type == dbCursorForUpdate && removedId != 0);
  updateInProgress = true;

  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
    {
      if (removedId == firstId)
      {
        firstId = lastId = currId = 0;
      }
      else
      {
        lastId = currId = prevId;
      }
    }
  }
  else
  {
    if (selection.curr != NULL)
    {
      if (--selection.curr->nRows == 0)
      {
        dbSelection::segment* next = selection.curr->next;

        if (selection.curr->prev != NULL)
        {
          selection.curr->prev->next = next;
        }
        else
        {
          selection.first = next;
        }

        if (next != NULL)
        {
          next->prev = selection.curr->prev;
          currId = next->rows[0];
          delete selection.curr;
          selection.curr = next;
          selection.pos = 0;
        }
        else
        {
          selection.last = selection.curr->prev;
          delete selection.curr;

          if ((selection.curr = selection.last) != NULL)
          {
            selection.pos = selection.curr->nRows-1;
            currId = selection.curr->rows[selection.pos];
          }
          else
          {
            currId = 0;
          }
        }
      }
      else
      {
        if (selection.pos < selection.curr->nRows)
        {
          memcpy(selection.curr->rows + selection.pos,
                 selection.curr->rows + selection.pos + 1,
                 (selection.curr->nRows - selection.pos)
                 *sizeof(oid_t));
        }
        else
        {
          selection.pos -= 1;
        }

        currId = selection.curr->rows[selection.pos];
      }
    }
    else
    {
      currId = 0;
    }
  }

  db->remove
  (table, removedId);

  removed = true;

  updateInProgress = false;

  if (currId != 0)
  {
    fetch();
  }
}


void dbAnyCursor::removeAllSelected()
{
  assert(type == dbCursorForUpdate);

  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;
  }
}


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()
{
  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()
{
  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;
  updateInProgress = false;
  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;
}






⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?