postgresql_cursor 0.6.4 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f0d7815c65eeeeb83cc41344d0e4a76906236c43392f837e9e2ba7bb14277a7
4
- data.tar.gz: 66b9dbcb6a17046a2d1338297f0b9e4233b46467bd0efb76a663db5d6cfcb4be
3
+ metadata.gz: 79f076e2bf123498e0df89e2933531efae406a754cf14d049be33f973fc791c0
4
+ data.tar.gz: 260e4db366a8ccacb370d04c894b643c8363ed666e46fae77c81ec2b79d09b1e
5
5
  SHA512:
6
- metadata.gz: cc42f9f219afb24cbbe15abf0829de57b8f3c8002a3658e931bfbc97a065d080706e500ba86b3a3bacf8778ca824032556497f520ee1153348f8f9057fc98b6b
7
- data.tar.gz: ec58f29782cfac48985b1c8d491726cfb23ebc1cefae89766045bff36989b238e01a10fa0eb6f436efdc0446b73395b6fdb32f13cfd239166b3713736c4d8f20
6
+ metadata.gz: 18720db87b3218629b6658a7fec653f56775eed3cea0af4cae6d0422a93b7f2dfa338c47752f5be84f46a1b72dbee4c0ec677ee7e6057894ad85c31937fef02b
7
+ data.tar.gz: 48aff84018a7924fff8c1eefbef1240b5adec9f43c12d29fd744b8af80ef283edae66249f5546d7c81741fed93d70838ac494031518a2814c4f44e43f5ff3944
data/.gitignore CHANGED
@@ -15,6 +15,7 @@ tmtags
15
15
 
16
16
  ## IntelliJ/Rubymine
17
17
  .idea
18
+ *.iml
18
19
 
19
20
  ## PROJECT::GENERAL
20
21
  coverage
@@ -22,4 +23,4 @@ rdoc
22
23
  pkg
23
24
 
24
25
  ## PROJECT::SPECIFIC
25
- Gemfile.lock
26
+ Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,27 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.6.5
4
+ - 2.7.1
5
+ before_install:
6
+ - sudo apt-get update
7
+ - sudo apt-get --yes remove postgresql\*
8
+ - sudo apt-get install -y postgresql-12 postgresql-client-12
9
+ - sudo cp /etc/postgresql/{9.6,12}/main/pg_hba.conf
10
+ - sudo service postgresql restart 12
11
+ gemfile:
12
+ - gemfiles/activerecord_4.gemfile
13
+ - gemfiles/activerecord_5.gemfile
14
+ - gemfiles/activerecord_6.gemfile
15
+ matrix:
16
+ exclude:
17
+ - rvm: 2.7.1
18
+ gemfile: gemfiles/activerecord_4.gemfile
19
+ services:
20
+ - postgresql
21
+ before_script:
22
+ - psql -c 'create database postgresql_cursor_test;' -U postgres
23
+ - psql -c 'CREATE ROLE travis SUPERUSER LOGIN CREATEDB;' -U postgres
24
+ - psql -c 'create table products ( id serial primary key, data varchar);' -U postgres -d postgresql_cursor_test
25
+ - psql -c 'create table prices ( id serial primary key, data varchar, product_id integer);' -U postgres -d postgresql_cursor_test
26
+ addons:
27
+ postgresql: '12.3'
data/Appraisals ADDED
@@ -0,0 +1,12 @@
1
+ appraise "activerecord-4" do
2
+ gem "activerecord", "4.2.11.1"
3
+ gem "pg", "~> 0.15"
4
+ end
5
+
6
+ appraise "activerecord-5" do
7
+ gem "activerecord", "5.2.3"
8
+ end
9
+
10
+ appraise "activerecord-6" do
11
+ gem "activerecord", "6.0.0"
12
+ end
data/Rakefile CHANGED
@@ -21,4 +21,5 @@ desc "Setup testing database and table"
21
21
  task :setup do
22
22
  sh %q(createdb postgresql_cursor_test)
23
23
  sh %Q<echo "create table products ( id serial primary key, data varchar);" | psql postgresql_cursor_test>
24
+ sh %Q<echo "create table prices ( id serial primary key, data varchar, product_id integer);" | psql postgresql_cursor_test>
24
25
  end
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "4.2.11.1"
6
+ gem "pg", "~> 0.15"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "5.2.3"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "6.0.0"
6
+
7
+ gemspec path: "../"
@@ -41,29 +41,32 @@ module PostgreSQLCursor
41
41
  # PostgreSQLCursor::Cursor.new("select ....")
42
42
  #
43
43
  # Returns the cursor object when called with new.
44
- def initialize(sql, options={})
45
- @sql = sql
46
- @options = options
44
+ def initialize(sql, options = {})
45
+ @sql = sql
46
+ @options = options
47
47
  @connection = @options.fetch(:connection) { ::ActiveRecord::Base.connection }
48
- @count = 0
49
- @iterate = options[:instances] ? :each_instance : :each_row
50
- @batched = false
48
+ @count = 0
49
+ @iterate = options[:instances] ? :each_instance : :each_row
50
+ @batched = false
51
51
  end
52
52
 
53
- # Specify the type to instantiate, or reset to return a Hash
54
- def iterate_type(type=nil)
55
- if type.nil? || type == Hash
53
+ # Specify the type to instantiate, or reset to return a Hash.
54
+ #
55
+ # Explicitly check for type class to prevent calling equality
56
+ # operator on active record relation, which will load it.
57
+ def iterate_type(type = nil)
58
+ if type.nil? || (type.instance_of?(Class) && type == Hash)
56
59
  @iterate = :each_row
57
- elsif type == Array
60
+ elsif type.instance_of?(Class) && type == Array
58
61
  @iterate = :each_array
59
62
  else
60
63
  @iterate = :each_instance
61
- @type = type
64
+ @type = type
62
65
  end
63
66
  self
64
67
  end
65
68
 
66
- def iterate_batched(batched=true)
69
+ def iterate_batched(batched = true)
67
70
  @batched = batched
68
71
  self
69
72
  end
@@ -76,16 +79,16 @@ module PostgreSQLCursor
76
79
  # Returns the count of rows processed
77
80
  def each(&block)
78
81
  if @iterate == :each_row
79
- @batched ? self.each_row_batch(&block) : self.each_row(&block)
82
+ @batched ? each_row_batch(&block) : each_row(&block)
80
83
  elsif @iterate == :each_array
81
- @batched ? self.each_array_batch(&block) : self.each_array(&block)
84
+ @batched ? each_array_batch(&block) : each_array(&block)
82
85
  else
83
- @batched ? self.each_instance_batch(@type, &block) : self.each_instance(@type, &block)
86
+ @batched ? each_instance_batch(@type, &block) : each_instance(@type, &block)
84
87
  end
85
88
  end
86
89
 
87
90
  def each_row(&block)
88
- self.each_tuple do |row|
91
+ each_tuple do |row|
89
92
  row = row.symbolize_keys if @options[:symbolize_keys]
90
93
  block.call(row)
91
94
  end
@@ -95,7 +98,7 @@ module PostgreSQLCursor
95
98
  old_iterate = @iterate
96
99
  @iterate = :each_array
97
100
  begin
98
- rv = self.each_tuple do |row|
101
+ rv = each_tuple do |row|
99
102
  block.call(row)
100
103
  end
101
104
  ensure
@@ -104,11 +107,11 @@ module PostgreSQLCursor
104
107
  rv
105
108
  end
106
109
 
107
- def each_instance(klass=nil, &block)
110
+ def each_instance(klass = nil, &block)
108
111
  klass ||= @type
109
- self.each_tuple do |row|
112
+ each_tuple do |row|
110
113
  if ::ActiveRecord::VERSION::MAJOR < 4
111
- model = klass.send(:instantiate,row)
114
+ model = klass.send(:instantiate, row)
112
115
  else
113
116
  @column_types ||= column_types
114
117
  model = klass.send(:instantiate, row, @column_types)
@@ -118,7 +121,7 @@ module PostgreSQLCursor
118
121
  end
119
122
 
120
123
  def each_row_batch(&block)
121
- self.each_batch do |batch|
124
+ each_batch do |batch|
122
125
  batch.map!(&:symbolize_keys) if @options[:symbolize_keys]
123
126
  block.call(batch)
124
127
  end
@@ -128,7 +131,7 @@ module PostgreSQLCursor
128
131
  old_iterate = @iterate
129
132
  @iterate = :each_array
130
133
  begin
131
- rv = self.each_batch do |batch|
134
+ rv = each_batch do |batch|
132
135
  block.call(batch)
133
136
  end
134
137
  ensure
@@ -137,15 +140,15 @@ module PostgreSQLCursor
137
140
  rv
138
141
  end
139
142
 
140
- def each_instance_batch(klass=nil, &block)
143
+ def each_instance_batch(klass = nil, &block)
141
144
  klass ||= @type
142
- self.each_batch do |batch|
145
+ each_batch do |batch|
143
146
  models = batch.map do |row|
144
147
  if ::ActiveRecord::VERSION::MAJOR < 4
145
- model = klass.send(:instantiate, row)
148
+ klass.send(:instantiate, row)
146
149
  else
147
150
  @column_types ||= column_types
148
- model = klass.send(:instantiate, row, @column_types)
151
+ klass.send(:instantiate, row, @column_types)
149
152
  end
150
153
  end
151
154
  block.call(models)
@@ -160,11 +163,11 @@ module PostgreSQLCursor
160
163
  options = cols.last.is_a?(Hash) ? cols.pop : {}
161
164
  @options.merge!(options)
162
165
  @options[:symbolize_keys] = true
163
- self.iterate_type(options[:class]) if options[:class]
164
- cols = cols.map {|c| c.to_sym }
165
- result = []
166
+ iterate_type(options[:class]) if options[:class]
167
+ cols = cols.map { |c| c.to_sym }
168
+ result = []
166
169
 
167
- self.each() do |row|
170
+ each do |row|
168
171
  row = row.symbolize_keys if row.is_a?(Hash)
169
172
  result << cols.map { |c| row[c] }
170
173
  end
@@ -173,48 +176,44 @@ module PostgreSQLCursor
173
176
  result
174
177
  end
175
178
 
176
- def each_tuple(&block) #:nodoc:
177
- has_do_until = @options.has_key?(:until)
178
- has_do_while = @options.has_key?(:while)
179
- @count = 0
179
+ def each_tuple(&block) # :nodoc:
180
+ has_do_until = @options.has_key?(:until)
181
+ has_do_while = @options.has_key?(:while)
182
+ @count = 0
180
183
  @column_types = nil
181
184
  with_optional_transaction do
182
- begin
183
- open
184
- while (row = fetch) do
185
- break if row.size==0
186
- @count += 1
187
- rc = block.call(row)
188
- break if has_do_until && rc == @options[:until]
189
- break if has_do_while && rc != @options[:while]
190
- end
191
- rescue Exception => e
192
- raise e
193
- ensure
194
- close if @block
185
+ open
186
+ while (row = fetch)
187
+ break if row.size == 0
188
+ @count += 1
189
+ rc = block.call(row)
190
+ break if has_do_until && rc == @options[:until]
191
+ break if has_do_while && rc != @options[:while]
195
192
  end
193
+ rescue => e
194
+ raise e
195
+ ensure
196
+ close if @block && connection.active?
196
197
  end
197
198
  @count
198
199
  end
199
200
 
200
- def each_batch(&block) #:nodoc:
201
+ def each_batch(&block) # :nodoc:
201
202
  has_do_until = @options.key?(:until)
202
203
  has_do_while = @options.key?(:while)
203
204
  @count = 0
204
205
  @column_types = nil
205
206
  with_optional_transaction do
206
- begin
207
- open
208
- while (batch = fetch_block)
209
- break if batch.empty?
210
- @count += 1
211
- rc = block.call(batch)
212
- break if has_do_until && rc == @options[:until]
213
- break if has_do_while && rc != @options[:while]
214
- end
215
- ensure
216
- close if @block
207
+ open
208
+ while (batch = fetch_block)
209
+ break if batch.empty?
210
+ @count += 1
211
+ rc = block.call(batch)
212
+ break if has_do_until && rc == @options[:until]
213
+ break if has_do_while && rc != @options[:while]
217
214
  end
215
+ ensure
216
+ close if @block && connection.active?
218
217
  end
219
218
  @count
220
219
  end
@@ -231,7 +230,7 @@ module PostgreSQLCursor
231
230
  fields = @result.fields
232
231
  fields.each_with_index do |fname, i|
233
232
  ftype = @result.ftype i
234
- fmod = @result.fmod i
233
+ fmod = @result.fmod i
235
234
  types[fname] = @connection.get_type_map.fetch(ftype, fmod) do |oid, mod|
236
235
  warn "unknown OID: #{fname}(#{oid}) (#{sql})"
237
236
  if ::ActiveRecord::VERSION::MAJOR <= 4
@@ -248,8 +247,8 @@ module PostgreSQLCursor
248
247
  # Public: Opens (actually, "declares") the cursor. Call this before fetching
249
248
  def open
250
249
  set_cursor_tuple_fraction
251
- @cursor = @options[:cursor_name] || ("cursor_" + SecureRandom.uuid.gsub("-",""))
252
- hold = @options[:with_hold] ? 'with hold ' : ''
250
+ @cursor = @options[:cursor_name] || ("cursor_" + SecureRandom.uuid.delete("-"))
251
+ hold = @options[:with_hold] ? "with hold " : ""
253
252
  @result = @connection.execute("declare #{@cursor} no scroll cursor #{hold}for #{@sql}")
254
253
  @block = []
255
254
  end
@@ -257,23 +256,23 @@ module PostgreSQLCursor
257
256
  # Public: Returns the next row from the cursor, or empty hash if end of results
258
257
  #
259
258
  # Returns a row as a hash of {'colname'=>value,...}
260
- def fetch(options={})
259
+ def fetch(options = {})
261
260
  open unless @block
262
- fetch_block if @block.size==0
261
+ fetch_block if @block.size == 0
263
262
  row = @block.shift
264
263
  row = row.symbolize_keys if row && options[:symbolize_keys]
265
264
  row
266
265
  end
267
266
 
268
267
  # Private: Fetches the next block of rows into @block
269
- def fetch_block(block_size=nil)
270
- block_size ||= @block_size ||= @options.fetch(:block_size) { 1000 }
268
+ def fetch_block(block_size = nil)
269
+ block_size ||= @block_size ||= @options.fetch(:block_size, 1000)
271
270
  @result = @connection.execute("fetch #{block_size} from #{@cursor}")
272
271
 
273
- if @iterate == :each_array
274
- @block = @result.each_row.collect {|row| row }
272
+ @block = if @iterate == :each_array
273
+ @result.each_row.collect { |row| row }
275
274
  else
276
- @block = @result.collect {|row| row }
275
+ @result.collect { |row| row }
277
276
  end
278
277
  end
279
278
 
@@ -295,8 +294,8 @@ module PostgreSQLCursor
295
294
  # This is a value between 0.1 and 1.0 (PostgreSQL defaults to 0.1, this library defaults to 1.0)
296
295
  # used to determine the expected fraction (percent) of result rows returned the the caller.
297
296
  # This value determines the access path by the query planner.
298
- def set_cursor_tuple_fraction(frac=1.0)
299
- @cursor_tuple_fraction ||= @options.fetch(:fraction) { 1.0 }
297
+ def set_cursor_tuple_fraction(frac = 1.0)
298
+ @cursor_tuple_fraction ||= @options.fetch(:fraction, 1.0)
300
299
  return @cursor_tuple_fraction if frac == @cursor_tuple_fraction
301
300
  @cursor_tuple_fraction = frac
302
301
  @result = @connection.execute("set cursor_tuple_fraction to #{frac}")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PostgresqlCursor
4
- VERSION = '0.6.4'
4
+ VERSION = "0.6.5"
5
5
  end
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('lib', __dir__)
3
+ lib = File.expand_path("lib", __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'postgresql_cursor/version'
5
+ require "postgresql_cursor/version"
6
6
 
7
7
  Gem::Specification.new do |spec|
8
- spec.name = 'postgresql_cursor'
9
- spec.version = PostgresqlCursor::VERSION
10
- spec.authors = ['Allen Fair']
11
- spec.email = ['allen.fair@gmail.com']
12
- spec.summary = <<-SUMMARY
8
+ spec.name = "postgresql_cursor"
9
+ spec.version = PostgresqlCursor::VERSION
10
+ spec.authors = ["Allen Fair"]
11
+ spec.email = ["allen.fair@gmail.com"]
12
+ spec.summary = <<-SUMMARY
13
13
  ActiveRecord PostgreSQL Adapter extension for using a cursor to return a
14
14
  large result set
15
15
  SUMMARY
@@ -20,25 +20,25 @@ Gem::Specification.new do |spec|
20
20
  rows in 'chunks' (default of 1_000 rows), buffers them, and returns the rows
21
21
  one at a time.
22
22
  DESCRIPTION
23
- spec.homepage = 'http://github.com/afair/postgresql_cursor'
24
- spec.license = 'MIT'
23
+ spec.homepage = "http://github.com/afair/postgresql_cursor"
24
+ spec.license = "MIT"
25
25
 
26
- spec.files = `git ls-files -z`.split("\x0")
27
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
28
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
29
- spec.require_paths = ['lib']
26
+ spec.files = `git ls-files -z`.split("\x0")
27
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
30
29
 
31
30
  # Remove this for jruby which should use 'activerecord-jdbcpostgresql-adapter'
32
31
  # spec.add_dependency 'pg'
33
32
 
34
- spec.add_dependency 'activerecord', '>= 3.1.0'
33
+ spec.add_dependency "activerecord", ">= 7.0.0"
35
34
  # spec.add_dependency 'activerecord', '~> 3.1.0'
36
35
  # spec.add_dependency 'activerecord', '~> 4.1.0'
37
36
  # spec.add_dependency 'activerecord', '~> 5.0.0'
38
37
  # spec.add_dependency 'activerecord', '~> 6.0.0'
39
38
 
40
- spec.add_development_dependency 'irb'
41
- spec.add_development_dependency 'minitest'
42
- spec.add_development_dependency 'pg'
43
- spec.add_development_dependency 'rake'
39
+ spec.add_development_dependency "irb"
40
+ spec.add_development_dependency "minitest"
41
+ spec.add_development_dependency "pg"
42
+ spec.add_development_dependency "rake"
43
+ spec.add_development_dependency "appraisal"
44
44
  end
data/test/helper.rb CHANGED
@@ -10,6 +10,8 @@ ActiveRecord::Base.establish_connection(adapter: 'postgresql',
10
10
  username: ENV['TEST_USER'] || ENV['USER'] || 'postgresql_cursor')
11
11
 
12
12
  class Product < ActiveRecord::Base
13
+ has_many :prices
14
+
13
15
  # create table records (id serial primary key);
14
16
  def self.generate(max=1_000)
15
17
  max.times do |i|
@@ -18,5 +20,9 @@ class Product < ActiveRecord::Base
18
20
  end
19
21
  end
20
22
 
23
+ class Price < ActiveRecord::Base
24
+ belongs_to :product
25
+ end
26
+
21
27
  Product.destroy_all
22
28
  Product.generate(1000)
@@ -3,16 +3,15 @@
3
3
  # rake setup
4
4
  # or create the database manually if your environment doesn't permit
5
5
  ################################################################################
6
- require_relative 'helper'
7
- require 'minitest/autorun'
8
- require 'minitest/pride'
6
+ require_relative "helper"
7
+ require "minitest/autorun"
8
+ require "minitest/pride"
9
9
 
10
10
  class TestPostgresqlCursor < Minitest::Test
11
-
12
11
  def test_each
13
12
  c = PostgreSQLCursor::Cursor.new("select * from products order by 1")
14
13
  nn = 0
15
- n = c.each { nn += 1}
14
+ n = c.each { nn += 1 }
16
15
  assert_equal nn, n
17
16
  end
18
17
 
@@ -29,22 +28,22 @@ class TestPostgresqlCursor < Minitest::Test
29
28
  end
30
29
 
31
30
  def test_each_while_until
32
- c = PostgreSQLCursor::Cursor.new("select * from products order by 1", until:true)
33
- n = c.each { |r| r['id'].to_i > 100 }
31
+ c = PostgreSQLCursor::Cursor.new("select * from products order by 1", until: true)
32
+ n = c.each { |r| r["id"].to_i > 100 }
34
33
  assert_equal 101, n
35
34
 
36
- c = PostgreSQLCursor::Cursor.new("select * from products order by 1", while:true)
37
- n = c.each { |r| r['id'].to_i < 100 }
35
+ c = PostgreSQLCursor::Cursor.new("select * from products order by 1", while: true)
36
+ n = c.each { |r| r["id"].to_i < 100 }
38
37
  assert_equal 100, n
39
38
  end
40
39
 
41
40
  def test_each_batch_while_until
42
41
  c = PostgreSQLCursor::Cursor.new("select * from products order by id asc", until: true, block_size: 50)
43
- n = c.each_batch { |b| b.last['id'].to_i > 100 }
42
+ n = c.each_batch { |b| b.last["id"].to_i > 100 }
44
43
  assert_equal 3, n
45
44
 
46
45
  c = PostgreSQLCursor::Cursor.new("select * from products order by id asc", while: true, block_size: 50)
47
- n = c.each_batch { |b| b.last['id'].to_i < 100 }
46
+ n = c.each_batch { |b| b.last["id"].to_i < 100 }
48
47
  assert_equal 2, n
49
48
  end
50
49
 
@@ -68,20 +67,26 @@ class TestPostgresqlCursor < Minitest::Test
68
67
 
69
68
  def test_relation
70
69
  nn = 0
71
- Product.where("id>0").each_row {|r| nn += 1 }
70
+ Product.where("id>0").each_row { |r| nn += 1 }
72
71
  assert_equal 1000, nn
73
72
  end
74
73
 
75
74
  def test_relation_batch
76
75
  nn = 0
77
76
  row = nil
78
- Product.where("id>0").each_row_batch(block_size: 100) { |b| row = b.last; nn += 1 }
77
+ Product.where("id>0").each_row_batch(block_size: 100) { |b|
78
+ row = b.last
79
+ nn += 1
80
+ }
79
81
  assert_equal 10, nn
80
82
  assert_equal Hash, row.class
81
83
 
82
84
  nn = 0
83
85
  row = nil
84
- Product.where("id>0").each_instance_batch(block_size: 100) { |b| row = b.last; nn += 1 }
86
+ Product.where("id>0").each_instance_batch(block_size: 100) { |b|
87
+ row = b.last
88
+ nn += 1
89
+ }
85
90
  assert_equal 10, nn
86
91
  assert_equal Product, row.class
87
92
  end
@@ -89,12 +94,18 @@ class TestPostgresqlCursor < Minitest::Test
89
94
  def test_activerecord
90
95
  nn = 0
91
96
  row = nil
92
- Product.each_row_by_sql("select * from products") {|r| row = r; nn += 1 }
97
+ Product.each_row_by_sql("select * from products") { |r|
98
+ row = r
99
+ nn += 1
100
+ }
93
101
  assert_equal 1000, nn
94
102
  assert_equal Hash, row.class
95
103
 
96
104
  nn = 0
97
- Product.each_instance_by_sql("select * from products") {|r| row = r; nn += 1 }
105
+ Product.each_instance_by_sql("select * from products") { |r|
106
+ row = r
107
+ nn += 1
108
+ }
98
109
  assert_equal 1000, nn
99
110
  assert_equal Product, row.class
100
111
  end
@@ -102,32 +113,52 @@ class TestPostgresqlCursor < Minitest::Test
102
113
  def test_activerecord_batch
103
114
  nn = 0
104
115
  row = nil
105
- Product.each_row_batch_by_sql("select * from products", block_size: 100) { |b| row = b.last; nn += 1 }
116
+ Product.each_row_batch_by_sql("select * from products", block_size: 100) { |b|
117
+ row = b.last
118
+ nn += 1
119
+ }
106
120
  assert_equal 10, nn
107
121
  assert_equal Hash, row.class
108
122
 
109
123
  nn = 0
110
- Product.each_instance_batch_by_sql("select * from products", block_size: 100) { |b| row = b.last; nn += 1 }
124
+ Product.each_instance_batch_by_sql("select * from products", block_size: 100) { |b|
125
+ row = b.last
126
+ nn += 1
127
+ }
111
128
  assert_equal 10, nn
112
129
  assert_equal Product, row.class
113
130
  end
114
131
 
115
132
  def test_exception
116
- begin
117
- Product.each_row_by_sql("select * from products") do |r|
118
- raise "Oops"
119
- end
120
- rescue Exception => e
121
- assert_equal e.message, 'Oops'
133
+ Product.each_row_by_sql("select * from products") do |r|
134
+ raise "Oops"
122
135
  end
136
+ rescue => e
137
+ assert_equal e.message, "Oops"
123
138
  end
124
139
 
125
140
  def test_batch_exception
126
141
  Product.each_row_batch_by_sql("select * from products") do |r|
127
- raise 'Oops'
142
+ raise "Oops"
143
+ end
144
+ rescue => e
145
+ assert_equal e.message, "Oops"
146
+ end
147
+
148
+ def test_exception_in_failed_transaction
149
+ Product.each_row_by_sql("select * from products") do |r|
150
+ Product.connection.execute("select kaboom")
151
+ end
152
+ rescue => e
153
+ assert_match(/PG::InFailedSqlTransaction/, e.message)
154
+ end
155
+
156
+ def test_batch_exception_in_failed_transaction
157
+ Product.each_row_batch_by_sql("select * from products") do |r|
158
+ Product.connection.execute("select kaboom")
128
159
  end
129
160
  rescue => e
130
- assert_equal e.message, 'Oops'
161
+ assert_match(/PG::InFailedSqlTransaction/, e.message)
131
162
  end
132
163
 
133
164
  def test_cursor
@@ -144,11 +175,11 @@ class TestPostgresqlCursor < Minitest::Test
144
175
  def test_batched_cursor
145
176
  cursor = Product.all.each_row_batch(block_size: 100)
146
177
  assert cursor.respond_to?(:each)
147
- b = cursor.map { |batch| batch.map { |r| r['id'] } }
178
+ b = cursor.map { |batch| batch.map { |r| r["id"] } }
148
179
  assert_equal 10, b.size
149
180
  cursor = Product.each_row_batch_by_sql("select * from products", block_size: 100)
150
181
  assert cursor.respond_to?(:each)
151
- b = cursor.map { |batch| batch.map { |r| r['id'] } }
182
+ b = cursor.map { |batch| batch.map { |r| r["id"] } }
152
183
  assert_equal 10, b.size
153
184
  end
154
185
 
@@ -162,9 +193,9 @@ class TestPostgresqlCursor < Minitest::Test
162
193
 
163
194
  def test_with_hold
164
195
  items = 0
165
- Product.where("id < 4") .each_instance(with_hold: true, block_size:1) do |row|
196
+ Product.where("id < 4").each_instance(with_hold: true, block_size: 1) do |row|
166
197
  Product.transaction do
167
- row.update(data:Time.now.to_f.to_s)
198
+ row.update(data: Time.now.to_f.to_s)
168
199
  items += 1
169
200
  end
170
201
  end
@@ -173,22 +204,25 @@ class TestPostgresqlCursor < Minitest::Test
173
204
 
174
205
  def test_fetch_symbolize_keys
175
206
  Product.transaction do
176
- #cursor = PostgreSQLCursor::Cursor.new("select * from products order by 1")
207
+ # cursor = PostgreSQLCursor::Cursor.new("select * from products order by 1")
177
208
  cursor = Product.all.each_row
178
209
  r = cursor.fetch
179
210
  assert r.has_key?("id")
180
- r = cursor.fetch(symbolize_keys:true)
211
+ r = cursor.fetch(symbolize_keys: true)
181
212
  assert r.has_key?(:id)
182
213
  cursor.close
183
214
  end
184
215
  end
185
216
 
186
217
  def test_bad_sql
187
- begin
188
- ActiveRecord::Base.each_row_by_sql('select * from bad_table') { }
189
- raise "Did Not Raise Expected Exception"
190
- rescue Exception => e
191
- assert_match(/bad_table/, e.message)
192
- end
218
+ ActiveRecord::Base.each_row_by_sql("select * from bad_table") {}
219
+ raise "Did Not Raise Expected Exception"
220
+ rescue => e
221
+ assert_match(/bad_table/, e.message)
222
+ end
223
+
224
+ def test_relation_association_is_not_loaded
225
+ cursor = Product.first.prices.each_instance
226
+ refute cursor.instance_variable_get(:@type).loaded?
193
227
  end
194
228
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: postgresql_cursor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Allen Fair
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-03 00:00:00.000000000 Z
11
+ date: 2022-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 3.1.0
19
+ version: 7.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 3.1.0
26
+ version: 7.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: irb
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: appraisal
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  description: |2
84
98
  PostgreSQL Cursor is an extension to the ActiveRecord PostgreSQLAdapter for
85
99
  very large result sets. It provides a cursor open/fetch/close interface to
@@ -94,11 +108,15 @@ extra_rdoc_files: []
94
108
  files:
95
109
  - ".document"
96
110
  - ".gitignore"
111
+ - ".travis.yml"
112
+ - Appraisals
97
113
  - Gemfile
98
- - Gemfile.lock
99
114
  - LICENSE
100
115
  - README.md
101
116
  - Rakefile
117
+ - gemfiles/activerecord_4.gemfile
118
+ - gemfiles/activerecord_5.gemfile
119
+ - gemfiles/activerecord_6.gemfile
102
120
  - lib/postgresql_cursor.rb
103
121
  - lib/postgresql_cursor/active_record/connection_adapters/postgresql_type_map.rb
104
122
  - lib/postgresql_cursor/active_record/relation/cursor_iterators.rb
@@ -116,7 +134,7 @@ homepage: http://github.com/afair/postgresql_cursor
116
134
  licenses:
117
135
  - MIT
118
136
  metadata: {}
119
- post_install_message:
137
+ post_install_message:
120
138
  rdoc_options: []
121
139
  require_paths:
122
140
  - lib
@@ -131,11 +149,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
149
  - !ruby/object:Gem::Version
132
150
  version: '0'
133
151
  requirements: []
134
- rubygems_version: 3.0.6
135
- signing_key:
152
+ rubygems_version: 3.3.7
153
+ signing_key:
136
154
  specification_version: 4
137
155
  summary: ActiveRecord PostgreSQL Adapter extension for using a cursor to return a
138
156
  large result set
139
- test_files:
140
- - test/helper.rb
141
- - test/test_postgresql_cursor.rb
157
+ test_files: []
data/Gemfile.lock DELETED
@@ -1,44 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- postgresql_cursor (0.6.4)
5
- activerecord (>= 3.1.0)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activemodel (6.0.0)
11
- activesupport (= 6.0.0)
12
- activerecord (6.0.0)
13
- activemodel (= 6.0.0)
14
- activesupport (= 6.0.0)
15
- activesupport (6.0.0)
16
- concurrent-ruby (~> 1.0, >= 1.0.2)
17
- i18n (>= 0.7, < 2)
18
- minitest (~> 5.1)
19
- tzinfo (~> 1.1)
20
- zeitwerk (~> 2.1, >= 2.1.8)
21
- concurrent-ruby (1.1.5)
22
- i18n (1.6.0)
23
- concurrent-ruby (~> 1.0)
24
- irb (1.0.0)
25
- minitest (5.12.0)
26
- pg (1.1.4)
27
- rake (13.0.0)
28
- thread_safe (0.3.6)
29
- tzinfo (1.2.5)
30
- thread_safe (~> 0.1)
31
- zeitwerk (2.1.10)
32
-
33
- PLATFORMS
34
- ruby
35
-
36
- DEPENDENCIES
37
- irb
38
- minitest
39
- pg
40
- postgresql_cursor!
41
- rake
42
-
43
- BUNDLED WITH
44
- 1.17.3