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,116 @@
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 'delegate'
24
+ require 'active_support/core_ext/array'
25
+
26
+ module Masamune::Commands
27
+ class HadoopStreaming < SimpleDelegator
28
+ def self.default_hadoop_streaming_jar
29
+ @default_hadoop_streaming_jar ||=
30
+ case RUBY_PLATFORM
31
+ when /darwin/
32
+ Dir.glob('/usr/local/Cellar/hadoop/**/hadoop-streaming-*.jar').first
33
+ when /linux/
34
+ '/usr/lib/hadoop-mapreduce/hadoop-streaming.jar'
35
+ else
36
+ raise "unknown RUBY_PLATFORM=#{RUBY_PLATFORM}"
37
+ end
38
+ end
39
+
40
+ DEFAULT_ATTRIBUTES =
41
+ {
42
+ :path => 'hadoop',
43
+ :options => [],
44
+ :jar => default_hadoop_streaming_jar,
45
+ :input => [],
46
+ :output => nil,
47
+ :mapper => nil,
48
+ :reducer => nil,
49
+ :extra => [],
50
+ :upload => true,
51
+ :quote => false
52
+ }
53
+
54
+ attr_reader :input
55
+
56
+ def initialize(delegate, attrs = {})
57
+ super delegate
58
+ DEFAULT_ATTRIBUTES.merge(configuration.hadoop_streaming).merge(attrs).each do |name, value|
59
+ instance_variable_set("@#{name}", value)
60
+ end
61
+ @input = Array.wrap(@input)
62
+ end
63
+
64
+ # TODO ensure jar/ mapper/reduce exists, warn or remove if output exists
65
+ def command_args
66
+ args = []
67
+ args << @path
68
+ args << ['jar', @jar]
69
+ args << (@quote ? @extra.map { |arg| quote_arg(arg) } : @extra)
70
+ args << @options.map(&:to_a)
71
+ args << ['-input', *@input] if @input
72
+ args << ['-mapper', @mapper]
73
+ args << ['-file', @mapper] if @upload
74
+ args << ['-reducer', @reducer] if @reducer
75
+ args << ['-file', @reducer] if @upload && @reducer
76
+ args << ['-output', @output]
77
+ args.flatten
78
+ end
79
+
80
+ def before_execute
81
+ @input.reject! do |path|
82
+ if filesystem.exists?(path)
83
+ false
84
+ else
85
+ logger.debug("Removing missing input #{path} from hadoop_streaming command")
86
+ true
87
+ end
88
+ end
89
+ @input.map! do |path|
90
+ if path =~ /part_.*\Z/ || path =~ /\..*\Z/
91
+ path
92
+ elsif path =~ %r{/\Z}
93
+ path + '*'
94
+ else
95
+ path + '/*'
96
+ end
97
+ end
98
+ console("hadoop_streaming %s -> %s (%s/%s)" % [@input.join(' '), @output, @mapper, @reducer])
99
+ end
100
+
101
+ def around_execute(&block)
102
+ Dir.chdir(filesystem.path(:run_dir)) do
103
+ yield
104
+ end
105
+ end
106
+
107
+ private
108
+
109
+ # FIXME shell quoting is a separate concern
110
+ def quote_arg(arg)
111
+ out = arg.dup
112
+ out.gsub!(%q('\t'), %q('"'\\\\\\\\t'"'))
113
+ out
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,178 @@
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 'delegate'
24
+ require 'csv'
25
+
26
+ require 'masamune/string_format'
27
+ require 'masamune/commands/shell'
28
+
29
+ module Masamune::Commands
30
+ class Hive < SimpleDelegator
31
+ include Masamune::StringFormat
32
+
33
+ PROMPT = 'hive>'
34
+
35
+ DEFAULT_ATTRIBUTES =
36
+ {
37
+ :path => 'hive',
38
+ :options => [],
39
+ :database => 'default',
40
+ :setup_files => [],
41
+ :schema_files => [],
42
+ :file => nil,
43
+ :exec => nil,
44
+ :input => nil,
45
+ :output => nil,
46
+ :print => false,
47
+ :block => nil,
48
+ :variables => {},
49
+ :buffer => nil,
50
+ :service => false,
51
+ :delimiter => "\001",
52
+ :csv => false,
53
+ :debug => false
54
+ }
55
+
56
+ def initialize(delegate, attrs = {})
57
+ super delegate
58
+ DEFAULT_ATTRIBUTES.merge(configuration.hive).merge(attrs).each do |name, value|
59
+ instance_variable_set("@#{name}", value)
60
+ end
61
+ end
62
+
63
+ def stdin
64
+ if @input || @exec
65
+ @stdin ||= StringIO.new(strip_sql(@input || @exec))
66
+ end
67
+ end
68
+
69
+ def interactive?
70
+ !(@exec || @file)
71
+ end
72
+
73
+ def print?
74
+ @print
75
+ end
76
+
77
+ def command_args
78
+ args = []
79
+ args << @path
80
+ if @service
81
+ args << ['--service', 'hiveserver']
82
+ else
83
+ args << ['--database', @database] if @database && !@service
84
+ args << @options.map(&:to_a)
85
+ args << load_setup_files.map(&:to_a)
86
+ args << command_args_for_file if @file
87
+ end
88
+ args.flatten
89
+ end
90
+
91
+ def before_execute
92
+ if @file
93
+ console("hive with file #{@file}")
94
+ end
95
+
96
+ if @debug and output = @rendered_file || @file
97
+ logger.debug("#{output}:\n" + File.read(output))
98
+ end
99
+
100
+ if @exec
101
+ console("hive exec '#{strip_sql(@exec)}' #{'into ' + @output if @output}")
102
+ end
103
+
104
+ if @output
105
+ @buffer = Tempfile.new('masamune')
106
+ end
107
+ end
108
+
109
+ def around_execute(&block)
110
+ Dir.chdir(filesystem.path(:run_dir)) do
111
+ yield
112
+ end
113
+ end
114
+
115
+ def after_execute
116
+ return unless @buffer
117
+ @buffer.flush unless @buffer.closed?
118
+ @buffer.close unless @buffer.closed?
119
+ return unless @output
120
+
121
+ filesystem.move_file_to_file(@buffer.path, @output)
122
+ end
123
+
124
+ # FIXME use temporary tables with delimiters for CSV output format
125
+ def handle_stdout(line, line_no)
126
+ if line =~ /\A#{PROMPT}/
127
+ logger.debug(line)
128
+ else
129
+ @block.call(line) if @block
130
+
131
+ if @buffer
132
+ @buffer.puts(@csv ? line.split(@delimiter).map { |row| encode_row(row) }.to_csv : line)
133
+ else
134
+ console(line) if print?
135
+ end
136
+ end
137
+ end
138
+
139
+ def encode_row(row)
140
+ row unless row == 'NULL' || row == ''
141
+ end
142
+
143
+ def load_setup_files
144
+ files = []
145
+ @setup_files.each do |path|
146
+ filesystem.glob_sort(path, order: :basename).each do |file|
147
+ files << file
148
+ end
149
+ end
150
+ files.flatten.compact.map { |file| {'-i' => file} }
151
+ end
152
+
153
+ def command_args_for_file
154
+ @file =~ /\.erb\Z/ ? command_args_for_template : command_args_for_simple_file
155
+ end
156
+
157
+ def command_args_for_simple_file
158
+ filesystem.copy_file_to_file(@file, remote_file)
159
+ ['-f', remote_file].tap do |args|
160
+ @variables.each do |key, val|
161
+ args << ['-d', "#{key.to_s}=#{val.to_s}"]
162
+ end
163
+ end
164
+ end
165
+
166
+ def command_args_for_template
167
+ @rendered_file = Masamune::Template.render_to_file(@file, @variables)
168
+ filesystem.copy_file_to_file(@rendered_file, remote_file)
169
+ ['-f', remote_file]
170
+ end
171
+
172
+ private
173
+
174
+ def remote_file
175
+ @remote_file ||= File.join(filesystem.mktempdir!(:tmp_dir), filesystem.basename(@file)).gsub(/.erb\z/,'')
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,37 @@
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 'delegate'
24
+
25
+ module Masamune::Commands
26
+ class Interactive < SimpleDelegator
27
+
28
+ def initialize(delegate, attrs = {})
29
+ super delegate
30
+ @interactive = attrs.fetch(:interactive, false)
31
+ end
32
+
33
+ def interactive?
34
+ @interactive
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,128 @@
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 'delegate'
24
+
25
+ require 'masamune/string_format'
26
+
27
+ module Masamune::Commands
28
+ class Postgres < SimpleDelegator
29
+ include Masamune::StringFormat
30
+ include Masamune::Commands::PostgresCommon
31
+
32
+ DEFAULT_ATTRIBUTES =
33
+ {
34
+ :path => 'psql',
35
+ :options => [],
36
+ :hostname => 'localhost',
37
+ :database => 'postgres',
38
+ :username => 'postgres',
39
+ :pgpass_file => nil,
40
+ :file => nil,
41
+ :exec => nil,
42
+ :input => nil,
43
+ :output => nil,
44
+ :print => false,
45
+ :block => nil,
46
+ :csv => false,
47
+ :variables => {},
48
+ :tuple_output => false,
49
+ :debug => false
50
+ }
51
+
52
+ def initialize(delegate, attrs = {})
53
+ super delegate
54
+ DEFAULT_ATTRIBUTES.merge(configuration.postgres).merge(attrs).each do |name, value|
55
+ instance_variable_set("@#{name}", value)
56
+ end
57
+ end
58
+
59
+ def stdin
60
+ if @input
61
+ @stdin ||= StringIO.new(strip_sql(@input))
62
+ end
63
+ end
64
+
65
+ def interactive?
66
+ !(@exec || @file)
67
+ end
68
+
69
+ def print?
70
+ @print
71
+ end
72
+
73
+ def command_args
74
+ args = []
75
+ args << @path
76
+ args << '--host=%s' % @hostname if @hostname
77
+ args << '--dbname=%s' % @database
78
+ args << '--username=%s' % @username if @username
79
+ args << '--no-password'
80
+ args << @options.map(&:to_a)
81
+ args << command_args_for_file if @file
82
+ args << '--output=%s' % @output if @output
83
+ args << '--no-align' << '--field-separator=,' << '--pset=footer' if @csv
84
+ args << '--command=%s' % strip_sql(@exec) if @exec
85
+ args << '--pset=tuples_only' if @tuple_output
86
+ args.flatten.compact
87
+ end
88
+
89
+ def before_execute
90
+ console("psql with file #{@file}") if @file
91
+ if @debug and output = @rendered_file || @file
92
+ logger.debug("#{output}:\n" + File.read(output))
93
+ end
94
+ end
95
+
96
+ def handle_stdout(line, line_no)
97
+ if line =~ /\A#{prompt}/
98
+ logger.debug(line)
99
+ else
100
+ @block.call(line) if @block
101
+ console(line) if print?
102
+ end
103
+ end
104
+
105
+ def prompt
106
+ @database + '=>'
107
+ end
108
+
109
+ private
110
+
111
+ def command_args_for_file
112
+ @file =~ /\.erb\Z/ ? command_args_for_template : command_args_for_simple_file
113
+ end
114
+
115
+ def command_args_for_simple_file
116
+ ['--file=%s' % @file].tap do |args|
117
+ @variables.each do |key, val|
118
+ args << '--set=%s' % "#{key.to_s}='#{val.to_s}'"
119
+ end
120
+ end
121
+ end
122
+
123
+ def command_args_for_template
124
+ @rendered_file = Masamune::Template.render_to_file(@file, @variables)
125
+ ['--file=%s' % @rendered_file]
126
+ end
127
+ end
128
+ end