db_fuel 1.2.1.pre.alpha.2 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -0
- data/README.md +16 -12
- data/db_fuel.gemspec +2 -2
- data/lib/db_fuel/library/active_record/base.rb +16 -3
- data/lib/db_fuel/library/active_record/find_or_insert.rb +12 -7
- data/lib/db_fuel/library/active_record/insert.rb +11 -8
- data/lib/db_fuel/library/active_record/update.rb +11 -13
- data/lib/db_fuel/library/active_record/update_all.rb +12 -8
- data/lib/db_fuel/library/active_record/upsert.rb +30 -26
- data/lib/db_fuel/modeling/attribute_renderer_set.rb +8 -8
- data/lib/db_fuel/version.rb +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96e96867b0df819c4a00e446f47fe586d48a12da5798e0743b8895940ff126af
|
4
|
+
data.tar.gz: fed359df2f9d2512740e39ad65fd5e6fabed287fb1403bed525fe4b0af5bdf0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72382d90f1368e9ac9d4cb35a64b60235ec5822568be79ce5a92fd956e41eed9a139d6cf9681585af24932c4e5ff7759e8cb4b36eb2e1cefa0f20e120baa478c
|
7
|
+
data.tar.gz: d127c76c1d94e35e2c8b46aff67c6e80735b9381348ae3fb984e983b67701889b0448d5ae00e53218ec52453d7a7e1d7f3df39feaefaaa139652fe35e36fbaff
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
|
2
|
+
# 2.2.0 (May 23rd, 2021)
|
3
|
+
|
4
|
+
Updates:
|
5
|
+
|
6
|
+
* Updating dependencies for dbee to include newest versions.
|
7
|
+
# 2.1.0 (May 19th, 2021)
|
8
|
+
|
9
|
+
Additions:
|
10
|
+
|
11
|
+
* Added keys_register to all db_fuel/active_record jobs.
|
12
|
+
|
13
|
+
# 2.0.1 (March 18th, 2021)
|
14
|
+
|
15
|
+
Changes:
|
16
|
+
|
17
|
+
* Updated attribute_renderer_set to avoid an evaluation time issue with acts_as_hashable.
|
18
|
+
|
19
|
+
# 2.0.0 (March 16th, 2021)
|
20
|
+
|
21
|
+
New Jobs:
|
22
|
+
* db_fuel/active_record/upsert
|
23
|
+
* db_fuel/active_record/update_all
|
24
|
+
|
25
|
+
Changes:
|
26
|
+
* db_fuel/active_record/update now only updates a single record. Use db_fuel/active_record/update_all to update multiple records at a time.
|
27
|
+
|
1
28
|
# 1.1.0 (Decmeber 1st, 2020)
|
2
29
|
|
3
30
|
New Jobs:
|
data/README.md
CHANGED
@@ -24,11 +24,11 @@ Refer to the [Burner](https://github.com/bluemarblepayroll/burner) library for m
|
|
24
24
|
|
25
25
|
### ActiveRecord Jobs
|
26
26
|
|
27
|
-
* **db_fuel/active_record/find_or_insert** [name, table_name, attributes, debug,
|
28
|
-
* **db_fuel/active_record/insert** [name, table_name, attributes, debug,
|
29
|
-
* **db_fuel/active_record/update_all** [name, table_name, attributes, debug, register, separator, timestamps, unique_attributes]: This job can take the objects in a register and updates them within a database table. Attributes defines which object properties to convert to SQL SET clauses while unique_attributes translate to WHERE clauses. One or more records may be updated at a time. Refer to the class and constructor specification for more detail.
|
30
|
-
* **db_fuel/active_record/update** [name, table_name, attributes, debug, register,
|
31
|
-
* **db_fuel/active_record/upsert** [name, table_name, attributes, debug,
|
27
|
+
* **db_fuel/active_record/find_or_insert** [name, table_name, attributes, debug, primary_keyed_column, keys_register, register, separator, timestamps, unique_attributes]: An extension of the `db_fuel/active_record/insert` job that adds an existence check before SQL insertion. The `unique_attributes` will be converted to WHERE clauses for performing the existence check.
|
28
|
+
* **db_fuel/active_record/insert** [name, table_name, attributes, debug, primary_keyed_column, keys_register, register, separator, timestamps]: This job can take the objects in a register and insert them into a database table. If primary_keyed_column is specified then its key will be set to the primary key. Note that composite primary keys are not supported. Attributes defines which object properties to convert to SQL. Refer to the class and constructor specification for more detail.
|
29
|
+
* **db_fuel/active_record/update_all** [name, table_name, attributes, debug, keys_register, register, separator, timestamps, unique_attributes]: This job can take the objects in a register and updates them within a database table. Attributes defines which object properties to convert to SQL SET clauses while unique_attributes translate to WHERE clauses. One or more records may be updated at a time. Refer to the class and constructor specification for more detail.
|
30
|
+
* **db_fuel/active_record/update** [name, table_name, attributes, debug, keys_register, register, primary_keyed_column, separator, timestamps, unique_attributes]: This job can take the unique objects in a register and updates them within a database table. Attributes defines which object properties to convert to SQL SET clauses while unique_attributes translate to WHERE clauses to find the records to update. The primary_keyed_column is used to update the unique record. Only one record will be updated per statement. Note that composite primary keys are not supported. Refer to the class and constructor specification for more detail.
|
31
|
+
* **db_fuel/active_record/upsert** [name, table_name, attributes, debug, primary_keyed_column, keys_register, register, separator, timestamps, unique_attributes]: This job can take the objects in a register and either inserts or updates them within a database table. Attributes defines which object properties to convert to SQL SET clauses while each key in unique_attributes become a WHERE clause in order to check for the existence of a specific record. The updated record will use the primary_keyed_column specified to perform the UPDATE operation. Note that composite primary keys are not supported. Refer to the class and constructor specification for more detail.
|
32
32
|
|
33
33
|
### Dbee Jobs
|
34
34
|
|
@@ -187,7 +187,7 @@ pipeline = {
|
|
187
187
|
{ key: :last_name }
|
188
188
|
],
|
189
189
|
table_name: 'patients',
|
190
|
-
|
190
|
+
primary_keyed_column: {
|
191
191
|
key: :id
|
192
192
|
}
|
193
193
|
}
|
@@ -203,13 +203,13 @@ There should now be two new patients, AB0 and AB1, present in the table `patient
|
|
203
203
|
|
204
204
|
Notes:
|
205
205
|
|
206
|
-
* Since we specified the `
|
206
|
+
* Since we specified the `primary_keyed_column`, the records' `id` attributes should be set to their respective primary key values.
|
207
207
|
* Composite primary keys are not currently supported.
|
208
208
|
* Set `debug: true` to print out each INSERT statement in the output (not for production use.)
|
209
209
|
|
210
210
|
#### Inserting Only New Records
|
211
211
|
|
212
|
-
Another job `db_fuel/active_record/find_or_insert` allows for an existence check to performed each insertion. If a record is found then it will not insert the record. If `
|
212
|
+
Another job `db_fuel/active_record/find_or_insert` allows for an existence check to performed each insertion. If a record is found then it will not insert the record. If `primary_keyed_column` is set then the existence check will also still set the primary key on the payload's respective object. Note that composite primary keys are not currently supported. We can build on the above insert example for only inserting new patients if their chart_number is unique:
|
213
213
|
|
214
214
|
````ruby
|
215
215
|
pipeline = {
|
@@ -233,7 +233,7 @@ pipeline = {
|
|
233
233
|
{ key: :last_name }
|
234
234
|
],
|
235
235
|
table_name: 'patients',
|
236
|
-
|
236
|
+
primary_keyed_column: {
|
237
237
|
key: :id
|
238
238
|
},
|
239
239
|
unique_attributes: [
|
@@ -274,7 +274,7 @@ pipeline = {
|
|
274
274
|
{ key: :last_name }
|
275
275
|
],
|
276
276
|
table_name: 'patients',
|
277
|
-
|
277
|
+
primary_keyed_column: {
|
278
278
|
key: :id
|
279
279
|
},
|
280
280
|
unique_attributes: [
|
@@ -331,7 +331,7 @@ Each database record should have been updated with their new respective middle n
|
|
331
331
|
|
332
332
|
#### Upserting Records
|
333
333
|
|
334
|
-
Let's say we don't know if these chart_number values already exist or not.
|
334
|
+
Let's say we don't know if these chart_number values already exist or not.
|
335
335
|
So we want db_fuel to either insert a record if the chart_number doesn't exist or update the record if the chart_number already exists.
|
336
336
|
|
337
337
|
````ruby
|
@@ -356,7 +356,7 @@ pipeline = {
|
|
356
356
|
{ key: :last_name }
|
357
357
|
],
|
358
358
|
table_name: 'patients',
|
359
|
-
|
359
|
+
primary_keyed_column: {
|
360
360
|
key: :id
|
361
361
|
},
|
362
362
|
unique_attributes: [
|
@@ -378,6 +378,10 @@ Notes:
|
|
378
378
|
|
379
379
|
* The `unique_attributes` translate to WHERE clauses.
|
380
380
|
* Set `debug: true` to print out each UPDATE statement in the output (not for production use.)
|
381
|
+
|
382
|
+
#### Limiting The Columns Being Inserted/Updated
|
383
|
+
|
384
|
+
All the db_fuel/active_record/* jobs now feature an optional `keys_register` option. If this is set, the register will be read and used as a key filter for which fields to set. For example, if you configure a db_fuel/active_record/insert job to update A, B, C, and D, but your keys_register contains [A,B] then only A and B will be inserted/set. This is helpful in scenarios where you may want to outline how to update _all_ possible fields but your input set only contains a subset of those fields and you do not wish to set the others to null.
|
381
385
|
## Contributing
|
382
386
|
|
383
387
|
### Development Environment Configuration
|
data/db_fuel.gemspec
CHANGED
@@ -43,8 +43,8 @@ Gem::Specification.new do |s|
|
|
43
43
|
s.add_dependency('activerecord', activerecord_version)
|
44
44
|
s.add_dependency('acts_as_hashable', '~>1.2')
|
45
45
|
s.add_dependency('burner', '~>1.7')
|
46
|
-
s.add_dependency('dbee', '~>
|
47
|
-
s.add_dependency('dbee-active_record', '~>2.
|
46
|
+
s.add_dependency('dbee', '~>3.0')
|
47
|
+
s.add_dependency('dbee-active_record', '~>2.2')
|
48
48
|
s.add_dependency('objectable', '~>1.0')
|
49
49
|
|
50
50
|
s.add_development_dependency('guard-rspec', '~>4.7')
|
@@ -22,6 +22,7 @@ module DbFuel
|
|
22
22
|
attr_reader :attribute_renderers,
|
23
23
|
:db_provider,
|
24
24
|
:debug,
|
25
|
+
:keys_register,
|
25
26
|
:resolver,
|
26
27
|
:attribute_renderers_set
|
27
28
|
|
@@ -30,14 +31,16 @@ module DbFuel
|
|
30
31
|
name: '',
|
31
32
|
attributes: [],
|
32
33
|
debug: false,
|
34
|
+
keys_register: nil,
|
33
35
|
register: Burner::DEFAULT_REGISTER,
|
34
36
|
separator: ''
|
35
37
|
)
|
36
38
|
super(name: name, register: register)
|
37
39
|
|
38
|
-
@
|
39
|
-
@
|
40
|
-
|
40
|
+
@keys_register = keys_register.to_s
|
41
|
+
@resolver = Objectable.resolver(separator: separator)
|
42
|
+
@attribute_renderers_set = Modeling::AttributeRendererSet.new(resolver: resolver,
|
43
|
+
attributes: attributes)
|
41
44
|
@db_provider = DbProvider.new(table_name)
|
42
45
|
@debug = debug || false
|
43
46
|
end
|
@@ -49,6 +52,16 @@ module DbFuel
|
|
49
52
|
|
50
53
|
output.detail(message)
|
51
54
|
end
|
55
|
+
|
56
|
+
def resolve_key_set(output, payload)
|
57
|
+
return Set.new if keys_register.empty?
|
58
|
+
|
59
|
+
keys = array(payload[keys_register]).map(&:to_s).to_set
|
60
|
+
|
61
|
+
output.detail("Limiting to only keys: #{keys.to_a.join(', ')}") if keys.any?
|
62
|
+
|
63
|
+
keys
|
64
|
+
end
|
52
65
|
end
|
53
66
|
end
|
54
67
|
end
|
@@ -14,8 +14,9 @@ module DbFuel
|
|
14
14
|
module ActiveRecord
|
15
15
|
# This job is a slight enhancement to the insert job, in that it will only insert new
|
16
16
|
# records. It will use the unique_keys to first run a query to see if it exists.
|
17
|
-
# Each unique_key becomes a WHERE clause. If
|
18
|
-
# found then the first record's id will be set to
|
17
|
+
# Each unique_key becomes a WHERE clause. If primary_keyed_column is specified
|
18
|
+
# and a record is found then the first record's id will be set to
|
19
|
+
# the primary_keyed_column.
|
19
20
|
#
|
20
21
|
# Expected Payload[register] input: array of objects
|
21
22
|
# Payload[register] output: array of objects.
|
@@ -36,8 +37,9 @@ module DbFuel
|
|
36
37
|
# returned objects will be printed in the output. Only use this option while
|
37
38
|
# debugging issues as it will fill up the output with (potentially too much) data.
|
38
39
|
#
|
39
|
-
#
|
40
|
-
#
|
40
|
+
# primary_keyed_column: If primary_keyed_column is present then it will be used to set
|
41
|
+
# the object's property to the returned primary key
|
42
|
+
# from the INSERT statement.
|
41
43
|
#
|
42
44
|
# separator: Just like other jobs with a 'separator' option, if the objects require
|
43
45
|
# key-path notation or nested object support, you can set the separator
|
@@ -55,7 +57,8 @@ module DbFuel
|
|
55
57
|
name: '',
|
56
58
|
attributes: [],
|
57
59
|
debug: false,
|
58
|
-
|
60
|
+
keys_register: nil,
|
61
|
+
primary_keyed_column: nil,
|
59
62
|
register: Burner::DEFAULT_REGISTER,
|
60
63
|
separator: '',
|
61
64
|
timestamps: true,
|
@@ -64,10 +67,11 @@ module DbFuel
|
|
64
67
|
|
65
68
|
super(
|
66
69
|
name: name,
|
70
|
+
keys_register: keys_register,
|
67
71
|
table_name: table_name,
|
68
72
|
attributes: attributes,
|
69
73
|
debug: debug,
|
70
|
-
|
74
|
+
primary_keyed_column: primary_keyed_column,
|
71
75
|
register: register,
|
72
76
|
separator: separator,
|
73
77
|
timestamps: timestamps,
|
@@ -80,6 +84,7 @@ module DbFuel
|
|
80
84
|
total_existed = 0
|
81
85
|
|
82
86
|
payload[register] = array(payload[register])
|
87
|
+
keys = resolve_key_set(output, payload)
|
83
88
|
|
84
89
|
payload[register].each do |row|
|
85
90
|
exists = find_record(output, row, payload.time)
|
@@ -89,7 +94,7 @@ module DbFuel
|
|
89
94
|
next
|
90
95
|
end
|
91
96
|
|
92
|
-
insert_record(output, row, payload.time)
|
97
|
+
insert_record(output, row, payload.time, keys)
|
93
98
|
|
94
99
|
total_inserted += 1
|
95
100
|
end
|
@@ -17,8 +17,6 @@ module DbFuel
|
|
17
17
|
# Expected Payload[register] input: array of objects
|
18
18
|
# Payload[register] output: array of objects.
|
19
19
|
class Insert < Upsert
|
20
|
-
# attr_reader :primary_key
|
21
|
-
|
22
20
|
# Arguments:
|
23
21
|
# name: name of the job within the Burner::Pipeline.
|
24
22
|
#
|
@@ -33,8 +31,9 @@ module DbFuel
|
|
33
31
|
# returned objects will be printed in the output. Only use this option while
|
34
32
|
# debugging issues as it will fill up the output with (potentially too much) data.
|
35
33
|
#
|
36
|
-
#
|
37
|
-
#
|
34
|
+
# primary_keyed_column: If primary_keyed_column is present then it will be used to
|
35
|
+
# set the object's property to the returned primary key
|
36
|
+
# from the INSERT statement.
|
38
37
|
#
|
39
38
|
# separator: Just like other jobs with a 'separator' option, if the objects require
|
40
39
|
# key-path notation or nested object support, you can set the separator
|
@@ -46,23 +45,24 @@ module DbFuel
|
|
46
45
|
# to the current UTC timestamp.
|
47
46
|
def initialize(
|
48
47
|
table_name:,
|
48
|
+
keys_register: nil,
|
49
49
|
name: '',
|
50
50
|
attributes: [],
|
51
51
|
debug: false,
|
52
|
-
|
52
|
+
primary_keyed_column: nil,
|
53
53
|
register: Burner::DEFAULT_REGISTER,
|
54
54
|
separator: '',
|
55
55
|
timestamps: true
|
56
56
|
)
|
57
|
-
|
58
57
|
attributes = Burner::Modeling::Attribute.array(attributes)
|
59
58
|
|
60
59
|
super(
|
61
60
|
name: name,
|
61
|
+
keys_register: keys_register,
|
62
62
|
table_name: table_name,
|
63
63
|
attributes: attributes,
|
64
64
|
debug: debug,
|
65
|
-
|
65
|
+
primary_keyed_column: primary_keyed_column,
|
66
66
|
register: register,
|
67
67
|
separator: separator,
|
68
68
|
timestamps: timestamps
|
@@ -71,8 +71,11 @@ module DbFuel
|
|
71
71
|
|
72
72
|
def perform(output, payload)
|
73
73
|
payload[register] = array(payload[register])
|
74
|
+
keys = resolve_key_set(output, payload)
|
75
|
+
|
76
|
+
output.detail("Inserting #{payload[register].count} record(s)")
|
74
77
|
|
75
|
-
payload[register].each { |row| insert_record(output, row, payload.time) }
|
78
|
+
payload[register].each { |row| insert_record(output, row, payload.time, keys) }
|
76
79
|
end
|
77
80
|
end
|
78
81
|
end
|
@@ -15,7 +15,7 @@ module DbFuel
|
|
15
15
|
# This job can take the unique objects in a register and updates them within database table.
|
16
16
|
# The attributes translate to SQL SET clauses and the unique_keys translate to
|
17
17
|
# WHERE clauses to find the records to update.
|
18
|
-
# The
|
18
|
+
# The primary_keyed_column is used to update the unique record.
|
19
19
|
# Only one record will be updated per statement.
|
20
20
|
#
|
21
21
|
# Expected Payload[register] input: array of objects
|
@@ -35,7 +35,7 @@ module DbFuel
|
|
35
35
|
# returned objects will be printed in the output. Only use this option while
|
36
36
|
# debugging issues as it will fill up the output with (potentially too much) data.
|
37
37
|
#
|
38
|
-
#
|
38
|
+
# primary_keyed_column [required]: Primary key column for the corresponding table.
|
39
39
|
# Used as the WHERE clause for the UPDATE statement.
|
40
40
|
# Only one record will be updated at a time
|
41
41
|
# using the primary key specified.
|
@@ -56,7 +56,8 @@ module DbFuel
|
|
56
56
|
name: '',
|
57
57
|
attributes: [],
|
58
58
|
debug: false,
|
59
|
-
|
59
|
+
primary_keyed_column: nil,
|
60
|
+
keys_register: nil,
|
60
61
|
register: Burner::DEFAULT_REGISTER,
|
61
62
|
separator: '',
|
62
63
|
timestamps: true,
|
@@ -70,7 +71,8 @@ module DbFuel
|
|
70
71
|
table_name: table_name,
|
71
72
|
attributes: attributes,
|
72
73
|
debug: debug,
|
73
|
-
|
74
|
+
keys_register: keys_register,
|
75
|
+
primary_keyed_column: primary_keyed_column,
|
74
76
|
register: register,
|
75
77
|
separator: separator,
|
76
78
|
timestamps: timestamps,
|
@@ -81,20 +83,16 @@ module DbFuel
|
|
81
83
|
end
|
82
84
|
|
83
85
|
def perform(output, payload)
|
84
|
-
total_rows_affected = 0
|
85
|
-
|
86
86
|
payload[register] = array(payload[register])
|
87
|
+
keys = resolve_key_set(output, payload)
|
87
88
|
|
88
|
-
payload[register].
|
89
|
-
|
90
|
-
|
91
|
-
first_record = update_record(output, row, payload.time)
|
92
|
-
|
93
|
-
rows_affected = 1 if first_record
|
89
|
+
total_rows_affected = payload[register].inject(0) do |memo, row|
|
90
|
+
first_record = update_record(output, row, payload.time, keys)
|
91
|
+
rows_affected = first_record ? 1 : 0
|
94
92
|
|
95
93
|
debug_detail(output, "Individual Rows Affected: #{rows_affected}")
|
96
94
|
|
97
|
-
|
95
|
+
memo + rows_affected
|
98
96
|
end
|
99
97
|
|
100
98
|
output.detail("Total Rows Affected: #{total_rows_affected}")
|
@@ -50,6 +50,7 @@ module DbFuel
|
|
50
50
|
attributes: [],
|
51
51
|
debug: false,
|
52
52
|
register: Burner::DEFAULT_REGISTER,
|
53
|
+
keys_register: nil,
|
53
54
|
separator: '',
|
54
55
|
timestamps: true,
|
55
56
|
unique_attributes: []
|
@@ -62,7 +63,8 @@ module DbFuel
|
|
62
63
|
table_name: table_name,
|
63
64
|
attributes: attributes,
|
64
65
|
debug: debug,
|
65
|
-
|
66
|
+
primary_keyed_column: nil,
|
67
|
+
keys_register: keys_register,
|
66
68
|
register: register,
|
67
69
|
separator: separator,
|
68
70
|
timestamps: timestamps,
|
@@ -73,19 +75,21 @@ module DbFuel
|
|
73
75
|
end
|
74
76
|
|
75
77
|
def perform(output, payload)
|
76
|
-
total_rows_affected = 0
|
77
|
-
|
78
78
|
payload[register] = array(payload[register])
|
79
|
+
keys = resolve_key_set(output, payload)
|
79
80
|
|
80
|
-
payload[register].
|
81
|
-
where_object = attribute_renderers_set
|
82
|
-
|
81
|
+
total_rows_affected = payload[register].inject(0) do |memo, row|
|
82
|
+
where_object = attribute_renderers_set.transform(
|
83
|
+
unique_attribute_renderers,
|
84
|
+
row,
|
85
|
+
payload.time
|
86
|
+
)
|
83
87
|
|
84
|
-
rows_affected = update(output, row, payload.time, where_object)
|
88
|
+
rows_affected = update(output, row, payload.time, where_object, keys)
|
85
89
|
|
86
90
|
debug_detail(output, "Individual Rows Affected: #{rows_affected}")
|
87
91
|
|
88
|
-
|
92
|
+
memo + rows_affected
|
89
93
|
end
|
90
94
|
|
91
95
|
output.detail("Total Rows Affected: #{total_rows_affected}")
|
@@ -16,12 +16,12 @@ module DbFuel
|
|
16
16
|
# It will use the unique_keys to first run a query to see if it exists.
|
17
17
|
# Each unique_key becomes a WHERE clause. If a record is found it will then
|
18
18
|
# update the found record using the primary key specified.
|
19
|
-
# If a record is updated or created the record's id will be set to the
|
19
|
+
# If a record is updated or created the record's id will be set to the primary_keyed_column.
|
20
20
|
#
|
21
21
|
# Expected Payload[register] input: array of objects
|
22
22
|
# Payload[register] output: array of objects.
|
23
23
|
class Upsert < Base
|
24
|
-
attr_reader :
|
24
|
+
attr_reader :primary_keyed_column, :timestamps, :unique_attribute_renderers
|
25
25
|
|
26
26
|
# Arguments:
|
27
27
|
# name: name of the job within the Burner::Pipeline.
|
@@ -38,9 +38,10 @@ module DbFuel
|
|
38
38
|
# debugging issues as it will fill
|
39
39
|
# up the output with (potentially too much) data.
|
40
40
|
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
41
|
+
# primary_keyed_column [required]: Used to set the object's property to the
|
42
|
+
# returned primary key from the
|
43
|
+
# INSERT statement or used as the
|
44
|
+
# WHERE clause for the UPDATE statement.
|
44
45
|
#
|
45
46
|
# separator: Just like other jobs with a 'separator' option, if the objects require
|
46
47
|
# key-path notation or nested object support, you can set the separator
|
@@ -57,7 +58,8 @@ module DbFuel
|
|
57
58
|
# order to check for the existence of a specific record.
|
58
59
|
def initialize(
|
59
60
|
table_name:,
|
60
|
-
|
61
|
+
primary_keyed_column:,
|
62
|
+
keys_register: nil,
|
61
63
|
name: '',
|
62
64
|
attributes: [],
|
63
65
|
debug: false,
|
@@ -68,6 +70,7 @@ module DbFuel
|
|
68
70
|
)
|
69
71
|
super(
|
70
72
|
name: name,
|
73
|
+
keys_register: keys_register,
|
71
74
|
table_name: table_name,
|
72
75
|
attributes: attributes,
|
73
76
|
debug: debug,
|
@@ -75,10 +78,10 @@ module DbFuel
|
|
75
78
|
separator: separator
|
76
79
|
)
|
77
80
|
|
78
|
-
@
|
81
|
+
@primary_keyed_column = Modeling::KeyedColumn.make(primary_keyed_column, nullable: true)
|
79
82
|
|
80
83
|
@unique_attribute_renderers = attribute_renderers_set
|
81
|
-
.
|
84
|
+
.make_renderers(unique_attributes)
|
82
85
|
|
83
86
|
@timestamps = timestamps
|
84
87
|
|
@@ -86,15 +89,16 @@ module DbFuel
|
|
86
89
|
end
|
87
90
|
|
88
91
|
def perform(output, payload)
|
89
|
-
raise ArgumentError, '
|
92
|
+
raise ArgumentError, 'primary_keyed_column is required' unless primary_keyed_column
|
90
93
|
|
91
94
|
total_inserted = 0
|
92
95
|
total_updated = 0
|
93
96
|
|
94
97
|
payload[register] = array(payload[register])
|
98
|
+
keys = resolve_key_set(output, payload)
|
95
99
|
|
96
100
|
payload[register].each do |row|
|
97
|
-
record_updated = insert_or_update(output, row, payload.time)
|
101
|
+
record_updated = insert_or_update(output, row, payload.time, keys)
|
98
102
|
|
99
103
|
if record_updated
|
100
104
|
total_updated += 1
|
@@ -118,16 +122,16 @@ module DbFuel
|
|
118
122
|
|
119
123
|
first_record = db_provider.first(unique_row)
|
120
124
|
|
121
|
-
id = resolver.get(first_record,
|
125
|
+
id = resolver.get(first_record, primary_keyed_column.column)
|
122
126
|
|
123
|
-
resolver.set(row,
|
127
|
+
resolver.set(row, primary_keyed_column.key, id)
|
124
128
|
|
125
129
|
debug_detail(output, "Record Exists: #{first_record}") if first_record
|
126
130
|
|
127
131
|
first_record
|
128
132
|
end
|
129
133
|
|
130
|
-
def insert_record(output, row, time)
|
134
|
+
def insert_record(output, row, time, keys = Set.new)
|
131
135
|
dynamic_attrs = if timestamps
|
132
136
|
# doing an INSERT and timestamps should be set
|
133
137
|
# set the created_at and updated_at fields
|
@@ -136,7 +140,7 @@ module DbFuel
|
|
136
140
|
attribute_renderers_set.attribute_renderers
|
137
141
|
end
|
138
142
|
|
139
|
-
set_object = attribute_renderers_set.transform(dynamic_attrs, row, time)
|
143
|
+
set_object = attribute_renderers_set.transform(dynamic_attrs, row, time, keys)
|
140
144
|
|
141
145
|
insert_sql = db_provider.insert_sql(set_object)
|
142
146
|
|
@@ -144,34 +148,34 @@ module DbFuel
|
|
144
148
|
|
145
149
|
id = db_provider.insert(set_object)
|
146
150
|
|
147
|
-
# add the primary key name and value to row if
|
148
|
-
resolver.set(row,
|
151
|
+
# add the primary key name and value to row if primary_keyed_column was specified
|
152
|
+
resolver.set(row, primary_keyed_column.key, id) if primary_keyed_column
|
149
153
|
|
150
154
|
debug_detail(output, "Insert Return: #{row}")
|
151
155
|
end
|
152
156
|
|
153
157
|
# Updates only a single record. Lookups primary key to update the record.
|
154
|
-
def update_record(output, row, time)
|
155
|
-
raise ArgumentError, '
|
158
|
+
def update_record(output, row, time, keys)
|
159
|
+
raise ArgumentError, 'primary_keyed_column is required' unless primary_keyed_column
|
156
160
|
|
157
161
|
first_record = find_record(output, row, time)
|
158
162
|
|
159
163
|
if first_record
|
160
164
|
debug_detail(output, "Record Exists: #{first_record}")
|
161
165
|
|
162
|
-
id = resolver.get(first_record,
|
166
|
+
id = resolver.get(first_record, primary_keyed_column.column)
|
163
167
|
|
164
|
-
where_object = {
|
168
|
+
where_object = { primary_keyed_column.column => id }
|
165
169
|
|
166
170
|
# update record using the primary key as the WHERE clause
|
167
|
-
update(output, row, time, where_object)
|
171
|
+
update(output, row, time, where_object, keys)
|
168
172
|
end
|
169
173
|
|
170
174
|
first_record
|
171
175
|
end
|
172
176
|
|
173
177
|
# Updates one or many records depending on where_object passed
|
174
|
-
def update(output, row, time, where_object)
|
178
|
+
def update(output, row, time, where_object, keys)
|
175
179
|
dynamic_attrs = if timestamps
|
176
180
|
# doing an UPDATE and timestamps should be set,
|
177
181
|
# modify the updated_at field, don't modify the created_at field
|
@@ -180,7 +184,7 @@ module DbFuel
|
|
180
184
|
attribute_renderers_set.attribute_renderers
|
181
185
|
end
|
182
186
|
|
183
|
-
set_object = attribute_renderers_set.transform(dynamic_attrs, row, time)
|
187
|
+
set_object = attribute_renderers_set.transform(dynamic_attrs, row, time, keys)
|
184
188
|
|
185
189
|
update_sql = db_provider.update_sql(set_object, where_object)
|
186
190
|
|
@@ -193,14 +197,14 @@ module DbFuel
|
|
193
197
|
|
194
198
|
private
|
195
199
|
|
196
|
-
def insert_or_update(output, row, time)
|
197
|
-
first_record = update_record(output, row, time)
|
200
|
+
def insert_or_update(output, row, time, keys)
|
201
|
+
first_record = update_record(output, row, time, keys)
|
198
202
|
|
199
203
|
if first_record
|
200
204
|
first_record
|
201
205
|
else
|
202
206
|
# create the record
|
203
|
-
insert_record(output, row, time)
|
207
|
+
insert_record(output, row, time, keys)
|
204
208
|
nil
|
205
209
|
end
|
206
210
|
end
|
@@ -12,18 +12,18 @@ module DbFuel
|
|
12
12
|
# Creates attribute renderers based on attributes passed.
|
13
13
|
# Also constains methods to transform attribute renderers
|
14
14
|
# and include timestamp attributes if needed.
|
15
|
-
class AttributeRendererSet
|
16
|
-
CREATED_AT = :created_at
|
15
|
+
class AttributeRendererSet # :nodoc:
|
17
16
|
NOW_TYPE = 'r/value/now'
|
17
|
+
CREATED_AT = :created_at
|
18
18
|
UPDATED_AT = :updated_at
|
19
19
|
|
20
20
|
attr_reader :attribute_renderers, :resolver
|
21
21
|
|
22
|
-
def initialize(attributes: []
|
22
|
+
def initialize(resolver:, attributes: [])
|
23
23
|
raise ArgumentError, 'resolver is required' unless resolver
|
24
24
|
|
25
25
|
@resolver = resolver
|
26
|
-
@attribute_renderers =
|
26
|
+
@attribute_renderers = make_renderers(attributes)
|
27
27
|
|
28
28
|
freeze
|
29
29
|
end
|
@@ -46,22 +46,22 @@ module DbFuel
|
|
46
46
|
end + attribute_renderers
|
47
47
|
end
|
48
48
|
|
49
|
-
def
|
49
|
+
def make_renderers(attributes)
|
50
50
|
Burner::Modeling::Attribute
|
51
51
|
.array(attributes)
|
52
52
|
.map { |a| Burner::Modeling::AttributeRenderer.new(a, resolver) }
|
53
53
|
end
|
54
54
|
|
55
|
-
def transform(attribute_renderers, row, time)
|
55
|
+
def transform(attribute_renderers, row, time, keys = Set.new)
|
56
56
|
attribute_renderers.each_with_object({}) do |attribute_renderer, memo|
|
57
|
+
next if keys.any? && keys.exclude?(attribute_renderer.key)
|
58
|
+
|
57
59
|
value = attribute_renderer.transform(row, time)
|
58
60
|
|
59
61
|
resolver.set(memo, attribute_renderer.key, value)
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
63
|
-
private
|
64
|
-
|
65
65
|
def created_at_timestamp_attribute
|
66
66
|
timestamp_attribute(CREATED_AT)
|
67
67
|
end
|
data/lib/db_fuel/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: db_fuel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Ruggio
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2021-
|
12
|
+
date: 2021-05-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -65,28 +65,28 @@ dependencies:
|
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '3.0'
|
69
69
|
type: :runtime
|
70
70
|
prerelease: false
|
71
71
|
version_requirements: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '3.0'
|
76
76
|
- !ruby/object:Gem::Dependency
|
77
77
|
name: dbee-active_record
|
78
78
|
requirement: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '2.
|
82
|
+
version: '2.2'
|
83
83
|
type: :runtime
|
84
84
|
prerelease: false
|
85
85
|
version_requirements: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '2.
|
89
|
+
version: '2.2'
|
90
90
|
- !ruby/object:Gem::Dependency
|
91
91
|
name: objectable
|
92
92
|
requirement: !ruby/object:Gem::Requirement
|
@@ -274,9 +274,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
274
274
|
version: '2.5'
|
275
275
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
276
276
|
requirements:
|
277
|
-
- - "
|
277
|
+
- - ">="
|
278
278
|
- !ruby/object:Gem::Version
|
279
|
-
version:
|
279
|
+
version: '0'
|
280
280
|
requirements: []
|
281
281
|
rubygems_version: 3.0.3
|
282
282
|
signing_key:
|