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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +54 -0
- data/Rakefile +15 -0
- data/bin/masamune-elastic-mapreduce +4 -0
- data/bin/masamune-hive +4 -0
- data/bin/masamune-psql +4 -0
- data/bin/masamune-shell +4 -0
- data/lib/masamune.rb +56 -0
- data/lib/masamune/accumulate.rb +60 -0
- data/lib/masamune/actions.rb +38 -0
- data/lib/masamune/actions/data_flow.rb +131 -0
- data/lib/masamune/actions/date_parse.rb +75 -0
- data/lib/masamune/actions/elastic_mapreduce.rb +68 -0
- data/lib/masamune/actions/execute.rb +52 -0
- data/lib/masamune/actions/filesystem.rb +37 -0
- data/lib/masamune/actions/hadoop_filesystem.rb +40 -0
- data/lib/masamune/actions/hadoop_streaming.rb +41 -0
- data/lib/masamune/actions/hive.rb +74 -0
- data/lib/masamune/actions/postgres.rb +76 -0
- data/lib/masamune/actions/postgres_admin.rb +34 -0
- data/lib/masamune/actions/s3cmd.rb +44 -0
- data/lib/masamune/actions/transform.rb +89 -0
- data/lib/masamune/after_initialize_callbacks.rb +55 -0
- data/lib/masamune/cached_filesystem.rb +110 -0
- data/lib/masamune/commands.rb +37 -0
- data/lib/masamune/commands/elastic_mapreduce.rb +119 -0
- data/lib/masamune/commands/hadoop_filesystem.rb +57 -0
- data/lib/masamune/commands/hadoop_streaming.rb +116 -0
- data/lib/masamune/commands/hive.rb +178 -0
- data/lib/masamune/commands/interactive.rb +37 -0
- data/lib/masamune/commands/postgres.rb +128 -0
- data/lib/masamune/commands/postgres_admin.rb +72 -0
- data/lib/masamune/commands/postgres_common.rb +33 -0
- data/lib/masamune/commands/retry_with_backoff.rb +60 -0
- data/lib/masamune/commands/s3cmd.rb +70 -0
- data/lib/masamune/commands/shell.rb +202 -0
- data/lib/masamune/configuration.rb +195 -0
- data/lib/masamune/data_plan.rb +31 -0
- data/lib/masamune/data_plan/builder.rb +66 -0
- data/lib/masamune/data_plan/elem.rb +190 -0
- data/lib/masamune/data_plan/engine.rb +162 -0
- data/lib/masamune/data_plan/rule.rb +292 -0
- data/lib/masamune/data_plan/set.rb +176 -0
- data/lib/masamune/environment.rb +164 -0
- data/lib/masamune/filesystem.rb +567 -0
- data/lib/masamune/has_environment.rb +40 -0
- data/lib/masamune/helpers.rb +27 -0
- data/lib/masamune/helpers/postgres.rb +84 -0
- data/lib/masamune/io.rb +33 -0
- data/lib/masamune/last_element.rb +53 -0
- data/lib/masamune/method_logger.rb +41 -0
- data/lib/masamune/multi_io.rb +39 -0
- data/lib/masamune/schema.rb +36 -0
- data/lib/masamune/schema/catalog.rb +233 -0
- data/lib/masamune/schema/column.rb +527 -0
- data/lib/masamune/schema/dimension.rb +133 -0
- data/lib/masamune/schema/event.rb +121 -0
- data/lib/masamune/schema/fact.rb +133 -0
- data/lib/masamune/schema/map.rb +265 -0
- data/lib/masamune/schema/row.rb +133 -0
- data/lib/masamune/schema/store.rb +115 -0
- data/lib/masamune/schema/table.rb +308 -0
- data/lib/masamune/schema/table_reference.rb +76 -0
- data/lib/masamune/spec_helper.rb +23 -0
- data/lib/masamune/string_format.rb +34 -0
- data/lib/masamune/tasks/elastic_mapreduce_thor.rb +60 -0
- data/lib/masamune/tasks/hive_thor.rb +55 -0
- data/lib/masamune/tasks/postgres_thor.rb +47 -0
- data/lib/masamune/tasks/shell_thor.rb +63 -0
- data/lib/masamune/template.rb +77 -0
- data/lib/masamune/thor.rb +186 -0
- data/lib/masamune/thor_loader.rb +38 -0
- data/lib/masamune/topological_hash.rb +34 -0
- data/lib/masamune/transform.rb +47 -0
- data/lib/masamune/transform/bulk_upsert.psql.erb +64 -0
- data/lib/masamune/transform/bulk_upsert.rb +52 -0
- data/lib/masamune/transform/consolidate_dimension.rb +54 -0
- data/lib/masamune/transform/deduplicate_dimension.psql.erb +52 -0
- data/lib/masamune/transform/deduplicate_dimension.rb +53 -0
- data/lib/masamune/transform/define_event_view.hql.erb +51 -0
- data/lib/masamune/transform/define_event_view.rb +60 -0
- data/lib/masamune/transform/define_index.psql.erb +34 -0
- data/lib/masamune/transform/define_schema.hql.erb +23 -0
- data/lib/masamune/transform/define_schema.psql.erb +79 -0
- data/lib/masamune/transform/define_schema.rb +56 -0
- data/lib/masamune/transform/define_table.hql.erb +34 -0
- data/lib/masamune/transform/define_table.psql.erb +95 -0
- data/lib/masamune/transform/define_table.rb +40 -0
- data/lib/masamune/transform/define_unique.psql.erb +30 -0
- data/lib/masamune/transform/insert_reference_values.psql.erb +43 -0
- data/lib/masamune/transform/insert_reference_values.rb +64 -0
- data/lib/masamune/transform/load_dimension.rb +47 -0
- data/lib/masamune/transform/load_fact.rb +45 -0
- data/lib/masamune/transform/operator.rb +96 -0
- data/lib/masamune/transform/relabel_dimension.psql.erb +76 -0
- data/lib/masamune/transform/relabel_dimension.rb +39 -0
- data/lib/masamune/transform/rollup_fact.psql.erb +79 -0
- data/lib/masamune/transform/rollup_fact.rb +149 -0
- data/lib/masamune/transform/snapshot_dimension.psql.erb +75 -0
- data/lib/masamune/transform/snapshot_dimension.rb +74 -0
- data/lib/masamune/transform/stage_dimension.psql.erb +39 -0
- data/lib/masamune/transform/stage_dimension.rb +83 -0
- data/lib/masamune/transform/stage_fact.psql.erb +80 -0
- data/lib/masamune/transform/stage_fact.rb +111 -0
- data/lib/masamune/version.rb +25 -0
- data/spec/fixtures/aggregate.sql.erb +25 -0
- data/spec/fixtures/comment.sql.erb +27 -0
- data/spec/fixtures/invalid.sql.erb +23 -0
- data/spec/fixtures/relative.sql.erb +23 -0
- data/spec/fixtures/simple.sql.erb +28 -0
- data/spec/fixtures/whitespace.sql.erb +30 -0
- data/spec/masamune/actions/elastic_mapreduce_spec.rb +108 -0
- data/spec/masamune/actions/execute_spec.rb +50 -0
- data/spec/masamune/actions/hadoop_filesystem_spec.rb +44 -0
- data/spec/masamune/actions/hadoop_streaming_spec.rb +74 -0
- data/spec/masamune/actions/hive_spec.rb +117 -0
- data/spec/masamune/actions/postgres_admin_spec.rb +58 -0
- data/spec/masamune/actions/postgres_spec.rb +134 -0
- data/spec/masamune/actions/s3cmd_spec.rb +44 -0
- data/spec/masamune/actions/transform_spec.rb +144 -0
- data/spec/masamune/after_initialization_callbacks_spec.rb +61 -0
- data/spec/masamune/cached_filesystem_spec.rb +167 -0
- data/spec/masamune/commands/hadoop_filesystem_spec.rb +50 -0
- data/spec/masamune/commands/hadoop_streaming_spec.rb +106 -0
- data/spec/masamune/commands/hive_spec.rb +117 -0
- data/spec/masamune/commands/postgres_admin_spec.rb +69 -0
- data/spec/masamune/commands/postgres_spec.rb +100 -0
- data/spec/masamune/commands/retry_with_backoff_spec.rb +116 -0
- data/spec/masamune/commands/s3cmd_spec.rb +50 -0
- data/spec/masamune/commands/shell_spec.rb +101 -0
- data/spec/masamune/configuration_spec.rb +102 -0
- data/spec/masamune/data_plan/builder_spec.rb +91 -0
- data/spec/masamune/data_plan/elem_spec.rb +102 -0
- data/spec/masamune/data_plan/engine_spec.rb +356 -0
- data/spec/masamune/data_plan/rule_spec.rb +407 -0
- data/spec/masamune/data_plan/set_spec.rb +517 -0
- data/spec/masamune/environment_spec.rb +65 -0
- data/spec/masamune/filesystem_spec.rb +1421 -0
- data/spec/masamune/helpers/postgres_spec.rb +95 -0
- data/spec/masamune/schema/catalog_spec.rb +613 -0
- data/spec/masamune/schema/column_spec.rb +696 -0
- data/spec/masamune/schema/dimension_spec.rb +137 -0
- data/spec/masamune/schema/event_spec.rb +75 -0
- data/spec/masamune/schema/fact_spec.rb +117 -0
- data/spec/masamune/schema/map_spec.rb +593 -0
- data/spec/masamune/schema/row_spec.rb +28 -0
- data/spec/masamune/schema/store_spec.rb +49 -0
- data/spec/masamune/schema/table_spec.rb +395 -0
- data/spec/masamune/string_format_spec.rb +60 -0
- data/spec/masamune/tasks/elastic_mapreduce_thor_spec.rb +57 -0
- data/spec/masamune/tasks/hive_thor_spec.rb +75 -0
- data/spec/masamune/tasks/postgres_thor_spec.rb +42 -0
- data/spec/masamune/tasks/shell_thor_spec.rb +51 -0
- data/spec/masamune/template_spec.rb +77 -0
- data/spec/masamune/thor_spec.rb +238 -0
- data/spec/masamune/transform/bulk_upsert.dimension_spec.rb +200 -0
- data/spec/masamune/transform/consolidate_dimension_spec.rb +62 -0
- data/spec/masamune/transform/deduplicate_dimension_spec.rb +84 -0
- data/spec/masamune/transform/define_event_view_spec.rb +84 -0
- data/spec/masamune/transform/define_schema_spec.rb +83 -0
- data/spec/masamune/transform/define_table.dimension_spec.rb +306 -0
- data/spec/masamune/transform/define_table.fact_spec.rb +291 -0
- data/spec/masamune/transform/define_table.table_spec.rb +525 -0
- data/spec/masamune/transform/insert_reference_values.dimension_spec.rb +111 -0
- data/spec/masamune/transform/insert_reference_values.fact_spec.rb +149 -0
- data/spec/masamune/transform/load_dimension_spec.rb +76 -0
- data/spec/masamune/transform/load_fact_spec.rb +89 -0
- data/spec/masamune/transform/relabel_dimension_spec.rb +102 -0
- data/spec/masamune/transform/rollup_fact_spec.rb +333 -0
- data/spec/masamune/transform/snapshot_dimension_spec.rb +103 -0
- data/spec/masamune/transform/stage_dimension_spec.rb +115 -0
- data/spec/masamune/transform/stage_fact_spec.rb +204 -0
- data/spec/masamune_spec.rb +32 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/support/masamune/example_group.rb +36 -0
- data/spec/support/masamune/mock_command.rb +99 -0
- data/spec/support/masamune/mock_delegate.rb +51 -0
- data/spec/support/masamune/mock_filesystem.rb +96 -0
- data/spec/support/masamune/thor_mute.rb +35 -0
- data/spec/support/rspec/example/action_example_group.rb +34 -0
- data/spec/support/rspec/example/task_example_group.rb +80 -0
- data/spec/support/rspec/example/transform_example_group.rb +36 -0
- data/spec/support/shared_examples/postgres_common_examples.rb +53 -0
- metadata +462 -0
@@ -0,0 +1,527 @@
|
|
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 'json'
|
24
|
+
|
25
|
+
module Masamune::Schema
|
26
|
+
class Column
|
27
|
+
DEFAULT_ATTRIBUTES =
|
28
|
+
{
|
29
|
+
id: nil,
|
30
|
+
type: :integer,
|
31
|
+
sub_type: nil,
|
32
|
+
array: false,
|
33
|
+
values: [],
|
34
|
+
null: false,
|
35
|
+
strict: true,
|
36
|
+
default: nil,
|
37
|
+
auto: false,
|
38
|
+
index: Set.new,
|
39
|
+
unique: Set.new,
|
40
|
+
ignore: false,
|
41
|
+
sequence_offset: 1,
|
42
|
+
surrogate_key: false,
|
43
|
+
natural_key: false,
|
44
|
+
measure: false,
|
45
|
+
partition: false,
|
46
|
+
aggregate: nil,
|
47
|
+
reference: nil,
|
48
|
+
parent: nil,
|
49
|
+
debug: false
|
50
|
+
}
|
51
|
+
|
52
|
+
DEFAULT_ATTRIBUTES.keys.each do |attr|
|
53
|
+
attr_accessor attr
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize(opts = {})
|
57
|
+
opts.symbolize_keys!
|
58
|
+
raise ArgumentError, 'required parameter id: missing' unless opts.key?(:id)
|
59
|
+
DEFAULT_ATTRIBUTES.merge(opts).each do |name, value|
|
60
|
+
public_send("#{name}=", value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def id=(id)
|
65
|
+
@id = id.to_sym
|
66
|
+
end
|
67
|
+
|
68
|
+
def name
|
69
|
+
if reference && reference.columns.include?(id)
|
70
|
+
[reference.label, reference.name, id].compact.join('_').to_sym
|
71
|
+
else
|
72
|
+
id
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def default
|
77
|
+
return @default unless @default.nil?
|
78
|
+
case type
|
79
|
+
when :uuid
|
80
|
+
'uuid_generate_v4()'
|
81
|
+
when :sequence
|
82
|
+
"nextval('#{sequence_id}')"
|
83
|
+
when :enum
|
84
|
+
values.first
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def index=(value)
|
89
|
+
@index ||= Set.new
|
90
|
+
@index.clear
|
91
|
+
@index +=
|
92
|
+
case value
|
93
|
+
when true
|
94
|
+
[id]
|
95
|
+
when false
|
96
|
+
[]
|
97
|
+
when String, Symbol
|
98
|
+
[value.to_sym]
|
99
|
+
when Array, Set
|
100
|
+
value.map(&:to_sym)
|
101
|
+
else
|
102
|
+
raise ArgumentError
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def unique
|
107
|
+
self.unique = 'natural' if natural_key
|
108
|
+
@unique
|
109
|
+
end
|
110
|
+
|
111
|
+
def unique=(value)
|
112
|
+
@unique ||= Set.new
|
113
|
+
@unique.clear
|
114
|
+
@unique +=
|
115
|
+
case value
|
116
|
+
when true
|
117
|
+
[id]
|
118
|
+
when false
|
119
|
+
[]
|
120
|
+
when String, Symbol
|
121
|
+
[value.to_sym]
|
122
|
+
when Array, Set
|
123
|
+
value.map(&:to_sym)
|
124
|
+
else
|
125
|
+
raise ArgumentError
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def foreign_key_name
|
130
|
+
"#{reference.name}.#{@id}".to_sym if reference
|
131
|
+
end
|
132
|
+
|
133
|
+
def compact_name
|
134
|
+
if reference
|
135
|
+
# XXX once columns only reference columns, this can be cleaned up
|
136
|
+
if @id == reference.surrogate_key.reference_name(reference.label)
|
137
|
+
"#{reference.id}.#{reference.surrogate_key.id}".to_sym
|
138
|
+
else
|
139
|
+
"#{reference.id}.#{@id}".to_sym
|
140
|
+
end
|
141
|
+
else
|
142
|
+
@id
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def qualified_name(label = nil)
|
147
|
+
[label, (parent ? "#{parent.name}.#{name}" : name)].compact.join('_').to_sym
|
148
|
+
end
|
149
|
+
|
150
|
+
def reference_name(label = nil)
|
151
|
+
qualified_name(label).to_s.gsub(/\./, '_').to_sym
|
152
|
+
end
|
153
|
+
|
154
|
+
def sql_type(for_surrogate_key = false)
|
155
|
+
elem =
|
156
|
+
case type
|
157
|
+
when :integer
|
158
|
+
for_surrogate_key ? 'SERIAL' : 'INTEGER'
|
159
|
+
when :money
|
160
|
+
'MONEY'
|
161
|
+
when :string
|
162
|
+
'VARCHAR'
|
163
|
+
when :uuid
|
164
|
+
'UUID'
|
165
|
+
when :date
|
166
|
+
'DATE'
|
167
|
+
when :timestamp
|
168
|
+
'TIMESTAMP'
|
169
|
+
when :boolean
|
170
|
+
'BOOLEAN'
|
171
|
+
when :sequence
|
172
|
+
'INTEGER'
|
173
|
+
when :enum
|
174
|
+
"#{sub_type || id}_TYPE".upcase
|
175
|
+
when :key_value
|
176
|
+
if parent.type == :stage && !parent.inherit
|
177
|
+
'JSON'
|
178
|
+
else
|
179
|
+
'HSTORE'
|
180
|
+
end
|
181
|
+
when :json, :yaml
|
182
|
+
'JSON'
|
183
|
+
end
|
184
|
+
array_value? ? "#{elem}[]" : elem
|
185
|
+
end
|
186
|
+
|
187
|
+
def hql_type
|
188
|
+
elem =
|
189
|
+
case type
|
190
|
+
when :integer
|
191
|
+
'INT'
|
192
|
+
when :string
|
193
|
+
'STRING'
|
194
|
+
else
|
195
|
+
sql_type
|
196
|
+
end
|
197
|
+
array_value? ? "ARRAY<#{elem}>" : elem
|
198
|
+
end
|
199
|
+
|
200
|
+
def sql_value(value)
|
201
|
+
return value if sql_function?(value)
|
202
|
+
return 'NULL' if value == :null
|
203
|
+
case type
|
204
|
+
when :boolean
|
205
|
+
value ? 'TRUE' : 'FALSE'
|
206
|
+
when :string
|
207
|
+
"'#{value}'"
|
208
|
+
when :enum
|
209
|
+
"'#{value}'::#{sql_type}"
|
210
|
+
else
|
211
|
+
value
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def csv_value(value)
|
216
|
+
return value if sql_function?(value)
|
217
|
+
return csv_array(value) if array_value?
|
218
|
+
return nil if value.nil?
|
219
|
+
case type
|
220
|
+
when :boolean
|
221
|
+
value ? 'TRUE' : (hive_encoding? ? nil : 'FALSE')
|
222
|
+
when :yaml
|
223
|
+
value.to_hash.to_yaml
|
224
|
+
when :json, :key_value
|
225
|
+
value.to_hash.to_json
|
226
|
+
when :date
|
227
|
+
value.to_s
|
228
|
+
when :timestamp
|
229
|
+
value.to_time.utc.iso8601(3)
|
230
|
+
when :string
|
231
|
+
value.empty? ? nil : value
|
232
|
+
else
|
233
|
+
value
|
234
|
+
end
|
235
|
+
rescue
|
236
|
+
raise ArgumentError, "Could not coerce '#{value}' into :#{type} for column '#{name}'"
|
237
|
+
end
|
238
|
+
|
239
|
+
def ruby_value(value, recursive = true)
|
240
|
+
value = nil if null_value?(value)
|
241
|
+
return value if sql_function?(value)
|
242
|
+
return ruby_array(value) if recursive && array_value?
|
243
|
+
case type
|
244
|
+
when :boolean
|
245
|
+
case value
|
246
|
+
when false, 0, '0', "'0'", /\Afalse\z/i
|
247
|
+
false
|
248
|
+
when true, 1, '1', "'1'", /\Atrue\z/i
|
249
|
+
true
|
250
|
+
end
|
251
|
+
when :date
|
252
|
+
case value
|
253
|
+
when Date
|
254
|
+
value
|
255
|
+
when String
|
256
|
+
Date.parse(value.to_s)
|
257
|
+
when nil
|
258
|
+
nil
|
259
|
+
end
|
260
|
+
when :timestamp
|
261
|
+
case value
|
262
|
+
when Time
|
263
|
+
value
|
264
|
+
when Date, DateTime
|
265
|
+
value.to_time
|
266
|
+
when String
|
267
|
+
if value =~ /\A\d+\z/
|
268
|
+
Time.at(value.to_i)
|
269
|
+
else
|
270
|
+
Time.parse(value)
|
271
|
+
end
|
272
|
+
when Integer
|
273
|
+
Time.at(value)
|
274
|
+
when nil
|
275
|
+
nil
|
276
|
+
end
|
277
|
+
when :integer
|
278
|
+
value.nil? ? nil : value.to_i
|
279
|
+
when :yaml
|
280
|
+
case value
|
281
|
+
when Hash
|
282
|
+
value
|
283
|
+
when String
|
284
|
+
ruby_key_value(YAML.load(value))
|
285
|
+
when nil
|
286
|
+
{}
|
287
|
+
end
|
288
|
+
when :json
|
289
|
+
case value
|
290
|
+
when Hash
|
291
|
+
value
|
292
|
+
when String
|
293
|
+
ruby_key_value(JSON.load(value))
|
294
|
+
when nil
|
295
|
+
{}
|
296
|
+
end
|
297
|
+
when :string
|
298
|
+
value.to_s
|
299
|
+
else
|
300
|
+
value
|
301
|
+
end
|
302
|
+
rescue
|
303
|
+
raise ArgumentError, "Could not coerce '#{value}' into :#{type} for column '#{name}'"
|
304
|
+
end
|
305
|
+
|
306
|
+
def default_ruby_value
|
307
|
+
return [] if array_value?
|
308
|
+
return {} if hash_value?
|
309
|
+
case type
|
310
|
+
when :date
|
311
|
+
Date.new(0)
|
312
|
+
when :timestamp
|
313
|
+
Time.new(0)
|
314
|
+
else
|
315
|
+
nil
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
def aggregate_value
|
320
|
+
return qualified_name unless aggregate
|
321
|
+
case aggregate
|
322
|
+
when :min
|
323
|
+
"MIN(#{qualified_name})"
|
324
|
+
when :max
|
325
|
+
"MAX(#{qualified_name})"
|
326
|
+
when :sum
|
327
|
+
"SUM(#{qualified_name})"
|
328
|
+
when :average
|
329
|
+
"AVG(#{qualified_name})"
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
def null_value?(value)
|
334
|
+
if type == :json || array_value?
|
335
|
+
return true if value == 'NULL'
|
336
|
+
end
|
337
|
+
return false unless value
|
338
|
+
if hive_encoding?
|
339
|
+
value.to_s == '\N'
|
340
|
+
else
|
341
|
+
false
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
def hive_encoding?
|
346
|
+
if parent && parent.store
|
347
|
+
parent.store.type == :hive
|
348
|
+
else
|
349
|
+
false
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
def sql_function?(value)
|
354
|
+
value =~ /\(\)\Z/
|
355
|
+
end
|
356
|
+
|
357
|
+
def array_value?
|
358
|
+
!!(array || (reference && reference.respond_to?(:multiple) && reference.multiple))
|
359
|
+
end
|
360
|
+
|
361
|
+
def hash_value?
|
362
|
+
[:key_value, :yaml, :json].include?(type)
|
363
|
+
end
|
364
|
+
|
365
|
+
def as_psql
|
366
|
+
[name, sql_type(surrogate_key), *sql_constraints, reference_constraint, sql_default].compact.join(' ')
|
367
|
+
end
|
368
|
+
|
369
|
+
def as_hash
|
370
|
+
{id: id}.tap do |hash|
|
371
|
+
DEFAULT_ATTRIBUTES.keys.each do |attr|
|
372
|
+
hash[attr] = public_send(attr)
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
# TODO: Add ELEMENT REFERENCES
|
378
|
+
def reference_constraint
|
379
|
+
return if parent.temporary?
|
380
|
+
return if degenerate?
|
381
|
+
return if array_value?
|
382
|
+
if reference && reference.surrogate_key.type == type
|
383
|
+
"REFERENCES #{reference.name}(#{reference.surrogate_key.name})"
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
class << self
|
388
|
+
def dereference_column_name(name)
|
389
|
+
return unless name
|
390
|
+
if name.to_s =~ /\./
|
391
|
+
reference_name, column_name = name.to_s.split('.')
|
392
|
+
[reference_name.to_sym, column_name.to_sym]
|
393
|
+
else
|
394
|
+
[nil, name.to_sym]
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
def ==(other)
|
400
|
+
return false unless other
|
401
|
+
id == other.id &&
|
402
|
+
typecast?(other.type) &&
|
403
|
+
(!reference || reference.id == other.reference.try(:id) || reference.id == other.parent.try(:id)) &&
|
404
|
+
(!other.reference || other.reference.id == reference.try(:id) || other.reference.id == parent.try(:id))
|
405
|
+
end
|
406
|
+
|
407
|
+
def eql?(other)
|
408
|
+
self == other
|
409
|
+
end
|
410
|
+
|
411
|
+
def hash
|
412
|
+
[id, type].hash
|
413
|
+
end
|
414
|
+
|
415
|
+
def typecast?(other_type)
|
416
|
+
return true if type == other_type
|
417
|
+
case [type, other_type]
|
418
|
+
when [:key_value, :yaml]
|
419
|
+
true
|
420
|
+
when [:key_value, :json]
|
421
|
+
true
|
422
|
+
when [:yaml, :json]
|
423
|
+
true
|
424
|
+
else
|
425
|
+
false
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
def auto_reference
|
430
|
+
reference && reference.surrogate_key.auto && !reference.insert
|
431
|
+
end
|
432
|
+
|
433
|
+
# XXX hack to work around columns not being able to reference columns
|
434
|
+
def references?(other)
|
435
|
+
return false unless other
|
436
|
+
if reference && other.reference && reference.id == other.reference.id
|
437
|
+
true
|
438
|
+
elsif parent && other.parent && parent.id == other.parent.id
|
439
|
+
self == other
|
440
|
+
elsif parent && other.parent && other.parent.parent && parent.id == other.parent.parent.id
|
441
|
+
self == other
|
442
|
+
elsif reference && other.parent && reference.id == other.parent.id
|
443
|
+
self == other
|
444
|
+
elsif natural_key || other.natural_key
|
445
|
+
self == other
|
446
|
+
else
|
447
|
+
false
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
def degenerate?
|
452
|
+
reference && reference.respond_to?(:degenerate) && reference.degenerate
|
453
|
+
end
|
454
|
+
|
455
|
+
def adjacent
|
456
|
+
return unless reference
|
457
|
+
reference.columns[id]
|
458
|
+
end
|
459
|
+
|
460
|
+
def sequence_id
|
461
|
+
"#{reference_name}_seq" if type == :sequence
|
462
|
+
end
|
463
|
+
|
464
|
+
def required_value?
|
465
|
+
if reference
|
466
|
+
!(reference.null || reference.default)
|
467
|
+
else
|
468
|
+
surrogate_key || natural_key
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
private
|
473
|
+
|
474
|
+
def sql_constraints
|
475
|
+
[].tap do |constraints|
|
476
|
+
constraints << 'NOT NULL' unless null || surrogate_key || !strict || parent.temporary? || degenerate?
|
477
|
+
constraints << "PRIMARY KEY" if surrogate_key
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
def sql_default
|
482
|
+
return if default.nil?
|
483
|
+
return if !strict
|
484
|
+
"DEFAULT #{sql_value(default)}"
|
485
|
+
end
|
486
|
+
|
487
|
+
def ruby_array(value)
|
488
|
+
case value
|
489
|
+
when Array
|
490
|
+
value.map { |elem| ruby_value(elem, false) }
|
491
|
+
when String
|
492
|
+
Array.wrap(JSON.load(value)).map { |elem| ruby_value(elem, false) }
|
493
|
+
when nil
|
494
|
+
[]
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
def ruby_key_value(hash)
|
499
|
+
case sub_type
|
500
|
+
when :boolean
|
501
|
+
Hash[hash.map { |key, value| ruby_boolean_key_value(key, value) }.compact]
|
502
|
+
else
|
503
|
+
hash
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
def ruby_boolean_key_value(key, value)
|
508
|
+
case value
|
509
|
+
when true, '1', 1
|
510
|
+
[key, true]
|
511
|
+
when false, '0', 0
|
512
|
+
[key, false]
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
def csv_array(value)
|
517
|
+
case value
|
518
|
+
when Array
|
519
|
+
ruby_value(value).to_json
|
520
|
+
when nil
|
521
|
+
[].to_json
|
522
|
+
else
|
523
|
+
[ruby_value(value, false)].to_json
|
524
|
+
end
|
525
|
+
end
|
526
|
+
end
|
527
|
+
end
|