fpsqlparser.pas 124 KB

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