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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/activefacts-compositions.gemspec +2 -2
  3. data/lib/activefacts/compositions/binary.rb +1 -1
  4. data/lib/activefacts/compositions/compositor.rb +16 -12
  5. data/lib/activefacts/compositions/datavault.rb +110 -115
  6. data/lib/activefacts/compositions/relational.rb +137 -94
  7. data/lib/activefacts/compositions/staging.rb +89 -27
  8. data/lib/activefacts/compositions/traits/datavault.rb +116 -49
  9. data/lib/activefacts/compositions/traits/rails.rb +2 -2
  10. data/lib/activefacts/compositions/version.rb +1 -1
  11. data/lib/activefacts/generator/doc/cwm.rb +6 -18
  12. data/lib/activefacts/generator/doc/ldm.rb +1 -1
  13. data/lib/activefacts/generator/etl/unidex.rb +341 -0
  14. data/lib/activefacts/generator/oo.rb +31 -14
  15. data/lib/activefacts/generator/rails/models.rb +6 -5
  16. data/lib/activefacts/generator/rails/schema.rb +5 -9
  17. data/lib/activefacts/generator/ruby.rb +2 -2
  18. data/lib/activefacts/generator/sql/mysql.rb +3 -184
  19. data/lib/activefacts/generator/sql/oracle.rb +3 -152
  20. data/lib/activefacts/generator/sql/postgres.rb +3 -145
  21. data/lib/activefacts/generator/sql/server.rb +3 -126
  22. data/lib/activefacts/generator/sql.rb +54 -422
  23. data/lib/activefacts/generator/summary.rb +15 -6
  24. data/lib/activefacts/generator/traits/expr.rb +41 -0
  25. data/lib/activefacts/generator/traits/sql/mysql.rb +280 -0
  26. data/lib/activefacts/generator/traits/sql/oracle.rb +265 -0
  27. data/lib/activefacts/generator/traits/sql/postgres.rb +287 -0
  28. data/lib/activefacts/generator/traits/sql/server.rb +262 -0
  29. data/lib/activefacts/generator/traits/sql.rb +538 -0
  30. metadata +13 -8
  31. data/lib/activefacts/compositions/docgraph.rb +0 -798
  32. data/lib/activefacts/compositions/staging/persistent.rb +0 -107
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 629d91efc99ba1f54872c6c668a1ee0f86bf7d04
4
- data.tar.gz: b2e8c929798553e24d7bf1e8fe0e81718c0b811b
3
+ metadata.gz: 9264168bcd4294c87277a11fde73ba06c0e490e6
4
+ data.tar.gz: 40f2da7b5f7a72066b13ed7bc2de790e3717af82
5
5
  SHA512:
6
- metadata.gz: a5ebe59af26c890d1f5771400d3dced9c123c96b252b10ee0805c04612fed3f7eac0ef4018ecfbdfe09882b43605fa6109307b831c2fce15541c0a5ff43311be
7
- data.tar.gz: bd9f2f20c79718881cf6a8f7c42b21cb37f6b0d5346302f77d9453341f6aff7768acc9f0e495c7b4e1850879935bddecf72d14e5fb98ce0740b62fa23e7973d1
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.20"
33
- spec.add_runtime_dependency "activefacts-cql", "~> 1", ">= 1.9.3"
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
@@ -1,4 +1,4 @@
1
- ### Composition
1
+ #
2
2
  # ActiveFacts Compositions, Binary Compositor.
3
3
  #
4
4
  # Fans of RDF will like this one.
@@ -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
- return if (@reference_populated ||= {})[role]
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
- a = @constellation.Absorption(
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/reverse_absorption (putting the "many" or optional side as reverse)
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 a.is_preferred_direction
75
- a.reverse_absorption = r
77
+ if component.is_preferred_direction
78
+ component.reverse_mapping = r
76
79
  else # Set this as the reverse absorption
77
- a.forward_absorption = r
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] = a
84
+ @component_by_fact[role.fact_type] = component
82
85
  end
83
86
  else # It's an indicator
84
- a = @constellation.Indicator(
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] = a # For completeness, in case a subclass uses it
93
+ @component_by_fact[role.fact_type] = component # For completeness, in case a subclass uses it
91
94
  end
92
- @reference_populated[role] = a
93
- trace :binarize, "Populating #{a.inspect}"
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 keys (default HID)"],
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
- # We need to find links that need surrogate keys before we inject the surrogates
64
- def inject_surrogates
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, extension = @option_id
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.to_a
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
- devolve composite
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
- # inject datetime and record source for rdv hubs and links
309
- inject_all_datetime_recordsource
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
- # Devolve point in time tables, if any
339
+ # Populate fields of any point in time tables
330
340
  @pit_composites.each do |composite|
331
- devolve_pit(composite)
341
+ populate_pit(composite)
332
342
  end
333
343
 
344
+ super
334
345
  end
335
346
 
336
- def devolve_pit(pit_composite)
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(:new, composite: pit_composite, is_unique: true,
351
- presence_constraint: nil, composite_as_natural_index: pit_composite #, composite_as_primary_index: pit_composite
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 = "#{sat_name}#{@option_id}"
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 prefer_natural_key building_natural_key, source_composite, target_composite
412
- return false if building_natural_key && (@link_composites.include?(source_composite) || @bdv_link_composites.include?(source_composite))
413
- building_natural_key && @hub_composites.include?(target_composite)
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 devolve it to a satellite
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 devolve composite, devolve_links = true
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.each do |member|
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 devolve_links && member.is_a?(MM::Absorption) && member.foreign_key
459
+ if split_off_links && member.is_a?(MM::Absorption) && member.foreign_key
443
460
  next if is_link
444
- devolve_absorption_to_link member, identifiers.include?(member)
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, devolve it to a link as well.
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
- devolve_member_to_satellite satellite, member
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 satellite:
491
+ # Add the audit and identity fields for the satellites:
474
492
  satellites.values.each do |satellite|
475
- audit_satellite composite, satellite
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 audit_satellite composite, satellite
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
- presence_constraint: nil, composite_as_natural_index: satellite, composite_as_primary_index: satellite)
495
- @constellation.IndexField(access_path: natural_index, ordinal: 0, component: fk_field)
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
- # REVISIT: re-ranking members without a preferred_identifier does not rank the PK fields in order.
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
- [apply_name(@option_sat_name, name), is_computed != nil]
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 devolve_member_to_satellite satellite, member
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 devolve_absorption_to_link absorption, make_copy
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
- debugger unless absorption.foreign_key.all_foreign_key_field.single
618
- fk2_component = absorption.foreign_key.all_foreign_key_field.single.component
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
- # REVISIT: This should be filled in by complete_foreign_keys, but it has no Absorption
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
- =begin
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 = apply_name(@option_ref_name, 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 = apply_name(@option_hub_name, 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 = apply_name(@option_link_name, 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 = apply_name(@option_link_name, 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 = apply_name(@option_pit_name, 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 = apply_name(@option_bridge_name, 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 inject_all_datetime_recordsource
720
- @link_composites.each do |composite|
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