Browse Source

- fcl-db: sql parser
- remove support for SET TERM/SET AUTODDL as it does not fall within Firebird SQL

git-svn-id: trunk@27961 -

reiniero 11 years ago
parent
commit
951d128042

+ 2 - 90
packages/fcl-db/src/sql/fpsqlparser.pas

@@ -101,8 +101,6 @@ Type
     function ParseCreateViewStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
     function ParseCreateTriggerStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
     function ParseSetGeneratorStatement(AParent: TSQLElement) : TSQLSetGeneratorStatement;
-    function ParseSetISQLStatement(AParent: TSQLElement) : TSQLSetISQLStatement;
-    function ParseSetTermStatement(AParent: TSQLElement) : TSQLSetTermStatement;
     function ParseCreateDatabaseStatement(AParent: TSQLElement; IsAlter: Boolean ): TSQLCreateDatabaseStatement;
     function ParseCreateShadowStatement(AParent: TSQLElement; IsAlter: Boolean ): TSQLCreateShadowStatement;
     function ParseAlterDatabaseStatement(AParent: TSQLElement; IsAlter: Boolean ): TSQLAlterDatabaseStatement;
@@ -163,12 +161,6 @@ Type
     Function Parse : TSQLElement;
     // Parse script containing 1 or more elements
     Function ParseScript(AllowPartial : Boolean = False) : TSQLElementList;
-    // Gets statement terminator (as e.g. used in SET TERM) so statements like
-    // EXECUTE BLOCK or CREATE PROCEDURE that contain semicolons can be parsed
-    function GetStatementTerminator: string;
-    // Sets statement terminator (as e.g. used in SET TERM) so statements like
-    // EXECUTE BLOCK or CREATE PROCEDURE that contain semicolons can be parsed
-    procedure SetStatementTerminator(AValue: string);
     // Auxiliary stuff
     Function CurrentToken : TSQLToken;
     Function CurrentTokenString : String;
@@ -1522,7 +1514,7 @@ begin
     S:=ParseProcedureStatement(AParent);
     Statements.Add(S);
     if not (PreviousToken=tsqlEnd) then
-      Consume([tsqlSemicolon,tsqlStatementTerminator]);
+      Consume([tsqlSemicolon]);
     end;
   Consume(tsqlEnd);
 end;
@@ -2981,74 +2973,6 @@ begin
   end;
 end;
 
-function TSQLParser.ParseSetISQLStatement(AParent: TSQLElement
-  ): TSQLSetISQLStatement;
-begin
-  // On entry, we're on the first argument e.g. AUTODDL in SET AUTODDL
-  // for now, only support AutoDDL
-  //SET AUTODDL: ignore these isql commands for now
-  case CurrentToken of
-    tsqlAutoDDL:
-      begin
-      Result:=TSQLSetISQLStatement(CreateElement(TSQLSetISQLStatement,AParent));
-      // SET AUTODDL ON, SET AUTODDL OFF; optional arguments
-      if (PeekNextToken in [tsqlOn, tsqlOff]) then
-        begin
-        GetNextToken;
-        if CurrentToken=tsqlOFF then
-          Result.Arguments:='AUTODDL OFF'
-        else
-          Result.Arguments:='AUTODDL ON';
-        Consume([tsqlOn,tsqlOff]);
-        end
-      else
-        begin
-        Result.Arguments:='AUTODDL ON';
-        Consume(tsqlAutoDDL);
-        end;
-      end
-    else
-      UnexpectedToken;
-  end;
-end;
-
-function TSQLParser.ParseSetTermStatement(AParent: TSQLElement
-  ): TSQLSetTermStatement;
-var
-  ExistingStatTerm: string;
-begin
-  // On entry, we're on the 'TERM' token
-  Consume(tsqlTerm) ;
-  try
-    Result:=TSQLSetTermStatement(CreateElement(TSQLSetTermStatement,AParent));
-    Expect([tsqlSemiColon,tsqlStatementTerminator,tsqlSymbolString,tsqlString]);
-    // Already set the expression's new value to the new terminator, but do not
-    // change tSQLStatementTerminator as GetNextToken etc need the old one to
-    // detect the closing terminator
-    case CurrentToken of
-      tsqlSemiColon, tsqlStatementTerminator: Result.NewTerminator:=TokenInfos[CurrentToken];
-      tsqlSymbolString, tsqlString: Result.NewTerminator:=CurrentTokenString;
-    end;
-    // Expect the old terminator...
-    GetNextToken;
-    // Parser will give tsqlSemicolon rather than tsqlStatementTerminator:
-    if TokenInfos[tsqlStatementTerminator]=TokenInfos[tsqlSEMICOLON] then
-    begin
-      Expect(tsqlSEMICOLON);
-      Result.OldTerminator:=TokenInfos[tsqlSEMICOLON];
-    end
-    else
-    begin
-      Expect(tsqlStatementTerminator);
-      Result.OldTerminator:=TokenInfos[tsqlStatementTerminator];
-    end;
-    //... and now set the new terminator:
-    TokenInfos[tsqlStatementTerminator]:=Result.NewTerminator; //process new terminator value
-  except
-    FreeAndNil(Result);
-    Raise;
-  end;
-end;
 
 function TSQLParser.ParseSecondaryFile(AParent: TSQLElement) : TSQLDatabaseFileInfo;
 
@@ -3453,8 +3377,6 @@ begin
   Consume(tsqlSet);
   Case CurrentToken of
     tsqlGenerator : Result:=ParseSetGeneratorStatement(AParent); //SET GENERATOR
-    tsqlTerm : Result:=ParseSetTermStatement(AParent); //SET TERM
-    tsqlAutoDDL : Result:=ParseSetISQLStatement(AParent); //SET AUTODDL
   else
     // For the time being
     UnexpectedToken;
@@ -3971,7 +3893,7 @@ begin
   else
     UnexpectedToken;
   end;
-  if Not (CurrentToken in [tsqlEOF,tsqlSemicolon,tsqlStatementTerminator]) then
+  if Not (CurrentToken in [tsqlEOF,tsqlSemicolon]) then
     begin
     FreeAndNil(Result);
     if (CurrentToken=tsqlBraceClose) then
@@ -4003,16 +3925,6 @@ begin
   end;
 end;
 
-function TSQLParser.GetStatementTerminator: string;
-begin
-  result:=TokenInfos[tsqlStatementTerminator];
-end;
-
-procedure TSQLParser.SetStatementTerminator(AValue: string);
-begin
-  TokenInfos[tsqlStatementTerminator]:=AValue;;
-end;
-
 function TSQLParser.CurrentToken: TSQLToken;
 begin
   Result:=FCurrent;

+ 5 - 15
packages/fcl-db/src/sql/fpsqlscanner.pp

@@ -42,8 +42,6 @@ type
    tsqlIdentifier {a table etc name},
    tsqlSymbolString {a string 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.}
-   {todo: move this out of fpsqlscanner into fpsqlparser with an option to disable},
    tsqlBraceOpen,tsqlBraceClose,tsqlSquareBraceOpen,tsqlSquareBraceClose,
    tsqlPlaceHolder {question mark},
    tsqlCOMMA,tsqlCOLON,tsqlDOT,tsqlSEMICOLON,
@@ -51,7 +49,7 @@ type
    tsqlEQ,tsqlGE,tsqlLE,tsqlNE,
    { Reserved words/keywords start here. They must be last }
    { Note: if adding before tsqlALL or after tsqlWHEN please update FirstKeyword/LastKeyword }
-   tsqlALL, tsqlAND, tsqlANY, tsqlASC, tsqlASCENDING, tsqlAVG, tsqlALTER, tsqlAdd, tsqlActive, tsqlAction, tsqlAs,tsqlAt, tsqlAuto, tsqlAutoDDL {not an FB reserved word but used in isql scripts}, tsqlAfter,tsqlAdmin,
+   tsqlALL, tsqlAND, tsqlANY, tsqlASC, tsqlASCENDING, tsqlAVG, tsqlALTER, tsqlAdd, tsqlActive, tsqlAction, tsqlAs,tsqlAt, tsqlAuto, tsqlAfter,tsqlAdmin,
    tsqlBETWEEN, tsqlBinary, tsqlBY, tsqlBLOB, tsqlBegin, tsqlBefore,
    tsqlCOLLATE, tsqlCONTAINING, tsqlCOUNT, tsqlCREATE, tsqlCOLUMN, tsqlCONSTRAINT, tsqlChar,tsqlCHARACTER, tsqlCHECK, tsqlComputed,tsqlCASCADE, tsqlCast, tsqlCommit,tsqlConnect,tsqlCache,tsqlConditional,tsqlCString,
    tsqlDESC, tsqlDESCENDING, tsqlDISTINCT, tsqlDEFAULT, tsqlDELETE, tsqlDO, tsqlDouble, tsqlDECLARE, tsqlDROP, tsqlDomain, tsqlDecimal, tsqlDate,tsqlDatabase,
@@ -69,7 +67,7 @@ type
    tsqlPrecision, tsqlPRIMARY,  tsqlProcedure, tsqlPosition, tsqlPlan, tsqlPassword, tsqlPage,tsqlPages,tsqlPageSize,tsqlPostEvent,tsqlPrivileges,tsqlPublic,
    tsqlRIGHT, tsqlROLE, tsqlReferences, tsqlRollBack, tsqlRelease,  tsqlretain,  tsqlReturningValues,tsqlReturns, tsqlrevoke,
    tsqlSELECT, tsqlSET, tsqlSINGULAR, tsqlSOME, tsqlSTARTING, tsqlSUM, tsqlSKIP,tsqlSUBTYPE,tsqlSize,tsqlSegment, tsqlSORT, tsqlSnapShot,tsqlSchema,tsqlShadow,tsqlSuspend,tsqlSQLCode,tsqlSmallint,
-   tSQLTABLE, tsqlText, tsqlTerm {not an FB reserved word, used in isql scripts}, tsqlTrigger, tsqlTime, tsqlTimeStamp, tsqlType, tsqlTo, tsqlTransaction, tsqlThen,
+   tSQLTABLE, tsqlText, tsqlTrigger, tsqlTime, tsqlTimeStamp, tsqlType, tsqlTo, tsqlTransaction, tsqlThen,
    tsqlUNION, tsqlUPDATE, tsqlUPPER,  tsqlUNIQUE, tsqlUSER,
    tsqlValue, tsqlVALUES, tsqlVARIABLE,  tsqlVIEW, tsqlVARCHAR,TSQLVARYING,
    tsqlWHERE, tsqlWITH, tsqlWHILE, tsqlWork, tsqlWhen
@@ -89,15 +87,14 @@ const
        'EOF','whitespace',
        'String',
        'identifier',
-       'symbol literal',
+       'symbol string',
        'integer number','float number', 'comment',
-       ';' {value may be changed at run time to any symbol or set of symbols},
        '(',')', '[',']',
        '?',',',':','.',';','>','<',
        '+','-','*','/','||',
        '=','>=','<=','<>',
        // Identifiers last:
-       'ALL', 'AND', 'ANY', 'ASC', 'ASCENDING', 'AVG', 'ALTER', 'ADD','ACTIVE','ACTION', 'AS', 'AT', 'AUTO', 'AUTODDL', 'AFTER', 'ADMIN',
+       'ALL', 'AND', 'ANY', 'ASC', 'ASCENDING', 'AVG', 'ALTER', 'ADD','ACTIVE','ACTION', 'AS', 'AT', 'AUTO', 'AFTER', 'ADMIN',
        'BETWEEN', 'BINARY', 'BY', 'BLOB','BEGIN', 'BEFORE',
        'COLLATE', 'CONTAINING', 'COUNT', 'CREATE', 'COLUMN', 'CONSTRAINT', 'CHAR','CHARACTER','CHECK', 'COMPUTED','CASCADE','CAST', 'COMMIT', 'CONNECT', 'CACHE','CONDITIONAL', 'CSTRING',
        'DESC', 'DESCENDING', 'DISTINCT',  'DEFAULT', 'DELETE', 'DO', 'DOUBLE', 'DECLARE', 'DROP', 'DOMAIN', 'DECIMAL', 'DATE','DATABASE',
@@ -115,7 +112,7 @@ const
        'PRECISION', 'PRIMARY', 'PROCEDURE','POSITION','PLAN', 'PASSWORD','PAGE','PAGES','PAGE_SIZE','POST_EVENT','PRIVILEGES','PUBLIC',
        'RIGHT', 'ROLE', 'REFERENCES', 'ROLLBACK','RELEASE', 'RETAIN', 'RETURNING_VALUES', 'RETURNS','REVOKE',
        'SELECT', 'SET', 'SINGULAR', 'SOME', 'STARTING', 'SUM', 'SKIP','SUB_TYPE', 'SIZE', 'SEGMENT', 'SORT', 'SNAPSHOT','SCHEMA','SHADOW','SUSPEND','SQLCODE','SMALLINT',
-       'TABLE', 'TEXT', 'TERM', 'TRIGGER', 'TIME', 'TIMESTAMP', 'TYPE', 'TO', 'TRANSACTION', 'THEN',
+       'TABLE', 'TEXT', 'TRIGGER', 'TIME', 'TIMESTAMP', 'TYPE', 'TO', 'TRANSACTION', 'THEN',
        'UNION', 'UPDATE', 'UPPER', 'UNIQUE', 'USER',
        'VALUE','VALUES','VARIABLE', 'VIEW','VARCHAR','VARYING',
        'WHERE', 'WITH', 'WHILE','WORK','WHEN'
@@ -187,7 +184,6 @@ Type
     // Used to parse out an identifier/name and store it in the list of identifiers
     function DoIdentifier : TSQLToken;
     // Used to parse out a string containing symbols
-    // Also looks for tsqlStatementTerminator
     function DoSymbolString : TSQLToken;
     function DoMultiLineComment: TSQLToken;
     function DoNumericLiteral: TSQLToken;
@@ -692,12 +688,6 @@ begin
     SetLength(FCurTokenString,Len);
     Move(TokenStart^,FCurTokenString[1],Len);
 
-    // Check if it is the statement terminator
-    if FCurTokenString=TokenInfos[tsqlStatementTerminator] then
-      begin
-      exit(tsqlStatementTerminator);
-      end;
-
     // Check if this is a keyword or identifier/literal
     // Probably not (due to naming rules) but it doesn't hurt
     If FKeyWords.Count=0 then

+ 0 - 24
packages/fcl-db/src/sql/fpsqltree.pp

@@ -912,20 +912,6 @@ Type
     Property Arguments : string Read FArgument Write FArgument;
   end;
 
-  { TSQLSetTermStatement }
-
-  TSQLSetTermStatement = Class(TSQLStatement)
-  private
-    FNewValue: string;
-    FOldValue: string;
-  Public
-    Function GetAsSQL(Options : TSQLFormatOptions; AIndent : Integer = 0): TSQLStringType; override;
-    // The first, new terminator in the SET TERM statement
-    Property NewTerminator : string Read FNewValue Write FNewValue;
-    // The second, old terminator in the SET TERM statement
-    Property OldTerminator : string Read FOldValue Write FOldValue;
-  end;
-
   { TSQLCreateRoleStatement }
 
   TSQLCreateRoleStatement = Class(TSQLCreateOrAlterStatement)
@@ -1890,16 +1876,6 @@ begin
   Result:='-- SET '+Arguments;
 end;
 
-{ TSQLSetTermStatement }
-
-function TSQLSetTermStatement.GetAsSQL(Options: TSQLFormatOptions;
-  AIndent: Integer): TSQLStringType;
-begin
-  // Note: we generate this as a comment as this is ISQL-specific and will generate
-  // errors when passed as SQL to servers
-  Result:='-- SET TERM '+NewTerminator+' '+OldTerminator;
-end;
-
 function TSQLElementList.GetE(AIndex : Integer): TSQLElement;
 begin
   Result:=TSQLElement(Items[AIndex]);

+ 1 - 148
packages/fcl-db/tests/tcparser.pas

@@ -844,20 +844,6 @@ type
     procedure Test2RolesToUser;
   end;
 
-  { TTestSetParser }
-
-  TTestSetParser = Class(TTestSQLParser)
-  published
-    procedure TestSetAutoDDL;
-    procedure TestSetAutoDDLOn;
-    procedure TestSetAutoDDLOff;
-    procedure TestSetAutoDDLCreateProcedure;
-    procedure TestSetTerm;
-    procedure TestSetTermSemicolon;
-    procedure TestSetTermCreateProcedure;
-    procedure TestSetTermCreateProcedureVar;
-  end;
-
   { TTestGlobalParser }
 
   TTestGlobalParser = Class(TTestSQLParser)
@@ -869,138 +855,6 @@ implementation
 
 uses typinfo;
 
-{ TTestSetParser }
-
-procedure TTestSetParser.TestSetAutoDDL;
-Const
-  Desired='-- SET AUTODDL ON';
-Var
-  I: TSQLSetISQLStatement;
-begin
-  CreateParser('SET AUTODDL;');
-  FToFree:=Parser.Parse;
-  I:=TSQLSetISQLStatement(CheckClass(FToFree,TSQLSetISQLStatement));
-  AssertEquals('GetAsSQL',I.GetAsSQL([]),Desired);
-end;
-
-procedure TTestSetParser.TestSetAutoDDLOn;
-Const
-  Desired='-- SET AUTODDL ON';
-Var
-  I: TSQLSetISQLStatement;
-begin
-  CreateParser('SET AUTODDL ON;');
-  FToFree:=Parser.Parse;
-  I:=TSQLSetISQLStatement(CheckClass(FToFree,TSQLSetISQLStatement));
-  AssertEquals('GetAsSQL',I.GetAsSQL([]),Desired);
-end;
-
-procedure TTestSetParser.TestSetAutoDDLOff;
-Const
-  Desired='-- SET AUTODDL OFF';
-Var
-  I: TSQLSetISQLStatement;
-begin
-  CreateParser('SET AUTODDL OFF;');
-  FToFree:=Parser.Parse;
-  I:=TSQLSetISQLStatement(CheckClass(FToFree,TSQLSetISQLStatement));
-  AssertEquals('GetAsSQL',I.GetAsSQL([]),Desired);
-end;
-
-procedure TTestSetParser.TestSetAutoDDLCreateProcedure;
-Const
-  SQL =
-   'SET AUTODDL ;'+LineEnding+
-   ''+LineEnding+
-   'CREATE PROCEDURE PROCNAME'+LineEnding+
-   'AS'+LineEnding+
-   'BEGIN'+LineEnding+
-   '  /* Empty procedure */'+LineEnding+
-   'END;';
-begin
-  CreateParser(SQL);
-  Parser.ParseScript;
-  //todo: test name etc of procedure
-end;
-
-procedure TTestSetParser.TestSetTerm;
-Var
-  S : TSQLSetTermStatement;
-
-begin
-  CreateParser('SET TERM ^ ;');
-  FToFree:=Parser.Parse;
-  S:=TSQLSetTermStatement(CheckClass(FToFree,TSQLSetTermStatement));
-  AssertEquals('New terminator','^',S.NewTerminator);
-  AssertEquals('Closing semicolon',tsqlSEMICOLON,Parser.CurrentToken);
-  Parser.GetNextToken;
-  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
-end;
-
-procedure TTestSetParser.TestSetTermSemicolon;
-Var
-  S : TSQLSetTermStatement;
-
-begin
-  CreateParser('SET TERM ; ^');
-  FParser.SetStatementTerminator('^'); // emulate a previous SET TERM ^ ;
-  AssertEquals('Closing statement terminator should match ^','^',Parser.GetStatementTerminator);
-  FToFree:=Parser.Parse;
-  S:=TSQLSetTermStatement(CheckClass(FToFree,TSQLSetTermStatement));
-  AssertEquals('New terminator',';',S.NewTerminator);
-  AssertEquals('Closing terminator',tsqlStatementTerminator,Parser.CurrentToken);
-  AssertEquals('Closing ^','^',Parser.CurrentTokenString);
-  Parser.GetNextToken;
-  AssertEquals('End of stream reached',tsqlEOF,Parser.CurrentToken);
-end;
-
-procedure TTestSetParser.TestSetTermCreateProcedure;
-Const
-  SQL =
-   'SET TERM ^ ;'+LineEnding+
-   ''+LineEnding+
-   'CREATE PROCEDURE PROCNAME'+LineEnding+
-   'AS'+LineEnding+
-   'BEGIN'+LineEnding+
-   '  /* Empty procedure */'+LineEnding+
-   'END^'+LineEnding+
-   ''+LineEnding+
-   'SET TERM ; ^';
-
-begin
-  CreateParser(SQL);
-  Parser.ParseScript;
-  //todo: test name etc of procedure
-end;
-
-procedure TTestSetParser.TestSetTermCreateProcedureVar;
-// Procedure with variable
-Const
-  SQL =
-    'SET TERM ^ ;'+LineEnding+
-    'CREATE PROCEDURE PROCWITHVAR'+LineEnding+
-    'RETURNS (LANGUAGES VARCHAR(15) CHARACTER SET NONE)'+LineEnding+
-    'AS'+LineEnding+
-    'DECLARE VARIABLE i INTEGER;'+LineEnding+
-    'BEGIN'+LineEnding+
-    '  i = 1;'+LineEnding+
-    '  WHILE (i <= 5) DO'+LineEnding+
-    '  BEGIN'+LineEnding+
-    '    SELECT language_req[:i] FROM job'+LineEnding+
-    '    INTO :languages;'+LineEnding+
-    '    i = i +1;'+LineEnding+
-    '    SUSPEND;'+LineEnding+
-    '  END'+LineEnding+
-    'END ^'+LineEnding+
-    'SET TERM ; ^';
-
-begin
-  CreateParser(SQL);
-  Parser.ParseScript;
-  //todo: test name etc of procedure
-end;
-
-
 { TTestGlobalParser }
 
 procedure TTestGlobalParser.TestEmpty;
@@ -1040,7 +894,7 @@ end;
 
 procedure TTestSQLParser.SetUp;
 begin
-  FParser.SetStatementTerminator(';');
+  // nothing yet
 end;
 
 procedure TTestSQLParser.TearDown;
@@ -8317,7 +8171,6 @@ initialization
                  TTestDeclareExternalFunctionParser,
                  TTestGrantParser,
                  TTestRevokeParser,
-                 TTestSetParser,
                  TTestGlobalParser]);
 end.