couchdb_to_sql 1.0.0 → 2.0.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/.rubocop_todo.yml +19 -8
- data/VERSION +1 -1
- data/lib/couchdb_to_sql/changes.rb +12 -6
- data/lib/couchdb_to_sql/document_handler.rb +2 -2
- data/lib/couchdb_to_sql/table_deleted_marker.rb +12 -27
- data/test/unit/changes_test.rb +32 -1
- data/test/unit/table_deleted_marker_test.rb +67 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51e5df8173322c4586364b13ebd30b450677af07
|
4
|
+
data.tar.gz: fbd8a500bea9b195f9287c0a18b12aab84de50dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 90a3d02890b0ccb1ae7714ba87633875ae31e7af56f0e456640a72b1f0f0d1c0a079888c34df997ca5a0787e705f3055fcde442449de1d7ac42b0334284c29fe
|
7
|
+
data.tar.gz: 97fda03da45da9ccdcbdc56b7182426a38d0ddb6db4b1773115c5f54aa5a93a17b8730c9d47ce6b98ea896da9e7b82ffe850d5e9a70ee5e8ad5c4d9c29f0baa0
|
data/.rubocop_todo.yml
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on
|
3
|
+
# on 2018-03-26 16:28:00 +0300 using RuboCop version 0.54.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
-
# Offense count:
|
9
|
+
# Offense count: 7
|
10
10
|
Metrics/AbcSize:
|
11
11
|
Max: 36
|
12
12
|
|
13
13
|
# Offense count: 1
|
14
14
|
# Configuration parameters: CountComments, ExcludedMethods.
|
15
15
|
Metrics/BlockLength:
|
16
|
-
Max:
|
16
|
+
Max: 28
|
17
17
|
|
18
18
|
# Offense count: 1
|
19
19
|
# Configuration parameters: CountBlocks.
|
@@ -23,17 +23,28 @@ Metrics/BlockNesting:
|
|
23
23
|
# Offense count: 2
|
24
24
|
# Configuration parameters: CountComments.
|
25
25
|
Metrics/ClassLength:
|
26
|
-
Max:
|
26
|
+
Max: 209
|
27
27
|
|
28
28
|
# Offense count: 2
|
29
29
|
Metrics/CyclomaticComplexity:
|
30
|
-
Max:
|
30
|
+
Max: 9
|
31
31
|
|
32
|
-
# Offense count:
|
32
|
+
# Offense count: 13
|
33
33
|
# Configuration parameters: CountComments.
|
34
34
|
Metrics/MethodLength:
|
35
|
-
Max:
|
35
|
+
Max: 38
|
36
36
|
|
37
37
|
# Offense count: 1
|
38
38
|
Metrics/PerceivedComplexity:
|
39
|
-
Max:
|
39
|
+
Max: 12
|
40
|
+
|
41
|
+
# Offense count: 2
|
42
|
+
Style/DateTime:
|
43
|
+
Exclude:
|
44
|
+
- 'lib/couchdb_to_sql/changes.rb'
|
45
|
+
|
46
|
+
# Offense count: 3
|
47
|
+
Style/EvalWithLocation:
|
48
|
+
Exclude:
|
49
|
+
- 'test/unit/document_handler_test.rb'
|
50
|
+
- 'test/unit/table_builder_test.rb'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0
|
@@ -137,9 +137,7 @@ module CouchdbToSql
|
|
137
137
|
uri = URI.parse(url)
|
138
138
|
|
139
139
|
# Authenticate?
|
140
|
-
if uri.user.present? && uri.password.present?
|
141
|
-
@http.set_auth(source.root, uri.user, uri.password)
|
142
|
-
end
|
140
|
+
@http.set_auth(source.root, uri.user, uri.password) if uri.user.present? && uri.password.present?
|
143
141
|
|
144
142
|
# Make sure the request has the latest sequence
|
145
143
|
query = {
|
@@ -186,7 +184,15 @@ module CouchdbToSql
|
|
186
184
|
|
187
185
|
if row['deleted']
|
188
186
|
log_info "received DELETE seq. #{seq} id: #{id}"
|
189
|
-
|
187
|
+
document_handlers = find_document_handlers(doc)
|
188
|
+
if document_handlers.empty?
|
189
|
+
log_info "Found deletion without type-identifying field, (id: '#{id}'), removing " \
|
190
|
+
'data from SQL/Postgres.'
|
191
|
+
log_info 'Trying all handlers...'
|
192
|
+
handlers.each { |handler| handler.delete(doc) }
|
193
|
+
else
|
194
|
+
document_handlers.each { |handler| handler.mark_as_deleted(doc) }
|
195
|
+
end
|
190
196
|
else
|
191
197
|
log_debug "received CHANGE seq. #{seq} id: #{id}"
|
192
198
|
|
@@ -206,8 +212,8 @@ module CouchdbToSql
|
|
206
212
|
end
|
207
213
|
end
|
208
214
|
|
209
|
-
update_sequence_table(seq)
|
210
|
-
end
|
215
|
+
update_sequence_table(seq) # transaction
|
216
|
+
end
|
211
217
|
elsif row['last_seq']
|
212
218
|
# Sometimes CouchDB will send an update to keep the connection alive
|
213
219
|
log_info "received last seq: #{row['last_seq']}"
|
@@ -29,9 +29,9 @@ module CouchdbToSql
|
|
29
29
|
# Handle a table definition.
|
30
30
|
def table(name, opts = {}, &block)
|
31
31
|
if @mode == :delete
|
32
|
-
TableDestroyer.new(self, name, opts).execute
|
32
|
+
TableDestroyer.new(self, name, opts, &block).execute
|
33
33
|
elsif @mode == :mark_as_deleted
|
34
|
-
TableDeletedMarker.new(self, name, opts).execute
|
34
|
+
TableDeletedMarker.new(self, name, opts, &block).execute
|
35
35
|
elsif @mode == :insert
|
36
36
|
TableBuilder.new(self, name, opts, &block).execute
|
37
37
|
end
|
@@ -9,35 +9,20 @@ module CouchdbToSql
|
|
9
9
|
class TableDeletedMarker < TableBuilder
|
10
10
|
def execute
|
11
11
|
dataset = handler.database[table_name]
|
12
|
+
handler.changes.log_info "Deletion with additional info present (#{primary_key} '#{handler.id}'), assuming tombstone. " \
|
13
|
+
'Updating data in SQL/Postgres database with data from CouchDB document.'
|
14
|
+
fields = attributes.merge(
|
15
|
+
_deleted: true,
|
16
|
+
_deleted_timestamp: Sequel::CURRENT_TIMESTAMP,
|
17
|
+
rev: handler.rev
|
18
|
+
)
|
12
19
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
_deleted: true,
|
18
|
-
_deleted_timestamp: Sequel::CURRENT_TIMESTAMP,
|
19
|
-
rev: handler.rev
|
20
|
+
dataset
|
21
|
+
.insert_conflict(
|
22
|
+
target: primary_key,
|
23
|
+
update: fields
|
20
24
|
)
|
21
|
-
|
22
|
-
dataset
|
23
|
-
.insert_conflict(
|
24
|
-
target: primary_key,
|
25
|
-
update: fields
|
26
|
-
)
|
27
|
-
.insert(fields)
|
28
|
-
else
|
29
|
-
handler.changes.log_info "Found deletion without 'id' field (#{primary_key} '#{handler.id}'), assuming plaque. Leaving " \
|
30
|
-
'data as-is in SQL/Postgres, only setting _deleted* fields.'
|
31
|
-
records_modified = dataset
|
32
|
-
.where(key_filter)
|
33
|
-
.update(
|
34
|
-
_deleted: true,
|
35
|
-
_deleted_timestamp: Sequel::CURRENT_TIMESTAMP,
|
36
|
-
rev: handler.rev
|
37
|
-
)
|
38
|
-
|
39
|
-
handler.changes.log_info "#{records_modified} record(s) were marked as deleted"
|
40
|
-
end
|
25
|
+
.insert(fields)
|
41
26
|
end
|
42
27
|
|
43
28
|
def key_filter
|
data/test/unit/changes_test.rb
CHANGED
@@ -74,6 +74,37 @@ class ChangesTest < Test::Unit::TestCase
|
|
74
74
|
assert_equal @changes.database[CouchdbToSql::COUCHDB_TO_SQL_SEQUENCES_TABLE].first.fetch(:highest_sequence), '3'
|
75
75
|
end
|
76
76
|
|
77
|
+
def test_mark_deleted_rows
|
78
|
+
doc = {
|
79
|
+
'order_number' => '12345',
|
80
|
+
'customer_number' => '54321',
|
81
|
+
'type' => 'Foo'
|
82
|
+
}
|
83
|
+
row = {
|
84
|
+
'seq' => 9,
|
85
|
+
'id' => '1234',
|
86
|
+
'deleted' => true,
|
87
|
+
'doc' => doc
|
88
|
+
}
|
89
|
+
|
90
|
+
handler = @changes.handlers[0]
|
91
|
+
handler.expects(:mark_as_deleted).with(doc)
|
92
|
+
|
93
|
+
handler = @changes.handlers[1]
|
94
|
+
handler.expects(:delete).never
|
95
|
+
handler.expects(:insert).never
|
96
|
+
handler.expects(:mark_as_deleted).with(doc).never
|
97
|
+
|
98
|
+
handler = @changes.handlers[2]
|
99
|
+
handler.expects(:delete).never
|
100
|
+
handler.expects(:insert).never
|
101
|
+
handler.expects(:mark_as_deleted).with(doc).never
|
102
|
+
|
103
|
+
@changes.send(:process_row, row)
|
104
|
+
|
105
|
+
assert_equal @changes.database[CouchdbToSql::COUCHDB_TO_SQL_SEQUENCES_TABLE].first.fetch(:highest_sequence), '9'
|
106
|
+
end
|
107
|
+
|
77
108
|
def test_deleting_rows
|
78
109
|
doc = {
|
79
110
|
'order_number' => '12345',
|
@@ -87,7 +118,7 @@ class ChangesTest < Test::Unit::TestCase
|
|
87
118
|
}
|
88
119
|
|
89
120
|
@changes.handlers.each do |handler|
|
90
|
-
handler.expects(:
|
121
|
+
handler.expects(:delete).with(doc)
|
91
122
|
end
|
92
123
|
|
93
124
|
@changes.send(:process_row, row)
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class TableDeletedMarkerTest < Test::Unit::TestCase
|
6
|
+
def described_class
|
7
|
+
CouchdbToSql::TableDeletedMarker
|
8
|
+
end
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@database = create_database
|
12
|
+
@changes = mock
|
13
|
+
@changes.stubs(:database).returns(@database)
|
14
|
+
@changes.stubs(:schema).returns(CouchdbToSql::Schema.new(@database, :items))
|
15
|
+
@changes.stubs(:log_info)
|
16
|
+
@handler = CouchdbToSql::DocumentHandler.new(@changes)
|
17
|
+
@handler.document = { '_id' => '12345' }
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_init
|
21
|
+
@row = described_class.new(@handler, 'items')
|
22
|
+
assert_equal @row.primary_key, :item_id
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_init_override_primary_key
|
26
|
+
@row = described_class.new(@handler, 'items', primary_key: 'foo_item_id')
|
27
|
+
assert_equal @row.primary_key, :foo_item_id
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_handler
|
31
|
+
@row = described_class.new(@handler, :items)
|
32
|
+
assert_equal @row.handler, @handler
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_key_filter
|
36
|
+
@row = described_class.new(@handler, :items)
|
37
|
+
assert_equal @row.key_filter, item_id: '12345'
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_execution_deletes_rows
|
41
|
+
@database[:items].insert(name: 'Test Item 1', item_id: '12345')
|
42
|
+
assert_equal @database[:items].count, 1, 'Did not create sample row correctly!'
|
43
|
+
@row = described_class.new(@handler, :items)
|
44
|
+
# @row.execute # TODO: Sqlite and PostGres have different upsert syntax
|
45
|
+
assert_equal 1, @database[:items].count
|
46
|
+
# assert_true @database[:items].first._deleted
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
51
|
+
def create_database
|
52
|
+
database = Sequel.sqlite
|
53
|
+
database.create_table :items do
|
54
|
+
String :item_id
|
55
|
+
String :name
|
56
|
+
Time :created_at
|
57
|
+
index :item_id, unique: true
|
58
|
+
end
|
59
|
+
database.create_table :groups do
|
60
|
+
String :group_id
|
61
|
+
String :name
|
62
|
+
Time :created_at
|
63
|
+
index :group_id, unique: true
|
64
|
+
end
|
65
|
+
database
|
66
|
+
end
|
67
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: couchdb_to_sql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Lown
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: exe
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2018-04-20 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activesupport
|
@@ -197,6 +197,7 @@ files:
|
|
197
197
|
- test/unit/document_handler_test.rb
|
198
198
|
- test/unit/schema_test.rb
|
199
199
|
- test/unit/table_builder_test.rb
|
200
|
+
- test/unit/table_deleted_marker_test.rb
|
200
201
|
- test/unit/table_destroyer_test.rb
|
201
202
|
homepage: https://github.com/ecraft/couchdb_to_sql
|
202
203
|
licenses:
|
@@ -218,7 +219,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
218
219
|
version: '0'
|
219
220
|
requirements: []
|
220
221
|
rubyforge_project:
|
221
|
-
rubygems_version: 2.6.
|
222
|
+
rubygems_version: 2.6.12
|
222
223
|
signing_key:
|
223
224
|
specification_version: 4
|
224
225
|
summary: Listen to a CouchDB changes feed and create rows in a relational database
|
@@ -230,4 +231,5 @@ test_files:
|
|
230
231
|
- test/unit/document_handler_test.rb
|
231
232
|
- test/unit/schema_test.rb
|
232
233
|
- test/unit/table_builder_test.rb
|
234
|
+
- test/unit/table_deleted_marker_test.rb
|
233
235
|
- test/unit/table_destroyer_test.rb
|