exwiw 1.1.4 → 1.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 +4 -4
- data/AGENTS.md +24 -0
- data/CHANGELOG.md +20 -1
- data/README.md +100 -26
- data/lib/exwiw/adapter/mongodb_adapter.rb +2 -2
- data/lib/exwiw/after_insert_hook.rb +17 -7
- data/lib/exwiw/cli.rb +88 -17
- data/lib/exwiw/query_ast.rb +25 -0
- data/lib/exwiw/query_ast_builder.rb +364 -94
- data/lib/exwiw/runner.rb +1 -0
- data/lib/exwiw/table_config.rb +17 -0
- data/lib/exwiw/version.rb +1 -1
- data/lib/exwiw.rb +40 -1
- metadata +2 -1
data/lib/exwiw/runner.rb
CHANGED
data/lib/exwiw/table_config.rb
CHANGED
|
@@ -38,6 +38,9 @@ module Exwiw
|
|
|
38
38
|
# different column name on this table).
|
|
39
39
|
attribute :scope_exempt, Serdes::OptionalType.new(Serdes::ConcreteType.new(Boolean)), skip_serializing_if_nil: true
|
|
40
40
|
attribute :scope_column, optional(String), skip_serializing_if_nil: true
|
|
41
|
+
# The ID space (Exwiw::DumpTarget#ids) the `scope_column` values belong to.
|
|
42
|
+
# nil means `default`. User-configured, never generated.
|
|
43
|
+
attribute :id_space, optional(String), skip_serializing_if_nil: true
|
|
41
44
|
|
|
42
45
|
# `reverse_scope` opts a table into multi-referencer reverse scoping (see
|
|
43
46
|
# Exwiw::ReverseScope and QueryAstBuilder#build_referenced_by_clause): a
|
|
@@ -175,6 +178,7 @@ module Exwiw
|
|
|
175
178
|
merged_table.bulk_insert_chunk_size = bulk_insert_chunk_size
|
|
176
179
|
merged_table.scope_exempt = scope_exempt
|
|
177
180
|
merged_table.scope_column = scope_column
|
|
181
|
+
merged_table.id_space = id_space
|
|
178
182
|
merged_table.reverse_scope = reverse_scope
|
|
179
183
|
merged_table.batch_scope = batch_scope
|
|
180
184
|
|
|
@@ -250,6 +254,19 @@ module Exwiw
|
|
|
250
254
|
"Table '#{name}': reverse_scope.column '#{reverse_scope.column}' is not a declared column."
|
|
251
255
|
end
|
|
252
256
|
|
|
257
|
+
if id_space
|
|
258
|
+
unless id_space.match?(ID_SPACE_NAME_PATTERN)
|
|
259
|
+
raise ArgumentError,
|
|
260
|
+
"Table '#{name}': id_space '#{id_space}' must start with a lowercase letter and " \
|
|
261
|
+
"contain only lowercase letters, digits and underscores."
|
|
262
|
+
end
|
|
263
|
+
if scope_column.nil?
|
|
264
|
+
raise ArgumentError,
|
|
265
|
+
"Table '#{name}': id_space names the ID space of the scope_column values, " \
|
|
266
|
+
"so it requires scope_column."
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
253
270
|
columns.each { |column| validate_ruby_side_masking!(column) }
|
|
254
271
|
end
|
|
255
272
|
end
|
data/lib/exwiw/version.rb
CHANGED
data/lib/exwiw.rb
CHANGED
|
@@ -64,7 +64,46 @@ module Exwiw
|
|
|
64
64
|
# (`scope_column IN ids`) and tables lacking it are reached by walking
|
|
65
65
|
# belongs_to up to the nearest table that has it. When set, `table_name` is
|
|
66
66
|
# nil. SQL adapters only.
|
|
67
|
-
|
|
67
|
+
#
|
|
68
|
+
# `ids` maps an ID space name to its values. A table's `scope_column` values
|
|
69
|
+
# belong to the ID space it declares (`id_space`, `default` when omitted), so
|
|
70
|
+
# groups of tables keyed by unrelated kinds of id can be scoped in one run. An
|
|
71
|
+
# Array is taken as the values of the `default` space. Single-target mode and
|
|
72
|
+
# the mongodb adapter use the `default` space only.
|
|
73
|
+
DEFAULT_ID_SPACE = "default"
|
|
74
|
+
ID_SPACE_NAME_PATTERN = /\A[a-z][a-z0-9_]*\z/
|
|
75
|
+
|
|
76
|
+
DumpTarget = Struct.new(:table_name, :ids, :ids_field, :scope_column, keyword_init: true) do
|
|
77
|
+
def self.normalize_ids(ids)
|
|
78
|
+
case ids
|
|
79
|
+
when nil then {}
|
|
80
|
+
when Hash then ids.to_h { |space, values| [space.to_s, Array(values)] }
|
|
81
|
+
else { DEFAULT_ID_SPACE => Array(ids) }
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def initialize(**kwargs)
|
|
86
|
+
super
|
|
87
|
+
self.ids = ids
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def ids=(value)
|
|
91
|
+
self[:ids] = self.class.normalize_ids(value)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def ids_for(id_space)
|
|
95
|
+
ids.fetch(id_space, [])
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def default_ids
|
|
99
|
+
ids_for(DEFAULT_ID_SPACE)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# ID spaces other than `default` that were given, with or without values.
|
|
103
|
+
def named_id_spaces
|
|
104
|
+
ids.keys - [DEFAULT_ID_SPACE]
|
|
105
|
+
end
|
|
106
|
+
end
|
|
68
107
|
# `uri` is an optional full connection string (currently only honored by the
|
|
69
108
|
# mongodb adapter, e.g. `mongodb+srv://...`). When present it is the source of
|
|
70
109
|
# truth for the connection — host/port/user/password are ignored — so TLS,
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: exwiw
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shia
|
|
@@ -47,6 +47,7 @@ extensions:
|
|
|
47
47
|
- ext/exwiw/ext_json/extconf.rb
|
|
48
48
|
extra_rdoc_files: []
|
|
49
49
|
files:
|
|
50
|
+
- AGENTS.md
|
|
50
51
|
- CHANGELOG.md
|
|
51
52
|
- LICENSE.txt
|
|
52
53
|
- README.md
|