* fcl-db: sql parser: support table.column notation for fields like

- SELECT A.B FROM A
- SELECT B FROM A ORDER BY C.D
- tests
Note: failing test due to needed implementation of parsing table.field into table and field references

git-svn-id: trunk@27912 -
This commit is contained in:
reiniero 2014-06-09 12:34:52 +00:00
parent a99919a4bc
commit c63b31c839
5 changed files with 58 additions and 19 deletions

View File

@ -511,6 +511,7 @@ procedure TSQLParser.ParseOrderBy(AParent: TSQLSelectStatement;
Var
O : TSQLOrderByElement;
F : TSQLElement;
BuildToken : string;
begin
// On entry we're on the ORDER token.
@ -518,10 +519,21 @@ begin
Expect(tsqlBy);
Repeat
GetNextToken;
// Deal with table.column notation:
Case CurrentToken of
tsqlIdentifier :
F:=CreateIdentifier(AParent,CurrentTokenString);
tsqlIntegerNumber :
begin
BuildToken:=CurrentTokenString;
If (PeekNextToken=tsqlDot) then
begin
GetNextToken; //past tsqlDot
GetNextToken;
Expect(tsqlIdentifier);
BuildToken:=BuildToken+'.'+CurrentTokenString;
end;
F:=CreateIdentifier(AParent,BuildToken);
end;
tsqlIntegerNumber : //e.g. ORDER BY 1
begin
F:=TSQLIntegerLiteral(CreateElement(TSQLIntegerLiteral,AParent));
TSQLIntegerLiteral(F).Value:=StrToInt(CurrentTokenString);
@ -2077,7 +2089,7 @@ begin
tsqlNull :
Result:=TSQLLiteral(CreateElement(TSQLNullLiteral,AParent));
tsqlValue :
Result:=TSQLLiteral(CreateElement(TSQLValueLiteral,AParent));
Result:=TSQLLiteral(CreateElement(TSQLValueLiteral,AParent));
tsqlUSER :
Result:=TSQLLiteral(CreateElement(TSQLUserLiteral,AParent));
else
@ -2219,7 +2231,7 @@ begin
if (CurrentToken=tsqlNot) then
begin
GetNextToken;
if not (tt=tsqlis) then
if not (tt=tsqlIS) then
UnexpectedToken;
Inverted:=true;
end;

View File

@ -40,7 +40,7 @@ type
tsqlEOF,tsqlWhiteSpace,
tsqlString {string literal},
tsqlIdentifier {a table etc name},
tsqlSymbolLiteral {a literal containing symbols/punctuation marks},
tsqlSymbolLiteral {a literal containing symbols/punctuation marks; only rarely used - e.g. in SET TERM ^ ;},
tsqlIntegerNumber,tsqlFloatNumber,tsqlComment,
tsqlStatementTerminator {statement separator, usually semicolon but may be changed by code. For now, limited to semicolon and symbol literals not already defined like tsqlCOMMA},
tsqlBraceOpen,tsqlBraceClose,tsqlSquareBraceOpen,tsqlSquareBraceClose,

View File

@ -150,6 +150,7 @@ Type
Property Value : TSQLStringType Read FValue Write FValue;
end;
{ TSQLIdentifierElement }
TSQLIdentifierName = Class(TSQLElement)
@ -585,13 +586,13 @@ Type
TSQLSelectField = Class(TSQLSelectElement)
private
FAliasName: TSQLIDentifierName;
FAliasName: TSQLIdentifierName;
FExpression: TSQLExpression;
Public
Destructor Destroy; override;
Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
Property Expression : TSQLExpression Read FExpression Write FExpression;
Property AliasName : TSQLIDentifierName Read FAliasName Write FAliasName;
Property AliasName : TSQLIdentifierName Read FAliasName Write FAliasName;
end;
{ TSQLTableReference }
@ -602,7 +603,7 @@ Type
TSQLSimpleTableReference = Class(TSQLTableReference)
private
FAliasName: TSQLIDentifierName;
FAliasName: TSQLIdentifierName;
FObjectName: TSQLIdentifierName;
FParams: TSQLElementList;
Public
@ -610,7 +611,7 @@ Type
Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
Property ObjectName : TSQLIdentifierName Read FObjectName Write FObjectName;
Property Params : TSQLElementList Read FParams Write FParams;
Property AliasName : TSQLIDentifierName Read FAliasName Write FAliasName;
Property AliasName : TSQLIdentifierName Read FAliasName Write FAliasName;
end;
{ TSQLJoinTableReference }
@ -722,7 +723,7 @@ Type
FPlan: TSQLSelectPlan;
FStartAt: TSQLExpression;
FTables: TSQLElementList;
FTN: TSQLidentifierName;
FTN: TSQLIdentifierName;
FUnion: TSQLSelectStatement;
FUnionAll: Boolean;
FWhere: TSQLExpression;
@ -730,7 +731,7 @@ Type
Constructor Create(AParent : TSQLElement); override;
Destructor Destroy; override;
Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
Property TransactionName : TSQLidentifierName Read FTN Write FTN;
Property TransactionName : TSQLIdentifierName Read FTN Write FTN;
Property Tables : TSQLElementList Read FTables;
Property Fields : TSQLElementList Read FFields;
Property Where : TSQLExpression read FWhere write FWhere;
@ -779,12 +780,12 @@ Type
TSQLUpdatePair = Class(TSQLElement)
private
FFieldName: TSQLidentifierName;
FFieldName: TSQLIdentifierName;
FValue: TSQLExpression;
Public
Destructor Destroy; override;
Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
Property FieldName : TSQLidentifierName Read FFieldName Write FFieldName;
Property FieldName : TSQLIdentifierName Read FFieldName Write FFieldName;
Property Value : TSQLExpression Read FValue Write FValue;
end;

View File

@ -1,6 +1,6 @@
{
This file is part of the Free Component Library
Copyright (c) 2010 by the Free Pascal development team
Copyright (c) 2010-2014 by the Free Pascal development team
SQL Syntax Tree SQL generation tests
@ -31,11 +31,11 @@ type
Private
FToFree:TSQLElement;
protected
procedure SetUp; override;
procedure TearDown; override;
procedure DoTestDropStatement(AClass: TSQLDropStatementClass; const AObjectName: String);
procedure DoTestAlterCreateProcedure(S: TSQLAlterCreateProcedureStatement; PHEAD: String);
procedure DoTestAlterCreateTrigger(S: TSQLAlterCreateTriggerStatement; PHEAD: String);
Procedure SetUp; override;
Procedure TearDown; override;
Procedure DoTestDropStatement(AClass: TSQLDropStatementClass; const AObjectName: String);
Procedure DoTestAlterCreateProcedure(S: TSQLAlterCreateProcedureStatement; PHEAD: String);
Procedure DoTestAlterCreateTrigger(S: TSQLAlterCreateTriggerStatement; PHEAD: String);
Function CreateIdentifier(Const AName : TSQLStringType) : TSQLIdentifierName;
Function CreateGrantee(Const AName : TSQLStringType; AClass : TSQLGranteeClass = Nil) : TSQLGrantee;
Function CreateLiteral(Const AValue : Integer) : TSQLIntegerLiteral;

View File

@ -378,6 +378,7 @@ type
procedure TestSelectTwoFieldsOneTable;
procedure TestSelectOneFieldAliasOneTable;
procedure TestSelectTwoFieldAliasesOneTable;
procedure TestSelectOneTableFieldOneTable;
procedure TestSelectOneDistinctFieldOneTable;
procedure TestSelectOneAllFieldOneTable;
procedure TestSelectAsteriskOneTable;
@ -427,6 +428,7 @@ type
procedure TestOrderByOneDescField;
procedure TestOrderByTwoDescFields;
procedure TestOrderByThreeDescFields;
procedure TestOrderByOneTableField;
procedure TestOrderByOneColumn;
procedure TestOrderByTwoColumns;
procedure TestOrderByTwoColumnsDesc;
@ -3755,6 +3757,16 @@ begin
AssertTable(Select.Tables[0],'A');
end;
procedure TTestSelectParser.TestSelectOneTableFieldOneTable;
begin
TestSelect('SELECT A.B FROM A');
AssertEquals('One field',1,Select.Fields.Count);
AssertField(Select.Fields[0],'B');
AssertEquals('One table',1,Select.Tables.Count);
AssertTable(Select.Tables[0],'A');
end;
procedure TTestSelectParser.TestSelectOneDistinctFieldOneTable;
begin
TestSelect('SELECT DISTINCT B FROM A');
@ -4274,6 +4286,7 @@ begin
AssertOrderBy(Select.OrderBy[1],'D',0,obAscending);
AssertOrderBy(Select.OrderBy[2],'E',0,obAscending);
end;
procedure TTestSelectParser.TestOrderByOneDescField;
begin
@ -4312,6 +4325,19 @@ begin
AssertOrderBy(Select.OrderBy[2],'E',0,obDescending);
end;
procedure TTestSelectParser.TestOrderByOneTableField;
begin
TestSelect('SELECT B FROM A ORDER BY C.D');
AssertEquals('One field',1,Select.Fields.Count);
AssertEquals('One table',1,Select.Tables.Count);
AssertField(Select.Fields[0],'B');
AssertTable(Select.Tables[0],'A');
AssertEquals('One order by field',1,Select.Orderby.Count);
AssertOrderBy(Select.OrderBy[0],'C',0,obAscending);
end;
procedure TTestSelectParser.TestOrderByOneColumn;
begin
TestSelect('SELECT B FROM A ORDER BY 1');