torque-postgresql 2.1.0 → 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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/lib/torque/postgresql/adapter/database_statements.rb +3 -15
  3. data/lib/torque/postgresql/adapter/quoting.rb +1 -1
  4. data/lib/torque/postgresql/adapter/schema_dumper.rb +2 -2
  5. data/lib/torque/postgresql/adapter/schema_statements.rb +5 -1
  6. data/lib/torque/postgresql/adapter.rb +20 -4
  7. data/lib/torque/postgresql/associations/belongs_to_many_association.rb +8 -6
  8. data/lib/torque/postgresql/associations/preloader/association.rb +2 -2
  9. data/lib/torque/postgresql/attributes/builder/enum.rb +5 -5
  10. data/lib/torque/postgresql/attributes/builder/period.rb +2 -6
  11. data/lib/torque/postgresql/attributes/enum.rb +1 -1
  12. data/lib/torque/postgresql/attributes/enum_set.rb +1 -1
  13. data/lib/torque/postgresql/base.rb +1 -1
  14. data/lib/torque/postgresql/config.rb +6 -0
  15. data/lib/torque/postgresql/inheritance.rb +1 -1
  16. data/lib/torque/postgresql/reflection/belongs_to_many_reflection.rb +4 -2
  17. data/lib/torque/postgresql/relation/inheritance.rb +9 -14
  18. data/lib/torque/postgresql/version.rb +1 -1
  19. data/lib/torque/postgresql.rb +0 -1
  20. data/lib/torque/range.rb +0 -2
  21. data/spec/factories/item.rb +5 -0
  22. data/spec/models/item.rb +3 -0
  23. data/spec/models/question.rb +3 -0
  24. data/spec/models/question_select.rb +2 -0
  25. data/spec/schema.rb +19 -1
  26. data/spec/tests/arel_spec.rb +30 -0
  27. data/spec/tests/belongs_to_many_spec.rb +31 -10
  28. data/spec/tests/period_spec.rb +9 -0
  29. data/spec/tests/range_spec.rb +1 -1
  30. data/spec/tests/table_inheritance_spec.rb +30 -21
  31. metadata +37 -32
  32. data/lib/torque/postgresql/coder.rb +0 -133
  33. data/spec/tests/coder_spec.rb +0 -367
@@ -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 = 'WITH "record_class" AS (SELECT "pg_class"."oid", "pg_class"."relname" AS _record_class FROM "pg_class")'
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 << ", \"record_class\".\"_record_class\" IN ('activity_books', 'activity_posts', 'activity_post_samples') AS _auto_cast"
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 = 'WITH "record_class" AS (SELECT "pg_class"."oid", "pg_class"."relname" AS _record_class FROM "pg_class")'
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 << ", \"record_class\".\"_record_class\" IN ('activity_books') AS _auto_cast"
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 = 'WITH "record_class" AS (SELECT "pg_class"."oid", "pg_class"."relname" AS _record_class FROM "pg_class")'
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 << ", \"record_class\".\"_record_class\" IN ('activity_books') AS _auto_cast"
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 \"record_class\".\"_record_class\" = 'activity_books'"
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 = 'WITH "record_class" AS (SELECT "pg_class"."oid", "pg_class"."relname" AS _record_class FROM "pg_class")'
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 = 'WITH "record_class" AS (SELECT "pg_class"."oid", "pg_class"."relname" AS _record_class FROM "pg_class")'
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"'
@@ -387,10 +377,10 @@ RSpec.describe 'TableInheritance' do
387
377
  base.create(title: 'Activity test')
388
378
  child.create(title: 'Activity book')
389
379
  other.create(name: 'An author name')
380
+ base.instance_variable_set(:@casted_dependents, nil)
390
381
  end
391
382
 
392
383
  it 'does not affect normal records' do
393
- base.instance_variable_set(:@casted_dependents, {})
394
384
  expect(base.first.cast_record).to be_a(base)
395
385
  expect(child.first.cast_record).to be_a(child)
396
386
  expect(other.first.cast_record).to be_a(other)
@@ -408,9 +398,28 @@ RSpec.describe 'TableInheritance' do
408
398
  end
409
399
 
410
400
  it 'does trigger record casting when accessed through inheritance' do
411
- base.instance_variable_set(:@casted_dependents, nil)
412
401
  expect(base.second.cast_record).to eql(child.first)
413
402
  end
403
+
404
+ context 'using uuid' do
405
+ let(:base) { Question }
406
+ let(:child) { QuestionSelect }
407
+
408
+ before :each do
409
+ base.create(title: 'Simple question')
410
+ child.create(title: 'Select question')
411
+ base.instance_variable_set(:@casted_dependents, nil)
412
+ end
413
+
414
+ it 'does not affect normal records' do
415
+ expect(base.first.cast_record).to be_a(base)
416
+ expect(child.first.cast_record).to be_a(child)
417
+ end
418
+
419
+ it 'does trigger record casting when accessed through inheritance' do
420
+ expect(base.second.cast_record).to eql(child.first)
421
+ end
422
+ end
414
423
  end
415
424
  end
416
425
  end
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.1.0
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-02-12 00:00:00.000000000 Z
11
+ date: 2021-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -215,7 +215,6 @@ files:
215
215
  - lib/torque/postgresql/auxiliary_statement.rb
216
216
  - lib/torque/postgresql/auxiliary_statement/settings.rb
217
217
  - lib/torque/postgresql/base.rb
218
- - lib/torque/postgresql/coder.rb
219
218
  - lib/torque/postgresql/collector.rb
220
219
  - lib/torque/postgresql/config.rb
221
220
  - lib/torque/postgresql/geometry_builder.rb
@@ -243,6 +242,7 @@ files:
243
242
  - spec/en.yml
244
243
  - spec/factories/authors.rb
245
244
  - spec/factories/comments.rb
245
+ - spec/factories/item.rb
246
246
  - spec/factories/posts.rb
247
247
  - spec/factories/tags.rb
248
248
  - spec/factories/texts.rb
@@ -260,7 +260,10 @@ files:
260
260
  - spec/models/course.rb
261
261
  - spec/models/geometry.rb
262
262
  - spec/models/guest_comment.rb
263
+ - spec/models/item.rb
263
264
  - spec/models/post.rb
265
+ - spec/models/question.rb
266
+ - spec/models/question_select.rb
264
267
  - spec/models/tag.rb
265
268
  - spec/models/text.rb
266
269
  - spec/models/time_keeper.rb
@@ -271,7 +274,6 @@ files:
271
274
  - spec/tests/arel_spec.rb
272
275
  - spec/tests/auxiliary_statement_spec.rb
273
276
  - spec/tests/belongs_to_many_spec.rb
274
- - spec/tests/coder_spec.rb
275
277
  - spec/tests/collector_spec.rb
276
278
  - spec/tests/distinct_on_spec.rb
277
279
  - spec/tests/enum_set_spec.rb
@@ -305,54 +307,57 @@ required_rubygems_version: !ruby/object:Gem::Requirement
305
307
  - !ruby/object:Gem::Version
306
308
  version: 1.8.11
307
309
  requirements: []
308
- rubygems_version: 3.1.4
310
+ rubygems_version: 3.1.2
309
311
  signing_key:
310
312
  specification_version: 4
311
313
  summary: ActiveRecord extension to access PostgreSQL advanced resources
312
314
  test_files:
313
- - spec/models/activity_post/sample.rb
315
+ - spec/en.yml
316
+ - spec/factories/authors.rb
317
+ - spec/factories/comments.rb
318
+ - spec/factories/item.rb
319
+ - spec/factories/posts.rb
320
+ - spec/factories/tags.rb
321
+ - spec/factories/texts.rb
322
+ - spec/factories/users.rb
323
+ - spec/factories/videos.rb
324
+ - spec/mocks/cache_query.rb
325
+ - spec/mocks/create_table.rb
314
326
  - spec/models/activity.rb
327
+ - spec/models/activity_book.rb
328
+ - spec/models/activity_post.rb
329
+ - spec/models/activity_post/sample.rb
315
330
  - spec/models/author.rb
316
331
  - spec/models/author_journalist.rb
317
332
  - spec/models/comment.rb
318
333
  - spec/models/course.rb
319
- - spec/models/post.rb
320
- - spec/models/text.rb
321
- - spec/models/user.rb
322
- - spec/models/activity_book.rb
323
- - spec/models/activity_post.rb
324
334
  - spec/models/geometry.rb
325
335
  - spec/models/guest_comment.rb
336
+ - spec/models/item.rb
337
+ - spec/models/post.rb
326
338
  - spec/models/tag.rb
339
+ - spec/models/text.rb
327
340
  - spec/models/time_keeper.rb
341
+ - spec/models/user.rb
328
342
  - spec/models/video.rb
329
- - spec/factories/authors.rb
330
- - spec/factories/comments.rb
331
- - spec/factories/posts.rb
332
- - spec/factories/tags.rb
333
- - spec/factories/texts.rb
334
- - spec/factories/users.rb
335
- - spec/factories/videos.rb
336
- - spec/tests/geometric_builder_spec.rb
337
- - spec/tests/range_spec.rb
343
+ - spec/models/question.rb
344
+ - spec/models/question_select.rb
345
+ - spec/spec_helper.rb
338
346
  - spec/tests/arel_spec.rb
339
- - spec/tests/insert_all_spec.rb
340
- - spec/tests/enum_spec.rb
341
- - spec/tests/period_spec.rb
342
- - spec/tests/coder_spec.rb
347
+ - spec/tests/auxiliary_statement_spec.rb
348
+ - spec/tests/belongs_to_many_spec.rb
343
349
  - spec/tests/collector_spec.rb
344
350
  - spec/tests/distinct_on_spec.rb
351
+ - spec/tests/enum_set_spec.rb
352
+ - spec/tests/enum_spec.rb
353
+ - spec/tests/geometric_builder_spec.rb
354
+ - spec/tests/has_many_spec.rb
355
+ - spec/tests/insert_all_spec.rb
345
356
  - spec/tests/interval_spec.rb
346
357
  - spec/tests/lazy_spec.rb
358
+ - spec/tests/period_spec.rb
347
359
  - spec/tests/quoting_spec.rb
360
+ - spec/tests/range_spec.rb
348
361
  - spec/tests/relation_spec.rb
349
- - spec/tests/auxiliary_statement_spec.rb
350
- - spec/tests/enum_set_spec.rb
351
- - spec/tests/has_many_spec.rb
352
- - spec/tests/belongs_to_many_spec.rb
353
362
  - spec/tests/table_inheritance_spec.rb
354
- - spec/mocks/cache_query.rb
355
- - spec/mocks/create_table.rb
356
- - spec/en.yml
357
- - spec/spec_helper.rb
358
363
  - spec/schema.rb
@@ -1,133 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Torque
4
- module PostgreSQL
5
- module Coder
6
-
7
- # This class represents an Record to be encoded, instead of a literal Array
8
- Record = Class.new(Array)
9
-
10
- class << self
11
-
12
- NEED_QUOTE_FOR = /[\\"(){}, \t\n\r\v\f]/m
13
- DELIMITER = ','
14
-
15
- # This method replace the +read_array+ method from PG gem
16
- # See https://github.com/ged/ruby-pg/blob/master/ext/pg_text_decoder.c#L177
17
- # for more information
18
- def decode(value)
19
- # TODO: Use StringScanner
20
- # See http://ruby-doc.org/stdlib-1.9.3/libdoc/strscan/rdoc/StringScanner.html
21
- _decode(::StringIO.new(value))
22
- end
23
-
24
- # This method replace the ++ method from PG gem
25
- # See https://github.com/ged/ruby-pg/blob/master/ext/pg_text_encoder.c#L398
26
- # for more information
27
- def encode(value)
28
- _encode(value)
29
- end
30
-
31
- private
32
-
33
- def _decode(stream)
34
- quoted = 0
35
- escaped = false
36
- result = []
37
- part = String.new
38
-
39
- # Always start getting the non-collection character, the second char
40
- stream.getc if stream.pos == 0
41
-
42
- # Check for an empty list
43
- return result if %w[} )].include?(stream.getc)
44
-
45
- # If it's not an empty list, return one position before iterating
46
- stream.pos -= 1
47
- stream.each_char do |c|
48
-
49
- case
50
- when quoted < 1
51
- case
52
- when c == DELIMITER, c == '}', c == ')'
53
-
54
- unless escaped
55
- # Non-quoted empty string or NULL as extense
56
- part = nil if quoted == 0 && ( part.length == 0 || part == 'NULL' )
57
- result << part
58
- end
59
-
60
- return result unless c == DELIMITER
61
-
62
- escaped = false
63
- quoted = 0
64
- part = String.new
65
-
66
- when c == '"'
67
- quoted = 1
68
- when c == '{', c == '('
69
- result << _decode(stream)
70
- escaped = true
71
- else
72
- part << c
73
- end
74
- when escaped
75
- escaped = false
76
- part << c
77
- when c == '\\'
78
- escaped = true
79
- when c == '"'
80
- if stream.getc == '"'
81
- part << c
82
- else
83
- stream.pos -= 1
84
- quoted = -1
85
- end
86
- else
87
- if ( c == '"' || c == "'" ) && stream.getc != c
88
- stream.pos -= 1
89
- quoted = -1
90
- else
91
- part << c
92
- end
93
- end
94
-
95
- end
96
- end
97
-
98
- def _encode(list)
99
- is_record = list.is_a?(Record)
100
- list.map! do |part|
101
- case part
102
- when NilClass
103
- is_record ? '' : 'NULL'
104
- when Array
105
- _encode(part)
106
- else
107
- _quote(part.to_s)
108
- end
109
- end
110
-
111
- result = is_record ? '(%s)' : '{%s}'
112
- result % list.join(DELIMITER)
113
- end
114
-
115
- def _quote(string)
116
- len = string.length
117
-
118
- # Fast results
119
- return '""' if len == 0
120
- return '"NULL"' if len == 4 && string == 'NULL'
121
-
122
- # Check if the string don't need quotes
123
- return string unless string =~ NEED_QUOTE_FOR
124
-
125
- # Use the original string escape function
126
- PG::Connection.escape_string(string).inspect
127
- end
128
-
129
- end
130
-
131
- end
132
- end
133
- end