postgresql_cursor 0.5.1 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 01a81f4aa5a5a18d0b26ad2bc2ae9d3b7d02dcb5
4
- data.tar.gz: f8b3ca7158110a45ba7f28797a4d0c970f11bdb5
3
+ metadata.gz: 8bd16d1710bfc6796d8410b99d01b17c085118df
4
+ data.tar.gz: 4ad5f707f0c96ddbf85fb57ed2935d7c6e2e1da6
5
5
  SHA512:
6
- metadata.gz: 204072400a16ff6934d82d03b95b3bca16ee047bd2676e00fd799de199e6fb5e6e89dc0935cb3b58fc36279e0957ebe63394c0cfac6e5d7051a434aa0d78045d
7
- data.tar.gz: 1454bea0121abc656677f69150581ee04884717eed3b53bae7097cc555ec23312f5b3469cf74628f21fe16b9df1ab2b07999c678ea7cfa615ee68a8aa35dd749
6
+ metadata.gz: 69547256fbc79ab776b41a05729ead0eb05bc0c6cc94fb2da60a19922376e4ddbd3fa686f76f3ed0bd2e98e35e16a072828fdae0f29f687fc4e14ff0364bd8be
7
+ data.tar.gz: 90e5cda34d77577766143c53b26300696791298ac2c9f20ba09d204e9be443ccafa3c0bbbf70619679e829abaf2734ef271f59991352739dfcab54c63e6050f1
data/.gitignore CHANGED
@@ -22,3 +22,4 @@ rdoc
22
22
  pkg
23
23
 
24
24
  ## PROJECT::SPECIFIC
25
+ Gemfile.lock
@@ -1,33 +1,33 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- postgresql_cursor (0.5.1)
5
- activerecord (>= 3.2.0)
4
+ postgresql_cursor (0.6.0)
5
+ activerecord (>= 3.1.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activemodel (4.1.5)
11
- activesupport (= 4.1.5)
10
+ activemodel (4.2.5.1)
11
+ activesupport (= 4.2.5.1)
12
12
  builder (~> 3.1)
13
- activerecord (4.1.5)
14
- activemodel (= 4.1.5)
15
- activesupport (= 4.1.5)
16
- arel (~> 5.0.0)
17
- activesupport (4.1.5)
18
- i18n (~> 0.6, >= 0.6.9)
13
+ activerecord (4.2.5.1)
14
+ activemodel (= 4.2.5.1)
15
+ activesupport (= 4.2.5.1)
16
+ arel (~> 6.0)
17
+ activesupport (4.2.5.1)
18
+ i18n (~> 0.7)
19
19
  json (~> 1.7, >= 1.7.7)
20
20
  minitest (~> 5.1)
21
- thread_safe (~> 0.1)
21
+ thread_safe (~> 0.3, >= 0.3.4)
22
22
  tzinfo (~> 1.1)
23
- arel (5.0.1.20140414130214)
23
+ arel (6.0.3)
24
24
  builder (3.2.2)
25
- i18n (0.6.11)
26
- json (1.8.1)
27
- minitest (5.3.3)
28
- pg (0.17.1)
29
- rake (10.3.1)
30
- thread_safe (0.3.4)
25
+ i18n (0.7.0)
26
+ json (1.8.3)
27
+ minitest (5.8.4)
28
+ pg (0.18.4)
29
+ rake (10.5.0)
30
+ thread_safe (0.3.5)
31
31
  tzinfo (1.2.2)
32
32
  thread_safe (~> 0.1)
33
33
 
@@ -39,3 +39,6 @@ DEPENDENCIES
39
39
  pg
40
40
  postgresql_cursor!
41
41
  rake
42
+
43
+ BUNDLED WITH
44
+ 1.11.2
data/README.md CHANGED
@@ -13,10 +13,16 @@ set is exhausted. By fetching a smaller chunk of data, this reduces the
13
13
  amount of memory your application uses and prevents the potential crash
14
14
  of running out of memory.
15
15
 
16
- Version 0.5.0 has been refactored to install more smoothly into ActiveRecord.
17
- It supports Rails and ActiveRecord 3.2.x and up.
16
+ This extension is not intended to support the "FOR UPDATE / WHERE
17
+ CURRENT OF" syntax to process and update each row in place. The primary
18
+ goal is to read a large number of rows using buffering.
18
19
 
19
- ##Use Cursors
20
+ Supports Rails/ActiveRecord v3.1 (v3.2 recommended) higher (including
21
+ v5.0) and Ruby 1.9 and higher. Not all features work in ActiveRecord v3.1.
22
+ Support for this gem will only be for officially supported versions of
23
+ ActiveRecord and Ruby; others can try older versions of the gem.
24
+
25
+ ##Using Cursors
20
26
 
21
27
  PostgreSQLCursor was developed to take advantage of PostgreSQL's cursors. Cursors allow the program
22
28
  to declare a cursor to run a given query returning "chunks" of rows to the application program while
@@ -43,6 +49,17 @@ Product.each_row_by_sql("select * from products") { |hash| Product.process(hash)
43
49
  Product.each_instance_by_sql("select * from products") { |product| product.process }
44
50
  ```
45
51
 
52
+ Cursors must be run in a transaction if you need to fetch each row yourself
53
+
54
+ ```ruby
55
+ Product.transaction do
56
+ cursor = Product.all.each_row
57
+ row = cursor.fetch #=> {"id"=>"1"}
58
+ row = cursor.fetch(symbolize_keys:true) #=> {:id =>"2"}
59
+ cursor.close
60
+ end
61
+ ```
62
+
46
63
  All these methods take an options hash to control things more:
47
64
 
48
65
  block_size:n The number of rows to fetch from the database each time (default 1000)
@@ -53,6 +70,7 @@ All these methods take an options hash to control things more:
53
70
  PostgreSQL uses 0.1 (optimize for 10% of result set)
54
71
  This library uses 1.0 (Optimize for 100% of the result set)
55
72
  Do not override this value unless you understand it.
73
+ with_hold:boolean Keep the cursor "open" even after a commit.
56
74
 
57
75
  Notes:
58
76
 
@@ -158,10 +176,22 @@ There are drawbacks with these methods:
158
176
  * The query is rerun for each chunk (1000 rows), starting at the next id sequence.
159
177
  * You cannot use overly complex queries as that will be rerun and incur more overhead.
160
178
 
179
+ ### How it works
180
+
181
+ Under the covers, the library calls the PostgreSQL cursor operations
182
+ with the psuedo-code:
183
+
184
+ SET cursor_tuple_fraction TO 1.0;
185
+ DECLARE cursor_1 CURSOR WITH HOLD FOR select * from widgets;
186
+ loop
187
+ rows = FETCH 100 FROM cursor_1;
188
+ rows.each {|row| yield row}
189
+ until rows.size < 100;
190
+ CLOSE cursor_1;
161
191
 
162
192
  ##Meta
163
193
  ###Author
164
- Allen Fair, [@allenfair](https://twitter/com/allenfair), http://github.com/afair
194
+ Allen Fair, [@allenfair](https://twitter.com/allenfair), http://github.com/afair
165
195
 
166
196
  Thanks to:
167
197
 
@@ -179,6 +209,11 @@ Thanks to:
179
209
  (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
180
210
  * Send me a pull request. Bonus points for topic branches.
181
211
 
212
+ ###Code of Conduct
213
+
214
+ This project adheres to the [Open Code of Conduct](http://todogroup.org/opencodeofconduct/#postgresql_cursor/2016@allenfair.com).
215
+ By participating, you are expected to honor this code.
216
+
182
217
  ###Copyright
183
218
 
184
219
  Copyright (c) 2010-2014 Allen Fair. See (MIT) LICENSE for details.
data/Rakefile CHANGED
@@ -20,5 +20,5 @@ end
20
20
  desc "Setup testing database and table"
21
21
  task :setup do
22
22
  sh %q(createdb postgresql_cursor_test)
23
- sh %Q<echo "create table products ( id serial primary key);" | psql postgresql_cursor_test>
23
+ sh %Q<echo "create table products ( id serial primary key, data varchar);" | psql postgresql_cursor_test>
24
24
  end
@@ -9,6 +9,7 @@ module PostgreSQLCursor
9
9
  # block_size: 1..n - The number of rows to fetch per db block fetch
10
10
  # while: value - Exits loop when block does not return this value.
11
11
  # until: value - Exits loop when block returns this value.
12
+ # with_hold: boolean - Allows the query to remain open across commit points.
12
13
  #
13
14
  # Example:
14
15
  # Post.each_row { |hash| Post.process(hash) }
@@ -41,6 +42,7 @@ module PostgreSQLCursor
41
42
  # block_size: 1..n - The number of rows to fetch per db block fetch
42
43
  # while: value - Exits loop when block does not return this value.
43
44
  # until: value - Exits loop when block returns this value.
45
+ # with_hold: boolean - Allows the query to remain open across commit points.
44
46
  #
45
47
  # Example:
46
48
  # Post.each_row_by_sql("select * from posts") { |hash| Post.process(hash) }
@@ -9,6 +9,7 @@
9
9
  # block_size: 1..n - The number of rows to fetch per db block fetch
10
10
  # while: value - Exits loop when block does not return this value.
11
11
  # until: value - Exits loop when block returns this value.
12
+ # with_hold: boolean - Allows the query to remain open across commit points.
12
13
  #
13
14
  # Exmaples:
14
15
  # PostgreSQLCursor::Cursor.new("select ...").each { |hash| ... }
@@ -30,6 +31,7 @@ module PostgreSQLCursor
30
31
  # fraction: 0.1..1.0 - The cursor_tuple_fraction (default 1.0)
31
32
  # block_size: 1..n - The number of rows to fetch per db block fetch
32
33
  # Defaults to 1000
34
+ # with_hold - Allows the query to remain open across commit points.
33
35
  #
34
36
  # Examples
35
37
  #
@@ -128,7 +130,7 @@ module PostgreSQLCursor
128
130
  rescue Exception => e
129
131
  raise e
130
132
  ensure
131
- close
133
+ close if @block
132
134
  end
133
135
  end
134
136
  @count
@@ -160,16 +162,20 @@ module PostgreSQLCursor
160
162
  def open
161
163
  set_cursor_tuple_fraction
162
164
  @cursor = @@cursor_seq += 1
163
- @result = @connection.execute("declare cursor_#{@cursor} cursor for #{@sql}")
165
+ hold = @options[:with_hold] ? 'with hold ' : ''
166
+ @result = @connection.execute("declare cursor_#{@cursor} cursor #{hold}for #{@sql}")
164
167
  @block = []
165
168
  end
166
169
 
167
170
  # Public: Returns the next row from the cursor, or empty hash if end of results
168
171
  #
169
172
  # Returns a row as a hash of {'colname'=>value,...}
170
- def fetch
173
+ def fetch(options={})
174
+ open unless @block
171
175
  fetch_block if @block.size==0
172
- @block.shift
176
+ row = @block.shift
177
+ row = row.symbolize_keys if row && options[:symbolize_keys]
178
+ row
173
179
  end
174
180
 
175
181
  # Private: Fetches the next block of rows into @block
@@ -1,3 +1,3 @@
1
1
  module PostgresqlCursor
2
- VERSION = "0.5.1"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -18,8 +18,13 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- #spec.add_dependency "pg" # Remove this for jruby, which should specify 'activerecord-jdbcpostgresql-adapter'
22
- spec.add_dependency "activerecord", ">= 3.2.0"
21
+ #spec.add_dependency "pg" # Remove this for jruby, which should specify 'activerecord-jdbcpostgresql-adapter'
22
+ spec.add_dependency "activerecord", ">= 3.1.0"
23
+ #spec.add_dependency "activerecord", "~> 3.1.0"
24
+ # Tests don't run on 4.0.0 since AR/AS have an older version of minitest as a run-time dependency(!) than our tests support
25
+ #spec.add_dependency "activerecord", "~> 4.0.0";# spec.add_dependency "minitest", "~> 4.2.0"
26
+ #spec.add_dependency "activerecord", "~> 4.1.0"
27
+ #spec.add_dependency "activerecord", "~> 5.0.0.beta2"
23
28
 
24
29
  spec.add_development_dependency "pg"
25
30
  spec.add_development_dependency "rake"
@@ -0,0 +1 @@
1
+ Gemfile.lock
@@ -1,7 +1,8 @@
1
1
  # A sample Gemfile
2
2
  source "https://rubygems.org"
3
3
 
4
- gem 'activerecord', '~> 3.2.0'
4
+ gem 'activerecord', '~> 3.1.0'
5
+ #gem 'activerecord', '~> 3.2.0'
5
6
  #gem 'activerecord', '~> 4.0.0'
6
7
  #gem 'activerecord', '~> 4.1.0'
7
8
  #gem 'activerecord', '4.1.2.rc1'
@@ -8,7 +8,7 @@ require 'postgresql_cursor'
8
8
  ActiveRecord::Base.establish_connection(adapter: 'postgresql',
9
9
  database: ENV['TEST_DATABASE'] || 'postgresql_cursor_test',
10
10
  username: ENV['TEST_USER'] || ENV['USER'] || 'postgresql_cursor')
11
-
11
+
12
12
  class Product < ActiveRecord::Base
13
13
  # create table records (id serial primary key);
14
14
  def self.generate(max=1_000)
@@ -78,5 +78,36 @@ class TestPostgresqlCursor < Minitest::Test
78
78
  assert_equal 1000, r.size
79
79
  assert_equal Fixnum, r.first.class
80
80
  end
81
-
81
+
82
+ def test_with_hold
83
+ items = 0
84
+ Product.where("id < 4") .each_instance(with_hold: true, block_size:1) do |row|
85
+ Product.transaction do
86
+ row.update(data:Time.now.to_f.to_s)
87
+ items += 1
88
+ end
89
+ end
90
+ assert_equal 3, items
91
+ end
92
+
93
+ def test_fetch_symbolize_keys
94
+ Product.transaction do
95
+ #cursor = PostgreSQLCursor::Cursor.new("select * from products order by 1")
96
+ cursor = Product.all.each_row
97
+ r = cursor.fetch
98
+ assert r.has_key?("id")
99
+ r = cursor.fetch(symbolize_keys:true)
100
+ assert r.has_key?(:id)
101
+ cursor.close
102
+ end
103
+ end
104
+
105
+ def test_bad_sql
106
+ begin
107
+ ActiveRecord::Base.each_row_by_sql('select * from bad_table') { }
108
+ raise "Did Not Raise Expected Exception"
109
+ rescue Exception => e
110
+ assert_match(/bad_table/, e.message)
111
+ end
112
+ end
82
113
  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.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Allen Fair
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-11 00:00:00.000000000 Z
11
+ date: 2016-02-22 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.2.0
19
+ version: 3.1.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.2.0
26
+ version: 3.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pg
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -83,7 +83,6 @@ files:
83
83
  - LICENSE
84
84
  - README.md
85
85
  - Rakefile
86
- - VERSION
87
86
  - lib/postgresql_cursor.rb
88
87
  - lib/postgresql_cursor/active_record/connection_adapters/postgresql_type_map.rb
89
88
  - lib/postgresql_cursor/active_record/relation/cursor_iterators.rb
@@ -91,8 +90,8 @@ files:
91
90
  - lib/postgresql_cursor/cursor.rb
92
91
  - lib/postgresql_cursor/version.rb
93
92
  - postgresql_cursor.gemspec
93
+ - test-app/.gitignore
94
94
  - test-app/Gemfile
95
- - test-app/Gemfile.lock
96
95
  - test-app/app.rb
97
96
  - test-app/run.sh
98
97
  - test/helper.rb
@@ -117,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
116
  version: '0'
118
117
  requirements: []
119
118
  rubyforge_project:
120
- rubygems_version: 2.2.2
119
+ rubygems_version: 2.5.1
121
120
  signing_key:
122
121
  specification_version: 4
123
122
  summary: ActiveRecord PostgreSQL Adapter extension for using a cursor to return a
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.4.3
@@ -1,34 +0,0 @@
1
- PATH
2
- remote: /Users/allen/src/postgresql_cursor
3
- specs:
4
- postgresql_cursor (0.5.0)
5
- activerecord (>= 3.2.0)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activemodel (3.2.18)
11
- activesupport (= 3.2.18)
12
- builder (~> 3.0.0)
13
- activerecord (3.2.18)
14
- activemodel (= 3.2.18)
15
- activesupport (= 3.2.18)
16
- arel (~> 3.0.2)
17
- tzinfo (~> 0.3.29)
18
- activesupport (3.2.18)
19
- i18n (~> 0.6, >= 0.6.4)
20
- multi_json (~> 1.0)
21
- arel (3.0.3)
22
- builder (3.0.4)
23
- i18n (0.6.9)
24
- multi_json (1.10.1)
25
- pg (0.17.1)
26
- tzinfo (0.3.39)
27
-
28
- PLATFORMS
29
- ruby
30
-
31
- DEPENDENCIES
32
- activerecord (~> 3.2.0)
33
- pg
34
- postgresql_cursor!