database.cpp

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

CPP
2,469
字号
      res *= x;
    }

    x *= x;
    y >>= 1;
  }

  return res;
}

bool dbDatabase::evaluate(dbExprNode* expr, oid_t oid, dbTable* table, dbAnyCursor* cursor)
{
  dbInheritedAttribute iattr;
  dbSynthesizedAttribute sattr;
  iattr.db = this;
  iattr.oid = oid;
  iattr.table = table;
  iattr.record = (byte*)getRow(oid);
  iattr.paramBase = (size_t)cursor->paramBase;
  execute(expr, iattr, sattr);
  return sattr.bvalue != 0;
}

void _fastcall dbDatabase::execute(dbExprNode*             expr,
                                   dbInheritedAttribute&   iattr,
                                   dbSynthesizedAttribute& sattr)
{
  dbSynthesizedAttribute sattr2, sattr3;

  switch (expr->cop)
  {

  case dbvmVoid:
    sattr.bvalue = true; // empty condition
    return;

  case dbvmCurrent:
    sattr.oid = iattr.oid;
    return;

  case dbvmFirst:
    sattr.oid = iattr.table->firstRow;
    return;

  case dbvmLast:
    sattr.oid = iattr.table->lastRow;
    return;

  case dbvmLoadBool:
    execute(expr->operand[0], iattr, sattr);
    sattr.bvalue = *(bool*)(sattr.base+expr->offs);
    return;

  case dbvmLoadInt1:
    execute(expr->operand[0], iattr, sattr);
    sattr.ivalue = *(int1*)(sattr.base+expr->offs);
    return;

  case dbvmLoadInt2:
    execute(expr->operand[0], iattr, sattr);
    sattr.ivalue = *(int2*)(sattr.base+expr->offs);
    return;

  case dbvmLoadInt4:
    execute(expr->operand[0], iattr, sattr);
    sattr.ivalue = *(int4*)(sattr.base+expr->offs);
    return;

  case dbvmLoadInt8:
    execute(expr->operand[0], iattr, sattr);
    sattr.ivalue = *(db_int8*)(sattr.base+expr->offs);
    return;

  case dbvmLoadReal4:
    execute(expr->operand[0], iattr, sattr);
    sattr.fvalue = *(real4*)(sattr.base+expr->offs);
    return;

  case dbvmLoadReal8:
    execute(expr->operand[0], iattr, sattr);
    sattr.fvalue = *(real8*)(sattr.base+expr->offs);
    return;

  case dbvmLoadReference:
    execute(expr->operand[0], iattr, sattr);
    sattr.oid = *(oid_t*)(sattr.base+expr->offs);
    return;

  case dbvmLoadArray:

  case dbvmLoadString:
    execute(expr->operand[0], iattr, sattr2);
    sattr.array.base = (char*)sattr2.base
                       + ((dbVarying*)(sattr2.base + expr->offs))->offs;
    sattr.array.size = ((dbVarying*)(sattr2.base + expr->offs))->size;
    return;

  case dbvmLoadRawBinary:
    execute(expr->operand[0], iattr, sattr);
    sattr.raw = (void*)(sattr.base+expr->offs);
    return;

  case dbvmLoadSelfBool:
    sattr.bvalue = *(bool*)(iattr.record+expr->offs);
    return;

  case dbvmLoadSelfInt1:
    sattr.ivalue = *(int1*)(iattr.record+expr->offs);
    return;

  case dbvmLoadSelfInt2:
    sattr.ivalue = *(int2*)(iattr.record+expr->offs);
    return;

  case dbvmLoadSelfInt4:
    sattr.ivalue = *(int4*)(iattr.record+expr->offs);
    return;

  case dbvmLoadSelfInt8:
    sattr.ivalue = *(db_int8*)(iattr.record+expr->offs);
    return;

  case dbvmLoadSelfReal4:
    sattr.fvalue = *(real4*)(iattr.record+expr->offs);
    return;

  case dbvmLoadSelfReal8:
    sattr.fvalue = *(real8*)(iattr.record+expr->offs);
    return;

  case dbvmLoadSelfReference:
    sattr.oid = *(oid_t*)(iattr.record+expr->offs);
    return;

  case dbvmLoadSelfArray:

  case dbvmLoadSelfString:
    sattr.array.base = (char*)iattr.record +
                       ((dbVarying*)(iattr.record + expr->offs))->offs;
    sattr.array.size = ((dbVarying*)(iattr.record + expr->offs))->size;
    return;

  case dbvmLoadSelfRawBinary:
    sattr.raw = (void*)(iattr.record+expr->offs);
    return;

  case dbvmInvokeMethodBool:
    execute(expr->ref.base, iattr, sattr);
    expr->ref.field->method->invoke(sattr.base, &sattr.bvalue);
    sattr.bvalue = *(bool*)&sattr.bvalue;
    return;

  case dbvmInvokeMethodInt1:
    execute(expr->ref.base, iattr, sattr);
    expr->ref.field->method->invoke(sattr.base, &sattr.ivalue);
    sattr.ivalue = *(int1*)&sattr.ivalue;
    return;

  case dbvmInvokeMethodInt2:
    execute(expr->ref.base, iattr, sattr);
    expr->ref.field->method->invoke(sattr.base, &sattr.ivalue);
    sattr.ivalue = *(int2*)&sattr.ivalue;
    return;

  case dbvmInvokeMethodInt4:
    execute(expr->ref.base, iattr, sattr);
    expr->ref.field->method->invoke(sattr.base, &sattr.ivalue);
    sattr.ivalue = *(int4*)&sattr.ivalue;
    return;

  case dbvmInvokeMethodInt8:
    execute(expr->ref.base, iattr, sattr);
    expr->ref.field->method->invoke(sattr.base, &sattr.ivalue);
    return;

  case dbvmInvokeMethodReal4:
    execute(expr->ref.base, iattr, sattr);
    expr->ref.field->method->invoke(sattr.base, &sattr.fvalue);
    sattr.fvalue = *(real4*)&sattr.fvalue;
    return;

  case dbvmInvokeMethodReal8:
    execute(expr->ref.base, iattr, sattr);
    expr->ref.field->method->invoke(sattr.base, &sattr.fvalue);
    return;

  case dbvmInvokeMethodReference:
    execute(expr->ref.base, iattr, sattr);
    expr->ref.field->method->invoke(sattr.base, &sattr.oid);
    return;

  case dbvmInvokeMethodString:
    execute(expr->ref.base, iattr, sattr);
    expr->ref.field->method->invoke(sattr.base, &sattr2.array.base);
    sattr.array.size = strlen(sattr2.array.base) + 1;
    sattr.array.base = dbStringValue::create(sattr2.array.base, iattr);
    delete[] sattr2.array.base;
    return;

  case dbvmInvokeSelfMethodBool:
    expr->ref.field->method->invoke(iattr.record, &sattr.bvalue);
    sattr.bvalue = *(bool*)&sattr.bvalue;
    return;

  case dbvmInvokeSelfMethodInt1:
    expr->ref.field->method->invoke(iattr.record, &sattr.ivalue);
    sattr.ivalue = *(int1*)&sattr.ivalue;
    return;

  case dbvmInvokeSelfMethodInt2:
    expr->ref.field->method->invoke(iattr.record, &sattr.ivalue);
    sattr.ivalue = *(int2*)&sattr.ivalue;
    return;

  case dbvmInvokeSelfMethodInt4:
    expr->ref.field->method->invoke(iattr.record, &sattr.ivalue);
    sattr.ivalue = *(int4*)&sattr.ivalue;
    return;

  case dbvmInvokeSelfMethodInt8:
    expr->ref.field->method->invoke(iattr.record, &sattr.ivalue);
    return;

  case dbvmInvokeSelfMethodReal4:
    expr->ref.field->method->invoke(iattr.record, &sattr.fvalue);
    sattr.fvalue = *(real4*)&sattr.fvalue;
    return;

  case dbvmInvokeSelfMethodReal8:
    expr->ref.field->method->invoke(iattr.record, &sattr.fvalue);
    return;

  case dbvmInvokeSelfMethodReference:
    expr->ref.field->method->invoke(iattr.record, &sattr.oid);
    return;

  case dbvmInvokeSelfMethodString:
    expr->ref.field->method->invoke(iattr.record, &sattr2.array.base);
    sattr.array.size = strlen(sattr2.array.base) + 1;
    sattr.array.base = dbStringValue::create(sattr2.array.base, iattr);
    delete[] sattr2.array.base;
    return;

  case dbvmLength:
    execute(expr->operand[0], iattr, sattr);
    sattr.ivalue = sattr.array.size;
    return;

  case dbvmStringLength:
    execute(expr->operand[0], iattr, sattr);
    sattr.ivalue = sattr.array.size - 1;
    return;

  case dbvmGetAt:
    execute(expr->operand[0], iattr, sattr);
    execute(expr->operand[1], iattr, sattr2);

    if ((nat8)sattr2.ivalue >= (nat8)sattr.array.size)
    {
      if (expr->operand[1]->cop == dbvmVariable)
      {
        longjmp(iattr.exists_iterator[expr->operand[1]->offs].unwind, 1);
      }

      iattr.removeTemporaries();
      iattr.db->handleError(IndexOutOfRangeError, NULL,
                            int(sattr2.ivalue));
    }

    sattr.base = (byte*)sattr.array.base + int(sattr2.ivalue)*expr->offs;
    return;

  case dbvmCharAt:
    execute(expr->operand[0], iattr, sattr);
    execute(expr->operand[1], iattr, sattr2);

    if ((nat8)sattr2.ivalue >= (nat8)(sattr.array.size-1))
    {
      if (expr->operand[1]->cop == dbvmVariable)
      {
        longjmp(iattr.exists_iterator[expr->operand[1]->offs].unwind, 1);
      }

      iattr.removeTemporaries();
      iattr.db->handleError(IndexOutOfRangeError, NULL,
                            int(sattr2.ivalue));
    }

    sattr.ivalue = (byte)sattr.array.base[int(sattr2.ivalue)];
    return;

  case dbvmExists:
    iattr.exists_iterator[expr->offs].index = 0;

    if (setjmp(iattr.exists_iterator[expr->offs].unwind) == 0)
    {
      do
      {
        execute(expr->operand[0], iattr, sattr);
        iattr.exists_iterator[expr->offs].index += 1;
      }
      while (!sattr.bvalue);
    }
    else
    {
      sattr.bvalue = false;
    }

    return;

  case dbvmVariable:
    sattr.ivalue = iattr.exists_iterator[expr->offs].index;
    return;

  case dbvmLoadVarBool:
    sattr.bvalue = *(bool*)((char*)expr->var + iattr.paramBase);
    return;

  case dbvmLoadVarInt1:
    sattr.ivalue = *(int1*)((char*)expr->var + iattr.paramBase);
    return;

  case dbvmLoadVarInt2:
    sattr.ivalue = *(int2*)((char*)expr->var + iattr.paramBase);
    return;

  case dbvmLoadVarInt4:
    sattr.ivalue = *(int4*)((char*)expr->var + iattr.paramBase);
    return;

  case dbvmLoadVarInt8:
    sattr.ivalue = *(db_int8*)((char*)expr->var + iattr.paramBase);
    return;

  case dbvmLoadVarReal4:
    sattr.fvalue = *(real4*)((char*)expr->var + iattr.paramBase);
    return;

  case dbvmLoadVarReal8:
    sattr.fvalue = *(real8*)((char*)expr->var + iattr.paramBase);
    return;

  case dbvmLoadVarReference:
    sattr.oid = *(oid_t*)((char*)expr->var + iattr.paramBase);
    return;

  case dbvmLoadVarString:
    sattr.array.base = (char*)((char*)expr->var + iattr.paramBase);
    sattr.array.size = strlen((char*)sattr.array.base) + 1;
    return;

  case dbvmLoadVarStringPtr:
    sattr.array.base = *(char**)((char*)expr->var + iattr.paramBase);
    sattr.array.size = strlen((char*)sattr.array.base) + 1;
    return;

  case dbvmLoadVarArray:
    sattr.array.base = (char*)((dbAnyArray*)((char*)expr->var + iattr.paramBase))->base();
    sattr.array.size = ((dbAnyArray*)((char*)expr->var + iattr.paramBase))->length();
    return;

  case dbvmLoadVarArrayPtr:
    {
      dbAnyArray* arr = *(dbAnyArray**)((char*)expr->var + iattr.paramBase);
      sattr.array.base = (char*)arr->base();
      sattr.array.size = arr->length();
      return;
    }

  case dbvmLoadVarRawBinary:
    sattr.raw = (void*)((char*)expr->var + iattr.paramBase);
    return;

#ifdef USE_STD_STRING

  case dbvmLoadVarStdString:
    sattr.array.base = (char*)((std::string*)((char*)expr->var + iattr.paramBase))->c_str();
    sattr.array.size = ((std::string*)((char*)expr->var + iattr.paramBase))->length() + 1;
    return;
#endif

  case dbvmLoadTrue:
    sattr.bvalue = true;
    return;

  case dbvmLoadFalse:
    sattr.bvalue = false;
    return;

  case dbvmLoadNull:
    sattr.oid = 0;
    return;

  case dbvmLoadIntConstant:
    sattr.ivalue = expr->ivalue;
    return;

  case dbvmLoadRealConstant:
    sattr.fvalue = expr->fvalue;
    return;

  case dbvmLoadStringConstant:
    sattr.array.base = expr->svalue.str;
    sattr.array.size = expr->svalue.len;
    return;

  case dbvmOrBool:
    execute(expr->operand[0], iattr, sattr);

    if (sattr.bvalue == 0)
    {
      execute(expr->operand[1], iattr, sattr);
    }

    return;

  case dbvmAndBool:
    execute(expr->operand[0], iattr, sattr);

    if (sattr.bvalue != 0)
    {
      execute(expr->operand[1], iattr, sattr);
    }

    return;

  case dbvmNotBool:
    execute(expr->operand[0], iattr, sattr);
    sattr.bvalue = !sattr.bvalue;
    return;

  case dbvmIsNull:
    execute(expr->operand[0], iattr, sattr);
    sattr.bvalue = sattr.oid == 0;
    return;

  case dbvmNegInt:
    execute(expr->operand[0], iattr, sattr);
    sattr.ivalue = -sattr.ivalue;
    return;

  case dbvmAddInt:
    execute(expr->operand[0], iattr, sattr);
    execute(expr->operand[1], iattr, sattr2);
    sattr.ivalue += sattr2.ivalue;
    return;

  case dbvmSubInt:
    execute(expr->operand[0], iattr, sattr);
    execute(expr->operand[1], iattr, sattr2);
    sattr.ivalue -= sattr2.ivalue;
    return;

  case dbvmMulInt:
    execute(expr->operand[0], iattr, sattr);
    execute(expr->operand[1], iattr, sattr2);
    sattr.ivalue *= sattr2.ivalue;
    return;

  case dbvmDivInt:
    execute(expr->operand[0], iattr, sattr);
    execute(expr->operand[1], iattr, sattr2);

    if (sattr2.ivalue == 0)
    {
      iattr.removeTemporaries();
      iattr.db->handleError(ArithmeticError, "Division by zero");
    }
    else
    {
      sattr.ivalue /= sattr2.ivalue;
    }

    return;

  case dbvmAndInt:
    execute(expr->operand[0], iattr, sattr);
    execute(expr->operand[1], iattr, sattr2);
    sattr.ivalue &= sattr2.ivalue;
    return;

  case dbvmOrInt:
    execute(expr->operand[0], iattr, sattr);
    execute(expr->operand[1], iattr, sattr2);
    sattr.ivalue |= sattr2.ivalue;
    return;

  case dbvmNotInt:
    execute(expr->operand[0], iattr, sattr);
    sattr.ivalue = ~sattr.ivalue;
    return;

  case dbvmAbsInt:
    execute(expr->operand[0], iattr, sattr);

⌨️ 快捷键说明

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