doltlite 0.11.18-x86_64-darwin
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.md +8 -0
- data/README.md +46 -0
- data/lib/doltlite/database.rb +115 -0
- data/lib/doltlite/library.rb +80 -0
- data/lib/doltlite/version.rb +4 -0
- data/lib/doltlite.rb +13 -0
- data/vendor/libdoltlite/libdoltlite.dylib +0 -0
- metadata +69 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d5b871d91389729fdbcdac4ddbacc1c9b8ab546772c90b049bfe6d76a02afb15
|
|
4
|
+
data.tar.gz: a1bbf9b1d9c8ec51300833ac2d630bd916df5e8e8330881eb5e0ac0903631106
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ef8f1159a3e889537e83987282dfe17834077eea7bcd9a3268577ecfc86299ecadc5331fd7a334bd6ad6af32bbf36e5b37a957533880d46d7d0984b99901bfe9
|
|
7
|
+
data.tar.gz: c8609e2b579493735c3695dd26818a99b6d7f85199db2c35a69ee424556417c377075c4a31ff727d75f88078ab9ae74fbee19c36687d4e9bc6b24bd284b0fd95
|
data/LICENSE.md
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# doltlite (Ruby)
|
|
2
|
+
|
|
3
|
+
[DoltLite](https://github.com/dolthub/doltlite) for Ruby: SQLite with Dolt-style
|
|
4
|
+
version control — `dolt_commit`, `dolt_branch`, `dolt_merge`, `dolt_diff`, and
|
|
5
|
+
the rest. A thin [FFI](https://github.com/ffi/ffi) layer over a bundled
|
|
6
|
+
`libdoltlite`; the `dolt_*` functions are reached through SQL.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
gem install doltlite
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Precompiled gems bundle `libdoltlite` for common platforms (Linux x86_64/arm64,
|
|
15
|
+
macOS arm64/x86_64), so no compiler is needed. The plain-Ruby gem falls back to
|
|
16
|
+
a system-installed `libdoltlite`.
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
require "doltlite"
|
|
22
|
+
|
|
23
|
+
db = Doltlite.open("app.db") # or ":memory:"
|
|
24
|
+
|
|
25
|
+
db.execute("CREATE TABLE notes(id INTEGER PRIMARY KEY, body TEXT)")
|
|
26
|
+
db.execute("INSERT INTO notes(body) VALUES (?)", "first note")
|
|
27
|
+
|
|
28
|
+
hash = db.commit(message: "add first note")
|
|
29
|
+
puts "committed #{hash}"
|
|
30
|
+
|
|
31
|
+
db.query("SELECT commit_hash, message FROM dolt_log").each do |commit_hash, message|
|
|
32
|
+
puts "#{commit_hash} #{message}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
db.close
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`execute`/`query` take positional bind values (`?`) and return rows as arrays of
|
|
39
|
+
column values. The `dolt_*` functions and virtual tables (`dolt_log`,
|
|
40
|
+
`dolt_status`, `dolt_diff`, `dolt_branches`, ...) are invoked through SQL.
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
Apache-2.0. The bundled engine is built from
|
|
45
|
+
[dolthub/doltlite](https://github.com/dolthub/doltlite); SQLite itself is public
|
|
46
|
+
domain.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
module Doltlite
|
|
2
|
+
class Error < StandardError; end
|
|
3
|
+
|
|
4
|
+
# A doltlite database connection: SQLite with Dolt version control.
|
|
5
|
+
#
|
|
6
|
+
# db = Doltlite::Database.new("app.db") # or ":memory:"
|
|
7
|
+
# db.execute("CREATE TABLE t(id INTEGER PRIMARY KEY, v TEXT)")
|
|
8
|
+
# db.execute("INSERT INTO t(v) VALUES (?)", "hello")
|
|
9
|
+
# db.commit(message: "first commit")
|
|
10
|
+
# db.query("SELECT commit_hash, message FROM dolt_log")
|
|
11
|
+
class Database
|
|
12
|
+
def initialize(path = ":memory:")
|
|
13
|
+
handle_ptr = FFI::MemoryPointer.new(:pointer)
|
|
14
|
+
flags = C::OPEN_READWRITE | C::OPEN_CREATE
|
|
15
|
+
rc = C.sqlite3_open_v2(path, handle_ptr, flags, nil)
|
|
16
|
+
@handle = handle_ptr.read_pointer
|
|
17
|
+
if rc != C::OK
|
|
18
|
+
message = @handle.null? ? "unable to open #{path}" : C.sqlite3_errmsg(@handle)
|
|
19
|
+
C.sqlite3_close_v2(@handle) unless @handle.null?
|
|
20
|
+
@handle = nil
|
|
21
|
+
raise Error, "open failed (#{rc}): #{message}"
|
|
22
|
+
end
|
|
23
|
+
@open = true
|
|
24
|
+
ObjectSpace.define_finalizer(self, self.class.finalizer(@handle))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Run SQL with optional positional bind values. Returns an array of rows
|
|
28
|
+
# (each row an array of column values); empty for non-SELECT statements.
|
|
29
|
+
def execute(sql, *binds)
|
|
30
|
+
stmt_ptr = FFI::MemoryPointer.new(:pointer)
|
|
31
|
+
rc = C.sqlite3_prepare_v2(@handle, sql, -1, stmt_ptr, nil)
|
|
32
|
+
raise Error, "prepare failed: #{C.sqlite3_errmsg(@handle)}" if rc != C::OK
|
|
33
|
+
stmt = stmt_ptr.read_pointer
|
|
34
|
+
begin
|
|
35
|
+
bind_all(stmt, binds)
|
|
36
|
+
collect_rows(stmt)
|
|
37
|
+
ensure
|
|
38
|
+
C.sqlite3_finalize(stmt)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
alias query execute
|
|
42
|
+
|
|
43
|
+
# Convenience for SELECT dolt_commit(...). Stages everything when all is
|
|
44
|
+
# true. Returns the new commit hash.
|
|
45
|
+
def commit(message:, all: true)
|
|
46
|
+
args = all ? ["-A", "-m", message] : ["-m", message]
|
|
47
|
+
placeholders = (["?"] * args.length).join(", ")
|
|
48
|
+
rows = execute("SELECT dolt_commit(#{placeholders})", *args)
|
|
49
|
+
rows.dig(0, 0)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def version
|
|
53
|
+
C.sqlite3_libversion
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def close
|
|
57
|
+
return unless @open
|
|
58
|
+
C.sqlite3_close_v2(@handle)
|
|
59
|
+
@open = false
|
|
60
|
+
@handle = nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def closed?
|
|
64
|
+
!@open
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.finalizer(handle)
|
|
68
|
+
proc { C.sqlite3_close_v2(handle) unless handle.nil? || handle.null? }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def bind_all(stmt, binds)
|
|
74
|
+
binds.each_with_index do |value, i|
|
|
75
|
+
index = i + 1
|
|
76
|
+
case value
|
|
77
|
+
when nil
|
|
78
|
+
C.sqlite3_bind_null(stmt, index)
|
|
79
|
+
when Integer
|
|
80
|
+
C.sqlite3_bind_int64(stmt, index, value)
|
|
81
|
+
when Float
|
|
82
|
+
C.sqlite3_bind_double(stmt, index, value)
|
|
83
|
+
else
|
|
84
|
+
str = value.to_s
|
|
85
|
+
C.sqlite3_bind_text(stmt, index, str, str.bytesize, C::TRANSIENT)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def collect_rows(stmt)
|
|
91
|
+
rows = []
|
|
92
|
+
ncols = C.sqlite3_column_count(stmt)
|
|
93
|
+
loop do
|
|
94
|
+
rc = C.sqlite3_step(stmt)
|
|
95
|
+
break if rc == C::DONE
|
|
96
|
+
raise Error, "step failed: #{C.sqlite3_errmsg(@handle)}" if rc != C::ROW
|
|
97
|
+
rows << (0...ncols).map { |c| column_value(stmt, c) }
|
|
98
|
+
end
|
|
99
|
+
rows
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def column_value(stmt, col)
|
|
103
|
+
case C.sqlite3_column_type(stmt, col)
|
|
104
|
+
when C::INTEGER then C.sqlite3_column_int64(stmt, col)
|
|
105
|
+
when C::FLOAT then C.sqlite3_column_double(stmt, col)
|
|
106
|
+
when C::NULL then nil
|
|
107
|
+
when C::BLOB
|
|
108
|
+
n = C.sqlite3_column_bytes(stmt, col)
|
|
109
|
+
C.sqlite3_column_blob(stmt, col).read_bytes(n)
|
|
110
|
+
else
|
|
111
|
+
C.sqlite3_column_text(stmt, col)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require "ffi"
|
|
2
|
+
require "rbconfig"
|
|
3
|
+
|
|
4
|
+
module Doltlite
|
|
5
|
+
# Locates and binds the doltlite shared library. Precompiled platform gems
|
|
6
|
+
# bundle the library under vendor/libdoltlite/; otherwise we fall back to a
|
|
7
|
+
# system-installed libdoltlite on the loader path.
|
|
8
|
+
module Library
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
def library_name
|
|
12
|
+
case RbConfig::CONFIG["host_os"]
|
|
13
|
+
when /darwin/ then "libdoltlite.dylib"
|
|
14
|
+
when /mswin|mingw|cygwin/ then "doltlite.dll"
|
|
15
|
+
else "libdoltlite.so"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Path to the bundled library inside the gem, or nil if not present.
|
|
20
|
+
def bundled_path
|
|
21
|
+
path = File.expand_path("../../vendor/libdoltlite/#{library_name}", __dir__)
|
|
22
|
+
File.exist?(path) ? path : nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# What FFI should load: the bundled library if present, else the bare name
|
|
26
|
+
# so the system loader resolves an installed libdoltlite.
|
|
27
|
+
def target
|
|
28
|
+
bundled_path || library_name
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# FFI bindings to the doltlite C API (the SQLite C API; dolt_* functions are
|
|
33
|
+
# reached through SQL).
|
|
34
|
+
module C
|
|
35
|
+
extend FFI::Library
|
|
36
|
+
ffi_lib Doltlite::Library.target
|
|
37
|
+
|
|
38
|
+
# Result codes
|
|
39
|
+
OK = 0
|
|
40
|
+
ROW = 100
|
|
41
|
+
DONE = 101
|
|
42
|
+
|
|
43
|
+
# Column types
|
|
44
|
+
INTEGER = 1
|
|
45
|
+
FLOAT = 2
|
|
46
|
+
TEXT = 3
|
|
47
|
+
BLOB = 4
|
|
48
|
+
NULL = 5
|
|
49
|
+
|
|
50
|
+
# open flags
|
|
51
|
+
OPEN_READWRITE = 0x00000002
|
|
52
|
+
OPEN_CREATE = 0x00000004
|
|
53
|
+
|
|
54
|
+
# SQLITE_TRANSIENT tells the engine to copy bound buffers.
|
|
55
|
+
TRANSIENT = FFI::Pointer.new(-1)
|
|
56
|
+
|
|
57
|
+
attach_function :sqlite3_open_v2, [:string, :pointer, :int, :string], :int
|
|
58
|
+
attach_function :sqlite3_close_v2, [:pointer], :int
|
|
59
|
+
attach_function :sqlite3_errmsg, [:pointer], :string
|
|
60
|
+
attach_function :sqlite3_errcode, [:pointer], :int
|
|
61
|
+
attach_function :sqlite3_exec, [:pointer, :string, :pointer, :pointer, :pointer], :int
|
|
62
|
+
attach_function :sqlite3_prepare_v2, [:pointer, :string, :int, :pointer, :pointer], :int
|
|
63
|
+
attach_function :sqlite3_step, [:pointer], :int
|
|
64
|
+
attach_function :sqlite3_reset, [:pointer], :int
|
|
65
|
+
attach_function :sqlite3_finalize, [:pointer], :int
|
|
66
|
+
attach_function :sqlite3_column_count, [:pointer], :int
|
|
67
|
+
attach_function :sqlite3_column_name, [:pointer, :int], :string
|
|
68
|
+
attach_function :sqlite3_column_type, [:pointer, :int], :int
|
|
69
|
+
attach_function :sqlite3_column_int64, [:pointer, :int], :int64
|
|
70
|
+
attach_function :sqlite3_column_double, [:pointer, :int], :double
|
|
71
|
+
attach_function :sqlite3_column_text, [:pointer, :int], :string
|
|
72
|
+
attach_function :sqlite3_column_bytes, [:pointer, :int], :int
|
|
73
|
+
attach_function :sqlite3_column_blob, [:pointer, :int], :pointer
|
|
74
|
+
attach_function :sqlite3_bind_int64, [:pointer, :int, :int64], :int
|
|
75
|
+
attach_function :sqlite3_bind_double, [:pointer, :int, :double], :int
|
|
76
|
+
attach_function :sqlite3_bind_text, [:pointer, :int, :string, :int, :pointer], :int
|
|
77
|
+
attach_function :sqlite3_bind_null, [:pointer, :int], :int
|
|
78
|
+
attach_function :sqlite3_libversion, [], :string
|
|
79
|
+
end
|
|
80
|
+
end
|
data/lib/doltlite.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require "doltlite/version"
|
|
2
|
+
require "doltlite/library"
|
|
3
|
+
require "doltlite/database"
|
|
4
|
+
|
|
5
|
+
# DoltLite for Ruby: SQLite with Dolt-style version control (branches, commits,
|
|
6
|
+
# merge, diff). A thin FFI layer over a bundled libdoltlite; the dolt_*
|
|
7
|
+
# functions are reached through SQL.
|
|
8
|
+
module Doltlite
|
|
9
|
+
# Open (creating if needed) a database. Use ":memory:" for in-memory.
|
|
10
|
+
def self.open(path = ":memory:")
|
|
11
|
+
Database.new(path)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
Binary file
|
metadata
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: doltlite
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.11.18
|
|
5
|
+
platform: x86_64-darwin
|
|
6
|
+
authors:
|
|
7
|
+
- DoltHub, Inc.
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-06-23 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: ffi
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.15'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.15'
|
|
27
|
+
description: 'DoltLite for Ruby: a drop-in SQLite engine with Dolt version control,
|
|
28
|
+
via a thin FFI layer over a bundled libdoltlite. The dolt_* functions are reached
|
|
29
|
+
through SQL.'
|
|
30
|
+
email:
|
|
31
|
+
- support@dolthub.com
|
|
32
|
+
executables: []
|
|
33
|
+
extensions: []
|
|
34
|
+
extra_rdoc_files: []
|
|
35
|
+
files:
|
|
36
|
+
- LICENSE.md
|
|
37
|
+
- README.md
|
|
38
|
+
- lib/doltlite.rb
|
|
39
|
+
- lib/doltlite/database.rb
|
|
40
|
+
- lib/doltlite/library.rb
|
|
41
|
+
- lib/doltlite/version.rb
|
|
42
|
+
- vendor/libdoltlite/libdoltlite.dylib
|
|
43
|
+
homepage: https://github.com/dolthub/doltlite-ruby
|
|
44
|
+
licenses:
|
|
45
|
+
- Apache-2.0
|
|
46
|
+
metadata:
|
|
47
|
+
homepage_uri: https://github.com/dolthub/doltlite-ruby
|
|
48
|
+
source_code_uri: https://github.com/dolthub/doltlite-ruby
|
|
49
|
+
bug_tracker_uri: https://github.com/dolthub/doltlite/issues
|
|
50
|
+
post_install_message:
|
|
51
|
+
rdoc_options: []
|
|
52
|
+
require_paths:
|
|
53
|
+
- lib
|
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ">="
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '3.0'
|
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
|
+
requirements:
|
|
61
|
+
- - ">="
|
|
62
|
+
- !ruby/object:Gem::Version
|
|
63
|
+
version: '0'
|
|
64
|
+
requirements: []
|
|
65
|
+
rubygems_version: 3.4.19
|
|
66
|
+
signing_key:
|
|
67
|
+
specification_version: 4
|
|
68
|
+
summary: SQLite with Dolt-style version control (branches, commits, merge, diff)
|
|
69
|
+
test_files: []
|