fpsqlparser.pas 114 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005
  1. {
  2. This file is part of the Free Component Library
  3. Copyright (c) 2010-2014 by the Free Pascal development team
  4. SQL source syntax parser
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit fpsqlparser;
  12. { $define debugparser}
  13. { $define debugexpr}
  14. {$mode objfpc}{$H+}
  15. interface
  16. uses
  17. Classes, SysUtils, fpsqlscanner, fpsqltree;
  18. Type
  19. TParseTypeFlag = (ptfAllowDomainName,ptfAlterDomain,ptfAllowConstraint,
  20. ptProcedureParam,ptfTableFieldDef,ptfCast,ptfExternalFunction,
  21. ptfExternalFunctionResult);
  22. TParseTypeFlags = Set of TParseTypeFlag;
  23. TExpressionOption = (eoCheckConstraint,eoTableConstraint,eoComputedBy,eoOnlyNull,
  24. eoFieldValue,eoSelectvalue,eoParamValue,eoWhereClause,eoJoin,
  25. eoHaving,eoListValue, eoIF);
  26. TExpressionOptions = set of TExpressionOption;
  27. TSelectFlag = (sfSingleTon,sfUnion,sfInto);
  28. TSelectFlags = Set of TSelectFlag;
  29. { TSQLParser }
  30. TSQLParser = Class(TObject)
  31. Private
  32. FInput : TStream;
  33. FScanner : TSQLScanner;
  34. FCurrent : TSQLToken;
  35. FCurrentString : String;
  36. FPrevious : TSQLToken;
  37. FFreeScanner : Boolean;
  38. FPeekToken: TSQLToken;
  39. FPeekTokenString: String;
  40. Procedure CheckEOF;
  41. protected
  42. procedure UnexpectedToken; overload;
  43. procedure UnexpectedToken(AExpected : TSQLTokens); overload;
  44. // All elements must be created with this factory function
  45. function CreateElement(AElementClass : TSQLElementClass; APArent : TSQLElement) : TSQLElement; virtual;
  46. function CreateLiteral(AParent: TSQLElement): TSQLLiteral;
  47. function CreateIdentifier(AParent : TSQLElement; Const AName : TSQLStringType) : TSQLIdentifierName;
  48. // Verify that current token is the expected token; raise error if not
  49. procedure Expect(aToken: TSQLToken);
  50. // Verify that current token is one of the expected tokens; raise error if not
  51. procedure Expect(aTokens: TSQLTokens);
  52. // Expects aToken as current token and eats it by calling GetNextToken
  53. procedure Consume(aToken: TSQLToken);
  54. // Expects aTokens tokens and eats the token by calling GetNextToken
  55. procedure Consume(aTokens: TSQLTokens);
  56. procedure Error(Msg : String);
  57. procedure Error(Fmt : String; Args : Array of const);
  58. // Expression support
  59. function ParseExprLevel1(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
  60. function ParseExprLevel2(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
  61. function ParseExprLevel3(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
  62. function ParseExprLevel4(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
  63. function ParseExprLevel5(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
  64. function ParseExprLevel6(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
  65. function ParseExprPrimitive(AParent: TSQLElement; EO : TExpressionOptions): TSQLExpression;
  66. function ParseInoperand(AParent: TSQLElement): TSQLExpression;
  67. // Lists, primitives
  68. function ParseIdentifierList(AParent: TSQLElement; AList: TSQLelementList): integer;
  69. function ParseValueList(AParent: TSQLElement; EO : TExpressionOptions): TSQLElementList;
  70. function ParseSQLValue(AParent: TSQLElement): TSQLExpression;
  71. function ParseCheckConstraint(AParent: TSQLElement; TableConstraint : Boolean = False): TSQLExpression;
  72. // Create/Alter statements
  73. function ParseAddTableElement(AParent: TSQLElement): TSQLAlterTableAddElementOperation;
  74. function ParseAlterTableElement(AParent: TSQLElement): TSQLAlterTableOperation;
  75. function ParseDropTableElement(AParent: TSQLElement): TSQLDropTableElementOperation;
  76. function ParseFieldConstraint(AParent: TSQLElement): TSQLFieldConstraint;
  77. function ParseForeignKeyDefinition(AParent: TSQLElement): TSQLForeignKeyDefinition;
  78. Procedure ParseCharTypeDefinition(Out DT: TSQLDataType; Out Len: Integer; Out ACharset : TSQLStringType);
  79. procedure ParseBlobDefinition(var ASegmentSize, ABlobType: Integer; Var ACharset : TSQLStringType);
  80. function ParseTypeDefinition(AParent: TSQLElement; Flags: TParseTypeFlags): TSQLTypeDefinition;
  81. function ParseTableFieldDef(AParent: TSQLElement): TSQLTableFieldDef;
  82. function ParseTableConstraint(AParent: TSQLElement): TSQLTableConstraintDef;
  83. function ParseCreateDomainStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
  84. function ParseCreateExceptionStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
  85. function ParseCreateGeneratorStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
  86. function ParseCreateRoleStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
  87. function ParseCreateIndexStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
  88. function ParseCreateProcedureStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
  89. function ParseCreateTableStatement(AParent: TSQLElement): TSQLCreateOrAlterStatement;
  90. function ParseAlterTableStatement(AParent: TSQLElement): TSQLAlterTableStatement;
  91. function ParseCreateViewStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
  92. function ParseCreateTriggerStatement(AParent: TSQLElement; IsAlter: Boolean): TSQLCreateOrAlterStatement;
  93. function ParseSetGeneratorStatement(AParent: TSQLElement) : TSQLSetGeneratorStatement;
  94. function ParseSetTermStatement(AParent: TSQLElement) : TSQLSetTermStatement;
  95. function ParseCreateDatabaseStatement(AParent: TSQLElement; IsAlter: Boolean ): TSQLCreateDatabaseStatement;
  96. function ParseCreateShadowStatement(AParent: TSQLElement; IsAlter: Boolean ): TSQLCreateShadowStatement;
  97. function ParseAlterDatabaseStatement(AParent: TSQLElement; IsAlter: Boolean ): TSQLAlterDatabaseStatement;
  98. function ParseSecondaryFile(AParent: TSQLElement): TSQLDatabaseFileInfo;
  99. function ParseDeclareFunctionStatement(AParent: TSQLElement): TSQLDeclareExternalFunctionStatement;
  100. function ParseDeclareStatement(AParent: TSQLElement): TSQLStatement;
  101. // GRANT parsing
  102. procedure ParseGranteeList(AParent: TSQLElement; List: TSQLElementList; AllowObject, AllowGroup,AllowPublic : Boolean; IsRevoke: Boolean = False);
  103. function ParseGrantExecuteStatement(AParent: TSQLElement): TSQLProcedureGrantStatement;
  104. function ParseGrantRoleStatement(AParent: TSQLElement): TSQLRoleGrantStatement;
  105. function ParseGrantTableStatement(AParent: TSQLElement): TSQLTableGrantStatement;
  106. // REVOKE parsing
  107. function ParseRevokeExecuteStatement(AParent: TSQLElement): TSQLProcedureRevokeStatement;
  108. function ParseRevokeRoleStatement(AParent: TSQLElement): TSQLRoleRevokeStatement;
  109. function ParseRevokeTableStatement(AParent: TSQLElement): TSQLTableRevokeStatement;
  110. // SELECT parsing
  111. function ParseExprAggregate(AParent: TSQLElement; EO: TExpressionOptions): TSQLAggregateFunctionExpression;
  112. procedure ParseFromClause(AParent: TSQLSelectStatement; AList: TSQLElementList);
  113. procedure ParseGroupBy(AParent: TSQLSelectStatement; AList: TSQLElementList);
  114. procedure ParseOrderBy(AParent: TSQLSelectStatement; AList: TSQLElementList);
  115. procedure ParseSelectFieldList(AParent: TSQLSelectStatement; AList: TSQLElementList; Singleton : Boolean);
  116. function ParseForUpdate(AParent: TSQLSelectStatement): TSQLElementList;
  117. function ParseSelectPlan(AParent: TSQLElement): TSQLSelectPlan;
  118. function ParseTableRef(AParent: TSQLSelectStatement): TSQLTableReference;
  119. procedure ParseIntoList(AParent: TSQLElement; List: TSQLElementList);
  120. // EXECUTE parsing
  121. function ParseExecuteProcedureStatement(AParent: TSQLElement): TSQLExecuteProcedureStatement;
  122. // Stored procedure parsing
  123. function ParseAssignStatement(AParent: TSQLElement): TSQLAssignStatement;
  124. function ParseExceptionStatement(AParent: TSQLElement): TSQLExceptionStatement;
  125. function ParseForStatement(AParent: TSQLElement): TSQLForStatement;
  126. function ParseIfStatement(AParent: TSQLElement): TSQLIFStatement;
  127. function ParsePostEventStatement(AParent: TSQLElement): TSQLPostEventStatement;
  128. procedure ParseProcedureParamList(AParent: TSQLElement; AList: TSQLElementList);
  129. procedure ParseCreateProcedureVariableList(AParent: TSQLElement; AList: TSQLElementList);
  130. function ParseProcedureStatement(AParent: TSQLElement): TSQLStatement;
  131. procedure ParseStatementBlock(AParent: TSQLElement; Statements: TSQLElementList);
  132. function ParseWhenStatement(AParent: TSQLElement): TSQLWhenStatement;
  133. function ParseWhileStatement(AParent: TSQLElement): TSQLWhileStatement;
  134. Public
  135. Constructor Create(AInput: TStream);
  136. Constructor Create(AScanner : TSQLScanner);
  137. Destructor Destroy; override;
  138. Function ParseSelectStatement(AParent : TSQLElement; Flags : TSelectFlags = []) : TSQLSelectStatement;
  139. Function ParseUpdateStatement(AParent : TSQLElement) : TSQLUpdateStatement;
  140. Function ParseInsertStatement(AParent : TSQLElement) : TSQLInsertStatement;
  141. Function ParseDeleteStatement(AParent : TSQLElement) : TSQLDeleteStatement;
  142. // Parses both create and alter statements
  143. Function ParseCreateStatement(AParent : TSQLElement; IsAlter : Boolean = False) : TSQLCreateOrAlterStatement;
  144. Function ParseDropStatement(AParent : TSQLElement) : TSQLDropStatement;
  145. Function ParseRollbackStatement(AParent : TSQLElement) : TSQLRollbackStatement;
  146. Function ParseCommitStatement(AParent : TSQLElement) : TSQLCommitStatement;
  147. Function ParseSetStatement(AParent : TSQLElement) : TSQLStatement;
  148. Function ParseConnectStatement(AParent : TSQLElement) : TSQLConnectStatement;
  149. Function ParseGrantStatement(AParent: TSQLElement): TSQLGrantStatement;
  150. Function ParseRevokeStatement(AParent: TSQLElement): TSQLGrantStatement;
  151. Function Parse : TSQLElement;
  152. Function ParseScript(AllowPartial : Boolean = False) : TSQLElementList;
  153. // Gets statement terminator (as e.g. used in SET TERM) so statements like
  154. // EXECUTE BLOCK or CREATE PROCEDURE that contain semicolons can be parsed
  155. function GetStatementTerminator: string;
  156. // Sets statement terminator (as e.g. used in SET TERM) so statements like
  157. // EXECUTE BLOCK or CREATE PROCEDURE that contain semicolons can be parsed
  158. procedure SetStatementTerminator(AValue: string);
  159. // Auxiliary stuff
  160. Function CurrentToken : TSQLToken;
  161. Function CurrentTokenString : String;
  162. // Gets next token; also updates current token
  163. Function GetNextToken : TSQLToken;
  164. // Looks at next token without changing current token
  165. Function PeekNextToken : TSQLToken;
  166. Function PreviousToken : TSQLToken;
  167. Function IsEndOfLine : Boolean;
  168. function CurSource: String;
  169. Function CurLine : Integer;
  170. Function CurPos : Integer;
  171. end;
  172. { ESQLParser }
  173. ESQLParser = Class(Exception)
  174. private
  175. FCol: Integer;
  176. FFileName: String;
  177. FLine: Integer;
  178. Public
  179. Property Line : Integer Read FLine Write FLine;
  180. Property Col : Integer Read FCol Write FCol;
  181. Property FileName : String Read FFileName Write FFileName;
  182. end;
  183. Function StringToSQLExtractElement(Const S : TSQLStringType; Out Res : TSQLExtractElement) : Boolean;
  184. implementation
  185. uses typinfo;
  186. Resourcestring
  187. SerrUnmatchedBrace = 'Expected ).';
  188. SErrCommaOrBraceExpected = 'Expected , or ).';
  189. SErrUnexpectedToken = 'Unexpected token: %s';
  190. SErrUnexpectedTokenOf = 'Unexpected token: %s, expected one of %s';
  191. SErrTokenMismatch = 'Unexpected token: ''%s'', expected: ''%s''';
  192. SErrExpectedDBObject = 'Expected database object type. Got: ''%s''';
  193. SErrDomainNotAllowed = 'Domain name not allowed in type definition.';
  194. SErrExpectedChar = 'Expected CHAR or CHARACTER, got "%s"';
  195. SErrVaryingNotAllowed = 'VARYING not allowed at this point.';
  196. SErrUnknownBooleanOp = 'Unknown boolean operation';
  197. SErrUnknownComparison = 'unknown Comparison operation';
  198. SErrIntegerExpected = 'Integer expression expected';
  199. SErrInvalidUseOfCollate = 'Invalid use of COLLATE';
  200. SErrCannotAlterGenerator = 'Alter generator statement unknown';
  201. SErrInvalidLiteral = 'Invalid literal: "%s"';
  202. SErrNoAggregateAllowed = 'Aggregate function not allowed.';
  203. SErrAsteriskOnlyInCount = '* allowed only in COUNT aggregate';
  204. SErrUpperOneArgument = 'Only one argument for UPPER allowed';
  205. SErrHavingWithoutGroupBy = 'HAVING without GROUP BY clause not allowed';
  206. SErrNoAsteriskInSingleTon = '* not allowed in singleton select';
  207. SErrUnionFieldCountMatch = 'Field count mismatch in select union : %d <> %d';
  208. SErrInvalidExtract = 'Invalid element for extract: %s';
  209. SErrOuterWithout = 'OUTER without previous LEFT, RIGHT or FULL';
  210. Function StringToSQLExtractElement(Const S : TSQLStringType; Out Res : TSQLExtractElement) : Boolean;
  211. Var
  212. I : TSQLExtractElement;
  213. SU : TSQLStringTYpe;
  214. begin
  215. Result:=False;
  216. SU:=Uppercase(S);
  217. For I:=Low(TSQLExtractElement) to High(TSQLExtractElement) do
  218. If ExtractElementNames[i]=SU then
  219. begin
  220. Res:=I;
  221. Exit(True);
  222. end;
  223. end;
  224. { TSQLParser }
  225. procedure TSQLParser.Expect(aToken: TSQLToken);
  226. begin
  227. {$ifdef debugparser} Writeln('Expecting : ',GetEnumName(TypeInfo(TSQLToken),Ord(AToken)), ' As string: ',TokenInfos[AToken]);{$endif debugparser}
  228. If (CurrentToken<>aToken) then
  229. Error(SerrTokenMismatch,[CurrenttokenString,TokenInfos[aToken]]);
  230. end;
  231. procedure TSQLParser.Expect(aTokens: TSQLTokens);
  232. begin
  233. if not (CurrentToken in aTokens) then
  234. UnexpectedToken(aTokens);
  235. end;
  236. procedure TSQLParser.Consume(aToken: TSQLToken);
  237. begin
  238. Expect(aToken);
  239. GetNextToken;
  240. end;
  241. procedure TSQLParser.Consume(aTokens: TSQLTokens);
  242. begin
  243. Expect(aTokens);
  244. GetNextToken;
  245. end;
  246. function TSQLParser.CurSource: String;
  247. begin
  248. Result:=FScanner.CurFilename;
  249. end;
  250. function TSQLParser.CurLine: Integer;
  251. begin
  252. Result:=FScanner.CurRow;
  253. end;
  254. function TSQLParser.CurPos: Integer;
  255. begin
  256. Result:=FScanner.CurColumn;
  257. end;
  258. procedure TSQLParser.Error(Msg: String);
  259. Var
  260. ErrAt : String;
  261. E : ESQLParser;
  262. begin
  263. If Assigned(FScanner) then
  264. If FScanner.CurFilename<>'' then
  265. ErrAt:=Format('Error: file "%s" line %d, pos %d: ',[FScanner.CurFileName,FScanner.CurRow,FScanner.CurColumn])
  266. else
  267. ErrAt:=Format('Error: line %d, pos %d: ',[FScanner.Currow,FScanner.CurColumn]);
  268. E:=ESQLParser.Create(ErrAt+Msg);
  269. If Assigned(FScanner) then
  270. begin
  271. E.Line:=FScanner.CurRow;
  272. E.Col:=FScanner.CurColumn;
  273. E.FileName:=FScanner.CurFilename;
  274. end;
  275. Raise E;
  276. end;
  277. procedure TSQLParser.Error(Fmt: String; Args: array of const);
  278. begin
  279. Error(Format(Fmt,Args));
  280. end;
  281. function TSQLParser.CreateElement(AElementClass: TSQLElementClass;
  282. APArent: TSQLElement): TSQLElement;
  283. begin
  284. Result:=AElementClass.Create(AParent);
  285. Result.Source:=CurSource;
  286. Result.SourceLine:=CurLine;
  287. Result.SourcePos:=CurPos;
  288. end;
  289. function TSQLParser.ParseTableRef(AParent: TSQLSelectStatement
  290. ): TSQLTableReference;
  291. Var
  292. T : TSQLSimpleTablereference;
  293. J : TSQLJoinTableReference;
  294. begin
  295. If (CurrentToken=tsqlBraceOpen) then
  296. begin
  297. GetNextToken;
  298. Result:=ParseTableRef(AParent);
  299. Consume(tsqlBraceClose)
  300. end
  301. else
  302. begin
  303. Expect(tsqlIdentifier);
  304. T:=TSQLSimpleTableReference(CreateElement(TSQLSimpleTableReference,AParent));
  305. Result:=T;
  306. T.ObjectName:=CreateIdentifier(T,CurrentTokenString);
  307. GetNextToken;
  308. If CurrentToken=tsqlBraceOpen then
  309. begin
  310. T.Params:=ParseValueList(AParent,[eoParamValue]);
  311. GetNextToken;
  312. end;
  313. // Table aliases with and without AS keyword
  314. if (CurrentToken in [tsqlIdentifier,tsqlAs]) then
  315. begin
  316. if CurrentToken=tsqlAs then
  317. begin
  318. GetNextToken;
  319. Expect(tsqlIdentifier);
  320. end;
  321. T.AliasName:=CreateIdentifier(T,CurrentTokenString);
  322. GetNextToken;
  323. end;
  324. end;
  325. Repeat
  326. If CurrentToken in [tsqlInner,tsqlFull,tsqlJoin,tsqlOuter,tsqlLeft,tsqlRight] then
  327. begin
  328. J:=TSQLJoinTableReference(CreateElement(TSQLJoinTableReference,AParent));
  329. J.Left:=Result;
  330. Result:=J;
  331. Case CurrentToken of
  332. tsqlInner : J.JoinType:=jtInner;
  333. tsqlJoin : J.JoinType:=jtNone;
  334. tsqlFull : J.JoinType:=jtFullOuter;
  335. tsqlLeft : J.JoinType:=jtLeft;
  336. tsqlRight : J.JoinType:=jtRight;
  337. end;
  338. if CurrentToken<>tsqlJoin then
  339. GetNextToken;
  340. // Ignore OUTER in FULL OUTER, LEFT OUTER, RIGHT OUTER...:
  341. if CurrentToken=tsqlOuter then
  342. begin
  343. if PreviousToken in [tsqlFull, tsqlLeft, tSQLRight] then
  344. Consume(tsqlOuter)
  345. else
  346. Error(SErrOuterWithout);
  347. end;
  348. Consume(tsqlJoin);
  349. J.Right:=ParseTableRef(AParent);
  350. Consume(tsqlOn);
  351. J.JoinClause:=ParseExprLevel1(J,[eoJOIN]);
  352. end;
  353. until Not (CurrentToken in [tsqlInner,tsqlFull,tsqlJoin,tsqlOuter,tsqlLeft,tsqlRight]);
  354. end;
  355. procedure TSQLParser.ParseFromClause(AParent: TSQLSelectStatement;
  356. AList: TSQLElementList);
  357. Var
  358. T : TSQLTableReference;
  359. Done : Boolean;
  360. begin
  361. // On entry, we are on the FROM keyword.
  362. Consume(tsqlFrom);
  363. Repeat
  364. T:=ParseTableRef(AParent);
  365. AList.Add(T);
  366. Done:=(CurrentToken<>tsqlComma);
  367. If not Done then
  368. GetNextToken;
  369. until Done;
  370. end;
  371. procedure TSQLParser.ParseSelectFieldList(AParent: TSQLSelectStatement;
  372. AList: TSQLElementList; Singleton: Boolean);
  373. Var
  374. F : TSQLSelectField;
  375. B : Boolean;
  376. begin
  377. // On entry, we're on the token preceding the field list.
  378. B:=True;
  379. Repeat
  380. GetNextToken;
  381. If B then
  382. begin
  383. if (CurrentToken=tsqlDistinct) then
  384. begin
  385. AParent.Distinct:=True;
  386. GetNextToken;
  387. end
  388. else if (CurrentToken=tsqlAll) then
  389. begin
  390. AParent.All:=True;
  391. GetNextToken;
  392. end;
  393. B:=False;
  394. end;
  395. If (CurrentToken=tsqlMul) then
  396. begin
  397. If Singleton then
  398. Error(SErrNoAsteriskInSingleTon);
  399. AList.Add(CreateElement(TSQLSelectAsterisk,AParent));
  400. GetNextToken;
  401. end
  402. else
  403. begin
  404. F:=TSQLSelectField(CreateElement(TSQLSelectField,AParent));
  405. AList.Add(F);
  406. F.Expression:=ParseExprLevel1(AParent,[eoSelectvalue]);
  407. If CurrentToken in [tsqlAs,Tsqlidentifier] then
  408. begin
  409. If currentToken=tsqlAs then
  410. GetNextToken;
  411. Expect(tsqlIdentifier);
  412. F.AliasName:=CreateIdentifier(F,CurrentTokenString);
  413. GetNextToken;
  414. end;
  415. end;
  416. Expect([tsqlComma,tsqlFrom]);
  417. until (CurrentToken=tsqlFROM);
  418. end;
  419. procedure TSQLParser.ParseGroupBy(AParent: TSQLSelectStatement;
  420. AList: TSQLElementList);
  421. Var
  422. N : TSQLStringType;
  423. begin
  424. // On entry we're on the GROUP token.
  425. Consume(tsqlGroup);
  426. Expect(tsqlBy);
  427. Repeat
  428. GetNextToken;
  429. Expect(tsqlIdentifier);
  430. N:=CurrentTokenString;
  431. GetNextToken;
  432. If (CurrentToken=tsqlDot) then
  433. begin
  434. GetNextToken;
  435. Expect(tsqlIdentifier);
  436. N:=N+'.'+CurrentTokenString;
  437. GetNextToken;
  438. end;
  439. AList.Add(CreateIdentifier(AParent,N));
  440. until (CurrentToken<>tsqlComma);
  441. end;
  442. function TSQLParser.ParseForUpdate(AParent: TSQLSelectStatement
  443. ): TSQLElementList;
  444. begin
  445. // On entry we're on the FOR token.
  446. Consume(tsqlFor);
  447. Expect(tsqlUpdate);
  448. Result:=TSQLElementList.Create(True);
  449. try
  450. Repeat
  451. GetNextToken;
  452. Expect(tsqlIdentifier);
  453. Result.Add(CreateIdentifier(AParent,CurrentTokenString));
  454. until (CurrentToken<>tsqlComma);
  455. except
  456. FreeAndNil(Result);
  457. Raise;
  458. end;
  459. end;
  460. procedure TSQLParser.ParseOrderBy(AParent: TSQLSelectStatement;
  461. AList: TSQLElementList);
  462. Var
  463. O : TSQLOrderByElement;
  464. F : TSQLElement;
  465. begin
  466. // On entry we're on the ORDER token.
  467. Consume(tsqlOrder);
  468. Expect(tsqlBy);
  469. Repeat
  470. GetNextToken;
  471. Case CurrentToken of
  472. tsqlIdentifier :
  473. F:=CreateIdentifier(AParent,CurrentTokenString);
  474. tsqlIntegerNumber :
  475. begin
  476. F:=TSQLIntegerLiteral(CreateElement(TSQLIntegerLiteral,AParent));
  477. TSQLIntegerLiteral(F).Value:=StrToInt(CurrentTokenString);
  478. end
  479. else
  480. UnexpectedToken([tsqlIdentifier,tsqlIntegerNumber]);
  481. end;
  482. try
  483. O:=TSQLOrderByElement(CreateElement(TSQLOrderByElement,APArent));
  484. AList.Add(O);
  485. O.Field:=F;
  486. F:=Nil;
  487. except
  488. FreeAndNil(F);
  489. Raise;
  490. end;
  491. GetNextToken;
  492. If (CurrentToken=tsqlCollate) then
  493. begin
  494. GetNextToken;
  495. Expect(tsqlidentifier);
  496. O.Collation:=CreateIdentifier(O,CurrentTokenString);
  497. GetNextToken;
  498. end;
  499. If (CurrentToken in [tsqlDesc,tsqlAsc,tsqlDescending,tsqlAscending]) then
  500. begin
  501. If (CurrentToken in [tsqlDesc,tsqlDescending]) then
  502. O.OrderBy:=obDescending
  503. else
  504. O.OrderBy:=obAscending;
  505. GetNextToken;
  506. end;
  507. until (CurrentToken<>tsqlComma);
  508. end;
  509. function TSQLParser.ParseSelectPlan(AParent: TSQLElement): TSQLSelectPlan;
  510. Var
  511. E : TSQLSelectPlanExpr;
  512. I : TSQLSelectPlanItem;
  513. L : TSQLElementList;
  514. N : TSQLStringType;
  515. begin
  516. Result:=Nil;
  517. try
  518. Case CurrentToken of
  519. tsqlIdentifier :
  520. begin
  521. If Not (AParent is TSQLSelectPlanExpr) then
  522. UnexpectedToken([tsqlJoin,tsqlmerge,tsqlSort]);
  523. N:=CurrentTokenString;
  524. Case GetNextToken of
  525. tsqlNatural:
  526. begin
  527. I:=TSQLSelectNaturalPlan(CreateElement(TSQLSelectNaturalPlan,AParent));
  528. Result:=I;
  529. end;
  530. tsqlIndex :
  531. begin
  532. I:=TSQLSelectIndexedPlan(CreateElement(TSQLSelectIndexedPlan,AParent));
  533. Result:=I;
  534. L:=TSQLSelectIndexedPlan(I).Indexes;
  535. GetNextToken;
  536. expect(tsqlBraceOpen);
  537. Repeat
  538. GetNextToken;
  539. Expect(tsqlidentifier);
  540. L.Add(CreateIdentifier(Result,CurrentTokenString));
  541. GetNextToken;
  542. Expect([tsqlComma,tsqlBraceClose]);
  543. until (CurrentToken=tsqlBraceClose);
  544. end;
  545. tsqlOrder:
  546. begin
  547. GetNextToken;
  548. expect(tsqlIdentifier);
  549. I:=TSQLSelectOrderedPlan(CreateElement(TSQLSelectOrderedPlan,AParent));
  550. Result:=I;
  551. TSQLSelectOrderedPlan(I).OrderIndex:=CreateIdentifier(I,CurrentTokenstring);
  552. end;
  553. else
  554. Unexpectedtoken([tsqlNatural,tsqlIndex,tsqlOrder]);
  555. end;
  556. I.TableName:=CreateIdentifier(I,N);
  557. end;
  558. tsqlJoin,
  559. tsqlmerge,
  560. tsqlSort,
  561. tsqlBraceOpen:
  562. begin
  563. E:=TSQLSelectPlanExpr(CreateElement(TSQLSelectPlanExpr,AParent));
  564. Result:=E;
  565. Case CurrentToken of
  566. tsqlJoin,
  567. tsqlBraceOpen : E.Jointype:=pjtJoin;
  568. tsqlSort : E.JoinType:=pjtSort;
  569. tsqlMerge : E.JoinType:=pjtMerge;
  570. end;
  571. If (CurrentToken<>tsqlBraceOpen) then
  572. GetNextToken;
  573. expect(tsqlBraceOpen);
  574. repeat
  575. GetNextToken;
  576. E.Items.Add(ParseSelectPlan(E));
  577. Expect([tsqlComma,tsqlBraceClose]);
  578. until (CurrentToken=tsqlBraceClose);
  579. end;
  580. else
  581. UnexpectedToken([tsqlIdentifier,tsqlJoin,tsqlmerge,tsqlSort]);
  582. end;
  583. GetNextToken;
  584. except
  585. FreeAndNil(Result);
  586. Raise;
  587. end;
  588. end;
  589. function TSQLParser.ParseSelectStatement(AParent: TSQLElement; Flags : TSelectFlags = []): TSQLSelectStatement;
  590. begin
  591. // On entry, we're on the SELECT keyword
  592. Expect(tsqlSelect);
  593. Result:=TSQLSelectStatement(CreateElement(TSQLSelectStatement,AParent));
  594. try
  595. If (PeekNextToken=tsqlTransaction) then
  596. begin
  597. Consume(tsqlSelect);
  598. GetNextToken;
  599. Expect(TSQLIdentifier);
  600. Result.TransactionName:=CreateIdentifier(Result,CurrentTokenString);
  601. end;
  602. ParseSelectFieldList(Result,Result.Fields,sfSingleton in Flags);
  603. // On return, we are on the FROM keyword.
  604. ParseFromClause(Result,Result.Tables);
  605. If CurrentToken=tsqlWhere then
  606. begin
  607. GetNextToken;
  608. Result.Where:=ParseExprLevel1(Result,[eoWhereClause]);
  609. end;
  610. if CurrentToken=tsqlGroup then
  611. ParseGroupBy(Result,Result.GroupBy);
  612. if CurrentToken=tsqlHaving then
  613. begin
  614. If (Result.GroupBy.Count=0) then
  615. Error(SErrHavingWithoutGroupBy);
  616. GetNextToken;
  617. Result.Having:=ParseExprLevel1(Result,[eoHaving]);
  618. end;
  619. if (CurrentToken=tsqlUnion) then
  620. begin
  621. GetNextToken;
  622. If (CurrentToken=tsqlAll) then
  623. begin
  624. Result.UnionAll:=True;
  625. GetNextToken;
  626. end;
  627. Result.Union:=ParseSelectStatement(Result,Flags + [sfunion]);
  628. If (Result.Fields.count<>Result.Union.Fields.Count) then
  629. Error(SErrUnionFieldCountMatch,[Result.Fields.Count,Result.Union.Fields.Count])
  630. end;
  631. if (CurrentToken=tsqlPlan) then
  632. begin
  633. GetNextToken;
  634. Result.Plan:=ParseSelectPlan(Result);
  635. end;
  636. if not (sfUnion in Flags) then
  637. begin
  638. if (CurrentToken=tsqlOrder) then
  639. ParseOrderBy(Result,Result.OrderBy);
  640. if (CurrentToken=tsqlFOR) then
  641. Result.ForUpdate:=ParseForUpdate(Result);
  642. end;
  643. if (sfInto in Flags) then
  644. begin
  645. if (CurrentToken=tsqlInto) then
  646. begin
  647. Result.Into:=TSQLElementList.Create(true);
  648. ParseIntoList(Result,Result.Into);
  649. end;
  650. end;
  651. except
  652. FreeAndNil(Result);
  653. Raise;
  654. end;
  655. end;
  656. function TSQLParser.ParseUpdateStatement(AParent: TSQLElement
  657. ): TSQLUpdateStatement;
  658. Var
  659. P : TSQLUpdatePair;
  660. N : String;
  661. begin
  662. // On entry, we're on the UPDATE keyword
  663. Consume(tsqlUpdate);
  664. Expect(tsqlidentifier);
  665. Result:=TSQLUpdateStatement(CreateElement(TSQLUpdateStatement,AParent));
  666. try
  667. Result.TableName:=CreateIdentifier(Result,CurrentTokenString);
  668. GetNextToken;
  669. Expect(tsqlSet);
  670. Repeat
  671. GetNextToken;
  672. Expect(tsqlIdentifier);
  673. P:=TSQLUpdatePair(CreateElement(TSQLUpdatePair,Result));
  674. Result.Values.Add(P);
  675. N:=CurrentTokenString;
  676. GetNextToken;
  677. If (CurrentToken=tsqlDot) then
  678. begin
  679. GetNextToken;
  680. Expect(TSQLIdentifier);
  681. N:=N+'.'+CurrentTokenString;
  682. GetNextToken;
  683. end;
  684. Consume(tsqlEq);
  685. P.FieldName:=CreateIdentifier(P,N);
  686. P.Value:=ParseExprLevel1(P,[eoFieldValue]);
  687. until (CurrentToken<>tsqlComma);
  688. If (CurrentToken=tsqlWhere) then
  689. begin
  690. GetNextToken;
  691. Result.WhereClause:=ParseExprLevel1(P,[eoWhereClause]);
  692. end;
  693. except
  694. FreeAndNil(Result);
  695. Raise;
  696. end;
  697. end;
  698. function TSQLParser.ParseInsertStatement(AParent: TSQLElement): TSQLInsertStatement;
  699. begin
  700. // On entry, we're on the INSERT statement
  701. Consume(tsqlInsert);
  702. Consume(tsqlInto);
  703. Expect(tsqlidentifier);
  704. Result:=TSQLInsertStatement(CreateElement(TSQLinsertStatement,AParent));
  705. try
  706. Result.TableName:=CreateIdentifier(Result,CurrentTokenString);
  707. GetNextToken;
  708. If CurrentToken=tsqlBraceOpen then
  709. begin
  710. Result.Fields:=TSQLElementList.Create(True);
  711. Repeat
  712. GetNextToken;
  713. Expect(tsqlIdentifier);
  714. Result.Fields.Add(CreateIdentifier(Result,CurrentTokenString));
  715. GetNextToken;
  716. Expect([tsqlBraceClose,tsqlComma]);
  717. Until (CurrentToken=tsqlBraceClose);
  718. GetNextToken;
  719. end;
  720. Case CurrentToken of
  721. tsqlSelect :
  722. Result.Select:=ParseSelectStatement(Result);
  723. tsqlValues :
  724. begin
  725. GetNextToken;
  726. Result.Values:=ParsevalueList(Result,[eoFieldValue]);
  727. GetNextToken; // consume )
  728. end;
  729. else
  730. UnexpectedToken([tsqlselect,tsqlValues]);
  731. end;
  732. except
  733. FreeAndNil(Result);
  734. Raise;
  735. end;
  736. end;
  737. function TSQLParser.ParseDeleteStatement(AParent: TSQLElement
  738. ): TSQLDeleteStatement;
  739. begin
  740. // On entry, we're on the DELETE token.
  741. consume(tsqlDelete);
  742. consume(tsqlFrom);
  743. Expect(tsqlidentifier);
  744. Result:=TSQLDeleteStatement(CreateElement(TSQLDeleteStatement,AParent));
  745. try
  746. Result.TableName:=CreateIdentifier(Result,CurrentTokenString);
  747. GetNextToken;
  748. if CurrentToken=tsqlIdentifier then
  749. begin
  750. Result.AliasName:=CreateIdentifier(Result,CurrentTokenString);
  751. GetNextToken;
  752. end;
  753. if CurrentToken=tsqlwhere then
  754. begin
  755. Consume(tsqlWhere);
  756. Result.WhereClause:=ParseExprLevel1(Result,[eoWhereClause]);
  757. end;
  758. except
  759. FreeAndNil(Result);
  760. Raise;
  761. end;
  762. end;
  763. function TSQLParser.ParseTableFieldDef(AParent: TSQLElement): TSQLTableFieldDef;
  764. begin
  765. // on entry, we're on the field name
  766. Result:=TSQLTableFieldDef(CreateElement(TSQLTableFieldDef,AParent));
  767. try
  768. Result.FieldName:=CreateIdentifier(Result,CurrentTokenString);
  769. if PeekNextToken = tsqlComputed then
  770. begin
  771. GetNextToken;
  772. Consume(tsqlComputed);
  773. If CurrentToken=tsqlBy then
  774. GetNextToken;
  775. Consume(tsqlBraceopen);
  776. Result.ComputedBy:=ParseExprLevel1(Result,[eoComputedBy]);
  777. Consume(tsqlBraceClose);
  778. end
  779. else //not computed, regular field
  780. Result.FieldType:=ParseTypeDefinition(Result,[ptfAllowDomainName,ptfAllowConstraint,ptfTableFieldDef]);
  781. except
  782. FreeAndNil(Result);
  783. Raise;
  784. end;
  785. end;
  786. function TSQLParser.ParseTableConstraint(AParent: TSQLElement
  787. ): TSQLTableConstraintDef;
  788. Procedure ParseFieldList(R : TSQLTableFieldsConstraintDef);
  789. begin
  790. GetNextToken;
  791. Consume(tsqlBraceOpen);
  792. ParseIdentifierList(AParent,R.FieldList);
  793. // Consume(tsqlBraceClose);
  794. end;
  795. Var
  796. N : TSQLStringType;
  797. K : TSQLTableForeignKeyConstraintDef;
  798. begin
  799. If CurrentToken=tsqlConstraint then
  800. begin
  801. GetNextToken;
  802. Expect(tsqlIdentifier);
  803. N:=CurrentTokenString;
  804. GetNextToken
  805. end;
  806. Result:=Nil;
  807. try
  808. Case CurrentToken of
  809. tsqlUnique :
  810. begin
  811. Result:=TSQLTableUniqueConstraintDef(CreateElement(TSQLTableUniqueConstraintDef,AParent));
  812. ParseFieldList(TSQLTableFieldsConstraintDef(Result));
  813. end;
  814. tsqlPrimary :
  815. begin
  816. GetNextToken;
  817. Expect(tsqlKey);
  818. Result:=TSQLTablePrimaryKeyConstraintDef(CreateElement(TSQLTablePrimaryKeyConstraintDef,AParent));
  819. ParseFieldList(TSQLTableFieldsConstraintDef(Result));
  820. end;
  821. tsqlForeign :
  822. begin
  823. GetNextToken;
  824. Expect(tsqlKey);
  825. K:=TSQLTableForeignKeyConstraintDef(CreateElement(TSQLTableForeignKeyConstraintDef,AParent));
  826. Result:=K;
  827. ParseFieldList(TSQLTableFieldsConstraintDef(Result));
  828. Expect(tsqlReferences);
  829. K.Definition:=ParseForeignKeyDefinition(K);
  830. end;
  831. tsqlCheck:
  832. begin
  833. Result:=TSQLTableCheckConstraintDef(CreateElement(TSQLTableCheckConstraintDef,AParent));
  834. TSQLTableCheckConstraintDef(Result).Check:=ParseCheckConstraint(Result,True);
  835. end
  836. else
  837. UnexpectedToken([tsqlUnique,tsqlPrimary,tsqlForeign,tsqlCheck]);
  838. end;
  839. If (N<>'') then
  840. Result.ConstraintName:=CreateIdentifier(Result,N);
  841. // GetNextToken;
  842. except
  843. FreeAndNil(Result);
  844. Raise;
  845. end;
  846. end;
  847. function TSQLParser.ParseCreateTableStatement(AParent: TSQLElement): TSQLCreateOrAlterStatement;
  848. Var
  849. C : TSQLCreateTableStatement;
  850. HC : Boolean;
  851. begin
  852. // On enter, we're on the TABLE token.
  853. Consume(tsqlTable);
  854. C:=TSQLCreateTableStatement(CreateElement(TSQLCreateTableStatement,AParent));
  855. try
  856. Expect(tsqlIdentifier);
  857. C.ObjectName:=CreateIdentifier(C,CurrentTokenstring);
  858. GetNextToken;
  859. If (CurrentToken=tsqlExternal) then
  860. begin
  861. GetNextToken;
  862. If (CurrentToken=tsqlFile) then
  863. GetNextToken;
  864. Expect(tsqlString);
  865. C.ExternalFileName:=CreateLiteral(C) as TSQLStringLiteral;
  866. GetNextToken;
  867. end;
  868. Expect(tsqlBraceOpen);
  869. HC:=False;
  870. Repeat
  871. GetNextToken;
  872. Case CurrentToken of
  873. tsqlIdentifier :
  874. begin
  875. if HC then
  876. UnexpectedToken;
  877. C.FieldDefs.Add(ParseTableFieldDef(C));
  878. end;
  879. tsqlCheck,
  880. tsqlConstraint,
  881. tsqlForeign,
  882. tsqlPrimary,
  883. tsqlUnique:
  884. begin
  885. C.Constraints.Add(ParseTableConstraint(C));
  886. HC:=true;
  887. end
  888. else
  889. UnexpectedToken([tsqlIdentifier,tsqlCheck, tsqlConstraint,tsqlForeign,tsqlPrimary,tsqlUnique]);
  890. end;
  891. expect([tsqlBraceClose,tsqlComma]);
  892. until (CurrentToken=tsqlBraceClose);
  893. GetNextToken;
  894. Result:=C;
  895. except
  896. FreeandNil(C);
  897. Raise;
  898. end;
  899. end;
  900. function TSQLParser.ParseDropTableElement(AParent : TSQLElement) : TSQLDropTableElementOperation;
  901. Var
  902. C : Boolean;
  903. begin
  904. // On entry, we are on DROP token
  905. C:=(GetNextToken=tsqlConstraint);
  906. If C then
  907. GetNextToken;
  908. Expect(tsqlidentifier);
  909. If C then
  910. Result:=TSQLDropTableConstraintOperation(CreateElement(TSQLDropTableConstraintOperation,AParent))
  911. else
  912. Result:=TSQLDropTableFieldOperation(CreateElement(TSQLDropTableFieldOperation,AParent));
  913. Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
  914. GetNextToken;
  915. end;
  916. function TSQLParser.ParseAddTableElement(AParent : TSQLElement) : TSQLAlterTableAddElementOperation;
  917. begin
  918. Result:=Nil;
  919. try
  920. Case GetNextToken of
  921. tsqlIdentifier :
  922. begin
  923. Result:=TSQLAlterTableAddElementOperation(CreateElement(TSQLAlterTableAddFieldOPeration,AParent));
  924. Result.Element:=ParseTableFieldDef(Result);
  925. end;
  926. tsqlCheck,
  927. tsqlConstraint,
  928. tsqlForeign,
  929. tsqlPrimary,
  930. tsqlUnique:
  931. begin
  932. Result:=TSQLAlterTableAddElementOperation(CreateElement(TSQLAlterTableAddConstraintOperation,AParent));
  933. Result.Element:=ParseTableConstraint(Result);
  934. end
  935. else
  936. UnexpectedToken([tsqlIdentifier,tsqlCheck, tsqlConstraint,tsqlForeign,tsqlPrimary,tsqlUnique]);
  937. end;
  938. except
  939. FreeAndNil(Result);
  940. Raise;
  941. end;
  942. end;
  943. function TSQLParser.ParseAlterTableElement(AParent : TSQLElement) : TSQLAlterTableOperation;
  944. Var
  945. N : TSQLStringType;
  946. begin
  947. Result:=Nil;
  948. If GetnextToken=tsqlColumn then
  949. GetNextToken;
  950. expect(tsqlidentifier);
  951. N:=CurrentTokenString;
  952. try
  953. Case GetNextToken of
  954. tsqlTo :
  955. begin
  956. GetNextToken;
  957. Result:=TSQLAlterTableOperation(CreateElement(TSQLAlterTableFieldNameOperation,AParent));
  958. TSQLAlterTableFieldNameOperation(Result).NewName:=CreateIdentifier(Result,CurrentTokenString);
  959. GetNextToken;
  960. end;
  961. tsqltype:
  962. begin
  963. Result:=TSQLAlterTableOperation(CreateElement(TSQLAlterTableFieldTypeOperation,AParent));
  964. TSQLAlterTableFieldTypeOperation(Result).NewType:= ParseTypeDefinition(Result,[ptfAllowDomainName,ptfAllowConstraint,ptfTableFieldDef]);
  965. end;
  966. tsqlPosition:
  967. begin
  968. GetNextToken;
  969. Expect(tsqlIntegerNumber);
  970. Result:=TSQLAlterTableOperation(CreateElement(TSQLAlterTableFieldPositionOperation,AParent));
  971. TSQLAlterTableFieldPositionOperation(Result).NewPosition:=StrToInt(CurrentTokenString);
  972. GetNextToken;
  973. end
  974. else
  975. UnexpectedToken([tsqlTo,tsqltype,tsqlPosition]);
  976. end;
  977. Result.ObjectName:=CreateIdentifier(Result,N);
  978. except
  979. FreeAndNil(Result);
  980. Raise;
  981. end;
  982. end;
  983. function TSQLParser.ParseAlterTableStatement(AParent: TSQLElement): TSQLAlterTableStatement;
  984. begin
  985. // On enter, we're on the TABLE token.
  986. Consume(tsqlTable);
  987. Result:=TSQLAlterTableStatement(CreateElement(TSQLAlterTableStatement,AParent));
  988. try
  989. Expect(tsqlIdentifier);
  990. Result.ObjectName:=CreateIdentifier(Result,CurrentTokenstring);
  991. Repeat
  992. GetNextToken;
  993. Case CurrentToken of
  994. tsqlAdd:
  995. begin
  996. Result.Operations.Add(ParseAddTableElement(Result));
  997. end;
  998. tsqlAlter:
  999. begin
  1000. Result.Operations.Add(ParseAlterTableElement(Result));
  1001. end;
  1002. tsqlDrop :
  1003. begin
  1004. Result.Operations.add(ParseDropTableElement(Result));
  1005. end;
  1006. else
  1007. UnexpectedToken([tsqlAdd,tsqlAlter,tsqlDrop]);
  1008. end;
  1009. until (CurrentToken<>tsqlComma);
  1010. except
  1011. FreeandNil(Result);
  1012. Raise;
  1013. end;
  1014. end;
  1015. function TSQLParser.ParseCreateIndexStatement(AParent: TSQLElement; IsAlter: Boolean
  1016. ): TSQLCreateOrAlterStatement;
  1017. Var
  1018. O : TIndexOptions;
  1019. C : TSQLCreateIndexStatement;
  1020. A : TSQLAlterIndexStatement;
  1021. begin
  1022. O:=[];
  1023. // On enter, we're on the UNIQUE, ASCENDING, DESCENDING or INDEX token
  1024. If IsAlter then
  1025. begin
  1026. expect(tsqlIndex);
  1027. Consume(tsqlIndex);
  1028. A:=TSQLAlterIndexStatement(CreateElement(TSQLAlterIndexStatement,APArent));
  1029. try
  1030. Expect(tsqlIdentifier);
  1031. A.ObjectName:=CreateIdentifier(A,CurrentTokenString);
  1032. GetNextToken;
  1033. Expect([tsqlActive,tsqlInactive]);
  1034. A.Inactive:=CurrentToken=tsqlInactive;
  1035. GetNextToken; // Token after ) or (in)Active
  1036. Result:=A;
  1037. except
  1038. FReeAndNil(A);
  1039. Raise;
  1040. end;
  1041. end
  1042. else
  1043. begin
  1044. C:=TSQLCreateIndexStatement(CreateElement(TSQLCreateIndexStatement,APArent));
  1045. try
  1046. If (CurrentToken=tsqlUnique) then
  1047. begin
  1048. GetNextToken;
  1049. Include(O,ioUnique);
  1050. end;
  1051. If (CurrentToken=tsqlAscending) then
  1052. begin
  1053. GetNextToken;
  1054. Include(O,ioAscending);
  1055. end
  1056. else If (CurrentToken=tsqlDescending) then
  1057. begin
  1058. GetNextToken;
  1059. Include(O,ioDescending);
  1060. end;
  1061. C.Options:=O;
  1062. Consume(tsqlIndex);
  1063. Expect(tsqlIdentifier);
  1064. C.ObjectName:=CreateIdentifier(C,CurrentTokenString);
  1065. GetNextToken;
  1066. Consume(tsqlOn);
  1067. Expect(tsqlIdentifier);
  1068. C.TableName:=Createidentifier(C,CurrentTokenString); // name of table
  1069. GetNextToken;
  1070. Consume(tsqlBraceOpen);
  1071. ParseIdentifierList(C,C.FieldNames);
  1072. Result:=C;
  1073. except
  1074. FreeAndNil(C);
  1075. Raise;
  1076. end;
  1077. end;
  1078. end;
  1079. function TSQLParser.ParseCreateViewStatement(AParent: TSQLElement; IsAlter: Boolean
  1080. ): TSQLCreateOrAlterStatement;
  1081. Var
  1082. V : TSQLCreateViewStatement;
  1083. begin
  1084. // on entry, we're on the VIEW token.
  1085. If IsAlter then
  1086. UnexpectedToken;
  1087. Result:=Nil;
  1088. Consume(tsqlView);
  1089. Expect(tsqlIdentifier);
  1090. V:=TSQLCreateViewStatement(CreateElement(TSQLCreateViewStatement,APArent));
  1091. Result:=V;
  1092. try
  1093. V.ObjectName:=CreateIdentifier(V,CurrentTokenString);
  1094. GetNextToken;
  1095. If (CurrentToken=tsqlBraceOpen) then
  1096. begin
  1097. GetNextToken;
  1098. ParseIdentifierList(Result,V.Fields);
  1099. end;
  1100. Consume(tsqlAs);
  1101. V.Select:=ParseSelectStatement(V,[]);
  1102. If (CurrentToken=tsqlWith) then
  1103. begin
  1104. GetNextToken;
  1105. Consume(tsqlCheck);
  1106. Consume(tsqlOption);
  1107. V.WithCheckOption:=True;
  1108. end;
  1109. except
  1110. FreeAndNil(Result);
  1111. Raise;
  1112. end;
  1113. end;
  1114. procedure TSQLParser.ParseProcedureParamList(AParent: TSQLElement;
  1115. AList: TSQLElementList);
  1116. Var
  1117. P : TSQLProcedureParamDef;
  1118. begin
  1119. // On Entry, we're on the ( token
  1120. Repeat
  1121. GetNextToken;
  1122. Expect(tsqlIdentifier);
  1123. P:=TSQLProcedureParamDef(CreateElement(TSQLProcedureParamDef,AParent));
  1124. try
  1125. Alist.Add(P);
  1126. except
  1127. P.free;
  1128. Raise;
  1129. end;
  1130. P.ParamName:=CreateIdentifier(P,CurrentTokenString);
  1131. // Typedefinition will go to next token
  1132. P.ParamType:=ParseTypeDefinition(P,[ptProcedureParam]);
  1133. Until (CurrentToken<>tsqlComma);
  1134. Consume(tsqlBraceClose);
  1135. end;
  1136. procedure TSQLParser.ParseCreateProcedureVariableList(AParent: TSQLElement;
  1137. AList: TSQLElementList);
  1138. Var
  1139. P : TSQLProcedureParamDef;
  1140. begin
  1141. // On Entry, we're on the DECLARE token
  1142. Repeat
  1143. Consume(tsqlDeclare);
  1144. Consume(tsqlVariable);
  1145. Expect(tsqlIdentifier);
  1146. P:=TSQLProcedureParamDef(CreateElement(TSQLProcedureParamDef,AParent));
  1147. Try
  1148. AList.Add(P);
  1149. except
  1150. P.Free;
  1151. Raise;
  1152. end;
  1153. P.ParamName:=CreateIdentifier(P,CurrentTokenString);
  1154. // Typedefinition will go to next token
  1155. P.ParamType:=ParseTypeDefinition(P,[ptProcedureParam]);
  1156. Consume(tsqlSemicolon);
  1157. Until (CurrentToken<>tsqlDeclare);
  1158. end;
  1159. function TSQLParser.ParseIfStatement(AParent: TSQLElement): TSQLIFStatement;
  1160. Var
  1161. Pt : TSQLToken;
  1162. begin
  1163. // On Entry, we're on the IF token
  1164. Consume(tsqlIf);
  1165. Consume(tsqlBraceOpen);
  1166. Result:=TSQLIFStatement(CreateElement(TSQLIFStatement,AParent));
  1167. try
  1168. Result.Condition:=ParseExprLevel1(AParent,[eoIF]);
  1169. Consume(tsqlBraceClose);
  1170. Consume(tsqlThen);
  1171. Result.TrueBranch:=ParseProcedureStatement(Result);
  1172. If (CurrentToken=tsqlSemicolon) and (PeekNextToken=tsqlElse) then
  1173. begin
  1174. PT:=CurrentToken;
  1175. GetNextToken;
  1176. end
  1177. else if (CurrentToken=tsqlElse) then
  1178. if not (PreviousToken=tsqlEnd) then
  1179. UnexpectedToken;
  1180. If CurrentToken=tsqlElse then
  1181. begin
  1182. GetNextToken;
  1183. Result.FalseBranch:=ParseProcedureStatement(Result);
  1184. end;
  1185. except
  1186. FreeAndNil(Result);
  1187. Raise;
  1188. end;
  1189. end;
  1190. procedure TSQLParser.ParseIntoList(AParent : TSQLElement; List : TSQLElementList);
  1191. begin
  1192. // On Entry, we're on the INTO token
  1193. Repeat
  1194. GetNextToken;
  1195. If (currentToken=tsqlColon) then
  1196. Consume(tsqlColon);
  1197. Expect(tsqlIdentifier);
  1198. List.Add(CreateIdentifier(AParent,CurrentTokenString));
  1199. GetNextToken;
  1200. Until (CurrentToken<>tsqlComma);
  1201. end;
  1202. function TSQLParser.ParseForStatement(AParent: TSQLElement): TSQLForStatement;
  1203. begin
  1204. // On Entry, we're on the FOR token
  1205. Consume(tsqlFor);
  1206. Expect(tsqlSelect);
  1207. Result:=TSQLForStatement(CreateElement(TSQLForStatement,AParent));
  1208. try
  1209. Result.Select:=ParseSelectStatement(Result,[]);
  1210. Expect(tsqlInto);
  1211. ParseIntoList(Result,Result.FieldList);
  1212. Consume(tsqlDo);
  1213. Result.Statement:=ParseProcedureStatement(Result);
  1214. except
  1215. FreeAndNil(Result);
  1216. Raise;
  1217. end;
  1218. end;
  1219. function TSQLParser.ParseExceptionStatement(AParent: TSQLElement
  1220. ): TSQLExceptionStatement;
  1221. begin
  1222. // On Entry, we're on the EXCEPTION token
  1223. Consume(tsqlException);
  1224. Expect(tsqlIdentifier);
  1225. Result:=TSQLExceptionStatement(CreateElement(TSQLExceptionStatement,AParent));
  1226. try
  1227. Result.ExceptionName:=CreateIdentifier(Result,CurrentTokenString);
  1228. GetNextToken;
  1229. except
  1230. FreeAndNil(Result);
  1231. Raise;
  1232. end;
  1233. end;
  1234. function TSQLParser.ParseAssignStatement(AParent: TSQLElement
  1235. ): TSQLAssignStatement;
  1236. Var
  1237. N : TSQLStringType;
  1238. begin
  1239. // On entry, we're on the identifier token;
  1240. expect(tsqlIdentifier);
  1241. Result:=TSQLAssignStatement(CreateElement(TSQLAssignStatement,AParent));
  1242. try
  1243. N:=CurrentTokenString;
  1244. GetNextToken;
  1245. If (CurrentToken=tsqlDot) and (Uppercase(N)='NEW') then
  1246. begin
  1247. GetNextToken;
  1248. Expect(tsqlIdentifier);
  1249. N:=N+'.'+CurrentTokenString;
  1250. GetNextToken;
  1251. end;
  1252. Result.Variable:=CreateIdentifier(Result,N);
  1253. Consume(tsqlEq);
  1254. Result.Expression:=ParseExprLevel1(Result,[]);
  1255. except
  1256. FreeAndNil(Result);
  1257. Raise;
  1258. end;
  1259. end;
  1260. function TSQLParser.ParsePostEventStatement(AParent: TSQLElement
  1261. ): TSQLPostEventStatement;
  1262. begin
  1263. // On Entry, we're on the POST_EVENT token
  1264. Consume(tsqlPostEvent);
  1265. Result:=TSQLPostEventStatement(CreateElement(TSQLPostEventStatement,AParent));
  1266. try
  1267. Case CurrentToken of
  1268. tsqlIdentifier : Result.ColName:=CreateIdentifier(Result,CurrentTokenString);
  1269. tsqlString : Result.EventName:=CurrentTokenString;
  1270. else
  1271. UnexpectedToken([tsqlIdentifier,tsqlString]);
  1272. end;
  1273. GetNextToken;
  1274. except
  1275. FreeAndNil(Result);
  1276. Raise;
  1277. end;
  1278. end;
  1279. function TSQLParser.ParseWhileStatement(AParent: TSQLElement
  1280. ): TSQLWhileStatement;
  1281. begin
  1282. // On entry, we're on the WHILE Token
  1283. Consume(tsqlWhile);
  1284. Consume(tsqlBraceOpen);
  1285. Result:=TSQLWhileStatement(CreateElement(TSQLWhileStatement,AParent));
  1286. try
  1287. Result.Condition:=ParseExprLevel1(Result,[eoIF]);
  1288. Consume(tsqlBraceClose);
  1289. Consume(tsqlDO);
  1290. Result.Statement:=ParseProcedureStatement(Result);
  1291. except
  1292. FreeAndNil(Result);
  1293. Raise;
  1294. end;
  1295. end;
  1296. function TSQLParser.ParseWhenStatement(AParent: TSQLElement): TSQLWhenStatement;
  1297. Var
  1298. E : TSQLWhenException;
  1299. S : TSQLWhenSQLError;
  1300. G : TSQLWhenGDSError;
  1301. begin
  1302. Consume(tsqlWhen);
  1303. Result:=TSQLWhenStatement(CreateElement(TSQLWhenStatement,AParent));
  1304. try
  1305. if (CurrentToken=tsqlAny) then
  1306. begin
  1307. Result.AnyError:=True;
  1308. GetNextToken
  1309. end
  1310. else
  1311. Repeat
  1312. if (Result.Errors.Count>0) then
  1313. GetNextToken;
  1314. Case CurrentToken of
  1315. tsqlException:
  1316. begin
  1317. GetNextToken;
  1318. Expect(tsqlIdentifier);
  1319. E:=TSQLWhenException(CreateElement(TSQLWhenException,AParent));
  1320. E.ExceptionName:=CreateIdentifier(E,CurrentTokenString);
  1321. Result.Errors.Add(E);
  1322. end;
  1323. tsqlSQLCode:
  1324. begin
  1325. GetNextToken;
  1326. Expect(tsqlIntegerNumber);
  1327. S:=TSQLWhenSQLError(CreateElement(TSQLWhenSQLError,AParent));
  1328. S.ErrorCode:=StrToInt(CurrentTokenString);
  1329. Result.Errors.Add(S);
  1330. end;
  1331. tsqlGDSCODE:
  1332. begin
  1333. GetNextToken;
  1334. Expect(tsqlIntegerNumber);
  1335. G:=TSQLWhenGDSError(CreateElement(TSQLWhenGDSError,AParent));
  1336. G.GDSErrorNumber:=StrToInt(CurrentTokenString);
  1337. Result.Errors.Add(G);
  1338. end;
  1339. else
  1340. UnexpectedToken([tsqlException,tsqlSQLCode,tsqlGDSCODE]);
  1341. end;
  1342. GetNextToken;
  1343. until (CurrentToken<>tsqlComma);
  1344. consume(tsqlDo);
  1345. Result.Statement:=ParseProcedureStatement(Result);
  1346. except
  1347. FreeAndNil(Result);
  1348. Raise;
  1349. end;
  1350. end;
  1351. function TSQLParser.ParseProcedureStatement(AParent: TSQLElement
  1352. ): TSQLStatement;
  1353. begin
  1354. Result:=Nil;
  1355. Case CurrentToken of
  1356. tsqlBegin :
  1357. begin
  1358. Result:=TSQLStatementBlock(CreateElement(TSQLStatementBlock,AParent));
  1359. ParseStatementBlock(Result,TSQLStatementBlock(Result).Statements);
  1360. end;
  1361. tsqlIf : Result:=ParseIfStatement(AParent);
  1362. tsqlFor : Result:=ParseForStatement(AParent);
  1363. tsqlException : Result:=ParseExceptionStatement(AParent);
  1364. tsqlIdentifier : Result:=ParseAssignStatement(AParent);
  1365. tsqlExecute : Result:=ParseExecuteProcedureStatement(AParent);
  1366. tsqlExit : begin
  1367. Result:=TSQLExitStatement(CreateElement(TSQLExitStatement,AParent));
  1368. GetNextToken;
  1369. end;
  1370. tsqlSuspend : begin
  1371. Result:=TSQLSuspendStatement(CreateElement(TSQLSuspendStatement,AParent));
  1372. GetNextToken;
  1373. end;
  1374. tsqlPostEvent : Result:=ParsePostEventStatement(AParent);
  1375. tsqlWhile : Result:=ParseWhileStatement(AParent);
  1376. tsqlWhen : Result:=ParseWhenStatement(AParent);
  1377. tsqlSelect : Result:=ParseSelectStatement(AParent,[sfInto]);
  1378. tsqlInsert : Result:=ParseInsertStatement(AParent);
  1379. tsqlDelete : Result:=ParseDeleteStatement(AParent);
  1380. tsqlUpdate : Result:=ParseUpdateStatement(AParent);
  1381. else
  1382. UnexpectedToken;
  1383. end;
  1384. end;
  1385. procedure TSQLParser.ParseStatementBlock(AParent: TSQLElement;
  1386. Statements: TSQLElementList);
  1387. Var
  1388. S: TSQLStatement;
  1389. begin
  1390. Consume(tsqlBegin);
  1391. While (CurrentToken<>tsqlEnd) do
  1392. begin
  1393. S:=ParseProcedureStatement(AParent);
  1394. Statements.Add(S);
  1395. if not (PreviousToken=tsqlEnd) then
  1396. Consume([tsqlSemicolon,tsqlStatementTerminator]);
  1397. end;
  1398. Consume(tsqlEnd);
  1399. end;
  1400. function TSQLParser.ParseCreateProcedureStatement(AParent: TSQLElement; IsAlter: Boolean
  1401. ): TSQLCreateOrAlterStatement;
  1402. Var
  1403. P : TSQLAlterCreateProcedureStatement;
  1404. begin
  1405. // On entry, we're on the PROCEDURE statement.
  1406. Consume(tsqlProcedure);
  1407. expect(tsqlIdentifier);
  1408. If IsAlter then
  1409. P:=TSQLAlterProcedureStatement(CreateElement(TSQLAlterProcedureStatement,AParent))
  1410. else
  1411. P:=TSQLCreateProcedureStatement(CreateElement(TSQLCreateProcedureStatement,AParent));
  1412. Result:=P;
  1413. try
  1414. Result.ObjectName:=CreateIdentifier(P,CurrentTokenString);
  1415. GetNextToken;
  1416. If (CurrentToken=tsqlBraceOpen) then
  1417. ParseProcedureParamList(Result,P.InputVariables);
  1418. If (CurrentToken=tsqlReturns) then
  1419. begin
  1420. GetNextToken;
  1421. expect(tsqlBraceOpen);
  1422. ParseProcedureParamList(Result,P.OutputVariables);
  1423. end;
  1424. Consume(tsqlAs);
  1425. if (CurrentToken=tsqlDeclare) then
  1426. ParseCreateProcedureVariableList(Result,P.LocalVariables);
  1427. expect(tsqlBegin);
  1428. ParseStatementBlock(Result,P.Statements);
  1429. except
  1430. FreeAndNil(Result);
  1431. Raise;
  1432. end;
  1433. end;
  1434. function TSQLParser.ParseCreateGeneratorStatement(AParent: TSQLElement; IsAlter: Boolean
  1435. ): TSQLCreateOrAlterStatement;
  1436. begin
  1437. GetNextToken;
  1438. Expect(tsqlIdentifier);
  1439. If IsAlter then
  1440. Error(SErrCannotAlterGenerator);
  1441. Result:=TSQLCreateOrAlterStatement(CreateElement(TSQLCreateGeneratorStatement,AParent));
  1442. try
  1443. Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
  1444. except
  1445. FreeAndNil(Result);
  1446. Raise;
  1447. end;
  1448. GetNextToken; // Comma;
  1449. end;
  1450. function TSQLParser.ParseCreateRoleStatement(AParent: TSQLElement;
  1451. IsAlter: Boolean): TSQLCreateOrAlterStatement;
  1452. begin
  1453. If IsAlter then
  1454. UnexpectedToken; // no ALTER ROLE
  1455. GetNextToken;
  1456. Expect(tsqlIdentifier);
  1457. Result:=TSQLCreateOrAlterStatement(CreateElement(TSQLCreateRoleStatement,AParent));
  1458. Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
  1459. GetNextToken; // Comma;
  1460. end;
  1461. procedure TSQLParser.ParseCharTypeDefinition(out DT: TSQLDataType; out
  1462. Len: Integer; out ACharset: TSQLStringType);
  1463. begin
  1464. Len:=0;
  1465. Case CurrentToken of
  1466. tsqlNCHAR : dt:=sdtNchar;
  1467. tsqlVarChar : dt:=sdtVarChar;
  1468. tsqlCharacter,
  1469. tsqlChar : dt:=sdtChar;
  1470. tsqlCString : dt:=sdtCstring;
  1471. tsqlNational :
  1472. begin
  1473. dt:=sdtNChar;
  1474. GetNextToken;
  1475. expect([tsqlCharacter,tsqlChar]);
  1476. end;
  1477. end;
  1478. GetNextToken; // VARYING, Start of size, CHARACTER SET or end
  1479. If (CurrentToken=tsqlVarying) then // CHAR VARYING or CHARACTER VARYING;
  1480. begin
  1481. If (dt in [sdtNCHAR,sdtChar]) then
  1482. begin
  1483. if dt=sdtNCHAR then
  1484. dt:=sdtNVARCHAR
  1485. else
  1486. dt:=sdtVarChar;
  1487. GetNextToken
  1488. end
  1489. else
  1490. Error(SErrVaryingNotAllowed);
  1491. end;
  1492. If (CurrentToken=tsqlBraceOpen) then // (LEN)
  1493. begin
  1494. GetNextToken;
  1495. Expect(tsqlIntegerNumber);
  1496. len:=StrToInt(CurrentTokenString);
  1497. GetNextToken;
  1498. Expect(tsqlBraceClose);
  1499. GetNextToken;
  1500. end
  1501. else if (dt=sdtCstring) then
  1502. UnexpectedToken;
  1503. if (CurrentToken=tsqlCharacter) then // Character SET NNN
  1504. begin
  1505. if (dt=sdtCstring) then
  1506. UnexpectedToken;
  1507. GetNextToken;
  1508. Consume(tsqlSet);
  1509. Expect(tsqlIdentifier);
  1510. ACharSet:=CurrentTokenString;
  1511. GetNextToken;
  1512. end;
  1513. end;
  1514. procedure TSQLParser.ParseBlobDefinition(var ASegmentSize, ABlobType: Integer;
  1515. var ACharset: TSQLStringType);
  1516. begin
  1517. // On entry, we are on the blob token.
  1518. GetNextToken;
  1519. If (CurrentToken=tsqlBraceOpen) then // (segment[,subtype])
  1520. begin
  1521. GetNextToken;
  1522. Expect(tsqlIntegerNumber);
  1523. ASegmentSize:=StrtoInt(CurrentTokenString);
  1524. GetNextToken;
  1525. If (CurrentToken=tsqlComma) then
  1526. begin
  1527. GetNextToken;
  1528. Expect(tsqlIntegerNumber);
  1529. ABlobType:=StrtoInt(CurrentTokenString);
  1530. GetNextToken;
  1531. end;
  1532. Consume(tsqlBraceClose);
  1533. If CurrentToken in [tsqlSubtype,tsqlSegment] then
  1534. Error(SErrUnexpectedToken,[CurrentTokenString]);
  1535. end
  1536. else
  1537. begin
  1538. If CurrentToken=tsqlSubtype then // SUB_TYPE T
  1539. begin
  1540. GetNextToken;
  1541. Expect([tsqlIntegerNumber,tsqlBinary,tsqlText]);
  1542. case CurrentToken of
  1543. tsqlBinary: ABlobType:=0; //FB2.0+ see Language Reference Update
  1544. tsqlText: ABlobType:=1;
  1545. tsqlIntegerNumber: ABlobType:=StrtoInt(CurrentTokenString);
  1546. else Error('ParseBlobDefinition: internal error: unknown token type.');
  1547. end;
  1548. GetNextToken;
  1549. end;
  1550. If (CurrentToken=tsqlSegment) then // SEGMENT SIZE S
  1551. begin
  1552. GetNextToken;
  1553. Consume(tsqlSize);
  1554. Expect(tsqlIntegerNumber);
  1555. ASegmentSize:=StrtoInt(CurrentTokenString);
  1556. GetNextToken;
  1557. end;
  1558. end;
  1559. if (CurrentToken=tsqlCharacter) then // CHARACTER SET NNN
  1560. begin
  1561. GetNextToken;
  1562. Consume(tsqlSet);
  1563. Expect(tsqlIdentifier);
  1564. ACharSet:=CurrentTokenString;
  1565. GetNextToken;
  1566. end;
  1567. end;
  1568. function TSQLParser.ParseForeignKeyDefinition(AParent: TSQLElement
  1569. ): TSQLForeignKeyDefinition;
  1570. // On entry, we're on ON Return true if On delete
  1571. Function ParseForeignKeyAction (Out Res : TForeignKeyAction) : Boolean;
  1572. begin
  1573. GetNextToken;
  1574. Case CurrentToken of
  1575. tsqlDelete,
  1576. tsqlUpdate: Result:=CurrentToken=tsqlDelete;
  1577. else
  1578. UnexpectedToken([tsqlDelete,tsqlupdate]);
  1579. end;
  1580. Case GetNextToken of
  1581. tsqlNo :
  1582. begin
  1583. GetNextToken;
  1584. expect(tsqlAction);
  1585. Res:=fkaNoAction;
  1586. end;
  1587. tsqlCascade :
  1588. Res:=fkaCascade;
  1589. tsqlSet:
  1590. begin
  1591. Case GetNextToken of
  1592. tsqlDefault :
  1593. Res:=fkaSetDefault;
  1594. tsqlNull:
  1595. Res:=fkaSetNull;
  1596. else
  1597. UnexpectedToken([tsqlDefault,tsqlNull]);
  1598. end;
  1599. end
  1600. else
  1601. UnexpectedToken([tsqlNo,tsqlCascade,tsqlSet]);
  1602. end;
  1603. GetNextToken;
  1604. end;
  1605. Var
  1606. FKA : TForeignKeyAction;
  1607. begin
  1608. Result:=Nil;
  1609. // on entry, we are on the 'REFERENCES' token
  1610. GetNextToken;
  1611. Expect(tsqlidentifier);
  1612. Result:=TSQLForeignKeyDefinition(CreateElement(TSQLForeignKeyDefinition,AParent));
  1613. try
  1614. Result.TableName:=CreateIdentifier(Result,CurrentTokenString);
  1615. GetNextToken;
  1616. If (CurrentToken=tsqlBraceOpen) then
  1617. begin
  1618. GetNextToken;
  1619. ParseidentifierList(Result,Result.FieldList);
  1620. end;
  1621. if (CurrentToken=tsqlOn) then
  1622. begin
  1623. If ParseForeignKeyAction(FKA) then
  1624. Result.OnDelete:=FKA
  1625. else
  1626. Result.OnUpdate:=FKA;
  1627. end;
  1628. if (CurrentToken=tsqlOn) then
  1629. begin
  1630. If ParseForeignKeyAction(FKA) then
  1631. Result.OnDelete:=FKA
  1632. else
  1633. Result.OnUpdate:=FKA;
  1634. end;
  1635. except
  1636. FreeAndNil(Result);
  1637. Raise;
  1638. end;
  1639. end;
  1640. function TSQLParser.ParseFieldConstraint(AParent: TSQLElement
  1641. ): TSQLFieldConstraint;
  1642. Var
  1643. N : TSQLStringType;
  1644. K : TSQLForeignKeyFieldConstraint;
  1645. C : TSQLCheckFieldConstraint;
  1646. L : TSQLFieldConstraintList;
  1647. P : Boolean;
  1648. begin
  1649. Result:=Nil;
  1650. L:=Nil;
  1651. P:=False;
  1652. try
  1653. Repeat
  1654. If (Result<>Nil) then
  1655. begin
  1656. L:=TSQLFieldConstraintList.Create(AParent);
  1657. L.List.Add(Result);
  1658. Result:=Nil;
  1659. end;
  1660. If CurrentToken=tsqlConstraint then
  1661. begin
  1662. GetNextToken;
  1663. Expect(tsqlIdentifier);
  1664. N:=CurrentTokenString;
  1665. GetNextToken
  1666. end;
  1667. Case CurrentToken of
  1668. tsqlUnique :
  1669. begin
  1670. If P then
  1671. Error('Only one primary/unique field constraint allowed');
  1672. Result:=TSQLFieldConstraint(CreateElement(TSQLUniqueFieldConstraint,AParent));
  1673. GetNextToken;
  1674. P:=True;
  1675. end;
  1676. tsqlPrimary :
  1677. begin
  1678. If P then
  1679. Error('Only one primary/unique field constraint allowed');
  1680. GetNextToken;
  1681. Expect(tsqlKey);
  1682. Result:=TSQLFieldConstraint(CreateElement(TSQLPrimaryKeyFieldConstraint,AParent));
  1683. GetNextToken;
  1684. P:=True;
  1685. end;
  1686. tsqlReferences :
  1687. begin
  1688. K:=TSQLForeignKeyFieldConstraint(CreateElement(TSQLForeignKeyFieldConstraint,AParent));
  1689. Result:=K;
  1690. K.Definition:=ParseForeignKeyDefinition(K);
  1691. end;
  1692. tsqlCheck :
  1693. begin
  1694. C:=TSQLCheckFieldConstraint(CreateElement(TSQLCheckFieldConstraint,AParent));
  1695. Result:=C;
  1696. C.Expression:=ParseCheckConstraint(K,True);
  1697. end
  1698. else
  1699. UnexpectedToken([tsqlUnique,tsqlPrimary,tsqlReferences,tsqlCheck]);
  1700. end;
  1701. If (N<>'') then
  1702. Result.ConstraintName:=CreateIdentifier(Result,N);
  1703. Until Not (CurrentToken in [tsqlUnique,tsqlPrimary,tsqlReferences,tsqlCheck,tsqlConstraint]);
  1704. If Assigned(L) then
  1705. begin
  1706. L.List.Add(Result);
  1707. Result:=L;
  1708. end;
  1709. except
  1710. If (L<>Result) then
  1711. FReeAndNil(L);
  1712. FreeAndNil(Result);
  1713. Raise;
  1714. end;
  1715. end;
  1716. function TSQLParser.ParseTypeDefinition(AParent: TSQLElement;
  1717. Flags: TParseTypeFlags): TSQLTypeDefinition;
  1718. Var
  1719. TN : String;
  1720. AD : Integer;
  1721. DT : TSQLDataType;
  1722. AA : Boolean; // Allow Array
  1723. GN : Boolean; // Do GetNextToken ?
  1724. NN : Boolean; // Not Null ?
  1725. sc,prec : Integer;
  1726. bt : integer;
  1727. D : TSQLTypeDefinition;
  1728. cs : TSQLStringType;
  1729. Coll : TSQLCollation;
  1730. C : TSQLFieldConstraint;
  1731. begin
  1732. // We are positioned on the token prior to the type definition.
  1733. AA:=True;
  1734. GN:=True;
  1735. prec:=0;
  1736. sc:=0;
  1737. bt:=0;
  1738. NN:=True;
  1739. Coll:=Nil;
  1740. Case GetNextToken of
  1741. tsqlIdentifier :
  1742. If not (ptfAllowDomainName in Flags) then
  1743. Error(SErrDomainNotAllowed)
  1744. else
  1745. begin
  1746. DT:=sdtDomain;
  1747. TN:=CurrentTokenString;
  1748. end;
  1749. tsqlInt,
  1750. tsqlInteger :
  1751. dt:=sdtInteger;
  1752. tsqlSmallInt :
  1753. dt:=sdtSmallInt;
  1754. tsqlDate:
  1755. dt:=sdtDate;
  1756. tsqlTimeStamp:
  1757. dt:=sdtDateTime;
  1758. tsqlDouble:
  1759. begin
  1760. GetNextToken;
  1761. Expect(tsqlPrecision); //DOUBLE PRECISION
  1762. dt:=sdtDoublePrecision;
  1763. end;
  1764. tsqlFloat:
  1765. dt:=sdtFloat;
  1766. tsqlTime:
  1767. dt:=sdtTime;
  1768. tsqlDecimal,
  1769. tsqlNumeric:
  1770. begin
  1771. if CurrentToken=tsqlDecimal then
  1772. dt:=sdtDecimal
  1773. else
  1774. dt:=sdtNumeric;
  1775. GetNextToken;
  1776. GN:=False;
  1777. If (CurrentToken=tsqlBraceOpen) then
  1778. begin
  1779. GetNextToken;
  1780. Expect(tsqlIntegerNumber);
  1781. prec:=StrToInt(CurrentTokenString);
  1782. if (GetNextToken=tsqlBraceClose) then
  1783. sc:=0
  1784. else
  1785. begin
  1786. GetNextToken;
  1787. Expect(tsqlIntegerNumber);
  1788. sc:=StrToInt(CurrentTokenString);
  1789. GetNextToken;
  1790. Expect(tsqlBraceClose);
  1791. end;
  1792. GetNextToken; // position on first token after closing brace. GN=False !
  1793. end;
  1794. end;
  1795. tsqlCstring,
  1796. tsqlChar,
  1797. tsqlNChar,
  1798. tsqlVarChar,
  1799. tsqlCharacter,
  1800. tsqlNational :
  1801. begin
  1802. If (CurrentToken=tsqlCstring) and Not (([ptfExternalFunction,ptfExternalFunctionResult]*Flags) <> []) then
  1803. UnexpectedToken;
  1804. GN:=False;
  1805. ParseCharTypeDefinition(DT,Prec,cs);
  1806. end;
  1807. tsqlBlob :
  1808. begin
  1809. dt:=sdtBlob;
  1810. GN:=False;
  1811. ParseBlobDefinition(prec,bt,cs);
  1812. end;
  1813. else
  1814. UnexpectedToken;
  1815. end;
  1816. If GN then
  1817. GetNextToken;
  1818. // We are now on array definition or rest of type.
  1819. If (CurrentToken=tsqlSquareBraceOpen) then
  1820. begin
  1821. GetNextToken;
  1822. Expect(tsqlIntegerNumber);
  1823. AD:=Strtoint(CurrentTokenString);
  1824. GetNextToken;
  1825. Expect(tsqlSquareBraceClose);
  1826. GetNextToken;
  1827. end
  1828. else
  1829. AD:=0;
  1830. // Collation is here in domain (needs checking ?)
  1831. If (CurrentToken=tsqlCollate) then
  1832. begin
  1833. If not (dt in [sdtChar,sdtVarchar,sdtNchar,sdtNVarChar,sdtBlob]) then
  1834. Error(SErrInvalidUseOfCollate);
  1835. GetNextToken;
  1836. Expect(tsqlIdentifier);
  1837. Coll:=TSQLCollation(CreateElement(TSQLCollation,AParent));
  1838. Coll.Name:=CurrentTokenString;
  1839. GetNextToken;
  1840. end
  1841. else
  1842. Coll:=Nil;
  1843. C:=Nil;
  1844. D:=TSQLTypeDefinition(CreateElement(TSQLTypeDefinition,AParent));
  1845. try
  1846. D.DataType:=DT;
  1847. D.TypeName:=TN;
  1848. D.Len:=PRec;
  1849. D.Scale:=Sc;
  1850. D.BlobType:=bt;
  1851. D.ArrayDim:=AD;
  1852. D.Charset:=CS;
  1853. D.Collation:=Coll;
  1854. D.Constraint:=C;
  1855. if (not (ptfAlterDomain in Flags)) then // Alternative is to raise an error in each of the following
  1856. begin
  1857. If (CurrentToken=tsqlDefault) then
  1858. begin
  1859. GetNextToken;
  1860. D.DefaultValue:=CreateLiteral(D);
  1861. GetNextToken;
  1862. end;
  1863. if (CurrentToken=tsqlNot) then
  1864. begin
  1865. GetNextToken;
  1866. Expect(tsqlNULL);
  1867. D.NotNull:=True;
  1868. GetNextToken;
  1869. end;
  1870. If (CurrentToken=tsqlCheck) and not (ptfTableFieldDef in Flags) then
  1871. begin
  1872. D.Check:=ParseCheckConstraint(D,False);
  1873. // Parsecheckconstraint is on next token.
  1874. end;
  1875. // Firebird 2.5 generates/accepts NOT NULL after CHECK constraint instead
  1876. // of before it in at least domain definitions:
  1877. if (CurrentToken=tsqlNot) then
  1878. begin
  1879. GetNextToken;
  1880. Expect(tsqlNULL);
  1881. D.NotNull:=True;
  1882. GetNextToken;
  1883. end;
  1884. // Constraint is before collation.
  1885. if CurrentToken in [tsqlConstraint,tsqlCheck,tsqlUnique,tsqlprimary,tsqlReferences] then
  1886. begin
  1887. If Not (ptfAllowConstraint in Flags) then
  1888. UnexpectedToken;
  1889. D.Constraint:=ParseFieldConstraint(AParent);
  1890. end;
  1891. // table definition can have PRIMARY KEY CHECK
  1892. If (CurrentToken=tsqlCheck) and (ptfTableFieldDef in Flags) then
  1893. begin
  1894. D.Check:=ParseCheckConstraint(D,False);
  1895. // Parsecheckconstraint is on next token.
  1896. end;
  1897. // Collation is after constraint in table
  1898. If (CurrentToken=tsqlCollate) then
  1899. begin
  1900. If not (dt in [sdtChar,sdtVarchar,sdtNchar,sdtNVarChar,sdtBlob]) then
  1901. Error(SErrInvalidUseOfCollate);
  1902. GetNextToken;
  1903. Expect(tsqlIdentifier);
  1904. Coll:=TSQLCollation(CreateElement(TSQLCollation,AParent));
  1905. Coll.Name:=CurrentTokenString;
  1906. GetNextToken;
  1907. end
  1908. else
  1909. Coll:=Nil;
  1910. If (CurrentToken=tsqlBy) and (ptfExternalFunctionResult in Flags) then
  1911. begin
  1912. GetNextToken;
  1913. Consume(tsqlValue);
  1914. D.ByValue:=True;
  1915. end;
  1916. end;
  1917. Result:=D;
  1918. except
  1919. FreeAndNil(D);
  1920. Raise;
  1921. end;
  1922. end;
  1923. function TSQLParser.CreateLiteral(AParent : TSQLElement) : TSQLLiteral;
  1924. begin
  1925. Result:=Nil;
  1926. Case CurrentToken of
  1927. tsqlIntegerNumber:
  1928. begin
  1929. Result:=TSQLLiteral(CreateElement(TSQLIntegerLiteral,AParent));
  1930. TSQLIntegerLiteral(Result).Value:=StrToInt(CurrentTokenString);
  1931. end;
  1932. tsqlString:
  1933. begin
  1934. Result:=TSQLLiteral(CreateElement(TSQLStringLiteral,AParent));
  1935. TSQLStringLiteral(Result).Value:=CurrentTokenString;
  1936. end;
  1937. tsqlFloatNumber:
  1938. begin
  1939. Result:=TSQLLiteral(CreateElement(TSQLFloatLiteral,AParent));
  1940. TSQLFloatLiteral(Result).Value:=StrToFloat(CurrentTokenString);
  1941. end;
  1942. tsqlNull :
  1943. Result:=TSQLLiteral(CreateElement(TSQLNullLiteral,AParent));
  1944. tsqlValue :
  1945. Result:=TSQLLiteral(CreateElement(TSQLValueLiteral,AParent));
  1946. tsqlUSER :
  1947. Result:=TSQLLiteral(CreateElement(TSQLUserLiteral,AParent));
  1948. else
  1949. Error(SErrInvalidLiteral,[CurrentTokenString]);
  1950. end;
  1951. end;
  1952. procedure TSQLParser.CheckEOF;
  1953. begin
  1954. If CurrentToken=tsqlEOF then
  1955. Error('Unexpected end of command');
  1956. end;
  1957. function TSQLParser.ParseExprLevel1(AParent: TSQLElement; EO: TExpressionOptions
  1958. ): TSQLExpression;
  1959. var
  1960. tt: TSQLToken;
  1961. B : TSQLBinaryExpression;
  1962. Right: TSQLExpression;
  1963. L : TSQLLiteralExpression;
  1964. begin
  1965. Result:=ParseExprLevel2(AParent,EO);
  1966. Try
  1967. while (CurrentToken in [tsqlAnd,tsqlOr{,tsqlIs}]) do
  1968. begin
  1969. tt:=CurrentToken;
  1970. GetNextToken;
  1971. CheckEOF;
  1972. B:=TSQLBinaryExpression(CreateElement(TSQLBinaryExpression,AParent));
  1973. B.Left:=TSQLExpression(Result);
  1974. Result:=B;
  1975. If tt=tsqlIs then
  1976. begin
  1977. If CurrentToken=tsqlNot then
  1978. begin
  1979. // B.Operation:=boIsNot;
  1980. GetNextToken;
  1981. end
  1982. else
  1983. B.Operation:=boIs;
  1984. Expect(tsqlNull);
  1985. L:=TSQLLiteralExpression(CreateElement(TSQLLiteralExpression,AParent));
  1986. L.Literal:=CreateLiteral(AParent);
  1987. B.Right:=L;
  1988. GetNexttoken;
  1989. end
  1990. else
  1991. begin
  1992. case tt of
  1993. tsqlOr : B.Operation:=boOr;
  1994. tsqlAnd : B.Operation:=boAnd;
  1995. Else
  1996. Error(SErrUnknownBooleanOp)
  1997. end;
  1998. B.Right:=ParseExprLevel2(AParent,EO);
  1999. end;
  2000. end;
  2001. Except
  2002. Result.Free;
  2003. Raise;
  2004. end;
  2005. end;
  2006. function TSQLParser.ParseInoperand(AParent: TSQLElement): TSQLExpression;
  2007. Var
  2008. S : TSQLSelectExpression;
  2009. L : TSQLListExpression;
  2010. Done : Boolean;
  2011. begin
  2012. // On entry, we're on the first token after IN token, which is the ( token.
  2013. Consume(tsqlBraceopen);
  2014. try
  2015. If (CurrentToken=tsqlSelect) then
  2016. begin
  2017. S:=TSQLSelectExpression(CreateElement(TSQLSelectExpression,APArent));
  2018. Result:=S;
  2019. S.Select:=ParseSelectStatement(AParent,[sfSingleton]);
  2020. Consume(tsqlBraceClose);
  2021. end
  2022. else
  2023. begin
  2024. L:=TSQLListExpression(CreateElement(TSQLListExpression,AParent));
  2025. Result:=L;
  2026. Repeat
  2027. L.List.Add(ParseExprLevel1(L,[eoListValue]));
  2028. Expect([tsqlBraceClose,tsqlComma]);
  2029. Done:=(CurrentToken=tsqlBraceClose);
  2030. GetNextToken;
  2031. until Done;
  2032. end;
  2033. except
  2034. FreeAndNil(Result);
  2035. end;
  2036. end;
  2037. function TSQLParser.ParseExprLevel2(AParent: TSQLElement; EO: TExpressionOptions
  2038. ): TSQLExpression;
  2039. var
  2040. tt: TSQLToken;
  2041. Right : TSQLExpression;
  2042. B : TSQLBinaryExpression;
  2043. T : TSQLTernaryExpression;
  2044. O : TSQLBinaryOperation;
  2045. U : TSQLUnaryExpression;
  2046. Inverted,bw,doin : Boolean;
  2047. begin
  2048. {$ifdef debugexpr} Writeln('Level 2 ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
  2049. Result:=ParseExprLevel3(AParent,EO);
  2050. try
  2051. if (CurrentToken in sqlComparisons) then
  2052. begin
  2053. tt:=CurrentToken;
  2054. Inverted:=CurrentToken=tsqlnot;
  2055. CheckEOF;
  2056. GetNextToken;
  2057. CheckEOF;
  2058. if Inverted then
  2059. begin
  2060. tt:=CurrentToken;
  2061. if Not (tt in sqlInvertableComparisons) then
  2062. Error(SErrUnexpectedToken,[CurrentTokenString]);
  2063. GetNextToken;
  2064. // Step past expected STARTING WITH
  2065. If (tt=tsqlStarting) and (CurrentToken=tsqlWith) then
  2066. GetNextToken;
  2067. end
  2068. else
  2069. begin
  2070. // Step past expected STARTING WITH
  2071. If (tt=tsqlStarting) and (CurrentToken=tsqlWith) then
  2072. GetNextToken;
  2073. if (CurrentToken=tsqlNot) then
  2074. begin
  2075. GetNextToken;
  2076. if not (tt=tsqlis) then
  2077. UnexpectedToken;
  2078. Inverted:=true;
  2079. end;
  2080. end;
  2081. bw:=False;
  2082. doin:=false;
  2083. B:=nil; //needed for test later
  2084. Case tt of
  2085. tsqlLT : O:=boLT;
  2086. tsqlLE : O:=boLE;
  2087. tsqlGT : O:=boGT;
  2088. tsqlGE : O:=boGE;
  2089. tsqlEq : O:=boEq;
  2090. tsqlNE : O:=boNE;
  2091. tsqlLike : O:=boLike;
  2092. tsqlIn : doIn:=true;
  2093. tsqlis : O:=boIs;
  2094. tsqlContaining : O:=boContaining;
  2095. tsqlStarting : O:=boStarting;
  2096. tsqlBetween : bw:=true;
  2097. Else
  2098. Error(SErrUnknownComparison)
  2099. end;
  2100. If doIn then
  2101. begin
  2102. Right:=ParseInOperand(AParent);
  2103. B:=TSQLBinaryExpression(CreateElement(TSQLBinaryExpression,AParent));
  2104. B.Operation:=boIn;
  2105. B.Left:=Result;
  2106. Result:=B;
  2107. B.Right:=Right;
  2108. end
  2109. else
  2110. begin
  2111. Right:=ParseExprLevel3(AParent,EO);
  2112. If (O=boLike) and (CurrentToken=tsqlEscape) then
  2113. begin
  2114. GetNextToken;
  2115. T:=TSQLTernaryExpression(CreateElement(TSQLTernaryExpression,AParent));
  2116. T.Left:=Result;
  2117. Result:=T;
  2118. T.Middle:=Right;
  2119. T.Right:=ParseExprLevel3(AParent,EO);
  2120. T.Operation:=toLikeEscape
  2121. end
  2122. else If bw then
  2123. begin
  2124. Consume(tsqlAnd);
  2125. T:=TSQLTernaryExpression(CreateElement(TSQLTernaryExpression,AParent));
  2126. T.Left:=Result;
  2127. Result:=T;
  2128. T.Middle:=Right;
  2129. T.Right:=ParseExprLevel3(AParent,EO);
  2130. T.Operation:=toBetween;
  2131. end
  2132. else
  2133. begin
  2134. B:=TSQLBinaryExpression(CreateElement(TSQLBinaryExpression,AParent));
  2135. B.Operation:=O;
  2136. B.Left:=Result;
  2137. Result:=B;
  2138. B.Right:=Right;
  2139. end;
  2140. end;
  2141. If Inverted then
  2142. if (Assigned(B)) and (B.Operation=boIs) then
  2143. B.Operation:=boIsNot
  2144. else
  2145. begin
  2146. U:=TSQLUnaryExpression(CreateElement(TSQLUnaryExpression,AParent));
  2147. U.Operand:=Result;
  2148. U.Operation:=uoNot;
  2149. Result:=U;
  2150. end;
  2151. end;
  2152. Except
  2153. Result.Free;
  2154. Raise;
  2155. end;
  2156. end;
  2157. function TSQLParser.ParseExprLevel3(AParent: TSQLElement; EO: TExpressionOptions
  2158. ): TSQLExpression;
  2159. Function NegativeNumber : Boolean; inline;
  2160. begin
  2161. Result:=(CurrentToken in [tsqlIntegerNumber,tsqlFloatNumber]) and (StrToInt(CurrentTokenString)<0)
  2162. end;
  2163. var
  2164. tt : TSQLToken;
  2165. right : TSQLExpression;
  2166. B : TSQLBinaryExpression;
  2167. begin
  2168. {$ifdef debugexpr} Writeln('Level 3 ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
  2169. Result:=ParseExprLevel4(AParent,EO);
  2170. try
  2171. {$ifdef debugexpr} Writeln('Level 3 continues ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
  2172. // Scanner returns -N as an negative number, not as - (positive number)
  2173. // NegativeNumber is for the case A-1 or so: convert to A + -1
  2174. while (CurrentToken in [tsqlConcatenate,tsqlPlus,tsqlMinus]) or NegativeNumber do
  2175. begin
  2176. tt:=CurrentToken;
  2177. If NegativeNumber then
  2178. tt:=tsqlPlus // Pretend we've eaten +
  2179. else
  2180. begin
  2181. GetNextToken;
  2182. CheckEOF;
  2183. end;
  2184. Right:=ParseExprLevel4(AParent,EO);
  2185. B:=TSQLBinaryExpression(CreateElement(TSQLBinaryExpression,AParent));
  2186. B.Left:=Result;
  2187. Result:=B;
  2188. B.Right:=Right;
  2189. Case tt of
  2190. tsqlPlus : B.Operation:=boAdd;
  2191. tsqlMinus : B.Operation:=boSubtract;
  2192. tsqlConcatenate : B.Operation:=boConcat;
  2193. end;
  2194. end;
  2195. Except
  2196. Result.Free;
  2197. Raise;
  2198. end;
  2199. end;
  2200. function TSQLParser.ParseExprLevel4(AParent: TSQLElement; EO: TExpressionOptions
  2201. ): TSQLExpression;
  2202. var
  2203. tt : TSQLToken;
  2204. right : TSQLExpression;
  2205. B : TSQLBinaryExpression;
  2206. begin
  2207. {$ifdef debugexpr} Writeln('Level 4 ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
  2208. Result:=ParseExprLevel5(AParent,EO);
  2209. try
  2210. while (CurrentToken in [tsqlMul,tsqlDiv]) do
  2211. begin
  2212. tt:=CurrentToken;
  2213. GetNextToken;
  2214. CheckEOF;
  2215. Right:=ParseExprLevel5(AParent,EO);
  2216. B:=TSQLBinaryExpression(CreateElement(TSQLBinaryExpression,AParent));
  2217. B.Left:=Result;
  2218. B.Right:=Right;
  2219. Case tt of
  2220. tsqlMul : B.Operation:=boMultiply;
  2221. tsqlDiv : B.Operation:=boDivide;
  2222. end;
  2223. end;
  2224. Except
  2225. Result.Free;
  2226. Raise;
  2227. end;
  2228. end;
  2229. function TSQLParser.ParseExprLevel5(AParent: TSQLElement; EO: TExpressionOptions
  2230. ): TSQLExpression;
  2231. Var
  2232. tt : tsqltoken;
  2233. U : TSQLUnaryExpression;
  2234. begin
  2235. {$ifdef debugexpr} Writeln('Level 5 ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
  2236. tt:=tsqlunknown;
  2237. if (CurrentToken in [tsqlNot,tsqlPlus,tsqlMinus]) then
  2238. begin
  2239. tt:=CurrentToken;
  2240. GetNextToken;
  2241. CheckEOF;
  2242. end;
  2243. Result:=ParseExprLevel6(AParent,EO);
  2244. try
  2245. If tt<>tsqlUnknown then
  2246. begin
  2247. U:=TSQLunaryExpression(CreateElement(TSQLunaryExpression,AParent));
  2248. if tt=tsqlNot then
  2249. U.Operation:=uoNot
  2250. else
  2251. U.Operation:=uoMinus;
  2252. U.Operand:=Result;
  2253. Result:=U;
  2254. end;
  2255. except
  2256. FreeandNil(Result);
  2257. Raise;
  2258. end;
  2259. end;
  2260. function TSQLParser.ParseExprLevel6(AParent: TSQLElement; EO: TExpressionOptions
  2261. ): TSQLExpression;
  2262. begin
  2263. {$ifdef debugexpr} Writeln('Level 6 ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
  2264. if (CurrentToken=tsqlBraceOpen) then
  2265. begin
  2266. GetNextToken;
  2267. If (CurrentToken<>tsqlselect) then
  2268. Result:=ParseExprLevel1(AParent,EO)
  2269. else
  2270. begin
  2271. Result:=TSQLExpression(CreateElement(TSQLSelectExpression,AParent));
  2272. try
  2273. TSQLSelectExpression(Result).Select:=ParseSelectStatement(Result,[sfSingleTon]);
  2274. except
  2275. FreeAndNil(Result);
  2276. Raise;
  2277. end;
  2278. end;
  2279. try
  2280. if (CurrentToken<>tsqlBraceClose) then
  2281. Error(SerrUnmatchedBrace);
  2282. GetNextToken;
  2283. Except
  2284. Result.Free;
  2285. Raise;
  2286. end;
  2287. end
  2288. else
  2289. Result:=ParseExprPrimitive(AParent,EO);
  2290. end;
  2291. function TSQLParser.ParseIdentifierList(AParent: TSQLElement;
  2292. AList: TSQLelementList): integer;
  2293. Var
  2294. Done : Boolean;
  2295. begin
  2296. // on entry, we're on first identifier
  2297. Expect(tsqlIdentifier);
  2298. Result:=0;
  2299. Done:=False;
  2300. repeat
  2301. if CurrentToken=tsqlComma then
  2302. GetNextToken;
  2303. Expect(tsqlIdentifier);
  2304. AList.add(CreateIdentifier(AParent,CurrentTokenString));
  2305. Inc(Result);
  2306. until (GetNextToken<>tsqlComma);
  2307. Expect(tsqlBraceClose);
  2308. GetNextToken;
  2309. end;
  2310. function TSQLParser.ParseValueList(AParent: TSQLElement; EO: TExpressionOptions
  2311. ): TSQLElementList;
  2312. Var
  2313. E : TSQLExpression;
  2314. begin
  2315. Result:=Nil;
  2316. E:=Nil;
  2317. // First token is (
  2318. Expect(tsqlBraceOpen);
  2319. Repeat
  2320. GetNextToken;
  2321. If (CurrentToken<>tsqlBraceClose) then
  2322. E:=ParseExprLevel1(AParent,EO);
  2323. If (E<>Nil) then
  2324. begin
  2325. If Result=Nil then
  2326. Result:=TSQLElementList.Create(True);
  2327. Result.Add(E);
  2328. end;
  2329. Expect([tsqlComma,tsqlBraceClose]);
  2330. Until CurrentToken=tsqlBraceClose;
  2331. end;
  2332. procedure TSQLParser.UnexpectedToken;
  2333. begin
  2334. Error(SErrUnexpectedToken,[CurrentTokenString]);
  2335. end;
  2336. procedure TSQLParser.UnexpectedToken(AExpected: TSQLTokens);
  2337. Var
  2338. S : String;
  2339. I : TSQLToken;
  2340. begin
  2341. S:='';
  2342. For I:=Low(TSQLToken) to High(TSQLToken) do
  2343. if I in AExpected then
  2344. begin
  2345. If (S<>'') then
  2346. S:=S+',';
  2347. S:=S+TokenInfos[i];
  2348. end;
  2349. Error(SErrUnexpectedTokenOf,[CurrentTokenString,S]);
  2350. end;
  2351. function TSQLParser.CreateIdentifier(AParent: TSQLElement;
  2352. const AName: TSQLStringType): TSQLIdentifierName;
  2353. begin
  2354. Result:=TSQLIdentifierName(CreateElement(TSQLIdentifierName,AParent));
  2355. Result.Name:=AName;
  2356. end;
  2357. function TSQLParser.ParseExprAggregate(AParent: TSQLElement;
  2358. EO: TExpressionOptions): TSQLAggregateFunctionExpression;
  2359. begin
  2360. Result:=TSQLAggregateFunctionExpression(CreateElement(TSQLAggregateFunctionExpression,AParent));
  2361. try
  2362. Case CurrentToken of
  2363. tsqlCount : Result.Aggregate:=afCount;
  2364. tsqlSum : Result.Aggregate:=afSum;
  2365. tsqlAvg : Result.Aggregate:=afAvg;
  2366. tsqlMax : Result.Aggregate:=afMax;
  2367. tsqlMin : Result.Aggregate:=afMin;
  2368. end;
  2369. GetNextToken;
  2370. Consume(tsqlBraceOpen);
  2371. If CurrentToken=tsqlMul then
  2372. begin
  2373. If Result.Aggregate<>afCount then
  2374. Error(SErrAsteriskOnlyInCount);
  2375. Result.OPtion:=aoAsterisk;
  2376. GetNextToken;
  2377. end
  2378. else
  2379. begin
  2380. if (CurrentToken in [tsqlAll,tsqlDistinct]) then
  2381. begin
  2382. If CurrentToken=tsqlAll then
  2383. Result.Option:=aoAll
  2384. else
  2385. Result.Option:=aoDistinct;
  2386. GetNextToken;
  2387. end;
  2388. Result.Expression:=ParseExprLevel1(Result,EO);
  2389. end;
  2390. Consume(tsqlBraceClose);
  2391. except
  2392. FreeAndNil(Result);
  2393. Raise;
  2394. end;
  2395. end;
  2396. function TSQLParser.ParseExprPrimitive(AParent: TSQLElement;
  2397. EO: TExpressionOptions): TSQLExpression;
  2398. Var
  2399. L : TSQLElementList;
  2400. N : String;
  2401. C : TSQLElementClass;
  2402. E : TSQLExtractElement;
  2403. begin
  2404. Result:=Nil;
  2405. try
  2406. {$ifdef debugexpr} Writeln('Primitive ',TokenInfos[CurrentToken],': ',CurrentTokenString);{$endif debugexpr}
  2407. Case CurrentToken of
  2408. tsqlIntegerNumber,
  2409. tsqlString,
  2410. tsqlFloatNumber,
  2411. tsqlNull, // True and False belong here
  2412. tsqlValue,
  2413. tsqlUser:
  2414. begin
  2415. Result:=TSQLLiteralExpression(CreateElement(TSQLLiteralExpression,AParent));
  2416. TSQLLiteralExpression(Result).Literal:=CreateLiteral(AParent);
  2417. GetNextToken;
  2418. end;
  2419. tsqlCast:
  2420. begin
  2421. GetNextToken;
  2422. Consume(tsqlBraceOpen);
  2423. Result:=TSQLCastExpression(CreateElement(TSQLCastExpression,AParent));
  2424. TSQLCastExpression(Result).Value:=ParseExprLevel1(Result,EO);
  2425. Expect(tsqlAs);
  2426. TSQLCastExpression(Result).NewType:=ParseTypeDefinition(Result,[ptfCast]);
  2427. Consume(tsqlBraceClose);
  2428. end;
  2429. tsqlExtract:
  2430. begin
  2431. GetNextToken;
  2432. Consume(tsqlBraceOpen);
  2433. Expect(tsqlIdentifier);
  2434. if not StringToSQLExtractElement(CurrentTokenString,E) then
  2435. Error(SErrInvalidExtract,[CurrentTokenString]);
  2436. Consume(tsqlIdentifier);
  2437. Consume(tsqlFrom);
  2438. Result:=TSQLExtractExpression(CreateElement(TSQLExtractExpression,AParent));
  2439. TSQLExtractExpression(Result).Element:=E;
  2440. TSQLExtractExpression(Result).Value:=ParseExprLevel1(Result,EO);
  2441. Consume(tsqlBraceClose);
  2442. end;
  2443. tsqlExists,
  2444. tsqlAll,
  2445. tsqlAny,
  2446. tsqlSome,
  2447. tsqlSingular:
  2448. begin
  2449. Case CurrentToken of
  2450. tsqlExists : C:=TSQLexistsExpression;
  2451. tsqlAll : C:=TSQLAllExpression;
  2452. tsqlAny : C:=TSQLAnyExpression;
  2453. tsqlSome : C:=TSQLSomeExpression;
  2454. tsqlSingular : C:=TSQLSingularExpression;
  2455. end;
  2456. GetNextToken;
  2457. Consume(tsqlBraceOpen);
  2458. Result:=TSQLSelectionExpression(CreateElement(C,AParent));
  2459. TSQLSelectionExpression(Result).Select:=ParseSelectStatement(Result,[]);
  2460. Consume(tsqlBraceClose);
  2461. end;
  2462. tsqlCount,
  2463. tsqlSum,
  2464. tsqlAvg,
  2465. tsqlMax,
  2466. tsqlMin :
  2467. begin
  2468. If not ([eoSelectValue,eoHaving]*EO <> []) then
  2469. Error(SErrNoAggregateAllowed);
  2470. Result:=ParseExprAggregate(APArent,EO);
  2471. end;
  2472. tsqlUpper :
  2473. begin
  2474. GetNextToken;
  2475. L:=ParseValueList(AParent,EO);
  2476. If L.Count<>1 then
  2477. begin
  2478. FreeAndNil(L);
  2479. Error(SErrUpperOneArgument);
  2480. end;
  2481. GetNextToken; // Consume );
  2482. Result:=TSQLFunctionCallExpression(CreateElement(TSQLFunctionCallExpression,AParent));
  2483. TSQLFunctionCallExpression(Result).IDentifier:='UPPER';
  2484. TSQLFunctionCallExpression(Result).Arguments:=L;
  2485. end;
  2486. tsqlGenID :
  2487. begin
  2488. GetNextToken;
  2489. Consume(tsqlBraceOpen);
  2490. expect(tsqlIdentifier);
  2491. N:=CurrentTokenString;
  2492. GetNextToken;
  2493. Consume(tsqlComma);
  2494. Result:=TSQLGenIDExpression(CreateElement(TSQLGenIDExpression,AParent));
  2495. TSQLGenIDExpression(Result).Generator:=CreateIdentifier(Result,N);
  2496. TSQLGenIDExpression(Result).Value:=ParseExprLevel1(AParent,EO);
  2497. Consume(tsqlBraceClose);
  2498. end;
  2499. tsqlColon:
  2500. begin
  2501. if (([eoCheckConstraint,eoTableConstraint,eoComputedBy] * EO)<>[]) then
  2502. Error(SErrUnexpectedToken,[CurrentTokenString]);
  2503. GetNextToken;
  2504. expect(tsqlIdentifier);
  2505. N:=CurrentTokenString;
  2506. Result:=TSQLParameterExpression(CreateElement(TSQLParameterExpression,AParent));
  2507. TSQLParameterExpression(Result).Identifier:=CreateIdentifier(Result,N);
  2508. Consume(tsqlIdentifier);
  2509. end;
  2510. tsqlIdentifier:
  2511. begin
  2512. N:=CurrentTokenString;
  2513. If (GetNextToken<>tsqlBraceOpen) then
  2514. begin
  2515. If (eoCheckConstraint in EO) and not (eoTableConstraint in EO) then
  2516. Error(SErrUnexpectedToken,[CurrentTokenString]);
  2517. If (CurrentToken=tsqlDot) then
  2518. begin
  2519. GetNextToken;
  2520. Expect(tsqlIdentifier);
  2521. N:=N+'.'+CurrentTokenString;
  2522. GetNextToken;
  2523. end;
  2524. // plain identifier
  2525. Result:=TSQLIdentifierExpression(CreateElement(TSQLIdentifierExpression,APArent));
  2526. TSQLIdentifierExpression(Result).IDentifier:=CreateIdentifier(Result,N);
  2527. // Array access ?
  2528. If (CurrentToken=tsqlSquareBraceOpen) then
  2529. begin
  2530. If (GetNextToken<>tsqlIntegerNumber) then
  2531. Error(SErrIntegerExpected);
  2532. TSQLIdentifierExpression(Result).ElementIndex:=StrToInt(CurrentTokenString);
  2533. GetNextToken;
  2534. Consume(tsqlSquareBraceClose);
  2535. end;
  2536. end
  2537. else
  2538. begin
  2539. L:=ParseValueList(AParent,EO);
  2540. GetNextToken; // Consume );
  2541. // Function call
  2542. Result:=TSQLFunctionCallExpression(CreateElement(TSQLFunctionCallExpression,AParent));
  2543. TSQLFunctionCallExpression(Result).IDentifier:=N;
  2544. TSQLFunctionCallExpression(Result).Arguments:=L;
  2545. end;
  2546. end;
  2547. else
  2548. UnexpectedToken;
  2549. end;
  2550. except
  2551. FreeAndNil(Result);
  2552. Raise;
  2553. end;
  2554. end;
  2555. function TSQLParser.ParseSQLValue(AParent : TSQLElement) : TSQLExpression;
  2556. Var
  2557. E : TSQLExpression;
  2558. begin
  2559. E:=ParseExprLevel1(AParent,[]);
  2560. Result:=E;
  2561. end;
  2562. function TSQLParser.ParseCheckConstraint(AParent : TSQLElement; TableConstraint : Boolean = False) : TSQLExpression;
  2563. Var
  2564. EO : TExpressionOptions;
  2565. begin
  2566. // We are on the 'CHECK' token.
  2567. GetNextToken;
  2568. Consume(tsqlBraceOpen);
  2569. EO:=[eoCheckConstraint];
  2570. If TableConstraint then
  2571. EO:=EO+[eoTableConstraint];
  2572. Result:=ParseExprLevel1(AParent,EO);
  2573. Consume(tsqlBraceClose);
  2574. end;
  2575. function TSQLParser.ParseCreateDomainStatement(AParent: TSQLElement; IsAlter: Boolean
  2576. ): TSQLCreateOrAlterStatement;
  2577. var
  2578. D : TSQLCreateDomainStatement;
  2579. A : TSQLAlterDomainStatement;
  2580. N : TSQLStringType;
  2581. NN : Boolean;
  2582. begin
  2583. Result:=Nil;
  2584. GetNextToken;
  2585. Expect(tsqlIdentifier);
  2586. N:=CurrentTokenString;
  2587. If not IsAlter then
  2588. begin
  2589. D:=TSQLCreateDomainStatement(CreateElement(TSQLCreateDomainStatement,AParent));
  2590. try
  2591. D.ObjectName:=CreateIdentifier(D,N);
  2592. If (PeekNextToken=tsqlAs) then
  2593. GetNextToken;
  2594. D.TypeDefinition:=ParseTypeDefinition(D,[])
  2595. except
  2596. FreeAndNil(D);
  2597. Raise;
  2598. end;
  2599. Result:=D;
  2600. end
  2601. else
  2602. begin //alter statement
  2603. A:=Nil;
  2604. NN:=False;
  2605. try
  2606. Case GetNextToken of
  2607. tsqlSet:
  2608. begin
  2609. GetNextToken;
  2610. Expect(tsqlDefault);
  2611. GetNextToken;
  2612. A:=TSQLAlterDomainSetDefaultStatement(CreateElement(TSQLAlterDomainSetDefaultStatement,APArent));
  2613. TSQLAlterDomainSetDefaultStatement(A).DefaultValue:=CreateLiteral(A);
  2614. end;
  2615. tsqlDrop:
  2616. begin
  2617. Case GetNextToken of
  2618. tsqlDefault : A:=TSQLAlterDomainDropDefaultStatement(CreateElement(TSQLAlterDomainDropDefaultStatement,APArent));
  2619. tsqlConstraint : A:=TSQLAlterDomainDropCheckStatement(CreateElement(TSQLAlterDomainDropCheckStatement,APArent));
  2620. else
  2621. Error(SErrUnexpectedToken,[CurrentTokenString]);
  2622. end;
  2623. end;
  2624. tsqlAdd:
  2625. begin
  2626. if (GetNextToken=tsqlConstraint) then
  2627. GetNextToken;
  2628. Expect(tsqlCheck);
  2629. A:=TSQLAlterDomainAddCheckStatement(CreateElement(TSQLAlterDomainAddCheckStatement,APArent));
  2630. TSQLAlterDomainAddCheckStatement(A).Check:=ParseCheckConstraint(A);
  2631. NN:=True;
  2632. end;
  2633. tsqlType:
  2634. begin
  2635. A:=TSQLAlterDomainTypeStatement(CreateElement(TSQLAlterDomainTypeStatement,AParent));
  2636. TSQLAlterDomainTypeStatement(A).NewType:=ParseTypeDefinition(A,[ptfAlterDomain]);
  2637. NN:=True;
  2638. end;
  2639. tsqlIdentifier:
  2640. begin
  2641. A:=TSQLAlterDomainRenameStatement(CreateElement(TSQLAlterDomainRenameStatement,APArent));
  2642. TSQLAlterDomainRenameStatement(A).NewName:=CreateIdentifier(A,CurrentTokenString);
  2643. end;
  2644. else
  2645. UnexpectedToken([tsqlSet,tsqlIdentifier,tsqlAdd,tsqlType,tsqlDrop]);
  2646. end;
  2647. A.ObjectName:=CreateIdentifier(A,N);
  2648. Result:=A;
  2649. If not NN then
  2650. GetNextToken;
  2651. except
  2652. FreeAndNil(A);
  2653. Raise;
  2654. end;
  2655. end;
  2656. end;
  2657. function TSQLParser.ParseCreateExceptionStatement(AParent: TSQLElement;
  2658. IsAlter: Boolean): TSQLCreateOrAlterStatement;
  2659. var
  2660. E : TSQLCreateExceptionStatement;
  2661. N : TSQLStringType;
  2662. begin
  2663. GetNextToken;
  2664. Expect(tsqlIdentifier);
  2665. N:=CurrentTokenString;
  2666. try
  2667. if IsAlter then
  2668. E:=TSQLCreateExceptionStatement(CreateElement(TSQLAlterExceptionStatement,AParent))
  2669. else
  2670. E:=TSQLCreateExceptionStatement(CreateElement(TSQLCreateExceptionStatement,AParent));
  2671. E.ObjectName:=CreateIdentifier(E,N);
  2672. GetNextToken;
  2673. Expect(tsqlString);
  2674. E.ExceptionMessage:=TSQLStringLiteral(CreateElement(TSQLStringLiteral,E));
  2675. E.ExceptionMessage.Value:=CurrentTokenString;
  2676. GetNextToken;
  2677. except
  2678. FreeAndNil(E);
  2679. Raise;
  2680. end;
  2681. Result:=E;
  2682. end;
  2683. function TSQLParser.ParseCreateTriggerStatement(AParent: TSQLElement; IsAlter: Boolean
  2684. ): TSQLCreateOrAlterStatement;
  2685. Var
  2686. T : TSQLAlterCreateTriggerStatement;
  2687. begin
  2688. // On entry, we're on the 'TRIGGER' token.
  2689. Consume(tsqlTrigger);
  2690. If IsAlter then
  2691. T:=TSQLAlterTriggerStatement(CreateElement(TSQLAlterTriggerStatement,APArent))
  2692. else
  2693. T:=TSQLCreateTriggerStatement(CreateElement(TSQLCreateTriggerStatement,APArent));
  2694. Result:=T;
  2695. try
  2696. Expect(tsqlidentifier);
  2697. Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
  2698. getnexttoken;
  2699. If Not IsAlter then
  2700. begin
  2701. Consume(tsqlfor);
  2702. Expect(tsqlidentifier);
  2703. T.TableName:=CreateIdentifier(Result,CurrentTokenString);
  2704. GetNextToken;
  2705. end;
  2706. if (CurrentToken in [tsqlActive,tsqlInactive]) then
  2707. begin
  2708. If CurrentToken=tsqlActive then
  2709. T.State:=tsActive
  2710. else
  2711. T.State:=tsInactive;
  2712. GetNextToken;
  2713. end;
  2714. Expect([tsqlBefore,tsqlAfter]);
  2715. if CurrentToken=tsqlBefore then
  2716. T.Moment:=tmBefore
  2717. else
  2718. T.Moment:=tmAfter;
  2719. Repeat
  2720. GetNextToken;
  2721. Expect([tsqlDelete,tsqlInsert,tsqlUpdate]);
  2722. Case CurrentToken of
  2723. tsqlDelete : T.Operations:=T.Operations+[toDelete];
  2724. tsqlUpdate : T.Operations:=T.Operations+[toUpdate];
  2725. tsqlInsert : T.Operations:=T.Operations+[toInsert];
  2726. end;
  2727. GetNextToken;
  2728. Until (CurrentToken<>tsqlOr);
  2729. If CurrentToken=tsqlPosition then
  2730. begin
  2731. GetNextToken;
  2732. Expect(tsqlIntegerNumber);
  2733. T.Position:=StrToInt(CurrentTokenString);
  2734. GetNextToken;
  2735. end;
  2736. Consume(tsqlAs);
  2737. if (CurrentToken=tsqlDeclare) then
  2738. ParseCreateProcedureVariableList(Result,T.LocalVariables);
  2739. expect(tsqlBegin);
  2740. ParseStatementBlock(Result,T.Statements);
  2741. except
  2742. FreeAndNil(Result);
  2743. Raise;
  2744. end;
  2745. end;
  2746. function TSQLParser.ParseSetGeneratorStatement(AParent: TSQLElement
  2747. ): TSQLSetGeneratorStatement;
  2748. begin
  2749. // On entry, we're on the 'GENERATOR' token
  2750. Consume(tsqlGenerator) ;
  2751. try
  2752. Result:=TSQLSetGeneratorStatement(CreateElement(TSQLSetGeneratorStatement,AParent));
  2753. expect(tsqlidentifier);
  2754. Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
  2755. GetNextToken;
  2756. consume(tsqlto);
  2757. expect(tsqlIntegerNumber);
  2758. Result.NewValue:=StrToInt(CurrentTokenString);
  2759. GetNextToken;
  2760. except
  2761. FreeAndNil(Result);
  2762. Raise;
  2763. end;
  2764. end;
  2765. function TSQLParser.ParseSetTermStatement(AParent: TSQLElement
  2766. ): TSQLSetTermStatement;
  2767. var
  2768. ExistingStatTerm: string;
  2769. begin
  2770. // On entry, we're on the 'TERM' token
  2771. Consume(tsqlTerm) ;
  2772. try
  2773. Result:=TSQLSetTermStatement(CreateElement(TSQLSetTermStatement,AParent));
  2774. expect([tsqlSemiColon,tsqlStatementTerminator,tsqlSymbolLiteral,tsqlString]);
  2775. // Already set the expression's new value to the new terminator, but do not
  2776. // change tSQLStatementTerminator as GetNextToken etc need the old one to
  2777. // detect the closing terminator
  2778. case CurrentToken of
  2779. tsqlSemiColon, tsqlStatementTerminator: Result.NewValue:=TokenInfos[CurrentToken];
  2780. tsqlSymbolLiteral, tsqlString: Result.NewValue:=CurrentTokenString;
  2781. end;
  2782. // Expect the old terminator...
  2783. GetNextToken;
  2784. // Parser will give tsqlSemicolon rather than tsqlStatementTerminator:
  2785. if TokenInfos[tsqlStatementTerminator]=TokenInfos[tsqlSEMICOLON] then
  2786. Expect(tsqlSEMICOLON)
  2787. else
  2788. Expect(tsqlStatementTerminator);
  2789. //... and now set the new terminator:
  2790. TokenInfos[tsqlStatementTerminator]:=Result.NewValue; //process new terminator value
  2791. except
  2792. FreeAndNil(Result);
  2793. Raise;
  2794. end;
  2795. end;
  2796. function TSQLParser.ParseSecondaryFile(AParent: TSQLElement) : TSQLDatabaseFileInfo;
  2797. Var
  2798. I : INteger;
  2799. Last : TSQLToken;
  2800. begin
  2801. // On entry, we're on the FILE token
  2802. Consume(tsqlFile);
  2803. Result:=TSQLDatabaseFileInfo(CreateElement(TSQLDatabaseFileInfo,APArent));
  2804. try
  2805. Expect(tsqlString);
  2806. Result.FileName:=CurrentTokenString;
  2807. getNextToken;
  2808. I:=0;
  2809. last:=tsqlEOF;
  2810. While (I<2) and (CurrentToken in [tsqlLength,tsqlStarting]) do
  2811. begin
  2812. Inc(I);
  2813. If (CurrentToken=tsqlLength) then
  2814. begin
  2815. If Last=tsqlLength then
  2816. UnexpectedToken;
  2817. Last:=tsqlLength;
  2818. GetNextToken;
  2819. if (CurrentToken=tsqlEq) then
  2820. GetNextToken;
  2821. Expect(tsqlIntegerNumber);
  2822. Result.Length:=StrToInt(CurrentTokenString);
  2823. GetNextToken;
  2824. If CurrentToken in [tsqlPage,tsqlPages] then
  2825. GetNextToken;
  2826. end
  2827. else if (CurrentToken=tsqlStarting) then
  2828. begin
  2829. If Last=tsqlStarting then
  2830. UnexpectedToken;
  2831. Last:=tsqlStarting;
  2832. GetNextToken;
  2833. if (CurrentToken=tsqlAt) then
  2834. begin
  2835. GetNextToken;
  2836. If CurrentToken=tsqlPage then
  2837. GetNextToken;
  2838. end;
  2839. Expect(tsqlIntegerNumber);
  2840. Result.StartPage:=StrToInt(CurrentTokenString);
  2841. GetNextToken;
  2842. end;
  2843. end;
  2844. except
  2845. FreeAndNil(Result);
  2846. Raise;
  2847. end;
  2848. end;
  2849. function TSQLParser.ParseCreateDatabaseStatement(AParent: TSQLElement; IsAlter: Boolean) : TSQLCreateDatabaseStatement;
  2850. begin
  2851. // On entry, we're on the DATABASE or SCHEMA token
  2852. Result:=TSQLCreateDatabaseStatement(CreateElement(TSQLCreateDatabaseStatement,AParent));
  2853. try
  2854. Result.UseSchema:=(CurrentToken=tsqlSchema);
  2855. GetNextToken;
  2856. Expect(tsqlString);
  2857. Result.FileName:=CurrentTokenString;
  2858. GetNextToken;
  2859. If (CurrentToken=tsqlUSER) then
  2860. begin
  2861. GetNextToken;
  2862. Expect(tsqlString);
  2863. Result.UserName:=CurrentTokenString;
  2864. GetNextToken;
  2865. end;
  2866. If (CurrentToken=tsqlPassword) then
  2867. begin
  2868. GetNextToken;
  2869. Expect(tsqlString);
  2870. Result.Password:=CurrentTokenString;
  2871. GetNextToken;
  2872. end;
  2873. If (CurrentToken=tsqlPageSize) then
  2874. begin
  2875. GetNextToken;
  2876. if CurrentToken=tsqlEq then
  2877. GetNextToken;
  2878. Expect(tsqlIntegerNumber);
  2879. Result.Pagesize:=StrtoIntDef(CurrentTokenString,0);
  2880. GetNextToken;
  2881. end;
  2882. If (CurrentToken=tsqlLength) then
  2883. begin
  2884. GetNextToken;
  2885. if (CurrentToken=tsqlEq) then
  2886. GetNextToken;
  2887. Expect(tsqlIntegerNumber);
  2888. Result.Length:=StrtoIntDef(CurrentTokenString,0);
  2889. GetNextToken;
  2890. If CurrentToken in [tsqlPage,tsqlPages] then
  2891. GetNextToken;
  2892. end;
  2893. If (CurrentToken=tsqlDefault) then
  2894. begin
  2895. GetNextToken;
  2896. Consume(tsqlCharacter);
  2897. Consume(tsqlSet);
  2898. Expect(tsqlidentifier);
  2899. Result.CharSet:=CreateIdentifier(Result,CurrentTokenString);
  2900. GetNextToken;
  2901. end;
  2902. While (CurrentToken=tsqlFile) do
  2903. Result.SecondaryFiles.Add(ParseSecondaryFile(Result));
  2904. except
  2905. FreeAndNil(Result);
  2906. Raise
  2907. end;
  2908. end;
  2909. function TSQLParser.ParseCreateShadowStatement(AParent: TSQLElement;
  2910. IsAlter: Boolean): TSQLCreateShadowStatement;
  2911. begin
  2912. // On entry, we're on the SHADOW token.
  2913. if IsAlter then
  2914. UnexpectedToken;
  2915. Consume(tsqlShadow);
  2916. Result:=TSQLCreateShadowStatement(CreateElement(TSQLCreateShadowStatement,AParent));
  2917. try
  2918. Expect(tsqlIntegerNumber);
  2919. Result.Number:=StrToInt(CurrentTokenString);
  2920. GetNextToken;
  2921. If (CurrentToken=tsqlManual) then
  2922. begin
  2923. Result.Manual:=True;
  2924. GetNextToken;
  2925. end
  2926. else If (CurrentToken=tsqlAuto) then
  2927. GetNextToken;
  2928. if (CurrentToken=tsqlConditional) then
  2929. begin
  2930. Result.Conditional:=True;
  2931. GetNextToken;
  2932. end;
  2933. expect(tsqlString);
  2934. Result.FileName:=CurrentTokenString;
  2935. GetNextToken;
  2936. If (CurrentToken=tsqlLength) then
  2937. begin
  2938. GetNextToken;
  2939. if (CurrentToken=tsqlEq) then
  2940. GetNextToken;
  2941. Expect(tsqlIntegerNumber);
  2942. Result.Length:=StrtoIntDef(CurrentTokenString,0);
  2943. GetNextToken;
  2944. If CurrentToken in [tsqlPage,tsqlPages] then
  2945. GetNextToken;
  2946. end;
  2947. While (CurrentToken=tsqlFile) do
  2948. Result.SecondaryFiles.Add(ParseSecondaryFile(Result));
  2949. except
  2950. FreeAndNil(Result);
  2951. Raise;
  2952. end;
  2953. end;
  2954. function TSQLParser.ParseAlterDatabaseStatement(AParent: TSQLElement;
  2955. IsAlter: Boolean): TSQLAlterDatabaseStatement;
  2956. begin
  2957. // On entry, we're on the DATABASE or SCHEMA token.
  2958. Result:=TSQLAlterDatabaseStatement(CreateElement(TSQLAlterDatabaseStatement,APArent));
  2959. try
  2960. Result.UseSchema:=CurrentToken=tsqlSchema;
  2961. GetNextToken;
  2962. expect(tsqlAdd);
  2963. While (CurrentToken in [tsqlAdd,tsqlFile]) do
  2964. begin
  2965. if CurrentToken=tsqlAdd then
  2966. GetNextToken;
  2967. Expect(tsqlFile);
  2968. Result.Operations.Add(ParseSecondaryFile(Result));
  2969. end;
  2970. if Result.Operations.Count=0 then
  2971. UnexpectedToken([tsqlAdd]);
  2972. except
  2973. FreeAndNil(Result);
  2974. Raise;
  2975. end;
  2976. end;
  2977. function TSQLParser.ParseCreateStatement(AParent: TSQLElement; IsAlter: Boolean
  2978. ): TSQLCreateOrAlterStatement;
  2979. begin
  2980. Case GetNextToken of
  2981. tsqlTable : if IsAlter then
  2982. Result:=ParseAlterTableStatement(AParent)
  2983. else
  2984. Result:=ParseCreateTableStatement(AParent);
  2985. tsqlUnique,
  2986. tsqlAscending,
  2987. tsqlDescending,
  2988. tsqlIndex : Result:=ParseCreateIndexStatement(AParent,IsAlter);
  2989. tsqlView : Result:=ParseCreateViewStatement(AParent,IsAlter);
  2990. tsqlProcedure : Result:=ParseCreateProcedureStatement(AParent,IsAlter);
  2991. tsqlDomain : Result:=ParseCreateDomainStatement(AParent,IsAlter);
  2992. tsqlGenerator : Result:=ParseCreateGeneratorStatement(AParent,IsAlter);
  2993. tsqlException : Result:=ParseCreateExceptionStatement(AParent,IsAlter);
  2994. tsqlTrigger : Result:=ParseCreateTriggerStatement(AParent,IsAlter);
  2995. tsqlRole : Result:=ParseCreateRoleStatement(AParent,IsAlter);
  2996. tsqlSchema,
  2997. tsqlDatabase : If IsAlter then
  2998. Result:=ParseAlterDatabaseStatement(AParent,IsAlter)
  2999. else
  3000. Result:=ParseCreateDatabaseStatement(AParent,IsAlter);
  3001. tsqlShadow : Result:=ParseCreateShadowStatement(AParent,IsAlter);
  3002. else
  3003. Error(SErrExpectedDBObject,[CurrentTokenString]);
  3004. end;
  3005. end;
  3006. function TSQLParser.ParseDropStatement(AParent: TSQLElement
  3007. ): TSQLDropStatement;
  3008. Var
  3009. C : TSQLElementClass;
  3010. begin
  3011. // We're positioned on the DROP token.
  3012. C:=Nil;
  3013. Case GetNextToken of
  3014. {
  3015. Filter,
  3016. }
  3017. tsqlExternal : begin
  3018. GetNextToken;
  3019. Expect(tsqlFunction);
  3020. C:=TSQLDropExternalFunctionStatement;
  3021. end;
  3022. tsqlShadow : C:=TSQLDropShadowStatement;
  3023. tsqlRole : C:=TSQLDropRoleStatement;
  3024. tsqlDatabase : C:=TSQLDropDatabaseStatement;
  3025. tsqlException : C:=TSQLDropExceptionStatement;
  3026. tsqlTable : C:=TSQLDropTableStatement;
  3027. tsqlIndex : C:=TSQLDropIndexStatement;
  3028. tsqlView : C:=TSQLDropViewStatement;
  3029. tsqlProcedure : C:=TSQLDropProcedureStatement;
  3030. tsqlDomain : C:=TSQLDropDomainStatement;
  3031. tsqlGenerator : C:=TSQLDropGeneratorStatement;
  3032. tsqlTrigger : C:=TSQLDropTriggerStatement;
  3033. else
  3034. Error(SErrExpectedDBObject,[CurrentTokenString]);
  3035. end;
  3036. GetNextToken;
  3037. If C=TSQLDropShadowStatement then
  3038. Expect(tsqlIntegerNumber)
  3039. else
  3040. Expect(tsqlIdentifier);
  3041. Result:=TSQLDropStatement(CreateElement(C,AParent));
  3042. Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
  3043. GetNextToken; // Comma
  3044. end;
  3045. function TSQLParser.ParseRollbackStatement(AParent: TSQLElement
  3046. ): TSQLRollbackStatement;
  3047. begin
  3048. // On entry, we're on the ROLLBACK statement
  3049. Consume(tsqlRollBack);
  3050. Result:=TSQLRollBackStatement(CreateElement(TSQLRollBackStatement,AParent));
  3051. try
  3052. If (CurrentToken=tsqlTransaction) then
  3053. begin
  3054. GetNextToken;
  3055. expect(tsqlidentifier);
  3056. Result.TransactionName:=CreateIdentifier(Result,CurrentTokenString);
  3057. GetNextToken;
  3058. end;
  3059. Result.Work:=(CurrentToken=tsqlWork);
  3060. if Result.Work then
  3061. GetNextToken;
  3062. Result.Release:=(CurrentToken=tsqlRelease);
  3063. if Result.Release then
  3064. GetNextToken;
  3065. except
  3066. FreeAndNil(Result);
  3067. Raise;
  3068. end;
  3069. end;
  3070. function TSQLParser.ParseCommitStatement(AParent: TSQLElement
  3071. ): TSQLCommitStatement;
  3072. begin
  3073. Consume(tsqlCommit);
  3074. Result:=TSQLCommitStatement(CreateElement(TSQLCommitStatement,AParent));
  3075. try
  3076. Result.Work:=(CurrentToken=tsqlWork);
  3077. if Result.Work then
  3078. GetNextToken;
  3079. If (CurrentToken=tsqlTransaction) then
  3080. begin
  3081. GetNextToken;
  3082. expect(tsqlidentifier);
  3083. Result.TransactionName:=CreateIdentifier(Result,CurrentTokenString);
  3084. GetNextToken;
  3085. end;
  3086. Result.Release:=(CurrentToken=tsqlRelease);
  3087. if Result.Release then
  3088. GetNextToken;
  3089. Result.Retain:=(CurrentToken=tsqlRetain);
  3090. if Result.Retain then
  3091. begin
  3092. GetNextToken;
  3093. If CurrentToken=tsqlSnapshot then
  3094. GetNextToken;
  3095. end;
  3096. except
  3097. FreeAndNil(Result);
  3098. Raise;
  3099. end;
  3100. end;
  3101. function TSQLParser.ParseExecuteProcedureStatement(AParent: TSQLElement): TSQLExecuteProcedureStatement;
  3102. Var
  3103. NeedClose,
  3104. Done : Boolean;
  3105. TN : TSQLStringType;
  3106. begin
  3107. Result:=Nil;
  3108. // On Entry, we're on the EXECUTE statement
  3109. Consume(tsqlExecute);
  3110. Consume(tsqlProcedure);
  3111. If (CurrentToken=tsqlTransaction) then
  3112. begin
  3113. GetNextToken;
  3114. Expect(TSQLIdentifier);
  3115. TN:=CurrentTokenString;
  3116. GetNextToken;
  3117. end;
  3118. Expect(tsqlIdentifier);
  3119. Result:=TSQLExecuteProcedureStatement(CreateELement(TSQLExecuteProcedureStatement,AParent));
  3120. try
  3121. Result.ProcedureName:=CreateIdentifier(Result,CurrentTokenString);
  3122. if (TN<>'') then
  3123. Result.TransactionName:=CreateIdentifier(Result,TN);
  3124. GetNextToken;
  3125. // ( is optional. It CAN be part of a (SELECT, and then it is NOT part of the brackets around the params.
  3126. NeedClose:=(CurrentToken=tsqlBraceOpen) and (PeekNextToken<>tsqlSelect);
  3127. If NeedClose then
  3128. GetNextToken;
  3129. Done:=False;
  3130. If Not (CurrentToken in [tsqlSemicolon,tsqlEOF,tsqlReturningValues]) then
  3131. Repeat
  3132. Result.Params.Add(ParseExprLevel1(Result,[eoFieldValue]));
  3133. If CurrentToken=tsqlComma then
  3134. GetNextToken
  3135. else if (CurrentToken=tsqlBraceClose) then
  3136. begin
  3137. if Not NeedClose then
  3138. UnexpectedToken;
  3139. Done:=True;
  3140. GetNextToken;
  3141. end
  3142. else
  3143. begin
  3144. If NeedClose then
  3145. UnexpectedToken([tsqlBraceClose]);
  3146. Expect([tsqlEOF,tsqlSemicolon,tsqlReturningValues]);
  3147. Done:=True;
  3148. end;
  3149. until Done;
  3150. if (CurrentToken=tsqlReturningValues) then
  3151. begin
  3152. GetNextToken;
  3153. NeedClose:=(CurrentToken=tsqlBraceOpen);
  3154. If NeedClose then
  3155. Consume(tsqlBraceOpen);
  3156. Repeat
  3157. if CurrentToken=tsqlComma then
  3158. GetNextToken;
  3159. if CurrentToken=tsqlColon then
  3160. GetNextToken;
  3161. Expect(tsqlIdentifier);
  3162. Result.Returning.Add(CreateIdentifier(Result,CurrentTokenString));
  3163. GetNextToken;
  3164. until (CurrentToken<>tsqlComma);
  3165. If NeedClose then
  3166. Consume(tsqlBraceClose);
  3167. end;
  3168. except
  3169. FreeAndNil(Result);
  3170. Raise;
  3171. end;
  3172. end;
  3173. function TSQLParser.ParseSetStatement(AParent: TSQLElement): TSQLStatement;
  3174. begin
  3175. // On Entry, we're on the SET statement
  3176. Consume(tsqlSet);
  3177. Case CurrentToken of
  3178. tsqlGenerator : Result:=ParseSetGeneratorStatement(AParent);
  3179. tsqlTerm : Result:=ParseSetTermStatement(AParent);
  3180. else
  3181. // For the time being
  3182. UnexpectedToken;
  3183. end;
  3184. end;
  3185. function TSQLParser.ParseConnectStatement(AParent: TSQLElement
  3186. ): TSQLConnectStatement;
  3187. begin
  3188. // On entry, we're on CONNECT
  3189. consume(tsqlConnect);
  3190. Expect(tsqlString);
  3191. Result:=TSQLConnectStatement(CreateElement(TSQLConnectStatement,AParent));
  3192. try
  3193. Result.DatabaseName:=CurrentTokenString;
  3194. GetNextToken;
  3195. If CurrentToken=tsqlUSER then
  3196. begin
  3197. GetNextToken;
  3198. Expect(tsqlString);
  3199. Result.UserName:=CurrentTokenString;
  3200. GetNextToken;
  3201. end;
  3202. If CurrentToken=tsqlPassword then
  3203. begin
  3204. GetNextToken;
  3205. Expect(tsqlString);
  3206. Result.Password:=CurrentTokenString;
  3207. GetNextToken;
  3208. end;
  3209. If CurrentToken=tsqlRole then
  3210. begin
  3211. GetNextToken;
  3212. Expect(tsqlString);
  3213. Result.Role:=CurrentTokenString;
  3214. GetNextToken;
  3215. end;
  3216. If CurrentToken=tsqlCache then
  3217. begin
  3218. GetNextToken;
  3219. Expect(tsqlIntegerNumber);
  3220. Result.Cache:=StrtoIntDef(CurrentTokenString,0);
  3221. GetNextToken;
  3222. end;
  3223. except
  3224. FreeAndNil(Result);
  3225. Raise;
  3226. end;
  3227. end;
  3228. constructor TSQLParser.Create(AInput: TStream);
  3229. begin
  3230. FInput:=AInput;
  3231. FCurrent:=TSQLUnknown;
  3232. FScanner:=TSQLScanner.Create(FInput);
  3233. FFreeScanner:=True;
  3234. end;
  3235. constructor TSQLParser.Create(AScanner: TSQLScanner);
  3236. begin
  3237. FCurrent:=TSQLUnknown;
  3238. FScanner:=AScanner;
  3239. FFreeScanner:=False;
  3240. end;
  3241. destructor TSQLParser.Destroy;
  3242. begin
  3243. If FFreeScanner then
  3244. FreeAndNil(FScanner);
  3245. inherited Destroy;
  3246. end;
  3247. function TSQLParser.ParseDeclareFunctionStatement(AParent: TSQLElement
  3248. ): TSQLDeclareExternalFunctionStatement;
  3249. begin
  3250. // On entry, we're on the EXTERNAL token
  3251. Consume(tsqlExternal);
  3252. Consume(tsqlFunction);
  3253. Expect(tsqlidentifier);
  3254. Result:=TSQLDeclareExternalFunctionStatement(CreateElement(TSQLDeclareExternalFunctionStatement,AParent));
  3255. try
  3256. Result.ObjectName:=CreateIdentifier(Result,CurrentTokenString);
  3257. If (PeekNextToken=tsqlReturns) then
  3258. GetNextToken
  3259. else
  3260. Repeat
  3261. Result.Arguments.Add(Self.ParseTypeDefinition(Result,[ptfExternalFunction]));
  3262. Until (CurrentToken<>tsqlComma);
  3263. Expect(tsqlReturns);
  3264. Result.ReturnType:=ParseTypeDefinition(Result,[ptfExternalFunctionResult]);
  3265. Result.FreeIt:=(CurrentToken=tsqlFreeIt);
  3266. If Result.FreeIt then
  3267. GetNextToken;
  3268. Consume(tsqlEntryPoint);
  3269. Expect(tsqlString);
  3270. Result.EntryPoint:=CurrentTokenString;
  3271. GetNextToken;
  3272. Consume(tsqlModuleName);
  3273. Expect(tsqlString);
  3274. Result.ModuleName:=CurrentTokenstring;
  3275. GetNextToken;
  3276. except
  3277. FreeAndNil(Result);
  3278. Raise;
  3279. end;
  3280. end;
  3281. function TSQLParser.ParseDeclareStatement(AParent: TSQLElement): TSQLStatement;
  3282. begin
  3283. // On entry, we're on the DECLARE statement
  3284. Consume(tsqlDeclare);
  3285. // For the moment, only 'DECLARE EXTERNAL FUNCTION' is supported
  3286. Case CurrentToken of
  3287. tsqlExternal : Result:=ParseDeclareFunctionStatement(AParent);
  3288. else
  3289. UnexpectedToken([tsqlExternal]);
  3290. end;
  3291. end;
  3292. procedure TSQLParser.ParseGranteeList(AParent: TSQLElement;
  3293. List: TSQLElementList; AllowObject, AllowGroup, AllowPublic: Boolean; IsRevoke: Boolean = False);
  3294. Type
  3295. TSQLGranteeClass = Class of TSQLGrantee;
  3296. Function CreateGrantee(NextIdentifier : Boolean; AClass : TSQLGranteeClass) : TSQLGrantee;
  3297. begin
  3298. if NextIdentifier then
  3299. begin
  3300. GetNextToken;
  3301. Expect(tsqlIdentifier);
  3302. end;
  3303. Result:=TSQLGrantee(CreateElement(AClass,AParent));
  3304. Result.Name:=CurrentTokenString;
  3305. List.Add(Result);
  3306. end;
  3307. Var
  3308. E : TSQLTokens;
  3309. begin
  3310. if IsRevoke then
  3311. Consume(tsqlFrom)
  3312. else
  3313. Consume(tsqlTo);
  3314. E:=[tsqlIdentifier,tsqlUser];
  3315. If AllowObject then
  3316. E:=E+[tsqlProcedure,tsqlView,tsqlTrigger,tsqlPublic]
  3317. else If AllowPublic then
  3318. E:=E+[tsqlPublic];
  3319. If AllowGroup then
  3320. E:=E+[tsqlGROUP];
  3321. Expect(E);
  3322. Repeat
  3323. If CurrentToken=tsqlComma then
  3324. GetNextToken;
  3325. Case CurrentToken of
  3326. tsqlUser,
  3327. tsqlIdentifier :
  3328. CreateGrantee(CurrentToken=tsqlUser,TSQLUserGrantee);
  3329. TsqlGroup :
  3330. begin
  3331. If Not AllowGroup then
  3332. UnexpectedToken;
  3333. CreateGrantee(true,TSQLGroupGrantee);
  3334. end;
  3335. TsqlPublic :
  3336. begin
  3337. If Not (AllowPublic or AllowObject) then
  3338. UnexpectedToken;
  3339. CreateGrantee(False,TSQLPublicGrantee);
  3340. end;
  3341. TsqlTrigger:
  3342. begin
  3343. If Not AllowObject then
  3344. UnexpectedToken;
  3345. CreateGrantee(True,TSQLTriggerGrantee);
  3346. end;
  3347. TsqlView:
  3348. begin
  3349. If Not AllowObject then
  3350. UnexpectedToken;
  3351. CreateGrantee(true,TSQLViewGrantee);
  3352. end;
  3353. TsqlProcedure:
  3354. begin
  3355. If Not AllowObject then
  3356. UnexpectedToken;
  3357. CreateGrantee(true,TSQLProcedureGrantee);
  3358. end;
  3359. end;
  3360. Until (GetNextToken<>tsqlComma);
  3361. end;
  3362. function TSQLParser.ParseGrantTableStatement(AParent: TSQLElement): TSQLTableGrantStatement;
  3363. Var
  3364. C : TSQLColumnPrivilege;
  3365. P : TSQLPrivilege;
  3366. begin
  3367. Result:=TSQLTableGrantStatement(CreateElement(TSQLTableGrantStatement,APArent));
  3368. try
  3369. // On entry, we're on the first ALL/SELECT/UPDATE/INSERT/DELETE/REFERENCE etc. token.
  3370. if CurrentToken=tsqlAll then
  3371. begin
  3372. Result.Privileges.Add(CreateElement(TSQLAllPrivilege,Result));
  3373. If GetNextToken=tsqlPrivileges then
  3374. GetNextToken;
  3375. end
  3376. else
  3377. Repeat
  3378. P:=Nil;
  3379. C:=Nil;
  3380. if CurrentToken=tsqlComma then
  3381. GetNextToken;
  3382. Case CurrentToken of
  3383. tsqlSelect : P:=TSQLSelectPrivilege(CreateElement(TSQLSelectPrivilege,Result));
  3384. tsqlInsert : P:=TSQLInsertPrivilege(CreateElement(TSQLInsertPrivilege,Result));
  3385. tsqlDelete : P:=TSQLDeletePrivilege(CreateElement(TSQLDeletePrivilege,Result));
  3386. tsqlUpdate,
  3387. tsqlReferences :
  3388. begin
  3389. if CurrentToken=tsqlUpdate then
  3390. C:=TSQLUpdatePrivilege(CreateElement(TSQLUpdatePrivilege,AParent))
  3391. else
  3392. C:=TSQLReferencePrivilege(CreateElement(TSQLReferencePrivilege,AParent));
  3393. P:=C;
  3394. GetNextToken;
  3395. If (CurrentToken=tsqlBraceOpen) then
  3396. begin
  3397. GetNextToken;
  3398. C.Columns:=TSQLElementList.Create(True);
  3399. ParseIdentifierList(C,C.Columns);
  3400. end;
  3401. end;
  3402. else
  3403. UnexpectedToken([tsqlselect,tsqlInsert,tsqlDelete,tsqlUpdate,tsqlReferences]);
  3404. end;
  3405. Result.Privileges.Add(P);
  3406. If C=Nil then
  3407. GetNextToken;
  3408. Until (CurrentToken<>tsqlComma);
  3409. Consume(tsqlOn);
  3410. Expect(tsqlidentifier);
  3411. Result.TableName:=CreateIdentifier(Result,CurrentTokenString);
  3412. GetNextToken;
  3413. ParseGranteeList(Result,Result.Grantees,True,True,True);
  3414. If (CurrentToken=tsqlWith) then
  3415. begin
  3416. Consume(tsqlWith);
  3417. Consume(tsqlGrant);
  3418. Consume(tsqlOption);
  3419. Result.GrantOption:=True;
  3420. end;
  3421. except
  3422. FreeAndNil(Result);
  3423. Raise;
  3424. end;
  3425. end;
  3426. function TSQLParser.ParseRevokeExecuteStatement(AParent: TSQLElement
  3427. ): TSQLProcedureRevokeStatement;
  3428. BEGIN
  3429. // On entry, we're on the EXECUTE token
  3430. Consume(tsqlExecute);
  3431. Consume(tsqlOn);
  3432. Consume(tsqlProcedure);
  3433. Expect(tsqlIdentifier);
  3434. Result:=TSQLProcedureRevokeStatement(CreateElement(TSQLProcedureRevokeStatement,AParent));
  3435. try
  3436. Result.ProcedureName:=CreateIdentifier(Result,CurrentTokenString);
  3437. GetNextToken;
  3438. ParseGranteeList(Result,Result.Grantees,True,False,True,True);
  3439. If (CurrentToken=tsqlWith) then
  3440. begin
  3441. Consume(tsqlWith);
  3442. Consume(tsqlGrant);
  3443. Consume(tsqlOption);
  3444. Result.GrantOption:=True;
  3445. end;
  3446. except
  3447. FreeAndNil(Result);
  3448. Raise;
  3449. end;
  3450. end;
  3451. function TSQLParser.ParseRevokeRoleStatement(AParent: TSQLElement
  3452. ): TSQLRoleRevokeStatement;
  3453. begin
  3454. Result:=Nil;
  3455. // On entry, we're on the identifier token
  3456. expect(tsqlIdentifier);
  3457. Result:=TSQLRoleRevokeStatement(CreateElement(TSQLRoleRevokeStatement,AParent));
  3458. try
  3459. Repeat
  3460. if CurrentToken=tsqlComma then
  3461. GetNextToken;
  3462. expect(tsqlIdentifier);
  3463. Result.Roles.Add(CreateIDentifier(Aparent,CurrentTokenString));
  3464. Until (GetNextToken<>tsqlComma);
  3465. Expect(tsqlFrom);
  3466. ParseGranteeList(Result,Result.Grantees,False,False,True,True);
  3467. except
  3468. FreeAndNil(Result);
  3469. Raise;
  3470. end;
  3471. end;
  3472. function TSQLParser.ParseRevokeTableStatement(AParent: TSQLElement
  3473. ): TSQLTableRevokeStatement;
  3474. Var
  3475. C : TSQLColumnPrivilege;
  3476. P : TSQLPrivilege;
  3477. begin
  3478. Result:=TSQLTableRevokeStatement(CreateElement(TSQLTableRevokeStatement,APArent));
  3479. try
  3480. // On entry, we're on the first GRANT,ALL/SELECT/UPDATE/INSERT/DELETE/REFERENCE etc. token.
  3481. If (CurrentToken=tsqlGrant) then
  3482. begin
  3483. Consume(tsqlGrant);
  3484. Consume(tsqlOption);
  3485. Consume(tsqlFor);
  3486. Result.GrantOption:=True;
  3487. end;
  3488. if CurrentToken=tsqlAll then
  3489. begin
  3490. Result.Privileges.Add(CreateElement(TSQLAllPrivilege,Result));
  3491. If GetNextToken=tsqlPrivileges then
  3492. GetNextToken;
  3493. end
  3494. else
  3495. Repeat
  3496. P:=Nil;
  3497. C:=Nil;
  3498. if CurrentToken=tsqlComma then
  3499. GetNextToken;
  3500. Case CurrentToken of
  3501. tsqlSelect : P:=TSQLSelectPrivilege(CreateElement(TSQLSelectPrivilege,Result));
  3502. tsqlInsert : P:=TSQLInsertPrivilege(CreateElement(TSQLInsertPrivilege,Result));
  3503. tsqlDelete : P:=TSQLDeletePrivilege(CreateElement(TSQLDeletePrivilege,Result));
  3504. tsqlUpdate,
  3505. tsqlReferences :
  3506. begin
  3507. if CurrentToken=tsqlUpdate then
  3508. C:=TSQLUpdatePrivilege(CreateElement(TSQLUpdatePrivilege,AParent))
  3509. else
  3510. C:=TSQLReferencePrivilege(CreateElement(TSQLReferencePrivilege,AParent));
  3511. P:=C;
  3512. GetNextToken;
  3513. If (CurrentToken=tsqlBraceOpen) then
  3514. begin
  3515. GetNextToken;
  3516. C.Columns:=TSQLElementList.Create(True);
  3517. ParseIdentifierList(C,C.Columns);
  3518. end;
  3519. end;
  3520. else
  3521. UnexpectedToken([tsqlselect,tsqlInsert,tsqlDelete,tsqlUpdate,tsqlReferences]);
  3522. end;
  3523. Result.Privileges.Add(P);
  3524. If C=Nil then
  3525. GetNextToken;
  3526. Until (CurrentToken<>tsqlComma);
  3527. Consume(tsqlOn);
  3528. Expect(tsqlidentifier);
  3529. Result.TableName:=CreateIdentifier(Result,CurrentTokenString);
  3530. GetNextToken;
  3531. ParseGranteeList(Result,Result.Grantees,True,True,True,True);
  3532. except
  3533. FreeAndNil(Result);
  3534. Raise;
  3535. end;
  3536. end;
  3537. function TSQLParser.ParseGrantExecuteStatement(AParent: TSQLElement): TSQLProcedureGrantStatement;
  3538. begin
  3539. // On entry, we're on the EXECUTE token
  3540. Consume(tsqlExecute);
  3541. Consume(tsqlOn);
  3542. Consume(tsqlProcedure);
  3543. Expect(tsqlIdentifier);
  3544. Result:=TSQLProcedureGrantStatement(CreateElement(TSQLProcedureGrantStatement,AParent));
  3545. try
  3546. Result.ProcedureName:=CreateIdentifier(Result,CurrentTokenString);
  3547. GetNextToken;
  3548. ParseGranteeList(Result,Result.Grantees,True,False,True);
  3549. If (CurrentToken=tsqlWith) then
  3550. begin
  3551. Consume(tsqlWith);
  3552. Consume(tsqlGrant);
  3553. Consume(tsqlOption);
  3554. Result.GrantOption:=True;
  3555. end;
  3556. except
  3557. FreeAndNil(Result);
  3558. Raise;
  3559. end;
  3560. end;
  3561. function TSQLParser.ParseGrantRoleStatement(AParent: TSQLElement): TSQLRoleGrantStatement;
  3562. begin
  3563. Result:=Nil;
  3564. // On entry, we're on the identifier token
  3565. expect(tsqlIdentifier);
  3566. Result:=TSQLRoleGrantStatement(CreateElement(TSQLRoleGrantStatement,AParent));
  3567. try
  3568. Repeat
  3569. if CurrentToken=tsqlComma then
  3570. GetNextToken;
  3571. expect(tsqlIdentifier);
  3572. Result.Roles.Add(CreateIDentifier(Aparent,CurrentTokenString));
  3573. Until (GetNextToken<>tsqlComma);
  3574. Expect(tsqlTo);
  3575. ParseGranteeList(Result,Result.Grantees,False,False,True);
  3576. If (CurrentToken=tsqlWith) then
  3577. begin
  3578. Consume(tsqlWith);
  3579. Consume(tsqlAdmin);
  3580. Consume(tsqlOption);
  3581. Result.AdminOption:=True;
  3582. end;
  3583. except
  3584. FreeAndNil(Result);
  3585. Raise;
  3586. end;
  3587. end;
  3588. function TSQLParser.ParseGrantStatement(AParent: TSQLElement): TSQLGrantStatement;
  3589. begin
  3590. // On entry, we're on the GRANT token
  3591. Result:=Nil;
  3592. try
  3593. Consume(tsqlGrant);
  3594. Case CurrentToken of
  3595. tsqlExecute: Result:=ParseGrantExecutestatement(AParent);
  3596. tsqlAll,
  3597. tsqlUpdate,
  3598. tsqlReferences,
  3599. tsqlInsert,
  3600. tsqldelete,
  3601. tsqlSelect : Result:=ParseGrantTablestatement(AParent);
  3602. tsqlIdentifier : Result:=ParseGrantRolestatement(AParent);
  3603. else
  3604. UnExpectedToken([tsqlIdentifier, tsqlExecute, tsqlall,
  3605. tsqlUpdate, tsqldelete, tsqlReferences, tsqlInsert, tsqlSelect]);
  3606. end;
  3607. except
  3608. FreeAndNil(Result);
  3609. Raise;
  3610. end;
  3611. end;
  3612. function TSQLParser.ParseRevokeStatement(AParent: TSQLElement
  3613. ): TSQLGrantStatement;
  3614. begin
  3615. // On entry, we're on the GRANT token
  3616. Result:=Nil;
  3617. try
  3618. Consume(tsqlRevoke);
  3619. Case CurrentToken of
  3620. tsqlExecute: Result:=ParseRevokeExecutestatement(AParent);
  3621. tsqlGrant,
  3622. tsqlAll,
  3623. tsqlUpdate,
  3624. tsqlReferences,
  3625. tsqlInsert,
  3626. tsqldelete,
  3627. tsqlSelect : Result:=ParseRevokeTablestatement(AParent);
  3628. tsqlIdentifier : Result:=ParseRevokeRolestatement(AParent);
  3629. else
  3630. UnExpectedToken([tsqlIdentifier, tsqlExecute,tsqlgrant,tsqlall,
  3631. tsqlUpdate, tsqldelete, tsqlReferences, tsqlInsert, tsqlSelect]);
  3632. end;
  3633. except
  3634. FreeAndNil(Result);
  3635. Raise;
  3636. end;
  3637. end;
  3638. function TSQLParser.Parse: TSQLElement;
  3639. begin
  3640. if CurrentToken=tsqlEOF then begin
  3641. Result:=nil;
  3642. Exit;
  3643. end;
  3644. GetNextToken;
  3645. Case CurrentToken of
  3646. tsqlSelect : Result:=ParseSelectStatement(Nil,[]);
  3647. tsqlUpdate : Result:=ParseUpdateStatement(Nil);
  3648. tsqlInsert : Result:=ParseInsertStatement(Nil);
  3649. tsqlDelete : Result:=ParseDeleteStatement(Nil);
  3650. tsqlCreate,
  3651. tsqlAlter : Result:=ParseCreateStatement(Nil,(tsqlAlter=CurrentToken));
  3652. tsqlDrop : Result:=ParseDropStatement(Nil);
  3653. tsqlSet : Result:=ParseSetStatement(Nil);
  3654. tsqlRollback : Result:=ParseRollBackStatement(Nil);
  3655. tsqlCommit : Result:=ParseCommitStatement(Nil);
  3656. tsqlExecute : Result:=ParseExecuteProcedureStatement(Nil);
  3657. tsqlConnect : Result:=ParseConnectStatement(Nil);
  3658. tsqlDeclare : Result:=ParseDeclareStatement(Nil);
  3659. tsqlGrant : Result:=ParseGrantStatement(Nil);
  3660. tsqlRevoke : Result:=ParseRevokeStatement(Nil);
  3661. tsqlEOF : Result:=nil;
  3662. else
  3663. UnexpectedToken;
  3664. end;
  3665. if Not (CurrentToken in [tsqlEOF,tsqlSemicolon,tsqlStatementTerminator]) then
  3666. begin
  3667. FreeAndNil(Result);
  3668. if (CurrentToken=tsqlBraceClose) then
  3669. Error(SerrUnmatchedBrace);
  3670. Error(SErrUnexpectedToken,[CurrentTokenString]);
  3671. end;
  3672. end;
  3673. function TSQLParser.ParseScript(AllowPartial : Boolean = False): TSQLElementList;
  3674. var
  3675. E : TSQLElement;
  3676. begin
  3677. Result:=TSQLElementList.Create(True);
  3678. try
  3679. E:=Parse;
  3680. While (E<>Nil) do
  3681. begin
  3682. Result.Add(E);
  3683. E:=Parse;
  3684. end;
  3685. except
  3686. If Not AllowPartial then
  3687. begin
  3688. FreeAndNil(Result);
  3689. Raise;
  3690. end;
  3691. end;
  3692. end;
  3693. function TSQLParser.GetStatementTerminator: string;
  3694. begin
  3695. result:=TokenInfos[tsqlStatementTerminator];
  3696. end;
  3697. procedure TSQLParser.SetStatementTerminator(AValue: string);
  3698. begin
  3699. TokenInfos[tsqlStatementTerminator]:=AValue;;
  3700. end;
  3701. function TSQLParser.CurrentToken: TSQLToken;
  3702. begin
  3703. Result:=FCurrent;
  3704. end;
  3705. function TSQLParser.CurrentTokenString: String;
  3706. begin
  3707. Result:=FCurrentString;
  3708. end;
  3709. function TSQLParser.GetNextToken: TSQLToken;
  3710. begin
  3711. FPrevious:=FCurrent;
  3712. // Set if not already peeked; otherwise fetch and look
  3713. If (FPeekToken<>tsqlUnknown) then
  3714. begin
  3715. FCurrent:=FPeekToken;
  3716. FCurrentString:=FPeekTokenString;
  3717. FPeekToken:=tsqlUnknown;
  3718. FPeekTokenString:='';
  3719. end
  3720. else
  3721. begin
  3722. FCurrent:=FScanner.FetchToken;
  3723. FCurrentString:=FScanner.CurTokenString;
  3724. end;
  3725. Result:=FCurrent;
  3726. {$ifdef debugparser}Writeln('GetNextToken : ',GetEnumName(TypeInfo(TSQLToken),Ord(FCurrent)), ' As string: ',FCurrentString);{$endif debugparser}
  3727. end;
  3728. function TSQLParser.PeekNextToken: TSQLToken;
  3729. begin
  3730. If (FPeekToken=tsqlUnknown) then
  3731. begin
  3732. FPeekToken:=FScanner.FetchToken;
  3733. FPeekTokenString:=FScanner.CurTokenString;
  3734. end;
  3735. {$ifdef debugparser}Writeln('PeekNextToken : ',GetEnumName(TypeInfo(TSQLToken),Ord(FPeekToken)), ' As string: ',FPeekTokenString);{$endif debugparser}
  3736. Result:=FPeekToken;
  3737. end;
  3738. function TSQLParser.PreviousToken: TSQLToken;
  3739. begin
  3740. Result:=FPRevious;
  3741. end;
  3742. function TSQLParser.IsEndOfLine: Boolean;
  3743. begin
  3744. Result:=FScanner.IsEndOfLine;
  3745. end;
  3746. end.