activefacts-compositions 1.9.15 → 1.9.16

Sign up to get free protection for your applications and to get access to all the features.
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