Skip to content

Commit

Permalink
Force binary data inserted for a string data type to utf-8 and log an
Browse files Browse the repository at this point in the history
error.  Strings tagged as binary will be stored in sqlite3 as blobs.  It
is an error to insert binary data to a string column, so an error is
emitted in the log file.  People are highly encouraged to track down the
source of the binary strings and make sure that the encoding is set
correctly before inserting to the database.
  • Loading branch information
tenderlove committed Aug 25, 2011
1 parent 635b9d4 commit 42a7979
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 3 deletions.
Expand Up @@ -161,10 +161,25 @@ def quoted_date(value) #:nodoc:
end
end

def type_cast(value, column) # :nodoc:
return super unless BigDecimal === value
if "<3".encoding_aware?
def type_cast(value, column) # :nodoc:
return value.to_f if BigDecimal === value
return super unless String === value
return super unless column && value

value = super
if column.type == :string && value.encoding == Encoding::ASCII_8BIT
@logger.error "Binary data inserted for `string` type on column `#{column.name}`"
value.encode! 'utf-8'
end
value
end
else
def type_cast(value, column) # :nodoc:
return super unless BigDecimal === value

value.to_f
value.to_f
end
end

# DATABASE STATEMENTS ======================================
Expand Down
16 changes: 16 additions & 0 deletions activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
@@ -1,5 +1,6 @@
# encoding: utf-8
require "cases/helper"
require 'models/owner'

module ActiveRecord
module ConnectionAdapters
Expand All @@ -19,6 +20,21 @@ def setup
eosql
end

def test_column_types
return skip('only test encoding on 1.9') unless "<3".encoding_aware?

owner = Owner.create!(:name => "hello".encode('ascii-8bit'))
owner.reload
select = Owner.columns.map { |c| "typeof(#{c.name})" }.join ', '
result = Owner.connection.exec_query <<-esql
SELECT #{select}
FROM #{Owner.table_name}
WHERE #{Owner.primary_key} = #{owner.id}
esql

assert(!result.rows.first.include?("blob"), "should not store blobs")
end

def test_exec_insert
column = @conn.columns('items').find { |col| col.name == 'number' }
vals = [[column, 10]]
Expand Down

0 comments on commit 42a7979

Please sign in to comment.