mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 01:09:25 +02:00
* 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:
parent
a99919a4bc
commit
c63b31c839
@ -511,6 +511,7 @@ procedure TSQLParser.ParseOrderBy(AParent: TSQLSelectStatement;
|
|||||||
Var
|
Var
|
||||||
O : TSQLOrderByElement;
|
O : TSQLOrderByElement;
|
||||||
F : TSQLElement;
|
F : TSQLElement;
|
||||||
|
BuildToken : string;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
// On entry we're on the ORDER token.
|
// On entry we're on the ORDER token.
|
||||||
@ -518,10 +519,21 @@ begin
|
|||||||
Expect(tsqlBy);
|
Expect(tsqlBy);
|
||||||
Repeat
|
Repeat
|
||||||
GetNextToken;
|
GetNextToken;
|
||||||
|
// Deal with table.column notation:
|
||||||
Case CurrentToken of
|
Case CurrentToken of
|
||||||
tsqlIdentifier :
|
tsqlIdentifier :
|
||||||
F:=CreateIdentifier(AParent,CurrentTokenString);
|
begin
|
||||||
tsqlIntegerNumber :
|
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
|
begin
|
||||||
F:=TSQLIntegerLiteral(CreateElement(TSQLIntegerLiteral,AParent));
|
F:=TSQLIntegerLiteral(CreateElement(TSQLIntegerLiteral,AParent));
|
||||||
TSQLIntegerLiteral(F).Value:=StrToInt(CurrentTokenString);
|
TSQLIntegerLiteral(F).Value:=StrToInt(CurrentTokenString);
|
||||||
@ -2077,7 +2089,7 @@ begin
|
|||||||
tsqlNull :
|
tsqlNull :
|
||||||
Result:=TSQLLiteral(CreateElement(TSQLNullLiteral,AParent));
|
Result:=TSQLLiteral(CreateElement(TSQLNullLiteral,AParent));
|
||||||
tsqlValue :
|
tsqlValue :
|
||||||
Result:=TSQLLiteral(CreateElement(TSQLValueLiteral,AParent));
|
Result:=TSQLLiteral(CreateElement(TSQLValueLiteral,AParent));
|
||||||
tsqlUSER :
|
tsqlUSER :
|
||||||
Result:=TSQLLiteral(CreateElement(TSQLUserLiteral,AParent));
|
Result:=TSQLLiteral(CreateElement(TSQLUserLiteral,AParent));
|
||||||
else
|
else
|
||||||
@ -2219,7 +2231,7 @@ begin
|
|||||||
if (CurrentToken=tsqlNot) then
|
if (CurrentToken=tsqlNot) then
|
||||||
begin
|
begin
|
||||||
GetNextToken;
|
GetNextToken;
|
||||||
if not (tt=tsqlis) then
|
if not (tt=tsqlIS) then
|
||||||
UnexpectedToken;
|
UnexpectedToken;
|
||||||
Inverted:=true;
|
Inverted:=true;
|
||||||
end;
|
end;
|
||||||
|
@ -40,7 +40,7 @@ type
|
|||||||
tsqlEOF,tsqlWhiteSpace,
|
tsqlEOF,tsqlWhiteSpace,
|
||||||
tsqlString {string literal},
|
tsqlString {string literal},
|
||||||
tsqlIdentifier {a table etc name},
|
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,
|
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},
|
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,
|
tsqlBraceOpen,tsqlBraceClose,tsqlSquareBraceOpen,tsqlSquareBraceClose,
|
||||||
|
@ -150,6 +150,7 @@ Type
|
|||||||
Property Value : TSQLStringType Read FValue Write FValue;
|
Property Value : TSQLStringType Read FValue Write FValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ TSQLIdentifierElement }
|
{ TSQLIdentifierElement }
|
||||||
|
|
||||||
TSQLIdentifierName = Class(TSQLElement)
|
TSQLIdentifierName = Class(TSQLElement)
|
||||||
@ -585,13 +586,13 @@ Type
|
|||||||
|
|
||||||
TSQLSelectField = Class(TSQLSelectElement)
|
TSQLSelectField = Class(TSQLSelectElement)
|
||||||
private
|
private
|
||||||
FAliasName: TSQLIDentifierName;
|
FAliasName: TSQLIdentifierName;
|
||||||
FExpression: TSQLExpression;
|
FExpression: TSQLExpression;
|
||||||
Public
|
Public
|
||||||
Destructor Destroy; override;
|
Destructor Destroy; override;
|
||||||
Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
|
Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
|
||||||
Property Expression : TSQLExpression Read FExpression Write FExpression;
|
Property Expression : TSQLExpression Read FExpression Write FExpression;
|
||||||
Property AliasName : TSQLIDentifierName Read FAliasName Write FAliasName;
|
Property AliasName : TSQLIdentifierName Read FAliasName Write FAliasName;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TSQLTableReference }
|
{ TSQLTableReference }
|
||||||
@ -602,7 +603,7 @@ Type
|
|||||||
|
|
||||||
TSQLSimpleTableReference = Class(TSQLTableReference)
|
TSQLSimpleTableReference = Class(TSQLTableReference)
|
||||||
private
|
private
|
||||||
FAliasName: TSQLIDentifierName;
|
FAliasName: TSQLIdentifierName;
|
||||||
FObjectName: TSQLIdentifierName;
|
FObjectName: TSQLIdentifierName;
|
||||||
FParams: TSQLElementList;
|
FParams: TSQLElementList;
|
||||||
Public
|
Public
|
||||||
@ -610,7 +611,7 @@ Type
|
|||||||
Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
|
Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
|
||||||
Property ObjectName : TSQLIdentifierName Read FObjectName Write FObjectName;
|
Property ObjectName : TSQLIdentifierName Read FObjectName Write FObjectName;
|
||||||
Property Params : TSQLElementList Read FParams Write FParams;
|
Property Params : TSQLElementList Read FParams Write FParams;
|
||||||
Property AliasName : TSQLIDentifierName Read FAliasName Write FAliasName;
|
Property AliasName : TSQLIdentifierName Read FAliasName Write FAliasName;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TSQLJoinTableReference }
|
{ TSQLJoinTableReference }
|
||||||
@ -722,7 +723,7 @@ Type
|
|||||||
FPlan: TSQLSelectPlan;
|
FPlan: TSQLSelectPlan;
|
||||||
FStartAt: TSQLExpression;
|
FStartAt: TSQLExpression;
|
||||||
FTables: TSQLElementList;
|
FTables: TSQLElementList;
|
||||||
FTN: TSQLidentifierName;
|
FTN: TSQLIdentifierName;
|
||||||
FUnion: TSQLSelectStatement;
|
FUnion: TSQLSelectStatement;
|
||||||
FUnionAll: Boolean;
|
FUnionAll: Boolean;
|
||||||
FWhere: TSQLExpression;
|
FWhere: TSQLExpression;
|
||||||
@ -730,7 +731,7 @@ Type
|
|||||||
Constructor Create(AParent : TSQLElement); override;
|
Constructor Create(AParent : TSQLElement); override;
|
||||||
Destructor Destroy; override;
|
Destructor Destroy; override;
|
||||||
Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; 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 Tables : TSQLElementList Read FTables;
|
||||||
Property Fields : TSQLElementList Read FFields;
|
Property Fields : TSQLElementList Read FFields;
|
||||||
Property Where : TSQLExpression read FWhere write FWhere;
|
Property Where : TSQLExpression read FWhere write FWhere;
|
||||||
@ -779,12 +780,12 @@ Type
|
|||||||
|
|
||||||
TSQLUpdatePair = Class(TSQLElement)
|
TSQLUpdatePair = Class(TSQLElement)
|
||||||
private
|
private
|
||||||
FFieldName: TSQLidentifierName;
|
FFieldName: TSQLIdentifierName;
|
||||||
FValue: TSQLExpression;
|
FValue: TSQLExpression;
|
||||||
Public
|
Public
|
||||||
Destructor Destroy; override;
|
Destructor Destroy; override;
|
||||||
Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; 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;
|
Property Value : TSQLExpression Read FValue Write FValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
This file is part of the Free Component Library
|
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
|
SQL Syntax Tree SQL generation tests
|
||||||
|
|
||||||
@ -31,11 +31,11 @@ type
|
|||||||
Private
|
Private
|
||||||
FToFree:TSQLElement;
|
FToFree:TSQLElement;
|
||||||
protected
|
protected
|
||||||
procedure SetUp; override;
|
Procedure SetUp; override;
|
||||||
procedure TearDown; override;
|
Procedure TearDown; override;
|
||||||
procedure DoTestDropStatement(AClass: TSQLDropStatementClass; const AObjectName: String);
|
Procedure DoTestDropStatement(AClass: TSQLDropStatementClass; const AObjectName: String);
|
||||||
procedure DoTestAlterCreateProcedure(S: TSQLAlterCreateProcedureStatement; PHEAD: String);
|
Procedure DoTestAlterCreateProcedure(S: TSQLAlterCreateProcedureStatement; PHEAD: String);
|
||||||
procedure DoTestAlterCreateTrigger(S: TSQLAlterCreateTriggerStatement; PHEAD: String);
|
Procedure DoTestAlterCreateTrigger(S: TSQLAlterCreateTriggerStatement; PHEAD: String);
|
||||||
Function CreateIdentifier(Const AName : TSQLStringType) : TSQLIdentifierName;
|
Function CreateIdentifier(Const AName : TSQLStringType) : TSQLIdentifierName;
|
||||||
Function CreateGrantee(Const AName : TSQLStringType; AClass : TSQLGranteeClass = Nil) : TSQLGrantee;
|
Function CreateGrantee(Const AName : TSQLStringType; AClass : TSQLGranteeClass = Nil) : TSQLGrantee;
|
||||||
Function CreateLiteral(Const AValue : Integer) : TSQLIntegerLiteral;
|
Function CreateLiteral(Const AValue : Integer) : TSQLIntegerLiteral;
|
||||||
|
@ -378,6 +378,7 @@ type
|
|||||||
procedure TestSelectTwoFieldsOneTable;
|
procedure TestSelectTwoFieldsOneTable;
|
||||||
procedure TestSelectOneFieldAliasOneTable;
|
procedure TestSelectOneFieldAliasOneTable;
|
||||||
procedure TestSelectTwoFieldAliasesOneTable;
|
procedure TestSelectTwoFieldAliasesOneTable;
|
||||||
|
procedure TestSelectOneTableFieldOneTable;
|
||||||
procedure TestSelectOneDistinctFieldOneTable;
|
procedure TestSelectOneDistinctFieldOneTable;
|
||||||
procedure TestSelectOneAllFieldOneTable;
|
procedure TestSelectOneAllFieldOneTable;
|
||||||
procedure TestSelectAsteriskOneTable;
|
procedure TestSelectAsteriskOneTable;
|
||||||
@ -427,6 +428,7 @@ type
|
|||||||
procedure TestOrderByOneDescField;
|
procedure TestOrderByOneDescField;
|
||||||
procedure TestOrderByTwoDescFields;
|
procedure TestOrderByTwoDescFields;
|
||||||
procedure TestOrderByThreeDescFields;
|
procedure TestOrderByThreeDescFields;
|
||||||
|
procedure TestOrderByOneTableField;
|
||||||
procedure TestOrderByOneColumn;
|
procedure TestOrderByOneColumn;
|
||||||
procedure TestOrderByTwoColumns;
|
procedure TestOrderByTwoColumns;
|
||||||
procedure TestOrderByTwoColumnsDesc;
|
procedure TestOrderByTwoColumnsDesc;
|
||||||
@ -3755,6 +3757,16 @@ begin
|
|||||||
AssertTable(Select.Tables[0],'A');
|
AssertTable(Select.Tables[0],'A');
|
||||||
end;
|
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;
|
procedure TTestSelectParser.TestSelectOneDistinctFieldOneTable;
|
||||||
begin
|
begin
|
||||||
TestSelect('SELECT DISTINCT B FROM A');
|
TestSelect('SELECT DISTINCT B FROM A');
|
||||||
@ -4274,6 +4286,7 @@ begin
|
|||||||
AssertOrderBy(Select.OrderBy[1],'D',0,obAscending);
|
AssertOrderBy(Select.OrderBy[1],'D',0,obAscending);
|
||||||
AssertOrderBy(Select.OrderBy[2],'E',0,obAscending);
|
AssertOrderBy(Select.OrderBy[2],'E',0,obAscending);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestSelectParser.TestOrderByOneDescField;
|
procedure TTestSelectParser.TestOrderByOneDescField;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@ -4312,6 +4325,19 @@ begin
|
|||||||
AssertOrderBy(Select.OrderBy[2],'E',0,obDescending);
|
AssertOrderBy(Select.OrderBy[2],'E',0,obDescending);
|
||||||
end;
|
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;
|
procedure TTestSelectParser.TestOrderByOneColumn;
|
||||||
begin
|
begin
|
||||||
TestSelect('SELECT B FROM A ORDER BY 1');
|
TestSelect('SELECT B FROM A ORDER BY 1');
|
||||||
|
Loading…
Reference in New Issue
Block a user