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

📄 gaselectstm.pas

📁 一个sql语法分析程序
💻 PAS
字号:
{*******************************************************}
{                                                       }
{       Advanced SQL statement parser                   }
{       Copyright (c) 2001 AS Gaiasoft                  }
{       Created by Gert Kello                           }
{                                                       }
{*******************************************************}

unit gaSelectStm;

interface

uses
  gaAdvancedSQLParser, gaSQLParserHelperClasses;

type
  TSelectStatementState = (sssNone, sssFieldList, sssFromList, sssJoinClause,
    sssWhereClause, sssGroupBy, sssHavingClause, sssOrderBy, sssUnion,
    sssStatementComplete);

  TSelectStatementType = (sstSelectAll, sstSelectDistinct);

  TSelectStatementStates = set of TSelectStatementState;

  TgaSelectSQLStatement = class (TgaCustomSQLStatement)
  private
    FOrderByClause: TgaSQLOrderByList;
    FSelectType: TSelectStatementType;
    FStatementFields: TgaSQLFieldList;
    FStatementState: TSelectStatementState;
    FStatementTables: TgaSQLTableList;
    FWhereClause: TgaSQLWhereExpression;
    procedure SetStatementState(const Value: TSelectStatementState);
  protected
    procedure DoAfterStatementStateChange; override;
    procedure DoBeforeStatementStateChange(const NewStateOrd: LongInt); 
            override;
    function GetNewStatementState: TSelectStatementState;
    function GetStatementType: TSQLStatementType; override;
    procedure ModifyStatementInNormalState(Sender: TObject; AToken: 
            TgaSQLTokenObj); override;
    procedure ParseFieldList(AToken: TgaSQLTokenObj);
    procedure ParseGroupBy;
    procedure ParseHavingClause;
    procedure ParseJoin;
    property StatementState: TSelectStatementState read FStatementState write 
            SetStatementState;
  public
    constructor Create(AOwner: TgaAdvancedSQLParser); override;
    constructor CreateFromStatement(AOwner: TgaAdvancedSQLParser; AStatement: 
            TgaNoSQLStatement); override;
    constructor CreateOwned(AOwner: TgaAdvancedSQLParser; AOwnerStatement: 
            TgaCustomSQLStatement); override;
    destructor Destroy; override;
    property OrderByClause: TgaSQLOrderByList read FOrderByClause;
    property SelectType: TSelectStatementType read FSelectType;
    property StatementFields: TgaSQLFieldList read FStatementFields;
    property StatementTables: TgaSQLTableList read FStatementTables;
    property WhereClause: TgaSQLWhereExpression read FWhereClause;
  end;
  
const
  SelectAllowedNextState: array[TSelectStatementState] of TSelectStatementStates =
    ( {sssNone} [sssFieldList],
      {sssFieldList}[sssFromList],
      {sssFromList} [sssJoinClause, sssWhereClause, sssGroupBy, sssOrderBy,
                      sssUnion, sssStatementComplete],
      {sssJoinClause} [sssWhereClause, sssGroupBy, sssOrderBy, sssUnion,
                        sssStatementComplete],
      {sssWhereClause} [sssGroupBy, sssOrderBy, sssUnion, sssStatementComplete],
      {sssGroupBy} [sssHavingClause, sssOrderBy, sssUnion, sssStatementComplete],
      {sssHavingClause} [sssOrderBy, sssUnion, sssStatementComplete],
      {sssOrderBy} [sssUnion, sssStatementComplete],
      {sssUnion} [], {unions will be parsed by another class}
      {sssStatementComplete} []);

implementation

uses
  SysUtils, TypInfo, gaBasicSQLParser, gaSQLParserConsts;

{
**************************** TgaSelectSQLStatement *****************************
}
constructor TgaSelectSQLStatement.Create(AOwner: TgaAdvancedSQLParser);
begin
  inherited Create(AOwner);
  FStatementState := sssNone;
  FStatementFields := TgaSQLFieldList.Create(Self);
  FStatementTables := TgaSQLTableList.Create(Self);
end;

constructor TgaSelectSQLStatement.CreateFromStatement(AOwner: 
        TgaAdvancedSQLParser; AStatement: TgaNoSQLStatement);
begin
  inherited CreateFromStatement(AOwner, AStatement);
  FStatementState := sssNone;
  FStatementFields := TgaSQLFieldList.Create(Self);
  FStatementTables := TgaSQLTableList.Create(Self);
end;

constructor TgaSelectSQLStatement.CreateOwned(AOwner: TgaAdvancedSQLParser; 
        AOwnerStatement: TgaCustomSQLStatement);
begin
  inherited CreateOwned(AOwner, AOwnerStatement);
  FStatementState := sssNone;
  FStatementFields := TgaSQLFieldList.Create(Self);
  FStatementTables := TgaSQLTableList.Create(Self);
end;

destructor TgaSelectSQLStatement.Destroy;
begin
  FOrderByClause.Free;
  FStatementFields.Free;
  FStatementTables.Free;
  FWhereClause.Free;
  inherited Destroy;
end;

procedure TgaSelectSQLStatement.DoAfterStatementStateChange;
begin
  inherited DoAfterStatementStateChange;
  if (StatementState > sssJoinClause) and (not Assigned(FWhereClause)) then
  begin
    if StatementState = sssWhereClause then
      FWhereClause := TgaSQLWhereExpression.Create(Self)
    else begin
      CurrentSQL.Previous;
      CurrentSQL.InsertAfterCurrent(TgaSQLTokenObj.CreatePlaceHolder, True);
      FWhereClause := TgaSQLWhereExpression.Create(Self);
      FWhereClause.ParseComplete := True;
      CurrentSQL.Next;
    end;
  end;
  if (StatementState > sssHavingClause) and (not Assigned(FOrderByClause)) then
  begin
    if StatementState = sssOrderBy then
      FOrderByClause := TgaSQLOrderByList.Create(Self)
    else begin
      CurrentSQL.Previous;
      CurrentSQL.InsertAfterCurrent(TgaSQLTokenObj.CreatePlaceHolder, True);
      FOrderByClause := TgaSQLOrderByList.Create(Self);
      FOrderByClause.ParseComplete := True;
      CurrentSQL.Next;
    end
  end;
end;

procedure TgaSelectSQLStatement.DoBeforeStatementStateChange(const NewStateOrd: 
        LongInt);
begin
  inherited DoBeforeStatementStateChange(NewStateOrd);
  case StatementState of
    sssWhereClause: begin
      WhereClause.Last;
      WhereClause.Previous;
      WhereClause.ParseComplete := True;
    end;
    sssOrderBy: begin
      OrderByClause.Last;
      OrderByClause.Previous;
      OrderByClause.ParseComplete := True;
    end;
  end;
end;

function TgaSelectSQLStatement.GetNewStatementState: TSelectStatementState;
var
  TokenStr: string;
begin
  (*
    SELECT [TRANSACTION transaction]
    [DISTINCT | ALL]
    {* | <val> [, <val> 匽}
    [INTO : var [, : var 匽]
    FROM <tableref> [, <tableref> 匽
    [WHERE <search_condition>]
    [GROUP BY col [COLLATE collation] [, col [COLLATE collation] 匽
    [HAVING <search_condition>]
    [UNION <select_expr> [ALL]]
    [PLAN <plan_expr>]
    [ORDER BY <order_list>]
    [FOR UPDATE [OF col [, col 匽]];
  *)
  Result := StatementState;
  TokenStr := UpperCase(OwnerParser.TokenString);
  if OwnerParser.TokenType = stSymbol then
  begin
    if TokenStr = 'SELECT' then
      Result := sssFieldList
    else if TokenStr = 'FROM' then
      Result := sssFromList
    else if TokenStr = 'WHERE' then
      Result := sssWhereClause
    else if TokenStr = 'GROUP' then
      Result := sssGroupBy
    else if TokenStr = 'HAVING' then
      Result := sssHavingClause
    else if TokenStr = 'ORDER' then
      Result := sssOrderBy
    else if TokenStr = 'UNION' then
      Result := sssUnion
    else if (TokenStr = 'INNER') or (TokenStr = 'JOIN') or
      (TokenStr = 'LEFT') or (TokenStr = 'RIGHT') or (TokenStr = 'FULL') then
      Result := sssJoinClause;
  end else if OwnerParser.TokenType = stEnd then
    Result := sssStatementComplete;
end;

function TgaSelectSQLStatement.GetStatementType: TSQLStatementType;
begin
  Result := sstSelect;
end;

procedure TgaSelectSQLStatement.ModifyStatementInNormalState(Sender: TObject; 
        AToken: TgaSQLTokenObj);
begin
  inherited;
  StatementState := GetNewStatementState;
  if StatusCode <> 0 then
    raise Exception.CreateFmt('Statement status code is %d', [StatusCode]);
  if InternalStatementState > 0 then
    case StatementState of
      sssNone:
        {the statement starts with comment or whitespace};
      sssFieldList:
        ParseFieldList(AToken);
      sssFromList:
        StatementTables.ExecuteTokenAdded(Sender, AToken);
      sssWhereClause:
        WhereClause.ExecuteTokenAdded(Sender, AToken);
      sssGroupBy:
        ParseGroupBy;
      sssHavingClause:
        ParseHavingClause;
      sssJoinClause:
        ParseJoin;
      sssOrderBy:
        OrderByClause.ExecuteTokenAdded(Self, AToken);
      sssStatementComplete:
        DoStatementComplete;
      else
        raise Exception.CreateFmt(SUnknownStatementState,
          [ClassName, GetEnumName(TypeInfo(TSelectStatementState), Ord(StatementState))]);
    end
  else
    InternalStatementState := 1;
end;

procedure TgaSelectSQLStatement.ParseFieldList(AToken: TgaSQLTokenObj);
begin
  if InternalStatementState = 1 then
  begin
    if AToken.TokenType in [stDelimitier, stComment] then
      // continue
    else begin
      if AToken.TokenSymbolIs('ALL') then
        FSelectType := sstSelectAll
      else if AToken.TokenSymbolIs('DISTINCT') then
        FSelectType := sstSelectDistinct
      else
      StatementFields.ExecuteTokenAdded(Self, AToken);
      InternalStatementState := 2;
    end;
  end else
    StatementFields.ExecuteTokenAdded(Self, AToken);
end;

procedure TgaSelectSQLStatement.ParseGroupBy;
begin
  // #todo2
end;

procedure TgaSelectSQLStatement.ParseHavingClause;
begin
  // #todo2
end;

procedure TgaSelectSQLStatement.ParseJoin;
begin
  // #todo2
end;

procedure TgaSelectSQLStatement.SetStatementState(const Value: 
        TSelectStatementState);
begin
  if StatementState <> Value then
  begin
    if StatusCode = 0 then
      if Value in SelectAllowedNextState[FStatementState] then
      begin
        DoBeforeStatementStateChange(Ord(Value));
        FStatementState := Value;
        InternalStatementState := 0;
        DoAfterStatementStateChange;
      end else
        StatusCode := errWrongKeywordSequence;
    if Value = sssStatementComplete then
    begin
      DoBeforeStatementStateChange(Ord(Value));
      FStatementState := Value;
      InternalStatementState := 0;
      DoAfterStatementStateChange;
    end;
  end;
end;

end.

⌨️ 快捷键说明

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