Implement automatic identifier quoting

This commit is contained in:
Jeremy Penner 2022-04-02 22:23:01 -04:00
parent 0f31f8ea4c
commit 078e667c44

View file

@ -88,6 +88,8 @@
(let [i (if iprev (+ iprev 1) 1)]
(when (<= i max) i))))
(fn quoteid [name] (.. "\"" (name:gsub "\"" "\"\"") "\""))
(fn Compiler.new [self]
(set self.tables {})
(set self.rules {}))
@ -164,10 +166,10 @@
[:const val] (do (table.insert analysis.constants val) "?")
[:column itable icolumn] (.. "_t" itable "."
(match (. self.tables (. analysis.tables itable))
colnames (. colnames icolumn)
colnames (quoteid (. colnames icolumn))
_ (.. "c" icolumn)))
[:rowid itable] (.. "_t" itable "._rowid_")
[:as subexpr name] (.. (self:gen-expr analysis subexpr) " AS " name)
[:as subexpr name] (.. (self:gen-expr analysis subexpr) " AS " (quoteid name))
[:set column subexpr] (.. column " = " (self:gen-expr analysis subexpr))
(where [:var name] (. analysis.variable-mapping name)) (self:gen-expr analysis (. analysis.variable-mapping name))
(where [op lhs rhs] (. infix-ops op)) (.. "(" (self:gen-expr analysis lhs) " " op " " (self:gen-expr analysis rhs) ")")
@ -189,7 +191,7 @@
column-count (match rule
[[[:literal _ clauses]]] (length clauses)
_ (error (.. "Rule should be list of list of literals, was " (fv rule))))]
(.. name "(" (table.concat (icollect [i (countiter column-count)] (.. "c" i)) ", ") ") AS NOT MATERIALIZED ("
(.. (quoteid name) "(" (table.concat (icollect [i (countiter column-count)] (.. "c" i)) ", ") ") AS NOT MATERIALIZED ("
(cat rule " UNION " #(self:gen-rule-clause analysis $1)) ")")))
(fn Compiler.gen-with-rules [self analysis]
@ -210,7 +212,7 @@
(cat analysis.selection ", " #(self:gen-expr analysis $1))
"true")
(if (> (length analysis.tables) 0)
(.. " FROM " (cat analysis.tables " JOIN " #(.. $1 " AS _t" $2)))
(.. " FROM " (cat analysis.tables " JOIN " #(.. (quoteid $1) " AS _t" $2)))
"")
(if (> (length analysis.clauses) 0)
(.. " WHERE " (cat analysis.clauses " AND " #(self:gen-expr analysis $1)))
@ -219,10 +221,10 @@
(fn tail [[ _ & result]] result)
(fn Compiler.gen-update [self analysis]
"Generates an UPDATE statement for the query defined by analysis."
(.. "UPDATE " (. analysis.tables 1) " AS _t1 SET "
(.. "UPDATE " (quoteid (. analysis.tables 1)) " AS _t1 SET "
(cat analysis.selection ", " #(self:gen-expr analysis $1))
(if (>= (length analysis.tables) 2)
(.. " FROM " (cat (tail analysis.tables) " JOIN " #(.. $1 " AS _t" (+ $2 1))))
(.. " FROM " (cat (tail analysis.tables) " JOIN " #(.. (quoteid $1) " AS _t" (+ $2 1))))
"")
(if (> (length analysis.clauses) 0)
(.. " WHERE " (cat analysis.clauses " AND " #(self:gen-expr analysis $1)))
@ -248,7 +250,7 @@
[:var :_] nil
expr [:as expr (. columns icolumn)])))
(set analysis.query (.. (self:gen-with-rules analysis)
"INSERT INTO " name " (" (cat analysis.selection ", " #(match $1 [:as _ column] column)) ") "
"INSERT INTO " (quoteid name) " (" (cat analysis.selection ", " #(match $1 [:as _ column] (quoteid column))) ") "
(self:gen-select analysis)))
analysis)
_ (error (.. "Expected literal, got " (fv head)))))
@ -260,7 +262,7 @@
(let [analysis (new-analysis)]
(each [_ literal (ipairs [head ...])] (self:analyze-literal analysis literal))
(set analysis.selection [[:as [:rowid 1] :_rowid_]])
(set analysis.query (.. (self:gen-with-rules analysis) "DELETE FROM " name " WHERE _rowid_ IN (" (self:gen-select analysis) ")"))
(set analysis.query (.. (self:gen-with-rules analysis) "DELETE FROM " (quoteid name) " WHERE _rowid_ IN (" (self:gen-select analysis) ")"))
analysis)
_ (error (.. "Expected literal, got " (fv head)))))