📄 gaselectstm.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 + -