activefacts-compositions 1.9.15 → 1.9.16

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
  SHA1:
3
- metadata.gz: f1bf118df915877ab33968a6777b33a62cf37324
4
- data.tar.gz: bd5400584518e29d8bdefc7caf593379805a6e35
3
+ metadata.gz: 1f365db9787609b86e8184f61d9fc4c2d0b6e76e
4
+ data.tar.gz: 66f3cd28bbd6eeadb7a9ee48fb1afd2774697193
5
5
  SHA512:
6
- metadata.gz: 2012ef677cea2524ef6ff02df61e07af2822faad359ae4975f375ab374760db27d0ba981064969a55fabfcc13d2d24ec690b620f7c93281fded26764cf2f98f3
7
- data.tar.gz: 30771fd537a8249d6f12f4c197eb1925e73cc2dc41222c6cc381591895216902bd7b479da6176309eae85eb8021ab7dd506701cd8429dfbcc82c7a08b905173d
6
+ metadata.gz: 1b8237ff0549bd7d36c8c8bcae1ad5272a3d13357c61ae4b7bcd4f9c1cd6c88bc46525844128d472231034c4df2c999230c7e964eee40a730515549ab94d2fcc
7
+ data.tar.gz: 8057016adea612072f44aa65a84496d6e80660394ae9199157868475dca6e9a39ed96679c0b71cc62408f3a964bca2ebe9fbc1511d4fbb1b8fda9aeeeed81143
data/.gitignore CHANGED
@@ -14,3 +14,4 @@
14
14
  *.diff
15
15
  actual
16
16
  .byebug_history
17
+ log
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  this_file = File.absolute_path(__FILE__)
6
- if this_file =~ %r{\A#{ENV['HOME']}}i
6
+ if this_file =~ %r{\A#{ENV['HOME']}}i and !ENV['USE_INSTALLED']
7
7
  dir = File.dirname(File.dirname(this_file))
8
8
  $stderr.puts "Using work area gems in #{dir} from activefacts-compositions"
9
9
  gem 'activefacts-api', path: dir+'/api'
@@ -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.19"
33
- spec.add_runtime_dependency "activefacts-cql", "~> 1", ">= 1.9"
32
+ spec.add_runtime_dependency "activefacts-metamodel", "~> 1", ">= 1.9.20"
33
+ spec.add_runtime_dependency "activefacts-cql", "~> 1", ">= 1.9.3"
34
34
  end
@@ -20,9 +20,6 @@ module ActiveFacts
20
20
 
21
21
  def self.options
22
22
  {
23
- # source: ['Boolean', "Generate composition for source schema"],
24
- # target: ['Boolean', "Generate composition for target schema"],
25
- # transform: ['Boolean', "Generate composition for transform schema"]
26
23
  }
27
24
  end
28
25
 
@@ -50,16 +47,11 @@ module ActiveFacts
50
47
  populate_references
51
48
  end
52
49
 
53
- private
54
- # Preferred identifiers are cached, but the process produces trace output
55
- # that appears in the "tutti" mode used in testing. This precludes that.
56
- def preload_preferred_identifiers
57
- @constellation.EntityType.map{|k, et| et.preferred_identifier }
58
- end
50
+ def populate_reference role
51
+ return if (@reference_populated ||= {})[role]
52
+ @reference_populated[role] = true
59
53
 
60
- def populate_reference object_type, role
61
54
  parent = @binary_mappings[role.object_type]
62
-
63
55
  return if role.fact_type.all_role.size > 2
64
56
  if role.fact_type.all_role.size != 1
65
57
  counterpart = role.counterpart
@@ -97,9 +89,18 @@ module ActiveFacts
97
89
  )
98
90
  @component_by_fact[role.fact_type] = a # For completeness, in case a subclass uses it
99
91
  end
92
+ @reference_populated[role] = a
100
93
  trace :binarize, "Populating #{a.inspect}"
101
94
  end
102
95
 
96
+ private
97
+
98
+ # Preferred identifiers are cached, but the process produces trace output
99
+ # that appears in the "tutti" mode used in testing. This precludes that.
100
+ def preload_preferred_identifiers
101
+ @constellation.EntityType.map{|k, et| et.preferred_identifier }
102
+ end
103
+
103
104
  def populate_references
104
105
  # A table of Mappings by object type, with a default Mapping for each:
105
106
  @binary_mappings = Hash.new do |h, object_type|
@@ -124,7 +125,7 @@ module ActiveFacts
124
125
  # Exclude base roles in objectified fact types (unless unary); just use link fact types
125
126
  next if role.fact_type.entity_type && role.fact_type.all_role.size != 1
126
127
  next if role.variable # REVISIT: Continue to ignore roles in derived fact types?
127
- populate_reference object_type, role
128
+ populate_reference role
128
129
  end
129
130
  if object_type.is_a?(ActiveFacts::Metamodel::ValueType)
130
131
  # This requires a change in the metamodel to use TypeInheritance for ValueTypes
@@ -198,6 +199,7 @@ module ActiveFacts
198
199
  end
199
200
  end
200
201
 
202
+ public
201
203
  # Display the primitive binary mapping:
202
204
  def show_references
203
205
  trace :composition, "Displaying the mappings:" do
@@ -6,10 +6,14 @@
6
6
  # Copyright (c) 2015 Clifford Heath. Read the LICENSE file.
7
7
  #
8
8
  require "activefacts/compositions/relational"
9
+ require "activefacts/compositions/traits/datavault"
9
10
 
10
11
  module ActiveFacts
11
12
  module Compositions
12
13
  class DataVault < Relational
14
+ extend Traits::DataVault
15
+ include Traits::DataVault
16
+
13
17
  BDV_ANNOTATIONS = /same as link|hierarchy link|computed link|exploration link|computed satellite|point in time|bridge/
14
18
  BDV_LINK_ANNOTATIONS = /same as link|hierarchy link|computed link|exploration link/
15
19
  BDV_SAT_ANNOTATIONS = /computed satellite/
@@ -18,9 +22,9 @@ module ActiveFacts
18
22
 
19
23
  public
20
24
  def self.options
21
- {
25
+ datavault_options.
26
+ merge({
22
27
  reference: ['Boolean', "Emit the reference (static) tables as well. Default is to omit them"],
23
- datestamp: ['String', "Use this data type for date stamps"],
24
28
  id: ['String', "Append this to data vault surrogate keys (default HID)"],
25
29
  hubname: ['String', "Suffix or pattern for naming hub tables. Include a + to insert the name. Default 'HUB'"],
26
30
  linkname: ['String', "Suffix or pattern for naming link tables. Include a + to insert the name. Default 'LINK'"],
@@ -28,14 +32,15 @@ module ActiveFacts
28
32
  pitname: ['String', "Suffix or pattern for naming point in time tables. Include a + to insert the name. Default 'PIT'"],
29
33
  bridgename: ['String', "Suffix or pattern for naming bridge tables. Include a + to insert the name. Default 'BRIDGE'"],
30
34
  refname: ['String', "Suffix or pattern for naming reference tables. Include a + to insert the name. Default '+'"],
31
- }.merge(Relational.options).
35
+ }).
36
+ merge(Relational.options).
32
37
  reject{|k,v| [:surrogates].include?(k) } # Datavault surrogates are not optional
33
38
  end
34
39
 
35
40
  def initialize constellation, name, options = {}
36
41
  # Extract recognised options:
42
+ datavault_initialize options
37
43
  @option_reference = options.delete('reference')
38
- @option_datestamp = options.delete('datestamp')
39
44
  @option_id = ' ' + (options.delete('id') || 'HID')
40
45
  @option_hub_name = options.delete('hubname') || 'HUB'
41
46
  @option_hub_name.sub!(/^/,'+ ') unless @option_hub_name =~ /\+/
@@ -288,7 +293,7 @@ module ActiveFacts
288
293
  mapped_to
289
294
  end
290
295
 
291
- def devolve_all
296
+ def apply_schema_transformations
292
297
  delete_reference_table_foreign_keys
293
298
 
294
299
  # For each hub and link, move each non-identifying member
@@ -298,7 +303,7 @@ module ActiveFacts
298
303
  end
299
304
 
300
305
  # Rename parents for rdv and bdv
301
- rename_parents
306
+ apply_composite_name_pattern
302
307
 
303
308
  # inject datetime and record source for rdv hubs and links
304
309
  inject_all_datetime_recordsource
@@ -690,7 +695,7 @@ module ActiveFacts
690
695
  pattern.sub(/\+/, name)
691
696
  end
692
697
 
693
- def rename_parents
698
+ def apply_composite_name_pattern
694
699
  @reference_composites.each do |composite|
695
700
  composite.mapping.name = apply_name(@option_ref_name, composite.mapping.name)
696
701
  end
@@ -55,7 +55,8 @@ module ActiveFacts
55
55
  # Traverse the absorbed objects to build the path to each required column, including foreign keys:
56
56
  absorb_all_columns
57
57
 
58
- devolve_all
58
+ # Once the basic structure has been decided, we can play with it
59
+ apply_schema_transformations
59
60
 
60
61
  # Populate the target fields of foreign keys
61
62
  complete_foreign_keys
@@ -72,8 +73,8 @@ module ActiveFacts
72
73
  end
73
74
 
74
75
  def make_candidates
75
- @candidates = @binary_mappings.inject({}) do |hash, (absorption, mapping)|
76
- hash[mapping.object_type] = Candidate.new(self, mapping)
76
+ @candidates = @binary_mappings.inject(@candidates || {}) do |hash, (absorption, mapping)|
77
+ hash[mapping.object_type] ||= Candidate.new(self, mapping)
77
78
  hash
78
79
  end
79
80
  end
@@ -407,64 +408,6 @@ module ActiveFacts
407
408
  return true
408
409
  end
409
410
 
410
- #
411
- # Datetime and recordsource functions defined here because they are used in both Staging and Datavault subclasses
412
- #
413
- def inject_datetime_recordsource mapping
414
- # Add a load DateTime value
415
- date_field = @constellation.ValidFrom(:new,
416
- parent: mapping,
417
- name: "Load"+datestamp_type_name,
418
- object_type: datestamp_type
419
- )
420
-
421
- # Add a load DateTime value
422
- recsrc_field = @constellation.ValueField(:new,
423
- parent: mapping,
424
- name: "RecordSource",
425
- object_type: recordsource_type
426
- )
427
- mapping.re_rank
428
- date_field
429
- end
430
-
431
- def datestamp_type_name
432
- @datestamp_type_name ||= begin
433
- [true, '', 'true', 'yes', nil].include?(t = @option_datestamp) ? 'DateTime' : t
434
- end
435
- end
436
-
437
- def datestamp_type
438
- @datestamp_type ||= begin
439
- vocabulary = @composition.all_composite.to_a[0].mapping.object_type.vocabulary
440
- @constellation.ObjectType[[[vocabulary.name], datestamp_type_name]] or
441
- @constellation.ValueType(
442
- vocabulary: vocabulary,
443
- name: datestamp_type_name,
444
- concept: [:new, :implication_rule => "datestamp injection"]
445
- )
446
- end
447
- end
448
-
449
- def recordsource_type_name
450
- @recordsource_type_name ||= begin
451
- [true, '', 'true', 'yes', nil].include?(t = @option_recordsource) ? 'String' : t
452
- end
453
- end
454
-
455
- def recordsource_type
456
- @recordsource_type ||= begin
457
- vocabulary = @composition.all_composite.to_a[0].mapping.object_type.vocabulary
458
- @constellation.ObjectType[[[vocabulary.name], recordsource_type_name]] or
459
- @constellation.ValueType(
460
- vocabulary: vocabulary,
461
- name: recordsource_type_name,
462
- concept: [:new]
463
- )
464
- end
465
- end
466
-
467
-
468
411
  def clean_unused_mappings
469
412
  @candidates.keys.to_a.each do |object_type|
470
413
  candidate = @candidates[object_type]
@@ -556,20 +499,7 @@ module ActiveFacts
556
499
  end
557
500
 
558
501
  # Overwritten by Staging and Datavault subclasses
559
- def devolve_all
560
- end
561
-
562
- #
563
- # Rename parents functions defined because they are used in both Staging and Datavault subclasses
564
- #
565
- def apply_name pattern, name
566
- pattern.sub(/\+/, name)
567
- end
568
-
569
- def rename_parents
570
- @composites.each do |key, composite|
571
- composite.mapping.name = apply_name(@option_stg_name, composite.mapping.name)
572
- end
502
+ def apply_schema_transformations
573
503
  end
574
504
 
575
505
  # This member is an Absorption. Process it recursively, absorbing all its members or just a key
@@ -6,25 +6,40 @@
6
6
  # Copyright (c) 2016 Graeme Port. Read the LICENSE file.
7
7
  #
8
8
  require "activefacts/compositions/relational"
9
+ require "activefacts/compositions/traits/datavault"
9
10
 
10
11
  module ActiveFacts
11
12
  module Compositions
12
13
  class Staging < Relational
14
+ extend Traits::DataVault
15
+ include Traits::DataVault
13
16
  public
14
17
  def self.options
15
- {
18
+ datavault_options.
19
+ merge({
16
20
  stgname: ['String', "Suffix or pattern for naming staging tables. Include a + to insert the name. Default 'STG'"],
17
- }.merge(Relational.options).
21
+ }).
22
+ merge(Relational.options).
18
23
  reject{|k,v| [:surrogates].include?(k) }
19
24
  end
20
25
 
21
26
  def initialize constellation, name, options = {}
22
27
  # Extract recognised options:
28
+ datavault_initialize options
23
29
  @option_stg_name = options.delete('stgname') || 'STG'
24
30
  @option_stg_name.sub!(/^/,'+ ') unless @option_stg_name =~ /\+/
25
31
 
26
32
  super constellation, name, options, 'Staging'
33
+ end
34
+
35
+ def generate
36
+ create_loadbatch if @option_loadbatch
37
+ super
38
+ end
27
39
 
40
+ def inject_value_fields
41
+ super
42
+ inject_loadbatch_relationships
28
43
  end
29
44
 
30
45
  def inject_all_datetime_recordsource
@@ -33,15 +48,16 @@ module ActiveFacts
33
48
 
34
49
  trace :staging, "Injecting load datetime and record source" do
35
50
  @composition.all_composite.each do |composite|
51
+ next if composite.mapping.object_type.name == @option_loadbatch
36
52
  inject_datetime_recordsource composite.mapping
37
53
  composite.mapping.re_rank
38
54
  end
39
55
  end
40
56
  end
41
57
 
42
- def devolve_all
58
+ def apply_schema_transformations
43
59
  # Rename composites with STG prefix
44
- rename_parents
60
+ apply_composite_name_pattern
45
61
 
46
62
  inject_all_datetime_recordsource
47
63
  end
@@ -0,0 +1,115 @@
1
+ module ActiveFacts
2
+ module Compositions
3
+ module Traits
4
+ module DataVault
5
+ def datavault_options
6
+ {
7
+ datestamp: ['String', "Data type name to use for data vault date stamps (default: DateTime)"],
8
+ recordsource: ['String', "Data type name to use for data vault record source (default: String)"],
9
+ loadbatch: ['String', "Create a load batch table using this name, default LoadBatch"],
10
+ }
11
+ end
12
+
13
+ def datavault_initialize options
14
+ @option_datestamp = options.delete('datestamp')
15
+ @option_datestamp = 'DateTime' if [true, '', 'true', 'yes', nil].include?(@option_datestamp)
16
+ @option_recordsource = options.delete('recordsource')
17
+ @option_recordsource = 'String' if [true, '', 'true', 'yes', nil].include?(@option_recordsource)
18
+ @option_loadbatch = options.delete('loadbatch')
19
+ @option_loadbatch = 'LoadBatch' if [true, '', 'true', 'yes'].include?(@option_loadbatch)
20
+ end
21
+
22
+ def create_loadbatch
23
+ vocabulary = @constellation.Vocabulary.values[0]
24
+
25
+ schema_text = %Q{
26
+ schema #{vocabulary.name};
27
+
28
+ each #{@option_loadbatch} ID is written as an Auto Counter auto-assigned at commit;
29
+ each #{@option_loadbatch} is independent identified by its ID;
30
+ each #{@option_datestamp} is written as a #{@option_datestamp};
31
+ #{@option_loadbatch} began at one start-#{@option_datestamp};
32
+ }
33
+ @compiler = ActiveFacts::CQL::Compiler.new(@vocabulary, constellation: @constellation)
34
+ @compiler.compile(schema_text)
35
+ @loadbatch_entity_type = @constellation.EntityType[[vocabulary.identifying_role_values, @option_loadbatch]]
36
+ end
37
+
38
+ def inject_loadbatch_relationships
39
+ @composition.all_composite.each do |composite|
40
+ next if composite.mapping.object_type.name == @option_loadbatch
41
+ @compiler.compile("#{composite.mapping.name} was loaded in one #{@option_loadbatch};")
42
+ end
43
+ @loadbatch_entity_type.all_role.each do |role|
44
+ populate_reference role
45
+ populate_reference role.counterpart
46
+ end
47
+ end
48
+
49
+ def inject_datetime_recordsource mapping
50
+ # Add a load DateTime value
51
+ date_field = @constellation.ValidFrom(:new,
52
+ parent: mapping,
53
+ name: "LoadTime",
54
+ object_type: datestamp_type
55
+ )
56
+
57
+ # Add a load DateTime value
58
+ recsrc_field = @constellation.ValueField(:new,
59
+ parent: mapping,
60
+ name: "RecordSource",
61
+ object_type: recordsource_type
62
+ )
63
+ mapping.re_rank
64
+ date_field
65
+ end
66
+
67
+ def datestamp_type_name
68
+ @option_datestamp
69
+ end
70
+
71
+ def datestamp_type
72
+ @datestamp_type ||= begin
73
+ vocabulary = @composition.all_composite.to_a[0].mapping.object_type.vocabulary
74
+ @constellation.ObjectType[[[vocabulary.name], datestamp_type_name]] or
75
+ @constellation.ValueType(
76
+ vocabulary: vocabulary,
77
+ name: datestamp_type_name,
78
+ concept: [:new, :implication_rule => "datestamp injection"]
79
+ )
80
+ end
81
+ end
82
+
83
+ def recordsource_type_name
84
+ @option_recordsource
85
+ end
86
+
87
+ def recordsource_type
88
+ @recordsource_type ||= begin
89
+ vocabulary = @composition.all_composite.to_a[0].mapping.object_type.vocabulary
90
+ @constellation.ObjectType[[[vocabulary.name], recordsource_type_name]] or
91
+ @constellation.ValueType(
92
+ vocabulary: vocabulary,
93
+ name: recordsource_type_name,
94
+ concept: [:new]
95
+ )
96
+ end
97
+ end
98
+
99
+ #
100
+ # Rename parents functions defined because they are used in both Staging and Datavault subclasses
101
+ #
102
+ def apply_name_pattern pattern, name
103
+ pattern.sub(/\+/, name)
104
+ end
105
+
106
+ def apply_composite_name_pattern
107
+ @composites.each do |key, composite|
108
+ next if composite.mapping.object_type.name == @option_loadbatch
109
+ composite.mapping.name = apply_name_pattern(@option_stg_name, composite.mapping.name)
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -1,5 +1,5 @@
1
1
  module ActiveFacts
2
2
  module Compositions
3
- VERSION = "1.9.15"
3
+ VERSION = "1.9.16"
4
4
  end
5
5
  end
@@ -0,0 +1,206 @@
1
+ #
2
+ # ActiveFacts MySQL Schema Generator
3
+ #
4
+ # Copyright (c) 2009-2016 Clifford Heath. Read the LICENSE file.
5
+ #
6
+ # Reserved words gathered from:
7
+ # https://dev.mysql.com/doc/refman/5.7/en/keywords.html
8
+ #
9
+ require 'digest/sha1'
10
+ require 'activefacts/metamodel'
11
+ require 'activefacts/compositions'
12
+ require 'activefacts/generator/sql'
13
+
14
+ module ActiveFacts
15
+ module Generators
16
+ # Options are comma or space separated:
17
+ # * underscore
18
+ class SQL
19
+ class MySQL < SQL
20
+ def self.options
21
+ super.merge({
22
+ # no: [String, "no new options defined here"]
23
+ })
24
+ end
25
+
26
+ def table_name_max
27
+ 64
28
+ end
29
+
30
+ def data_type_context
31
+ MySQLDataTypeContext.new
32
+ end
33
+
34
+ def auto_assign_modifier
35
+ ' AUTO_INCREMENT'
36
+ end
37
+
38
+ def generate_schema
39
+ ''
40
+ end
41
+
42
+ def normalise_type(type_name, length, value_constraint, options)
43
+ type = MM::DataType.normalise(type_name)
44
+ case type
45
+ when MM::DataType::TYPE_Integer
46
+ if aa = options[:auto_assign]
47
+ 'BIGINT'
48
+ else
49
+ super
50
+ end
51
+ when MM::DataType::TYPE_Money; ['DECIMAL', length]
52
+ when MM::DataType::TYPE_DateTime; 'DATETIME'
53
+ when MM::DataType::TYPE_Timestamp;'DATETIME'
54
+ when MM::DataType::TYPE_Binary;
55
+ if type_name =~ /^(guid|uuid)$/i && (!length || length == 16)
56
+ if ![nil, ''].include?(options[:auto_assign])
57
+ options[:default] = " DEFAULT UNHEX(REPLACE(UUID(),'-',''))"
58
+ options.delete(:auto_assign) # Don't auto-assign foreign keys
59
+ end
60
+ return ['BINARY', 16]
61
+ end
62
+
63
+ super type_name, length, value_constraint, options
64
+ # MySQL has various non-standard blob types also
65
+ else
66
+ super
67
+ end
68
+ end
69
+
70
+ # Reserved words cannot be used anywhere without quoting.
71
+ # Keywords have existing definitions, so should not be used without quoting.
72
+ # Both lists here are added to the supertype's lists
73
+ def reserved_words
74
+ @mysql_reserved_words ||= %w{
75
+ ACCESSIBLE ANALYZE CHANGE DATABASE DATABASES DAY_HOUR
76
+ DAY_MICROSECOND DAY_MINUTE DAY_SECOND DELAYED DISTINCTROW
77
+ DIV DUAL ENCLOSED ESCAPED EXPLAIN FLOAT4 FLOAT8 FORCE
78
+ FULLTEXT HIGH_PRIORITY HOUR_MICROSECOND HOUR_MINUTE
79
+ HOUR_SECOND INDEX INFILE INT1 INT2 INT3 INT4 INT8
80
+ IO_AFTER_GTIDS IO_BEFORE_GTIDS KEYS KILL LINEAR LINES
81
+ LOAD LOCK LONG LONGBLOB LONGTEXT LOW_PRIORITY MASTER_BIND
82
+ MASTER_SSL_VERIFY_SERVER_CERT MEDIUMBLOB MEDIUMINT
83
+ MEDIUMTEXT MIDDLEINT MINUTE_MICROSECOND MINUTE_SECOND
84
+ NO_WRITE_TO_BINLOG OPTIMIZE OPTIMIZER_COSTS OPTIONALLY
85
+ OUTFILE PURGE READ_WRITE REGEXP RENAME REPLACE REQUIRE
86
+ RLIKE SCHEMAS SECOND_MICROSECOND SEPARATOR SHOW SPATIAL
87
+ SQL_BIG_RESULT SQL_CALC_FOUND_ROWS SQL_SMALL_RESULT SSL
88
+ STARTING STORED STRAIGHT_JOIN TERMINATED TINYBLOB TINYINT
89
+ TINYTEXT UNLOCK UNSIGNED USE UTC_DATE UTC_TIME UTC_TIMESTAMP
90
+ VARCHARACTER VIRTUAL XOR YEAR_MONTH ZEROFILL _FILENAME
91
+ }
92
+ super + @mysql_reserved_words
93
+ end
94
+
95
+ def key_words
96
+ # These keywords should not be used for columns or tables:
97
+ @mysql_key_words ||= %w{
98
+ ACCOUNT AGAINST AGGREGATE ALGORITHM ANALYSE ASCII
99
+ AUTOEXTEND_SIZE AUTO_INCREMENT AVG_ROW_LENGTH BACKUP
100
+ BINLOG BLOCK BOOL BTREE BYTE CACHE CHANGED CHANNEL
101
+ CHARSET CHECKSUM CIPHER CLIENT CODE COLUMN_FORMAT COMMENT
102
+ COMPACT COMPLETION COMPRESSED COMPRESSION CONCURRENT
103
+ CONSISTENT CONTEXT CPU DATAFILE DATETIME DEFAULT_AUTH
104
+ DELAY_KEY_WRITE DES_KEY_FILE DIRECTORY DISABLE DISCARD
105
+ DISK DUMPFILE DUPLICATE ENABLE ENCRYPTION ENDS ENGINE
106
+ ENGINES ENUM ERROR ERRORS EVENT EVENTS EXCHANGE EXPANSION
107
+ EXPIRE EXPORT EXTENDED EXTENT_SIZE FAST FAULTS FIELDS
108
+ FILE_BLOCK_SIZE FIXED FLUSH FOLLOWS FORMAT GEOMETRY
109
+ GEOMETRYCOLLECTION GET_FORMAT GRANTS GROUP_REPLICATION
110
+ HASH HELP HOST HOSTS IDENTIFIED IGNORE_SERVER_IDS INDEXES
111
+ INITIAL_SIZE INSERT_METHOD INSTALL IO IO_THREAD IPC
112
+ ISSUER JSON KEY_BLOCK_SIZE LEAVES LESS LINESTRING LIST
113
+ LOCKS LOGFILE LOGS MASTER MASTER_AUTO_POSITION
114
+ MASTER_CONNECT_RETRY MASTER_DELAY MASTER_HEARTBEAT_PERIOD
115
+ MASTER_HOST MASTER_LOG_FILE MASTER_LOG_POS MASTER_PASSWORD
116
+ MASTER_PORT MASTER_RETRY_COUNT MASTER_SERVER_ID MASTER_SSL
117
+ MASTER_SSL_CA MASTER_SSL_CAPATH MASTER_SSL_CERT
118
+ MASTER_SSL_CIPHER MASTER_SSL_CRL MASTER_SSL_CRLPATH
119
+ MASTER_SSL_KEY MASTER_TLS_VERSION MASTER_USER
120
+ MAX_CONNECTIONS_PER_HOUR MAX_QUERIES_PER_HOUR MAX_ROWS
121
+ MAX_SIZE MAX_STATEMENT_TIME MAX_UPDATES_PER_HOUR
122
+ MAX_USER_CONNECTIONS MEDIUM MEMORY MICROSECOND MIGRATE
123
+ MIN_ROWS MODE MODIFY MULTILINESTRING MULTIPOINT
124
+ MULTIPOLYGON MUTEX MYSQL_ERRNO NDB NDBCLUSTER NEVER
125
+ NODEGROUP NONBLOCKING NO_WAIT NVARCHAR OLD_PASSWORD ONE
126
+ OWNER PACK_KEYS PAGE PARSER PARSE_GCOL_EXPR PARTITIONING
127
+ PARTITIONS PASSWORD PHASE PLUGIN PLUGINS PLUGIN_DIR
128
+ POINT POLYGON PORT PREV PROCESSLIST PROFILE PROFILES
129
+ PROXY QUARTER QUERY QUICK READ_ONLY REBUILD RECOVER
130
+ REDOFILE REDO_BUFFER_SIZE REDUNDANT RELAY RELAYLOG
131
+ RELAY_LOG_FILE RELAY_LOG_POS RELAY_THREAD RELOAD REMOVE
132
+ REORGANIZE REPAIR REPLICATE_DO_DB REPLICATE_DO_TABLE
133
+ REPLICATE_IGNORE_DB REPLICATE_IGNORE_TABLE REPLICATE_REWRITE_DB
134
+ REPLICATE_WILD_DO_TABLE REPLICATE_WILD_IGNORE_TABLE
135
+ REPLICATION RESET RESUME REVERSE ROTATE ROW_FORMAT RTREE
136
+ SCHEDULE SERIAL SHARE SHUTDOWN SIGNED SLAVE SLOW SNAPSHOT
137
+ SOCKET SONAME SOUNDS SQL_AFTER_GTIDS SQL_AFTER_MTS_GAPS
138
+ SQL_BEFORE_GTIDS SQL_BUFFER_RESULT SQL_CACHE SQL_NO_CACHE
139
+ SQL_THREAD SQL_TSI_DAY SQL_TSI_HOUR SQL_TSI_MINUTE
140
+ SQL_TSI_MONTH SQL_TSI_QUARTER SQL_TSI_SECOND SQL_TSI_WEEK
141
+ SQL_TSI_YEAR STACKED STARTS STATS_AUTO_RECALC
142
+ STATS_PERSISTENT STATS_SAMPLE_PAGES STATUS STOP STORAGE
143
+ STRING SUBJECT SUBPARTITION SUBPARTITIONS SUPER SUSPEND
144
+ SWAPS SWITCHES TABLES TABLESPACE TABLE_CHECKSUM TEMPTABLE
145
+ TEXT THAN TIMESTAMPADD TIMESTAMPDIFF TRIGGERS TYPES
146
+ UNDEFINED UNDOFILE UNDO_BUFFER_SIZE UNICODE UNINSTALL
147
+ UPGRADE USER_RESOURCES USE_FRM VALIDATION VARIABLES
148
+ WAIT WARNINGS WEEK WEIGHT_STRING X509 XA XID
149
+ }
150
+
151
+ super + @mysql_key_words
152
+ end
153
+
154
+ def go s = ''
155
+ "#{s};\n\n"
156
+ end
157
+
158
+ def open_escape
159
+ '`'
160
+ end
161
+
162
+ def close_escape
163
+ '`'
164
+ end
165
+
166
+ def index_kind(index)
167
+ ''
168
+ end
169
+
170
+ class MySQLDataTypeContext < SQLDataTypeContext
171
+ def integer_ranges
172
+ [
173
+ ['TINYINT', -2**7, 2**7-1],
174
+ ['TINYINT UNSIGNED', 0, 2**8-1],
175
+ ['MEDIUMINT', -2**23, 2**23-1],
176
+ ] + super
177
+ end
178
+
179
+ def boolean_type
180
+ 'BOOLEAN'
181
+ end
182
+
183
+ def valid_from_type
184
+ 'DATETIME' # The TIMESTAMP type starts in 1970
185
+ end
186
+
187
+ def default_char_type
188
+ (@unicode ? 'N' : '') +
189
+ 'CHAR'
190
+ end
191
+
192
+ def default_varchar_type
193
+ (@unicode ? 'N' : '') +
194
+ 'VARCHAR'
195
+ end
196
+
197
+ def date_time_type
198
+ 'DATETIME'
199
+ end
200
+ end
201
+ end
202
+
203
+ end
204
+ publish_generator SQL::MySQL
205
+ end
206
+ end
@@ -0,0 +1,174 @@
1
+ #
2
+ # ActiveFacts Oracle SQL Schema Generator
3
+ #
4
+ # Copyright (c) 2009-2016 Clifford Heath. Read the LICENSE file.
5
+ #
6
+ # Reserved words gathered from:
7
+ # https://docs.oracle.com/cd/B28359_01/appdev.111/b31231/appb.htm
8
+ #
9
+ require 'digest/sha1'
10
+ require 'activefacts/metamodel'
11
+ require 'activefacts/compositions'
12
+ require 'activefacts/generator/sql'
13
+
14
+ module ActiveFacts
15
+ module Generators
16
+ # Options are comma or space separated:
17
+ # * underscore
18
+ class SQL
19
+ class Oracle < SQL
20
+ def self.options
21
+ super.merge({
22
+ # no: [String, "no new options defined here"]
23
+ })
24
+ end
25
+
26
+ def initialize composition, options = {}
27
+ super(composition, {'tables' => 'shout', 'columns' => 'shout'}.merge(options))
28
+ end
29
+
30
+ def table_name_max
31
+ 30
32
+ end
33
+
34
+ def data_type_context
35
+ OracleDataTypeContext.new
36
+ end
37
+
38
+ def auto_assign_modifier
39
+ ' GENERATED BY DEFAULT ON NULL AS IDENTITY'
40
+ end
41
+
42
+ def generate_schema
43
+ ''
44
+ end
45
+
46
+ def normalise_type(type_name, length, value_constraint, options)
47
+ type = MM::DataType.normalise(type_name)
48
+ case type
49
+ when MM::DataType::TYPE_Integer
50
+ if aa = options[:auto_assign]
51
+ 'LONGINTEGER'
52
+ else
53
+ super
54
+ end
55
+ when MM::DataType::TYPE_Money; 'MONEY'
56
+ when MM::DataType::TYPE_DateTime; 'DATETIME'
57
+ when MM::DataType::TYPE_Timestamp;'DATETIME'
58
+ when MM::DataType::TYPE_Binary;
59
+ if type_name =~ /^(guid|uuid)$/i && (!length || length == 16)
60
+ if ![nil, ''].include?(options[:auto_assign])
61
+ options[:default] = " DEFAULT SYS_GUID()"
62
+ options.delete(:auto_assign)
63
+ end
64
+ return ['RAW', 32]
65
+ end
66
+ ['LOB', length]
67
+ else
68
+ super
69
+ end
70
+ end
71
+
72
+ # Reserved words cannot be used anywhere without quoting.
73
+ # Keywords have existing definitions, so should not be used without quoting.
74
+ # Both lists here are added to the supertype's lists
75
+ def reserved_words
76
+ @oracle_reserved_words ||= %w{
77
+ ACCESS ARRAYLEN AUDIT CLUSTER COMMENT COMPRESS EXCLUSIVE
78
+ IDENTIFIED INDEX INITIAL LOCK LONG MAXEXTENTS MINUS
79
+ MODE MODIFY NOAUDIT NOCOMPRESS NOTFOUND NOWAIT OFFLINE
80
+ ONLINE PCTFREE RAW RENAME RESOURCE ROWID ROWLABEL ROWNUM
81
+ SHARE SQLBUF SUCCESSFUL SYNONYM SYSDATE UID VALIDATE
82
+ VARCHAR2
83
+ }
84
+ @oracle_plsql_reserved_words ||= %w{
85
+ ABORT ACCEPT ACCESS ARRAYLEN ASSERT ASSIGN BASE_TABLE
86
+ BINARY_INTEGER BODY CHAR_BASE CLUSTER CLUSTERS COLAUTH
87
+ COMPRESS CONSTANT CRASH CURRVAL DATABASE DATA_BASE DBA
88
+ DEBUGOFF DEBUGON DEFINITION DELAY DELTA DIGITS DISPOSE
89
+ ELSIF ENTRY EXCEPTION_INIT FORM GENERIC IDENTIFIED INDEX
90
+ INDEXES LIMITED MINUS MLSLABEL MODE NEXTVAL NOCOMPRESS
91
+ NUMBER_BASE PACKAGE PCTFREE POSITIVE PRAGMA PRIVATE
92
+ RAISE RECORD REMR RENAME RESOURCE REVERSE ROWID ROWLABEL
93
+ ROWNUM ROWTYPE RUN SEPARATE SQLERRM STDDEV SUBTYPE
94
+ TABAUTH TABLES TASK TERMINATE USE VARCHAR2 VARIANCE
95
+ VIEWS XOR
96
+ }
97
+ super + @oracle_reserved_words
98
+ end
99
+
100
+ def key_words
101
+ # These keywords should not be used for columns or tables:
102
+ @oracle_key_words ||= %w{
103
+ ANALYZE ARCHIVE ARCHIVELOG BACKUP BECOME BLOCK BODY
104
+ CACHE CANCEL CHANGE CHECKPOINT COMPILE CONTENTS CONTROLFILE
105
+ DATABASE DATAFILE DBA DISABLE DISMOUNT DUMP ENABLE
106
+ EVENTS EXCEPTIONS EXPLAIN EXTENT EXTERNALLY FLUSH FORCE
107
+ FREELIST FREELISTS INITRANS LAYER LISTS LOGFILE MANAGE
108
+ MANUAL MAXDATAFILES MAXINSTANCES MAXLOGFILES MAXLOGHISTORY
109
+ MAXLOGMEMBERS MAXTRANS MINEXTENTS MOUNT NOARCHIVELOG
110
+ NOCACHE NOCYCLE NOMAXVALUE NOMINVALUE NOORDER NORESETLOGS
111
+ NORMAL NOSORT OPTIMAL OWN PACKAGE PARALLEL PCTINCREASE
112
+ PCTUSED PLAN PRIVATE PROFILE QUOTA RECOVER RESETLOGS
113
+ RESTRICTED REUSE ROLES SCN SEGMENT SHARED SNAPSHOT SORT
114
+ STATEMENT_ID STATISTICS STOP STORAGE SWITCH TABLES
115
+ TABLESPACE THREAD TRACING TRIGGERS UNLIMITED USE
116
+ }
117
+ super + @oracle_key_words
118
+ end
119
+
120
+ def go s = ''
121
+ "#{s};\n\n"
122
+ end
123
+
124
+ def open_escape
125
+ '"'
126
+ end
127
+
128
+ def close_escape
129
+ '"'
130
+ end
131
+
132
+ def index_kind(index)
133
+ ''
134
+ end
135
+
136
+ class OracleDataTypeContext < SQLDataTypeContext
137
+ def integer_ranges
138
+ [
139
+ ['SHORTINTEGER', -2**15, 2**15-1], # The standard says -10^5..10^5 (less than 16 bits)
140
+ ['INTEGER', -2**31, 2**31-1], # The standard says -10^10..10^10 (more than 32 bits!)
141
+ ['LONGINTEGER', -2**63, 2**63-1], # The standard says -10^19..10^19 (less than 64 bits)
142
+ ]
143
+ end
144
+
145
+ def boolean_type
146
+ 'BOOLEAN'
147
+ end
148
+
149
+ def valid_from_type
150
+ 'TIMESTAMP'
151
+ end
152
+
153
+ # There is no performance benefit in using fixed-length CHAR fields,
154
+ # and an added burden of trimming the implicitly added white-space
155
+ def default_char_type
156
+ (@unicode ? 'N' : '') +
157
+ 'VARCHAR'
158
+ end
159
+
160
+ def default_varchar_type
161
+ (@unicode ? 'N' : '') +
162
+ 'VARCHAR'
163
+ end
164
+
165
+ def date_time_type
166
+ 'TIMESTAMP'
167
+ end
168
+ end
169
+ end
170
+
171
+ end
172
+ publish_generator SQL::Oracle
173
+ end
174
+ end
@@ -1,7 +1,10 @@
1
1
  #
2
- # ActiveFacts Standard SQL Schema Generator
2
+ # ActiveFacts PostgreSQL Schema Generator
3
3
  #
4
- # Copyright (c) 2009-2016 Clifford Heath. Read the LICENSE file.
4
+ # Copyright (c) 2017 Clifford Heath. Read the LICENSE file.
5
+ #
6
+ # Reserved words gathered from:
7
+ # https://www.postgresql.org/docs/9.5/static/sql-keywords-appendix.html
5
8
  #
6
9
  require 'digest/sha1'
7
10
  require 'activefacts/metamodel'
@@ -29,7 +32,7 @@ module ActiveFacts
29
32
  end
30
33
 
31
34
  def data_type_context
32
- PostgresqlDataTypeContext.new
35
+ PostgresDataTypeContext.new
33
36
  end
34
37
 
35
38
  def auto_assign_modifier
@@ -61,8 +64,8 @@ module ActiveFacts
61
64
  super
62
65
  end
63
66
  when MM::DataType::TYPE_Money; 'MONEY'
64
- when MM::DataType::TYPE_DateTime; 'DATETIME'
65
- when MM::DataType::TYPE_Timestamp;'DATETIME'
67
+ when MM::DataType::TYPE_DateTime; 'TIMESTAMP'
68
+ when MM::DataType::TYPE_Timestamp;'TIMESTAMP'
66
69
  when MM::DataType::TYPE_Binary;
67
70
  if length && length <= 8192
68
71
  super
@@ -127,7 +130,7 @@ module ActiveFacts
127
130
  ''
128
131
  end
129
132
 
130
- class PostgresqlDataTypeContext < SQLDataTypeContext
133
+ class PostgresDataTypeContext < SQLDataTypeContext
131
134
  def integer_ranges
132
135
  super
133
136
  end
@@ -1,8 +1,11 @@
1
1
  #
2
- # ActiveFacts Standard SQL Schema Generator
2
+ # ActiveFacts SQL Server Schema Generator
3
3
  #
4
4
  # Copyright (c) 2009-2016 Clifford Heath. Read the LICENSE file.
5
5
  #
6
+ # Reserved words gathered from:
7
+ # https://technet.microsoft.com/en-us/library/ms189822(v=sql.110).aspx
8
+ #
6
9
  require 'digest/sha1'
7
10
  require 'activefacts/metamodel'
8
11
  require 'activefacts/compositions'
@@ -32,15 +35,20 @@ module ActiveFacts
32
35
  ' IDENTITY'
33
36
  end
34
37
 
35
- def normalise_type(type_name, length, value_constraint)
36
- return ['UNIQUEIDENTIFIER', 16] if type_name =~ /^(guid|uuid)$/i
37
-
38
+ def normalise_type(type_name, length, value_constraint, options)
38
39
  type = MM::DataType.normalise(type_name)
39
40
  case type
40
41
  when MM::DataType::TYPE_Money; 'MONEY'
41
42
  when MM::DataType::TYPE_DateTime; 'DATETIME'
42
43
  when MM::DataType::TYPE_Timestamp;'DATETIME'
43
44
  when MM::DataType::TYPE_Binary;
45
+ if type_name =~ /^(guid|uuid)$/i && (!length || length == 16)
46
+ if ![nil, ''].include?(options[:auto_assign])
47
+ options[:default] = ' DEFAULT NEWID()'
48
+ options.delete(:auto_assign)
49
+ end
50
+ return 'UNIQUEIDENTIFIER'
51
+ end
44
52
  if length && length <= 8192
45
53
  super
46
54
  else
@@ -3,6 +3,10 @@
3
3
  #
4
4
  # Copyright (c) 2009-2016 Clifford Heath. Read the LICENSE file.
5
5
  #
6
+ # Reserved words for various versions of the standard gathered from:
7
+ # http://developer.mimer.se/validator/sql-reserved-words.tml
8
+ # https://www.postgresql.org/docs/9.5/static/sql-keywords-appendix.html
9
+ #
6
10
  require 'digest/sha1'
7
11
  require 'activefacts/metamodel'
8
12
  require 'activefacts/metamodel/datatypes'
@@ -247,7 +251,12 @@ module ActiveFacts
247
251
  when MM::DataType::TYPE_DateTime; 'TIMESTAMP'
248
252
  when MM::DataType::TYPE_Timestamp;'TIMESTAMP'
249
253
  when MM::DataType::TYPE_Binary;
250
- length ||= 16 if type_name =~ /^(guid|uuid)$/i
254
+ if type_name =~ /^(guid|uuid)$/i && (!length || length == 16)
255
+ length ||= 16
256
+ if ![nil, ''].include?(options[:auto_assign])
257
+ options.delete(:auto_assign) # Don't auto-assign foreign keys
258
+ end
259
+ end
251
260
  if length
252
261
  ['BINARY', length]
253
262
  else
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activefacts-compositions
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.15
4
+ version: 1.9.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clifford Heath
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-09 00:00:00.000000000 Z
11
+ date: 2017-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -149,7 +149,7 @@ dependencies:
149
149
  version: '1'
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
- version: 1.9.19
152
+ version: 1.9.20
153
153
  type: :runtime
154
154
  prerelease: false
155
155
  version_requirements: !ruby/object:Gem::Requirement
@@ -159,7 +159,7 @@ dependencies:
159
159
  version: '1'
160
160
  - - ">="
161
161
  - !ruby/object:Gem::Version
162
- version: 1.9.19
162
+ version: 1.9.20
163
163
  - !ruby/object:Gem::Dependency
164
164
  name: activefacts-cql
165
165
  requirement: !ruby/object:Gem::Requirement
@@ -169,7 +169,7 @@ dependencies:
169
169
  version: '1'
170
170
  - - ">="
171
171
  - !ruby/object:Gem::Version
172
- version: '1.9'
172
+ version: 1.9.3
173
173
  type: :runtime
174
174
  prerelease: false
175
175
  version_requirements: !ruby/object:Gem::Requirement
@@ -179,7 +179,7 @@ dependencies:
179
179
  version: '1'
180
180
  - - ">="
181
181
  - !ruby/object:Gem::Version
182
- version: '1.9'
182
+ version: 1.9.3
183
183
  description: Create and represent composite schemas, schema transforms and data transforms
184
184
  over a fact-based model
185
185
  email:
@@ -209,6 +209,7 @@ files:
209
209
  - lib/activefacts/compositions/names.rb
210
210
  - lib/activefacts/compositions/relational.rb
211
211
  - lib/activefacts/compositions/staging.rb
212
+ - lib/activefacts/compositions/traits/datavault.rb
212
213
  - lib/activefacts/compositions/traits/rails.rb
213
214
  - lib/activefacts/compositions/version.rb
214
215
  - lib/activefacts/generator.rb
@@ -222,6 +223,8 @@ files:
222
223
  - lib/activefacts/generator/rails/schema.rb
223
224
  - lib/activefacts/generator/ruby.rb
224
225
  - lib/activefacts/generator/sql.rb
226
+ - lib/activefacts/generator/sql/mysql.rb
227
+ - lib/activefacts/generator/sql/oracle.rb
225
228
  - lib/activefacts/generator/sql/postgres.rb
226
229
  - lib/activefacts/generator/sql/server.rb
227
230
  - lib/activefacts/generator/summary.rb