implement self-joins

This commit is contained in:
Jeremy Penner 2022-03-26 12:24:03 -04:00
parent c25cb5d292
commit 881943ed17

View file

@ -45,32 +45,34 @@
(table.insert list value))) (table.insert list value)))
(fn Sqlog.reference-name [self analysis name] (fn Sqlog.reference-name [self analysis name]
(if (. self.rules name) (append-if-missing analysis.referenced-rules name) (if (or (. self.rules name) (. self.tables name))
(. self.tables name) (append-if-missing analysis.tables name) (do (table.insert analysis.tables name)
(length analysis.tables))
(error (.. "Unknown table / rule " name)))) (error (.. "Unknown table / rule " name))))
(fn Sqlog.reference-variable [self analysis varname name icolumn] (fn Sqlog.reference-variable [self analysis varname expr]
(match (. analysis.variable-mapping varname) (match (. analysis.variable-mapping varname)
mapping (add-clause analysis [:= mapping [:column name icolumn]]) mapping (add-clause analysis [:= mapping expr])
nil (do (tset analysis.variable-mapping varname [:column name icolumn]) nil (do (tset analysis.variable-mapping varname expr)
(table.insert analysis.variables varname)))) (table.insert analysis.variables varname))))
(fn Sqlog.analyze-literal [self analysis literal] (fn Sqlog.analyze-literal [self analysis literal]
(match literal (match literal
[:literal name params] (do (self:reference-name analysis name) [:literal name params] (let [itable (self:reference-name analysis name)]
(each [icolumn value (ipairs params)] (each [icolumn value (ipairs params)]
(match value (match value
[:var varname] (self:reference-variable analysis varname name icolumn) [:var varname] (self:reference-variable analysis varname [:column itable icolumn])
[:const val] (add-clause analysis [:= [:column name icolumn] [:const val]]) [:const val] (add-clause analysis [:= [:column itable icolumn] [:const val]])
_ (error (.. "expected var or const, got " (fv value)))))) _ (error (.. "expected var or const, got " (fv value))))))
_ (error (.. "Expected literal but got " (fv literal))))) _ (error (.. "Expected literal but got " (fv literal)))))
(fn new-analysis [] {:referenced-rules [] :variables [] :variable-mapping {} :selection [] :clauses [] :tables [] :constants []}) (fn new-analysis [] {:variables [] :variable-mapping {} :selection [] :clauses [] :tables [] :constants []})
(fn Sqlog.gen-expr [self analysis expr] (fn Sqlog.gen-expr [self analysis expr]
(match expr (match expr
[:const val] (do (table.insert analysis.constants val) "?") [:const val] (do (table.insert analysis.constants val) "?")
[:column name icolumn] (.. name "." (match (. self.tables name) [:column itable icolumn] (.. "_t" itable "."
(match (. self.tables (. analysis.tables itable))
colnames (. colnames icolumn) colnames (. colnames icolumn)
_ (.. "c" icolumn))) _ (.. "c" icolumn)))
[:as subexpr name] (.. (self:gen-expr analysis subexpr) " AS " name) [:as subexpr name] (.. (self:gen-expr analysis subexpr) " AS " name)
@ -86,7 +88,7 @@
(cat analysis.selection ", " #(self:gen-expr analysis $1)) (cat analysis.selection ", " #(self:gen-expr analysis $1))
"true") "true")
" FROM " " FROM "
(cat (lume.concat analysis.tables analysis.referenced-rules) " JOIN ") (cat analysis.tables " JOIN " #(.. $1 " AS _t" $2))
(if (> (length analysis.clauses) 0) (if (> (length analysis.clauses) 0)
(.. " WHERE " (cat analysis.clauses " AND " #(self:gen-expr analysis $1))) (.. " WHERE " (cat analysis.clauses " AND " #(self:gen-expr analysis $1)))
""))) "")))