= PostgreSQLCursor PostgreSQL Cursor is an extension to the ActiveRecord PostgreSQLAdapter for very large result sets. It provides a cursor open/fetch/close interface to access data without loading all rows into memory, and instead loads the result rows in "chunks" (default of 10_000 rows), buffers them, and returns the rows one at a time. For web pages, an application would not want to process a large amount of data, usually employing a Pagination scheme to present it to the users. Background processes sometimes need to generate a large amount of data, and the ActiveRecord approach to load all data into memory is not the best fit here. Previous solutions employ pagination to fetch each block, then re-running the query for the next "page". This gem avoids re-executing the query by using the PostgreSQL cursors. Like the #find_by_sql method, #find_cursor returns each row as a hash instead of an instantiated model class. The rationale for this is performance, though an option to return instances is available. Julian's benchmarks showed returning instances was a factor of 4 slower than return the hash. ==Installation [sudo] gem install postgresql_cursor This does not require Rails to work, just ActiveRecord < 3.0.0 and the 'pg' gem. ==Usage A Rails/ActiveRecord plugin for the PostgreSQL database adapter that will add cursors to a find_cursor() method to process very large result sets. the *find_cursor* method uses cursors to pull in one data block (of x records) at a time, and return each record as a Hash to a procedural block. When each data block is exhausted, it will fetch the next one. *find_by_sql_with_cursor* takes a custom SQL statement and returns each row. ==Examples Account.find_with_cursor(:conditions=>["status = ?", 'good']).each do |row| puts row.to_json end Account.find_by_sql_with_cursor("select ...", :buffer_size=>1000) do |row| row.process end Account.transaction do cursor = Account.find_with_cursor(...) { |record| record.symbolize_keys } while record = cursor.next do record.process # => {:column=>value, ...} cursor.close if cursor.count > 1000 # Halts loop after 1000 records end end Account.find_with_cursor(...) { |record| record.symbolize_keys }.each do |row| row.process end ==Authors Allen Fair, allen.fair@gmail.com, http://github.com/afair Thank you to: * Iulian Dogariu, http://github.com/iulianu (Fixes) * Julian Mehnle, http://www.mehnle.net (Suggestions) == Note on Patches/Pull Requests * Fork the project. * Make your feature addition or bug fix. * Add tests for it. This is important so I don't break it in a future version unintentionally. * Commit, do not mess with rakefile, version, or history. (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) * Send me a pull request. Bonus points for topic branches. == Copyright Copyright (c) 2010 Allen Fair. See LICENSE for details.