All Projects β†’ fukamachi β†’ Cl Dbi

fukamachi / Cl Dbi

Database independent interface for Common Lisp

Labels

Projects that are alternatives of or similar to Cl Dbi

Docker Couchdb
🐳 Source of the official Apache CouchDB Docker image ⚠️ NOTICE ⚠️: moved to the CouchDB org
Stars: ✭ 157 (-3.09%)
Mutual labels:  database
Sdb
Simple and fast string based key-value database with support for arrays and json
Stars: ✭ 159 (-1.85%)
Mutual labels:  database
Postgres Migrations
🐦 A Stack Overflow-inspired PostgreSQL migration library with strict ordering and immutable migrations
Stars: ✭ 161 (-0.62%)
Mutual labels:  database
Opensanctions
An open database of international sanctions data, persons of interest and politically exposed persons
Stars: ✭ 157 (-3.09%)
Mutual labels:  database
Sqlservice
The missing SQLAlchemy ORM interface.
Stars: ✭ 159 (-1.85%)
Mutual labels:  database
Webtau
Webtau (short for web test automation) is a testing API, command line tool and a framework to write unit, integration and end-to-end tests. Test across REST-API, Graph QL, Browser, Database, CLI and Business Logic with consistent set of matchers and concepts. REPL mode speeds-up tests development. Rich reporting cuts down investigation time.
Stars: ✭ 156 (-3.7%)
Mutual labels:  database
Gaea
Gaea is a mysql proxy, it's developed by xiaomi b2c-dev team.
Stars: ✭ 2,123 (+1210.49%)
Mutual labels:  database
Speedment
Speedment is a Stream ORM Java Toolkit and Runtime
Stars: ✭ 1,978 (+1120.99%)
Mutual labels:  database
Eicu Code
Code and website related to the eICU Collaborative Research Database
Stars: ✭ 159 (-1.85%)
Mutual labels:  database
Doctrine Postgis
Spatial and Geographic Data with PostGIS and Doctrine.
Stars: ✭ 161 (-0.62%)
Mutual labels:  database
Pomelo.entityframeworkcore.mysql
Entity Framework Core provider for MySQL and MariaDB built on top of MySqlConnector
Stars: ✭ 2,099 (+1195.68%)
Mutual labels:  database
Db
A blazing fast ACID compliant NoSQL DataLake with support for storing 17 formats of data. Full SQL and DML capabilities along with Java stored procedures for advanced data processing.
Stars: ✭ 159 (-1.85%)
Mutual labels:  database
Dspp Keras
Protein order and disorder data for Keras, Tensor Flow and Edward frameworks with automated update cycle made for continuous learning applications.
Stars: ✭ 160 (-1.23%)
Mutual labels:  database
Filtrex
A library for performing and validating complex filters from a client (e.g. smart filters)
Stars: ✭ 157 (-3.09%)
Mutual labels:  database
Vue Materialize Datatable
A fancy Materialize CSS datatable VueJS component.
Stars: ✭ 162 (+0%)
Mutual labels:  database
Bolt
An embedded key/value database for Go.
Stars: ✭ 12,415 (+7563.58%)
Mutual labels:  database
Sqldb Logger
A logger for Go SQL database driver without modify existing *sql.DB stdlib usage.
Stars: ✭ 160 (-1.23%)
Mutual labels:  database
Vscode
Connect to MongoDB and Atlas and directly from your VS Code environment, navigate your databases and collections, inspect your schema and use playgrounds to prototype queries and aggregations.
Stars: ✭ 161 (-0.62%)
Mutual labels:  database
Crud
CRUD is Really Urgly coDed -- δΈ‡θƒ½εΏ«ι€ŸεŽŸεž‹η³»η»Ÿ
Stars: ✭ 162 (+0%)
Mutual labels:  database
Postgresdbsamples
Sample databases for postgres
Stars: ✭ 161 (-0.62%)
Mutual labels:  database

CL-DBI - Database-independent interface for Common Lisp

Build Status

Usage

Connecting - MYSQL

(defvar *connection*
  (dbi:connect :mysql
               :database-name "test"
               :username "nobody"
               :password "1234"))

Connecting - SQLite

 (defvar *connection*
  (dbi:connect :sqlite3
               :database-name "/home/gt/test.sqlite3"))

Executing a query

(let* ((query (dbi:prepare *connection*
                           "SELECT * FROM somewhere WHERE flag = ? OR updated_at > ?"))
       (query (dbi:execute query (list 0 "2011-11-01"))))
  (loop for row = (dbi:fetch query)
        while row
        ;; process "row".
        ))

;; Do it all at once
(dbi:fetch-all (dbi:execute (dbi:prepare *connection* "SELECT * FROM somewhere WHERE flag = ? OR updated_at > ?")
                            (list 0 "2011-11-01")))

dbi:do-sql is another option that prepares and executes a single statement. It returns the number of rows affected. It's typically used for non-SELECT statements.

(dbi:do-sql *connection*
            "INSERT INTO somewhere (flag, updated_at) VALUES (?, NOW())"
            (list 0))
;=> 1

Breaking change warning: cl-dbi prior to march 2020 did not pass arguments with list:

(dbi:execute query 0 "2011-11-01")
;; is now:
(dbi:execute query (list 0 "2011-11-01")

The version in Quicklisp 2020-03-25 is incompatible with older code.

Using dbi:with-connection to ensure connections are closed

(dbi:with-connection (conn :sqlite3 :database-name "/home/fukamachi/test.db")
  (let* ((query (dbi:prepare conn "SELECT * FROM People"))
         (query (dbi:execute query)))
    (loop for row = (dbi:fetch query)
          while row
          do (format t "~A~%" row))))

Connection pooling

dbi:connect-cached returns a existing connection if the database is already connected. Since one cache will be created for each thread, it's safe to use in a multithread application.

Description

CL-DBI provides a uniform interface for many SQL databases, so you need not learn a separate API for each database.

This library is especially convenient when you want to use different databases in different environments. For example, you might use MySQL as a production database, but use SQLite3 on your development system. To switch database backends you need only change the arguments to dbi:connect.

Databases

  • SQLite3
  • PostgreSQL
  • MySQL

Installation

This library is available on Quicklisp.

CL-USER> (ql:quickload :cl-dbi)
To load "cl-dbi":
  Load 1 ASDF system:
    cl-dbi
; Loading "cl-dbi"

(:CL-DBI)

API

User-Level API

  • connect [driver-name & params] => <dbi-connection>
  • connect-cached [driver-name & params] => <dbi-connection>
  • disconnect [<dbi-connection>] => T or NIL
  • prepare [conn sql] => <dbi-query>
  • prepare-cached [conn sql] => <dbi-query>
  • execute [query &optional params] => something
  • fetch [result] => a row data as plist
  • fetch-all [result] => a list of all row data
  • do-sql [conn sql &optional params]
  • list-all-drivers [] => (<dbi-driver> ..)
  • find-driver [driver-name] => <dbi-driver>
  • with-transaction [conn]
  • begin-transaction [conn]
  • commit [conn]
  • rollback [conn]
  • ping [conn] => T or NIL
  • row-count [conn] => a number of rows modified by the last executed INSERT/UPDATE/DELETE
  • with-connection [connection-variable-name &body body]

Driver-Level API

  • <dbi-driver>
  • <dbi-connection>
  • make-connection [driver params]
  • disconnect [<dbi-connection>] => T or NIL
  • prepare [conn sql] => <dbi-query>
  • prepare-cached [conn sql] => <dbi-query>
  • fetch-using-connection [conn result] => a row data as plist
  • do-sql [conn sql &optional params]
  • execute-using-connection => something
  • escape-sql => string
  • begin-transaction [conn]
  • commit [conn]
  • rollback [conn]
  • ping [conn] => T or NIL
  • row-count [conn] => a number of rows modified by the last executed INSERT/UPDATE/DELETE
  • free-query-resources [query] free resources associated with a prepared query (this is required only for sqlite3 driver at the moment)

Creating a new driver

Create a subclass of <dbi-driver> and implement following methods.

  • make-connection
  • disconnect [<dbi-connection>] => T or NIL
  • execute-using-connection

These methods can be overriden if needed.

  • prepare
  • fetch-using-connection
  • do-sql
  • escape-sql

Hook of SQL execution

CL-DBI provides dbi:*sql-execution-hooks*, a hook to run for each SQL execution, particularly used for logging.

The hook function takes these 4 values:

  • SQL (string)
  • placeholder parameters (list)
  • Row count of the results (integer or null)
  • Took time in miliseconds (integer or null)

The row count and its execution time can be null, if those values are not available for the driver for some reason.

dbi:simple-sql-logger is also provided for printing those values directly to *standard-output*. It can be enabled as so:

(push #'dbi:simple-sql-logger dbi:*sql-execution-hooks*)

Development

Running all tests in the Docker

This will not require you to install Postgres or Mysql. All you need is Docker and Docker Compose.

To run all tests, execute this in the shell:

docker-compose up tests

Running specific driver's unittests

Running tests with docker-compose does not allow you to debug code in SLIME or SLY. To do this, you need to start databases as separate containers and to make their ports available to the host machine.

Here is how you can start Postgres and Mysql in Docker and run unittests agains them:

  • Start a docker container with the database

    For example, with postgres:

    docker run --rm -ti \
           -e POSTGRES_USER=cl-dbi \
           -e POSTGRES_PASSWORD=cl-dbi \
           -p 5432:5432 \
           postgres:10
    

    Or with mysql:

    docker run --rm -ti \
           --name cl-dbi \
           -e MYSQL_ROOT_PASSWORD=cl-dbi \
           -p 3306:3306 \
           mysql:8
    
    docker exec -ti \
           cl-dbi \
           mysql -pcl-dbi \
                 -e 'create database if not exists `cl-dbi`'
    
  • Then in Lisp repl load the unittests:

    (ql:quickload :dbi/test)
    ;; Turn off colors if you are in the Emacs
    (setf rove:*enable-colors* nil)
    ;; Set this to debug failed test
    (setf rove:*debug-on-error* t)
    
  • And start driver's unittests:

    For postgres:

    (dbi.test:run-driver-tests :postgres
                               :database-name "postgres"
                               :host "localhost"
                               :port 5432
                               :username "cl-dbi"
                               :password "cl-dbi")
    

    For mysql:

    ;; Probably you will need to load library manually if
    ;; it was installed using Homebrew:
    (push "/usr/local/opt/mysql-client/lib/" cffi:*foreign-library-directories*)
    (cffi:load-foreign-library "libmysqlclient.20.dylib"
                               :search-path "/usr/local/opt/mysql-client/lib/")
    (dbi.test:run-driver-tests :mysql
                               :database-name "cl-dbi"
                               :host "127.0.0.1"
                               :port 3306
                               :username "root"
                               :password "cl-dbi")
    

    Also, you can run a single test like this:

    (dbi.test:run-driver-tests :mysql
                               :database-name "cl-dbi"
                               :host "127.0.0.1"
                               :port 3306
                               :username "root"
                               :password "cl-dbi"
                               :test-name 'select-after-commit)
    

Changelog

2020-03

  • breaking change: dbi:execute now takes its parameters as a list (to avoid the call arguments limit, see !61:
(dbi:execute query 0 "2011-11-01")
;; is now:
(dbi:execute query (list 0 "2020-03-13")

The version in Quicklisp 2020-03-25 is incompatible with older code.

Author

Copyright

Copyright (c) 2011 Eitaro Fukamachi ([email protected])

License

Licensed under the LLGPL License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].