-
Notifications
You must be signed in to change notification settings - Fork 51
First steps towards DB Connection #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
e32b85d
fix(sqlite3_nif): execute/2 return signature
dmitriid 17debf8
feat(connection): connection.ex skeleton module
dmitriid 650918a
feat(connection): connect + disconnect
dmitriid 2bde243
feat(connection): checkin + checkout
dmitriid 458742f
feat(connection): prepare
dmitriid 1d48cad
feat(connection): begin transaction + commit + rollback
dmitriid File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
defmodule Exqlite.Connection do | ||
|
||
@doc """ | ||
This module imlements connection details as defined in DBProtocol. | ||
|
||
Notes: | ||
- we try to closely follow structure and naming convention of myxql. | ||
- sqlite thrives when there are many small conventions, so we may not implement | ||
some strategies employed by other adapters. See https://sqlite.org/np1queryprob.html | ||
""" | ||
|
||
use DBConnection | ||
alias Exqlite.Sqlite3 | ||
alias Exqlite.Error | ||
alias Exqlite.Result | ||
|
||
defstruct [ | ||
:db | ||
] | ||
|
||
@impl true | ||
def connect(opts) do | ||
path = Keyword.get(opts, :path) | ||
|
||
case path do | ||
nil -> | ||
{:error, | ||
%Error{ | ||
message: | ||
"You must provide a :path to the database. Example: connect(path: \"./\") or connect(path: :memory)" | ||
}} | ||
|
||
_ -> | ||
do_connect(path) | ||
end | ||
end | ||
|
||
@impl true | ||
def disconnect(_reason, %__MODULE__{db: db}) do | ||
case Sqlite3.close(db) do | ||
:ok -> :ok | ||
{:error, reason} -> {:error, %Error{message: reason}} | ||
end | ||
end | ||
|
||
@impl true | ||
def checkin(state) do | ||
{:ok, state} | ||
end | ||
|
||
@impl true | ||
def checkout(state) do | ||
{:ok, state} | ||
end | ||
|
||
###---------------------------------- | ||
# handle_* implementations | ||
###---------------------------------- | ||
|
||
@impl true | ||
def handle_prepare(query, _opts, state) do | ||
# TODO: we may want to cache prepared queries like Myxql does | ||
# for now we just invoke sqlite directly | ||
case Sqlite3.prepare(state.db, query) do | ||
{:ok, statement} -> {:ok, statement, state} | ||
{:error, reason} -> %Error{message: reason} | ||
end | ||
end | ||
|
||
@doc """ | ||
Begin a transaction. | ||
|
||
For full info refer to sqlite docs: https://sqlite.org/lang_transaction.html | ||
|
||
Note: default transaction mode is DEFERRED. | ||
""" | ||
@impl true | ||
def handle_begin(opts, state) do | ||
# TODO: track nested transactions. | ||
# sqlite doesn't nest transactions with BEGIN... COMMIT..., | ||
# use the SAVEPOINT and RELEASE commands. | ||
|
||
# TODO: handle/track SAVEPOINT | ||
case Keyword.get(opts, :mode, :deferred) do | ||
:immediate -> handle_transaction(:begin, "BEGIN IMMEDIATE TRANSACTION", state) | ||
:exclusive -> handle_transaction(:begin, "BEGIN EXCLUSIVE TRANSACTION", state) | ||
mode when mode in [nil, :deferred] -> handle_transaction(:begin, "BEGIN TRANSACTION", state) | ||
end | ||
end | ||
|
||
@impl true | ||
def handle_commit(_opts, state) do | ||
# TODO: once we handle SAVEPOINT, we need to handle RELEASE | ||
# COMMIT TO | ||
# Meanwhile we just COMMIT | ||
# see https://sqlite.org/lang_transaction.html | ||
handle_transaction(:commit, "COMMIT", state) | ||
end | ||
|
||
@impl true | ||
def handle_rollback(_opts, state) do | ||
# TODO: once we handle SAVEPOINT, we need to handle ROLLBACK TO | ||
# Meanwhile we just ROLLBACK | ||
# see https://sqlite.org/lang_transaction.html | ||
handle_transaction(:rollback, "ROLLBACK", state) | ||
end | ||
|
||
###---------------------------------- | ||
# Internal functions and helpers | ||
###---------------------------------- | ||
|
||
defp do_connect(path) do | ||
case Sqlite3.open(path) do | ||
{:ok, db} -> | ||
state = %__MODULE__{ | ||
db: db | ||
} | ||
|
||
{:ok, state} | ||
|
||
{:error, reason} -> | ||
{:error, %Exqlite.Error{message: reason}} | ||
end | ||
end | ||
|
||
defp handle_transaction(call, statement, state) do | ||
case Sqlite3.execute(state.db, statement) do | ||
:ok -> | ||
result = %Result{ | ||
command: call | ||
} | ||
|
||
# TODO: if we track transactions, update state here | ||
{:ok, statement, result, state} | ||
|
||
{:error, {code, reason}} -> | ||
{:error, %Error{message: "#{reason}. Code: #{code}"}} | ||
end | ||
end | ||
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool I completely forgot about these modes for the transaction 👍🏻