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