activerecord-virgodb-adapter 0.1.4 → 0.1.6

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: d6376b065e29146c096491b6ce2a68e4331e806161a570b6549b068561a85f1f
4
- data.tar.gz: 1555e75fdf0c2418c1d3439fb1940f7dd284e48e28109248ffd249454b41dc55
3
+ metadata.gz: '0390e08c3ff3f57f95bce4609600461132e9af55122f1d9be076bd59171bc37d'
4
+ data.tar.gz: 216fb2576dd924f68d9e0e635824a825b0bc6863db6f3694438943343a630df3
5
5
  SHA512:
6
- metadata.gz: ab5ef2e0113e6c38295495cb10d1c2ca4bb77d135b65a636cf58aee8777146bc29795b1c7d3d2950898735a81367e2d88e3ce235a3d4f567b7e934ae8d69e885
7
- data.tar.gz: 7375e48809a1b05cc4a1ae8add6ed5e1a36d33a4564e0c711a8a8228e910e4f79d9ad039aaeccd66b839b88a4ff31640aec9e5d0f9ac246398d320b6b1224611
6
+ metadata.gz: d3bfd3b9cdad22f0385a1f9d13a84483aa26c89cc3c16f38d231f8c8885b2af9a1beac0ef7d53ee6237b87092c074026fab6370fab4b605230342a81a8c574b5
7
+ data.tar.gz: 52c0f3df23b6a21a97a6322f58d59aa2c75511c998a21ce4e3eb54d8049f674c97d1b61061f377fcd1e028832669b7573033d2a6409804ffc241749cf91492bf
@@ -72,6 +72,7 @@ module ActiveRecord
72
72
 
73
73
  def structure_dump(filename, extra_flags)
74
74
  super
75
+ strip_null_autoindex_blank_lines!(filename)
75
76
  reformat_create_table_statements!(filename)
76
77
  annotate_physical_layout!(filename)
77
78
  dump_schema_versions!(filename)
@@ -194,23 +195,69 @@ module ActiveRecord
194
195
  File.write(filename, content)
195
196
  end
196
197
 
197
- # `SQLite3Adapter#structure_dump`'s raw `SELECT sql FROM sqlite_master`
198
- # path (used whenever `ActiveRecord::SchemaDumper.ignore_tables` is
198
+ # `SQLiteDatabaseTasks#structure_dump`'s `ignore_tables`-triggered
199
+ # fallback (used whenever `ActiveRecord::SchemaDumper.ignore_tables` is
199
200
  # non-empty, e.g. excluding tables owned by a separate replication/
200
- # backup mechanism) reproduces each
201
- # CREATE TABLE exactly as ActiveRecord originally generated it --
202
- # one long line, every column crammed together. Fine for SQLite to
203
- # load back (structure_load doesn't care about whitespace), useless to
204
- # a human reading the dump next to `db/clickhouse_structure.sql`
205
- # (ClickHouse's own `SHOW CREATE TABLE` is naturally one-column-per-line,
206
- # for comparison). Purely cosmetic, safe to do unconditionally: only
207
- # rewrites the exact same statement with different whitespace, no DDL
208
- # semantics change. Skips statements that already span multiple lines
209
- # (e.g. this adapter's own hand-written `schema_versions` DDL, created
210
- # via a real newline-containing heredoc) -- nothing to reformat there.
201
+ # backup mechanism -- exactly hintpot's own litestream initializer)
202
+ # runs `SELECT sql || ';' FROM sqlite_master WHERE tbl_name NOT IN
203
+ # (...) ORDER BY tbl_name, type DESC, name` through the `sqlite3` CLI.
204
+ # Any table with a non-INTEGER (so non-rowid-alias) PRIMARY KEY --
205
+ # `maintenance_lease`, `flush_completions`, `ar_internal_metadata`,
206
+ # `schema_migrations`, all `TEXT PRIMARY KEY` -- gets a second,
207
+ # *hidden* row in `sqlite_master` for its `sqlite_autoindex_*`, whose
208
+ # `sql` column is NULL (an autoindex has no CREATE INDEX text of its
209
+ # own; SQLite generates it implicitly). `NULL || ';'` is NULL, and the
210
+ # `sqlite3` CLI's default `.nullvalue` prints a NULL result as nothing
211
+ # -- so each such table silently donates one stray blank line to the
212
+ # dump, unrelated to any table's real position or content (confirmed
213
+ # directly against a real `sqlite_master`; every non-blank-line-
214
+ # producing table here is either INTEGER PRIMARY KEY, a rowid alias
215
+ # needing no separate index, or has no primary key at all). The other
216
+ # `structure_dump` path (`.schema --nosys`, taken when
217
+ # `ignore_tables` is empty) already skips these rows itself --
218
+ # confirmed empirically too -- so this is purely a gap in the
219
+ # raw-SQL fallback, not something either path does on purpose.
220
+ # Stripping now, before `reformat_create_table_statements!` touches
221
+ # anything, means later steps never have to reason about which blank
222
+ # lines are "real" -- there aren't any yet at this point in the
223
+ # pipeline (`dump_schema_versions!`'s own deliberate ones are added
224
+ # after this runs).
225
+ def strip_null_autoindex_blank_lines!(filename)
226
+ content = File.read(filename)
227
+ content.gsub!(/\n\n+/, "\n")
228
+ File.write(filename, content)
229
+ end
230
+
231
+ # Reformats one-line CREATE TABLE statements (both `structure_dump`
232
+ # paths -- see `strip_null_autoindex_blank_lines!` above for the two --
233
+ # produce these one column crammed after another) into one column per
234
+ # line. Fine for SQLite to load back either way (structure_load
235
+ # doesn't care about whitespace), useless to a human reading the dump
236
+ # next to `db/clickhouse_structure.sql` (ClickHouse's own `SHOW CREATE
237
+ # TABLE` is naturally one-column-per-line, for comparison). Purely
238
+ # cosmetic, safe to do unconditionally: only rewrites the exact same
239
+ # statement with different whitespace, no DDL semantics change.
240
+ #
241
+ # Must handle statements that ALREADY span multiple lines, not just
242
+ # single-line ones: every virgodb-side manifest table (`crates/
243
+ # manifest/src/lib.rs`'s `maintenance_lease`, `orphaned_files`, this
244
+ # adapter's own `schema_versions`, ...) is bootstrapped from a
245
+ # multi-line, already-indented `CREATE TABLE` literal, and any column
246
+ # added to one of those later via `ALTER TABLE ... ADD COLUMN` (the
247
+ # only way SQLite can add a column to an existing table) gets its
248
+ # definition spliced into that SAME stored multi-line text, right
249
+ # before the final `)` -- with none of the original literal's
250
+ # indentation, producing exactly the lopsided
251
+ # "seven clean columns, then a cramped `, col1, col2)` tail" shape a
252
+ # single-line-only regex would silently skip over and leave raw.
253
+ # `/m` (dot matches newline) plus a non-greedy `(.*?)` is required
254
+ # together: `/m` alone with the old greedy `(.*)` would swallow every
255
+ # later `CREATE TABLE`/`CREATE INDEX` statement up to the LAST `);` in
256
+ # the file into one match, since nothing would stop it at the nearer
257
+ # one.
211
258
  def reformat_create_table_statements!(filename)
212
259
  content = File.read(filename)
213
- content.gsub!(/^CREATE TABLE (IF NOT EXISTS )?("[\w]+"|\w+) \((.*)\);$/) do
260
+ content.gsub!(/^CREATE TABLE (IF NOT EXISTS )?("[\w]+"|\w+) \((.*?)\);$/m) do
214
261
  if_not_exists = Regexp.last_match(1)
215
262
  table_name = Regexp.last_match(2)
216
263
  columns = split_top_level_commas(Regexp.last_match(3))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-virgodb-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - virgodb