fpsqlparser.pas 121 KB

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