64 lines
2.8 KiB
Fennel
64 lines
2.8 KiB
Fennel
(local Compiler (require :sqlog.compiler))
|
|
(local sqlite (require :diet-sqlite))
|
|
(local {: SQLITE_ROW} (require :diet-sqlite.codes))
|
|
|
|
(local Sqlog {})
|
|
|
|
(fn Sqlog.new [self ?dbname]
|
|
(set self.compiler (Compiler))
|
|
(set self.db (sqlite.assert (sqlite.open (or ?dbname ":memory:")))))
|
|
|
|
(fn Sqlog.deftable [self name ...] (self:execute (self.compiler:deftable name ...)))
|
|
(fn Sqlog.defrule [self head ...] (self.compiler:defrule head ...))
|
|
|
|
(fn multi? [analysis] (and analysis (> (length analysis) 0)))
|
|
(fn Sqlog.compile-sql [self analysis]
|
|
(if (multi? analysis) (each [_ a (ipairs analysis)] (self:compile-sql a))
|
|
(when (= analysis.stmt nil)
|
|
(let [stmt (sqlite.assert (sqlite.prepare self.db analysis.query))]
|
|
(sqlite.bind stmt analysis.constants)
|
|
(set analysis.stmt stmt))))
|
|
analysis)
|
|
|
|
(fn Sqlog.execute [self analysis ?collect-results]
|
|
(if (multi? analysis) (icollect [_ a (ipairs analysis)] (self:execute a ?collect-results))
|
|
(do (print "running:" analysis.query (fv analysis.constants))
|
|
(self:compile-sql analysis)
|
|
(sqlite.reset analysis.stmt)
|
|
(if ?collect-results
|
|
(let [result []]
|
|
(while (= SQLITE_ROW (sqlite.step analysis.stmt))
|
|
(table.insert result (collect [icol expr (ipairs analysis.selection)]
|
|
(match expr
|
|
[:as _ name] name
|
|
_ icol)
|
|
(sqlite.column analysis.stmt icol))))
|
|
result)
|
|
(sqlite.step analysis.stmt)))))
|
|
|
|
(fn Sqlog.compile-action [self action]
|
|
(self:compile-sql
|
|
(match action
|
|
[:do & actions] (icollect [_ act (ipairs actions)] (self:compile-action act))
|
|
[:!+ & insert] (self.compiler:insert (table.unpack insert))
|
|
[:literal] (self.compiler:insert action)
|
|
[:!- & delete] (self.compiler:delete (table.unpack delete))
|
|
[:!= & update] (self.compiler:update (table.unpack update))
|
|
_ (error (.. "No such action " (fv action))))))
|
|
|
|
(fn Sqlog.compile-query [self ...] (self:compile-sql (self.compiler:query ...)))
|
|
|
|
(fn Sqlog.specify [self action ...]
|
|
(when (not= action nil)
|
|
(match action
|
|
[:* & rule] (self:defrule (table.unpack rule))
|
|
[:table & params] (self:deftable (table.unpack (icollect [_ param (ipairs params)]
|
|
(match param [_ name] name))))
|
|
[:sql query & constants] (self:execute {: query : constants})
|
|
_ (self:execute (self:compile-action action)))
|
|
(self:specify ...)))
|
|
|
|
(fn Sqlog.query [self ...] (self:execute (self:compile-query ...) true))
|
|
|
|
(setmetatable Sqlog {:__call (fn [cls ...] (doto (setmetatable {} {:__index cls} ) (: :new ...)))})
|