torque-postgresql 2.1.3 → 2.2.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/lib/torque/postgresql/adapter/database_statements.rb +2 -0
- data/lib/torque/postgresql/adapter/quoting.rb +1 -1
- data/lib/torque/postgresql/adapter.rb +20 -4
- data/lib/torque/postgresql/associations/preloader/association.rb +2 -2
- data/lib/torque/postgresql/attributes/builder/period.rb +2 -6
- data/lib/torque/postgresql/config.rb +6 -0
- data/lib/torque/postgresql/inheritance.rb +1 -1
- data/lib/torque/postgresql/reflection/belongs_to_many_reflection.rb +4 -2
- data/lib/torque/postgresql/relation/inheritance.rb +9 -14
- data/lib/torque/postgresql/version.rb +1 -1
- data/lib/torque/range.rb +0 -2
- data/spec/tests/arel_spec.rb +30 -0
- data/spec/tests/period_spec.rb +9 -0
- data/spec/tests/range_spec.rb +1 -1
- data/spec/tests/table_inheritance_spec.rb +9 -19
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb3d81538edfb988d8566295fac7d055208e399d552b619d9d8b3b9234254686
|
4
|
+
data.tar.gz: 7c7c62bec966085eccbdc351041a94d04788e40f84b1120d88c1673c9d0e3b3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93cf49b971a0013d3f10263917437b7a552632e62f462d43b91aaad86ec66ba10b20a014bf2bbcaa883f1c6801df423fd3d98dd8d9546bd849920bb98b743e6c
|
7
|
+
data.tar.gz: 88cf63c02e13e80e48b5dfbe66e9157a52ecc8cc11410f0688e97a6c28e7f25a03adc9c7b71a45ffe9384a81debbf1a29d55363145a4ae6568c82cc9f7207a30
|
@@ -15,7 +15,14 @@ module Torque
|
|
15
15
|
include DatabaseStatements
|
16
16
|
include SchemaStatements
|
17
17
|
|
18
|
-
|
18
|
+
# :nodoc:
|
19
|
+
class DeduplicatableArray < ::Array
|
20
|
+
def deduplicate
|
21
|
+
map { |value| -value }
|
22
|
+
end
|
23
|
+
|
24
|
+
alias :-@ :deduplicate
|
25
|
+
end
|
19
26
|
|
20
27
|
# Get the current PostgreSQL version as a Gem Version.
|
21
28
|
def version
|
@@ -29,19 +36,28 @@ module Torque
|
|
29
36
|
super.merge(options.extract!(:inherits))
|
30
37
|
end
|
31
38
|
|
32
|
-
# Allow filtered bulk insert by adding the where clause. This method is
|
33
|
-
# +InsertAll+, so it somewhat safe to override it
|
39
|
+
# Allow filtered bulk insert by adding the where clause. This method is
|
40
|
+
# only used by +InsertAll+, so it somewhat safe to override it
|
34
41
|
def build_insert_sql(insert)
|
35
42
|
super.tap do |sql|
|
36
43
|
if insert.update_duplicates? && insert.where_condition?
|
37
44
|
if insert.returning
|
38
|
-
sql.
|
45
|
+
sql.sub!(' RETURNING ', " WHERE #{insert.where} RETURNING ")
|
39
46
|
else
|
40
47
|
sql << " WHERE #{insert.where}"
|
41
48
|
end
|
42
49
|
end
|
43
50
|
end
|
44
51
|
end
|
52
|
+
|
53
|
+
# Extend the extract default value to support array
|
54
|
+
def extract_value_from_default(default)
|
55
|
+
return super unless Torque::PostgreSQL.config.use_extended_defaults
|
56
|
+
return super unless default&.match(/ARRAY\[(.*?)\](?:::"?([\w. ]+)"?(?:\[\])+)?$/)
|
57
|
+
|
58
|
+
arr = $1.split(/(?!\B\[[^\]]*), ?(?![^\[]*\]\B)/)
|
59
|
+
DeduplicatableArray.new(arr.map(&method(:extract_value_from_default)))
|
60
|
+
end
|
45
61
|
end
|
46
62
|
|
47
63
|
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend Adapter
|
@@ -452,12 +452,8 @@ module Torque
|
|
452
452
|
def instance_current_on?
|
453
453
|
attr_value = threshold.present? ? method_names[:real] : attribute
|
454
454
|
default_value = default.inspect
|
455
|
-
|
456
|
-
|
457
|
-
"return #{default_value} if #{attr_value}.min.try(:infinite?)",
|
458
|
-
"return #{default_value} if #{attr_value}.max.try(:infinite?)",
|
459
|
-
"#{attr_value}.min < value && #{attr_value}.max > value",
|
460
|
-
].join("\n")
|
455
|
+
|
456
|
+
"#{attr_value}.nil? ? #{default_value} : #{attr_value}.include?(value)"
|
461
457
|
end
|
462
458
|
|
463
459
|
def instance_start
|
@@ -5,6 +5,7 @@ module Torque
|
|
5
5
|
include ActiveSupport::Configurable
|
6
6
|
|
7
7
|
# Stores a version check for compatibility purposes
|
8
|
+
AR604 = (ActiveRecord.gem_version >= Gem::Version.new('6.0.4'))
|
8
9
|
AR610 = (ActiveRecord.gem_version >= Gem::Version.new('6.1.0'))
|
9
10
|
|
10
11
|
# Use the same logger as the Active Record one
|
@@ -25,6 +26,11 @@ module Torque
|
|
25
26
|
# same configuration is set to true
|
26
27
|
config.eager_load = false
|
27
28
|
|
29
|
+
# This allows default values to have extended values like arrays and casted
|
30
|
+
# values. Extended defaults are still experimental, so enable and test it
|
31
|
+
# before using it in prod
|
32
|
+
config.use_extended_defaults = false
|
33
|
+
|
28
34
|
# Set a list of irregular model name when associated with table names
|
29
35
|
config.irregular_models = {}
|
30
36
|
def config.irregular_models=(hash)
|
@@ -146,7 +146,7 @@ module Torque
|
|
146
146
|
auto_cast = _auto_cast_attribute.to_s
|
147
147
|
record_class = _record_class_attribute.to_s
|
148
148
|
return super unless attributes.key?(record_class) &&
|
149
|
-
|
149
|
+
attributes.delete(auto_cast) && attributes[record_class] != table_name
|
150
150
|
|
151
151
|
klass = casted_dependents[attributes[record_class]]
|
152
152
|
raise_unable_to_cast(attributes[record_class]) if klass.nil?
|
@@ -56,8 +56,10 @@ module Torque
|
|
56
56
|
end
|
57
57
|
|
58
58
|
::ActiveRecord::Reflection.const_set(:BelongsToManyReflection, BelongsToManyReflection)
|
59
|
-
|
60
|
-
|
59
|
+
|
60
|
+
reflection_class = ::ActiveRecord::Reflection::AssociationReflection
|
61
|
+
reflection_class::VALID_AUTOMATIC_INVERSE_MACROS.push(:belongs_to_many) \
|
62
|
+
if reflection_class.const_defined?('VALID_AUTOMATIC_INVERSE_MACROS')
|
61
63
|
end
|
62
64
|
end
|
63
65
|
end
|
@@ -5,6 +5,8 @@ module Torque
|
|
5
5
|
module Relation
|
6
6
|
module Inheritance
|
7
7
|
|
8
|
+
# REGCLASS = ::Arel.sql('tableoid').cast('regclass')
|
9
|
+
|
8
10
|
# :nodoc:
|
9
11
|
def cast_records_value; get_value(:cast_records); end
|
10
12
|
# :nodoc:
|
@@ -44,14 +46,8 @@ module Torque
|
|
44
46
|
|
45
47
|
# Like #cast_records, but modifies relation in place
|
46
48
|
def cast_records!(*types, **options)
|
47
|
-
|
48
|
-
|
49
|
-
with!(record_class)
|
50
|
-
if options[:filter]
|
51
|
-
table = record_class.to_s.camelize.underscore
|
52
|
-
where!(table => { record_class => types.map(&:table_name) })
|
53
|
-
end
|
54
|
-
|
49
|
+
where!(regclass.cast(:varchar).in(types.map(&:table_name))) if options[:filter]
|
50
|
+
self.select_extra_values += [regclass.as(_record_class_attribute.to_s)]
|
55
51
|
self.cast_records_value = (types.present? ? types : model.casted_dependents.values)
|
56
52
|
self
|
57
53
|
end
|
@@ -109,13 +105,12 @@ module Torque
|
|
109
105
|
end
|
110
106
|
|
111
107
|
def build_auto_caster_marker(arel, types)
|
112
|
-
|
113
|
-
|
114
|
-
|
108
|
+
attribute = regclass.cast(:varchar).in(types.map(&:table_name))
|
109
|
+
attribute.as(self.class._auto_cast_attribute.to_s)
|
110
|
+
end
|
115
111
|
|
116
|
-
|
117
|
-
|
118
|
-
::Arel.sql(column.to_sql).as(auto_cast_attribute)
|
112
|
+
def regclass
|
113
|
+
arel_table['tableoid'].cast(:regclass)
|
119
114
|
end
|
120
115
|
|
121
116
|
end
|
data/lib/torque/range.rb
CHANGED
data/spec/tests/arel_spec.rb
CHANGED
@@ -48,6 +48,36 @@ RSpec.describe 'Arel' do
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
context 'on default value' do
|
52
|
+
let(:connection) { ActiveRecord::Base.connection }
|
53
|
+
|
54
|
+
before(:context) { Torque::PostgreSQL.config.use_extended_defaults = true }
|
55
|
+
after(:context) { Torque::PostgreSQL.config.use_extended_defaults = false }
|
56
|
+
after { Author.reset_column_information }
|
57
|
+
|
58
|
+
it 'does not break jsonb' do
|
59
|
+
expect { connection.add_column(:authors, :profile, :jsonb, default: []) }.not_to raise_error
|
60
|
+
expect(Author.columns_hash['profile'].default).to eq('[]')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'works properly when column is an array' do
|
64
|
+
expect { connection.add_column(:authors, :tag_ids, :bigint, array: true, default: []) }.not_to raise_error
|
65
|
+
expect(Author.columns_hash['tag_ids'].default).to eq([])
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'works with an array with enum values' do
|
69
|
+
value = ['visitor', 'assistant']
|
70
|
+
expect { connection.add_column(:authors, :roles, :roles, array: true, default: value) }.not_to raise_error
|
71
|
+
expect(Author.columns_hash['roles'].default).to eq(value)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'works with multi dimentional array' do
|
75
|
+
value = [['1', '2'], ['3', '4']]
|
76
|
+
expect { connection.add_column(:authors, :tag_ids, :string, array: true, default: value) }.not_to raise_error
|
77
|
+
expect(Author.columns_hash['tag_ids'].default).to eq(value)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
51
81
|
context 'on cast' do
|
52
82
|
it 'provides an array method' do
|
53
83
|
sample1 = ::Arel.array(1, 2, 3, 4)
|
data/spec/tests/period_spec.rb
CHANGED
@@ -266,6 +266,15 @@ RSpec.describe 'Period' do
|
|
266
266
|
|
267
267
|
instance.period = 4.hour.from_now.utc..6.hour.from_now.utc
|
268
268
|
expect(instance).not_to be_current_period
|
269
|
+
|
270
|
+
instance.period = [nil, 4.hours.ago.utc]
|
271
|
+
expect(instance).not_to be_current_period
|
272
|
+
|
273
|
+
instance.period = [4.hours.from_now.utc, nil]
|
274
|
+
expect(instance).not_to be_current_period
|
275
|
+
|
276
|
+
instance.period = [nil, nil]
|
277
|
+
expect(instance).to be_current_period
|
269
278
|
end
|
270
279
|
|
271
280
|
it 'checks fro current based on a value' do
|
data/spec/tests/range_spec.rb
CHANGED
@@ -292,14 +292,12 @@ RSpec.describe 'TableInheritance' do
|
|
292
292
|
end
|
293
293
|
|
294
294
|
it 'adds all statements to load all the necessary records' do
|
295
|
-
result = '
|
296
|
-
result << ' SELECT "activities".*, "record_class"."_record_class", "i_0"."description"'
|
295
|
+
result = 'SELECT "activities".*, "activities"."tableoid"::regclass AS _record_class, "i_0"."description"'
|
297
296
|
result << ', COALESCE("i_0"."url", "i_1"."url", "i_2"."url") AS url, "i_0"."activated" AS activity_books__activated'
|
298
297
|
result << ', "i_1"."activated" AS activity_posts__activated, "i_2"."activated" AS activity_post_samples__activated'
|
299
298
|
result << ', COALESCE("i_1"."file", "i_2"."file") AS file, COALESCE("i_1"."post_id", "i_2"."post_id") AS post_id'
|
300
|
-
result << ", \"
|
299
|
+
result << ", \"activities\".\"tableoid\"::regclass::varchar IN ('activity_books', 'activity_posts', 'activity_post_samples') AS _auto_cast"
|
301
300
|
result << ' FROM "activities"'
|
302
|
-
result << ' INNER JOIN "record_class" ON "record_class"."oid" = "activities"."tableoid"'
|
303
301
|
result << ' LEFT OUTER JOIN "activity_books" "i_0" ON "activities"."id" = "i_0"."id"'
|
304
302
|
result << ' LEFT OUTER JOIN "activity_posts" "i_1" ON "activities"."id" = "i_1"."id"'
|
305
303
|
result << ' LEFT OUTER JOIN "activity_post_samples" "i_2" ON "activities"."id" = "i_2"."id"'
|
@@ -307,33 +305,27 @@ RSpec.describe 'TableInheritance' do
|
|
307
305
|
end
|
308
306
|
|
309
307
|
it 'can be have simplefied joins' do
|
310
|
-
result = '
|
311
|
-
result << ' SELECT "activities".*, "record_class"."_record_class"'
|
308
|
+
result = 'SELECT "activities".*, "activities"."tableoid"::regclass AS _record_class'
|
312
309
|
result << ', "i_0"."description", "i_0"."url", "i_0"."activated"'
|
313
|
-
result << ", \"
|
310
|
+
result << ", \"activities\".\"tableoid\"::regclass::varchar IN ('activity_books') AS _auto_cast"
|
314
311
|
result << ' FROM "activities"'
|
315
|
-
result << ' INNER JOIN "record_class" ON "record_class"."oid" = "activities"."tableoid"'
|
316
312
|
result << ' LEFT OUTER JOIN "activity_books" "i_0" ON "activities"."id" = "i_0"."id"'
|
317
313
|
expect(base.cast_records(child).all.to_sql).to eql(result)
|
318
314
|
end
|
319
315
|
|
320
316
|
it 'can be filtered by record type' do
|
321
|
-
result = '
|
322
|
-
result << ' SELECT "activities".*, "record_class"."_record_class"'
|
317
|
+
result = 'SELECT "activities".*, "activities"."tableoid"::regclass AS _record_class'
|
323
318
|
result << ', "i_0"."description", "i_0"."url", "i_0"."activated"'
|
324
|
-
result << ", \"
|
319
|
+
result << ", \"activities\".\"tableoid\"::regclass::varchar IN ('activity_books') AS _auto_cast"
|
325
320
|
result << ' FROM "activities"'
|
326
|
-
result << ' INNER JOIN "record_class" ON "record_class"."oid" = "activities"."tableoid"'
|
327
321
|
result << ' LEFT OUTER JOIN "activity_books" "i_0" ON "activities"."id" = "i_0"."id"'
|
328
|
-
result << " WHERE \"
|
322
|
+
result << " WHERE \"activities\".\"tableoid\"::regclass::varchar IN ('activity_books')"
|
329
323
|
expect(base.cast_records(child, filter: true).all.to_sql).to eql(result)
|
330
324
|
end
|
331
325
|
|
332
326
|
it 'works with count and does not add extra columns' do
|
333
|
-
result = '
|
334
|
-
result << ' SELECT COUNT(*)'
|
327
|
+
result = 'SELECT COUNT(*)'
|
335
328
|
result << ' FROM "activities"'
|
336
|
-
result << ' INNER JOIN "record_class" ON "record_class"."oid" = "activities"."tableoid"'
|
337
329
|
result << ' LEFT OUTER JOIN "activity_books" "i_0" ON "activities"."id" = "i_0"."id"'
|
338
330
|
result << ' LEFT OUTER JOIN "activity_posts" "i_1" ON "activities"."id" = "i_1"."id"'
|
339
331
|
result << ' LEFT OUTER JOIN "activity_post_samples" "i_2" ON "activities"."id" = "i_2"."id"'
|
@@ -342,10 +334,8 @@ RSpec.describe 'TableInheritance' do
|
|
342
334
|
end
|
343
335
|
|
344
336
|
it 'works with sum and does not add extra columns' do
|
345
|
-
result = '
|
346
|
-
result << ' SELECT SUM("activities"."id")'
|
337
|
+
result = 'SELECT SUM("activities"."id")'
|
347
338
|
result << ' FROM "activities"'
|
348
|
-
result << ' INNER JOIN "record_class" ON "record_class"."oid" = "activities"."tableoid"'
|
349
339
|
result << ' LEFT OUTER JOIN "activity_books" "i_0" ON "activities"."id" = "i_0"."id"'
|
350
340
|
result << ' LEFT OUTER JOIN "activity_posts" "i_1" ON "activities"."id" = "i_1"."id"'
|
351
341
|
result << ' LEFT OUTER JOIN "activity_post_samples" "i_2" ON "activities"."id" = "i_2"."id"'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: torque-postgresql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carlos Silva
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09-
|
11
|
+
date: 2021-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|