;;; cl-scopes/storage/storage.lisp ;;;; Common layer for SQL storage functionality. (defpackage :scopes/storage (:use :common-lisp) (:export #:*db-config* #:make-engine #:make-storage #:db-params #:do-sql #:drop-table)) (in-package :scopes/storage) (defparameter *db-config* nil) (defvar *backends* '(:dbi dbi-make-engine)) (defvar *db-params* '(:sqlite3 (:id-type integer :json-type json) :postgres (:id-type bigserial :json-type jsonb))) (defclass db-engine () ((connect :initarg :connect) (params :initarg :params) (config :initarg :config))) (defun make-engine () (let ((backend (getf *db-config* :backend))) (funcall (getf *backends* backend) *db-config*))) (defclass storage () ((engine :initarg :engine) (conn :reader conn) (schema))) (defun make-storage (engine) (let ((st (make-instance 'storage :engine engine)) (conn (funcall (slot-value engine 'connect)))) (setf (slot-value st 'conn) conn) st)) (defun db-params (st) (slot-value (slot-value st 'engine) 'params)) (defun do-sql (st spec) (let ((sql (sxql:yield spec))) (print sql) (dbi:do-sql (conn st) sql))) (defun drop-table (st tn) (do-sql st (sxql:drop-table tn :if-exists t))) ;;; backend-/driver-specific stuff (defun dbi-make-engine (config) (let* ((db-type (getf config :db-type)) (params (getf *db-params* db-type)) (conn-args (getf config :connect-args))) (make-instance 'db-engine :params params :config config :connect #'(lambda () (apply #'dbi:connect-cached db-type conn-args)))))