Skip to content

Commit

Permalink
Remove type translation
Browse files Browse the repository at this point in the history
This has been deprecated for a while, time to remove it.  If users want
to keep the type translation feature, they can upgrade their
applications by implementing a delegate class.
  • Loading branch information
tenderlove committed Jan 10, 2024
1 parent 21db633 commit e1e61f8
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 199 deletions.
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,46 @@ This release drops support for Ruby 2.7. [#453] @flavorjones
### Removed

- Remove `SQLite3::VersionProxy` which has been deprecated since v1.3.2. [#453] @flavorjones
- Remove `SQLite3::Translator` and all related type translation methods.
If you need to do type translation on values returned from the statement object,
please wrap it with a delegate object. Here is an example of using a delegate
class to implement type translation:

```ruby
require "sqlite3"
require "delegate"

db = SQLite3::Database.new(":memory:")

return_value = db.execute_batch2 <<-EOSQL
CREATE TABLE items (id integer PRIMARY KEY AUTOINCREMENT, name string);
INSERT INTO items (name) VALUES ("foo");
INSERT INTO items (name) VALUES ("bar");
EOSQL

class MyTranslator < DelegateClass(SQLite3::Statement)
def step
row = super
return if done?

row.map.with_index do |item, i|
case types[i]
when "integer" # turn all integers to floats
item.to_f
when "string" # add "hello" to all strings
item + "hello"
end
end
end
end

db.prepare("SELECT * FROM items") do |stmt|
stmt = MyTranslator.new(stmt)
while row = stmt.step
p row
end
end
```


## 1.7.0 / 2023-12-27
Expand Down
43 changes: 0 additions & 43 deletions lib/sqlite3/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ def quote(string)
# Other supported +options+:
# - +:strict+: boolean (default false), disallow the use of double-quoted string literals (see https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted)
# - +:results_as_hash+: boolean (default false), return rows as hashes instead of arrays
# - +:type_translation+: boolean (default false), enable type translation
# - +:default_transaction_mode+: one of +:deferred+ (default), +:immediate+, or +:exclusive+. If a mode is not specified in a call to #transaction, this will be the default transaction mode.
#
def initialize file, options = {}, zvfs = nil
Expand Down Expand Up @@ -124,8 +123,6 @@ def initialize file, options = {}, zvfs = nil
@collations = {}
@functions = {}
@results_as_hash = options[:results_as_hash]
@type_translation = options[:type_translation]
@type_translator = make_type_translator @type_translation
@readonly = mode & Constants::Open::READONLY != 0
@default_transaction_mode = options[:default_transaction_mode] || :deferred

Expand All @@ -145,25 +142,6 @@ def encoding
@encoding ||= Encoding.find(execute("PRAGMA encoding").first.first)
end

def type_translation= value # :nodoc:
warn(<<~EOWARN) if $VERBOSE
#{caller(1..1).first} is calling `SQLite3::Database#type_translation=` which is deprecated and will be removed in version 2.0.0.
EOWARN
@type_translator = make_type_translator value
@type_translation = value
end
attr_reader :type_translation # :nodoc:

# Return the type translator employed by this database instance. Each
# database instance has its own type translator; this allows for different
# type handlers to be installed in each instance without affecting other
# instances. Furthermore, the translators are instantiated lazily, so that
# if a database does not use type translation, it will not be burdened by
# the overhead of a useless type translator. (See the Translator class.)
def translator
@translator ||= Translator.new
end

# Installs (or removes) a block that will be invoked for every access
# to the database. If the block returns 0 (or +nil+), the statement
# is allowed to proceed. Returning 1 causes an authorization error to
Expand Down Expand Up @@ -741,11 +719,6 @@ def []=(key, value)
end
end

# Translates a +row+ of data from the database with the given +types+
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:
Expand All @@ -756,21 +729,5 @@ def build_result_set stmt
ResultSet.new(self, stmt)
end
end

private

NULL_TRANSLATOR = lambda { |_, row| row }

def make_type_translator should_translate
if should_translate
lambda { |types, row|
types.zip(row).map do |type, value|
translator.translate(type, value)
end
}
else
NULL_TRANSLATOR
end
end
end
end
27 changes: 5 additions & 22 deletions lib/sqlite3/resultset.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ module SQLite3
class ResultSet
include Enumerable

class ArrayWithTypes < Array # :nodoc:
attr_accessor :types
end

class ArrayWithTypesAndFields < Array # :nodoc:
attr_writer :types
attr_writer :fields
Expand Down Expand Up @@ -94,19 +90,10 @@ def next
row = @stmt.step
return nil if @stmt.done?

row = @db.translate_from_db @stmt.types, row

row = if row.respond_to?(:fields)
# FIXME: this can only happen if the translator returns something
# that responds to `fields`. Since we're removing the translator
# in 2.0, we can remove this branch in 2.0.
ArrayWithTypes.new(row)
else
# FIXME: the `fields` and `types` methods are deprecated on this
# object for version 2.0, so we can safely remove this branch
# as well.
ArrayWithTypesAndFields.new(row)
end
# FIXME: the `fields` and `types` methods are deprecated on this
# object for version 2.0, so we can safely remove this branch
# as well.
row = ArrayWithTypesAndFields.new(row)

row.fields = @stmt.columns
row.types = @stmt.types
Expand Down Expand Up @@ -156,10 +143,6 @@ def next_hash
row = @stmt.step
return nil if @stmt.done?

# FIXME: type translation is deprecated, so this can be removed
# in 2.0
row = @db.translate_from_db @stmt.types, row

# FIXME: this can be switched to a regular hash in 2.0
row = HashWithTypesAndFields[*@stmt.columns.zip(row).flatten]

Expand All @@ -172,6 +155,6 @@ def next_hash
end

class HashResultSet < ResultSet # :nodoc:
alias :next :next_hash
alias_method :next, :next_hash
end
end
113 changes: 0 additions & 113 deletions lib/sqlite3/translator.rb

This file was deleted.

1 change: 0 additions & 1 deletion sqlite3.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ Gem::Specification.new do |s|
"lib/sqlite3/pragmas.rb",
"lib/sqlite3/resultset.rb",
"lib/sqlite3/statement.rb",
"lib/sqlite3/translator.rb",
"lib/sqlite3/value.rb",
"lib/sqlite3/version.rb",
"test/helper.rb",
Expand Down
20 changes: 0 additions & 20 deletions test/test_database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,26 +97,6 @@ def test_get_first_row
assert_equal [1], @db.get_first_row("SELECT 1")
end

def test_get_first_row_with_type_translation_and_hash_results
@db.results_as_hash = true
capture_io do # hush translation deprecation warnings
@db.type_translation = true
assert_equal({"1" => 1}, @db.get_first_row("SELECT 1"))
end
end

def test_execute_with_type_translation_and_hash
rows = []
@db.results_as_hash = true

capture_io do # hush translation deprecation warnings
@db.type_translation = true
@db.execute("SELECT 1") { |row| rows << row }
end

assert_equal({"1" => 1}, rows.first)
end

def test_encoding
assert @db.encoding, "database has encoding"
end
Expand Down

0 comments on commit e1e61f8

Please sign in to comment.