masamune 0.11.0

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.
Files changed (185) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +54 -0
  4. data/Rakefile +15 -0
  5. data/bin/masamune-elastic-mapreduce +4 -0
  6. data/bin/masamune-hive +4 -0
  7. data/bin/masamune-psql +4 -0
  8. data/bin/masamune-shell +4 -0
  9. data/lib/masamune.rb +56 -0
  10. data/lib/masamune/accumulate.rb +60 -0
  11. data/lib/masamune/actions.rb +38 -0
  12. data/lib/masamune/actions/data_flow.rb +131 -0
  13. data/lib/masamune/actions/date_parse.rb +75 -0
  14. data/lib/masamune/actions/elastic_mapreduce.rb +68 -0
  15. data/lib/masamune/actions/execute.rb +52 -0
  16. data/lib/masamune/actions/filesystem.rb +37 -0
  17. data/lib/masamune/actions/hadoop_filesystem.rb +40 -0
  18. data/lib/masamune/actions/hadoop_streaming.rb +41 -0
  19. data/lib/masamune/actions/hive.rb +74 -0
  20. data/lib/masamune/actions/postgres.rb +76 -0
  21. data/lib/masamune/actions/postgres_admin.rb +34 -0
  22. data/lib/masamune/actions/s3cmd.rb +44 -0
  23. data/lib/masamune/actions/transform.rb +89 -0
  24. data/lib/masamune/after_initialize_callbacks.rb +55 -0
  25. data/lib/masamune/cached_filesystem.rb +110 -0
  26. data/lib/masamune/commands.rb +37 -0
  27. data/lib/masamune/commands/elastic_mapreduce.rb +119 -0
  28. data/lib/masamune/commands/hadoop_filesystem.rb +57 -0
  29. data/lib/masamune/commands/hadoop_streaming.rb +116 -0
  30. data/lib/masamune/commands/hive.rb +178 -0
  31. data/lib/masamune/commands/interactive.rb +37 -0
  32. data/lib/masamune/commands/postgres.rb +128 -0
  33. data/lib/masamune/commands/postgres_admin.rb +72 -0
  34. data/lib/masamune/commands/postgres_common.rb +33 -0
  35. data/lib/masamune/commands/retry_with_backoff.rb +60 -0
  36. data/lib/masamune/commands/s3cmd.rb +70 -0
  37. data/lib/masamune/commands/shell.rb +202 -0
  38. data/lib/masamune/configuration.rb +195 -0
  39. data/lib/masamune/data_plan.rb +31 -0
  40. data/lib/masamune/data_plan/builder.rb +66 -0
  41. data/lib/masamune/data_plan/elem.rb +190 -0
  42. data/lib/masamune/data_plan/engine.rb +162 -0
  43. data/lib/masamune/data_plan/rule.rb +292 -0
  44. data/lib/masamune/data_plan/set.rb +176 -0
  45. data/lib/masamune/environment.rb +164 -0
  46. data/lib/masamune/filesystem.rb +567 -0
  47. data/lib/masamune/has_environment.rb +40 -0
  48. data/lib/masamune/helpers.rb +27 -0
  49. data/lib/masamune/helpers/postgres.rb +84 -0
  50. data/lib/masamune/io.rb +33 -0
  51. data/lib/masamune/last_element.rb +53 -0
  52. data/lib/masamune/method_logger.rb +41 -0
  53. data/lib/masamune/multi_io.rb +39 -0
  54. data/lib/masamune/schema.rb +36 -0
  55. data/lib/masamune/schema/catalog.rb +233 -0
  56. data/lib/masamune/schema/column.rb +527 -0
  57. data/lib/masamune/schema/dimension.rb +133 -0
  58. data/lib/masamune/schema/event.rb +121 -0
  59. data/lib/masamune/schema/fact.rb +133 -0
  60. data/lib/masamune/schema/map.rb +265 -0
  61. data/lib/masamune/schema/row.rb +133 -0
  62. data/lib/masamune/schema/store.rb +115 -0
  63. data/lib/masamune/schema/table.rb +308 -0
  64. data/lib/masamune/schema/table_reference.rb +76 -0
  65. data/lib/masamune/spec_helper.rb +23 -0
  66. data/lib/masamune/string_format.rb +34 -0
  67. data/lib/masamune/tasks/elastic_mapreduce_thor.rb +60 -0
  68. data/lib/masamune/tasks/hive_thor.rb +55 -0
  69. data/lib/masamune/tasks/postgres_thor.rb +47 -0
  70. data/lib/masamune/tasks/shell_thor.rb +63 -0
  71. data/lib/masamune/template.rb +77 -0
  72. data/lib/masamune/thor.rb +186 -0
  73. data/lib/masamune/thor_loader.rb +38 -0
  74. data/lib/masamune/topological_hash.rb +34 -0
  75. data/lib/masamune/transform.rb +47 -0
  76. data/lib/masamune/transform/bulk_upsert.psql.erb +64 -0
  77. data/lib/masamune/transform/bulk_upsert.rb +52 -0
  78. data/lib/masamune/transform/consolidate_dimension.rb +54 -0
  79. data/lib/masamune/transform/deduplicate_dimension.psql.erb +52 -0
  80. data/lib/masamune/transform/deduplicate_dimension.rb +53 -0
  81. data/lib/masamune/transform/define_event_view.hql.erb +51 -0
  82. data/lib/masamune/transform/define_event_view.rb +60 -0
  83. data/lib/masamune/transform/define_index.psql.erb +34 -0
  84. data/lib/masamune/transform/define_schema.hql.erb +23 -0
  85. data/lib/masamune/transform/define_schema.psql.erb +79 -0
  86. data/lib/masamune/transform/define_schema.rb +56 -0
  87. data/lib/masamune/transform/define_table.hql.erb +34 -0
  88. data/lib/masamune/transform/define_table.psql.erb +95 -0
  89. data/lib/masamune/transform/define_table.rb +40 -0
  90. data/lib/masamune/transform/define_unique.psql.erb +30 -0
  91. data/lib/masamune/transform/insert_reference_values.psql.erb +43 -0
  92. data/lib/masamune/transform/insert_reference_values.rb +64 -0
  93. data/lib/masamune/transform/load_dimension.rb +47 -0
  94. data/lib/masamune/transform/load_fact.rb +45 -0
  95. data/lib/masamune/transform/operator.rb +96 -0
  96. data/lib/masamune/transform/relabel_dimension.psql.erb +76 -0
  97. data/lib/masamune/transform/relabel_dimension.rb +39 -0
  98. data/lib/masamune/transform/rollup_fact.psql.erb +79 -0
  99. data/lib/masamune/transform/rollup_fact.rb +149 -0
  100. data/lib/masamune/transform/snapshot_dimension.psql.erb +75 -0
  101. data/lib/masamune/transform/snapshot_dimension.rb +74 -0
  102. data/lib/masamune/transform/stage_dimension.psql.erb +39 -0
  103. data/lib/masamune/transform/stage_dimension.rb +83 -0
  104. data/lib/masamune/transform/stage_fact.psql.erb +80 -0
  105. data/lib/masamune/transform/stage_fact.rb +111 -0
  106. data/lib/masamune/version.rb +25 -0
  107. data/spec/fixtures/aggregate.sql.erb +25 -0
  108. data/spec/fixtures/comment.sql.erb +27 -0
  109. data/spec/fixtures/invalid.sql.erb +23 -0
  110. data/spec/fixtures/relative.sql.erb +23 -0
  111. data/spec/fixtures/simple.sql.erb +28 -0
  112. data/spec/fixtures/whitespace.sql.erb +30 -0
  113. data/spec/masamune/actions/elastic_mapreduce_spec.rb +108 -0
  114. data/spec/masamune/actions/execute_spec.rb +50 -0
  115. data/spec/masamune/actions/hadoop_filesystem_spec.rb +44 -0
  116. data/spec/masamune/actions/hadoop_streaming_spec.rb +74 -0
  117. data/spec/masamune/actions/hive_spec.rb +117 -0
  118. data/spec/masamune/actions/postgres_admin_spec.rb +58 -0
  119. data/spec/masamune/actions/postgres_spec.rb +134 -0
  120. data/spec/masamune/actions/s3cmd_spec.rb +44 -0
  121. data/spec/masamune/actions/transform_spec.rb +144 -0
  122. data/spec/masamune/after_initialization_callbacks_spec.rb +61 -0
  123. data/spec/masamune/cached_filesystem_spec.rb +167 -0
  124. data/spec/masamune/commands/hadoop_filesystem_spec.rb +50 -0
  125. data/spec/masamune/commands/hadoop_streaming_spec.rb +106 -0
  126. data/spec/masamune/commands/hive_spec.rb +117 -0
  127. data/spec/masamune/commands/postgres_admin_spec.rb +69 -0
  128. data/spec/masamune/commands/postgres_spec.rb +100 -0
  129. data/spec/masamune/commands/retry_with_backoff_spec.rb +116 -0
  130. data/spec/masamune/commands/s3cmd_spec.rb +50 -0
  131. data/spec/masamune/commands/shell_spec.rb +101 -0
  132. data/spec/masamune/configuration_spec.rb +102 -0
  133. data/spec/masamune/data_plan/builder_spec.rb +91 -0
  134. data/spec/masamune/data_plan/elem_spec.rb +102 -0
  135. data/spec/masamune/data_plan/engine_spec.rb +356 -0
  136. data/spec/masamune/data_plan/rule_spec.rb +407 -0
  137. data/spec/masamune/data_plan/set_spec.rb +517 -0
  138. data/spec/masamune/environment_spec.rb +65 -0
  139. data/spec/masamune/filesystem_spec.rb +1421 -0
  140. data/spec/masamune/helpers/postgres_spec.rb +95 -0
  141. data/spec/masamune/schema/catalog_spec.rb +613 -0
  142. data/spec/masamune/schema/column_spec.rb +696 -0
  143. data/spec/masamune/schema/dimension_spec.rb +137 -0
  144. data/spec/masamune/schema/event_spec.rb +75 -0
  145. data/spec/masamune/schema/fact_spec.rb +117 -0
  146. data/spec/masamune/schema/map_spec.rb +593 -0
  147. data/spec/masamune/schema/row_spec.rb +28 -0
  148. data/spec/masamune/schema/store_spec.rb +49 -0
  149. data/spec/masamune/schema/table_spec.rb +395 -0
  150. data/spec/masamune/string_format_spec.rb +60 -0
  151. data/spec/masamune/tasks/elastic_mapreduce_thor_spec.rb +57 -0
  152. data/spec/masamune/tasks/hive_thor_spec.rb +75 -0
  153. data/spec/masamune/tasks/postgres_thor_spec.rb +42 -0
  154. data/spec/masamune/tasks/shell_thor_spec.rb +51 -0
  155. data/spec/masamune/template_spec.rb +77 -0
  156. data/spec/masamune/thor_spec.rb +238 -0
  157. data/spec/masamune/transform/bulk_upsert.dimension_spec.rb +200 -0
  158. data/spec/masamune/transform/consolidate_dimension_spec.rb +62 -0
  159. data/spec/masamune/transform/deduplicate_dimension_spec.rb +84 -0
  160. data/spec/masamune/transform/define_event_view_spec.rb +84 -0
  161. data/spec/masamune/transform/define_schema_spec.rb +83 -0
  162. data/spec/masamune/transform/define_table.dimension_spec.rb +306 -0
  163. data/spec/masamune/transform/define_table.fact_spec.rb +291 -0
  164. data/spec/masamune/transform/define_table.table_spec.rb +525 -0
  165. data/spec/masamune/transform/insert_reference_values.dimension_spec.rb +111 -0
  166. data/spec/masamune/transform/insert_reference_values.fact_spec.rb +149 -0
  167. data/spec/masamune/transform/load_dimension_spec.rb +76 -0
  168. data/spec/masamune/transform/load_fact_spec.rb +89 -0
  169. data/spec/masamune/transform/relabel_dimension_spec.rb +102 -0
  170. data/spec/masamune/transform/rollup_fact_spec.rb +333 -0
  171. data/spec/masamune/transform/snapshot_dimension_spec.rb +103 -0
  172. data/spec/masamune/transform/stage_dimension_spec.rb +115 -0
  173. data/spec/masamune/transform/stage_fact_spec.rb +204 -0
  174. data/spec/masamune_spec.rb +32 -0
  175. data/spec/spec_helper.rb +41 -0
  176. data/spec/support/masamune/example_group.rb +36 -0
  177. data/spec/support/masamune/mock_command.rb +99 -0
  178. data/spec/support/masamune/mock_delegate.rb +51 -0
  179. data/spec/support/masamune/mock_filesystem.rb +96 -0
  180. data/spec/support/masamune/thor_mute.rb +35 -0
  181. data/spec/support/rspec/example/action_example_group.rb +34 -0
  182. data/spec/support/rspec/example/task_example_group.rb +80 -0
  183. data/spec/support/rspec/example/transform_example_group.rb +36 -0
  184. data/spec/support/shared_examples/postgres_common_examples.rb +53 -0
  185. metadata +462 -0
@@ -0,0 +1,186 @@
1
+ # The MIT License (MIT)
2
+ #
3
+ # Copyright (c) 2014-2015, VMware, Inc. All Rights Reserved.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require 'date'
24
+ require 'thor'
25
+ require 'active_support/concern'
26
+
27
+ require 'masamune/after_initialize_callbacks'
28
+
29
+ module Masamune
30
+ module Thor
31
+ extend ActiveSupport::Concern
32
+
33
+ include Masamune::HasEnvironment
34
+ include Masamune::AfterInitializeCallbacks
35
+
36
+ SYSTEM_CONFIG_FILES = [
37
+ '/etc/masamune/config.yml',
38
+ '/etc/masamune/config.yml.erb',
39
+ '/opt/masamune/etc/config.yml',
40
+ '/opt/masamune/etc/config.yml.erb',
41
+ '/opt/etc/masamune/config.yml',
42
+ '/opt/etc/masamune/config.yml.erb',
43
+ "#{ENV['HOME']}/.masamune/config.yml"
44
+ ]
45
+
46
+ module ExtraArguments
47
+ def parse_extra(argv)
48
+ if i = argv.index('--')
49
+ if i > 0
50
+ [argv[0 .. i-1], argv[i+1..-1]]
51
+ else
52
+ [[], argv[i+1..-1]]
53
+ end
54
+ else
55
+ [argv, []]
56
+ end
57
+ end
58
+ end
59
+
60
+ module RescueLogger
61
+ def instance=(instance)
62
+ @instance = instance
63
+ end
64
+
65
+ def instance
66
+ @instance || Masamune
67
+ end
68
+
69
+ def start(*a)
70
+ super
71
+ rescue SignalException => e
72
+ raise e unless %w(SIGHUP SIGTERM).include?(e.to_s)
73
+ instance.logger.debug("Exiting at user request on #{e.to_s}")
74
+ exit 0
75
+ rescue => e
76
+ instance.logger.error("#{e.message} (#{e.class}) backtrace:")
77
+ e.backtrace.each { |x| instance.logger.error(x) }
78
+ $stderr.puts "For complete debug log see: #{instance.log_file_name.to_s}"
79
+ raise e
80
+ end
81
+ end
82
+
83
+ included do |thor|
84
+ thor.extend ExtraArguments
85
+ thor.extend RescueLogger
86
+ thor.class_eval do
87
+ include Masamune::Actions::Filesystem
88
+
89
+ attr_accessor :current_namespace
90
+ attr_accessor :current_task_name
91
+ attr_accessor :current_command_name
92
+ attr_accessor :extra
93
+
94
+ namespace :masamune
95
+ class_option :help, :type => :boolean, :aliases => '-h', :desc => 'Show help', :default => false
96
+ class_option :quiet, :type => :boolean, :aliases => '-q', :desc => 'Suppress all output', :default => false
97
+ class_option :verbose, :type => :boolean, :aliases => '-v', :desc => 'Print command execution information', :default => false
98
+ class_option :debug, :type => :boolean, :aliases => '-d', :desc => 'Print debugging information', :default => false
99
+ class_option :no_op, :type => :boolean, :desc => 'Do not execute commands that modify state', :default => false
100
+ class_option :dry_run, :type => :boolean, :aliases => '-n', :desc => 'Combination of --no-op and --verbose', :default => false
101
+ class_option :config, :desc => 'Configuration file'
102
+ class_option :version, :desc => 'Print version and exit', :type => :boolean
103
+ class_option :lock, :desc => 'Optional job lock name', :type => :string
104
+ class_option :'--', :desc => 'Extra pass through arguments'
105
+ def initialize(_args=[], _options={}, _config={})
106
+ self.environment.parent = self
107
+ self.filesystem.environment = self
108
+ self.current_namespace = self.class.namespace unless self.class.namespace == 'masamune'
109
+ self.current_task_name = _config[:current_command].name
110
+ self.current_command_name = current_namespace ? current_namespace + ':' + current_task_name : current_task_name
111
+ self.class.instance = self
112
+
113
+ if _options.is_a?(Array)
114
+ _options, self.extra = self.class.parse_extra(_options)
115
+ end
116
+
117
+ super _args, _options, _config
118
+
119
+ if display_help?
120
+ display_help
121
+ exit
122
+ end
123
+
124
+ environment.configure do |config|
125
+ config_file = options[:config]
126
+ config_file ||= config.filesystem.resolve_file([config.default_config_file] + SYSTEM_CONFIG_FILES)
127
+ raise ::Thor::RequiredArgumentMissingError, 'Option --config or valid system configuration file required' unless config_file
128
+
129
+ begin
130
+ config.load(config_file)
131
+ rescue
132
+ raise $! if options[:debug]
133
+ raise ::Thor::MalformattedArgumentError, "Could not load file provided for '--config'"
134
+ end
135
+
136
+ config.quiet = options[:quiet]
137
+ config.verbose = options[:verbose] || options[:dry_run]
138
+ config.debug = options[:debug]
139
+ config.no_op = options[:no_op] || options[:dry_run]
140
+ config.dry_run = options[:dry_run]
141
+ config.lock = options[:lock]
142
+
143
+ if options[:version]
144
+ puts environment.version
145
+ puts options if options[:verbose]
146
+ puts config.to_s if options[:verbose]
147
+ exit
148
+ end
149
+ end
150
+
151
+ after_initialize_invoke(options.symbolize_keys)
152
+ end
153
+
154
+ no_tasks do
155
+ def param(key)
156
+ environment.configuration.params[key]
157
+ end
158
+
159
+ def top_level?
160
+ self.current_command_name == ARGV.first
161
+ end
162
+ end
163
+
164
+ private
165
+
166
+ def display_help?
167
+ options[:help] || current_task_name == 'help'
168
+ end
169
+
170
+ def display_help
171
+ if options[:help]
172
+ help current_task_name
173
+ elsif current_task_name == 'help'
174
+ help args.first || default_and_only_command
175
+ else
176
+ help
177
+ end
178
+ end
179
+
180
+ def default_and_only_command
181
+ self.class.default_command if self.class.tasks.count == 1
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,38 @@
1
+ # The MIT License (MIT)
2
+ #
3
+ # Copyright (c) 2014-2015, VMware, Inc. All Rights Reserved.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module Masamune
24
+ module ThorLoader
25
+ def self.load_default_tasks
26
+ Masamune::ThorLoader.load_thorfiles(File.expand_path('../../../lib/masamune/tasks', __FILE__))
27
+ end
28
+
29
+ def self.load_thorfiles(dir)
30
+ Dir.chdir(dir) do
31
+ thor_files = Dir.glob('**/*.rb').delete_if { |x| not File.file?(x) }
32
+ thor_files.each do |f|
33
+ ::Thor::Util.load_thorfile(f)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,34 @@
1
+ # The MIT License (MIT)
2
+ #
3
+ # Copyright (c) 2014-2015, VMware, Inc. All Rights Reserved.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require 'tsort'
24
+
25
+ module Masamune
26
+ class TopologicalHash < Hash
27
+ include TSort
28
+
29
+ alias tsort_each_node each_key
30
+ def tsort_each_child(node, &block)
31
+ fetch(node).each(&block)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,47 @@
1
+ # The MIT License (MIT)
2
+ #
3
+ # Copyright (c) 2014-2015, VMware, Inc. All Rights Reserved.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module Masamune
24
+ module Transform
25
+ require 'masamune/transform/operator'
26
+
27
+ require 'masamune/transform/define_table'
28
+ require 'masamune/transform/define_event_view'
29
+ require 'masamune/transform/define_schema'
30
+
31
+ require 'masamune/transform/bulk_upsert'
32
+ require 'masamune/transform/insert_reference_values'
33
+
34
+ require 'masamune/transform/stage_dimension'
35
+ require 'masamune/transform/stage_fact'
36
+
37
+ require 'masamune/transform/load_dimension'
38
+ require 'masamune/transform/load_fact'
39
+
40
+ require 'masamune/transform/snapshot_dimension'
41
+ require 'masamune/transform/deduplicate_dimension'
42
+ require 'masamune/transform/consolidate_dimension'
43
+ require 'masamune/transform/relabel_dimension'
44
+
45
+ require 'masamune/transform/rollup_fact'
46
+ end
47
+ end
@@ -0,0 +1,64 @@
1
+ -- The MIT License (MIT)
2
+ --
3
+ -- Copyright (c) 2014-2015, VMware, Inc. All Rights Reserved.
4
+ --
5
+ -- Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ -- of this software and associated documentation files (the "Software"), to deal
7
+ -- in the Software without restriction, including without limitation the rights
8
+ -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ -- copies of the Software, and to permit persons to whom the Software is
10
+ -- furnished to do so, subject to the following conditions:
11
+ --
12
+ -- The above copyright notice and this permission notice shall be included in
13
+ -- all copies or substantial portions of the Software.
14
+ --
15
+ -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ -- THE SOFTWARE.
22
+
23
+ BEGIN;
24
+ LOCK TABLE <%= target.name %> IN EXCLUSIVE MODE;
25
+
26
+ <%- if target.update_columns.any? -%>
27
+ UPDATE
28
+ <%= target.name %>
29
+ SET
30
+ <%- target.update_columns.each do |column, last| -%>
31
+ <%= column.name %> = COALESCE(<%= source.name %>.<%= column.name %>, <%= target.name %>.<%= column.name %>)<%= ',' unless last %>
32
+ <%- end -%>
33
+ FROM
34
+ <%= source.name %>
35
+ WHERE
36
+ <%- target.unique_columns.each do |column, last| -%>
37
+ <%= target.name %>.<%= column.name %> = <%= source.name %>.<%= column.name %><%= ' AND' unless last %>
38
+ <%- end -%>
39
+ ;
40
+ <%- end -%>
41
+
42
+ <%- if target.unique_columns.any? -%>
43
+ INSERT INTO
44
+ <%= target.name %> (<%= target.insert_columns.map { |column,_| column.name }.join(', ') %>)
45
+ SELECT
46
+ <%- target.insert_columns.each do |column, last| -%>
47
+ <%= source.name %>.<%= column.name %><%= ',' unless last %>
48
+ <%- end -%>
49
+ FROM
50
+ <%= source.name %>
51
+ LEFT OUTER JOIN
52
+ <%= target.name %>
53
+ ON
54
+ <%- target.unique_columns.each do |column, last| -%>
55
+ <%= target.name %>.<%= column.name %> = <%= source.name %>.<%= column.name %><%= ' AND' unless last %>
56
+ <%- end -%>
57
+ WHERE
58
+ <%- target.unique_columns.each do |column, last| -%>
59
+ <%= target.name %>.<%= column.name %> IS NULL<%= ' AND' unless last %>
60
+ <%- end -%>
61
+ ;
62
+ <%- end -%>
63
+
64
+ COMMIT;
@@ -0,0 +1,52 @@
1
+ # The MIT License (MIT)
2
+ #
3
+ # Copyright (c) 2014-2015, VMware, Inc. All Rights Reserved.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module Masamune::Transform
24
+ module BulkUpsert
25
+ extend ActiveSupport::Concern
26
+
27
+ def bulk_upsert(source, target)
28
+ Operator.new(__method__, source: source, target: target, presenters: { postgres: Postgres})
29
+ end
30
+
31
+ private
32
+
33
+ class Postgres < SimpleDelegator
34
+ include Masamune::LastElement
35
+
36
+ def update_columns
37
+ columns.values.reject { |column| reserved_column_ids.include?(column.id) || column.surrogate_key || column.natural_key || column.unique.any? || column.auto_reference || column.ignore }
38
+ end
39
+ method_with_last_element :update_columns
40
+
41
+ def insert_columns
42
+ columns.values.reject { |column| column.surrogate_key || column.auto_reference || column.ignore }
43
+ end
44
+ method_with_last_element :insert_columns
45
+
46
+ def unique_columns
47
+ columns.values.select { |column| column.unique.any? && !column.null }
48
+ end
49
+ method_with_last_element :unique_columns
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,54 @@
1
+ # The MIT License (MIT)
2
+ #
3
+ # Copyright (c) 2014-2015, VMware, Inc. All Rights Reserved.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require 'masamune/transform/define_table'
24
+ require 'masamune/transform/snapshot_dimension'
25
+ require 'masamune/transform/bulk_upsert'
26
+ require 'masamune/transform/deduplicate_dimension'
27
+ require 'masamune/transform/relabel_dimension'
28
+
29
+ module Masamune::Transform
30
+ module ConsolidateDimension
31
+ include DefineTable
32
+ include BulkUpsert
33
+ include SnapshotDimension
34
+ include DeduplicateDimension
35
+ include RelabelDimension
36
+
37
+ extend ActiveSupport::Concern
38
+
39
+ def consolidate_dimension(target)
40
+ Operator.new \
41
+ define_table(target.stage_table(suffix: 'consolidated_forward')),
42
+ define_table(target.stage_table(suffix: 'consolidated_reverse')),
43
+ define_table(target.stage_table(suffix: 'consolidated')),
44
+ define_table(target.stage_table(suffix: 'deduplicated')),
45
+ snapshot_dimension(target.ledger_table, target.stage_table(suffix: 'consolidated_forward'), 'ASC'),
46
+ snapshot_dimension(target.ledger_table, target.stage_table(suffix: 'consolidated_reverse'), 'DESC'),
47
+ bulk_upsert(target.stage_table(suffix: 'consolidated_forward'), target.stage_table(suffix: 'consolidated')),
48
+ bulk_upsert(target.stage_table(suffix: 'consolidated_reverse'), target.stage_table(suffix: 'consolidated')),
49
+ deduplicate_dimension(target.stage_table(suffix: 'consolidated'), target.stage_table(suffix: 'deduplicated')),
50
+ bulk_upsert(target.stage_table(suffix: 'deduplicated'), target),
51
+ relabel_dimension(target)
52
+ end
53
+ end
54
+ end