activerecord-turso 0.2.1 → 0.3.0
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 +4 -4
- data/README.md +29 -9
- data/lib/active_record/connection_adapters/turso_adapter/connection_management.rb +2 -1
- data/lib/active_record/connection_adapters/turso_adapter/error_translation.rb +4 -2
- data/lib/active_record/tasks/turso_database_tasks.rb +124 -0
- data/lib/activerecord-turso/error.rb +6 -0
- data/lib/activerecord-turso/version.rb +1 -1
- data/lib/activerecord-turso.rb +6 -0
- data/lib/turso/ar/connection.rb +12 -104
- metadata +8 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cfdd23462f8313c9a19d64bab33314e3d5a4b7532249695f01811ebcf3fcccbd
|
|
4
|
+
data.tar.gz: 74e33f479629655b50621e300dc7a1d38b2d94d95edd2da9b57b3d18c5799dbe
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9dee234b1fa1abd37883de7c10b876cad339858a41643000eee969348ae0ad1da8458a8b546145aa1c7e38648e5e7da3734d35fa484b08c0d87260dc170f3fe5
|
|
7
|
+
data.tar.gz: 314bda7c65ccc415af50204690e098859517419f8f7ba035852a6230c0654c40f94a82ba3bd22ba54a829920cfb7f9159fbf1acc0de8e04816641669b6789938
|
data/README.md
CHANGED
|
@@ -4,12 +4,12 @@ ActiveRecord adapter for [Turso](https://turso.tech) (SQLite compatible db).
|
|
|
4
4
|
|
|
5
5
|
## Status
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Production ready for **embedded/local** ActiveRecord 8.1 applications using the Turso SQLite-compatible database engine. This adapter does **not** support remote `libsql://` URLs or Turso cloud authentication. The underlying `turso` gem releases the GVL during blocking operations, supports fiber-aware connection ownership, and uses native batch execution.
|
|
8
8
|
|
|
9
9
|
## Requirements
|
|
10
10
|
|
|
11
11
|
- Ruby >= 3.2
|
|
12
|
-
- ActiveRecord
|
|
12
|
+
- ActiveRecord ~> 8.1.0
|
|
13
13
|
- The `turso` Ruby gem
|
|
14
14
|
|
|
15
15
|
## Runtime dependencies
|
|
@@ -51,7 +51,9 @@ end
|
|
|
51
51
|
Post.create!(title: "Hello", body: "World", published: true)
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
##
|
|
54
|
+
## Configuration
|
|
55
|
+
|
|
56
|
+
### Recommended production configuration
|
|
55
57
|
|
|
56
58
|
```yaml
|
|
57
59
|
production:
|
|
@@ -65,6 +67,23 @@ production:
|
|
|
65
67
|
experimental_features: "index_method"
|
|
66
68
|
```
|
|
67
69
|
|
|
70
|
+
### Connection options
|
|
71
|
+
|
|
72
|
+
| Option | Description | Default |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| `database` | Path to the SQLite database file | Required |
|
|
75
|
+
| `journal_mode` | Journal mode (`wal`, `mvcc`, `delete`, etc.) | WAL |
|
|
76
|
+
| `pool` | Connection pool size | 5 |
|
|
77
|
+
| `timeout` | Busy timeout in milliseconds | 5000 |
|
|
78
|
+
| `busy_timeout` | Busy timeout in milliseconds (overrides `timeout`) | 5000 |
|
|
79
|
+
| `query_timeout` | Query timeout in milliseconds | 30000 |
|
|
80
|
+
| `experimental_features` | Comma-separated experimental features (`index_method`, `generated_columns`) | None |
|
|
81
|
+
| `statement_limit` | Maximum number of cached prepared statements | 1000 |
|
|
82
|
+
|
|
83
|
+
### `query_timeout` and `interrupt`
|
|
84
|
+
|
|
85
|
+
The adapter exposes `query_timeout=` to set a maximum execution time for queries. When a query exceeds this timeout, the Turso engine interrupts the operation and raises `ActiveRecord::QueryCanceled`. Use `interrupt` to cancel a running query from another thread.
|
|
86
|
+
|
|
68
87
|
### MVCC / BEGIN CONCURRENT (experimental)
|
|
69
88
|
|
|
70
89
|
⚠️ **Experimental.** Do not use in production unless you understand the caveats below. Normal ActiveRecord model persistence (`create!`, `save!`, `update!`, `touch`) is **not supported** inside `transaction(concurrent: true)`.
|
|
@@ -95,6 +114,7 @@ development:
|
|
|
95
114
|
- `transaction(concurrent: true)` requires the same database connection to be held for the entire retry loop. Rails' connection pool may reap the connection between retries, which can silently break MVCC semantics. Use this only when you understand the pooling behavior of your app.
|
|
96
115
|
- `lock!`, `with_lock`, and `lock_version` are not meaningful under MVCC. Do not use them inside concurrent transactions.
|
|
97
116
|
- If the retry limit is exhausted, the conflict is raised as `ActiveRecord::StatementInvalid`. You must handle it in application code.
|
|
117
|
+
- Normal ActiveRecord model persistence (`create!`, `save!`, `update!`, `touch`) is **not supported** inside a concurrent transaction because ActiveRecord opens its own internal transaction for each model change. Use raw SQL (`execute`, `exec_query`) or bulk operations (`insert_all`, `update_all`, `update_columns`) instead.
|
|
98
118
|
|
|
99
119
|
### Full-text search (Tantivy)
|
|
100
120
|
|
|
@@ -168,9 +188,9 @@ The following limitations apply to the current implementation. Read this section
|
|
|
168
188
|
|
|
169
189
|
The adapter builds column type maps from `column_decltype` metadata. This works for most column definitions but may not capture type information for computed expressions or subquery columns.
|
|
170
190
|
|
|
171
|
-
### 2. Batch SQL execution uses
|
|
191
|
+
### 2. Batch SQL execution uses the Turso native batch API
|
|
172
192
|
|
|
173
|
-
The adapter's batch execution path
|
|
193
|
+
The adapter's batch execution path uses the Turso native batch API (`execute_batch`), which correctly handles semicolons inside string literals, triggers, and stored expressions.
|
|
174
194
|
|
|
175
195
|
### 3. MVCC requires opt-in and has ActiveRecord compatibility caveats
|
|
176
196
|
|
|
@@ -187,9 +207,9 @@ Only use `transaction(concurrent: true)` after testing it under your app's concu
|
|
|
187
207
|
|
|
188
208
|
The adapter uses a bounded statement pool with a default limit inherited from Rails (typically `1000`). Statements are evicted with an LRU policy and finalized against the underlying Turso connection. Set `statement_limit` in `database.yml` to tune the pool size.
|
|
189
209
|
|
|
190
|
-
### 5. ActiveRecord 8.
|
|
210
|
+
### 5. Only ActiveRecord 8.1 is supported
|
|
191
211
|
|
|
192
|
-
|
|
212
|
+
The adapter is pinned to ActiveRecord `~> 8.1.0`.
|
|
193
213
|
|
|
194
214
|
### 6. INSERT RETURNING is disabled (not supported by Turso)
|
|
195
215
|
|
|
@@ -200,9 +220,9 @@ The underlying Turso SQLite build does not support `INSERT ... RETURNING` syntax
|
|
|
200
220
|
- Transaction isolation levels other than the default are reported as unsupported (`supports_transaction_isolation?` returns `false`) because Turso remote connections do not provide shared-cache read-uncommitted semantics.
|
|
201
221
|
- `insert_on_conflict` is enabled only when the reported SQLite version is `>= 3.24.0`.
|
|
202
222
|
|
|
203
|
-
### 8. `execute_batch`
|
|
223
|
+
### 8. `execute_batch` uses the Turso native batch API
|
|
204
224
|
|
|
205
|
-
The `turso` gem
|
|
225
|
+
The `turso` gem's `execute_batch` uses the Turso native batch API (`prepare_first`/`execute` loop), correctly handling edge cases like semicolons in string literals and triggers.
|
|
206
226
|
|
|
207
227
|
## Development
|
|
208
228
|
|
|
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
|
5
5
|
class TursoAdapter < SQLite3Adapter
|
|
6
6
|
module ErrorTranslation
|
|
7
7
|
def translate_exception(exception, message:, sql:, binds:)
|
|
8
|
-
cause = exception.cause
|
|
8
|
+
cause = exception.cause || exception
|
|
9
9
|
case cause
|
|
10
10
|
when ::Turso::ConstraintException
|
|
11
11
|
translate_constraint_error(message, sql, binds)
|
|
@@ -14,7 +14,7 @@ module ActiveRecord
|
|
|
14
14
|
when ::Turso::BusySnapshotException
|
|
15
15
|
ActiveRecord::SerializationFailure.new(message, sql: sql, binds: binds)
|
|
16
16
|
when ::Turso::BusyException
|
|
17
|
-
|
|
17
|
+
ActiveRecordTurso::BusyError.new(message, sql: sql, binds: binds)
|
|
18
18
|
when ::Turso::ReadonlyException
|
|
19
19
|
ActiveRecord::ReadOnlyRecord.new(message, sql: sql, binds: binds)
|
|
20
20
|
when ::Turso::IoException, ::Turso::CorruptException
|
|
@@ -38,6 +38,8 @@ module ActiveRecord
|
|
|
38
38
|
ActiveRecord::InvalidForeignKey.new(message, sql: sql, binds: binds)
|
|
39
39
|
when /unique constraint|primary key/i
|
|
40
40
|
ActiveRecord::RecordNotUnique.new(message, sql: sql, binds: binds)
|
|
41
|
+
when /NOT NULL|cannot be NULL/i
|
|
42
|
+
ActiveRecord::NotNullViolation.new(message, sql: sql, binds: binds)
|
|
41
43
|
else
|
|
42
44
|
ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
|
|
43
45
|
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_record/tasks/database_tasks"
|
|
4
|
+
|
|
5
|
+
module ActiveRecord
|
|
6
|
+
module Tasks
|
|
7
|
+
class TursoDatabaseTasks < SQLiteDatabaseTasks
|
|
8
|
+
def initialize(db_config, root = nil)
|
|
9
|
+
@configuration = db_config
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def create
|
|
13
|
+
path = configuration.database
|
|
14
|
+
return if path == ":memory:"
|
|
15
|
+
|
|
16
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
17
|
+
establish_connection(configuration)
|
|
18
|
+
connection.execute("SELECT 1")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def drop
|
|
22
|
+
path = configuration.database
|
|
23
|
+
return if path == ":memory:"
|
|
24
|
+
|
|
25
|
+
disconnect!
|
|
26
|
+
FileUtils.rm_f(path)
|
|
27
|
+
FileUtils.rm_f("#{path}-wal")
|
|
28
|
+
FileUtils.rm_f("#{path}-shm")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def purge
|
|
32
|
+
drop
|
|
33
|
+
create
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def charset
|
|
37
|
+
"UTF-8"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def charset_collation
|
|
41
|
+
nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def structure_dump(filename, extra_flags)
|
|
45
|
+
establish_connection(configuration)
|
|
46
|
+
io = File.open(filename, "w")
|
|
47
|
+
io.puts("PRAGMA foreign_keys = OFF;")
|
|
48
|
+
|
|
49
|
+
tables = connection.query_values(<<~SQL, "SCHEMA")
|
|
50
|
+
SELECT name FROM sqlite_master
|
|
51
|
+
WHERE type = 'table'
|
|
52
|
+
AND name NOT LIKE 'sqlite_%'
|
|
53
|
+
AND name NOT LIKE '__turso_internal_%'
|
|
54
|
+
ORDER BY name
|
|
55
|
+
SQL
|
|
56
|
+
|
|
57
|
+
tables.each do |table|
|
|
58
|
+
sql = connection.query_value(<<~SQL, "SCHEMA")
|
|
59
|
+
SELECT sql FROM sqlite_master WHERE name = #{connection.quote(table)}
|
|
60
|
+
SQL
|
|
61
|
+
io.puts("#{sql};") if sql
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
indexes = connection.query_values(<<~SQL, "SCHEMA")
|
|
65
|
+
SELECT name FROM sqlite_master
|
|
66
|
+
WHERE type = 'index'
|
|
67
|
+
AND name NOT LIKE 'sqlite_%'
|
|
68
|
+
AND sql IS NOT NULL
|
|
69
|
+
ORDER BY name
|
|
70
|
+
SQL
|
|
71
|
+
|
|
72
|
+
indexes.each do |index|
|
|
73
|
+
sql = connection.query_value(<<~SQL, "SCHEMA")
|
|
74
|
+
SELECT sql FROM sqlite_master WHERE name = #{connection.quote(index)}
|
|
75
|
+
SQL
|
|
76
|
+
io.puts("#{sql};") if sql
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
views = connection.query_values(<<~SQL, "SCHEMA")
|
|
80
|
+
SELECT name FROM sqlite_master
|
|
81
|
+
WHERE type = 'view'
|
|
82
|
+
AND name NOT LIKE 'sqlite_%'
|
|
83
|
+
ORDER BY name
|
|
84
|
+
SQL
|
|
85
|
+
|
|
86
|
+
views.each do |view|
|
|
87
|
+
sql = connection.query_value(<<~SQL, "SCHEMA")
|
|
88
|
+
SELECT sql FROM sqlite_master WHERE name = #{connection.quote(view)}
|
|
89
|
+
SQL
|
|
90
|
+
io.puts("#{sql};") if sql
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
io.puts("PRAGMA foreign_keys = ON;")
|
|
94
|
+
io.close
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def structure_load(filename, extra_flags)
|
|
98
|
+
establish_connection(configuration)
|
|
99
|
+
sql = File.read(filename)
|
|
100
|
+
ActiveRecord::Base.connection.raw_connection.execute_batch(sql)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
|
|
105
|
+
def configuration
|
|
106
|
+
@configuration
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def connection
|
|
110
|
+
ActiveRecord::Base.connection
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def establish_connection(config)
|
|
114
|
+
@configuration = config
|
|
115
|
+
ActiveRecord::Base.establish_connection(config)
|
|
116
|
+
ActiveRecord::Base.connection.connect!
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def disconnect!
|
|
120
|
+
ActiveRecord::Base.connection_pool.disconnect!
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
data/lib/activerecord-turso.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "active_record"
|
|
4
4
|
require "turso"
|
|
5
5
|
|
|
6
|
+
require_relative "activerecord-turso/error"
|
|
6
7
|
require_relative "turso/ar/connection"
|
|
7
8
|
require_relative "active_record/connection_adapters/turso_adapter"
|
|
8
9
|
|
|
@@ -11,3 +12,8 @@ ActiveRecord::ConnectionAdapters.register(
|
|
|
11
12
|
"ActiveRecord::ConnectionAdapters::TursoAdapter",
|
|
12
13
|
"active_record/connection_adapters/turso_adapter"
|
|
13
14
|
)
|
|
15
|
+
|
|
16
|
+
require "active_record/tasks/database_tasks"
|
|
17
|
+
require_relative "active_record/tasks/turso_database_tasks"
|
|
18
|
+
|
|
19
|
+
ActiveRecord::Tasks::DatabaseTasks.register_task(/turso/, "ActiveRecord::Tasks::TursoDatabaseTasks")
|
data/lib/turso/ar/connection.rb
CHANGED
|
@@ -7,7 +7,9 @@ module Turso
|
|
|
7
7
|
class Connection
|
|
8
8
|
extend Forwardable
|
|
9
9
|
|
|
10
|
-
def_delegators :@db, :close, :closed?, :changes, :total_changes
|
|
10
|
+
def_delegators :@db, :close, :closed?, :changes, :total_changes,
|
|
11
|
+
:last_insert_rowid, :prepare, :interrupt, :busy_timeout=,
|
|
12
|
+
:query_timeout, :query_timeout=
|
|
11
13
|
|
|
12
14
|
DEFAULT_BUSY_TIMEOUT_MS = 5000
|
|
13
15
|
DEFAULT_QUERY_TIMEOUT_MS = 30_000
|
|
@@ -18,12 +20,14 @@ module Turso
|
|
|
18
20
|
busy_timeout: config[:busy_timeout] || config[:timeout] || DEFAULT_BUSY_TIMEOUT_MS,
|
|
19
21
|
query_timeout: config[:query_timeout] || DEFAULT_QUERY_TIMEOUT_MS
|
|
20
22
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
if config[:experimental_features]
|
|
24
|
+
features = Array(config[:experimental_features]).map(&:to_s).reject(&:empty?)
|
|
25
|
+
db_opts[:experimental_features] = features.join(",") unless features.empty?
|
|
26
|
+
end
|
|
27
|
+
database = ::Turso::Database.new(config[:database].to_s, **db_opts)
|
|
28
|
+
@db = database.connection
|
|
29
|
+
@db.busy_timeout = db_opts[:busy_timeout]
|
|
30
|
+
@db.query_timeout = db_opts[:query_timeout]
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
def raw_connection
|
|
@@ -48,107 +52,11 @@ module Turso
|
|
|
48
52
|
end
|
|
49
53
|
|
|
50
54
|
def execute_batch(sql)
|
|
51
|
-
|
|
52
|
-
@db.execute(stmt)
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def prepare(sql)
|
|
57
|
-
@db.prepare(sql)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def busy_timeout=(ms)
|
|
61
|
-
@db.busy_timeout = ms.to_i
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def interrupt
|
|
65
|
-
@db.interrupt
|
|
55
|
+
@db.execute_batch(sql)
|
|
66
56
|
end
|
|
67
57
|
|
|
68
58
|
private
|
|
69
59
|
|
|
70
|
-
def split_batch(sql)
|
|
71
|
-
statements = []
|
|
72
|
-
current = +""
|
|
73
|
-
in_string = false
|
|
74
|
-
in_line_comment = false
|
|
75
|
-
in_block_comment = false
|
|
76
|
-
i = 0
|
|
77
|
-
while i < sql.length
|
|
78
|
-
char = sql[i]
|
|
79
|
-
next_char = sql[i + 1]
|
|
80
|
-
|
|
81
|
-
if in_line_comment
|
|
82
|
-
if char == "\n"
|
|
83
|
-
in_line_comment = false
|
|
84
|
-
end
|
|
85
|
-
i += 1
|
|
86
|
-
next
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
if in_block_comment
|
|
90
|
-
if char == "*" && next_char == "/"
|
|
91
|
-
in_block_comment = false
|
|
92
|
-
i += 2
|
|
93
|
-
else
|
|
94
|
-
i += 1
|
|
95
|
-
end
|
|
96
|
-
next
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
if in_string
|
|
100
|
-
if char == "'" && next_char == "'"
|
|
101
|
-
current << char << next_char
|
|
102
|
-
i += 2
|
|
103
|
-
next
|
|
104
|
-
elsif char == "'"
|
|
105
|
-
in_string = false
|
|
106
|
-
current << char
|
|
107
|
-
i += 1
|
|
108
|
-
next
|
|
109
|
-
end
|
|
110
|
-
current << char
|
|
111
|
-
i += 1
|
|
112
|
-
next
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
case char
|
|
116
|
-
when "'"
|
|
117
|
-
in_string = true
|
|
118
|
-
current << char
|
|
119
|
-
when "-"
|
|
120
|
-
if next_char == "-"
|
|
121
|
-
in_line_comment = true
|
|
122
|
-
i += 2
|
|
123
|
-
next
|
|
124
|
-
end
|
|
125
|
-
current << char
|
|
126
|
-
when "#"
|
|
127
|
-
in_line_comment = true
|
|
128
|
-
i += 1
|
|
129
|
-
next
|
|
130
|
-
when "/"
|
|
131
|
-
if next_char == "*"
|
|
132
|
-
in_block_comment = true
|
|
133
|
-
i += 2
|
|
134
|
-
next
|
|
135
|
-
end
|
|
136
|
-
current << char
|
|
137
|
-
when ";"
|
|
138
|
-
stmt = current.strip
|
|
139
|
-
statements << stmt unless stmt.empty?
|
|
140
|
-
current = +""
|
|
141
|
-
else
|
|
142
|
-
current << char
|
|
143
|
-
end
|
|
144
|
-
i += 1
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
stmt = current.strip
|
|
148
|
-
statements << stmt unless stmt.empty?
|
|
149
|
-
statements
|
|
150
|
-
end
|
|
151
|
-
|
|
152
60
|
def normalize_binds(binds)
|
|
153
61
|
binds.map do |value|
|
|
154
62
|
case value
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord-turso
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ben D'Angelo
|
|
@@ -13,22 +13,16 @@ dependencies:
|
|
|
13
13
|
name: activerecord
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- - "
|
|
17
|
-
- !ruby/object:Gem::Version
|
|
18
|
-
version: '8.0'
|
|
19
|
-
- - "<"
|
|
16
|
+
- - "~>"
|
|
20
17
|
- !ruby/object:Gem::Version
|
|
21
|
-
version:
|
|
18
|
+
version: 8.1.0
|
|
22
19
|
type: :runtime
|
|
23
20
|
prerelease: false
|
|
24
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
22
|
requirements:
|
|
26
|
-
- - "
|
|
27
|
-
- !ruby/object:Gem::Version
|
|
28
|
-
version: '8.0'
|
|
29
|
-
- - "<"
|
|
23
|
+
- - "~>"
|
|
30
24
|
- !ruby/object:Gem::Version
|
|
31
|
-
version:
|
|
25
|
+
version: 8.1.0
|
|
32
26
|
- !ruby/object:Gem::Dependency
|
|
33
27
|
name: turso
|
|
34
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -69,7 +63,9 @@ files:
|
|
|
69
63
|
- lib/active_record/connection_adapters/turso_adapter/schema_statements.rb
|
|
70
64
|
- lib/active_record/connection_adapters/turso_adapter/statement_pool.rb
|
|
71
65
|
- lib/active_record/connection_adapters/turso_adapter/transaction_management.rb
|
|
66
|
+
- lib/active_record/tasks/turso_database_tasks.rb
|
|
72
67
|
- lib/activerecord-turso.rb
|
|
68
|
+
- lib/activerecord-turso/error.rb
|
|
73
69
|
- lib/activerecord-turso/version.rb
|
|
74
70
|
- lib/turso/ar/connection.rb
|
|
75
71
|
licenses:
|
|
@@ -91,5 +87,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
91
87
|
requirements: []
|
|
92
88
|
rubygems_version: 4.0.15
|
|
93
89
|
specification_version: 4
|
|
94
|
-
summary: ActiveRecord adapter for Turso
|
|
90
|
+
summary: Embedded ActiveRecord adapter for Turso (SQLite-compatible)
|
|
95
91
|
test_files: []
|