{"id":17964804,"url":"https://github.com/dbi-beam/dbi","last_synced_at":"2025-03-25T06:31:02.664Z","repository":{"id":16624285,"uuid":"19379329","full_name":"dbi-beam/dbi","owner":"dbi-beam","description":"Erlang and Elixir DataBase Interface","archived":false,"fork":false,"pushed_at":"2018-08-17T09:26:16.000Z","size":972,"stargazers_count":16,"open_issues_count":5,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-19T09:40:42.579Z","etag":null,"topics":["database-connection","dbi","elixir","erlang","library","mysql-client","postgresql-client","sqlite"],"latest_commit_sha":null,"homepage":"","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dbi-beam.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-05-02T15:24:53.000Z","updated_at":"2024-01-24T08:44:57.000Z","dependencies_parsed_at":"2022-07-26T13:48:11.282Z","dependency_job_id":null,"html_url":"https://github.com/dbi-beam/dbi","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbi-beam%2Fdbi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbi-beam%2Fdbi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbi-beam%2Fdbi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbi-beam%2Fdbi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dbi-beam","download_url":"https://codeload.github.com/dbi-beam/dbi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245413597,"owners_count":20611350,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database-connection","dbi","elixir","erlang","library","mysql-client","postgresql-client","sqlite"],"created_at":"2024-10-29T12:08:47.146Z","updated_at":"2025-03-25T06:31:02.341Z","avatar_url":"https://github.com/dbi-beam.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"DBI for Erlang\n==============\n\n[![Build Status](https://api.travis-ci.org/altenwald/dbi.png)](https://travis-ci.org/altenwald/dbi)\n[![Codecov](https://img.shields.io/codecov/c/github/altenwald/dbi.svg)](https://codecov.io/gh/altenwald/dbi)\n[![License: LGPL 2.1](https://img.shields.io/badge/License-GNU%20Lesser%20General%20Public%20License%20v2.1-blue.svg)](https://raw.githubusercontent.com/altenwald/dbi/master/COPYING)\n[![Hex](https://img.shields.io/hexpm/v/dbi.svg)](https://hex.pm/packages/dbi)\n\nDatabase Interface for Erlang and Elixir. This is an abstract implementation to use the most common database libraries ([p1_mysql][1], [epgsql][2] and [esqlite][4], and others you want) to use with standard SQL in your programs and don't worry about if you need to change between the main databases in the market.\n\n**IMPORTANT** Note that you'll need to include one (or several) of the other dependencies in the (DBI-BEAM)(https://github.com/dbi-beam) group to use SQLite, MySQL, PostgreSQL or other database supported.\n\n### Install (rebar3)\n\nTo use it, with rebar, you only need to add the dependency to the rebar.config file:\n\n```erlang\n{deps, [\n    {dbi, \"1.1.0\"}\n]}\n```\n\n### Install (mix)\n\nTo use it, with mix, you only need to add the dependency to the mix.exs file:\n\n```elixir\n{:dbi, \"~\u003e 1.1.0\"}\n```\n\n### Configuration\n\nThe configuration is made in the configuration file (`sys.config` or `app.config`) so, you can add a new block for config the database connection as follow:\n\n```erlang\n{dbi, [\n    {mydatabase, [\n        {type, mysql},\n        {host, \"localhost\"},\n        {user, \"root\"},\n        {pass, \"root\"},\n        {database, \"mydatabase\"},\n        {poolsize, 10}\n    ]},\n    {mylocaldb, [\n        {type, sqlite},\n        {database, \":memory:\"}\n    ]},\n    {mystrongdb, [\n        {type, pgsql},\n        {host, \"localhost\"},\n        {user, \"root\"},\n        {pass, \"root\"},\n        {database, \"mystrongdb\"},\n        {poolsize, 100}\n    ]}\n]}\n```\n\nThe available types in this moment are: `mysql`, `pgsql` and `sqlite`.\n\nIn case you're using Elixir, you can define the configuration for your project in this way:\n\n```elixir\nconfg :dbi, mydatabase: [\n              type: :mysql,\n              host: 'localhost',\n              user: 'root',\n              pass: 'root',\n              database: 'mydatabase',\n              poolsize: 10\n            ],\n            mylocaldb: [\n              type: :sqlite,\n              database: ':memory'\n            ],\n            mystrongdb: [\n              type: :pgsql,\n              host: 'localhost',\n              user: 'root',\n              pass: 'root',\n              database: 'mystrongdb',\n              poolsize: 100\n            ]\n```\n\n### Using DBI\n\nTo do a query (Erlang):\n\n```erlang\n{ok, Count, Rows} = dbi:do_query(mydatabase, \"SELECT * FROM users\", []),\n```\n\nElixir:\n\n```elixir\n{:ok, count, rows} = DBI.do_query(:mydatabase, \"SELECT * FROM users\", [])\n```\n\nOr with params (Erlang):\n\n```erlang\n{ok, Count, Rows} = dbi:do_query(mydatabase,\n    \"SELECT * FROM users WHERE id = $1\", [12]),\n```\n\nElixir:\n\n```elixir\n{:ok, count, rows} = DBI.do_query(:mydatabase,\n    \"SELECT * FROM users WHERE id = $1\", [12])\n```\n\nRows has the format: `[{field1, field2, ..., fieldN}, ...]`\n\n**IMPORTANT** the use of $1..$100 in the query is extracted from pgsql, in mysql and sqlite is converted to the `?` syntax so, if you write this query:\n\n```erlang\n{ok, Count, Rows} = dbi:do_query(mydatabase,\n    \"UPDATE users SET name = $2 WHERE id = $1\", [12, \"Mike\"]),\n```\n\nElixir:\n\n```elixir\n{:ok, count, rows} = DBI.do_query(:mydatabase,\n    \"UPDATE users SET name = $2 WHERE id = $1\", [12, \"Mike\"])\n```\n\nThat should works well in pgsql, but **NOT for mysql and NOT for sqlite**. For avoid this situations, the best to do is **always keep the order of the params**.\n\n### Delayed or Queued queries\n\nIf you want to create a connection to send only commands like INSERT, UPDATE or DELETE but without saturate the database (and run out database connections in the pool) you can use `dbi_delayed` (Erlang):\n\n```erlang\n{ok, PID} = dbi_delayed:start_link(delay_myconn, myconn),\ndbi_delayed:do_query(delay_myconn,\n    \"INSERT INTO my tab VALUES ($1, $2)\", [N1, N2]),\n```\n\nElixir:\n\n```elixir\n{:ok, pid} = DBI.Delayed.start_link(:delay_myconn, :myconn)\nDBI.Delayed.do_query(:delay_myconn,\n    \"INSERT INTO my tab VALUES ($1, $2)\", [n1, n2])\n```\n\nThis use only one connection from the pool `myconn`, when the query ends then `dbi_delayed` gets another query to run from the queue. You get statistics about the progress and the queue size (Erlang):\n\n```erlang\ndbi_delayed:stats(delay_myconn).\n[\n    {size, 0},\n    {query_error, 0},\n    {query_ok, 1}\n]\n```\n\nElixir:\n\n```elixir\nDBI.Delayed.stats(:delay_myconn)\n[\n    size: 0,\n    query_error: 0,\n    query_ok: 1\n]\n```\n\nThe delayed can be added to the configuration:\n\n```erlang\n{dbi, [\n    {mydatabase, [\n        {type, mysql},\n        {host, \"localhost\"},\n        {user, \"root\"},\n        {pass, \"root\"},\n        {database, \"mydatabase\"},\n        {poolsize, 10},\n        {delayed, delay_myconn}\n    ]}\n]}\n```\n\nElixir:\n\n```elixir\nconfig :dbi, mydatabase: [\n               type: :mysql,\n               host: 'localhost',\n               user: 'root',\n               pass: 'root',\n               database: 'mydatabase',\n               poolsize: 10,\n               delayed: :delay_myconn\n             ]\n```\n\n### Cache queries\n\nAnother thing you can do is use a cache for SQL queries. The cache store the SQL as `key` and the result as `value` and keep the values for the time you specify in the configuration file:\n\n```erlang\n{dbi, [\n    {mydatabase, [\n        {type, mysql},\n        {host, \"localhost\"},\n        {user, \"root\"},\n        {pass, \"root\"},\n        {database, \"mydatabase\"},\n        {poolsize, 10},\n        {cache, 5}\n    ]}\n]}\n```\n\nElixir:\n\n```elixir\nconfig :dbi, mydatabase: [\n               type: :mysql,\n               host: 'localhost',\n               user: 'root',\n               pass: 'root',\n               database: 'mydatabase',\n               poolsize: 10,\n               cache: 5\n             ]\n```\n\nThe cache param is in seconds. The ideal time to keep the cache values depends on the size of your tables, the data to store in the cache and how frequent are the changes in that data. For avoid flood and other issues due to fast queries or a lot of queries in little time you can use 5 or 10 seconds. To store the information about constants or other data without frequent changes you can use 3600 (one hour) or more time.\n\nTo use the cache you should to use the following function from `dbi_cache`:\n\n```erlang\ndbi_cache:do_query(mydatabase, \"SELECT items FROM table\"),\n```\n\nElixir:\n\n```elixir\nDBI.Cache.do_query(:mydatabase, \"SELECT items FROM table\")\n```\n\nYou can use `do_query/2` or `do_query/3` if you want to use params. And if you want to use a specific TTL (time-to-live) for your query, you can use `do_query/4`:\n\n```erlang\ndbi_cache:do_query(mydatabase,\n    \"SELECT items FROM table\", [], 3600),\n```\n\nElixir:\n\n```elixir\nDBI.Cache.do_query(:mydatabase,\n    \"SELECT items FROM table\", [], 3600)\n```\n\n### Migrations\n\nYou can add a configuration for each connection to configure migrations for a specific application:\n\n```erlang\n{dbi, [\n    {mydatabase, [\n        {type, mysql},\n        {host, \"localhost\"},\n        {user, \"root\"},\n        {pass, \"root\"},\n        {database, \"mydatabase\"},\n        {poolsize, 10},\n        {migrations, myapp}\n    ]}\n]},\n```\n\nFor your application you'll need to create the path `priv/migrations` and locate there the files. The files must to have the format: `code_description_create.sql`. It's mandatory to have the code (it's recomended an incremental code like 001, 002, and so on) and the suffix `_create`. The extension must to be `sql`.\n\nThe content of the file is a plain SQL file with the following format:\n\n```sql\n-- :create_users_table\nCREATE TABLE users (\n    id serial primary key not null,\n    name varchar\n);\n```\n\nThe table `schema_migrations` will be created then to store the migrations applied to avoid to apply them twice.\n\n### Fixtures\n\nWhen you're testing your software and using a real database connection you'll need to insert some specific data in a easy way. Fixtures is a mechanism to do it. You only need to format the data in the following way:\n\n```erlang\nData = [{users,\n         [\"id\", \"name\", \"surname\"],\n         [{1, \u003c\u003c\"Manuel\"\u003e\u003e, \u003c\u003c\"Rubio\"\u003e\u003e},\n          {2, \u003c\u003c\"Marga\"\u003e\u003e, \u003c\u003c\"Ortiz\"\u003e\u003e}]}].\n```\n\nThis will auto-generate `INSERT` queries to the table `users` with the name of the columns (id, name, surname) and the columns.\n\nYou can run this as:\n\n```erlang\ndbi_fixtures:populate(my_connection, Data)\n```\n\n**IMPORTANT** The only restriction is the first column has to be an ID (numeric one). The system will call to `dbi:update_seq/3` when the data is inserted to update the ID to the last ID inserted.\n\nEnjoy!\n\n[1]: https://github.com/processone/p1_mysql\n[2]: https://github.com/wg/epgsql\n[4]: https://github.com/mmzeeman/esqlite\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbi-beam%2Fdbi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdbi-beam%2Fdbi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbi-beam%2Fdbi/lists"}