fpsqlparser.pas 122 KB

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