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,525 @@
|
|
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 'spec_helper'
|
24
|
+
|
25
|
+
describe Masamune::Transform::DefineTable do
|
26
|
+
subject { transform.define_table(target).to_s }
|
27
|
+
|
28
|
+
context 'for postgres table with columns' do
|
29
|
+
before do
|
30
|
+
catalog.schema :postgres do
|
31
|
+
table 'user' do
|
32
|
+
column 'tenant_id'
|
33
|
+
column 'user_id'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
let(:target) { catalog.postgres.user_table }
|
39
|
+
|
40
|
+
it 'should render table template' do
|
41
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
42
|
+
CREATE TABLE IF NOT EXISTS user_table
|
43
|
+
(
|
44
|
+
id SERIAL PRIMARY KEY,
|
45
|
+
tenant_id INTEGER NOT NULL,
|
46
|
+
user_id INTEGER NOT NULL
|
47
|
+
);
|
48
|
+
EOS
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'for postgres table with index columns' do
|
53
|
+
before do
|
54
|
+
catalog.schema :postgres do
|
55
|
+
table 'user' do
|
56
|
+
column 'tenant_id', index: true
|
57
|
+
column 'user_id', index: true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
let(:target) { catalog.postgres.user_table }
|
63
|
+
|
64
|
+
it 'should render table template' do
|
65
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
66
|
+
CREATE TABLE IF NOT EXISTS user_table
|
67
|
+
(
|
68
|
+
id SERIAL PRIMARY KEY,
|
69
|
+
tenant_id INTEGER NOT NULL,
|
70
|
+
user_id INTEGER NOT NULL
|
71
|
+
);
|
72
|
+
|
73
|
+
DO $$ BEGIN
|
74
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_3854361_index') THEN
|
75
|
+
CREATE INDEX user_table_3854361_index ON user_table (tenant_id);
|
76
|
+
END IF; END $$;
|
77
|
+
|
78
|
+
DO $$ BEGIN
|
79
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_e8701ad_index') THEN
|
80
|
+
CREATE INDEX user_table_e8701ad_index ON user_table (user_id);
|
81
|
+
END IF; END $$;
|
82
|
+
EOS
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'for postgres table with multiple index columns' do
|
87
|
+
before do
|
88
|
+
catalog.schema :postgres do
|
89
|
+
table 'user' do
|
90
|
+
column 'tenant_id', index: ['tenant_id', 'shared']
|
91
|
+
column 'user_id', index: ['user_id', 'shared']
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
let(:target) { catalog.postgres.user_table }
|
97
|
+
|
98
|
+
it 'should render table template' do
|
99
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
100
|
+
CREATE TABLE IF NOT EXISTS user_table
|
101
|
+
(
|
102
|
+
id SERIAL PRIMARY KEY,
|
103
|
+
tenant_id INTEGER NOT NULL,
|
104
|
+
user_id INTEGER NOT NULL
|
105
|
+
);
|
106
|
+
|
107
|
+
DO $$ BEGIN
|
108
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_3854361_index') THEN
|
109
|
+
CREATE INDEX user_table_3854361_index ON user_table (tenant_id);
|
110
|
+
END IF; END $$;
|
111
|
+
|
112
|
+
DO $$ BEGIN
|
113
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_e8701ad_index') THEN
|
114
|
+
CREATE INDEX user_table_e8701ad_index ON user_table (user_id);
|
115
|
+
END IF; END $$;
|
116
|
+
|
117
|
+
DO $$ BEGIN
|
118
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_e0e4295_index') THEN
|
119
|
+
CREATE INDEX user_table_e0e4295_index ON user_table (tenant_id, user_id);
|
120
|
+
END IF; END $$;
|
121
|
+
EOS
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'for postgres table with multiple unique columns' do
|
126
|
+
before do
|
127
|
+
catalog.schema :postgres do
|
128
|
+
table 'user' do
|
129
|
+
column 'tenant_id', unique: ['shared']
|
130
|
+
column 'user_id', unique: ['user_id', 'shared']
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
let(:target) { catalog.postgres.user_table }
|
136
|
+
|
137
|
+
it 'should render table template' do
|
138
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
139
|
+
CREATE TABLE IF NOT EXISTS user_table
|
140
|
+
(
|
141
|
+
id SERIAL PRIMARY KEY,
|
142
|
+
tenant_id INTEGER NOT NULL,
|
143
|
+
user_id INTEGER NOT NULL
|
144
|
+
);
|
145
|
+
|
146
|
+
DO $$ BEGIN
|
147
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_e8701ad_key') THEN
|
148
|
+
ALTER TABLE user_table ADD CONSTRAINT user_table_e8701ad_key UNIQUE(user_id);
|
149
|
+
END IF; END $$;
|
150
|
+
|
151
|
+
DO $$ BEGIN
|
152
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_e0e4295_key') THEN
|
153
|
+
ALTER TABLE user_table ADD CONSTRAINT user_table_e0e4295_key UNIQUE(tenant_id, user_id);
|
154
|
+
END IF; END $$;
|
155
|
+
EOS
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'for postgres table with enum column' do
|
160
|
+
before do
|
161
|
+
catalog.schema :postgres do
|
162
|
+
table 'user' do
|
163
|
+
column 'tenant_id'
|
164
|
+
column 'user_id'
|
165
|
+
column 'state', type: :enum, sub_type: :user_state, values: %w(active inactive terminated), default: 'active'
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
let(:target) { catalog.postgres.user_table }
|
171
|
+
|
172
|
+
it 'should render table template' do
|
173
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
174
|
+
DO $$ BEGIN
|
175
|
+
IF NOT EXISTS (SELECT 1 FROM pg_type t WHERE LOWER(t.typname) = LOWER('USER_STATE_TYPE')) THEN
|
176
|
+
CREATE TYPE USER_STATE_TYPE AS ENUM ('active', 'inactive', 'terminated');
|
177
|
+
END IF; END $$;
|
178
|
+
|
179
|
+
CREATE TABLE IF NOT EXISTS user_table
|
180
|
+
(
|
181
|
+
id SERIAL PRIMARY KEY,
|
182
|
+
tenant_id INTEGER NOT NULL,
|
183
|
+
user_id INTEGER NOT NULL,
|
184
|
+
state USER_STATE_TYPE NOT NULL DEFAULT 'active'::USER_STATE_TYPE
|
185
|
+
);
|
186
|
+
EOS
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
context 'for postgres table with surrogate_key columns override' do
|
191
|
+
before do
|
192
|
+
catalog.schema :postgres do
|
193
|
+
table 'user' do
|
194
|
+
column 'identifier', type: :uuid, surrogate_key: true
|
195
|
+
column 'name', type: :string
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
let(:target) { catalog.postgres.user_table }
|
201
|
+
|
202
|
+
it 'should render table template' do
|
203
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
204
|
+
CREATE TABLE IF NOT EXISTS user_table
|
205
|
+
(
|
206
|
+
identifier UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
207
|
+
name VARCHAR NOT NULL
|
208
|
+
);
|
209
|
+
EOS
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
context 'for postgres table with partial values' do
|
214
|
+
before do
|
215
|
+
catalog.schema :postgres do
|
216
|
+
table 'user' do
|
217
|
+
column 'name', type: :string
|
218
|
+
column 'description', type: :string
|
219
|
+
row name: 'registered', description: 'Registered'
|
220
|
+
row name: 'active'
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
let(:target) { catalog.postgres.user_table }
|
226
|
+
|
227
|
+
it 'should render table template' do
|
228
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
229
|
+
CREATE TABLE IF NOT EXISTS user_table
|
230
|
+
(
|
231
|
+
id SERIAL PRIMARY KEY,
|
232
|
+
name VARCHAR NOT NULL,
|
233
|
+
description VARCHAR NOT NULL
|
234
|
+
);
|
235
|
+
|
236
|
+
INSERT INTO user_table (name, description)
|
237
|
+
SELECT 'registered', 'Registered'
|
238
|
+
WHERE NOT EXISTS (SELECT 1 FROM user_table WHERE name = 'registered' AND description = 'Registered');
|
239
|
+
|
240
|
+
INSERT INTO user_table (name)
|
241
|
+
SELECT 'active'
|
242
|
+
WHERE NOT EXISTS (SELECT 1 FROM user_table WHERE name = 'active');
|
243
|
+
EOS
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
context 'for postgres table with shared unique index' do
|
248
|
+
before do
|
249
|
+
catalog.schema :postgres do
|
250
|
+
table 'user' do
|
251
|
+
column 'tenant_id', unique: 'tenant_and_user', index: 'tenant_and_user'
|
252
|
+
column 'user_id', unique: 'tenant_and_user', index: 'tenant_and_user'
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
let(:target) { catalog.postgres.user_table }
|
258
|
+
|
259
|
+
it 'should render table template' do
|
260
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
261
|
+
CREATE TABLE IF NOT EXISTS user_table
|
262
|
+
(
|
263
|
+
id SERIAL PRIMARY KEY,
|
264
|
+
tenant_id INTEGER NOT NULL,
|
265
|
+
user_id INTEGER NOT NULL
|
266
|
+
);
|
267
|
+
|
268
|
+
DO $$ BEGIN
|
269
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_e0e4295_key') THEN
|
270
|
+
ALTER TABLE user_table ADD CONSTRAINT user_table_e0e4295_key UNIQUE(tenant_id, user_id);
|
271
|
+
END IF; END $$;
|
272
|
+
|
273
|
+
DO $$ BEGIN
|
274
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_e0e4295_index') THEN
|
275
|
+
CREATE UNIQUE INDEX user_table_e0e4295_index ON user_table (tenant_id, user_id);
|
276
|
+
END IF; END $$;
|
277
|
+
EOS
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
context 'for postgres table with multiple default and named rows' do
|
282
|
+
before do
|
283
|
+
catalog.schema :postgres do
|
284
|
+
table 'user' do
|
285
|
+
column 'tenant_id', type: :integer, natural_key: true
|
286
|
+
column 'user_id', type: :integer, natural_key: true
|
287
|
+
row tenant_id: 'default_tenant_id()', user_id: -1, attributes: {default: true}
|
288
|
+
row tenant_id: 'default_tenant_id()', user_id: -2, attributes: {id: 'unknown'}
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
let(:target) { catalog.postgres.user_table }
|
294
|
+
|
295
|
+
it 'should render table template' do
|
296
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
297
|
+
CREATE TABLE IF NOT EXISTS user_table
|
298
|
+
(
|
299
|
+
id SERIAL PRIMARY KEY,
|
300
|
+
tenant_id INTEGER NOT NULL,
|
301
|
+
user_id INTEGER NOT NULL
|
302
|
+
);
|
303
|
+
|
304
|
+
DO $$ BEGIN
|
305
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_e0e4295_key') THEN
|
306
|
+
ALTER TABLE user_table ADD CONSTRAINT user_table_e0e4295_key UNIQUE(tenant_id, user_id);
|
307
|
+
END IF; END $$;
|
308
|
+
|
309
|
+
INSERT INTO user_table (tenant_id, user_id)
|
310
|
+
SELECT default_tenant_id(), -1
|
311
|
+
WHERE NOT EXISTS (SELECT 1 FROM user_table WHERE tenant_id = default_tenant_id() AND user_id = -1);
|
312
|
+
|
313
|
+
INSERT INTO user_table (tenant_id, user_id)
|
314
|
+
SELECT default_tenant_id(), -2
|
315
|
+
WHERE NOT EXISTS (SELECT 1 FROM user_table WHERE tenant_id = default_tenant_id() AND user_id = -2);
|
316
|
+
|
317
|
+
CREATE OR REPLACE FUNCTION default_user_id()
|
318
|
+
RETURNS INTEGER IMMUTABLE AS $$
|
319
|
+
SELECT -1;
|
320
|
+
$$ LANGUAGE SQL;
|
321
|
+
|
322
|
+
CREATE OR REPLACE FUNCTION default_user_table_id()
|
323
|
+
RETURNS INTEGER IMMUTABLE AS $$
|
324
|
+
SELECT id FROM user_table WHERE tenant_id = default_tenant_id() AND user_id = -1;
|
325
|
+
$$ LANGUAGE SQL;
|
326
|
+
|
327
|
+
CREATE OR REPLACE FUNCTION unknown_user_id()
|
328
|
+
RETURNS INTEGER IMMUTABLE AS $$
|
329
|
+
SELECT -2;
|
330
|
+
$$ LANGUAGE SQL;
|
331
|
+
|
332
|
+
CREATE OR REPLACE FUNCTION unknown_user_table_id()
|
333
|
+
RETURNS INTEGER IMMUTABLE AS $$
|
334
|
+
SELECT id FROM user_table WHERE tenant_id = default_tenant_id() AND user_id = -2;
|
335
|
+
$$ LANGUAGE SQL;
|
336
|
+
EOS
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
context 'for postgres table with referenced tables' do
|
341
|
+
before do
|
342
|
+
catalog.schema :postgres do
|
343
|
+
table 'user_account_state' do
|
344
|
+
column 'name', type: :string, unique: true
|
345
|
+
column 'description', type: :string
|
346
|
+
row name: 'registered', description: 'Registered'
|
347
|
+
row name: 'active', description: 'Active', attributes: { default: true }
|
348
|
+
row name: 'inactive', description: 'Inactive'
|
349
|
+
end
|
350
|
+
|
351
|
+
table 'user' do
|
352
|
+
references :user_account_state
|
353
|
+
column 'name', type: :string
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
let(:target) { catalog.postgres.user_table }
|
359
|
+
|
360
|
+
it 'should render table template' do
|
361
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
362
|
+
CREATE TABLE IF NOT EXISTS user_table
|
363
|
+
(
|
364
|
+
id SERIAL PRIMARY KEY,
|
365
|
+
user_account_state_table_id INTEGER NOT NULL REFERENCES user_account_state_table(id) DEFAULT default_user_account_state_table_id(),
|
366
|
+
name VARCHAR NOT NULL
|
367
|
+
);
|
368
|
+
|
369
|
+
DO $$ BEGIN
|
370
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_bd2027e_index') THEN
|
371
|
+
CREATE INDEX user_table_bd2027e_index ON user_table (user_account_state_table_id);
|
372
|
+
END IF; END $$;
|
373
|
+
EOS
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
context 'for postgres table with labeled referenced table' do
|
378
|
+
before do
|
379
|
+
catalog.schema :postgres do
|
380
|
+
table 'user_account_state' do
|
381
|
+
column 'name', type: :string, unique: true
|
382
|
+
column 'description', type: :string
|
383
|
+
row name: 'active', description: 'Active', attributes: { default: true }
|
384
|
+
end
|
385
|
+
|
386
|
+
table 'user' do
|
387
|
+
references :user_account_state
|
388
|
+
references :user_account_state, label: 'hr', null: true, default: :null
|
389
|
+
column 'name', type: :string
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
let(:target) { catalog.postgres.user_table }
|
395
|
+
|
396
|
+
it 'should render table template' do
|
397
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
398
|
+
CREATE TABLE IF NOT EXISTS user_table
|
399
|
+
(
|
400
|
+
id SERIAL PRIMARY KEY,
|
401
|
+
user_account_state_table_id INTEGER NOT NULL REFERENCES user_account_state_table(id) DEFAULT default_user_account_state_table_id(),
|
402
|
+
hr_user_account_state_table_id INTEGER REFERENCES user_account_state_table(id),
|
403
|
+
name VARCHAR NOT NULL
|
404
|
+
);
|
405
|
+
|
406
|
+
DO $$ BEGIN
|
407
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_bd2027e_index') THEN
|
408
|
+
CREATE INDEX user_table_bd2027e_index ON user_table (user_account_state_table_id);
|
409
|
+
END IF; END $$;
|
410
|
+
|
411
|
+
DO $$ BEGIN
|
412
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_074da4a_index') THEN
|
413
|
+
CREATE INDEX user_table_074da4a_index ON user_table (hr_user_account_state_table_id);
|
414
|
+
END IF; END $$;
|
415
|
+
EOS
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
context '#stage_table' do
|
420
|
+
before do
|
421
|
+
catalog.schema :postgres do
|
422
|
+
table 'user_account_state' do
|
423
|
+
column 'name', type: :string, unique: true
|
424
|
+
column 'description', type: :string
|
425
|
+
end
|
426
|
+
|
427
|
+
table 'user' do
|
428
|
+
references :user_account_state
|
429
|
+
references :user_account_state, label: 'hr'
|
430
|
+
column 'name', type: :string
|
431
|
+
end
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
let(:table) { catalog.postgres.user_table }
|
436
|
+
let(:target) { table.stage_table(columns: columns) }
|
437
|
+
|
438
|
+
context 'without specified columns' do
|
439
|
+
let(:columns) { [] }
|
440
|
+
|
441
|
+
it 'should render table template' do
|
442
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
443
|
+
CREATE TEMPORARY TABLE IF NOT EXISTS user_table_stage
|
444
|
+
(
|
445
|
+
user_account_state_table_id INTEGER,
|
446
|
+
hr_user_account_state_table_id INTEGER,
|
447
|
+
name VARCHAR
|
448
|
+
);
|
449
|
+
|
450
|
+
CREATE INDEX user_table_stage_bd2027e_index ON user_table_stage (user_account_state_table_id);
|
451
|
+
CREATE INDEX user_table_stage_074da4a_index ON user_table_stage (hr_user_account_state_table_id);
|
452
|
+
EOS
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
context 'for postgres table with all specified columns' do
|
457
|
+
let(:columns) { %w(hr_user_account_state_table_id user_account_state_table_id name) }
|
458
|
+
|
459
|
+
it 'should render table template' do
|
460
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
461
|
+
CREATE TEMPORARY TABLE IF NOT EXISTS user_table_stage
|
462
|
+
(
|
463
|
+
hr_user_account_state_table_id INTEGER,
|
464
|
+
user_account_state_table_id INTEGER,
|
465
|
+
name VARCHAR
|
466
|
+
);
|
467
|
+
|
468
|
+
CREATE INDEX user_table_stage_074da4a_index ON user_table_stage (hr_user_account_state_table_id);
|
469
|
+
CREATE INDEX user_table_stage_bd2027e_index ON user_table_stage (user_account_state_table_id);
|
470
|
+
EOS
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
context 'for postgres table with all specified columns in denormalized form' do
|
475
|
+
let(:columns) { %w(hr_user_account_state.name user_account_state.name name) }
|
476
|
+
|
477
|
+
it 'should render table template' do
|
478
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
479
|
+
CREATE TEMPORARY TABLE IF NOT EXISTS user_table_stage
|
480
|
+
(
|
481
|
+
hr_user_account_state_table_name VARCHAR,
|
482
|
+
user_account_state_table_name VARCHAR,
|
483
|
+
name VARCHAR
|
484
|
+
);
|
485
|
+
EOS
|
486
|
+
end
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
context 'for postgres table with sequence column' do
|
491
|
+
before do
|
492
|
+
catalog.schema :postgres do
|
493
|
+
table 'user' do
|
494
|
+
column 'id', type: :sequence, surrogate_key: true, sequence_offset: 1024
|
495
|
+
column 'tenant_id'
|
496
|
+
column 'user_id'
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
let(:target) { catalog.postgres.user_table }
|
502
|
+
|
503
|
+
it 'should render table template' do
|
504
|
+
is_expected.to eq <<-EOS.strip_heredoc
|
505
|
+
DO $$ BEGIN
|
506
|
+
IF NOT EXISTS (SELECT 1 FROM pg_class c WHERE c.relname = 'user_table_id_seq') THEN
|
507
|
+
CREATE SEQUENCE user_table_id_seq;
|
508
|
+
ALTER SEQUENCE user_table_id_seq RESTART 1024;
|
509
|
+
END IF; END $$;
|
510
|
+
|
511
|
+
CREATE TABLE IF NOT EXISTS user_table
|
512
|
+
(
|
513
|
+
id INTEGER PRIMARY KEY DEFAULT nextval('user_table_id_seq'),
|
514
|
+
tenant_id INTEGER NOT NULL,
|
515
|
+
user_id INTEGER NOT NULL
|
516
|
+
);
|
517
|
+
|
518
|
+
DO $$ BEGIN
|
519
|
+
IF NOT EXISTS (SELECT 1 WHERE sequence_owner('user_table_id_seq') = 'user_table.id') THEN
|
520
|
+
ALTER SEQUENCE user_table_id_seq OWNED BY user_table.id;
|
521
|
+
END IF; END $$;
|
522
|
+
EOS
|
523
|
+
end
|
524
|
+
end
|
525
|
+
end
|