activerecord-beagle-turso 0.1.2 → 0.1.4
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 954e05b945781cc01a630306c4cb5d9368ef5dcc54876269229afed57f3a56d1
|
|
4
|
+
data.tar.gz: e512726ed37adeeee5ce7fe6268d3ecda615c079a4b041cca7a1677cce9d55fd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e48728f8d4c61291db44090aab87067f31b76ef0503db34cdfcab18cb66e4d204a35b2ab7cdc3d6114ce555a49b347fdf88cc6406f5a08acb6cbc43e97d748e8
|
|
7
|
+
data.tar.gz: 70b9fb0e606a6e8e844a737d250016b800fdf21eb47e29ab3ead567821a5250ba95ff90a2e3dbaeb9283e1673624b3a8d31ed506bb0ce9e4217e5d5751e24965
|
|
@@ -126,7 +126,22 @@ module ActiveRecord
|
|
|
126
126
|
# foreign_key_check) falls through to the real driver result instead
|
|
127
127
|
# of a synthesized one -- failing loudly on a genuine future gap
|
|
128
128
|
# rather than silently lying.
|
|
129
|
-
|
|
129
|
+
#
|
|
130
|
+
# The SQL-comment allowances on both ends are load-bearing, not
|
|
131
|
+
# cosmetic: with `config.active_record.query_log_tags_enabled = true`
|
|
132
|
+
# (the Rails app-generator default for development since 7.0) every
|
|
133
|
+
# statement arrives tagged -- `PRAGMA defer_foreign_keys
|
|
134
|
+
# /*application='MyApp'*/`. An `\z`-anchored match misses that, the
|
|
135
|
+
# synthesized default never fires, and the very crash this constant
|
|
136
|
+
# exists to prevent comes back: `add_foreign_key` (and every other
|
|
137
|
+
# alter_table schema change) dies with "query failed: incomplete
|
|
138
|
+
# input" while loading db/schema.rb. Tags can be prepended as well as
|
|
139
|
+
# appended (query_log_tags_format / prepend_comment), so allow both.
|
|
140
|
+
SQL_COMMENTS = %r{(?:\s*/\*.*?\*/)*}m
|
|
141
|
+
private_constant :SQL_COMMENTS
|
|
142
|
+
|
|
143
|
+
BARE_PRAGMA_READ_REGEX =
|
|
144
|
+
/\A#{SQL_COMMENTS}\s*PRAGMA\s+(defer_foreign_keys|read_uncommitted)\s*#{SQL_COMMENTS}\s*\z/im
|
|
130
145
|
private_constant :BARE_PRAGMA_READ_REGEX
|
|
131
146
|
|
|
132
147
|
# --- execution surface used by BeagleTursoAdapter#perform_query ---
|
|
@@ -191,6 +206,82 @@ module ActiveRecord
|
|
|
191
206
|
end
|
|
192
207
|
|
|
193
208
|
private
|
|
209
|
+
# Every table-listing question Rails asks (`tables`, `views`,
|
|
210
|
+
# `data_sources`, `table_exists?`, and through them the schema cache and
|
|
211
|
+
# the schema dumper) is built from this one string in
|
|
212
|
+
# SQLite3::SchemaStatements.
|
|
213
|
+
#
|
|
214
|
+
# beagle_turso's engine keeps a `__turso_internal_seq___turso_internal_
|
|
215
|
+
# autoincrement_<table>` bookkeeping table for each AUTOINCREMENT table.
|
|
216
|
+
# They are engine internals of exactly the kind Rails already excludes
|
|
217
|
+
# by name (`sqlite_sequence`, `sqlite_schema`), but Rails cannot know
|
|
218
|
+
# about them -- so without this filter `db:schema:dump` emits one
|
|
219
|
+
# `create_table "__turso_internal_seq_..."` block per table into
|
|
220
|
+
# db/schema.rb, and the next `db:schema:load` tries to create them for
|
|
221
|
+
# real.
|
|
222
|
+
def data_source_sql(name = nil, type: nil)
|
|
223
|
+
"#{super} AND name NOT LIKE '\\_\\_turso\\_internal\\_%' ESCAPE '\\'"
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# A column definition in the DDL that carries a parenthesised type
|
|
227
|
+
# argument: `"price" decimal (10, 2) NOT NULL`, `a varchar (50)`. The
|
|
228
|
+
# name may be bare or quoted with ", ` or []; the type may be several
|
|
229
|
+
# words ("double precision"); the argument is one or two integers.
|
|
230
|
+
DECLARED_TYPE_REGEX = /
|
|
231
|
+
\A\s*
|
|
232
|
+
(?:"(?<name>[^"]*)" | `(?<name>[^`]*)` | \[(?<name>[^\]]*)\] | (?<name>\w+))
|
|
233
|
+
\s+
|
|
234
|
+
(?<type>[A-Za-z_][A-Za-z0-9_\ ]*?)
|
|
235
|
+
\s*\(\s*(?<args>\d+\s*(?:,\s*\d+)?)\s*\)
|
|
236
|
+
/x
|
|
237
|
+
private_constant :DECLARED_TYPE_REGEX
|
|
238
|
+
|
|
239
|
+
# Restore type arguments that beagle_turso's `PRAGMA table_info` drops.
|
|
240
|
+
#
|
|
241
|
+
# turso reports a column's declared type as the bare type name: a
|
|
242
|
+
# `decimal(10,2)` column comes back as `decimal`, `varchar(50)` as
|
|
243
|
+
# `varchar`, `datetime(6)` as `datetime`. Rails derives precision,
|
|
244
|
+
# scale and limit by parsing exactly that string, so all three silently
|
|
245
|
+
# become nil. Real SQLite returns the full declared type here, and the
|
|
246
|
+
# information is not lost on disk -- the CREATE TABLE in sqlite_master
|
|
247
|
+
# still says `decimal (10, 2)` -- so recover it from there.
|
|
248
|
+
#
|
|
249
|
+
# Left alone this is worse than cosmetic schema.rb churn: a dump emits
|
|
250
|
+
# `t.decimal "price"` with no precision/scale, and loading that dump
|
|
251
|
+
# builds a column whose values are no longer rounded to 2 decimal
|
|
252
|
+
# places. `super` already splits the DDL into per-column strings to
|
|
253
|
+
# recover COLLATE, AUTOINCREMENT and GENERATED ALWAYS AS for the same
|
|
254
|
+
# reason; this is the same trick for the type itself.
|
|
255
|
+
#
|
|
256
|
+
# Only fills in a missing argument -- a type that already arrived with
|
|
257
|
+
# one is left untouched, so this becomes an automatic no-op if turso
|
|
258
|
+
# starts reporting declared types in full.
|
|
259
|
+
def table_structure_with_collation(table_name, basic_structure)
|
|
260
|
+
columns = super
|
|
261
|
+
return columns unless columns.any? { |column| !column["type"].to_s.include?("(") }
|
|
262
|
+
|
|
263
|
+
declared = declared_column_types(table_name, columns.filter_map { |c| c["name"] })
|
|
264
|
+
return columns if declared.empty?
|
|
265
|
+
|
|
266
|
+
columns.each do |column|
|
|
267
|
+
next if column["type"].to_s.include?("(")
|
|
268
|
+
|
|
269
|
+
full_type = declared[column["name"]]
|
|
270
|
+
column["type"] = full_type if full_type
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# Maps column name -> declared type with its argument normalised back
|
|
275
|
+
# to Rails' own spelling (`decimal (10, 2)` -> `decimal(10,2)`), which
|
|
276
|
+
# is what Rails' precision/scale/limit extraction expects to see.
|
|
277
|
+
def declared_column_types(table_name, column_names)
|
|
278
|
+
table_structure_sql(table_name, column_names).each_with_object({}) do |column_string, declared|
|
|
279
|
+
next unless (match = DECLARED_TYPE_REGEX.match(column_string))
|
|
280
|
+
|
|
281
|
+
declared[match[:name]] = "#{match[:type]}(#{match[:args].gsub(/\s+/, '')})"
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
194
285
|
# The single seam. AbstractAdapter#raw_execute funnels every statement
|
|
195
286
|
# here and expects an ActiveRecord::Result back, with the notification
|
|
196
287
|
# payload's affected_rows/row_count filled in. cast_result (inherited)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord-beagle-turso
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- BeagleSoftwareUK
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|