lib/rubyrep/connection_extenders/postgresql_extender.rb in rubyrep-1.0.1 vs lib/rubyrep/connection_extenders/postgresql_extender.rb in rubyrep-1.0.2
- old
+ new
@@ -1,36 +1,7 @@
require 'time'
-# A cursor to iterate over the records returned by select_cursor.
-# Only one row is kept in memory at a time.
-class PGresult
- # Returns true if there are more rows to read.
- def next?
- @current_row_num ||= 0
- @num_rows ||= self.ntuples()
- @current_row_num < @num_rows
- end
-
- # Returns the row as a column => value hash and moves the cursor to the next row.
- def next_row
- raise("no more rows available") unless next?
- row = {}
- @fields ||= self.fields
- @fields.each_with_index do |field, field_index|
- if self.getisnull(@current_row_num, field_index)
- value = nil
- else
- value = self.getvalue @current_row_num, field_index
- end
-
- row[@fields[field_index]] = value
- end
- @current_row_num += 1
- row
- end
-end
-
# Hack:
# For some reasons these methods were removed in Rails 2.2.2, thus breaking
# the binary and multi-lingual data loading.
# So here they are again.
module ActiveRecord
@@ -108,86 +79,13 @@
end
module RR
module ConnectionExtenders
- # Fetches results from a PostgreSQL cursor object.
- class PostgreSQLFetcher
-
- # The current database connection
- attr_accessor :connection
-
- # Name of the cursor from which to fetch
- attr_accessor :cursor_name
-
- # Number of rows to be read at once
- attr_accessor :row_buffer_size
-
- # Creates a new fetcher.
- # * +connection+: the current database connection
- # * +cursor_name+: name of the cursor from which to fetch
- # * +row_buffer_size+: number of records to read at once
- def initialize(connection, cursor_name, row_buffer_size)
- self.connection = connection
- self.cursor_name = cursor_name
- self.row_buffer_size = row_buffer_size
- end
-
- # Executes the specified SQL staements, returning the result
- def execute(sql)
- connection.execute sql
- end
-
- # Returns true if there are more rows to read.
- def next?
- @current_result ||= execute("FETCH FORWARD #{row_buffer_size} FROM #{cursor_name}")
- @current_result.next?
- end
-
- # Returns the row as a column => value hash and moves the cursor to the next row.
- def next_row
- raise("no more rows available") unless next?
- row = @current_result.next_row
- unless @current_result.next?
- @current_result.clear
- @current_result = nil
- end
- row
- end
-
- # Closes the cursor and frees up all ressources
- def clear
- if @current_result
- @current_result.clear
- @current_result = nil
- end
- result = execute("CLOSE #{cursor_name}")
- result.clear if result
- end
- end
-
# Provides various PostgreSQL specific functionality required by Rubyrep.
module PostgreSQLExtender
RR::ConnectionExtenders.register :postgresql => self
- # Executes the given sql query with the otional name written in the
- # ActiveRecord log file.
- #
- # :+row_buffer_size+ controls how many records are ready into memory at a
- # time. Implemented using the PostgeSQL "DECLARE CURSOR" and "FETCH" constructs.
- # This is necessary as the postgresql driver always reads the
- # complete resultset into memory.
- #
- # Returns the results as a Cursor object supporting
- # * next? - returns true if there are more rows to read
- # * next_row - returns the row as a column => value hash and moves the cursor to the next row
- # * clear - clearing the cursor (making allocated memory available for GC)
- def select_cursor(sql, row_buffer_size = 1000)
- cursor_name = "RR_#{Time.now.to_i}#{rand(1_000_000)}"
- execute("DECLARE #{cursor_name} NO SCROLL CURSOR WITH HOLD FOR " + sql)
- PostgreSQLFetcher.new(self, cursor_name, row_buffer_size)
- end
-
# Returns an ordered list of primary key column names of the given table
def primary_key_names(table)
row = self.select_one(<<-end_sql)
SELECT relname
FROM pg_class