purview 1.0.0.alpha
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/.gitignore +33 -0
- data/.travis.yml +18 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +143 -0
- data/Rakefile +11 -0
- data/TODO +81 -0
- data/lib/purview/columns/base.rb +65 -0
- data/lib/purview/columns/boolean.rb +11 -0
- data/lib/purview/columns/created_timestamp.rb +11 -0
- data/lib/purview/columns/date.rb +11 -0
- data/lib/purview/columns/float.rb +11 -0
- data/lib/purview/columns/id.rb +11 -0
- data/lib/purview/columns/integer.rb +11 -0
- data/lib/purview/columns/money.rb +11 -0
- data/lib/purview/columns/string.rb +11 -0
- data/lib/purview/columns/text.rb +11 -0
- data/lib/purview/columns/time.rb +11 -0
- data/lib/purview/columns/timestamp.rb +11 -0
- data/lib/purview/columns/updated_timestamp.rb +11 -0
- data/lib/purview/columns/uuid.rb +11 -0
- data/lib/purview/columns.rb +14 -0
- data/lib/purview/connections/base.rb +55 -0
- data/lib/purview/connections/mysql.rb +39 -0
- data/lib/purview/connections/postgresql.rb +27 -0
- data/lib/purview/connections.rb +3 -0
- data/lib/purview/databases/base.rb +559 -0
- data/lib/purview/databases/mysql.rb +207 -0
- data/lib/purview/databases/postgresql.rb +210 -0
- data/lib/purview/databases.rb +3 -0
- data/lib/purview/exceptions/base.rb +5 -0
- data/lib/purview/exceptions/could_not_acquire_lock.rb +9 -0
- data/lib/purview/exceptions/lock_already_released.rb +9 -0
- data/lib/purview/exceptions/no_table.rb +9 -0
- data/lib/purview/exceptions/no_window.rb +9 -0
- data/lib/purview/exceptions/rows_outside_window.rb +18 -0
- data/lib/purview/exceptions/table.rb +13 -0
- data/lib/purview/exceptions.rb +7 -0
- data/lib/purview/loaders/base.rb +154 -0
- data/lib/purview/loaders/mysql.rb +81 -0
- data/lib/purview/loaders/postgresql.rb +81 -0
- data/lib/purview/loaders.rb +3 -0
- data/lib/purview/loggers/base.rb +99 -0
- data/lib/purview/loggers/console.rb +11 -0
- data/lib/purview/loggers.rb +2 -0
- data/lib/purview/mixins/helpers.rb +21 -0
- data/lib/purview/mixins/logger.rb +21 -0
- data/lib/purview/mixins.rb +2 -0
- data/lib/purview/parsers/base.rb +39 -0
- data/lib/purview/parsers/csv.rb +49 -0
- data/lib/purview/parsers/tsv.rb +11 -0
- data/lib/purview/parsers.rb +3 -0
- data/lib/purview/pullers/base.rb +19 -0
- data/lib/purview/pullers/uri.rb +66 -0
- data/lib/purview/pullers.rb +2 -0
- data/lib/purview/refinements/object.rb +5 -0
- data/lib/purview/refinements/time.rb +5 -0
- data/lib/purview/refinements.rb +2 -0
- data/lib/purview/structs/base.rb +10 -0
- data/lib/purview/structs/result.rb +7 -0
- data/lib/purview/structs/window.rb +7 -0
- data/lib/purview/structs.rb +3 -0
- data/lib/purview/tables/base.rb +140 -0
- data/lib/purview/tables/raw.rb +13 -0
- data/lib/purview/tables.rb +2 -0
- data/lib/purview/types/base.rb +9 -0
- data/lib/purview/types/boolean.rb +9 -0
- data/lib/purview/types/date.rb +9 -0
- data/lib/purview/types/float.rb +9 -0
- data/lib/purview/types/integer.rb +9 -0
- data/lib/purview/types/money.rb +9 -0
- data/lib/purview/types/string.rb +9 -0
- data/lib/purview/types/text.rb +9 -0
- data/lib/purview/types/time.rb +9 -0
- data/lib/purview/types/timestamp.rb +9 -0
- data/lib/purview/types/uuid.rb +9 -0
- data/lib/purview/types.rb +11 -0
- data/lib/purview/version.rb +3 -0
- data/lib/purview.rb +27 -0
- data/purview.gemspec +29 -0
- data/spec/spec_helper.rb +5 -0
- metadata +210 -0
@@ -0,0 +1,207 @@
|
|
1
|
+
module Purview
|
2
|
+
module Databases
|
3
|
+
class MySQL < Base
|
4
|
+
def false_value
|
5
|
+
'0'
|
6
|
+
end
|
7
|
+
|
8
|
+
def null_value
|
9
|
+
'NULL'
|
10
|
+
end
|
11
|
+
|
12
|
+
def true_value
|
13
|
+
'1'
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def connection_opts
|
19
|
+
super.merge(:database => name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def connection_type
|
23
|
+
Purview::Connections::MySQL
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_index_sql(table_name, index_name, table, columns, index_opts={})
|
27
|
+
'CREATE INDEX %s ON %s (%s)' % [
|
28
|
+
index_name,
|
29
|
+
table_name,
|
30
|
+
column_names(columns).join(', '),
|
31
|
+
]
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_table_sql(table_name, table, table_opts={})
|
35
|
+
'CREATE TABLE %s (%s)' % [
|
36
|
+
table_name,
|
37
|
+
column_definitions(table).join(', '),
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_temporary_table_sql(table_name, table, table_opts={})
|
42
|
+
'CREATE TEMPORARY TABLE %s LIKE %s' % [
|
43
|
+
table_name,
|
44
|
+
table.name,
|
45
|
+
]
|
46
|
+
end
|
47
|
+
|
48
|
+
def default_map
|
49
|
+
super.merge(Purview::Types::Timestamp => '0')
|
50
|
+
end
|
51
|
+
|
52
|
+
def drop_index_sql(table_name, index_name, table, columns, index_opts={})
|
53
|
+
'DROP INDEX %s' % [
|
54
|
+
index_name,
|
55
|
+
]
|
56
|
+
end
|
57
|
+
|
58
|
+
def drop_table_sql(table_name, table, table_opts={})
|
59
|
+
'DROP TABLE %s' % [
|
60
|
+
table_name,
|
61
|
+
]
|
62
|
+
end
|
63
|
+
|
64
|
+
def ensure_table_metadata_exists_for_table_sql(table)
|
65
|
+
'INSERT IGNORE INTO %s VALUES (%s, NULL, NULL, NULL, NULL)' % [
|
66
|
+
table_metadata_table_name,
|
67
|
+
quoted(table.name),
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
def ensure_table_metadata_table_exists_sql
|
72
|
+
'CREATE TABLE IF NOT EXISTS %s (%s PRIMARY KEY, %s, %s, %s, %s)' % [
|
73
|
+
table_metadata_table_name,
|
74
|
+
table_metadata_table_name_column_definition,
|
75
|
+
table_metadata_enabled_column_definition,
|
76
|
+
table_metadata_last_pulled_at_column_definition,
|
77
|
+
table_metadata_locked_at_column_definition,
|
78
|
+
table_metadata_max_timestamp_pulled_column_definition,
|
79
|
+
]
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_enabled_for_table_sql(table)
|
83
|
+
'SELECT %s FROM %s WHERE %s = %s' % [
|
84
|
+
table_metadata_enabled_column_name,
|
85
|
+
table_metadata_table_name,
|
86
|
+
table_metadata_table_name_column_name,
|
87
|
+
quoted(table.name),
|
88
|
+
]
|
89
|
+
end
|
90
|
+
|
91
|
+
def get_last_pulled_at_for_table_sql(table)
|
92
|
+
'SELECT %s FROM %s WHERE %s = %s' % [
|
93
|
+
table_metadata_last_pulled_at_column_name,
|
94
|
+
table_metadata_table_name,
|
95
|
+
table_metadata_table_name_column_name,
|
96
|
+
quoted(table.name),
|
97
|
+
]
|
98
|
+
end
|
99
|
+
|
100
|
+
def get_locked_at_for_table_sql(table)
|
101
|
+
'SELECT %s FROM %s WHERE %s = %s' % [
|
102
|
+
table_metadata_locked_at_column_name,
|
103
|
+
table_metadata_table_name,
|
104
|
+
table_metadata_table_name_column_name,
|
105
|
+
quoted(table.name),
|
106
|
+
]
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_max_timestamp_pulled_for_table_sql(table)
|
110
|
+
'SELECT %s FROM %s WHERE %s = %s' % [
|
111
|
+
table_metadata_max_timestamp_pulled_column_name,
|
112
|
+
table_metadata_table_name,
|
113
|
+
table_metadata_table_name_column_name,
|
114
|
+
quoted(table.name),
|
115
|
+
]
|
116
|
+
end
|
117
|
+
|
118
|
+
def limit_map
|
119
|
+
super.merge(Purview::Types::String => 255)
|
120
|
+
end
|
121
|
+
|
122
|
+
def lock_table_sql(table, timestamp)
|
123
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND %s IS NULL' % [
|
124
|
+
table_metadata_table_name,
|
125
|
+
table_metadata_locked_at_column_name,
|
126
|
+
quoted(timestamp),
|
127
|
+
table_metadata_table_name_column_name,
|
128
|
+
quoted(table.name),
|
129
|
+
table_metadata_locked_at_column_name,
|
130
|
+
]
|
131
|
+
end
|
132
|
+
|
133
|
+
def next_table_sql(timestamp)
|
134
|
+
'SELECT %s FROM %s WHERE %s = %s AND %s IS NULL ORDER BY %s IS NULL DESC, %s LIMIT 1' % [
|
135
|
+
table_metadata_table_name_column_name,
|
136
|
+
table_metadata_table_name,
|
137
|
+
table_metadata_enabled_column_name,
|
138
|
+
quoted(true_value),
|
139
|
+
table_metadata_locked_at_column_name,
|
140
|
+
table_metadata_last_pulled_at_column_name,
|
141
|
+
table_metadata_last_pulled_at_column_name,
|
142
|
+
]
|
143
|
+
end
|
144
|
+
|
145
|
+
def set_enabled_for_table_sql(table, enabled)
|
146
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND (%s IS NULL OR %s = %s)' % [
|
147
|
+
table_metadata_table_name,
|
148
|
+
table_metadata_enabled_column_name,
|
149
|
+
quoted(enabled),
|
150
|
+
table_metadata_table_name_column_name,
|
151
|
+
quoted(table.name),
|
152
|
+
table_metadata_enabled_column_name,
|
153
|
+
table_metadata_enabled_column_name,
|
154
|
+
quoted(false_value),
|
155
|
+
]
|
156
|
+
end
|
157
|
+
|
158
|
+
def set_last_pulled_at_for_table_sql(table, timestamp)
|
159
|
+
'UPDATE %s SET %s = %s WHERE %s = %s' % [
|
160
|
+
table_metadata_table_name,
|
161
|
+
table_metadata_last_pulled_at_column_name,
|
162
|
+
quoted(timestamp),
|
163
|
+
table_metadata_table_name_column_name,
|
164
|
+
quoted(table.name),
|
165
|
+
]
|
166
|
+
end
|
167
|
+
|
168
|
+
def set_locked_at_for_table_sql(table, timestamp)
|
169
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND %s' % [
|
170
|
+
table_metadata_table_name,
|
171
|
+
table_metadata_locked_at_column_name,
|
172
|
+
quoted(timestamp),
|
173
|
+
table_metadata_table_name_column_name,
|
174
|
+
quoted(table.name),
|
175
|
+
]
|
176
|
+
end
|
177
|
+
|
178
|
+
def set_max_timestamp_pulled_for_table_sql(table, timestamp)
|
179
|
+
'UPDATE %s SET %s = %s WHERE %s = %s' % [
|
180
|
+
table_metadata_table_name,
|
181
|
+
table_metadata_max_timestamp_pulled_column_name,
|
182
|
+
quoted(timestamp),
|
183
|
+
table_metadata_table_name_column_name,
|
184
|
+
quoted(table.name),
|
185
|
+
]
|
186
|
+
end
|
187
|
+
|
188
|
+
def type_map
|
189
|
+
super.merge(
|
190
|
+
Purview::Types::Money => 'decimal',
|
191
|
+
Purview::Types::UUID => 'varchar',
|
192
|
+
)
|
193
|
+
end
|
194
|
+
|
195
|
+
def unlock_table_sql(table)
|
196
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND %s IS NOT NULL' % [
|
197
|
+
table_metadata_table_name,
|
198
|
+
table_metadata_locked_at_column_name,
|
199
|
+
null_value,
|
200
|
+
table_metadata_table_name_column_name,
|
201
|
+
quoted(table.name),
|
202
|
+
table_metadata_locked_at_column_name,
|
203
|
+
]
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
module Purview
|
2
|
+
module Databases
|
3
|
+
class PostgreSQL < Base
|
4
|
+
def false_value
|
5
|
+
'FALSE'
|
6
|
+
end
|
7
|
+
|
8
|
+
def null_value
|
9
|
+
'NULL'
|
10
|
+
end
|
11
|
+
|
12
|
+
def true_value
|
13
|
+
'TRUE'
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def connection_opts
|
19
|
+
super.merge(:dbname => name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def connection_type
|
23
|
+
Purview::Connections::PostgreSQL
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_index_sql(table_name, index_name, table, columns, index_opts={})
|
27
|
+
'CREATE INDEX %s ON %s (%s)' % [
|
28
|
+
index_name,
|
29
|
+
table_name,
|
30
|
+
column_names(columns).join(', '),
|
31
|
+
]
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_table_sql(table_name, table, table_opts={})
|
35
|
+
'CREATE TABLE %s (%s)' % [
|
36
|
+
table_name,
|
37
|
+
column_definitions(table).join(', '),
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_temporary_table_sql(table_name, table, table_opts={})
|
42
|
+
'CREATE TEMPORARY TABLE %s (LIKE %s INCLUDING ALL)' % [
|
43
|
+
table_name,
|
44
|
+
table.name,
|
45
|
+
]
|
46
|
+
end
|
47
|
+
|
48
|
+
def drop_index_sql(table_name, index_name, table, columns, index_opts={})
|
49
|
+
'DROP INDEX %s' % [
|
50
|
+
index_name,
|
51
|
+
]
|
52
|
+
end
|
53
|
+
|
54
|
+
def drop_table_sql(table_name, table, table_opts={})
|
55
|
+
'DROP TABLE %s' % [
|
56
|
+
table_name,
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
def ensure_table_metadata_exists_for_table_sql(table)
|
61
|
+
'INSERT INTO %s (%s) SELECT %s WHERE NOT EXISTS (SELECT 1 FROM %s WHERE %s = %s)' % [
|
62
|
+
table_metadata_table_name,
|
63
|
+
table_metadata_table_name_column_name,
|
64
|
+
quoted(table.name),
|
65
|
+
table_metadata_table_name,
|
66
|
+
table_metadata_table_name_column_name,
|
67
|
+
quoted(table.name),
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
def ensure_table_metadata_table_exists_sql
|
72
|
+
'CREATE TABLE IF NOT EXISTS %s (%s PRIMARY KEY, %s, %s, %s, %s)' % [
|
73
|
+
table_metadata_table_name,
|
74
|
+
table_metadata_table_name_column_definition,
|
75
|
+
table_metadata_enabled_column_definition,
|
76
|
+
table_metadata_last_pulled_at_column_definition,
|
77
|
+
table_metadata_locked_at_column_definition,
|
78
|
+
table_metadata_max_timestamp_pulled_column_definition,
|
79
|
+
]
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_enabled_for_table_sql(table)
|
83
|
+
'SELECT %s FROM %s WHERE %s = %s' % [
|
84
|
+
table_metadata_enabled_column_name,
|
85
|
+
table_metadata_table_name,
|
86
|
+
table_metadata_table_name_column_name,
|
87
|
+
quoted(table.name),
|
88
|
+
]
|
89
|
+
end
|
90
|
+
|
91
|
+
def get_last_pulled_at_for_table_sql(table)
|
92
|
+
'SELECT %s FROM %s WHERE %s = %s' % [
|
93
|
+
table_metadata_last_pulled_at_column_name,
|
94
|
+
table_metadata_table_name,
|
95
|
+
table_metadata_table_name_column_name,
|
96
|
+
quoted(table.name),
|
97
|
+
]
|
98
|
+
end
|
99
|
+
|
100
|
+
def get_locked_at_for_table_sql(table)
|
101
|
+
'SELECT %s FROM %s WHERE %s = %s' % [
|
102
|
+
table_metadata_locked_at_column_name,
|
103
|
+
table_metadata_table_name,
|
104
|
+
table_metadata_table_name_column_name,
|
105
|
+
quoted(table.name),
|
106
|
+
]
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_max_timestamp_pulled_for_table_sql(table)
|
110
|
+
'SELECT %s FROM %s WHERE %s = %s' % [
|
111
|
+
table_metadata_max_timestamp_pulled_column_name,
|
112
|
+
table_metadata_table_name,
|
113
|
+
table_metadata_table_name_column_name,
|
114
|
+
quoted(table.name),
|
115
|
+
]
|
116
|
+
end
|
117
|
+
|
118
|
+
def limitless_types
|
119
|
+
super + [
|
120
|
+
Purview::Types::Money,
|
121
|
+
Purview::Types::UUID,
|
122
|
+
]
|
123
|
+
end
|
124
|
+
|
125
|
+
def lock_table_sql(table, timestamp)
|
126
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND %s IS NULL' % [
|
127
|
+
table_metadata_table_name,
|
128
|
+
table_metadata_locked_at_column_name,
|
129
|
+
quoted(timestamp),
|
130
|
+
table_metadata_table_name_column_name,
|
131
|
+
quoted(table.name),
|
132
|
+
table_metadata_locked_at_column_name,
|
133
|
+
]
|
134
|
+
end
|
135
|
+
|
136
|
+
def next_table_sql(timestamp)
|
137
|
+
'SELECT %s FROM %s WHERE %s = %s AND %s IS NULL ORDER BY %s IS NULL DESC, %s LIMIT 1' % [
|
138
|
+
table_metadata_table_name_column_name,
|
139
|
+
table_metadata_table_name,
|
140
|
+
table_metadata_enabled_column_name,
|
141
|
+
quoted(true_value),
|
142
|
+
table_metadata_locked_at_column_name,
|
143
|
+
table_metadata_last_pulled_at_column_name,
|
144
|
+
table_metadata_last_pulled_at_column_name,
|
145
|
+
]
|
146
|
+
end
|
147
|
+
|
148
|
+
def set_enabled_for_table_sql(table, enabled)
|
149
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND (%s IS NULL OR %s = %s)' % [
|
150
|
+
table_metadata_table_name,
|
151
|
+
table_metadata_enabled_column_name,
|
152
|
+
quoted(enabled),
|
153
|
+
table_metadata_table_name_column_name,
|
154
|
+
quoted(table.name),
|
155
|
+
table_metadata_enabled_column_name,
|
156
|
+
table_metadata_enabled_column_name,
|
157
|
+
quoted(false_value),
|
158
|
+
]
|
159
|
+
end
|
160
|
+
|
161
|
+
def set_last_pulled_at_for_table_sql(table, timestamp)
|
162
|
+
'UPDATE %s SET %s = %s WHERE %s = %s' % [
|
163
|
+
table_metadata_table_name,
|
164
|
+
table_metadata_last_pulled_at_column_name,
|
165
|
+
quoted(timestamp),
|
166
|
+
table_metadata_table_name_column_name,
|
167
|
+
quoted(table.name),
|
168
|
+
]
|
169
|
+
end
|
170
|
+
|
171
|
+
def set_locked_at_for_table_sql(table, timestamp)
|
172
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND %s' % [
|
173
|
+
table_metadata_table_name,
|
174
|
+
table_metadata_locked_at_column_name,
|
175
|
+
quoted(timestamp),
|
176
|
+
table_metadata_table_name_column_name,
|
177
|
+
quoted(table.name),
|
178
|
+
]
|
179
|
+
end
|
180
|
+
|
181
|
+
def set_max_timestamp_pulled_for_table_sql(table, timestamp)
|
182
|
+
'UPDATE %s SET %s = %s WHERE %s = %s' % [
|
183
|
+
table_metadata_table_name,
|
184
|
+
table_metadata_max_timestamp_pulled_column_name,
|
185
|
+
quoted(timestamp),
|
186
|
+
table_metadata_table_name_column_name,
|
187
|
+
quoted(table.name),
|
188
|
+
]
|
189
|
+
end
|
190
|
+
|
191
|
+
def type_map
|
192
|
+
super.merge(
|
193
|
+
Purview::Types::Money => 'money',
|
194
|
+
Purview::Types::UUID => 'uuid',
|
195
|
+
)
|
196
|
+
end
|
197
|
+
|
198
|
+
def unlock_table_sql(table)
|
199
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND %s IS NOT NULL' % [
|
200
|
+
table_metadata_table_name,
|
201
|
+
table_metadata_locked_at_column_name,
|
202
|
+
null_value,
|
203
|
+
table_metadata_table_name_column_name,
|
204
|
+
quoted(table.name),
|
205
|
+
table_metadata_locked_at_column_name,
|
206
|
+
]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Purview
|
2
|
+
module Exceptions
|
3
|
+
class RowsOutsideWindow < Base
|
4
|
+
def initialize(table_name, count)
|
5
|
+
@table_name = table_name
|
6
|
+
@count = count
|
7
|
+
end
|
8
|
+
|
9
|
+
def message
|
10
|
+
"#{count} row(s) outside window for table: #{table_name}"
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
attr_reader :count, :table_name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'purview/exceptions/base'
|
2
|
+
require 'purview/exceptions/table'
|
3
|
+
require 'purview/exceptions/could_not_acquire_lock'
|
4
|
+
require 'purview/exceptions/lock_already_released'
|
5
|
+
require 'purview/exceptions/no_table'
|
6
|
+
require 'purview/exceptions/no_window'
|
7
|
+
require 'purview/exceptions/rows_outside_window'
|
@@ -0,0 +1,154 @@
|
|
1
|
+
module Purview
|
2
|
+
module Loaders
|
3
|
+
class Base
|
4
|
+
def initialize(opts={})
|
5
|
+
@opts = opts
|
6
|
+
end
|
7
|
+
|
8
|
+
def load(connection, rows, window)
|
9
|
+
with_context_logging("`load` for: #{table.name}") do
|
10
|
+
with_temporary_table(connection, rows, window) do |temporary_table_name|
|
11
|
+
update_result = \
|
12
|
+
connection.execute(table_update_sql(window, temporary_table_name))
|
13
|
+
delete_result = \
|
14
|
+
connection.execute(table_delete_sql(window, temporary_table_name))
|
15
|
+
insert_result = \
|
16
|
+
connection.execute(table_insert_sql(window, temporary_table_name))
|
17
|
+
logger.debug(
|
18
|
+
'%d row(s) inserted, %d row(s) updated and %d row(s) deleted in: %s' % [
|
19
|
+
insert_result.rows_affected,
|
20
|
+
update_result.rows_affected,
|
21
|
+
delete_result.rows_affected,
|
22
|
+
table.name,
|
23
|
+
]
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
include Purview::Mixins::Helpers
|
32
|
+
include Purview::Mixins::Logger
|
33
|
+
|
34
|
+
attr_reader :opts
|
35
|
+
|
36
|
+
def count_column_name
|
37
|
+
'count'
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_temporary_table(connection)
|
41
|
+
database.create_temporary_table(
|
42
|
+
connection,
|
43
|
+
table,
|
44
|
+
:table => temporary_table_opts
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
def database
|
49
|
+
table.database
|
50
|
+
end
|
51
|
+
|
52
|
+
def id_in_sql(temporary_table_name)
|
53
|
+
raise %{All "#{Base}(s)" must override the "id_in_sql" method}
|
54
|
+
end
|
55
|
+
|
56
|
+
def in_window_sql(window)
|
57
|
+
raise %{All "#{Base}(s)" must override the "in_window_sql" method}
|
58
|
+
end
|
59
|
+
|
60
|
+
def load_temporary_table(connection, temporary_table_name, rows, window)
|
61
|
+
with_context_logging("`load_temporary_table` for: #{temporary_table_name}") do
|
62
|
+
rows.each_slice(rows_per_slice) do |rows_slice|
|
63
|
+
connection.execute(
|
64
|
+
temporary_table_insert_sql(
|
65
|
+
temporary_table_name,
|
66
|
+
rows_slice
|
67
|
+
)
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def not_in_window_sql(window)
|
74
|
+
raise %{All "#{Base}(s)" must override the "not_in_window_sql" method}
|
75
|
+
end
|
76
|
+
|
77
|
+
def quoted(value)
|
78
|
+
database.quoted(value)
|
79
|
+
end
|
80
|
+
|
81
|
+
def row_values(row)
|
82
|
+
table.column_names.map { |column_name| quoted(row[column_name]) }.join(', ')
|
83
|
+
end
|
84
|
+
|
85
|
+
def rows_per_slice
|
86
|
+
opts[:rows_per_slice] || 1000
|
87
|
+
end
|
88
|
+
|
89
|
+
def table
|
90
|
+
opts[:table]
|
91
|
+
end
|
92
|
+
|
93
|
+
def table_delete_sql(window, temporary_table_name)
|
94
|
+
raise %{All "#{Base}(s)" must override the "table_delete_sql" method}
|
95
|
+
end
|
96
|
+
|
97
|
+
def table_insert_sql(window, temporary_table_name)
|
98
|
+
raise %{All "#{Base}(s)" must override the "table_insert_sql" method}
|
99
|
+
end
|
100
|
+
|
101
|
+
def table_update_sql(window, temporary_table_name)
|
102
|
+
raise %{All "#{Base}(s)" must override the "table_update_sql" method}
|
103
|
+
end
|
104
|
+
|
105
|
+
def temporary_table_insert_sql(temporary_table_name, rows)
|
106
|
+
raise %{All "#{Base}(s)" must override the "temporary_table_insert_sql" method}
|
107
|
+
end
|
108
|
+
|
109
|
+
def temporary_table_opts
|
110
|
+
{
|
111
|
+
:create_indices => true,
|
112
|
+
:name => table.temporary_name,
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def temporary_table_verify_sql(temporary_table_name, rows, window)
|
117
|
+
raise %{All "#{Base}(s)" must override the "temporary_table_verify_sql" method}
|
118
|
+
end
|
119
|
+
|
120
|
+
def verify_temporary_table(connection, temporary_table_name, rows, window)
|
121
|
+
with_context_logging("`verify_temporary_table` for: #{temporary_table_name}") do
|
122
|
+
rows_outside_window = connection.execute(
|
123
|
+
temporary_table_verify_sql(
|
124
|
+
temporary_table_name,
|
125
|
+
rows,
|
126
|
+
window
|
127
|
+
)
|
128
|
+
).rows[0][count_column_name]
|
129
|
+
raise Purview::Exceptions::RowsOutsideWindow.new(temporary_table_name, rows_outside_window) \
|
130
|
+
unless zero?(rows_outside_window)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def with_temporary_table(connection, rows, window)
|
135
|
+
yield(
|
136
|
+
create_temporary_table(connection).tap do |temporary_table_name|
|
137
|
+
load_temporary_table(
|
138
|
+
connection,
|
139
|
+
temporary_table_name,
|
140
|
+
rows,
|
141
|
+
window
|
142
|
+
)
|
143
|
+
verify_temporary_table(
|
144
|
+
connection,
|
145
|
+
temporary_table_name,
|
146
|
+
rows,
|
147
|
+
window
|
148
|
+
)
|
149
|
+
end
|
150
|
+
)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|