Quellcode durchsuchen

sql parser: unify identifier path code

git-svn-id: trunk@46434 -
ondrej vor 5 Jahren
Ursprung
Commit
9fca033ac3

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

@@ -353,13 +353,13 @@ begin
      Expect(tsqlIdentifier);
      T:=TSQLSimpleTableReference(CreateElement(TSQLSimpleTableReference,AParent));
      Result:=T;
-     T.AddObjectNameToPath(CreateIdentifier(T,CurrentTokenString));
+     T.ObjectNamePath.Add(CreateIdentifier(T,CurrentTokenString));
      GetNextToken;
      while CurrentToken=tsqlDOT do
        begin
          GetNextToken;
          Expect(tsqlIdentifier);
-         T.AddObjectNameToPath(CreateIdentifier(T,CurrentTokenString));
+         T.ObjectNamePath.Add(CreateIdentifier(T,CurrentTokenString));
          GetNextToken;
        end;
      If CurrentToken=tsqlBraceOpen then
@@ -2861,13 +2861,13 @@ begin
             Error(SErrUnexpectedToken,[CurrentTokenString]);
           // Plain identifier
           Result:=TSQLIdentifierExpression(CreateElement(TSQLIdentifierExpression,APArent));
-          TSQLIdentifierExpression(Result).AddIdentifierToPath(CreateIdentifier(Result,N));
+          TSQLIdentifierExpression(Result).IdentifierPath.Add(CreateIdentifier(Result,N));
           while (CurrentToken=tsqlDot) do
             begin
             GetNextToken;
             Expect(tsqlIdentifier);
             N:=CurrentTokenString;
-            TSQLIdentifierExpression(Result).AddIdentifierToPath(CreateIdentifier(Result,N));
+            TSQLIdentifierExpression(Result).IdentifierPath.Add(CreateIdentifier(Result,N));
             GetNextToken;
             end;
           // Array access ?

+ 61 - 94
packages/fcl-db/src/sql/fpsqltree.pp

@@ -183,25 +183,32 @@ Type
     Property Literal : TSQLLiteral Read FLiteral write FLiteral;
   end;
 
+  { TSQLIdentifierPath }
+
+  TSQLIdentifierPath = Class(TSQLElementList)
+  private
+    function GetI(AIndex : Integer): TSQLIdentifierName;
+    procedure SetI(AIndex : Integer; const AIdentifier: TSQLIdentifierName);
+  Public
+    Function Add(AName: TSQLIdentifierName): Integer;
+    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
+    Property Identifiers[AIndex : Integer] : TSQLIdentifierName Read GetI Write SetI; default;
+  end;
+
   { TSQLIdentifierExpression }
 
   TSQLIdentifierExpression = Class(TSQLExpression)
   private
     FElementIndex: Integer;
-    FIdentifierPath: array of TSQLIdentifierName;
+    FIdentifierPath: TSQLIdentifierPath;
     function GetIdentifier: TSQLIdentifierName;
-    function GetIdentifierPath(Index: Integer): TSQLIdentifierName;
-    function GetIdentifierPathCount: Integer;
     procedure SetIdentifier(const AName: TSQLIdentifierName);
   Public
     Constructor Create(AParent : TSQLElement); override;
     Destructor Destroy; override;
     Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
     Property Identifier : TSQLIdentifierName Read GetIdentifier Write SetIdentifier;
-    Property IdentifierPathCount: Integer Read GetIdentifierPathCount;
-    Procedure AddIdentifierToPath(AName: TSQLIdentifierName);
-    Procedure ClearIdentifierPath;
-    Property IdentifierPath[Index: Integer] : TSQLIdentifierName Read GetIdentifierPath;
+    Property IdentifierPath: TSQLIdentifierPath Read FIdentifierPath;
     // For array types: index of element in array
     Property ElementIndex : Integer Read FElementIndex Write FElementIndex;
   end;
@@ -615,20 +622,16 @@ Type
   TSQLSimpleTableReference = Class(TSQLTableReference)
   private
     FAliasName: TSQLIdentifierName;
-    FObjectNamePath: array of TSQLIdentifierName;
+    FObjectNamePath: TSQLIdentifierPath;
     FParams: TSQLElementList;
     function GetObjectName: TSQLIdentifierName;
-    function GetObjectNamePath(Index: Integer): TSQLIdentifierName;
-    function GetObjectNamePathCount: Integer;
     procedure SetObjectName(const AName: TSQLIdentifierName);
   Public
+    constructor Create(AParent: TSQLElement); override;
     Destructor Destroy; override;
     Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
     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 ObjectNamePath : TSQLIdentifierPath Read FObjectNamePath;
     Property Params : TSQLElementList Read FParams Write FParams;
     Property AliasName : TSQLIdentifierName Read FAliasName Write FAliasName;
   end;
@@ -1969,6 +1972,36 @@ begin
     Sep:=', ';
 end;
 
+{ TSQLIdentifierPath }
+
+function TSQLIdentifierPath.Add(AName: TSQLIdentifierName): Integer;
+begin
+  Result := inherited Add(AName);
+end;
+
+function TSQLIdentifierPath.GetAsSQL(Options: TSQLFormatOptions; AIndent: Integer): TSQLStringType;
+var
+  N: TSQLElement;
+begin
+  Result := '';
+  for Pointer(N) in Self do
+    begin
+    if Result<>'' then
+      Result:=Result+'.';
+    Result:=Result+N.GetAsSQL(Options);
+    end;
+end;
+
+function TSQLIdentifierPath.GetI(AIndex: Integer): TSQLIdentifierName;
+begin
+  Result := TSQLIdentifierName(inherited Items[AIndex]);
+end;
+
+procedure TSQLIdentifierPath.SetI(AIndex: Integer; const AIdentifier: TSQLIdentifierName);
+begin
+  inherited Items[AIndex] := AIdentifier;
+end;
+
 { TSQLCaseExpressionBranch }
 
 destructor TSQLCaseExpressionBranch.Destroy;
@@ -3227,24 +3260,15 @@ end;
 
 { TSQLSimpleTableReference }
 
-procedure TSQLSimpleTableReference.AddObjectNameToPath(AName: TSQLIdentifierName);
+constructor TSQLSimpleTableReference.Create(AParent: TSQLElement);
 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;
+  inherited Create(AParent);
+  FObjectNamePath:=TSQLIdentifierPath.Create;
 end;
 
 destructor TSQLSimpleTableReference.Destroy;
 begin
-  ClearObjectNamePath;
+  FreeAndNil(FObjectNamePath);
   FreeAndNil(FParams);
   FreeAndNil(FAliasName);
   inherited Destroy;
@@ -3254,8 +3278,6 @@ function TSQLSimpleTableReference.GetAsSQL(Options: TSQLFormatOptions; AIndent :
 
 Var
   I : integer;
-  TableName: TSQLStringType;
-  N: TSQLIdentifierName;
 begin
   Result:='';
   If Assigned(FParams) and (FParams.Count>0) then
@@ -3268,40 +3290,20 @@ begin
       end;
     Result:='('+Result+')';
     end;
-  TableName := '';
-  for N in FObjectNamePath do
-    begin
-    if TableName<>'' then
-      TableName:=TableName+'.';
-    TableName:=TableName+N.GetAsSQL(Options);
-    end;
-  Result:= TableName+Result;
+  Result:= FObjectNamePath.GetAsSQL(Options, AIndent)+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);
+  Result := TSQLIdentifierName(FObjectNamePath.Last);
 end;
 
 procedure TSQLSimpleTableReference.SetObjectName(const AName: TSQLIdentifierName);
 begin
-  ClearObjectNamePath;
-  AddObjectNameToPath(AName);
+  FObjectNamePath.Clear;
+  FObjectNamePath.Add(AName);
 end;
 
 { TSQLJoinTableReference }
@@ -4292,67 +4294,32 @@ end;
 constructor TSQLIdentifierExpression.Create(AParent: TSQLElement);
 begin
   inherited Create(AParent);
+  FIdentifierPath:=TSQLIdentifierPath.Create;
   FElementIndex:=-1;
 end;
 
-procedure TSQLIdentifierExpression.AddIdentifierToPath(AName: TSQLIdentifierName);
-begin
-  SetLength(FIdentifierPath, Length(FIdentifierPath)+1);
-  FIdentifierPath[High(FIdentifierPath)] := AName;
-end;
-
-procedure TSQLIdentifierExpression.ClearIdentifierPath;
-var
-  N: TSQLIdentifierName;
-begin
-  for N in FIdentifierPath do
-    N.Free;
-  FIdentifierPath:=nil;
-end;
-
 destructor TSQLIdentifierExpression.Destroy;
 begin
-  ClearIdentifierPath;
+  FreeAndNil(FIdentifierPath);
   inherited Destroy;
 end;
 
 function TSQLIdentifierExpression.GetAsSQL(Options: TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType;
-var
-  N: TSQLIdentifierName;
 begin
-  Result := '';
-  for N in FIdentifierPath do
-    begin
-    if Result<>'' then
-      Result:=Result+'.';
-    Result:=Result+N.GetAsSQL(Options);
-    end;
+  Result := FIdentifierPath.GetAsSQL(Options, AIndent);
   If (ElementIndex<>-1) then
     Result:=Result+Format('[%d]',[Elementindex]);
 end;
 
 function TSQLIdentifierExpression.GetIdentifier: TSQLIdentifierName;
 begin
-  if Length(FIdentifierPath)>0 then
-    Result:=FIdentifierPath[High(FIdentifierPath)]
-  else
-    Result:=nil;
-end;
-
-function TSQLIdentifierExpression.GetIdentifierPath(Index: Integer): TSQLIdentifierName;
-begin
-  Result := FIdentifierPath[Index];
-end;
-
-function TSQLIdentifierExpression.GetIdentifierPathCount: Integer;
-begin
-  Result := Length(FIdentifierPath);
+  Result := TSQLIdentifierName(FIdentifierPath.Last);
 end;
 
 procedure TSQLIdentifierExpression.SetIdentifier(const AName: TSQLIdentifierName);
 begin
-  ClearIdentifierPath;
-  AddIdentifierToPath(AName);
+  FIdentifierPath.Clear;
+  FIdentifierPath.Add(AName);
 end;
 
 { TSQLSelectExpression }

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

@@ -427,8 +427,8 @@ Var
 
 begin
   I:=CreateIdentifierExpression('A');
-  I.AddIdentifierToPath(CreateIdentifier('B'));
-  I.AddIdentifierToPath(CreateIdentifier('C'));
+  I.IdentifierPath.Add(CreateIdentifier('B'));
+  I.IdentifierPath.Add(CreateIdentifier('C'));
   F:=CreateSelectField(I,'');
   AssertSQL(F,'A.B.C', []);
   AssertSQL(F,'"A"."B"."C"',[sfoDoubleQuoteIdentifier]);

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

@@ -3787,13 +3787,13 @@ begin
   AssertEquals('Two fields',2,Select.Fields.Count);
   AssertField(Select.Fields[0],'B');
   Expr := ((Select.Fields[0] as TSQLSelectField).Expression as TSQLIdentifierExpression);
-  AssertEquals('Field[0] path has 3 identifiers',3,Expr.IdentifierPathCount);
+  AssertEquals('Field[0] path has 3 identifiers',3,Expr.IdentifierPath.Count);
   AssertEquals('Field[0] schema is S','S',Expr.IdentifierPath[0].Name);
   AssertEquals('Field[0] table is A','A',Expr.IdentifierPath[1].Name);
   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('Table path has 2 objects',2,(Select.Tables[0] as TSQLSimpleTableReference).ObjectNamePath.Count);
   AssertEquals('Schema name = S','S',(Select.Tables[0] as TSQLSimpleTableReference).ObjectNamePath[0].Name);
 end;
 
@@ -3938,7 +3938,7 @@ begin
   // Field supports linking/refering to a table
   AssertField(Select.Fields[0],'B');
   Expr := ((Select.Fields[0] as TSQLSelectField).Expression as TSQLIdentifierExpression);
-  AssertEquals('Field has explicit table',2,Expr.IdentifierPathCount);
+  AssertEquals('Field has explicit table',2,Expr.IdentifierPath.Count);
   AssertEquals('Field has explicit table named A','A',Expr.IdentifierPath[0].Name);
   AssertEquals('One table',1,Select.Tables.Count);
   AssertTable(Select.Tables[0],'A');
@@ -3952,7 +3952,7 @@ begin
   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('Table path has 2 objects',2,(Select.Tables[0] as TSQLSimpleTableReference).ObjectNamePath.Count);
   AssertEquals('Schema name = S','S',(Select.Tables[0] as TSQLSimpleTableReference).ObjectNamePath[0].Name);
 end;
 
@@ -4013,7 +4013,7 @@ begin
   AssertEquals('One field',1,Select.Fields.Count);
   AssertField(Select.Fields[0],'B');
   Expr := ((Select.Fields[0] as TSQLSelectField).Expression as TSQLIdentifierExpression);
-  AssertEquals('Field has explicit table',2,Expr.IdentifierPathCount);
+  AssertEquals('Field has explicit table',2,Expr.IdentifierPath.Count);
   AssertEquals('Field has explicit table named C','C',Expr.IdentifierPath[0].Name);
   AssertEquals('One table',1,Select.Tables.Count);
   AssertTable(Select.Tables[0],'A');
@@ -4029,7 +4029,7 @@ begin
   AssertEquals('One field',1,Select.Fields.Count);
   AssertField(Select.Fields[0],'B');
   Expr := ((Select.Fields[0] as TSQLSelectField).Expression as TSQLIdentifierExpression);
-  AssertEquals('Field has explicit table',2,Expr.IdentifierPathCount);
+  AssertEquals('Field has explicit table',2,Expr.IdentifierPath.Count);
   AssertEquals('Field has explicit table named C','C',Expr.IdentifierPath[0].Name);
   AssertEquals('One table',1,Select.Tables.Count);
   AssertTable(Select.Tables[0],'A');