Browse Source

* 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 -

reiniero 11 years ago
parent
commit
c63b31c839

+ 16 - 4
packages/fcl-db/src/sql/fpsqlparser.pas

@@ -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;

+ 1 - 1
packages/fcl-db/src/sql/fpsqlscanner.pp

@@ -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,

+ 9 - 8
packages/fcl-db/src/sql/fpsqltree.pp

@@ -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;
 

+ 6 - 6
packages/fcl-db/tests/tcgensql.pas

@@ -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;

+ 26 - 0
packages/fcl-db/tests/tcparser.pas

@@ -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');