fpsqlparser.pas 121 KB

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