fpsqlparser.pas 122 KB

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