purview 1.5.0 → 1.6.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 +4 -4
- data/.gitignore +4 -2
- data/.travis.yml +4 -10
- data/Gemfile +8 -6
- data/README.md +33 -36
- data/TODO +54 -89
- data/lib/purview/connections.rb +2 -0
- data/lib/purview/connections/sqlite.rb +11 -0
- data/lib/purview/databases.rb +2 -0
- data/lib/purview/databases/base.rb +7 -7
- data/lib/purview/databases/mssql.rb +180 -0
- data/lib/purview/databases/postgresql.rb +4 -0
- data/lib/purview/databases/sqlite.rb +173 -0
- data/lib/purview/dialects.rb +1 -0
- data/lib/purview/dialects/sqlite.rb +25 -0
- data/lib/purview/loaders.rb +2 -0
- data/lib/purview/loaders/mssql.rb +85 -0
- data/lib/purview/loaders/sqlite.rb +85 -0
- data/lib/purview/pullers.rb +1 -0
- data/lib/purview/pullers/sqlite.rb +15 -0
- data/lib/purview/raw_connections.rb +5 -2
- data/lib/purview/raw_connections/jdbc/mysql.rb +1 -1
- data/lib/purview/raw_connections/jdbc/postgres.rb +1 -1
- data/lib/purview/raw_connections/jdbc/sqlite3.rb +21 -0
- data/lib/purview/raw_connections/sqlite3.rb +34 -0
- data/lib/purview/structs/base.rb +2 -1
- data/lib/purview/version.rb +1 -1
- data/purview.gemspec +3 -2
- metadata +17 -7
@@ -0,0 +1,173 @@
|
|
1
|
+
module Purview
|
2
|
+
module Databases
|
3
|
+
class SQLite < Base
|
4
|
+
private
|
5
|
+
|
6
|
+
def connection_type
|
7
|
+
Purview::Connections::SQLite
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_index_sql(table_name, index_name, index, index_opts={})
|
11
|
+
'CREATE%sINDEX %s ON %s (%s)' % [
|
12
|
+
index.unique? ? ' UNIQUE ' : ' ',
|
13
|
+
index_name,
|
14
|
+
table_name,
|
15
|
+
column_names(index).join(', '),
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_table_sql(table_name, table, table_opts={})
|
20
|
+
'CREATE TABLE %s (%s)' % [
|
21
|
+
table_name,
|
22
|
+
column_definitions(table).join(', '),
|
23
|
+
]
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_temporary_table_sql(table_name, table, table_opts={})
|
27
|
+
'CREATE TEMPORARY TABLE %s (%s)' % [
|
28
|
+
table_name,
|
29
|
+
column_definitions(table).join(', '),
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
def dialect_type
|
34
|
+
Purview::Dialects::SQLite
|
35
|
+
end
|
36
|
+
|
37
|
+
def disable_table_sql(table)
|
38
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND %s IS NOT NULL' % [
|
39
|
+
table_metadata_table.name,
|
40
|
+
table_metadata_table.enabled_at_column.name,
|
41
|
+
null_value,
|
42
|
+
table_metadata_table.table_name_column.name,
|
43
|
+
quoted(table.name),
|
44
|
+
table_metadata_table.enabled_at_column.name,
|
45
|
+
]
|
46
|
+
end
|
47
|
+
|
48
|
+
def drop_index_sql(table_name, index_name, index, 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 enable_table_sql(table, timestamp)
|
61
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND %s IS NULL' % [
|
62
|
+
table_metadata_table.name,
|
63
|
+
table_metadata_table.enabled_at_column.name,
|
64
|
+
quoted(timestamp),
|
65
|
+
table_metadata_table.table_name_column.name,
|
66
|
+
quoted(table.name),
|
67
|
+
table_metadata_table.enabled_at_column.name,
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
def ensure_table_metadata_absent_for_table_sql(table)
|
72
|
+
'DELETE FROM %s WHERE %s = %s' % [
|
73
|
+
table_metadata_table.name,
|
74
|
+
table_metadata_table.table_name_column.name,
|
75
|
+
quoted(table.name),
|
76
|
+
]
|
77
|
+
end
|
78
|
+
|
79
|
+
def ensure_table_metadata_exists_for_table_sql(table)
|
80
|
+
'INSERT INTO %s (%s) SELECT %s WHERE NOT EXISTS (SELECT 1 FROM %s WHERE %s = %s)' % [
|
81
|
+
table_metadata_table.name,
|
82
|
+
table_metadata_table.table_name_column.name,
|
83
|
+
quoted(table.name),
|
84
|
+
table_metadata_table.name,
|
85
|
+
table_metadata_table.table_name_column.name,
|
86
|
+
quoted(table.name),
|
87
|
+
]
|
88
|
+
end
|
89
|
+
|
90
|
+
def ensure_table_metadata_table_exists_sql
|
91
|
+
'CREATE TABLE IF NOT EXISTS %s (%s)' % [
|
92
|
+
table_metadata_table.name,
|
93
|
+
column_definitions(table_metadata_table).join(', '),
|
94
|
+
]
|
95
|
+
end
|
96
|
+
|
97
|
+
def initialize_table_sql(table, timestamp)
|
98
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND %s IS NULL' % [
|
99
|
+
table_metadata_table.name,
|
100
|
+
table_metadata_table.max_timestamp_pulled_column.name,
|
101
|
+
quoted(timestamp),
|
102
|
+
table_metadata_table.table_name_column.name,
|
103
|
+
quoted(table.name),
|
104
|
+
table_metadata_table.max_timestamp_pulled_column.name,
|
105
|
+
]
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_table_metadata_value_sql(table, column)
|
109
|
+
'SELECT %s FROM %s WHERE %s = %s' % [
|
110
|
+
column.name,
|
111
|
+
table_metadata_table.name,
|
112
|
+
table_metadata_table.table_name_column.name,
|
113
|
+
quoted(table.name),
|
114
|
+
]
|
115
|
+
end
|
116
|
+
|
117
|
+
def limit_map
|
118
|
+
super.merge(Purview::Types::String => 255)
|
119
|
+
end
|
120
|
+
|
121
|
+
def lock_table_sql(table, timestamp)
|
122
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND %s IS NULL' % [
|
123
|
+
table_metadata_table.name,
|
124
|
+
table_metadata_table.locked_at_column.name,
|
125
|
+
quoted(timestamp),
|
126
|
+
table_metadata_table.table_name_column.name,
|
127
|
+
quoted(table.name),
|
128
|
+
table_metadata_table.locked_at_column.name,
|
129
|
+
]
|
130
|
+
end
|
131
|
+
|
132
|
+
def next_table_sql(timestamp)
|
133
|
+
'SELECT %s FROM %s WHERE %s IS NOT NULL AND %s IS NOT NULL AND %s IS NULL ORDER BY %s IS NULL DESC, %s LIMIT 1' % [
|
134
|
+
table_metadata_table.table_name_column.name,
|
135
|
+
table_metadata_table.name,
|
136
|
+
table_metadata_table.enabled_at_column.name,
|
137
|
+
table_metadata_table.max_timestamp_pulled_column.name,
|
138
|
+
table_metadata_table.locked_at_column.name,
|
139
|
+
table_metadata_table.last_pulled_at_column.name,
|
140
|
+
table_metadata_table.last_pulled_at_column.name,
|
141
|
+
]
|
142
|
+
end
|
143
|
+
|
144
|
+
def set_table_metadata_value_sql(table, column, value)
|
145
|
+
'UPDATE %s SET %s = %s WHERE %s = %s' % [
|
146
|
+
table_metadata_table.name,
|
147
|
+
column.name,
|
148
|
+
quoted(value),
|
149
|
+
table_metadata_table.table_name_column.name,
|
150
|
+
quoted(table.name),
|
151
|
+
]
|
152
|
+
end
|
153
|
+
|
154
|
+
def type_map
|
155
|
+
super.merge(
|
156
|
+
Purview::Types::Money => 'decimal',
|
157
|
+
Purview::Types::UUID => 'varchar',
|
158
|
+
)
|
159
|
+
end
|
160
|
+
|
161
|
+
def unlock_table_sql(table)
|
162
|
+
'UPDATE %s SET %s = %s WHERE %s = %s AND %s IS NOT NULL' % [
|
163
|
+
table_metadata_table.name,
|
164
|
+
table_metadata_table.locked_at_column.name,
|
165
|
+
null_value,
|
166
|
+
table_metadata_table.table_name_column.name,
|
167
|
+
quoted(table.name),
|
168
|
+
table_metadata_table.locked_at_column.name,
|
169
|
+
]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
data/lib/purview/dialects.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Purview
|
2
|
+
module Dialects
|
3
|
+
class SQLite < Base
|
4
|
+
def false_value
|
5
|
+
'0'
|
6
|
+
end
|
7
|
+
|
8
|
+
def null_value
|
9
|
+
'NULL'
|
10
|
+
end
|
11
|
+
|
12
|
+
def quoted(value)
|
13
|
+
value.nil? ? null_value : value.quoted
|
14
|
+
end
|
15
|
+
|
16
|
+
def sanitized(value)
|
17
|
+
value.nil? ? null_value : value.sanitized
|
18
|
+
end
|
19
|
+
|
20
|
+
def true_value
|
21
|
+
'1'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/purview/loaders.rb
CHANGED
@@ -0,0 +1,85 @@
|
|
1
|
+
module Purview
|
2
|
+
module Loaders
|
3
|
+
class MSSQL < Base
|
4
|
+
private
|
5
|
+
|
6
|
+
def dialect_type
|
7
|
+
Purview::Dialects::MSSQL
|
8
|
+
end
|
9
|
+
|
10
|
+
def id_in_sql(temporary_table_name)
|
11
|
+
'SELECT %s FROM %s' % [
|
12
|
+
table.id_column.name,
|
13
|
+
temporary_table_name,
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
def in_window_sql(window)
|
18
|
+
'%s BETWEEN %s AND %s' % [
|
19
|
+
table.updated_timestamp_column.name,
|
20
|
+
quoted(window.min),
|
21
|
+
quoted(window.max),
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
def not_in_window_sql(window)
|
26
|
+
'%s NOT BETWEEN %s AND %s' % [
|
27
|
+
table.updated_timestamp_column.name,
|
28
|
+
quoted(window.min),
|
29
|
+
quoted(window.max),
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
def table_delete_sql(window, temporary_table_name)
|
34
|
+
'DELETE FROM %s WHERE %s AND %s NOT IN (%s)' % [
|
35
|
+
table.name,
|
36
|
+
in_window_sql(window),
|
37
|
+
table.id_column.name,
|
38
|
+
id_in_sql(temporary_table_name),
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
def table_insert_sql(window, temporary_table_name)
|
43
|
+
'INSERT INTO %s (%s) SELECT %s FROM %s t1 WHERE NOT EXISTS (SELECT 1 FROM %s t2 WHERE t1.%s = t2.%s)' % [
|
44
|
+
table.name,
|
45
|
+
table.column_names.join(', '),
|
46
|
+
table.column_names.join(', '),
|
47
|
+
temporary_table_name,
|
48
|
+
table.name,
|
49
|
+
table.id_column.name,
|
50
|
+
table.id_column.name,
|
51
|
+
]
|
52
|
+
end
|
53
|
+
|
54
|
+
def table_update_sql(window, temporary_table_name)
|
55
|
+
'UPDATE %s t1 JOIN %s t2 ON t1.%s = t2.%s SET %s' % [
|
56
|
+
table.name,
|
57
|
+
temporary_table_name,
|
58
|
+
table.id_column.name,
|
59
|
+
table.id_column.name,
|
60
|
+
table.column_names.map { |column_name| "t1.#{column_name} = t2.#{column_name}" }.join(', '),
|
61
|
+
]
|
62
|
+
end
|
63
|
+
|
64
|
+
def temporary_table_insert_sql(temporary_table_name, rows)
|
65
|
+
'INSERT INTO %s (%s) VALUES %s' % [
|
66
|
+
temporary_table_name,
|
67
|
+
table.column_names.join(', '),
|
68
|
+
rows.map { |row| "(#{row_values(row)})" }.join(', ')
|
69
|
+
]
|
70
|
+
end
|
71
|
+
|
72
|
+
def temporary_table_opts
|
73
|
+
super.merge(:create_indices => false)
|
74
|
+
end
|
75
|
+
|
76
|
+
def temporary_table_verify_sql(temporary_table_name, rows, window)
|
77
|
+
'SELECT COUNT(1) %s FROM %s WHERE %s' % [
|
78
|
+
count_column_name,
|
79
|
+
temporary_table_name,
|
80
|
+
not_in_window_sql(window),
|
81
|
+
]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Purview
|
2
|
+
module Loaders
|
3
|
+
class SQLite < Base
|
4
|
+
private
|
5
|
+
|
6
|
+
def dialect_type
|
7
|
+
Purview::Dialects::SQLite
|
8
|
+
end
|
9
|
+
|
10
|
+
def id_in_sql(temporary_table_name)
|
11
|
+
'SELECT %s FROM %s' % [
|
12
|
+
table.id_column.name,
|
13
|
+
temporary_table_name,
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
def in_window_sql(window)
|
18
|
+
'%s BETWEEN %s AND %s' % [
|
19
|
+
table.updated_timestamp_column.name,
|
20
|
+
quoted(window.min),
|
21
|
+
quoted(window.max),
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
def not_in_window_sql(window)
|
26
|
+
'%s NOT BETWEEN %s AND %s' % [
|
27
|
+
table.updated_timestamp_column.name,
|
28
|
+
quoted(window.min),
|
29
|
+
quoted(window.max),
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
def table_delete_sql(window, temporary_table_name)
|
34
|
+
'DELETE FROM %s WHERE %s AND %s NOT IN (%s)' % [
|
35
|
+
table.name,
|
36
|
+
in_window_sql(window),
|
37
|
+
table.id_column.name,
|
38
|
+
id_in_sql(temporary_table_name),
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
def table_insert_sql(window, temporary_table_name)
|
43
|
+
'INSERT INTO %s (%s) SELECT %s FROM %s t1 WHERE NOT EXISTS (SELECT 1 FROM %s t2 WHERE t1.%s = t2.%s)' % [
|
44
|
+
table.name,
|
45
|
+
table.column_names.join(', '),
|
46
|
+
table.column_names.join(', '),
|
47
|
+
temporary_table_name,
|
48
|
+
table.name,
|
49
|
+
table.id_column.name,
|
50
|
+
table.id_column.name,
|
51
|
+
]
|
52
|
+
end
|
53
|
+
|
54
|
+
def table_update_sql(window, temporary_table_name)
|
55
|
+
'UPDATE %s t1 JOIN %s t2 ON t1.%s = t2.%s SET %s' % [
|
56
|
+
table.name,
|
57
|
+
temporary_table_name,
|
58
|
+
table.id_column.name,
|
59
|
+
table.id_column.name,
|
60
|
+
table.column_names.map { |column_name| "t1.#{column_name} = t2.#{column_name}" }.join(', '),
|
61
|
+
]
|
62
|
+
end
|
63
|
+
|
64
|
+
def temporary_table_insert_sql(temporary_table_name, rows)
|
65
|
+
'INSERT INTO %s (%s) VALUES %s' % [
|
66
|
+
temporary_table_name,
|
67
|
+
table.column_names.join(', '),
|
68
|
+
rows.map { |row| "(#{row_values(row)})" }.join(', ')
|
69
|
+
]
|
70
|
+
end
|
71
|
+
|
72
|
+
def temporary_table_opts
|
73
|
+
super.merge(:create_indices => false)
|
74
|
+
end
|
75
|
+
|
76
|
+
def temporary_table_verify_sql(temporary_table_name, rows, window)
|
77
|
+
'SELECT COUNT(1) %s FROM %s WHERE %s' % [
|
78
|
+
count_column_name,
|
79
|
+
temporary_table_name,
|
80
|
+
not_in_window_sql(window),
|
81
|
+
]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/purview/pullers.rb
CHANGED
@@ -4,14 +4,17 @@ require 'purview/raw_connections/jdbc/base'
|
|
4
4
|
require 'purview/raw_connections/jdbc/jtds'
|
5
5
|
require 'purview/raw_connections/jdbc/mysql'
|
6
6
|
require 'purview/raw_connections/jdbc/postgres'
|
7
|
+
require 'purview/raw_connections/jdbc/sqlite3'
|
7
8
|
|
8
9
|
require 'purview/raw_connections/mysql2'
|
9
10
|
require 'purview/raw_connections/pg'
|
11
|
+
require 'purview/raw_connections/sqlite3'
|
10
12
|
require 'purview/raw_connections/tiny_tds'
|
11
13
|
|
12
14
|
if \
|
13
15
|
!defined?(Purview::RawConnections::MSSQL) &&
|
14
16
|
!defined?(Purview::RawConnections::MySQL) &&
|
15
|
-
!defined?(Purview::RawConnections::PostgreSQL)
|
16
|
-
|
17
|
+
!defined?(Purview::RawConnections::PostgreSQL) &&
|
18
|
+
!defined?(Purview::RawConnections::SQLite)
|
19
|
+
raise 'Could not initialize raw-connections; please install and require one or more of the following gems: `jdbc-jtds`, `jdbc-mysql`, `jdbc-postgres`, `jdbc-sqlite3`, `mysql2`, `pg`, `sqlite3` and/or `tiny_tds`'
|
17
20
|
end
|