activefacts-compositions 1.9.17 → 1.9.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/activefacts-compositions.gemspec +2 -2
- data/lib/activefacts/compositions/binary.rb +1 -1
- data/lib/activefacts/compositions/compositor.rb +16 -12
- data/lib/activefacts/compositions/datavault.rb +110 -115
- data/lib/activefacts/compositions/relational.rb +137 -94
- data/lib/activefacts/compositions/staging.rb +89 -27
- data/lib/activefacts/compositions/traits/datavault.rb +116 -49
- data/lib/activefacts/compositions/traits/rails.rb +2 -2
- data/lib/activefacts/compositions/version.rb +1 -1
- data/lib/activefacts/generator/doc/cwm.rb +6 -18
- data/lib/activefacts/generator/doc/ldm.rb +1 -1
- data/lib/activefacts/generator/etl/unidex.rb +341 -0
- data/lib/activefacts/generator/oo.rb +31 -14
- data/lib/activefacts/generator/rails/models.rb +6 -5
- data/lib/activefacts/generator/rails/schema.rb +5 -9
- data/lib/activefacts/generator/ruby.rb +2 -2
- data/lib/activefacts/generator/sql/mysql.rb +3 -184
- data/lib/activefacts/generator/sql/oracle.rb +3 -152
- data/lib/activefacts/generator/sql/postgres.rb +3 -145
- data/lib/activefacts/generator/sql/server.rb +3 -126
- data/lib/activefacts/generator/sql.rb +54 -422
- data/lib/activefacts/generator/summary.rb +15 -6
- data/lib/activefacts/generator/traits/expr.rb +41 -0
- data/lib/activefacts/generator/traits/sql/mysql.rb +280 -0
- data/lib/activefacts/generator/traits/sql/oracle.rb +265 -0
- data/lib/activefacts/generator/traits/sql/postgres.rb +287 -0
- data/lib/activefacts/generator/traits/sql/server.rb +262 -0
- data/lib/activefacts/generator/traits/sql.rb +538 -0
- metadata +13 -8
- data/lib/activefacts/compositions/docgraph.rb +0 -798
- data/lib/activefacts/compositions/staging/persistent.rb +0 -107
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9264168bcd4294c87277a11fde73ba06c0e490e6
|
4
|
+
data.tar.gz: 40f2da7b5f7a72066b13ed7bc2de790e3717af82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ecb7fb4562dbe1e8bef8924abc26a19c2aa4816eca5d09fd609b34a060acd11bef1d72642fe32ef631a5af2c1bd82bc968fbe8c48d386c0f409d41aba624c5bc
|
7
|
+
data.tar.gz: 46e7e8d45dadc6154867d2ce6ccd605bbcd897ab86f063481b8680b0fec4284ccd529edbd38fa86cabadeaad1584e82090fd89fc3f3a430da6dce47d61950106
|
@@ -29,6 +29,6 @@ Gem::Specification.new do |spec|
|
|
29
29
|
|
30
30
|
spec.add_development_dependency "activefacts", "~> 1", ">= 1.8"
|
31
31
|
spec.add_runtime_dependency "activefacts-api", "~> 1", ">= 1.9.11"
|
32
|
-
spec.add_runtime_dependency "activefacts-metamodel", "~> 1", ">= 1.9.
|
33
|
-
spec.add_runtime_dependency "activefacts-cql", "~> 1", ">= 1.9.
|
32
|
+
spec.add_runtime_dependency "activefacts-metamodel", "~> 1", ">= 1.9.22"
|
33
|
+
spec.add_runtime_dependency "activefacts-cql", "~> 1", ">= 1.9.5"
|
34
34
|
end
|
@@ -6,6 +6,8 @@
|
|
6
6
|
# The term "reference" used here means either an Absorption
|
7
7
|
# (one direction of a binary fact type relating two object types),
|
8
8
|
# or an Indicator (for a unary fact type).
|
9
|
+
# Later processes may create references for bare Mappings,
|
10
|
+
# or may replace several Indicators by a Discriminator.
|
9
11
|
#
|
10
12
|
# n-ary fact types and other objectified fact types are factored out by using the associated LinkFactTypes.
|
11
13
|
#
|
@@ -48,11 +50,12 @@ module ActiveFacts
|
|
48
50
|
end
|
49
51
|
|
50
52
|
def populate_reference role
|
51
|
-
|
53
|
+
component = (@reference_populated ||= {})[role]
|
54
|
+
return component if component
|
52
55
|
@reference_populated[role] = true
|
53
56
|
|
54
57
|
parent = @binary_mappings[role.object_type]
|
55
|
-
return if role.fact_type.all_role.size > 2
|
58
|
+
return nil if role.fact_type.all_role.size > 2
|
56
59
|
if role.fact_type.all_role.size != 1
|
57
60
|
counterpart = role.counterpart
|
58
61
|
rt = role_type(counterpart)
|
@@ -60,7 +63,7 @@ module ActiveFacts
|
|
60
63
|
raise "Fact type must be objectified: #{role.fact_type.default_reading}"
|
61
64
|
end
|
62
65
|
|
63
|
-
|
66
|
+
component = @constellation.Absorption(
|
64
67
|
:new,
|
65
68
|
name: role_name(counterpart),
|
66
69
|
parent: parent,
|
@@ -68,29 +71,30 @@ module ActiveFacts
|
|
68
71
|
parent_role: role,
|
69
72
|
child_role: counterpart
|
70
73
|
)
|
71
|
-
# Populate the absorption/
|
74
|
+
# Populate the absorption/reverse_mapping (putting the "many" or optional side as reverse)
|
72
75
|
if r = @component_by_fact[role.fact_type]
|
73
76
|
# Second occurrence of this fact type, set the direction:
|
74
|
-
if
|
75
|
-
|
77
|
+
if component.is_preferred_direction
|
78
|
+
component.reverse_mapping = r
|
76
79
|
else # Set this as the reverse absorption
|
77
|
-
|
80
|
+
component.forward_mapping = r
|
78
81
|
end
|
79
82
|
else
|
80
83
|
# First occurrence of this fact type
|
81
|
-
@component_by_fact[role.fact_type] =
|
84
|
+
@component_by_fact[role.fact_type] = component
|
82
85
|
end
|
83
86
|
else # It's an indicator
|
84
|
-
|
87
|
+
component = @constellation.Indicator(
|
85
88
|
:new,
|
86
89
|
name: role.name,
|
87
90
|
parent: parent,
|
88
91
|
role: role
|
89
92
|
)
|
90
|
-
@component_by_fact[role.fact_type] =
|
93
|
+
@component_by_fact[role.fact_type] = component # For completeness, in case a subclass uses it
|
91
94
|
end
|
92
|
-
@reference_populated[role] =
|
93
|
-
trace :binarize, "
|
95
|
+
@reference_populated[role] = component
|
96
|
+
trace :binarize, "Populated #{component.inspect}"
|
97
|
+
component
|
94
98
|
end
|
95
99
|
|
96
100
|
private
|
@@ -16,7 +16,7 @@ module ActiveFacts
|
|
16
16
|
|
17
17
|
BDV_ANNOTATIONS = /same as link|hierarchy link|computed link|exploration link|computed satellite|point in time|bridge/
|
18
18
|
BDV_LINK_ANNOTATIONS = /same as link|hierarchy link|computed link|exploration link/
|
19
|
-
BDV_SAT_ANNOTATIONS = /computed satellite/
|
19
|
+
BDV_SAT_ANNOTATIONS = /computed satellite/ # Not used yet
|
20
20
|
BDV_PIT_ANNOTATIONS = /point in time/
|
21
21
|
BDV_BRIDGE_ANNOTATIONS = /bridge/
|
22
22
|
|
@@ -25,7 +25,7 @@ module ActiveFacts
|
|
25
25
|
datavault_options.
|
26
26
|
merge({
|
27
27
|
reference: ['Boolean', "Emit the reference (static) tables as well. Default is to omit them"],
|
28
|
-
id: ['String', "Append this to data vault surrogate
|
28
|
+
id: ['String', "Append this to data vault surrogate key names (default HID)"],
|
29
29
|
hubname: ['String', "Suffix or pattern for naming hub tables. Include a + to insert the name. Default 'HUB'"],
|
30
30
|
linkname: ['String', "Suffix or pattern for naming link tables. Include a + to insert the name. Default 'LINK'"],
|
31
31
|
satname: ['String', "Suffix or pattern for naming satellite tables. Include a + to insert the name. Default 'SAT'"],
|
@@ -34,14 +34,18 @@ module ActiveFacts
|
|
34
34
|
refname: ['String', "Suffix or pattern for naming reference tables. Include a + to insert the name. Default '+'"],
|
35
35
|
}).
|
36
36
|
merge(Relational.options).
|
37
|
-
reject{|k,v| [:surrogates].include?(k) } # Datavault surrogates are not optional
|
37
|
+
reject{|k,v| [:fk, :surrogates].include?(k) }. # Datavault surrogates are not optional
|
38
|
+
merge({
|
39
|
+
fk: [%w{hash}, "Enforce foreign keys using a hash of the natural keys (ala Data Vault 2)"],
|
40
|
+
})
|
38
41
|
end
|
39
42
|
|
40
43
|
def initialize constellation, name, options = {}
|
41
44
|
# Extract recognised options:
|
42
45
|
datavault_initialize options
|
46
|
+
|
43
47
|
@option_reference = options.delete('reference')
|
44
|
-
@option_id = ' ' + (options.delete('id') || 'HID')
|
48
|
+
@option_id = '+ ' + (options.delete('id') || 'HID')
|
45
49
|
@option_hub_name = options.delete('hubname') || 'HUB'
|
46
50
|
@option_hub_name.sub!(/^/,'+ ') unless @option_hub_name =~ /\+/
|
47
51
|
@option_link_name = options.delete('linkname') || 'LINK'
|
@@ -60,10 +64,8 @@ module ActiveFacts
|
|
60
64
|
@option_surrogates = true # Always inject surrogates regardless of superclass
|
61
65
|
end
|
62
66
|
|
63
|
-
|
64
|
-
|
65
|
-
classify_composites
|
66
|
-
|
67
|
+
def generate
|
68
|
+
create_loadbatch if @option_audit == 'batch'
|
67
69
|
super
|
68
70
|
end
|
69
71
|
|
@@ -94,8 +96,14 @@ module ActiveFacts
|
|
94
96
|
super
|
95
97
|
end
|
96
98
|
|
99
|
+
def inject_surrogates
|
100
|
+
# We need to find links that need surrogate keys before we inject the surrogates
|
101
|
+
classify_composites
|
102
|
+
super
|
103
|
+
end
|
104
|
+
|
97
105
|
# Change the default extension from our superclass':
|
98
|
-
def inject_surrogate composite,
|
106
|
+
def inject_surrogate composite, name_pattern = @option_id
|
99
107
|
super
|
100
108
|
end
|
101
109
|
|
@@ -202,7 +210,7 @@ module ActiveFacts
|
|
202
210
|
mapped_to =
|
203
211
|
composite_key_structure composite
|
204
212
|
|
205
|
-
# It's a Link if the preferred identifier includes more than non_reference_composite.
|
213
|
+
# It's a Link if the preferred identifier includes more than one non_reference_composite.
|
206
214
|
mapped_to.compact.size > 1
|
207
215
|
end
|
208
216
|
end
|
@@ -250,7 +258,7 @@ module ActiveFacts
|
|
250
258
|
end
|
251
259
|
|
252
260
|
def detect_reference_tables
|
253
|
-
initial_composites = @composition.all_composite.
|
261
|
+
initial_composites = @composition.all_composite.select{|c| c != loadbatch_composite }
|
254
262
|
@reference_composites, @non_reference_composites =
|
255
263
|
initial_composites.partition { |composite| composite_is_reference(composite) }
|
256
264
|
end
|
@@ -299,14 +307,16 @@ module ActiveFacts
|
|
299
307
|
# For each hub and link, move each non-identifying member
|
300
308
|
# to a new satellite or promote it to a new link.
|
301
309
|
(@hub_composites + @link_composites).each do |composite|
|
302
|
-
|
310
|
+
split_satellites_from composite
|
303
311
|
end
|
304
312
|
|
305
313
|
# Rename parents for rdv and bdv
|
306
314
|
apply_composite_name_pattern
|
307
315
|
|
308
|
-
#
|
309
|
-
|
316
|
+
# Inject datetime and record source into the LoadBatch table
|
317
|
+
if @option_audit == 'batch'
|
318
|
+
inject_audit_fields(loadbatch_composite)
|
319
|
+
end
|
310
320
|
|
311
321
|
unless @option_reference
|
312
322
|
if trace :reference_retraction
|
@@ -326,14 +336,16 @@ module ActiveFacts
|
|
326
336
|
@constellation.loggers.pop if trace :reference_retraction
|
327
337
|
end
|
328
338
|
|
329
|
-
#
|
339
|
+
# Populate fields of any point in time tables
|
330
340
|
@pit_composites.each do |composite|
|
331
|
-
|
341
|
+
populate_pit(composite)
|
332
342
|
end
|
333
343
|
|
344
|
+
super
|
334
345
|
end
|
335
346
|
|
336
|
-
|
347
|
+
# A Point-In-Time table links a hub to its satellites applicable at a particular time
|
348
|
+
def populate_pit(pit_composite)
|
337
349
|
# inject standard PIT components: surrogate key, hub hash key and snapshot date time
|
338
350
|
inject_surrogate(pit_composite)
|
339
351
|
|
@@ -342,14 +354,16 @@ module ActiveFacts
|
|
342
354
|
pit_hub_field = hub_hash_field.fork_to_new_parent(pit_composite.mapping)
|
343
355
|
date_field = @constellation.ValidFrom(:new,
|
344
356
|
parent: pit_composite.mapping,
|
345
|
-
name: "Snapshot"+datestamp_type_name,
|
346
|
-
object_type: datestamp_type
|
357
|
+
name: "Snapshot "+datestamp_type_name,
|
358
|
+
object_type: datestamp_type,
|
359
|
+
injection_annotation: "datavault"
|
347
360
|
)
|
348
361
|
|
349
362
|
natural_index =
|
350
|
-
@constellation.Index(
|
351
|
-
|
352
|
-
|
363
|
+
@constellation.Index(
|
364
|
+
:new, composite: pit_composite, is_unique: true,
|
365
|
+
composite_as_natural_index: pit_composite #, composite_as_primary_index: pit_composite
|
366
|
+
)
|
353
367
|
@constellation.IndexField(access_path: natural_index, ordinal: 0, component: pit_hub_field)
|
354
368
|
@constellation.IndexField(access_path: natural_index, ordinal: 1, component: date_field)
|
355
369
|
|
@@ -357,8 +371,7 @@ module ActiveFacts
|
|
357
371
|
fk = @constellation.ForeignKey(
|
358
372
|
:new,
|
359
373
|
source_composite: pit_composite,
|
360
|
-
composite: hub_composite
|
361
|
-
absorption: nil # REVISIT: This is a ForeignKey without its mandatory Absorption. That's gonna hurt
|
374
|
+
composite: hub_composite
|
362
375
|
)
|
363
376
|
@constellation.ForeignKeyField(foreign_key: fk, ordinal: 0, component: pit_hub_field)
|
364
377
|
# This should be filled in by complete_foreign_keys, but there is no Absorption
|
@@ -370,14 +383,15 @@ module ActiveFacts
|
|
370
383
|
|
371
384
|
sat_composites.each do |sat_composite|
|
372
385
|
sat_name = sat_composite.mapping.name
|
373
|
-
sat_hash_name =
|
386
|
+
sat_hash_name = patterned_name(@option_id, sat_name)
|
374
387
|
|
375
388
|
src_hash_field = hub_hash_field.fork_to_new_parent(pit_composite.mapping)
|
376
389
|
src_hash_field.name = sat_hash_name
|
377
390
|
src_load_field = @constellation.ValidFrom(:new,
|
378
391
|
parent: pit_composite.mapping,
|
379
|
-
name: "#{sat_name} Load"+datestamp_type_name,
|
380
|
-
object_type: datestamp_type
|
392
|
+
name: "#{sat_name} Load "+datestamp_type_name,
|
393
|
+
object_type: datestamp_type,
|
394
|
+
injection_annotation: "datavault"
|
381
395
|
)
|
382
396
|
|
383
397
|
sat_index_fields = sat_composite.primary_index.all_index_field.to_a
|
@@ -388,8 +402,7 @@ module ActiveFacts
|
|
388
402
|
fk = @constellation.ForeignKey(
|
389
403
|
:new,
|
390
404
|
source_composite: pit_composite,
|
391
|
-
composite: sat_composite
|
392
|
-
absorption: nil # REVISIT: This is a ForeignKey without its mandatory Absorption. That's gonna hurt
|
405
|
+
composite: sat_composite
|
393
406
|
)
|
394
407
|
@constellation.ForeignKeyField(foreign_key: fk, ordinal: 0, component: src_hash_field)
|
395
408
|
@constellation.IndexField(access_path: fk, ordinal: 0, component: sat_hash_field)
|
@@ -408,19 +421,20 @@ module ActiveFacts
|
|
408
421
|
end
|
409
422
|
end
|
410
423
|
|
411
|
-
def
|
412
|
-
return
|
413
|
-
building_natural_key && @
|
424
|
+
def preferred_fk_type building_natural_key, source_composite, target_composite
|
425
|
+
return :hash if @option_fk == :hash
|
426
|
+
return :primary if building_natural_key && (@link_composites+@bdv_link_composites).include?(source_composite)
|
427
|
+
building_natural_key && @hub_composites.include?(target_composite) ? :natural : :primary
|
414
428
|
end
|
415
429
|
|
416
|
-
# For each member of this composite, decide whether to
|
430
|
+
# For each member of this composite, decide whether to split it to a satellite
|
417
431
|
# or to a new link. If it goes to a link that's still part of this natural key,
|
418
432
|
# we need to leave that key intact, but remove the foreign key it entails.
|
419
433
|
#
|
420
434
|
# New links and satellites get new fields for the load date-time and a
|
421
435
|
# references to the surrogate(s) on the hub or link, and add an index over
|
422
436
|
# those two fields.
|
423
|
-
def
|
437
|
+
def split_satellites_from composite, split_off_links = true
|
424
438
|
trace :datavault?, "Devolving non-identifying fields for #{composite.inspect}" do
|
425
439
|
# Find the members of this mapping that contain identifying leaves:
|
426
440
|
pi = composite.primary_index
|
@@ -433,20 +447,23 @@ module ActiveFacts
|
|
433
447
|
|
434
448
|
satellites = {}
|
435
449
|
is_link = @link_composites.include?(composite) || @links_as_hubs.include?(composite)
|
436
|
-
composite.mapping.all_member.to_a
|
450
|
+
member_snapshot = composite.mapping.all_member.to_a
|
451
|
+
version_field = inject_audit_fields(composite)
|
452
|
+
absorb_nested composite.mapping, version_field, {} if MM::Absorption === version_field
|
453
|
+
member_snapshot.each do |member|
|
437
454
|
|
438
455
|
# Any member that is the absorption of a foreign key to a hub or link
|
439
456
|
# (which is all, since we removed FKs to reference tables)
|
440
457
|
# must be converted to a Mapping for a new Entity Type that notionally
|
441
458
|
# objectifies the absorbed fact type. This Mapping is a new link composite.
|
442
|
-
if
|
459
|
+
if split_off_links && member.is_a?(MM::Absorption) && member.foreign_key
|
443
460
|
next if is_link
|
444
|
-
|
461
|
+
split_off_absorption_to_link member, identifiers.include?(member)
|
445
462
|
next
|
446
463
|
end
|
447
464
|
|
448
465
|
# If this member is in the natural or surrogate key, leave it there
|
449
|
-
# REVISIT: But if it is an FK to another hub,
|
466
|
+
# REVISIT: But if it is an FK to another hub, split it to a link as well.
|
450
467
|
next if identifiers.include?(member)
|
451
468
|
|
452
469
|
# We may absorb a subtype that has no contents. There's no point moving these to a satellite.
|
@@ -455,13 +472,14 @@ module ActiveFacts
|
|
455
472
|
satellite_name, is_computed = *name_satellite(member)
|
456
473
|
if !(satellite = satellites[satellite_name])
|
457
474
|
satellite = satellites[satellite_name] = create_satellite(satellite_name, composite)
|
475
|
+
identify_satellite composite, satellite
|
458
476
|
satellite.composite_group = (is_computed ? 'bdv' : 'rdv')
|
459
477
|
if member.is_a?(MM::Absorption) && check_pit(member)
|
460
478
|
@pit_satellite[member] = satellite
|
461
479
|
end
|
462
480
|
end
|
463
481
|
|
464
|
-
|
482
|
+
split_off_member_to_satellite satellite, member
|
465
483
|
end
|
466
484
|
composite.mapping.re_rank
|
467
485
|
|
@@ -470,49 +488,41 @@ module ActiveFacts
|
|
470
488
|
composite.all_foreign_key_as_source_composite.to_a.each(&:retract)
|
471
489
|
end
|
472
490
|
|
473
|
-
# Add the audit and identity fields for the
|
491
|
+
# Add the audit and identity fields for the satellites:
|
474
492
|
satellites.values.each do |satellite|
|
475
|
-
|
493
|
+
remove_satellite_validations satellite
|
476
494
|
end
|
477
495
|
end
|
478
496
|
end
|
479
497
|
|
480
498
|
# Add the audit and foreign key fields to a satellite for this composite
|
481
|
-
def
|
499
|
+
def identify_satellite composite, satellite
|
482
500
|
trace :datavault, "Adding parent key and load time to satellite #{satellite.mapping.name.inspect}" do
|
483
|
-
|
484
|
-
# Add a Surrogate foreign Key to the parent composite
|
485
|
-
fk_target = composite.primary_index.all_index_field.single
|
486
|
-
fk_field = fk_target.component.fork_to_new_parent satellite.mapping
|
487
|
-
|
488
|
-
# Add a load DateTime value and record source
|
489
|
-
date_field = inject_datetime_recordsource(satellite.mapping)
|
490
|
-
|
491
|
-
# Add a primary and natural key:
|
501
|
+
# Add a primary (which is also natural) key:
|
492
502
|
natural_index =
|
493
503
|
@constellation.Index(:new, composite: satellite, is_unique: true,
|
494
|
-
|
495
|
-
|
496
|
-
@constellation.IndexField(access_path: natural_index, ordinal: 1, component: date_field)
|
504
|
+
# composite_as_natural_index: satellite, # Must not be natural for the absorption to work correctly
|
505
|
+
composite_as_primary_index: satellite)
|
497
506
|
|
498
|
-
#
|
507
|
+
# Absorb and index a foreign key to the hub or link. We'll add the version_field to the index.
|
508
|
+
# REVISIT: The name here should be the renamed version of the parent's name AFTER it's been adjusted
|
509
|
+
object_type = composite.mapping.object_type
|
510
|
+
member = @constellation.Mapping(guid: :new, parent: satellite.mapping, name: composite.mapping.name, object_type: object_type)
|
511
|
+
paths = {object_type.preferred_identifier => natural_index}
|
512
|
+
absorb_nested satellite.mapping, member, paths
|
513
|
+
# Satellites don't really have a natural key, but never mind...
|
514
|
+
satellite.natural_index = satellite.primary_index
|
515
|
+
|
516
|
+
# Add the audit and time-versioning fields
|
517
|
+
version_field =
|
518
|
+
if @option_audit == 'batch'
|
519
|
+
inject_audit_fields satellite, composite
|
520
|
+
else
|
521
|
+
inject_audit_fields satellite
|
522
|
+
end
|
523
|
+
@constellation.IndexField(access_path: natural_index, ordinal: natural_index.all_index_field.size, component: version_field)
|
499
524
|
satellite.mapping.re_rank
|
500
525
|
|
501
|
-
# Add a foreign key to the hub
|
502
|
-
fk = @constellation.ForeignKey(
|
503
|
-
:new,
|
504
|
-
source_composite: satellite,
|
505
|
-
composite: composite,
|
506
|
-
absorption: nil # REVISIT: This is a ForeignKey without its mandatory Absorption. That's gonna hurt
|
507
|
-
)
|
508
|
-
@constellation.ForeignKeyField(foreign_key: fk, ordinal: 0, component: fk_field)
|
509
|
-
# This should be filled in by complete_foreign_keys, but there is no Absorption
|
510
|
-
@constellation.IndexField(access_path: fk, ordinal: 0, component: fk_target.component)
|
511
|
-
|
512
|
-
satellite.classify_constraints
|
513
|
-
satellite.all_local_constraint.map(&:local_constraint).each(&:retract)
|
514
|
-
leaf_constraints = satellite.mapping.all_leaf.flat_map(&:all_leaf_constraint).map(&:leaf_constraint).each(&:retract)
|
515
|
-
|
516
526
|
if satellite.composite_group == 'bdv'
|
517
527
|
@bdv_sat_composites << satellite
|
518
528
|
else
|
@@ -521,6 +531,12 @@ module ActiveFacts
|
|
521
531
|
end
|
522
532
|
end
|
523
533
|
|
534
|
+
def remove_satellite_validations satellite
|
535
|
+
satellite.classify_constraints
|
536
|
+
satellite.all_local_constraint.map(&:local_constraint).each(&:retract)
|
537
|
+
leaf_constraints = satellite.mapping.all_leaf.flat_map(&:all_leaf_constraint).map(&:leaf_constraint).each(&:retract)
|
538
|
+
end
|
539
|
+
|
524
540
|
# Decide what to call a new satellite that will adopt this component
|
525
541
|
def satellite_base_name_and_type component
|
526
542
|
computed_name = nil
|
@@ -539,7 +555,7 @@ module ActiveFacts
|
|
539
555
|
|
540
556
|
def name_satellite component
|
541
557
|
name, is_computed = *satellite_base_name_and_type(component)
|
542
|
-
[
|
558
|
+
[patterned_name(@option_sat_name, name), is_computed != nil]
|
543
559
|
end
|
544
560
|
|
545
561
|
# Create a new satellite for the same object_type as this composite
|
@@ -568,7 +584,7 @@ module ActiveFacts
|
|
568
584
|
end
|
569
585
|
|
570
586
|
# Move this member from its current parent to the satellite
|
571
|
-
def
|
587
|
+
def split_off_member_to_satellite satellite, member
|
572
588
|
remove_indices member
|
573
589
|
|
574
590
|
member.parent = satellite.mapping
|
@@ -578,7 +594,7 @@ module ActiveFacts
|
|
578
594
|
|
579
595
|
# This absorption reflects a time-varying fact type that involves another Hub, which becomes a new link.
|
580
596
|
# REVISIT: "make_copy" says that the original field must remain, because it's in its parent's natural key.
|
581
|
-
def
|
597
|
+
def split_off_absorption_to_link absorption, make_copy
|
582
598
|
trace :datavault, "Promote #{absorption.inspect} to a new Link" do
|
583
599
|
|
584
600
|
# REVISIT: Here we need a new objectified fact type with the same two players and the same readings,
|
@@ -614,8 +630,13 @@ module ActiveFacts
|
|
614
630
|
if absorption.foreign_key
|
615
631
|
trace :datavault, "Setting new source composite for #{absorption.foreign_key.inspect}"
|
616
632
|
absorption.foreign_key.source_composite = link
|
617
|
-
|
618
|
-
|
633
|
+
if absorption.foreign_key.all_foreign_key_field.single
|
634
|
+
fk2_component = absorption.foreign_key.all_foreign_key_field.single.component
|
635
|
+
else
|
636
|
+
p absorption.foreign_key
|
637
|
+
debugger
|
638
|
+
absorption.foreign_key.retract
|
639
|
+
end
|
619
640
|
end
|
620
641
|
end
|
621
642
|
|
@@ -642,8 +663,7 @@ module ActiveFacts
|
|
642
663
|
|
643
664
|
# Add a natural key:
|
644
665
|
natural_index =
|
645
|
-
@constellation.Index(:new, composite: link, is_unique: true,
|
646
|
-
presence_constraint: nil, composite_as_natural_index: link)
|
666
|
+
@constellation.Index(:new, composite: link, is_unique: true, composite_as_natural_index: link)
|
647
667
|
@constellation.IndexField(access_path: natural_index, ordinal: 0, component: fk1_component)
|
648
668
|
@constellation.IndexField(access_path: natural_index, ordinal: 1, component: fk2_component)
|
649
669
|
|
@@ -651,8 +671,7 @@ module ActiveFacts
|
|
651
671
|
fk1 = @constellation.ForeignKey(
|
652
672
|
:new,
|
653
673
|
source_composite: link,
|
654
|
-
composite: link_from
|
655
|
-
absorption: nil # REVISIT: This is a ForeignKey without its mandatory Absorption. That's gonna hurt
|
674
|
+
composite: link_from
|
656
675
|
)
|
657
676
|
@constellation.ForeignKeyField(foreign_key: fk1, ordinal: 0, component: fk1_component)
|
658
677
|
# REVISIT: This should be filled in by complete_foreign_keys, but it has no Absorption
|
@@ -662,67 +681,43 @@ module ActiveFacts
|
|
662
681
|
fk2 = @constellation.ForeignKey(
|
663
682
|
:new,
|
664
683
|
source_composite: link,
|
665
|
-
composite: link_to
|
666
|
-
absorption: nil # REVISIT: This is a ForeignKey without its mandatory Absorption. That's gonna hurt
|
684
|
+
composite: link_to
|
667
685
|
)
|
668
686
|
@constellation.ForeignKeyField(foreign_key: fk2, ordinal: 0, component: fk2_component)
|
669
|
-
#
|
687
|
+
# This can't be filled in by complete_foreign_keys because it has no Absorption
|
670
688
|
@constellation.IndexField(access_path: fk2, ordinal: 0, component: fk2_target.component)
|
671
689
|
absorption.foreign_key.retract
|
672
690
|
end
|
691
|
+
inject_audit_fields link, link_from
|
673
692
|
|
674
|
-
|
675
|
-
issues = 0
|
676
|
-
link.validate do |object, problem|
|
677
|
-
$stderr.puts "#{object.inspect}: #{problem}"
|
678
|
-
issues += 1
|
679
|
-
end
|
680
|
-
debugger if issues > 0
|
681
|
-
=end
|
682
|
-
|
683
|
-
|
684
|
-
# # Add a load DateTime value
|
685
|
-
# date_field = add_datetime_recordsource(mapping)
|
686
|
-
|
687
|
-
#link.mapping.re_rank
|
688
|
-
|
689
|
-
# devolve link, false
|
693
|
+
# split_satellites_from link, false
|
690
694
|
@link_composites << link
|
691
695
|
end
|
692
696
|
end
|
693
697
|
|
694
|
-
def apply_name pattern, name
|
695
|
-
pattern.sub(/\+/, name)
|
696
|
-
end
|
697
|
-
|
698
698
|
def apply_composite_name_pattern
|
699
699
|
@reference_composites.each do |composite|
|
700
|
-
composite.mapping.name =
|
700
|
+
composite.mapping.name = patterned_name(@option_ref_name, composite.mapping.name)
|
701
701
|
end
|
702
702
|
@hub_composites.each do |composite|
|
703
|
-
composite.mapping.name =
|
703
|
+
composite.mapping.name = patterned_name(@option_hub_name, composite.mapping.name)
|
704
704
|
end
|
705
705
|
@link_composites.each do |composite|
|
706
|
-
composite.mapping.name =
|
706
|
+
composite.mapping.name = patterned_name(@option_link_name, composite.mapping.name)
|
707
707
|
end
|
708
708
|
@bdv_link_composites.each do |composite|
|
709
|
-
composite.mapping.name =
|
709
|
+
composite.mapping.name = patterned_name(@option_link_name, composite.mapping.name)
|
710
710
|
end
|
711
711
|
@pit_composites.each do |composite|
|
712
|
-
composite.mapping.name =
|
712
|
+
composite.mapping.name = patterned_name(@option_pit_name, composite.mapping.name)
|
713
713
|
end
|
714
714
|
@bridge_composites.each do |composite|
|
715
|
-
composite.mapping.name =
|
715
|
+
composite.mapping.name = patterned_name(@option_bridge_name, composite.mapping.name)
|
716
716
|
end
|
717
717
|
end
|
718
718
|
|
719
|
-
def
|
720
|
-
|
721
|
-
inject_datetime_recordsource(composite.mapping)
|
722
|
-
end
|
723
|
-
@hub_composites.each do |composite|
|
724
|
-
inject_datetime_recordsource(composite.mapping)
|
725
|
-
end
|
719
|
+
def inject_loadbatch_relationships
|
720
|
+
# We can't do it the way our trait does, we treat hub+links, satellites, and fact links all differently
|
726
721
|
end
|
727
722
|
|
728
723
|
end
|