⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myldbexpressions.pas

📁 一个本地database引擎,支持中文T_Sql查询,兼容DELPHI标准数据库控件
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    doMAX:          Result := 'MAX';
    doCOUNT:        Result := 'COUNT';
    doCOUNTALL:     Result := 'COUNT(*)';
    else            Result:='unknown';
  end;
end;//GetOperatorName


//------------------------------------------------------------------------------
// Return FieldType
//------------------------------------------------------------------------------
function GetFieldType(const TypeName: string): TMYLDBAdvancedFieldType;
var
  i: Integer;
  s: String;
begin
  Result := aftUnknown;
  s := UpperCase(TypeName);
  for i:=Low(SQLFieldTypes) to High(SQLFieldTypes) do
    if SQLFieldTypes[i].SqlName = s then
      begin
        Result := SQLFieldTypes[i].AdvancedFieldType;
        break;
      end;
end;//GetFieldType



////////////////////////////////////////////////////////////////////////////////
//
// TMYLDBExpression
//
////////////////////////////////////////////////////////////////////////////////


//------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------
constructor TMYLDBExpression.Create;
begin
  FRootExprNode := nil;
  LLex := nil;
  FCaseInsensitive := False;
  FPartialKey := False;
  F3ValueLogic := True;
end;//Create


//------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------
constructor TMYLDBExpression.Create(RootNode: TMYLDBExprNode);
begin
  Create;
  FRootExprNode := RootNode;
end;//Create


//------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------
//constructor TMYLDBExpression.Create(Lexer: TMYLDBLexer);
//begin
//  Create;
//  LLex := Lexer;
//end;//Create



//------------------------------------------------------------------------------
// Destructor
//------------------------------------------------------------------------------
destructor TMYLDBExpression.Destroy;
begin
  Clear;
  inherited;
end;//Destroy


//------------------------------------------------------------------------------
// Clear all Variables
//------------------------------------------------------------------------------
procedure TMYLDBExpression.Clear;
begin
  // free nodes tree
  if (FRootExprNode <> nil) then
    begin
      FRootExprNode.Free;
      FRootExprNode := nil;
    end;
end;//Clear


//------------------------------------------------------------------------------
// Parsing for Locate
//------------------------------------------------------------------------------
procedure TMYLDBExpression.ParseForLocate(
                                          Cursor: TMYLDBCursor;
                                          FieldNames: String; // name1;name2
                                          KeyValues: Variant; //
                                          CaseInsensitive: boolean = true;
                                          PartialKey: boolean = false
                                       );
var
  i, ArrLen: Integer;
  FieldNamesList: TStringList;
  //Arr: Pointer;
  LeftNField: TMYLDBExprNodeField;
  RightNConst: TMYLDBExprNodeConst;
  EqNode: TMYLDBExprNodeComparison;
  IsArray: Boolean;
  //AndNode: TMYLDBExprNodeBoolean;
  //val: TMYLDBVariant;

  procedure AssignConstValue(const Value: Variant);
  begin
    if (LeftNField.BaseFieldType in [bftDate, bftTime, bftDateTime]) and
       (VarType(Value) in [varInteger, varDouble]) then
      RightNConst.Value.AsVariant := TDateTime(Value)
    else
      RightNConst.Value.AsVariant := Value;
  end;

begin
  Clear;
  LCursor := Cursor;
  F3ValueLogic := False;

  FieldNamesList := TStringList.Create;
  try
    FillFieldNames(FieldNamesList, FieldNames);

    // Determinate KeyValues count (can be array)
    if  (VarType(KeyValues) and varArray ) <> 0 then
      begin
        IsArray := true;
        ArrLen := VarArrayHighBound(KeyValues,1) - VarArrayLowBound(KeyValues,1) + 1
      end
    else
      begin
        IsArray := False;
        ArrLen := 1;
      end;

    if (FieldNamesList.Count <> ArrLen) then
      raise EMYLDBException.Create(30112, ErrorGNotEqualCountsOfFieldNamesAndKeyValues,
                                      [FieldNamesList.Count, ArrLen]);

    if (not IsArray) then
      begin
        // Field
        LeftNField := TMYLDBExprNodeField.Create(LCursor, FieldNamesList[0]);
        // Const
        RightNConst := TMYLDBExprNodeConst.Create;
        AssignConstValue(KeyValues);
        // RootNode
        FRootExprNode := TMYLDBExprNodeComparison.Create(doEQ, LeftNField,
                                      RightNConst, F3ValueLogic, CaseInsensitive, PartialKey);
      end
    else
      begin
        FRootExprNode := TMYLDBExprNodeBoolean.Create(doAND);
        for i:=0 to ArrLen-1 do
          begin
            // Field
            LeftNField := TMYLDBExprNodeField.Create(LCursor, FieldNamesList[i]);
            // Check FieldExists
            // ...
            // Const
            RightNConst := TMYLDBExprNodeConst.Create;
            AssignConstValue(VarArrayGet(KeyValues, i));

            // EqNode
            EqNode := TMYLDBExprNodeComparison.Create(doEQ, LeftNField, RightNConst,
                                       F3ValueLogic, CaseInsensitive, PartialKey);
            // Add to RootNode
            FRootExprNode.Children.Add(EqNode);
          end;
      end;
  finally
    FieldNamesList.Free;
  end;

  if LCursor <> nil then
    FRootExprNode.PatchWideStrings;

end;//ParseForLocate


//------------------------------------------------------------------------------
// Parsing for Filter
//------------------------------------------------------------------------------
procedure TMYLDBExpression.ParseForFilter(Cursor: TMYLDBCursor; Filter: String;
  CaseInsensitive, PartialKey: boolean);
var
  Lexer: TMYLDBLexer;
begin
  LCursor := Cursor;
  FCaseInsensitive := CaseInsensitive;
  FPartialKey := PartialKey;

  Lexer := TMYLDBLexer.Create(Filter);
  try
    if (Lexer.NumCommands = 0) then
       raise EMYLDBException.Create(30119, ErrorGBlankSqlCommand);
    Lexer.GetNextCommand;
    ParseForBooleanExpression(nil, Lexer);
  finally
    Lexer.Free;
  end;
end;//ParseForFilter


//------------------------------------------------------------------------------
// parse for IsAnyRecordMatchCondition (for quantified subquery comparison)
//------------------------------------------------------------------------------
procedure TMYLDBExpression.ParseForIsAnyRecordMatchCondition(
                                           Cursor: TMYLDBCursor;
                                           const FieldName: string;
                                           const Operator: TMYLDBDataOperator;
                                           const Value: TMYLDBVariant
                                           );
var
  LeftNField: TMYLDBExprNodeField;
  RightNConst: TMYLDBExprNodeConst;
begin
  Clear;
  LCursor := Cursor;
  F3ValueLogic := False;
  // Field
  LeftNField := TMYLDBExprNodeField.Create(LCursor, FieldName);
  // Const
  RightNConst := TMYLDBExprNodeConst.Create;
  RightNConst.Value.Assign(Value);
  // RootNode
  FRootExprNode := TMYLDBExprNodeComparison.Create(Operator, LeftNField,
                   RightNConst, F3ValueLogic, False, False);
  if LCursor <> nil then
    FRootExprNode.PatchWideStrings;
end;// ParseForIsAnyRecordMatchCondition


//------------------------------------------------------------------------------
// Parse For Boolean Expression (Filter, Where-Clause)
//------------------------------------------------------------------------------
procedure TMYLDBExpression.ParseForBooleanExpression(
                                        Dataset: TDataset;
                                        Lexer: TMYLDBLexer
                                        //CaseInsensitive: boolean = true;
                                        //PartialKey: boolean = false
                                                   );
begin
  Clear;
  LDataset := Dataset;
  LLex := Lexer;

  if (not LLex.GetCurrentToken(Token)) then
    raise EMYLDBException.Create(30118, ErrorGUnexpectedEndOfCommand,
                                              [Token.LineNum, Token.ColumnNum]);
  // Parse...
  FRootExprNode := ParseSearchCondition;

  if (FRootExprNode = nil) then
    raise EMYLDBException.Create(30066, ErrorGBooleanExpressionExpected,
                               [Token.Text, Token.LineNum, Token.ColumnNum]);
  MoveAndNodesToRoot;

  if LCursor <> nil then
    FRootExprNode.PatchWideStrings;
end;//ParseForBooleanExpression


//------------------------------------------------------------------------------
// Parse ValueExpression
//------------------------------------------------------------------------------
procedure TMYLDBExpression.ParseForValueExpression(
                                        Dataset: TDataset;
                                        Lexer: TMYLDBLexer
                                        //CaseInsensitive: boolean = true;
                                        //PartialKey: boolean = false
                                                 );
begin
 LLex := Lexer;
 LDataset := Dataset;
 if (Dataset <> nil) then begin
   FDatabaseName := TMYLDBDataset(Dataset).DatabaseName;
   FSessionName := TMYLDBDataset(Dataset).SessionName;
 end;
 //LCursor := Cursor;
 //FCaseInsensitive := CaseInsensitive;
 //FPartialKey := PartialKey;

 // get first token (for very beginning of the query) or current token
 if (not LLex.GetCurrentToken(Token)) then
  raise EMYLDBException.Create(30136, ErrorGUnexpectedEndOfCommand, [Token.LineNum, Token.ColumnNum]);

 // parse
 FRootExprNode := ParseValueExpression;
end;//ParseForValueExpression


//------------------------------------------------------------------------------
// default value: const or function
//------------------------------------------------------------------------------
function TMYLDBExpression.ParseForDefaultValueExpression(DefaultValue: String): Boolean;
var
  Lexer: TMYLDBLexer;
  Token: TToken;
begin
  try
    Lexer := TMYLDBLexer.Create(DefaultValue);
    try
      if (Lexer.NumCommands = 0) then
         Result := False
      else
        begin
          Lexer.GetNextCommand;
          ParseForValueExpression(nil, Lexer);
          Result := (Lexer.NumCommands = 1) and (not Lexer.LookNextToken(Token));
        end;
    finally
      Lexer.Free;
    end;
  except
    Result := False;
  end;
end;// ParseForDefaultValueExpression


//------------------------------------------------------------------------------
// Parse RowSubqueryExpression
//------------------------------------------------------------------------------
procedure TMYLDBExpression.ParseForRowSubqueryExpression(
                                    Dataset: TDataset;
                                    Lexer: TMYLDBLexer);
begin
 LLex := Lexer;
 LDataset := Dataset;
 FDatabaseName := TMYLDBDataset(Dataset).DatabaseName;
 FSessionName := TMYLDBDataset(Dataset).SessionName;

 // get first token (for very beginning of the query) or current token
 if (not LLex.GetCurrentToken(Token)) then
  raise EMYLDBException.Create(30497, ErrorGUnexpectedEndOfCommand, [Token.LineNum, Token.ColumnNum]);

 // parse

⌨️ 快捷键说明

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