postgresql_cursor 0.5.1 → 0.6.0

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
  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!