Преглед изворни кода

sql parser: support table with schema

git-svn-id: trunk@46419 -
ondrej пре 5 година
родитељ
комит
f368c848a5

+ 8 - 1
packages/fcl-db/src/sql/fpsqlparser.pas

@@ -345,8 +345,15 @@ begin
      Expect(tsqlIdentifier);
      T:=TSQLSimpleTableReference(CreateElement(TSQLSimpleTableReference,AParent));
      Result:=T;
-     T.ObjectName:=CreateIdentifier(T,CurrentTokenString);
+     T.AddObjectNameToPath(CreateIdentifier(T,CurrentTokenString));
      GetNextToken;
+     while CurrentToken=tsqlDOT do
+       begin
+         GetNextToken;
+         Expect(tsqlIdentifier);
+         T.AddObjectNameToPath(CreateIdentifier(T,CurrentTokenString));
+         GetNextToken;
+       end;
      If CurrentToken=tsqlBraceOpen then
        begin
        T.Params:=ParseValueList(AParent,[eoParamValue]);

+ 60 - 6
packages/fcl-db/src/sql/fpsqltree.pp

@@ -607,12 +607,20 @@ Type
   TSQLSimpleTableReference = Class(TSQLTableReference)
   private
     FAliasName: TSQLIdentifierName;
-    FObjectName: TSQLIdentifierName;
+    FObjectNamePath: array of TSQLIdentifierName;
     FParams: TSQLElementList;
+    function GetObjectName: TSQLIdentifierName;
+    function GetObjectNamePath(Index: Integer): TSQLIdentifierName;
+    function GetObjectNamePathCount: Integer;
+    procedure SetObjectName(const AName: TSQLIdentifierName);
   Public
     Destructor Destroy; override;
     Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
-    Property ObjectName : TSQLIdentifierName Read FObjectName Write FObjectName;
+    Property ObjectName : TSQLIdentifierName Read GetObjectName Write SetObjectName;
+    Property ObjectNamePathCount: Integer Read GetObjectNamePathCount;
+    Procedure AddObjectNameToPath(AName: TSQLIdentifierName);
+    Procedure ClearObjectNamePath;
+    Property ObjectNamePath[Index: Integer] : TSQLIdentifierName Read GetObjectNamePath;
     Property Params : TSQLElementList Read FParams Write FParams;
     Property AliasName : TSQLIdentifierName Read FAliasName Write FAliasName;
   end;
@@ -3073,9 +3081,24 @@ end;
 
 { TSQLSimpleTableReference }
 
+procedure TSQLSimpleTableReference.AddObjectNameToPath(AName: TSQLIdentifierName);
+begin
+  SetLength(FObjectNamePath, Length(FObjectNamePath)+1);
+  FObjectNamePath[High(FObjectNamePath)] := AName;
+end;
+
+procedure TSQLSimpleTableReference.ClearObjectNamePath;
+var
+  N: TSQLIdentifierName;
+begin
+  for N in FObjectNamePath do
+    N.Free;
+  FObjectNamePath := nil;
+end;
+
 destructor TSQLSimpleTableReference.Destroy;
 begin
-  FreeAndNil(FObjectName);
+  ClearObjectNamePath;
   FreeAndNil(FParams);
   FreeAndNil(FAliasName);
   inherited Destroy;
@@ -3085,7 +3108,8 @@ function TSQLSimpleTableReference.GetAsSQL(Options: TSQLFormatOptions; AIndent :
 
 Var
   I : integer;
-
+  TableName: TSQLStringType;
+  N: TSQLIdentifierName;
 begin
   Result:='';
   If Assigned(FParams) and (FParams.Count>0) then
@@ -3098,12 +3122,42 @@ begin
       end;
     Result:='('+Result+')';
     end;
-  If Assigned(FObjectname) then
-    Result:= FObjectName.GetAsSQL(Options)+Result;
+  TableName := '';
+  for N in FObjectNamePath do
+    begin
+    if TableName<>'' then
+      TableName:=TableName+'.';
+    TableName:=TableName+N.GetAsSQL(Options);
+    end;
+  Result:= TableName+Result;
   if Assigned(FAliasName) then
     Result:=Result+' '+FAliasName.GetAsSQL(Options);
 end;
 
+function TSQLSimpleTableReference.GetObjectName: TSQLIdentifierName;
+begin
+  if Length(FObjectNamePath)>0 then
+    Result := FObjectNamePath[High(FObjectNamePath)]
+  else
+    Result := nil;
+end;
+
+function TSQLSimpleTableReference.GetObjectNamePath(Index: Integer): TSQLIdentifierName;
+begin
+  Result := FObjectNamePath[Index];
+end;
+
+function TSQLSimpleTableReference.GetObjectNamePathCount: Integer;
+begin
+  Result := Length(FObjectNamePath);
+end;
+
+procedure TSQLSimpleTableReference.SetObjectName(const AName: TSQLIdentifierName);
+begin
+  ClearObjectNamePath;
+  AddObjectNameToPath(AName);
+end;
+
 { TSQLJoinTableReference }
 
 destructor TSQLJoinTableReference.Destroy;

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

@@ -411,6 +411,7 @@ type
     procedure TestSelectTwoFieldsThreeTablesJoin;
     procedure TestSelectTwoFieldsBracketThreeTablesJoin;
     procedure TestSelectTwoFieldsThreeBracketTablesJoin;
+    procedure TestSelectTableWithSchema;
     procedure TestAggregateCount;
     procedure TestAggregateCountAsterisk;
     procedure TestAggregateCountAll;
@@ -3811,6 +3812,17 @@ begin
   AssertTable(Select.Tables[0],'A');
 end;
 
+procedure TTestSelectParser.TestSelectTableWithSchema;
+begin
+  TestSelect('SELECT B,C FROM S.A');
+  AssertField(Select.Fields[0],'B');
+  AssertField(Select.Fields[1],'C');
+  AssertEquals('One table',1,Select.Tables.Count);
+  AssertTable(Select.Tables[0],'A','');
+  AssertEquals('Table path has 2 objects',2,(Select.Tables[0] as TSQLSimpleTableReference).ObjectNamePathCount);
+  AssertEquals('Schema name = S','S',(Select.Tables[0] as TSQLSimpleTableReference).ObjectNamePath[0].Name);
+end;
+
 procedure TTestSelectParser.TestSelectOneDistinctFieldOneTable;
 begin
   TestSelect('SELECT DISTINCT B FROM A');