Skip to content

Commit 080d60c

Browse files
committed
Remove type translation
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.
1 parent 21db633 commit 080d60c

File tree

7 files changed

+46
-246
lines changed

7 files changed

+46
-246
lines changed

CHANGELOG.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,46 @@ This release drops support for Ruby 2.7. [#453] @flavorjones
2828
### Removed
2929

3030
- Remove `SQLite3::VersionProxy` which has been deprecated since v1.3.2. [#453] @flavorjones
31+
- Remove `SQLite3::Translator` and all related type translation methods.
32+
If you need to do type translation on values returned from the statement object,
33+
please wrap it with a delegate object. Here is an example of using a delegate
34+
class to implement type translation:
35+
36+
```ruby
37+
require "sqlite3"
38+
require "delegate"
39+
40+
db = SQLite3::Database.new(":memory:")
41+
42+
return_value = db.execute_batch2 <<-EOSQL
43+
CREATE TABLE items (id integer PRIMARY KEY AUTOINCREMENT, name string);
44+
INSERT INTO items (name) VALUES ("foo");
45+
INSERT INTO items (name) VALUES ("bar");
46+
EOSQL
47+
48+
class MyTranslator < DelegateClass(SQLite3::Statement)
49+
def step
50+
row = super
51+
return if done?
52+
53+
row.map.with_index do |item, i|
54+
case types[i]
55+
when "integer" # turn all integers to floats
56+
item.to_f
57+
when "string" # add "hello" to all strings
58+
item + "hello"
59+
end
60+
end
61+
end
62+
end
63+
64+
db.prepare("SELECT * FROM items") do |stmt|
65+
stmt = MyTranslator.new(stmt)
66+
while row = stmt.step
67+
p row
68+
end
69+
end
70+
```
3171

3272

3373
## 1.7.0 / 2023-12-27

FAQ.md

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -289,49 +289,6 @@ by column name, even though they are still arrays!
289289
end
290290
```
291291

292-
## I'd like the values from a query to be the correct types, instead of String.
293-
294-
You can turn on "type translation" by setting `Database#type_translation` to
295-
true:
296-
297-
298-
```ruby
299-
db.type_translation = true
300-
db.execute( "select * from table" ) do |row|
301-
p row
302-
end
303-
```
304-
305-
306-
By doing this, each return value for each row will be translated to its
307-
correct type, based on its declared column type.
308-
309-
310-
You can even declare your own translation routines, if (for example) you are
311-
using an SQL type that is not handled by default:
312-
313-
314-
```ruby
315-
# assume "objects" table has the following schema:
316-
# create table objects (
317-
# name varchar2(20),
318-
# thing object
319-
# )
320-
321-
db.type_translation = true
322-
db.translator.add_translator( "object" ) do |type, value|
323-
db.decode( value )
324-
end
325-
326-
h = { :one=>:two, "three"=>"four", 5=>6 }
327-
dump = db.encode( h )
328-
329-
db.execute( "insert into objects values ( ?, ? )", "bob", dump )
330-
331-
obj = db.get_first_value( "select thing from objects where name='bob'" )
332-
p obj == h
333-
```
334-
335292
## How do I insert binary data into the database?
336293

337294
Use blobs. Blobs are new features of SQLite3. You have to use bind

lib/sqlite3/database.rb

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
require "sqlite3/errors"
33
require "sqlite3/pragmas"
44
require "sqlite3/statement"
5-
require "sqlite3/translator"
65
require "sqlite3/value"
76

87
module SQLite3
@@ -82,7 +81,6 @@ def quote(string)
8281
# Other supported +options+:
8382
# - +: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)
8483
# - +:results_as_hash+: boolean (default false), return rows as hashes instead of arrays
85-
# - +:type_translation+: boolean (default false), enable type translation
8684
# - +: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.
8785
#
8886
def initialize file, options = {}, zvfs = nil
@@ -124,8 +122,6 @@ def initialize file, options = {}, zvfs = nil
124122
@collations = {}
125123
@functions = {}
126124
@results_as_hash = options[:results_as_hash]
127-
@type_translation = options[:type_translation]
128-
@type_translator = make_type_translator @type_translation
129125
@readonly = mode & Constants::Open::READONLY != 0
130126
@default_transaction_mode = options[:default_transaction_mode] || :deferred
131127

@@ -145,25 +141,6 @@ def encoding
145141
@encoding ||= Encoding.find(execute("PRAGMA encoding").first.first)
146142
end
147143

148-
def type_translation= value # :nodoc:
149-
warn(<<~EOWARN) if $VERBOSE
150-
#{caller(1..1).first} is calling `SQLite3::Database#type_translation=` which is deprecated and will be removed in version 2.0.0.
151-
EOWARN
152-
@type_translator = make_type_translator value
153-
@type_translation = value
154-
end
155-
attr_reader :type_translation # :nodoc:
156-
157-
# Return the type translator employed by this database instance. Each
158-
# database instance has its own type translator; this allows for different
159-
# type handlers to be installed in each instance without affecting other
160-
# instances. Furthermore, the translators are instantiated lazily, so that
161-
# if a database does not use type translation, it will not be burdened by
162-
# the overhead of a useless type translator. (See the Translator class.)
163-
def translator
164-
@translator ||= Translator.new
165-
end
166-
167144
# Installs (or removes) a block that will be invoked for every access
168145
# to the database. If the block returns 0 (or +nil+), the statement
169146
# is allowed to proceed. Returning 1 causes an authorization error to
@@ -741,11 +718,6 @@ def []=(key, value)
741718
end
742719
end
743720

744-
# Translates a +row+ of data from the database with the given +types+
745-
def translate_from_db types, row
746-
@type_translator.call types, row
747-
end
748-
749721
# Given a statement, return a result set.
750722
# This is not intended for general consumption
751723
# :nodoc:
@@ -756,21 +728,5 @@ def build_result_set stmt
756728
ResultSet.new(self, stmt)
757729
end
758730
end
759-
760-
private
761-
762-
NULL_TRANSLATOR = lambda { |_, row| row }
763-
764-
def make_type_translator should_translate
765-
if should_translate
766-
lambda { |types, row|
767-
types.zip(row).map do |type, value|
768-
translator.translate(type, value)
769-
end
770-
}
771-
else
772-
NULL_TRANSLATOR
773-
end
774-
end
775731
end
776732
end

lib/sqlite3/resultset.rb

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ module SQLite3
99
class ResultSet
1010
include Enumerable
1111

12-
class ArrayWithTypes < Array # :nodoc:
13-
attr_accessor :types
14-
end
15-
1612
class ArrayWithTypesAndFields < Array # :nodoc:
1713
attr_writer :types
1814
attr_writer :fields
@@ -78,9 +74,7 @@ def eof?
7874
end
7975

8076
# Obtain the next row from the cursor. If there are no more rows to be
81-
# had, this will return +nil+. If type translation is active on the
82-
# corresponding database, the values in the row will be translated
83-
# according to their types.
77+
# had, this will return +nil+.
8478
#
8579
# The returned value will be an array, unless Database#results_as_hash has
8680
# been set to +true+, in which case the returned value will be a hash.
@@ -94,19 +88,10 @@ def next
9488
row = @stmt.step
9589
return nil if @stmt.done?
9690

97-
row = @db.translate_from_db @stmt.types, row
98-
99-
row = if row.respond_to?(:fields)
100-
# FIXME: this can only happen if the translator returns something
101-
# that responds to `fields`. Since we're removing the translator
102-
# in 2.0, we can remove this branch in 2.0.
103-
ArrayWithTypes.new(row)
104-
else
105-
# FIXME: the `fields` and `types` methods are deprecated on this
106-
# object for version 2.0, so we can safely remove this branch
107-
# as well.
108-
ArrayWithTypesAndFields.new(row)
109-
end
91+
# FIXME: the `fields` and `types` methods are deprecated on this
92+
# object for version 2.0, so we can safely remove this branch
93+
# as well.
94+
row = ArrayWithTypesAndFields.new(row)
11095

11196
row.fields = @stmt.columns
11297
row.types = @stmt.types
@@ -156,10 +141,6 @@ def next_hash
156141
row = @stmt.step
157142
return nil if @stmt.done?
158143

159-
# FIXME: type translation is deprecated, so this can be removed
160-
# in 2.0
161-
row = @db.translate_from_db @stmt.types, row
162-
163144
# FIXME: this can be switched to a regular hash in 2.0
164145
row = HashWithTypesAndFields[*@stmt.columns.zip(row).flatten]
165146

@@ -172,6 +153,6 @@ def next_hash
172153
end
173154

174155
class HashResultSet < ResultSet # :nodoc:
175-
alias :next :next_hash
156+
alias_method :next, :next_hash
176157
end
177158
end

lib/sqlite3/translator.rb

Lines changed: 0 additions & 113 deletions
This file was deleted.

sqlite3.gemspec

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ Gem::Specification.new do |s|
6868
"lib/sqlite3/pragmas.rb",
6969
"lib/sqlite3/resultset.rb",
7070
"lib/sqlite3/statement.rb",
71-
"lib/sqlite3/translator.rb",
7271
"lib/sqlite3/value.rb",
7372
"lib/sqlite3/version.rb",
7473
"test/helper.rb",

test/test_database.rb

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -97,26 +97,6 @@ def test_get_first_row
9797
assert_equal [1], @db.get_first_row("SELECT 1")
9898
end
9999

100-
def test_get_first_row_with_type_translation_and_hash_results
101-
@db.results_as_hash = true
102-
capture_io do # hush translation deprecation warnings
103-
@db.type_translation = true
104-
assert_equal({"1" => 1}, @db.get_first_row("SELECT 1"))
105-
end
106-
end
107-
108-
def test_execute_with_type_translation_and_hash
109-
rows = []
110-
@db.results_as_hash = true
111-
112-
capture_io do # hush translation deprecation warnings
113-
@db.type_translation = true
114-
@db.execute("SELECT 1") { |row| rows << row }
115-
end
116-
117-
assert_equal({"1" => 1}, rows.first)
118-
end
119-
120100
def test_encoding
121101
assert @db.encoding, "database has encoding"
122102
end

0 commit comments

Comments
 (0)