From c1fc1af1fc60ea6f0f26ac32f6dcd9427f0fbd2f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 9 Jan 2024 15:30:47 -0800 Subject: [PATCH] Use a factory method to eliminate "results as hash" check "Results as hash" should be set on the database, so we should only need to check it once when we first start the query. This patch pulls result set construction in to a factory method on the database object. Doing this eliminates a "translate to hash" check that is performed on every row fetch. --- lib/sqlite3/database.rb | 13 ++++++++++++- lib/sqlite3/resultset.rb | 8 ++++---- lib/sqlite3/statement.rb | 6 +++--- test/test_integration_resultset.rb | 1 + 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/sqlite3/database.rb b/lib/sqlite3/database.rb index 3dc14161..50b076e9 100644 --- a/lib/sqlite3/database.rb +++ b/lib/sqlite3/database.rb @@ -224,7 +224,7 @@ def execute sql, bind_vars = [], *args, &block prepare(sql) do |stmt| stmt.bind_params(bind_vars) - stmt = ResultSet.new self, stmt + stmt = build_result_set stmt if block stmt.each do |row| @@ -746,6 +746,17 @@ def translate_from_db types, row @type_translator.call types, row end + # Given a statement, return a result set. + # This is not intended for general consumption + # :nodoc: + def build_result_set stmt + if results_as_hash + HashResultSet.new(self, stmt) + else + ResultSet.new(self, stmt) + end + end + private NULL_TRANSLATOR = lambda { |_, row| row } diff --git a/lib/sqlite3/resultset.rb b/lib/sqlite3/resultset.rb index ef01d58b..2682397a 100644 --- a/lib/sqlite3/resultset.rb +++ b/lib/sqlite3/resultset.rb @@ -92,10 +92,6 @@ def eof? # For hashes, the column names are the keys of the hash, and the column # types are accessible via the +types+ property. def next - if @db.results_as_hash - return next_hash - end - row = @stmt.step return nil if @stmt.done? @@ -175,4 +171,8 @@ def next_hash row end end + + class HashResultSet < ResultSet # :nodoc: + alias :next :next_hash + end end diff --git a/lib/sqlite3/statement.rb b/lib/sqlite3/statement.rb index 2ff452be..25a772c0 100644 --- a/lib/sqlite3/statement.rb +++ b/lib/sqlite3/statement.rb @@ -79,12 +79,12 @@ def execute(*bind_vars) reset! if active? || done? bind_params(*bind_vars) unless bind_vars.empty? - @results = ResultSet.new(@connection, self) + results = @connection.build_result_set self step if column_count == 0 - yield @results if block_given? - @results + yield results if block_given? + results end # Execute the statement. If no block was given, this returns an array of diff --git a/test/test_integration_resultset.rb b/test/test_integration_resultset.rb index 28cbaad5..d9c4b200 100644 --- a/test/test_integration_resultset.rb +++ b/test/test_integration_resultset.rb @@ -97,6 +97,7 @@ def test_real_translation def test_next_results_as_hash @db.results_as_hash = true + @result = @stmt.execute @result.reset(1) hash = @result.next assert_equal({"a" => 1, "b" => "foo"},