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,76 @@
|
|
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
|
+
<%-# Relabel version column -%>
|
27
|
+
UPDATE <%= target.name %> SET version = NULL;
|
28
|
+
|
29
|
+
UPDATE
|
30
|
+
<%= target.name %>
|
31
|
+
SET
|
32
|
+
version = tmp.version
|
33
|
+
FROM
|
34
|
+
(
|
35
|
+
SELECT
|
36
|
+
id,
|
37
|
+
<%- target.window.each do |name| -%>
|
38
|
+
<%= name %>,
|
39
|
+
<%- end -%>
|
40
|
+
start_at,
|
41
|
+
rank() OVER (PARTITION BY <%= target.window.join(', ') %> ORDER BY start_at) AS version
|
42
|
+
FROM
|
43
|
+
<%= target.name %>
|
44
|
+
GROUP BY
|
45
|
+
<%= target.window(:id, :start_at).join(', ') %>
|
46
|
+
) AS tmp
|
47
|
+
WHERE
|
48
|
+
<%= target.name %>.id = tmp.id
|
49
|
+
;
|
50
|
+
|
51
|
+
<%-# Relabel end_at column -%>
|
52
|
+
UPDATE <%= target.name %> SET end_at = NULL;
|
53
|
+
|
54
|
+
UPDATE
|
55
|
+
<%= target.name %>
|
56
|
+
SET
|
57
|
+
end_at = tmp.end_at
|
58
|
+
FROM
|
59
|
+
(
|
60
|
+
SELECT
|
61
|
+
id,
|
62
|
+
start_at,
|
63
|
+
<%- target.window.each do |name| -%>
|
64
|
+
<%= name %>,
|
65
|
+
<%- end -%>
|
66
|
+
LEAD(start_at, 1) OVER (PARTITION BY <%= target.window.join(', ') %> ORDER BY start_at) AS end_at
|
67
|
+
FROM
|
68
|
+
<%= target.name %>
|
69
|
+
GROUP BY
|
70
|
+
<%= target.window(:id, :start_at).join(', ') %>
|
71
|
+
) AS tmp
|
72
|
+
WHERE
|
73
|
+
<%= target.name %>.id = tmp.id
|
74
|
+
;
|
75
|
+
|
76
|
+
COMMIT;
|
@@ -0,0 +1,39 @@
|
|
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 RelabelDimension
|
25
|
+
extend ActiveSupport::Concern
|
26
|
+
|
27
|
+
def relabel_dimension(target)
|
28
|
+
Operator.new(__method__, target: target, presenters: { postgres: Postgres })
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
class Postgres < SimpleDelegator
|
34
|
+
def window(*extra)
|
35
|
+
(columns.values.select { |column| extra.delete(column.name) || column.natural_key || column.auto_reference }.map(&:name) + extra).uniq
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,79 @@
|
|
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
|
+
<%- target_stage = target.stage_table %>
|
24
|
+
|
25
|
+
BEGIN;
|
26
|
+
|
27
|
+
DROP TABLE IF EXISTS <%= target_stage.name %> CASCADE;
|
28
|
+
CREATE TABLE IF NOT EXISTS <%= target_stage.name %> (LIKE <%= target.parent.name %> INCLUDING ALL);
|
29
|
+
|
30
|
+
ALTER TABLE <%= target_stage.name %> ADD CONSTRAINT <%= target_stage.name %>_time_key_check <%= target_stage.constraints %>;
|
31
|
+
<%- target.foreign_key_columns.each do |column| -%>
|
32
|
+
ALTER TABLE <%= target_stage.name %> ADD CONSTRAINT <%= target_stage.name %>_<%= column.name %>_fkey FOREIGN KEY (<%= column.name %>) <%= column.reference_constraint %>;
|
33
|
+
<%- end -%>
|
34
|
+
|
35
|
+
INSERT INTO
|
36
|
+
<%= target_stage.name %> (<%= target.insert_columns(source).join(', ') %>)
|
37
|
+
SELECT
|
38
|
+
<%- target.insert_values(source).each do |value, last| -%>
|
39
|
+
<%= value %><%= ',' unless last %>
|
40
|
+
<%- end -%>
|
41
|
+
FROM
|
42
|
+
<%= source.name %>
|
43
|
+
<%- target.join_conditions(source).each do |table, conditions| -%>
|
44
|
+
JOIN
|
45
|
+
<%= table %>
|
46
|
+
ON
|
47
|
+
<%= conditions.join(" AND\n ") %>
|
48
|
+
<%- end -%>
|
49
|
+
GROUP BY
|
50
|
+
<%- target.group_by(source).each do |value, last| -%>
|
51
|
+
<%= value %><%= ',' unless last %>
|
52
|
+
<%- end -%>
|
53
|
+
;
|
54
|
+
|
55
|
+
<%- target.index_columns.each do |column_names, unique| -%>
|
56
|
+
<%- index_name = "#{target_stage.name}_#{column_names.join('_')}_index" -%>
|
57
|
+
CREATE <%= unique ? 'UNIQUE INDEX' : 'INDEX' %> <%= index_name %> ON <%= target_stage.name %> (<%= column_names.join(', ') %>);
|
58
|
+
<%- end -%>
|
59
|
+
|
60
|
+
COMMIT;
|
61
|
+
|
62
|
+
BEGIN;
|
63
|
+
|
64
|
+
DROP TABLE IF EXISTS <%= target.name %>;
|
65
|
+
ALTER TABLE <%= target_stage.name %> RENAME TO <%= target.name %>;
|
66
|
+
|
67
|
+
ALTER TABLE <%= target.name %> INHERIT <%= target.parent.name %>;
|
68
|
+
ALTER TABLE <%= target.name %> ADD CONSTRAINT <%= target.name %>_time_key_check <%= target.constraints %> NOT VALID;
|
69
|
+
<%- target.foreign_key_columns.each do |column| -%>
|
70
|
+
ALTER TABLE <%= target.name %> ADD CONSTRAINT <%= target.name %>_<%= column.name %>_fkey FOREIGN KEY (<%= column.name %>) <%= column.reference_constraint %> NOT VALID;
|
71
|
+
<%- end -%>
|
72
|
+
|
73
|
+
<%- target.index_columns.each do |column_names, unique| -%>
|
74
|
+
<%- old_index_name = "#{target_stage.name}_#{column_names.join('_')}_index" -%>
|
75
|
+
<%- new_index_name = "#{target.name}_#{column_names.join('_')}_index" -%>
|
76
|
+
ALTER INDEX <%= old_index_name %> RENAME TO <%= new_index_name %>;
|
77
|
+
<%- end -%>
|
78
|
+
|
79
|
+
COMMIT;
|
@@ -0,0 +1,149 @@
|
|
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 RollupFact
|
25
|
+
extend ActiveSupport::Concern
|
26
|
+
|
27
|
+
def rollup_fact(source, target, date)
|
28
|
+
raise ArgumentError, "#{source.name} must have date_column to rollup" unless source.date_column
|
29
|
+
raise ArgumentError, "#{target.name} must have date_column to rollup" unless target.date_column
|
30
|
+
Operator.new __method__, source: source.partition_table(date), target: target.partition_table(date), presenters: { postgres: Postgres }
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
class Postgres < SimpleDelegator
|
36
|
+
include Masamune::LastElement
|
37
|
+
|
38
|
+
def insert_columns(source)
|
39
|
+
values = []
|
40
|
+
shared_columns(source).values.map do |columns|
|
41
|
+
column = columns.first
|
42
|
+
next if column.id == :last_modified_at
|
43
|
+
next if column.auto_reference
|
44
|
+
values << column.name
|
45
|
+
end
|
46
|
+
measures.each do |_ ,measure|
|
47
|
+
values << measure.name
|
48
|
+
end
|
49
|
+
values << time_key.name
|
50
|
+
values.compact
|
51
|
+
end
|
52
|
+
|
53
|
+
def insert_values(source)
|
54
|
+
values = []
|
55
|
+
values << "(#{first_date_surrogate_key})"
|
56
|
+
shared_columns(source).values.map do |columns|
|
57
|
+
column = columns.first
|
58
|
+
next unless column.reference
|
59
|
+
next if column.reference.type == :date
|
60
|
+
next if column.auto_reference
|
61
|
+
values << column.qualified_name
|
62
|
+
end
|
63
|
+
source.measures.each do |_ ,measure|
|
64
|
+
values << measure.aggregate_value
|
65
|
+
end
|
66
|
+
values << "(#{floor_time_key(source)})"
|
67
|
+
values
|
68
|
+
end
|
69
|
+
method_with_last_element :insert_values
|
70
|
+
|
71
|
+
def join_conditions(source)
|
72
|
+
{
|
73
|
+
source.date_column.reference.name => [
|
74
|
+
"#{source.date_column.reference.surrogate_key.qualified_name} = #{source.date_column.qualified_name}"
|
75
|
+
]
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def group_by(source)
|
80
|
+
group_by = []
|
81
|
+
group_by << date_column.reference.columns[rollup_key].qualified_name
|
82
|
+
shared_columns(source).values.map do |columns|
|
83
|
+
column = columns.first
|
84
|
+
next unless column.reference
|
85
|
+
next if column.reference.type == :date
|
86
|
+
next if column.auto_reference
|
87
|
+
group_by << column.qualified_name
|
88
|
+
end
|
89
|
+
group_by << "(#{floor_time_key(source)})" if grain == :hourly
|
90
|
+
group_by
|
91
|
+
end
|
92
|
+
method_with_last_element :group_by
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def rollup_key
|
97
|
+
case grain
|
98
|
+
when :hourly
|
99
|
+
:date_epoch
|
100
|
+
when :daily
|
101
|
+
:date_epoch
|
102
|
+
when :monthly
|
103
|
+
:month_epoch
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def date_key
|
108
|
+
:date_id
|
109
|
+
end
|
110
|
+
|
111
|
+
def first_date_surrogate_key
|
112
|
+
<<-EOS.gsub(/\s+/, ' ').strip
|
113
|
+
SELECT
|
114
|
+
#{date_column.reference.surrogate_key.name}
|
115
|
+
FROM
|
116
|
+
#{date_column.reference.name} d
|
117
|
+
WHERE
|
118
|
+
d.#{rollup_key} = #{date_column.reference.columns[rollup_key].qualified_name}
|
119
|
+
ORDER BY
|
120
|
+
d.#{date_key}
|
121
|
+
LIMIT 1
|
122
|
+
EOS
|
123
|
+
end
|
124
|
+
|
125
|
+
def floor_time_key(source)
|
126
|
+
case grain
|
127
|
+
when :hourly
|
128
|
+
"#{source.time_key.qualified_name} - (#{source.time_key.qualified_name} % #{1.hour.seconds})"
|
129
|
+
when :daily, :monthly
|
130
|
+
first_date_time_key
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def first_date_time_key
|
135
|
+
<<-EOS.gsub(/\s+/, ' ').strip
|
136
|
+
SELECT
|
137
|
+
#{rollup_key}
|
138
|
+
FROM
|
139
|
+
#{date_column.reference.name} d
|
140
|
+
WHERE
|
141
|
+
d.#{rollup_key} = #{date_column.reference.columns[rollup_key].qualified_name}
|
142
|
+
ORDER BY
|
143
|
+
d.#{date_key}
|
144
|
+
LIMIT 1
|
145
|
+
EOS
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,75 @@
|
|
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
|
+
<%#
|
24
|
+
Consolidate complete events from partial events
|
25
|
+
For discussion on range and group constructions, see:
|
26
|
+
http://www.postgresql.org/message-id/CAGnEbohhKmW55oB0FpQd3naXBkwi74E=8DRZBGFjS-MeGpXLaA@mail.gmail.com
|
27
|
+
-%>
|
28
|
+
WITH ranges AS (
|
29
|
+
SELECT *,
|
30
|
+
CASE WHEN delta = 0
|
31
|
+
THEN 1 ELSE NULL END r
|
32
|
+
FROM <%= source.name %>
|
33
|
+
), windows AS (
|
34
|
+
SELECT *,
|
35
|
+
SUM(r) OVER (ORDER BY <%= target.window("start_at #{order}", 'delta', 'source_uuid').join(', ') %>) window_id
|
36
|
+
FROM ranges
|
37
|
+
), snapshot AS (
|
38
|
+
SELECT
|
39
|
+
<%- target.insert_view_values.each do |value| -%>
|
40
|
+
consolidated.<%= value %><%= ',' %>
|
41
|
+
<%- end -%>
|
42
|
+
consolidated.parent_id,
|
43
|
+
consolidated.record_id,
|
44
|
+
consolidated.start_at
|
45
|
+
FROM (
|
46
|
+
SELECT DISTINCT ON (<%= target.window('start_at').join(', ') %>)
|
47
|
+
FIRST_VALUE(id) OVER w AS parent_id,
|
48
|
+
FIRST_VALUE(start_at) OVER w AS parent_start_at,
|
49
|
+
id AS record_id,
|
50
|
+
<%- target.insert_values(window: 'w').each do |value, last| -%>
|
51
|
+
<%= value %><%= ',' %>
|
52
|
+
<%- end -%>
|
53
|
+
start_at AS start_at
|
54
|
+
FROM
|
55
|
+
windows
|
56
|
+
WINDOW w AS (PARTITION BY <%= target.window('window_id').join(', ') %> ORDER BY start_at <%= order %>)
|
57
|
+
ORDER BY <%= target.window("start_at #{order}", 'window_id').join(', ') %>
|
58
|
+
) consolidated
|
59
|
+
WHERE
|
60
|
+
<%- target.insert_view_constraints.each do |constraint, last| -%>
|
61
|
+
consolidated.<%= constraint %><%= ' AND' unless last %>
|
62
|
+
<%- end -%>
|
63
|
+
)
|
64
|
+
INSERT INTO
|
65
|
+
<%= target.name %> (<%= target.insert_columns.join(', ') %>, parent_id, record_id, start_at)
|
66
|
+
SELECT
|
67
|
+
<%- target.insert_view_values.each do |value| -%>
|
68
|
+
<%= value %><%= ',' %>
|
69
|
+
<%- end -%>
|
70
|
+
parent_id,
|
71
|
+
record_id,
|
72
|
+
start_at
|
73
|
+
FROM
|
74
|
+
snapshot
|
75
|
+
;
|
@@ -0,0 +1,74 @@
|
|
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 SnapshotDimension
|
25
|
+
extend ActiveSupport::Concern
|
26
|
+
|
27
|
+
def snapshot_dimension(source, target, order = 'DESC')
|
28
|
+
Operator.new(__method__, source: source, target: target, order: order, presenters: { postgres: Postgres })
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
class Postgres < SimpleDelegator
|
34
|
+
include Masamune::LastElement
|
35
|
+
|
36
|
+
def insert_columns(source = nil)
|
37
|
+
consolidated_columns.map { |_, column| column.name }
|
38
|
+
end
|
39
|
+
|
40
|
+
def insert_view_values
|
41
|
+
consolidated_columns.map { |_, column| column.name }
|
42
|
+
end
|
43
|
+
|
44
|
+
def insert_view_constraints
|
45
|
+
consolidated_columns.reject { |_, column| column.null }.map { |_, column| "#{column.name} IS NOT NULL" }
|
46
|
+
end
|
47
|
+
method_with_last_element :insert_view_constraints
|
48
|
+
|
49
|
+
def window(*extra)
|
50
|
+
(columns.values.select { |column| extra.delete(column.name) || column.natural_key || column.auto_reference }.map(&:name) + extra).uniq
|
51
|
+
end
|
52
|
+
|
53
|
+
def insert_values(opts = {})
|
54
|
+
window = opts[:window]
|
55
|
+
consolidated_columns.map do |_, column|
|
56
|
+
if column.natural_key
|
57
|
+
"#{column.name} AS #{column.name}"
|
58
|
+
elsif column.type == :key_value
|
59
|
+
"hstore_merge(#{column.name}_now) OVER #{window} - hstore_merge(#{column.name}_was) OVER #{window} AS #{column.name}"
|
60
|
+
else
|
61
|
+
"coalesce_merge(#{column.name}) OVER #{window} AS #{column.name}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
method_with_last_element :insert_values
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def consolidated_columns
|
70
|
+
unreserved_columns.reject { |_, column| column.surrogate_key }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|