cl-scopes/storage/tracking.lisp

71 lines
2.4 KiB
Common Lisp

;;; cl-scopes/storage/tracking.lisp
;;;; A simple generic (SQL-based) storage for tracks, messages, and other stuff.
(defpackage :scopes/storage/tracking
(:use :common-lisp)
(:local-nicknames (:storage :scopes/storage))
(:export #:track #:time-stamp #:data
#:container
#:make-item
#:insert
#:create-indexes #:create-table))
(in-package :scopes/storage/tracking)
(defclass track ()
((head)
(time-stamp :reader time-stamp :accessor time-stamp!)
(data :accessor data :initform nil)
(container :reader container :initarg :container)))
(defclass container ()
((item-factory :initform #'(lambda (cont) (make-instance 'track :container cont)))
(head-fields :reader head-fields :initform '(taskid username))
(table-name :reader table-name :initform :tracks)
(indexes :reader indexes :initform '((taskid username) (username)))
(storage :reader storage :initarg :storage)))
(defun make-item (cont)
(funcall (slot-value cont 'item-factory) cont))
(defun insert (track)
(let* ((cont (container track))
(st (storage cont))
(table (storage:qualified-table-name st (table-name cont))))
(storage:do-sql st
(sxql:insert-into table
(sxql:set= :taskid "t01")))))
(defun create-table (cont)
(let*
((st (storage cont))
(tn (table-name cont))
(table (storage:qualified-table-name st tn))
(head-fields (head-fields cont))
(params (storage:db-params st))
(id-type (getf params :id-type))
(json-type (getf params :json-type))
(hf-def (mapcar #'(lambda (x)
(list x :type 'text :not-null t :default '|''|))
head-fields)))
(storage:do-sql st
(sxql:make-statement :create-table table
(nconc
`((trackid :type ,id-type :primary-key t :not-null t))
hf-def
`((timestamp :type timestamptz :not-null t :default current_timestamp)
(data :type ,json-type :not-null t :default |'{}'|)))))
(create-indexes st table tn (indexes cont))))
(defun create-indexes (st table tname ixs)
(let ((i 1)
(tn (symbol-name tname)))
(dolist (ix ixs)
(let ((ixname (intern (format nil "IDX_~a_~d" tn i))))
(incf i)
(storage:do-sql st
(sxql:create-index ixname :on (cons table ix)))))
(storage:do-sql st
(sxql:create-index (intern (format nil "IDX_~a_TS" tn))
:on (cons table '(timestamp))))))