fpsqlparser.pas 122 KB

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