parsesql.nim 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2009 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## The `parsesql` module implements a high performance SQL file
  10. ## parser. It parses PostgreSQL syntax and the SQL ANSI standard.
  11. ##
  12. ## Unstable API.
  13. import strutils, lexbase
  14. import std/private/decode_helpers
  15. # ------------------- scanner -------------------------------------------------
  16. type
  17. TokKind = enum ## enumeration of all SQL tokens
  18. tkInvalid, ## invalid token
  19. tkEof, ## end of file reached
  20. tkIdentifier, ## abc
  21. tkQuotedIdentifier, ## "abc"
  22. tkStringConstant, ## 'abc'
  23. tkEscapeConstant, ## e'abc'
  24. tkDollarQuotedConstant, ## $tag$abc$tag$
  25. tkBitStringConstant, ## B'00011'
  26. tkHexStringConstant, ## x'00011'
  27. tkInteger,
  28. tkNumeric,
  29. tkOperator, ## + - * / < > = ~ ! @ # % ^ & | ` ?
  30. tkSemicolon, ## ';'
  31. tkColon, ## ':'
  32. tkComma, ## ','
  33. tkParLe, ## '('
  34. tkParRi, ## ')'
  35. tkBracketLe, ## '['
  36. tkBracketRi, ## ']'
  37. tkDot ## '.'
  38. Token = object # a token
  39. kind: TokKind # the type of the token
  40. literal: string # the parsed (string) literal
  41. SqlLexer* = object of BaseLexer ## the parser object.
  42. filename: string
  43. const
  44. tokKindToStr: array[TokKind, string] = [
  45. "invalid", "[EOF]", "identifier", "quoted identifier", "string constant",
  46. "escape string constant", "dollar quoted constant", "bit string constant",
  47. "hex string constant", "integer constant", "numeric constant", "operator",
  48. ";", ":", ",", "(", ")", "[", "]", "."
  49. ]
  50. reservedKeywords = @[
  51. # statements
  52. "select", "from", "where", "group", "limit", "having",
  53. # functions
  54. "count",
  55. ]
  56. proc close(L: var SqlLexer) =
  57. lexbase.close(L)
  58. proc getColumn(L: SqlLexer): int =
  59. ## get the current column the parser has arrived at.
  60. result = getColNumber(L, L.bufpos)
  61. proc getLine(L: SqlLexer): int =
  62. result = L.lineNumber
  63. proc handleOctChar(c: var SqlLexer, xi: var int) =
  64. if c.buf[c.bufpos] in {'0'..'7'}:
  65. xi = (xi shl 3) or (ord(c.buf[c.bufpos]) - ord('0'))
  66. inc(c.bufpos)
  67. proc getEscapedChar(c: var SqlLexer, tok: var Token) =
  68. inc(c.bufpos)
  69. case c.buf[c.bufpos]
  70. of 'n', 'N':
  71. add(tok.literal, '\L')
  72. inc(c.bufpos)
  73. of 'r', 'R', 'c', 'C':
  74. add(tok.literal, '\c')
  75. inc(c.bufpos)
  76. of 'l', 'L':
  77. add(tok.literal, '\L')
  78. inc(c.bufpos)
  79. of 'f', 'F':
  80. add(tok.literal, '\f')
  81. inc(c.bufpos)
  82. of 'e', 'E':
  83. add(tok.literal, '\e')
  84. inc(c.bufpos)
  85. of 'a', 'A':
  86. add(tok.literal, '\a')
  87. inc(c.bufpos)
  88. of 'b', 'B':
  89. add(tok.literal, '\b')
  90. inc(c.bufpos)
  91. of 'v', 'V':
  92. add(tok.literal, '\v')
  93. inc(c.bufpos)
  94. of 't', 'T':
  95. add(tok.literal, '\t')
  96. inc(c.bufpos)
  97. of '\'', '\"':
  98. add(tok.literal, c.buf[c.bufpos])
  99. inc(c.bufpos)
  100. of '\\':
  101. add(tok.literal, '\\')
  102. inc(c.bufpos)
  103. of 'x', 'X':
  104. inc(c.bufpos)
  105. var xi = 0
  106. if handleHexChar(c.buf[c.bufpos], xi):
  107. inc(c.bufpos)
  108. if handleHexChar(c.buf[c.bufpos], xi):
  109. inc(c.bufpos)
  110. add(tok.literal, chr(xi))
  111. of '0'..'7':
  112. var xi = 0
  113. handleOctChar(c, xi)
  114. handleOctChar(c, xi)
  115. handleOctChar(c, xi)
  116. if (xi <= 255): add(tok.literal, chr(xi))
  117. else: tok.kind = tkInvalid
  118. else: tok.kind = tkInvalid
  119. proc handleCRLF(c: var SqlLexer, pos: int): int =
  120. case c.buf[pos]
  121. of '\c': result = lexbase.handleCR(c, pos)
  122. of '\L': result = lexbase.handleLF(c, pos)
  123. else: result = pos
  124. proc skip(c: var SqlLexer) =
  125. var pos = c.bufpos
  126. var nested = 0
  127. while true:
  128. case c.buf[pos]
  129. of ' ', '\t':
  130. inc(pos)
  131. of '-':
  132. if c.buf[pos+1] == '-':
  133. while not (c.buf[pos] in {'\c', '\L', lexbase.EndOfFile}): inc(pos)
  134. else:
  135. break
  136. of '/':
  137. if c.buf[pos+1] == '*':
  138. inc(pos, 2)
  139. while true:
  140. case c.buf[pos]
  141. of '\0': break
  142. of '\c', '\L':
  143. pos = handleCRLF(c, pos)
  144. of '*':
  145. if c.buf[pos+1] == '/':
  146. inc(pos, 2)
  147. if nested <= 0: break
  148. dec(nested)
  149. else:
  150. inc(pos)
  151. of '/':
  152. if c.buf[pos+1] == '*':
  153. inc(pos, 2)
  154. inc(nested)
  155. else:
  156. inc(pos)
  157. else: inc(pos)
  158. else: break
  159. of '\c', '\L':
  160. pos = handleCRLF(c, pos)
  161. else:
  162. break # EndOfFile also leaves the loop
  163. c.bufpos = pos
  164. proc getString(c: var SqlLexer, tok: var Token, kind: TokKind) =
  165. var pos = c.bufpos + 1
  166. tok.kind = kind
  167. block parseLoop:
  168. while true:
  169. while true:
  170. var ch = c.buf[pos]
  171. if ch == '\'':
  172. if c.buf[pos+1] == '\'':
  173. inc(pos, 2)
  174. add(tok.literal, '\'')
  175. else:
  176. inc(pos)
  177. break
  178. elif ch in {'\c', '\L', lexbase.EndOfFile}:
  179. tok.kind = tkInvalid
  180. break parseLoop
  181. elif (ch == '\\') and kind == tkEscapeConstant:
  182. c.bufpos = pos
  183. getEscapedChar(c, tok)
  184. pos = c.bufpos
  185. else:
  186. add(tok.literal, ch)
  187. inc(pos)
  188. c.bufpos = pos
  189. var line = c.lineNumber
  190. skip(c)
  191. if c.lineNumber > line:
  192. # a new line whitespace has been parsed, so we check if the string
  193. # continues after the whitespace:
  194. pos = c.bufpos
  195. if c.buf[pos] == '\'': inc(pos)
  196. else: break parseLoop
  197. else: break parseLoop
  198. c.bufpos = pos
  199. proc getDollarString(c: var SqlLexer, tok: var Token) =
  200. var pos = c.bufpos + 1
  201. tok.kind = tkDollarQuotedConstant
  202. var tag = "$"
  203. while c.buf[pos] in IdentChars:
  204. add(tag, c.buf[pos])
  205. inc(pos)
  206. if c.buf[pos] == '$': inc(pos)
  207. else:
  208. tok.kind = tkInvalid
  209. return
  210. while true:
  211. case c.buf[pos]
  212. of '\c', '\L':
  213. pos = handleCRLF(c, pos)
  214. add(tok.literal, "\L")
  215. of '\0':
  216. tok.kind = tkInvalid
  217. break
  218. of '$':
  219. inc(pos)
  220. var tag2 = "$"
  221. while c.buf[pos] in IdentChars:
  222. add(tag2, c.buf[pos])
  223. inc(pos)
  224. if c.buf[pos] == '$': inc(pos)
  225. if tag2 == tag: break
  226. add(tok.literal, tag2)
  227. add(tok.literal, '$')
  228. else:
  229. add(tok.literal, c.buf[pos])
  230. inc(pos)
  231. c.bufpos = pos
  232. proc getSymbol(c: var SqlLexer, tok: var Token) =
  233. var pos = c.bufpos
  234. while true:
  235. add(tok.literal, c.buf[pos])
  236. inc(pos)
  237. if c.buf[pos] notin {'a'..'z', 'A'..'Z', '0'..'9', '_', '$',
  238. '\128'..'\255'}:
  239. break
  240. c.bufpos = pos
  241. tok.kind = tkIdentifier
  242. proc getQuotedIdentifier(c: var SqlLexer, tok: var Token, quote = '\"') =
  243. var pos = c.bufpos + 1
  244. tok.kind = tkQuotedIdentifier
  245. while true:
  246. var ch = c.buf[pos]
  247. if ch == quote:
  248. if c.buf[pos+1] == quote:
  249. inc(pos, 2)
  250. add(tok.literal, quote)
  251. else:
  252. inc(pos)
  253. break
  254. elif ch in {'\c', '\L', lexbase.EndOfFile}:
  255. tok.kind = tkInvalid
  256. break
  257. else:
  258. add(tok.literal, ch)
  259. inc(pos)
  260. c.bufpos = pos
  261. proc getBitHexString(c: var SqlLexer, tok: var Token, validChars: set[char]) =
  262. var pos = c.bufpos + 1
  263. block parseLoop:
  264. while true:
  265. while true:
  266. var ch = c.buf[pos]
  267. if ch in validChars:
  268. add(tok.literal, ch)
  269. inc(pos)
  270. elif ch == '\'':
  271. inc(pos)
  272. break
  273. else:
  274. tok.kind = tkInvalid
  275. break parseLoop
  276. c.bufpos = pos
  277. var line = c.lineNumber
  278. skip(c)
  279. if c.lineNumber > line:
  280. # a new line whitespace has been parsed, so we check if the string
  281. # continues after the whitespace:
  282. pos = c.bufpos
  283. if c.buf[pos] == '\'': inc(pos)
  284. else: break parseLoop
  285. else: break parseLoop
  286. c.bufpos = pos
  287. proc getNumeric(c: var SqlLexer, tok: var Token) =
  288. tok.kind = tkInteger
  289. var pos = c.bufpos
  290. while c.buf[pos] in Digits:
  291. add(tok.literal, c.buf[pos])
  292. inc(pos)
  293. if c.buf[pos] == '.':
  294. tok.kind = tkNumeric
  295. add(tok.literal, c.buf[pos])
  296. inc(pos)
  297. while c.buf[pos] in Digits:
  298. add(tok.literal, c.buf[pos])
  299. inc(pos)
  300. if c.buf[pos] in {'E', 'e'}:
  301. tok.kind = tkNumeric
  302. add(tok.literal, c.buf[pos])
  303. inc(pos)
  304. if c.buf[pos] == '+':
  305. inc(pos)
  306. elif c.buf[pos] == '-':
  307. add(tok.literal, c.buf[pos])
  308. inc(pos)
  309. if c.buf[pos] in Digits:
  310. while c.buf[pos] in Digits:
  311. add(tok.literal, c.buf[pos])
  312. inc(pos)
  313. else:
  314. tok.kind = tkInvalid
  315. c.bufpos = pos
  316. proc getOperator(c: var SqlLexer, tok: var Token) =
  317. const operators = {'+', '-', '*', '/', '<', '>', '=', '~', '!', '@', '#', '%',
  318. '^', '&', '|', '`', '?'}
  319. tok.kind = tkOperator
  320. var pos = c.bufpos
  321. var trailingPlusMinus = false
  322. while true:
  323. case c.buf[pos]
  324. of '-':
  325. if c.buf[pos] == '-': break
  326. if not trailingPlusMinus and c.buf[pos+1] notin operators and
  327. tok.literal.len > 0: break
  328. of '/':
  329. if c.buf[pos] == '*': break
  330. of '~', '!', '@', '#', '%', '^', '&', '|', '`', '?':
  331. trailingPlusMinus = true
  332. of '+':
  333. if not trailingPlusMinus and c.buf[pos+1] notin operators and
  334. tok.literal.len > 0: break
  335. of '*', '<', '>', '=': discard
  336. else: break
  337. add(tok.literal, c.buf[pos])
  338. inc(pos)
  339. c.bufpos = pos
  340. proc getTok(c: var SqlLexer, tok: var Token) =
  341. tok.kind = tkInvalid
  342. setLen(tok.literal, 0)
  343. skip(c)
  344. case c.buf[c.bufpos]
  345. of ';':
  346. tok.kind = tkSemicolon
  347. inc(c.bufpos)
  348. add(tok.literal, ';')
  349. of ',':
  350. tok.kind = tkComma
  351. inc(c.bufpos)
  352. add(tok.literal, ',')
  353. of ':':
  354. tok.kind = tkColon
  355. inc(c.bufpos)
  356. add(tok.literal, ':')
  357. of 'e', 'E':
  358. if c.buf[c.bufpos + 1] == '\'':
  359. inc(c.bufpos)
  360. getString(c, tok, tkEscapeConstant)
  361. else:
  362. getSymbol(c, tok)
  363. of 'b', 'B':
  364. if c.buf[c.bufpos + 1] == '\'':
  365. tok.kind = tkBitStringConstant
  366. getBitHexString(c, tok, {'0'..'1'})
  367. else:
  368. getSymbol(c, tok)
  369. of 'x', 'X':
  370. if c.buf[c.bufpos + 1] == '\'':
  371. tok.kind = tkHexStringConstant
  372. getBitHexString(c, tok, {'a'..'f', 'A'..'F', '0'..'9'})
  373. else:
  374. getSymbol(c, tok)
  375. of '$': getDollarString(c, tok)
  376. of '[':
  377. tok.kind = tkBracketLe
  378. inc(c.bufpos)
  379. add(tok.literal, '[')
  380. of ']':
  381. tok.kind = tkBracketRi
  382. inc(c.bufpos)
  383. add(tok.literal, ']')
  384. of '(':
  385. tok.kind = tkParLe
  386. inc(c.bufpos)
  387. add(tok.literal, '(')
  388. of ')':
  389. tok.kind = tkParRi
  390. inc(c.bufpos)
  391. add(tok.literal, ')')
  392. of '.':
  393. if c.buf[c.bufpos + 1] in Digits:
  394. getNumeric(c, tok)
  395. else:
  396. tok.kind = tkDot
  397. inc(c.bufpos)
  398. add(tok.literal, '.')
  399. of '0'..'9': getNumeric(c, tok)
  400. of '\'': getString(c, tok, tkStringConstant)
  401. of '"': getQuotedIdentifier(c, tok, '"')
  402. of '`': getQuotedIdentifier(c, tok, '`')
  403. of lexbase.EndOfFile:
  404. tok.kind = tkEof
  405. tok.literal = "[EOF]"
  406. of 'a', 'c', 'd', 'f'..'w', 'y', 'z', 'A', 'C', 'D', 'F'..'W', 'Y', 'Z', '_',
  407. '\128'..'\255':
  408. getSymbol(c, tok)
  409. of '+', '-', '*', '/', '<', '>', '=', '~', '!', '@', '#', '%',
  410. '^', '&', '|', '?':
  411. getOperator(c, tok)
  412. else:
  413. add(tok.literal, c.buf[c.bufpos])
  414. inc(c.bufpos)
  415. proc errorStr(L: SqlLexer, msg: string): string =
  416. result = "$1($2, $3) Error: $4" % [L.filename, $getLine(L), $getColumn(L), msg]
  417. # ----------------------------- parser ----------------------------------------
  418. # Operator/Element Associativity Description
  419. # . left table/column name separator
  420. # :: left PostgreSQL-style typecast
  421. # [ ] left array element selection
  422. # - right unary minus
  423. # ^ left exponentiation
  424. # * / % left multiplication, division, modulo
  425. # + - left addition, subtraction
  426. # IS IS TRUE, IS FALSE, IS UNKNOWN, IS NULL
  427. # ISNULL test for null
  428. # NOTNULL test for not null
  429. # (any other) left all other native and user-defined oprs
  430. # IN set membership
  431. # BETWEEN range containment
  432. # OVERLAPS time interval overlap
  433. # LIKE ILIKE SIMILAR string pattern matching
  434. # < > less than, greater than
  435. # = right equality, assignment
  436. # NOT right logical negation
  437. # AND left logical conjunction
  438. # OR left logical disjunction
  439. type
  440. SqlNodeKind* = enum ## kind of SQL abstract syntax tree
  441. nkNone,
  442. nkIdent,
  443. nkQuotedIdent,
  444. nkStringLit,
  445. nkBitStringLit,
  446. nkHexStringLit,
  447. nkIntegerLit,
  448. nkNumericLit,
  449. nkPrimaryKey,
  450. nkForeignKey,
  451. nkNotNull,
  452. nkNull,
  453. nkStmtList,
  454. nkDot,
  455. nkDotDot,
  456. nkPrefix,
  457. nkInfix,
  458. nkCall,
  459. nkPrGroup,
  460. nkColumnReference,
  461. nkReferences,
  462. nkDefault,
  463. nkCheck,
  464. nkConstraint,
  465. nkUnique,
  466. nkIdentity,
  467. nkColumnDef, ## name, datatype, constraints
  468. nkInsert,
  469. nkUpdate,
  470. nkDelete,
  471. nkSelect,
  472. nkSelectDistinct,
  473. nkSelectColumns,
  474. nkSelectPair,
  475. nkAsgn,
  476. nkFrom,
  477. nkFromItemPair,
  478. nkGroup,
  479. nkLimit,
  480. nkHaving,
  481. nkOrder,
  482. nkJoin,
  483. nkDesc,
  484. nkUnion,
  485. nkIntersect,
  486. nkExcept,
  487. nkColumnList,
  488. nkValueList,
  489. nkWhere,
  490. nkCreateTable,
  491. nkCreateTableIfNotExists,
  492. nkCreateType,
  493. nkCreateTypeIfNotExists,
  494. nkCreateIndex,
  495. nkCreateIndexIfNotExists,
  496. nkEnumDef
  497. const
  498. LiteralNodes = {
  499. nkIdent, nkQuotedIdent, nkStringLit, nkBitStringLit, nkHexStringLit,
  500. nkIntegerLit, nkNumericLit
  501. }
  502. type
  503. SqlParseError* = object of ValueError ## Invalid SQL encountered
  504. SqlNode* = ref SqlNodeObj ## an SQL abstract syntax tree node
  505. SqlNodeObj* = object ## an SQL abstract syntax tree node
  506. case kind*: SqlNodeKind ## kind of syntax tree
  507. of LiteralNodes:
  508. strVal*: string ## AST leaf: the identifier, numeric literal
  509. ## string literal, etc.
  510. else:
  511. sons*: seq[SqlNode] ## the node's children
  512. SqlParser* = object of SqlLexer ## SQL parser object
  513. tok: Token
  514. proc newNode*(k: SqlNodeKind): SqlNode =
  515. when defined(js): # bug #14117
  516. case k
  517. of LiteralNodes:
  518. result = SqlNode(kind: k, strVal: "")
  519. else:
  520. result = SqlNode(kind: k, sons: @[])
  521. else:
  522. result = SqlNode(kind: k)
  523. proc newNode*(k: SqlNodeKind, s: string): SqlNode =
  524. result = SqlNode(kind: k)
  525. result.strVal = s
  526. proc newNode*(k: SqlNodeKind, sons: seq[SqlNode]): SqlNode =
  527. result = SqlNode(kind: k)
  528. result.sons = sons
  529. proc len*(n: SqlNode): int =
  530. if n.kind in LiteralNodes:
  531. result = 0
  532. else:
  533. result = n.sons.len
  534. proc `[]`*(n: SqlNode; i: int): SqlNode = n.sons[i]
  535. proc `[]`*(n: SqlNode; i: BackwardsIndex): SqlNode = n.sons[n.len - int(i)]
  536. proc add*(father, n: SqlNode) =
  537. add(father.sons, n)
  538. proc getTok(p: var SqlParser) =
  539. getTok(p, p.tok)
  540. proc sqlError(p: SqlParser, msg: string) =
  541. var e: ref SqlParseError
  542. new(e)
  543. e.msg = errorStr(p, msg)
  544. raise e
  545. proc isKeyw(p: SqlParser, keyw: string): bool =
  546. result = p.tok.kind == tkIdentifier and
  547. cmpIgnoreCase(p.tok.literal, keyw) == 0
  548. proc isOpr(p: SqlParser, opr: string): bool =
  549. result = p.tok.kind == tkOperator and
  550. cmpIgnoreCase(p.tok.literal, opr) == 0
  551. proc optKeyw(p: var SqlParser, keyw: string) =
  552. if p.tok.kind == tkIdentifier and cmpIgnoreCase(p.tok.literal, keyw) == 0:
  553. getTok(p)
  554. proc expectIdent(p: SqlParser) =
  555. if p.tok.kind != tkIdentifier and p.tok.kind != tkQuotedIdentifier:
  556. sqlError(p, "identifier expected")
  557. proc expect(p: SqlParser, kind: TokKind) =
  558. if p.tok.kind != kind:
  559. sqlError(p, tokKindToStr[kind] & " expected")
  560. proc eat(p: var SqlParser, kind: TokKind) =
  561. if p.tok.kind == kind:
  562. getTok(p)
  563. else:
  564. sqlError(p, tokKindToStr[kind] & " expected")
  565. proc eat(p: var SqlParser, keyw: string) =
  566. if isKeyw(p, keyw):
  567. getTok(p)
  568. else:
  569. sqlError(p, keyw.toUpperAscii() & " expected")
  570. proc opt(p: var SqlParser, kind: TokKind) =
  571. if p.tok.kind == kind: getTok(p)
  572. proc parseDataType(p: var SqlParser): SqlNode =
  573. if isKeyw(p, "enum"):
  574. result = newNode(nkEnumDef)
  575. getTok(p)
  576. if p.tok.kind == tkParLe:
  577. getTok(p)
  578. result.add(newNode(nkStringLit, p.tok.literal))
  579. getTok(p)
  580. while p.tok.kind == tkComma:
  581. getTok(p)
  582. result.add(newNode(nkStringLit, p.tok.literal))
  583. getTok(p)
  584. eat(p, tkParRi)
  585. else:
  586. expectIdent(p)
  587. result = newNode(nkIdent, p.tok.literal)
  588. getTok(p)
  589. # ignore (12, 13) part:
  590. if p.tok.kind == tkParLe:
  591. getTok(p)
  592. expect(p, tkInteger)
  593. getTok(p)
  594. while p.tok.kind == tkComma:
  595. getTok(p)
  596. expect(p, tkInteger)
  597. getTok(p)
  598. eat(p, tkParRi)
  599. proc getPrecedence(p: SqlParser): int =
  600. if isOpr(p, "*") or isOpr(p, "/") or isOpr(p, "%"):
  601. result = 6
  602. elif isOpr(p, "+") or isOpr(p, "-"):
  603. result = 5
  604. elif isOpr(p, "=") or isOpr(p, "<") or isOpr(p, ">") or isOpr(p, ">=") or
  605. isOpr(p, "<=") or isOpr(p, "<>") or isOpr(p, "!=") or isKeyw(p, "is") or
  606. isKeyw(p, "like") or isKeyw(p, "in"):
  607. result = 4
  608. elif isKeyw(p, "and"):
  609. result = 3
  610. elif isKeyw(p, "or"):
  611. result = 2
  612. elif isKeyw(p, "between"):
  613. result = 1
  614. elif p.tok.kind == tkOperator:
  615. # user-defined operator:
  616. result = 0
  617. else:
  618. result = - 1
  619. proc parseExpr(p: var SqlParser): SqlNode {.gcsafe.}
  620. proc parseSelect(p: var SqlParser): SqlNode {.gcsafe.}
  621. proc identOrLiteral(p: var SqlParser): SqlNode =
  622. case p.tok.kind
  623. of tkQuotedIdentifier:
  624. result = newNode(nkQuotedIdent, p.tok.literal)
  625. getTok(p)
  626. of tkIdentifier:
  627. result = newNode(nkIdent, p.tok.literal)
  628. getTok(p)
  629. of tkStringConstant, tkEscapeConstant, tkDollarQuotedConstant:
  630. result = newNode(nkStringLit, p.tok.literal)
  631. getTok(p)
  632. of tkBitStringConstant:
  633. result = newNode(nkBitStringLit, p.tok.literal)
  634. getTok(p)
  635. of tkHexStringConstant:
  636. result = newNode(nkHexStringLit, p.tok.literal)
  637. getTok(p)
  638. of tkInteger:
  639. result = newNode(nkIntegerLit, p.tok.literal)
  640. getTok(p)
  641. of tkNumeric:
  642. result = newNode(nkNumericLit, p.tok.literal)
  643. getTok(p)
  644. of tkParLe:
  645. getTok(p)
  646. result = newNode(nkPrGroup)
  647. while true:
  648. result.add(parseExpr(p))
  649. if p.tok.kind != tkComma: break
  650. getTok(p)
  651. eat(p, tkParRi)
  652. else:
  653. if p.tok.literal == "*":
  654. result = newNode(nkIdent, p.tok.literal)
  655. getTok(p)
  656. else:
  657. sqlError(p, "expression expected")
  658. getTok(p) # we must consume a token here to prevent endless loops!
  659. proc primary(p: var SqlParser): SqlNode =
  660. if (p.tok.kind == tkOperator and (p.tok.literal == "+" or p.tok.literal ==
  661. "-")) or isKeyw(p, "not"):
  662. result = newNode(nkPrefix)
  663. result.add(newNode(nkIdent, p.tok.literal))
  664. getTok(p)
  665. result.add(primary(p))
  666. return
  667. result = identOrLiteral(p)
  668. while true:
  669. case p.tok.kind
  670. of tkParLe:
  671. var a = result
  672. result = newNode(nkCall)
  673. result.add(a)
  674. getTok(p)
  675. while p.tok.kind != tkParRi:
  676. result.add(parseExpr(p))
  677. if p.tok.kind == tkComma: getTok(p)
  678. else: break
  679. eat(p, tkParRi)
  680. of tkDot:
  681. getTok(p)
  682. var a = result
  683. if p.tok.kind == tkDot:
  684. getTok(p)
  685. result = newNode(nkDotDot)
  686. else:
  687. result = newNode(nkDot)
  688. result.add(a)
  689. if isOpr(p, "*"):
  690. result.add(newNode(nkIdent, "*"))
  691. elif p.tok.kind in {tkIdentifier, tkQuotedIdentifier}:
  692. result.add(newNode(nkIdent, p.tok.literal))
  693. else:
  694. sqlError(p, "identifier expected")
  695. getTok(p)
  696. else: break
  697. proc lowestExprAux(p: var SqlParser, v: var SqlNode, limit: int): int =
  698. var
  699. v2, node, opNode: SqlNode
  700. v = primary(p) # expand while operators have priorities higher than 'limit'
  701. var opPred = getPrecedence(p)
  702. result = opPred
  703. while opPred > limit:
  704. node = newNode(nkInfix)
  705. opNode = newNode(nkIdent, p.tok.literal.toLowerAscii())
  706. getTok(p)
  707. result = lowestExprAux(p, v2, opPred)
  708. node.add(opNode)
  709. node.add(v)
  710. node.add(v2)
  711. v = node
  712. opPred = getPrecedence(p)
  713. proc parseExpr(p: var SqlParser): SqlNode =
  714. discard lowestExprAux(p, result, - 1)
  715. proc parseTableName(p: var SqlParser): SqlNode =
  716. expectIdent(p)
  717. result = primary(p)
  718. proc parseColumnReference(p: var SqlParser): SqlNode =
  719. result = parseTableName(p)
  720. if p.tok.kind == tkParLe:
  721. getTok(p)
  722. var a = result
  723. result = newNode(nkColumnReference)
  724. result.add(a)
  725. result.add(parseTableName(p))
  726. while p.tok.kind == tkComma:
  727. getTok(p)
  728. result.add(parseTableName(p))
  729. eat(p, tkParRi)
  730. proc parseCheck(p: var SqlParser): SqlNode =
  731. getTok(p)
  732. result = newNode(nkCheck)
  733. result.add(parseExpr(p))
  734. proc parseConstraint(p: var SqlParser): SqlNode =
  735. getTok(p)
  736. result = newNode(nkConstraint)
  737. expectIdent(p)
  738. result.add(newNode(nkIdent, p.tok.literal))
  739. getTok(p)
  740. optKeyw(p, "check")
  741. result.add(parseExpr(p))
  742. proc parseParIdentList(p: var SqlParser, father: SqlNode) =
  743. eat(p, tkParLe)
  744. while true:
  745. expectIdent(p)
  746. father.add(newNode(nkIdent, p.tok.literal))
  747. getTok(p)
  748. if p.tok.kind != tkComma: break
  749. getTok(p)
  750. eat(p, tkParRi)
  751. proc parseColumnConstraints(p: var SqlParser, result: SqlNode) =
  752. while true:
  753. if isKeyw(p, "default"):
  754. getTok(p)
  755. var n = newNode(nkDefault)
  756. n.add(parseExpr(p))
  757. result.add(n)
  758. elif isKeyw(p, "references"):
  759. getTok(p)
  760. var n = newNode(nkReferences)
  761. n.add(parseColumnReference(p))
  762. result.add(n)
  763. elif isKeyw(p, "not"):
  764. getTok(p)
  765. eat(p, "null")
  766. result.add(newNode(nkNotNull))
  767. elif isKeyw(p, "null"):
  768. getTok(p)
  769. result.add(newNode(nkNull))
  770. elif isKeyw(p, "identity"):
  771. getTok(p)
  772. result.add(newNode(nkIdentity))
  773. elif isKeyw(p, "primary"):
  774. getTok(p)
  775. eat(p, "key")
  776. result.add(newNode(nkPrimaryKey))
  777. elif isKeyw(p, "check"):
  778. result.add(parseCheck(p))
  779. elif isKeyw(p, "constraint"):
  780. result.add(parseConstraint(p))
  781. elif isKeyw(p, "unique"):
  782. getTok(p)
  783. result.add(newNode(nkUnique))
  784. else:
  785. break
  786. proc parseColumnDef(p: var SqlParser): SqlNode =
  787. expectIdent(p)
  788. result = newNode(nkColumnDef)
  789. result.add(newNode(nkIdent, p.tok.literal))
  790. getTok(p)
  791. result.add(parseDataType(p))
  792. parseColumnConstraints(p, result)
  793. proc parseIfNotExists(p: var SqlParser, k: SqlNodeKind): SqlNode =
  794. getTok(p)
  795. if isKeyw(p, "if"):
  796. getTok(p)
  797. eat(p, "not")
  798. eat(p, "exists")
  799. result = newNode(succ(k))
  800. else:
  801. result = newNode(k)
  802. proc parseTableConstraint(p: var SqlParser): SqlNode =
  803. if isKeyw(p, "primary"):
  804. getTok(p)
  805. eat(p, "key")
  806. result = newNode(nkPrimaryKey)
  807. parseParIdentList(p, result)
  808. elif isKeyw(p, "foreign"):
  809. getTok(p)
  810. eat(p, "key")
  811. result = newNode(nkForeignKey)
  812. parseParIdentList(p, result)
  813. eat(p, "references")
  814. var m = newNode(nkReferences)
  815. m.add(parseColumnReference(p))
  816. result.add(m)
  817. elif isKeyw(p, "unique"):
  818. getTok(p)
  819. eat(p, "key")
  820. result = newNode(nkUnique)
  821. parseParIdentList(p, result)
  822. elif isKeyw(p, "check"):
  823. result = parseCheck(p)
  824. elif isKeyw(p, "constraint"):
  825. result = parseConstraint(p)
  826. else:
  827. sqlError(p, "column definition expected")
  828. proc parseUnique(p: var SqlParser): SqlNode =
  829. result = parseExpr(p)
  830. if result.kind == nkCall: result.kind = nkUnique
  831. proc parseTableDef(p: var SqlParser): SqlNode =
  832. result = parseIfNotExists(p, nkCreateTable)
  833. expectIdent(p)
  834. result.add(newNode(nkIdent, p.tok.literal))
  835. getTok(p)
  836. if p.tok.kind == tkParLe:
  837. getTok(p)
  838. while p.tok.kind != tkParRi:
  839. if isKeyw(p, "constraint"):
  840. result.add parseConstraint(p)
  841. elif isKeyw(p, "primary") or isKeyw(p, "foreign"):
  842. result.add parseTableConstraint(p)
  843. elif isKeyw(p, "unique"):
  844. result.add parseUnique(p)
  845. elif p.tok.kind == tkIdentifier or p.tok.kind == tkQuotedIdentifier:
  846. result.add(parseColumnDef(p))
  847. else:
  848. result.add(parseTableConstraint(p))
  849. if p.tok.kind != tkComma: break
  850. getTok(p)
  851. eat(p, tkParRi)
  852. # skip additional crap after 'create table (...) crap;'
  853. while p.tok.kind notin {tkSemicolon, tkEof}:
  854. getTok(p)
  855. proc parseTypeDef(p: var SqlParser): SqlNode =
  856. result = parseIfNotExists(p, nkCreateType)
  857. expectIdent(p)
  858. result.add(newNode(nkIdent, p.tok.literal))
  859. getTok(p)
  860. eat(p, "as")
  861. result.add(parseDataType(p))
  862. proc parseWhere(p: var SqlParser): SqlNode =
  863. getTok(p)
  864. result = newNode(nkWhere)
  865. result.add(parseExpr(p))
  866. proc parseFromItem(p: var SqlParser): SqlNode =
  867. result = newNode(nkFromItemPair)
  868. if p.tok.kind == tkParLe:
  869. getTok(p)
  870. var select = parseSelect(p)
  871. result.add(select)
  872. eat(p, tkParRi)
  873. else:
  874. result.add(parseExpr(p))
  875. if isKeyw(p, "as"):
  876. getTok(p)
  877. result.add(parseExpr(p))
  878. proc parseIndexDef(p: var SqlParser): SqlNode =
  879. result = parseIfNotExists(p, nkCreateIndex)
  880. if isKeyw(p, "primary"):
  881. getTok(p)
  882. eat(p, "key")
  883. result.add(newNode(nkPrimaryKey))
  884. else:
  885. expectIdent(p)
  886. result.add(newNode(nkIdent, p.tok.literal))
  887. getTok(p)
  888. eat(p, "on")
  889. expectIdent(p)
  890. result.add(newNode(nkIdent, p.tok.literal))
  891. getTok(p)
  892. eat(p, tkParLe)
  893. expectIdent(p)
  894. result.add(newNode(nkIdent, p.tok.literal))
  895. getTok(p)
  896. while p.tok.kind == tkComma:
  897. getTok(p)
  898. expectIdent(p)
  899. result.add(newNode(nkIdent, p.tok.literal))
  900. getTok(p)
  901. eat(p, tkParRi)
  902. proc parseInsert(p: var SqlParser): SqlNode =
  903. getTok(p)
  904. eat(p, "into")
  905. expectIdent(p)
  906. result = newNode(nkInsert)
  907. result.add(newNode(nkIdent, p.tok.literal))
  908. getTok(p)
  909. if p.tok.kind == tkParLe:
  910. var n = newNode(nkColumnList)
  911. parseParIdentList(p, n)
  912. result.add n
  913. else:
  914. result.add(nil)
  915. if isKeyw(p, "default"):
  916. getTok(p)
  917. eat(p, "values")
  918. result.add(newNode(nkDefault))
  919. else:
  920. eat(p, "values")
  921. eat(p, tkParLe)
  922. var n = newNode(nkValueList)
  923. while true:
  924. n.add(parseExpr(p))
  925. if p.tok.kind != tkComma: break
  926. getTok(p)
  927. result.add(n)
  928. eat(p, tkParRi)
  929. proc parseUpdate(p: var SqlParser): SqlNode =
  930. getTok(p)
  931. result = newNode(nkUpdate)
  932. result.add(primary(p))
  933. eat(p, "set")
  934. while true:
  935. var a = newNode(nkAsgn)
  936. expectIdent(p)
  937. a.add(newNode(nkIdent, p.tok.literal))
  938. getTok(p)
  939. if isOpr(p, "="): getTok(p)
  940. else: sqlError(p, "= expected")
  941. a.add(parseExpr(p))
  942. result.add(a)
  943. if p.tok.kind != tkComma: break
  944. getTok(p)
  945. if isKeyw(p, "where"):
  946. result.add(parseWhere(p))
  947. else:
  948. result.add(nil)
  949. proc parseDelete(p: var SqlParser): SqlNode =
  950. getTok(p)
  951. if isOpr(p, "*"):
  952. getTok(p)
  953. result = newNode(nkDelete)
  954. eat(p, "from")
  955. result.add(primary(p))
  956. if isKeyw(p, "where"):
  957. result.add(parseWhere(p))
  958. else:
  959. result.add(nil)
  960. proc parseSelect(p: var SqlParser): SqlNode =
  961. getTok(p)
  962. if isKeyw(p, "distinct"):
  963. getTok(p)
  964. result = newNode(nkSelectDistinct)
  965. elif isKeyw(p, "all"):
  966. getTok(p)
  967. result = newNode(nkSelect)
  968. var a = newNode(nkSelectColumns)
  969. while true:
  970. if isOpr(p, "*"):
  971. a.add(newNode(nkIdent, "*"))
  972. getTok(p)
  973. else:
  974. var pair = newNode(nkSelectPair)
  975. pair.add(parseExpr(p))
  976. a.add(pair)
  977. if isKeyw(p, "as"):
  978. getTok(p)
  979. pair.add(parseExpr(p))
  980. if p.tok.kind != tkComma: break
  981. getTok(p)
  982. result.add(a)
  983. if isKeyw(p, "from"):
  984. var f = newNode(nkFrom)
  985. while true:
  986. getTok(p)
  987. f.add(parseFromItem(p))
  988. if p.tok.kind != tkComma: break
  989. result.add(f)
  990. if isKeyw(p, "where"):
  991. result.add(parseWhere(p))
  992. if isKeyw(p, "group"):
  993. getTok(p)
  994. eat(p, "by")
  995. var g = newNode(nkGroup)
  996. while true:
  997. g.add(parseExpr(p))
  998. if p.tok.kind != tkComma: break
  999. getTok(p)
  1000. result.add(g)
  1001. if isKeyw(p, "order"):
  1002. getTok(p)
  1003. eat(p, "by")
  1004. var n = newNode(nkOrder)
  1005. while true:
  1006. var e = parseExpr(p)
  1007. if isKeyw(p, "asc"):
  1008. getTok(p) # is default
  1009. elif isKeyw(p, "desc"):
  1010. getTok(p)
  1011. var x = newNode(nkDesc)
  1012. x.add(e)
  1013. e = x
  1014. n.add(e)
  1015. if p.tok.kind != tkComma: break
  1016. getTok(p)
  1017. result.add(n)
  1018. if isKeyw(p, "having"):
  1019. var h = newNode(nkHaving)
  1020. while true:
  1021. getTok(p)
  1022. h.add(parseExpr(p))
  1023. if p.tok.kind != tkComma: break
  1024. result.add(h)
  1025. if isKeyw(p, "union"):
  1026. result.add(newNode(nkUnion))
  1027. getTok(p)
  1028. elif isKeyw(p, "intersect"):
  1029. result.add(newNode(nkIntersect))
  1030. getTok(p)
  1031. elif isKeyw(p, "except"):
  1032. result.add(newNode(nkExcept))
  1033. getTok(p)
  1034. if isKeyw(p, "join") or isKeyw(p, "inner") or isKeyw(p, "outer") or isKeyw(p, "cross"):
  1035. var join = newNode(nkJoin)
  1036. result.add(join)
  1037. if isKeyw(p, "join"):
  1038. join.add(newNode(nkIdent, ""))
  1039. getTok(p)
  1040. else:
  1041. join.add(newNode(nkIdent, p.tok.literal.toLowerAscii()))
  1042. getTok(p)
  1043. eat(p, "join")
  1044. join.add(parseFromItem(p))
  1045. eat(p, "on")
  1046. join.add(parseExpr(p))
  1047. if isKeyw(p, "limit"):
  1048. getTok(p)
  1049. var l = newNode(nkLimit)
  1050. l.add(parseExpr(p))
  1051. result.add(l)
  1052. proc parseStmt(p: var SqlParser; parent: SqlNode) =
  1053. if isKeyw(p, "create"):
  1054. getTok(p)
  1055. optKeyw(p, "cached")
  1056. optKeyw(p, "memory")
  1057. optKeyw(p, "temp")
  1058. optKeyw(p, "global")
  1059. optKeyw(p, "local")
  1060. optKeyw(p, "temporary")
  1061. optKeyw(p, "unique")
  1062. optKeyw(p, "hash")
  1063. if isKeyw(p, "table"):
  1064. parent.add parseTableDef(p)
  1065. elif isKeyw(p, "type"):
  1066. parent.add parseTypeDef(p)
  1067. elif isKeyw(p, "index"):
  1068. parent.add parseIndexDef(p)
  1069. else:
  1070. sqlError(p, "TABLE expected")
  1071. elif isKeyw(p, "insert"):
  1072. parent.add parseInsert(p)
  1073. elif isKeyw(p, "update"):
  1074. parent.add parseUpdate(p)
  1075. elif isKeyw(p, "delete"):
  1076. parent.add parseDelete(p)
  1077. elif isKeyw(p, "select"):
  1078. parent.add parseSelect(p)
  1079. elif isKeyw(p, "begin"):
  1080. getTok(p)
  1081. else:
  1082. sqlError(p, "SELECT, CREATE, UPDATE or DELETE expected")
  1083. proc parse(p: var SqlParser): SqlNode =
  1084. ## parses the content of `p`'s input stream and returns the SQL AST.
  1085. ## Syntax errors raise an `SqlParseError` exception.
  1086. result = newNode(nkStmtList)
  1087. while p.tok.kind != tkEof:
  1088. parseStmt(p, result)
  1089. if p.tok.kind == tkEof:
  1090. break
  1091. eat(p, tkSemicolon)
  1092. proc close(p: var SqlParser) =
  1093. ## closes the parser `p`. The associated input stream is closed too.
  1094. close(SqlLexer(p))
  1095. type
  1096. SqlWriter = object
  1097. indent: int
  1098. upperCase: bool
  1099. buffer: string
  1100. proc add(s: var SqlWriter, thing: char) =
  1101. s.buffer.add(thing)
  1102. proc prepareAdd(s: var SqlWriter) {.inline.} =
  1103. if s.buffer.len > 0 and s.buffer[^1] notin {' ', '\L', '(', '.'}:
  1104. s.buffer.add(" ")
  1105. proc add(s: var SqlWriter, thing: string) =
  1106. s.prepareAdd
  1107. s.buffer.add(thing)
  1108. proc addKeyw(s: var SqlWriter, thing: string) =
  1109. var keyw = thing
  1110. if s.upperCase:
  1111. keyw = keyw.toUpperAscii()
  1112. s.add(keyw)
  1113. proc addIden(s: var SqlWriter, thing: string) =
  1114. var iden = thing
  1115. if iden.toLowerAscii() in reservedKeywords:
  1116. iden = '"' & iden & '"'
  1117. s.add(iden)
  1118. proc ra(n: SqlNode, s: var SqlWriter) {.gcsafe.}
  1119. proc rs(n: SqlNode, s: var SqlWriter, prefix = "(", suffix = ")", sep = ", ") =
  1120. if n.len > 0:
  1121. s.add(prefix)
  1122. for i in 0 .. n.len-1:
  1123. if i > 0: s.add(sep)
  1124. ra(n.sons[i], s)
  1125. s.add(suffix)
  1126. proc addMulti(s: var SqlWriter, n: SqlNode, sep = ',') =
  1127. if n.len > 0:
  1128. for i in 0 .. n.len-1:
  1129. if i > 0: s.add(sep)
  1130. ra(n.sons[i], s)
  1131. proc addMulti(s: var SqlWriter, n: SqlNode, sep = ',', prefix, suffix: char) =
  1132. if n.len > 0:
  1133. s.add(prefix)
  1134. for i in 0 .. n.len-1:
  1135. if i > 0: s.add(sep)
  1136. ra(n.sons[i], s)
  1137. s.add(suffix)
  1138. proc quoted(s: string): string =
  1139. "\"" & replace(s, "\"", "\"\"") & "\""
  1140. func escape(result: var string; s: string) =
  1141. result.add('\'')
  1142. for c in items(s):
  1143. case c
  1144. of '\0'..'\31':
  1145. result.add("\\x")
  1146. result.add(toHex(ord(c), 2))
  1147. of '\'': result.add("''")
  1148. else: result.add(c)
  1149. result.add('\'')
  1150. proc ra(n: SqlNode, s: var SqlWriter) =
  1151. if n == nil: return
  1152. case n.kind
  1153. of nkNone: discard
  1154. of nkIdent:
  1155. if allCharsInSet(n.strVal, {'\33'..'\127'}):
  1156. s.add(n.strVal)
  1157. else:
  1158. s.add(quoted(n.strVal))
  1159. of nkQuotedIdent:
  1160. s.add(quoted(n.strVal))
  1161. of nkStringLit:
  1162. s.prepareAdd
  1163. s.buffer.escape(n.strVal)
  1164. of nkBitStringLit:
  1165. s.add("b'" & n.strVal & "'")
  1166. of nkHexStringLit:
  1167. s.add("x'" & n.strVal & "'")
  1168. of nkIntegerLit, nkNumericLit:
  1169. s.add(n.strVal)
  1170. of nkPrimaryKey:
  1171. s.addKeyw("primary key")
  1172. rs(n, s)
  1173. of nkForeignKey:
  1174. s.addKeyw("foreign key")
  1175. rs(n, s)
  1176. of nkNotNull:
  1177. s.addKeyw("not null")
  1178. of nkNull:
  1179. s.addKeyw("null")
  1180. of nkDot:
  1181. ra(n.sons[0], s)
  1182. s.add('.')
  1183. ra(n.sons[1], s)
  1184. of nkDotDot:
  1185. ra(n.sons[0], s)
  1186. s.add(". .")
  1187. ra(n.sons[1], s)
  1188. of nkPrefix:
  1189. ra(n.sons[0], s)
  1190. s.add(' ')
  1191. ra(n.sons[1], s)
  1192. of nkInfix:
  1193. ra(n.sons[1], s)
  1194. s.add(' ')
  1195. ra(n.sons[0], s)
  1196. s.add(' ')
  1197. ra(n.sons[2], s)
  1198. of nkCall, nkColumnReference:
  1199. ra(n.sons[0], s)
  1200. s.add('(')
  1201. for i in 1..n.len-1:
  1202. if i > 1: s.add(',')
  1203. ra(n.sons[i], s)
  1204. s.add(')')
  1205. of nkPrGroup:
  1206. s.add('(')
  1207. s.addMulti(n)
  1208. s.add(')')
  1209. of nkReferences:
  1210. s.addKeyw("references")
  1211. ra(n.sons[0], s)
  1212. of nkDefault:
  1213. s.addKeyw("default")
  1214. ra(n.sons[0], s)
  1215. of nkCheck:
  1216. s.addKeyw("check")
  1217. ra(n.sons[0], s)
  1218. of nkConstraint:
  1219. s.addKeyw("constraint")
  1220. ra(n.sons[0], s)
  1221. s.addKeyw("check")
  1222. ra(n.sons[1], s)
  1223. of nkUnique:
  1224. s.addKeyw("unique")
  1225. rs(n, s)
  1226. of nkIdentity:
  1227. s.addKeyw("identity")
  1228. of nkColumnDef:
  1229. rs(n, s, "", "", " ")
  1230. of nkStmtList:
  1231. for i in 0..n.len-1:
  1232. ra(n.sons[i], s)
  1233. s.add(';')
  1234. of nkInsert:
  1235. assert n.len == 3
  1236. s.addKeyw("insert into")
  1237. ra(n.sons[0], s)
  1238. s.add(' ')
  1239. ra(n.sons[1], s)
  1240. if n.sons[2].kind == nkDefault:
  1241. s.addKeyw("default values")
  1242. else:
  1243. ra(n.sons[2], s)
  1244. of nkUpdate:
  1245. s.addKeyw("update")
  1246. ra(n.sons[0], s)
  1247. s.addKeyw("set")
  1248. var L = n.len
  1249. for i in 1 .. L-2:
  1250. if i > 1: s.add(", ")
  1251. var it = n.sons[i]
  1252. assert it.kind == nkAsgn
  1253. ra(it, s)
  1254. ra(n.sons[L-1], s)
  1255. of nkDelete:
  1256. s.addKeyw("delete from")
  1257. ra(n.sons[0], s)
  1258. ra(n.sons[1], s)
  1259. of nkSelect, nkSelectDistinct:
  1260. s.addKeyw("select")
  1261. if n.kind == nkSelectDistinct:
  1262. s.addKeyw("distinct")
  1263. for i in 0 ..< n.len:
  1264. ra(n.sons[i], s)
  1265. of nkSelectColumns:
  1266. for i, column in n.sons:
  1267. if i > 0: s.add(',')
  1268. ra(column, s)
  1269. of nkSelectPair:
  1270. ra(n.sons[0], s)
  1271. if n.sons.len == 2:
  1272. s.addKeyw("as")
  1273. ra(n.sons[1], s)
  1274. of nkFromItemPair:
  1275. if n.sons[0].kind in {nkIdent, nkQuotedIdent}:
  1276. ra(n.sons[0], s)
  1277. else:
  1278. assert n.sons[0].kind == nkSelect
  1279. s.add('(')
  1280. ra(n.sons[0], s)
  1281. s.add(')')
  1282. if n.sons.len == 2:
  1283. s.addKeyw("as")
  1284. ra(n.sons[1], s)
  1285. of nkAsgn:
  1286. ra(n.sons[0], s)
  1287. s.add(" = ")
  1288. ra(n.sons[1], s)
  1289. of nkFrom:
  1290. s.addKeyw("from")
  1291. s.addMulti(n)
  1292. of nkGroup:
  1293. s.addKeyw("group by")
  1294. s.addMulti(n)
  1295. of nkLimit:
  1296. s.addKeyw("limit")
  1297. s.addMulti(n)
  1298. of nkHaving:
  1299. s.addKeyw("having")
  1300. s.addMulti(n)
  1301. of nkOrder:
  1302. s.addKeyw("order by")
  1303. s.addMulti(n)
  1304. of nkJoin:
  1305. var joinType = n.sons[0].strVal
  1306. if joinType == "":
  1307. joinType = "join"
  1308. else:
  1309. joinType &= " " & "join"
  1310. s.addKeyw(joinType)
  1311. ra(n.sons[1], s)
  1312. s.addKeyw("on")
  1313. ra(n.sons[2], s)
  1314. of nkDesc:
  1315. ra(n.sons[0], s)
  1316. s.addKeyw("desc")
  1317. of nkUnion:
  1318. s.addKeyw("union")
  1319. of nkIntersect:
  1320. s.addKeyw("intersect")
  1321. of nkExcept:
  1322. s.addKeyw("except")
  1323. of nkColumnList:
  1324. rs(n, s)
  1325. of nkValueList:
  1326. s.addKeyw("values")
  1327. rs(n, s)
  1328. of nkWhere:
  1329. s.addKeyw("where")
  1330. ra(n.sons[0], s)
  1331. of nkCreateTable, nkCreateTableIfNotExists:
  1332. s.addKeyw("create table")
  1333. if n.kind == nkCreateTableIfNotExists:
  1334. s.addKeyw("if not exists")
  1335. ra(n.sons[0], s)
  1336. s.add('(')
  1337. for i in 1..n.len-1:
  1338. if i > 1: s.add(',')
  1339. ra(n.sons[i], s)
  1340. s.add(");")
  1341. of nkCreateType, nkCreateTypeIfNotExists:
  1342. s.addKeyw("create type")
  1343. if n.kind == nkCreateTypeIfNotExists:
  1344. s.addKeyw("if not exists")
  1345. ra(n.sons[0], s)
  1346. s.addKeyw("as")
  1347. ra(n.sons[1], s)
  1348. of nkCreateIndex, nkCreateIndexIfNotExists:
  1349. s.addKeyw("create index")
  1350. if n.kind == nkCreateIndexIfNotExists:
  1351. s.addKeyw("if not exists")
  1352. ra(n.sons[0], s)
  1353. s.addKeyw("on")
  1354. ra(n.sons[1], s)
  1355. s.add('(')
  1356. for i in 2..n.len-1:
  1357. if i > 2: s.add(", ")
  1358. ra(n.sons[i], s)
  1359. s.add(");")
  1360. of nkEnumDef:
  1361. s.addKeyw("enum")
  1362. rs(n, s)
  1363. proc renderSQL*(n: SqlNode, upperCase = false): string =
  1364. ## Converts an SQL abstract syntax tree to its string representation.
  1365. var s: SqlWriter
  1366. s.buffer = ""
  1367. s.upperCase = upperCase
  1368. ra(n, s)
  1369. return s.buffer
  1370. proc `$`*(n: SqlNode): string =
  1371. ## an alias for `renderSQL`.
  1372. renderSQL(n)
  1373. proc treeReprAux(s: SqlNode, level: int, result: var string) =
  1374. result.add('\n')
  1375. for i in 0 ..< level: result.add(" ")
  1376. result.add($s.kind)
  1377. if s.kind in LiteralNodes:
  1378. result.add(' ')
  1379. result.add(s.strVal)
  1380. else:
  1381. for son in s.sons:
  1382. treeReprAux(son, level + 1, result)
  1383. proc treeRepr*(s: SqlNode): string =
  1384. result = newStringOfCap(128)
  1385. treeReprAux(s, 0, result)
  1386. import streams
  1387. proc open(L: var SqlLexer, input: Stream, filename: string) =
  1388. lexbase.open(L, input)
  1389. L.filename = filename
  1390. proc open(p: var SqlParser, input: Stream, filename: string) =
  1391. ## opens the parser `p` and assigns the input stream `input` to it.
  1392. ## `filename` is only used for error messages.
  1393. open(SqlLexer(p), input, filename)
  1394. p.tok.kind = tkInvalid
  1395. p.tok.literal = ""
  1396. getTok(p)
  1397. proc parseSQL*(input: Stream, filename: string): SqlNode =
  1398. ## parses the SQL from `input` into an AST and returns the AST.
  1399. ## `filename` is only used for error messages.
  1400. ## Syntax errors raise an `SqlParseError` exception.
  1401. var p: SqlParser
  1402. open(p, input, filename)
  1403. try:
  1404. result = parse(p)
  1405. finally:
  1406. close(p)
  1407. proc parseSQL*(input: string, filename = ""): SqlNode =
  1408. ## parses the SQL from `input` into an AST and returns the AST.
  1409. ## `filename` is only used for error messages.
  1410. ## Syntax errors raise an `SqlParseError` exception.
  1411. parseSQL(newStringStream(input), "")