activerecord-postgresql-cursors 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/.travis.yml +18 -0
- data/Gemfile +4 -4
- data/MIT-LICENSE +1 -1
- data/README.rdoc +15 -10
- data/Rakefile +3 -1
- data/lib/active_record/postgresql_cursors/cursors.rb +14 -51
- data/lib/active_record/postgresql_cursors/version.rb +1 -1
- data/lib/activerecord-postgresql-cursors.rb +19 -41
- data/test/cursor_tests.rb +24 -35
- data/test/test_helper.rb +20 -26
- metadata +4 -4
- data/lib/active_record/postgresql_cursors/cursors_2.rb +0 -75
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4664b822d630c82374f56ca318d69c736c9ad819
|
4
|
+
data.tar.gz: 7318a45c89b1b76dcb8d79fecb6a499bac1a7a48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '053952a5bcc975b0bc7652e652d0f8029fda8a1dd470adbfc0a081d1095f0a0ec601ee4c633250930b16c7e089e8f175d4753d2580d3bb4c796f6f0ff67671b0'
|
7
|
+
data.tar.gz: a67bb236338e87143a8d0827edbbb847371b132f9fbc7dae09c9b39ce5a02129ece6fa8b809b2b8ca4a9cd989994203935c79a1d0b73a4a705d7cfc5b07afdd3
|
data/.travis.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.5.0
|
4
|
+
- 2.4.3
|
5
|
+
- 2.3.6
|
6
|
+
- 2.2.9
|
7
|
+
- jruby
|
8
|
+
env:
|
9
|
+
- RAILS_VERSION=5.1
|
10
|
+
- RAILS_VERSION=4.2
|
11
|
+
matrix:
|
12
|
+
allow_failures:
|
13
|
+
- rvm: jruby
|
14
|
+
before_install:
|
15
|
+
- gem update --system
|
16
|
+
- gem install bundler
|
17
|
+
before_script:
|
18
|
+
- psql -c 'create database postgresql_cursors_unit_tests;' -U postgres
|
data/Gemfile
CHANGED
@@ -5,12 +5,12 @@ gemspec
|
|
5
5
|
if RUBY_PLATFORM == "java"
|
6
6
|
gem "activerecord-jdbcpostgresql-adapter"
|
7
7
|
else
|
8
|
-
gem "pg"
|
8
|
+
gem "pg", '~> 0.21'
|
9
9
|
end
|
10
10
|
|
11
|
-
gem "rdoc"
|
12
|
-
gem "rake"
|
13
|
-
gem "minitest"
|
11
|
+
gem "rdoc"
|
12
|
+
gem "rake"
|
13
|
+
gem "minitest"
|
14
14
|
gem "minitest-reporters"
|
15
15
|
gem "guard-minitest"
|
16
16
|
gem "simplecov"
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
= ActiveRecord PostgreSQL Cursors
|
2
2
|
|
3
3
|
This extension allows you to loop through record sets using cursors in an
|
4
4
|
Enumerable fashion. This allows you to cut down memory usage by only pulling
|
@@ -9,21 +9,22 @@ To use a cursor, just change the first parameter to an
|
|
9
9
|
ActiveRecord::Base.find to :cursor instead of :first or :all or
|
10
10
|
whatever or use the ActiveRecord::Base.cursor method directly.
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
MyModel.find(:cursor, :conditions => 'some_column = true').each do |r|
|
13
|
+
puts r.inspect
|
14
|
+
end
|
15
15
|
|
16
|
-
|
16
|
+
MyModel.find(:cursor).collect { |r| r.foo / PI }.avg
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
MyModel.cursor.each do |r|
|
19
|
+
puts r.inspect
|
20
|
+
end
|
21
21
|
|
22
22
|
All ActiveRecord::Base.find options are available and should work as-is.
|
23
23
|
As a bonus, the PostgreSQLCursor object returned includes Enumerable,
|
24
24
|
so you can iterate to your heart's content.
|
25
25
|
|
26
|
-
This extension should work
|
26
|
+
This extension should work with Rails 4.2+. For older versions of Rails, try
|
27
|
+
out older versions of the gem.
|
27
28
|
|
28
29
|
At the moment, this is a non-scrollable cursor -- it will only fetch
|
29
30
|
forward. Also note that these cursors are non-updateable/insensitive to
|
@@ -48,5 +49,9 @@ while the first query is just used to build the larger joined query. This
|
|
48
49
|
allows for a brief window between the point that the cursor query is
|
49
50
|
created and the time it is executed. In these cases, it may be wise to wrap
|
50
51
|
your use or cursors in your own transaction to ensure that changes made to
|
51
|
-
the underlying data don't interfere with your cursor's
|
52
|
+
the underlying data don't interfere with your cursor's visibility.
|
52
53
|
|
54
|
+
== License
|
55
|
+
|
56
|
+
This gem is licensed under an MIT-style license. See the +MIT-LICENSE+ file for
|
57
|
+
details.
|
data/Rakefile
CHANGED
@@ -13,11 +13,14 @@ version = ActiveRecord::PostgreSQLCursors::VERSION
|
|
13
13
|
|
14
14
|
desc 'Test PostgreSQL extensions'
|
15
15
|
Rake::TestTask.new(:test) do |t|
|
16
|
+
t.libs << "#{File.dirname(__FILE__)}/test"
|
16
17
|
t.test_files = FileList['test/**/*_tests.rb']
|
17
18
|
t.verbose = !!ENV['VERBOSE_TESTS']
|
18
19
|
t.warning = !!ENV['WARNINGS']
|
19
20
|
end
|
20
21
|
|
22
|
+
task :default => :test
|
23
|
+
|
21
24
|
desc 'Build docs'
|
22
25
|
Rake::RDocTask.new do |t|
|
23
26
|
t.title = "ActiveRecord PostgreSQL Cursors #{version}"
|
@@ -25,4 +28,3 @@ Rake::RDocTask.new do |t|
|
|
25
28
|
t.rdoc_dir = 'doc'
|
26
29
|
t.rdoc_files.include('README.rdoc', 'MIT-LICENSE', 'lib/**/*.rb')
|
27
30
|
end
|
28
|
-
|
@@ -3,13 +3,7 @@ module ActiveRecord
|
|
3
3
|
module CursorExtensions
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
|
7
|
-
alias_method_chain :find, :cursors
|
8
|
-
end
|
9
|
-
|
10
|
-
# Override ActiveRecord::Base#find to allow for cursors in
|
11
|
-
# PostgreSQL. To use a cursor, set the first argument of
|
12
|
-
# find to :cursor. A PostgreSQLCursor object will be returned,
|
6
|
+
# Find using cursors. A PostgreSQLCursor object will be returned,
|
13
7
|
# which can then be used as an Enumerable to loop through the
|
14
8
|
# results.
|
15
9
|
#
|
@@ -18,21 +12,18 @@ module ActiveRecord
|
|
18
12
|
# is pretty unlikely to clash if you're using nested cursors.
|
19
13
|
# Alternatively, you can supply a specific cursor name by
|
20
14
|
# supplying a :cursor_name option.
|
21
|
-
def
|
22
|
-
|
15
|
+
def cursor(*args)
|
16
|
+
find_with_cursor('cursor', *args)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def find_with_cursor(*args)
|
23
22
|
options = args.extract_options!
|
24
23
|
cursor_name = options.delete(:cursor_name)
|
25
24
|
find_cursor(cursor_name, options)
|
26
|
-
else
|
27
|
-
find_without_cursors(*args)
|
28
25
|
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def cursor(*args)
|
32
|
-
find_with_cursors('cursor', *args)
|
33
|
-
end
|
34
26
|
|
35
|
-
private
|
36
27
|
# Find method for using cursors. This works just like the regular
|
37
28
|
# ActiveRecord::Base#find_every method, except it returns a
|
38
29
|
# PostgreSQLCursor object that can be used to loop through records.
|
@@ -41,22 +32,15 @@ module ActiveRecord
|
|
41
32
|
raise CursorsNotSupported, "#{connection.class} doesn't support cursors"
|
42
33
|
end
|
43
34
|
|
44
|
-
relation =
|
45
|
-
apply_finder_options(options, silence_deprecation = true)
|
46
|
-
else
|
47
|
-
apply_finder_options(options)
|
48
|
-
end
|
49
|
-
|
35
|
+
relation = merge(options.slice(:readonly, :references, :order, :limit, :joins, :group, :having, :offset, :select, :uniq))
|
50
36
|
including = (relation.eager_load_values + relation.includes_values).uniq
|
51
37
|
|
52
38
|
if including.present?
|
53
|
-
join_dependency =
|
54
|
-
ActiveRecord::Associations::JoinDependency.new(@klass, including, [])
|
55
|
-
else
|
56
|
-
ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, nil)
|
57
|
-
end
|
39
|
+
join_dependency = construct_join_dependency(joins_values)
|
58
40
|
|
59
|
-
|
41
|
+
aliases = join_dependency.aliases
|
42
|
+
join_relation = select(aliases.columns)
|
43
|
+
join_relation = apply_join_dependency(join_relation, join_dependency)
|
60
44
|
|
61
45
|
ActiveRecord::PostgreSQLCursor.new(self, cursor_name, join_relation, join_dependency)
|
62
46
|
else
|
@@ -64,23 +48,6 @@ module ActiveRecord
|
|
64
48
|
end
|
65
49
|
end
|
66
50
|
end
|
67
|
-
|
68
|
-
class PostgreSQLCursor
|
69
|
-
def initialize_with_rails(model, cursor_name, relation, join_dependency = nil)
|
70
|
-
@relation = relation
|
71
|
-
|
72
|
-
query = if ActiveRecord::VERSION::MAJOR >= 4
|
73
|
-
model.connection.unprepared_statement do
|
74
|
-
relation.to_sql
|
75
|
-
end
|
76
|
-
else
|
77
|
-
relation.to_sql
|
78
|
-
end
|
79
|
-
|
80
|
-
initialize_without_rails(model, cursor_name, query, join_dependency)
|
81
|
-
end
|
82
|
-
alias_method_chain :initialize, :rails
|
83
|
-
end
|
84
51
|
end
|
85
52
|
|
86
53
|
class ActiveRecord::Relation
|
@@ -89,10 +56,6 @@ end
|
|
89
56
|
|
90
57
|
class ActiveRecord::Base
|
91
58
|
class << self
|
92
|
-
|
93
|
-
delegate :cursor, :to => :all
|
94
|
-
else
|
95
|
-
delegate :cursor, :to => :scoped
|
96
|
-
end
|
59
|
+
delegate :cursor, to: :all
|
97
60
|
end
|
98
61
|
end
|
@@ -4,37 +4,26 @@ module ActiveRecord
|
|
4
4
|
# absolutely should be in our app.
|
5
5
|
class CursorsNotSupported < ActiveRecordError; end
|
6
6
|
|
7
|
-
module PostgreSQLCursors
|
8
|
-
module JoinDependency
|
9
|
-
# Extra method we can use to clear out a couple of things in
|
10
|
-
# JoinDependency so we can use some of the methods for our
|
11
|
-
# cursors code.
|
12
|
-
def clear_with_cursor
|
13
|
-
@reflections = []
|
14
|
-
@base_records_hash = {}
|
15
|
-
@base_records_in_order = []
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
7
|
# PostgreSQLCursor is an Enumerable class so you can use each, map,
|
21
8
|
# any? and all of those nice Enumerable methods.
|
22
9
|
#
|
23
10
|
# At the moment, cursors aren't scrollable and are fetch forward-only
|
24
11
|
# and read-only.
|
25
|
-
#
|
26
|
-
# This class isn't really meant to be used outside of the
|
27
|
-
# ActiveRecord::Base#find method.
|
28
12
|
class PostgreSQLCursor
|
29
13
|
include Enumerable
|
30
14
|
|
31
|
-
def initialize(model, cursor_name,
|
15
|
+
def initialize(model, cursor_name, relation, join_dependency = nil)
|
32
16
|
@model = model
|
17
|
+
@relation = relation
|
18
|
+
@join_dependency = join_dependency
|
19
|
+
|
33
20
|
@cursor_name = if cursor_name
|
34
21
|
@model.connection.quote_table_name(cursor_name.gsub(/"/, '\"'))
|
35
22
|
end
|
36
|
-
|
37
|
-
@
|
23
|
+
|
24
|
+
@query = model.connection.unprepared_statement do
|
25
|
+
relation.to_sql
|
26
|
+
end
|
38
27
|
end
|
39
28
|
|
40
29
|
def inspect
|
@@ -50,26 +39,28 @@ module ActiveRecord
|
|
50
39
|
if @join_dependency
|
51
40
|
rows = Array.new
|
52
41
|
last_id = nil
|
42
|
+
|
53
43
|
while row = fetch_forward
|
54
|
-
|
44
|
+
instantiated_row = @join_dependency.instantiate([row], @join_dependency.aliases).first
|
45
|
+
|
46
|
+
current_id = instantiated_row[@join_dependency.join_root.primary_key]
|
55
47
|
last_id ||= current_id
|
56
48
|
if last_id == current_id
|
57
49
|
rows << row
|
58
50
|
last_id = current_id
|
59
51
|
else
|
60
|
-
yield @join_dependency.instantiate(rows).first
|
61
|
-
@join_dependency.clear_with_cursor
|
52
|
+
yield @join_dependency.instantiate(rows, @join_dependency.aliases).first
|
62
53
|
rows = [ row ]
|
63
54
|
end
|
64
55
|
last_id = current_id
|
65
56
|
end
|
66
57
|
|
67
58
|
if !rows.empty?
|
68
|
-
yield @join_dependency.instantiate(rows).first
|
59
|
+
yield @join_dependency.instantiate(rows, @join_dependency.aliases).first
|
69
60
|
end
|
70
61
|
else
|
71
62
|
while row = fetch_forward
|
72
|
-
yield row
|
63
|
+
yield @model.instantiate(row)
|
73
64
|
end
|
74
65
|
end
|
75
66
|
ensure
|
@@ -80,12 +71,13 @@ module ActiveRecord
|
|
80
71
|
end
|
81
72
|
|
82
73
|
private
|
74
|
+
|
83
75
|
def cursor_name
|
84
|
-
@cursor_name ||= "cursor_#{(rand *
|
76
|
+
@cursor_name ||= "cursor_#{(rand * 1_000_000).ceil}"
|
85
77
|
end
|
86
78
|
|
87
79
|
def fetch_forward #:nodoc:
|
88
|
-
@
|
80
|
+
@relation.connection.select_all(%{FETCH FORWARD FROM #{cursor_name}}).first
|
89
81
|
end
|
90
82
|
|
91
83
|
def declare_cursor #:nodoc:
|
@@ -98,18 +90,4 @@ module ActiveRecord
|
|
98
90
|
end
|
99
91
|
end
|
100
92
|
|
101
|
-
|
102
|
-
class ActiveRecord::Associations::JoinDependency
|
103
|
-
include ActiveRecord::PostgreSQLCursors::JoinDependency
|
104
|
-
end
|
105
|
-
else
|
106
|
-
class ActiveRecord::Associations::ClassMethods::JoinDependency
|
107
|
-
include ActiveRecord::PostgreSQLCursors::JoinDependency
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
if ActiveRecord::VERSION::MAJOR >= 3
|
112
|
-
require File.join(File.dirname(__FILE__), *%w{ active_record postgresql_cursors cursors })
|
113
|
-
else
|
114
|
-
require File.join(File.dirname(__FILE__), *%w{ active_record postgresql_cursors cursors_2 })
|
115
|
-
end
|
93
|
+
require File.join(File.dirname(__FILE__), *%w{ active_record postgresql_cursors cursors })
|
data/test/cursor_tests.rb
CHANGED
@@ -1,20 +1,11 @@
|
|
1
1
|
|
2
|
-
$: << File.dirname(__FILE__)
|
3
2
|
require 'test_helper'
|
4
3
|
|
5
|
-
class PostgreSQLCursorTests <
|
4
|
+
class PostgreSQLCursorTests < Minitest::Test
|
6
5
|
include PostgreSQLCursorTestHelper
|
7
6
|
|
8
|
-
def test_find_cursor
|
9
|
-
cursor = Foo.find(:cursor, :order => 'id')
|
10
|
-
|
11
|
-
assert(cursor.is_a?(ActiveRecord::PostgreSQLCursor))
|
12
|
-
|
13
|
-
assert_equal(%w{ one two three four five }, cursor.collect(&:name))
|
14
|
-
end
|
15
|
-
|
16
7
|
def test_cursor_scoped
|
17
|
-
cursor = Foo.cursor(:
|
8
|
+
cursor = Foo.cursor(order: 'id')
|
18
9
|
|
19
10
|
assert(cursor.is_a?(ActiveRecord::PostgreSQLCursor))
|
20
11
|
|
@@ -22,7 +13,7 @@ class PostgreSQLCursorTests < MiniTest::Unit::TestCase
|
|
22
13
|
end
|
23
14
|
|
24
15
|
def test_cursor_while_updating
|
25
|
-
cursor = Foo.cursor(:
|
16
|
+
cursor = Foo.cursor(order: 'id')
|
26
17
|
|
27
18
|
cursor.each do |row|
|
28
19
|
row.name = "#{row.name}_updated"
|
@@ -33,7 +24,7 @@ class PostgreSQLCursorTests < MiniTest::Unit::TestCase
|
|
33
24
|
end
|
34
25
|
|
35
26
|
def test_with_associations
|
36
|
-
cursor = Foo.cursor(:
|
27
|
+
cursor = Foo.cursor(order: 'id')
|
37
28
|
|
38
29
|
cursor.each do |row|
|
39
30
|
assert(row.is_a?(Foo))
|
@@ -44,7 +35,7 @@ class PostgreSQLCursorTests < MiniTest::Unit::TestCase
|
|
44
35
|
end
|
45
36
|
|
46
37
|
def test_with_associations_eager_loading
|
47
|
-
cursor = Foo.cursor(:
|
38
|
+
cursor = Foo.cursor(order: 'foos.id', include: :bars)
|
48
39
|
|
49
40
|
cursor.each do |row|
|
50
41
|
assert(row.is_a?(Foo))
|
@@ -55,7 +46,7 @@ class PostgreSQLCursorTests < MiniTest::Unit::TestCase
|
|
55
46
|
end
|
56
47
|
|
57
48
|
def test_nested_cursors
|
58
|
-
cursor = Foo.cursor(:
|
49
|
+
cursor = Foo.cursor(order: 'foos.id')
|
59
50
|
|
60
51
|
cursor.each do |row|
|
61
52
|
bars_cursor = row.bars.cursor
|
@@ -67,30 +58,28 @@ class PostgreSQLCursorTests < MiniTest::Unit::TestCase
|
|
67
58
|
end
|
68
59
|
end
|
69
60
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
assert(bar.is_a?(Bar))
|
80
|
-
end
|
61
|
+
def test_as_relation
|
62
|
+
cursor = Foo.order('foos.id').where('foos.id >= 3').cursor
|
63
|
+
assert_equal(3, cursor.to_a.length)
|
64
|
+
|
65
|
+
cursor.each do |row|
|
66
|
+
assert(row.is_a?(Foo))
|
67
|
+
assert_equal(2, row.bars.length)
|
68
|
+
row.bars.each do |bar|
|
69
|
+
assert(bar.is_a?(Bar))
|
81
70
|
end
|
82
71
|
end
|
72
|
+
end
|
83
73
|
|
84
|
-
|
85
|
-
|
86
|
-
|
74
|
+
def test_as_relation_with_associations
|
75
|
+
cursor = Foo.includes(:bars).order('foos.id').where('foos.id >= 3').cursor
|
76
|
+
assert_equal(3, cursor.to_a.length)
|
87
77
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
end
|
78
|
+
cursor.each do |row|
|
79
|
+
assert(row.is_a?(Foo))
|
80
|
+
assert_equal(2, row.bars.length)
|
81
|
+
row.bars.each do |bar|
|
82
|
+
assert(bar.is_a?(Bar))
|
94
83
|
end
|
95
84
|
end
|
96
85
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
require 'simplecov'
|
2
|
+
require 'simplecov'
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
4
|
+
SimpleCov.command_name('Unit Tests')
|
5
|
+
SimpleCov.start do
|
6
|
+
add_filter '/test/'
|
9
7
|
end
|
10
8
|
|
11
9
|
require 'rubygems'
|
@@ -14,14 +12,11 @@ require 'active_support/core_ext/module/aliasing'
|
|
14
12
|
require 'active_record'
|
15
13
|
require 'logger'
|
16
14
|
require 'minitest/autorun'
|
17
|
-
|
18
|
-
if RUBY_VERSION >= '1.9'
|
19
|
-
require 'minitest/reporters'
|
20
|
-
end
|
15
|
+
require 'minitest/reporters'
|
21
16
|
|
22
17
|
require File.join(File.dirname(__FILE__), *%w{ .. lib activerecord-postgresql-cursors })
|
23
18
|
|
24
|
-
ActiveRecord::Base.logger = Logger.new(
|
19
|
+
ActiveRecord::Base.logger = Logger.new('debug.log') if ENV['ENABLE_LOGGER']
|
25
20
|
ActiveRecord::Base.configurations = {
|
26
21
|
'arunit' => {}
|
27
22
|
}
|
@@ -32,12 +27,12 @@ ActiveRecord::Base.configurations = {
|
|
32
27
|
}.each do |file|
|
33
28
|
file = File.join('test', file)
|
34
29
|
|
35
|
-
next unless File.
|
30
|
+
next unless File.exist?(file)
|
36
31
|
|
37
|
-
configuration = YAML.
|
32
|
+
configuration = YAML.safe_load(File.read(file))
|
38
33
|
|
39
34
|
if configuration['arunit']
|
40
|
-
ActiveRecord::Base.configurations['arunit']
|
35
|
+
ActiveRecord::Base.configurations['arunit'] = configuration['arunit']
|
41
36
|
end
|
42
37
|
|
43
38
|
if defined?(JRUBY_VERSION) && configuration['jdbc']
|
@@ -45,29 +40,31 @@ ActiveRecord::Base.configurations = {
|
|
45
40
|
end
|
46
41
|
end
|
47
42
|
|
48
|
-
ActiveRecord::Base.establish_connection
|
43
|
+
ActiveRecord::Base.establish_connection :arunit
|
49
44
|
ARBC = ActiveRecord::Base.connection
|
50
45
|
|
51
46
|
puts "Ruby version #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} - #{RbConfig::CONFIG['RUBY_INSTALL_NAME']}"
|
52
|
-
puts "Testing against ActiveRecord #{Gem.loaded_specs['activerecord'].version
|
53
|
-
|
47
|
+
puts "Testing against ActiveRecord #{Gem.loaded_specs['activerecord'].version}"
|
48
|
+
|
49
|
+
postgresql_version = ARBC.select_rows('SELECT version()').flatten.to_s
|
50
|
+
|
51
|
+
if postgresql_version
|
54
52
|
puts "PostgreSQL info from version(): #{postgresql_version}"
|
55
53
|
end
|
56
54
|
|
57
|
-
|
55
|
+
unless ARBC.data_source_exists?('foos')
|
58
56
|
ActiveRecord::Migration.create_table(:foos) do |t|
|
59
57
|
t.text :name
|
60
58
|
end
|
61
59
|
end
|
62
60
|
|
63
|
-
|
61
|
+
unless ARBC.data_source_exists?('bars')
|
64
62
|
ActiveRecord::Migration.create_table(:bars) do |t|
|
65
63
|
t.text :name
|
66
64
|
t.integer :foo_id
|
67
65
|
end
|
68
66
|
end
|
69
67
|
|
70
|
-
|
71
68
|
class Bar < ActiveRecord::Base
|
72
69
|
belongs_to :foo
|
73
70
|
end
|
@@ -84,18 +81,15 @@ module PostgreSQLCursorTestHelper
|
|
84
81
|
ARBC.execute(%{select setval('bars_id_seq', 1, false)})
|
85
82
|
|
86
83
|
%w{ six seven eight nine ten eleven twelve thirteen fourteen fifteen }.each do |name|
|
87
|
-
Bar.create(:
|
84
|
+
Bar.create(name: name)
|
88
85
|
end
|
89
86
|
|
90
87
|
%w{ one two three four five }.each_with_index do |name, i|
|
91
|
-
foo = Foo.new(:
|
88
|
+
foo = Foo.new(name: name)
|
92
89
|
foo.bar_ids = [ i + 1, i + 6 ]
|
93
90
|
foo.save
|
94
91
|
end
|
95
92
|
end
|
96
93
|
end
|
97
94
|
|
98
|
-
|
99
|
-
MiniTest::Reporters.use!(MiniTest::Reporters::SpecReporter.new)
|
100
|
-
end
|
101
|
-
|
95
|
+
Minitest::Reporters.use!(MiniTest::Reporters::SpecReporter.new)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-postgresql-cursors
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- J Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -32,6 +32,7 @@ extra_rdoc_files:
|
|
32
32
|
- README.rdoc
|
33
33
|
files:
|
34
34
|
- ".gitignore"
|
35
|
+
- ".travis.yml"
|
35
36
|
- Gemfile
|
36
37
|
- Guardfile
|
37
38
|
- MIT-LICENSE
|
@@ -39,7 +40,6 @@ files:
|
|
39
40
|
- Rakefile
|
40
41
|
- activerecord-postgresql-cursors.gemspec
|
41
42
|
- lib/active_record/postgresql_cursors/cursors.rb
|
42
|
-
- lib/active_record/postgresql_cursors/cursors_2.rb
|
43
43
|
- lib/active_record/postgresql_cursors/version.rb
|
44
44
|
- lib/activerecord-postgresql-cursors.rb
|
45
45
|
- test/cursor_tests.rb
|
@@ -65,7 +65,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
65
|
version: '0'
|
66
66
|
requirements: []
|
67
67
|
rubyforge_project:
|
68
|
-
rubygems_version: 2.
|
68
|
+
rubygems_version: 2.6.13
|
69
69
|
signing_key:
|
70
70
|
specification_version: 4
|
71
71
|
summary: Provides some support for PostgreSQL cursors in ActiveRecord.
|
@@ -1,75 +0,0 @@
|
|
1
|
-
|
2
|
-
module ActiveRecord
|
3
|
-
class Base
|
4
|
-
class << self
|
5
|
-
# Override ActiveRecord::Base#find to allow for cursors in
|
6
|
-
# PostgreSQL. To use a cursor, set the first argument of
|
7
|
-
# find to :cursor. A PostgreSQLCursor object will be returned,
|
8
|
-
# which can then be used as an Enumerable to loop through the
|
9
|
-
# results.
|
10
|
-
#
|
11
|
-
# By default, cursor names are generated automatically using
|
12
|
-
# "cursor_#{rand}", where rand is a big ol' random number that
|
13
|
-
# is pretty unlikely to clash if you're using nested cursors.
|
14
|
-
# Alternatively, you can supply a specific cursor name by
|
15
|
-
# supplying a :cursor_name option.
|
16
|
-
def find_with_cursors *args
|
17
|
-
if args.first.to_s == 'cursor'
|
18
|
-
options = args.extract_options!
|
19
|
-
cursor_name = options.delete(:cursor_name)
|
20
|
-
validate_find_options(options)
|
21
|
-
set_readonly_option!(options)
|
22
|
-
find_cursor(cursor_name, options)
|
23
|
-
else
|
24
|
-
find_without_cursors(*args)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
alias_method_chain :find, :cursors
|
28
|
-
|
29
|
-
def cursor(*args)
|
30
|
-
find(:cursor, *args)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
# Find method for using cursors. This works just like the regular
|
36
|
-
# ActiveRecord::Base#find_every method, except it returns a
|
37
|
-
# PostgreSQLCursor object that can be used to loop through records.
|
38
|
-
def self.find_cursor(cursor_name, options)
|
39
|
-
unless connection.is_a? ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
40
|
-
raise CursorsNotSupported, "#{connection.class} doesn't support cursors"
|
41
|
-
end
|
42
|
-
|
43
|
-
catch :invalid_query do
|
44
|
-
if options[:include]
|
45
|
-
join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(self, merge_includes(scope(:find, :include), options[:include]), options[:joins])
|
46
|
-
return ActiveRecord::PostgreSQLCursor.new(
|
47
|
-
self,
|
48
|
-
cursor_name,
|
49
|
-
construct_finder_sql_with_included_associations(
|
50
|
-
options,
|
51
|
-
join_dependency
|
52
|
-
),
|
53
|
-
join_dependency
|
54
|
-
)
|
55
|
-
else
|
56
|
-
return ActiveRecord::PostgreSQLCursor.new(
|
57
|
-
self,
|
58
|
-
cursor_name,
|
59
|
-
construct_finder_sql(
|
60
|
-
options
|
61
|
-
)
|
62
|
-
)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
nil
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
class PostgreSQLCursor
|
70
|
-
def initialize_with_rails_2(model, cursor_name, query, join_dependency = nil)
|
71
|
-
initialize_without_rails_2(model, cursor_name, query, join_dependency)
|
72
|
-
end
|
73
|
-
alias_method_chain :initialize, :rails_2
|
74
|
-
end
|
75
|
-
end
|