fpsqlparser.pas 120 KB

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