db.lisp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. (in-package #:chatikbot)
  2. (defvar *db-name* "db.sqlite" "SQLite database name")
  3. (defun db-path ()
  4. (merge-pathnames *db-name*
  5. (asdf:component-pathname
  6. (asdf:find-system '#:chatikbot))))
  7. (defun db-init ()
  8. (unless (probe-file (db-path))
  9. (sqlite:with-open-database (db (db-path))
  10. (sqlite:execute-non-query db "create table finance (ts, usd, eur, gbp, brent)")
  11. (sqlite:execute-non-query db "create index fin_ts_ids on finance (ts)"))))
  12. (defun db-add-finance (ts usd eur gbp brent)
  13. (sqlite:with-open-database (db (db-path) :busy-timeout 10)
  14. (sqlite:execute-non-query db "insert into finance (ts, usd, eur, gbp, brent) values (?, ?, ?, ?, ?)"
  15. ts usd eur gbp brent)))
  16. (defun db-get-last-finance ()
  17. (sqlite:with-open-database (db (db-path) :busy-timeout 10)
  18. (sqlite:execute-one-row-m-v db "select ts, usd, eur, gbp, brent from finance order by ts desc limit 1")))
  19. (defun %finance-alist (statement)
  20. (let ((names (sqlite:statement-column-names statement))
  21. (map '(("usd" . "USD/RUB") ("eur" . "EUR/RUB") ("gbp" . "GBP/RUB") ("brent" . "Brent"))))
  22. (cons (sqlite:statement-column-value statement 0)
  23. (loop
  24. for i from 1 below (length names)
  25. for col in (rest names)
  26. collect (cons (aget col map) (sqlite:statement-column-value statement i))))))
  27. (defun db-get-series (after-ts &optional usd eur gbp brent (avg 60))
  28. (let ((sql (format nil
  29. "select ts/~a*~a~:[~;,avg(usd) as usd~]~:[~;,avg(eur) as eur~]~:[~;,avg(gbp) as gbp~]~:[~;,avg(brent) as brent~] from finance where ts >= ? group by ts/~a order by ts"
  30. avg avg usd eur gbp brent avg)))
  31. (sqlite:with-open-database (db (db-path) :busy-timeout 10)
  32. (loop
  33. with statement = (sqlite:prepare-statement db sql)
  34. initially (sqlite:bind-parameter statement 1 (local-time:timestamp-to-unix after-ts))
  35. while (sqlite:step-statement statement)
  36. collect (%finance-alist statement)
  37. finally (sqlite:finalize-statement statement)))))