Skip to content
This repository has been archived by the owner on Apr 17, 2018. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Add honoring of Encoding.default_internal for do_postgres, do_sqlite3…
… and do_mysql
  • Loading branch information
dbussink committed May 6, 2010
1 parent c3fb421 commit b1c2fe5
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 34 deletions.
82 changes: 72 additions & 10 deletions data_objects/lib/data_objects/spec/encoding_spec.rb
Expand Up @@ -8,7 +8,6 @@
@connection.close
end


it 'should respond to #character_set' do @connection.should.respond_to(:character_set) end

describe 'character_set' do
Expand Down Expand Up @@ -44,20 +43,21 @@
end
end

shared 'returning correctly encoded strings for the default encoding' do
shared 'returning correctly encoded strings for the default database encoding' do

if defined?(::Encoding)

setup_test_environment
setup_test_environment

before do
@connection = DataObjects::Connection.new(CONFIG.uri)
end
before do
@connection.close if @connection
@connection = DataObjects::Connection.new(CONFIG.uri)
end

after do
@connection.close
end
after do
@connection.close
end

if defined?(::Encoding)
describe 'with encoded string support' do

describe 'reading a String' do
Expand Down Expand Up @@ -101,3 +101,65 @@
end

end

shared 'returning correctly encoded strings for the default internal encoding' do

if defined?(::Encoding)

setup_test_environment

before do
@connection.close if @connection
@encoding_before = Encoding.default_internal
Encoding.default_internal = 'ISO-8859-1'
@connection = DataObjects::Connection.new(CONFIG.uri)
end

after do
@connection.close
Encoding.default_internal = @encoding_before
end

describe 'with encoded string support' do

describe 'reading a String' do
before do
@reader = @connection.create_command("SELECT name, whitepaper_text FROM widgets WHERE ad_description = ?").execute_reader('Buy this product now!')
@reader.next!
@values = @reader.values
end

after do
@reader.close
end

it 'should return UTF-8 encoded String' do
@values.first.should.be.kind_of(String)
@values.first.encoding.name.should == 'ISO-8859-1'
@values.last.should.be.kind_of(String)
@values.last.encoding.name.should == 'ISO-8859-1'
end
end

describe 'reading a ByteArray' do
before do
@command = @connection.create_command("SELECT ad_image FROM widgets WHERE ad_description = ?")
@command.set_types(Extlib::ByteArray)
@reader = @command.execute_reader('Buy this product now!')
@reader.next!
@values = @reader.values
end

after do
@reader.close
end

it 'should return ASCII-8BIT encoded ByteArray' do
@values.first.should.be.kind_of(::Extlib::ByteArray)
@values.first.encoding.name.should == 'ASCII-8BIT'
end
end
end
end

end
28 changes: 21 additions & 7 deletions do_mysql/ext/do_mysql/do_mysql.c
Expand Up @@ -26,30 +26,36 @@
#ifdef HAVE_RUBY_ENCODING_H
#include <ruby/encoding.h>

#define DO_STR_NEW2(str, encoding) \
#define DO_STR_NEW2(str, encoding, internal_encoding) \
({ \
VALUE _string = rb_str_new2((const char *)str); \
if(encoding != -1) { \
rb_enc_associate_index(_string, encoding); \
} \
if(internal_encoding) { \
_string = rb_str_export_to_enc(_string, internal_encoding); \
} \
_string; \
})

#define DO_STR_NEW(str, len, encoding) \
#define DO_STR_NEW(str, len, encoding, internal_encoding) \
({ \
VALUE _string = rb_str_new((const char *)str, (long)len); \
if(encoding != -1) { \
rb_enc_associate_index(_string, encoding); \
} \
if(internal_encoding) { \
_string = rb_str_export_to_enc(_string, internal_encoding); \
} \
_string; \
})

#else

#define DO_STR_NEW2(str, encoding) \
#define DO_STR_NEW2(str, encoding, internal_encoding) \
rb_str_new2((const char *)str)

#define DO_STR_NEW(str, len, encoding) \
#define DO_STR_NEW(str, len, encoding, internal_encoding) \
rb_str_new((const char *)str, (long)len)
#endif

Expand Down Expand Up @@ -320,10 +326,16 @@ static VALUE typecast(const char *value, long length, const VALUE type, int enco
return Qnil;
}

#ifdef HAVE_RUBY_ENCODING_H
rb_encoding * internal_encoding = rb_default_internal_encoding();
#else
void * internal_encoding = NULL;
#endif

if (type == rb_cInteger) {
return rb_cstr2inum(value, 10);
} else if (type == rb_cString) {
return DO_STR_NEW(value, length, encoding);
return DO_STR_NEW(value, length, encoding, internal_encoding);
} else if (type == rb_cFloat) {
return rb_float_new(rb_cstr_to_dbl(value, Qfalse));
} else if (type == rb_cBigDecimal) {
Expand All @@ -345,7 +357,7 @@ static VALUE typecast(const char *value, long length, const VALUE type, int enco
} else if (type == rb_cNilClass) {
return Qnil;
} else {
return DO_STR_NEW(value, length, encoding);
return DO_STR_NEW(value, length, encoding, internal_encoding);
}

}
Expand Down Expand Up @@ -772,7 +784,9 @@ static VALUE cConnection_quote_string(VALUE self, VALUE string) {

// Wrap the escaped string in single-quotes, this is DO's convention
escaped[0] = escaped[quoted_length + 1] = '\'';
result = DO_STR_NEW(escaped, quoted_length + 2, FIX2INT(rb_iv_get(self, "@encoding_id")));
// We don't want to use the internal encoding, because this needs
// to go into the database in the connection encoding
result = DO_STR_NEW(escaped, quoted_length + 2, FIX2INT(rb_iv_get(self, "@encoding_id")), NULL);

free(escaped);
return result;
Expand Down
3 changes: 2 additions & 1 deletion do_mysql/spec/encoding_spec.rb
Expand Up @@ -5,5 +5,6 @@

describe DataObjects::Mysql::Connection do
behaves_like 'a driver supporting different encodings'
behaves_like 'returning correctly encoded strings for the default encoding'
behaves_like 'returning correctly encoded strings for the default database encoding'
behaves_like 'returning correctly encoded strings for the default internal encoding'
end
27 changes: 19 additions & 8 deletions do_postgres/ext/do_postgres/do_postgres.c
Expand Up @@ -44,34 +44,39 @@
#ifdef HAVE_RUBY_ENCODING_H
#include <ruby/encoding.h>

#define DO_STR_NEW2(str, encoding) \
#define DO_STR_NEW2(str, encoding, internal_encoding) \
({ \
VALUE _string = rb_str_new2((const char *)str); \
if(encoding != -1) { \
rb_enc_associate_index(_string, encoding); \
} \
if(internal_encoding) { \
_string = rb_str_export_to_enc(_string, internal_encoding); \
} \
_string; \
})

#define DO_STR_NEW(str, len, encoding) \
#define DO_STR_NEW(str, len, encoding, internal_encoding) \
({ \
VALUE _string = rb_str_new((const char *)str, (long)len); \
if(encoding != -1) { \
rb_enc_associate_index(_string, encoding); \
} \
if(internal_encoding) { \
_string = rb_str_export_to_enc(_string, internal_encoding); \
} \
_string; \
})

#else

#define DO_STR_NEW2(str, doc) \
#define DO_STR_NEW2(str, encoding, internal_encoding) \
rb_str_new2((const char *)str)

#define DO_STR_NEW(str, len, doc) \
#define DO_STR_NEW(str, len, encoding, internal_encoding) \
rb_str_new((const char *)str, (long)len)
#endif


// To store rb_intern values
static ID ID_NEW_DATE;
static ID ID_RATIONAL;
Expand Down Expand Up @@ -336,10 +341,16 @@ static VALUE infer_ruby_type(Oid type) {

static VALUE typecast(const char *value, long length, const VALUE type, int encoding) {

#ifdef HAVE_RUBY_ENCODING_H
rb_encoding * internal_encoding = rb_default_internal_encoding();
#else
void * internal_encoding = NULL;
#endif

if (type == rb_cInteger) {
return rb_cstr2inum(value, 10);
} else if (type == rb_cString) {
return DO_STR_NEW(value, length, encoding);
return DO_STR_NEW(value, length, encoding, internal_encoding);
} else if (type == rb_cFloat) {
return rb_float_new(rb_cstr_to_dbl(value, Qfalse));
} else if (type == rb_cBigDecimal) {
Expand All @@ -365,7 +376,7 @@ static VALUE typecast(const char *value, long length, const VALUE type, int enco
} else if (type == rb_cNilClass) {
return Qnil;
} else {
return DO_STR_NEW(value, length, encoding);
return DO_STR_NEW(value, length, encoding, internal_encoding);
}

}
Expand Down Expand Up @@ -490,7 +501,7 @@ static VALUE cConnection_quote_string(VALUE self, VALUE string) {
// Wrap the escaped string in single-quotes, this is DO's convention
escaped[quoted_length + 1] = escaped[0] = '\'';

result = DO_STR_NEW(escaped, quoted_length + 2, FIX2INT(rb_iv_get(self, "@encoding_id")));
result = DO_STR_NEW(escaped, quoted_length + 2, FIX2INT(rb_iv_get(self, "@encoding_id")), NULL);

free(escaped);
return result;
Expand Down
3 changes: 2 additions & 1 deletion do_postgres/spec/encoding_spec.rb
Expand Up @@ -15,6 +15,7 @@
# can be overridden -- but for now, we won't support doing this.
#
behaves_like 'a driver supporting different encodings'
behaves_like 'returning correctly encoded strings for the default encoding'
behaves_like 'returning correctly encoded strings for the default database encoding'
behaves_like 'returning correctly encoded strings for the default internal encoding'
end
end
10 changes: 8 additions & 2 deletions do_sqlite3/ext/do_sqlite3/do_sqlite3.c
Expand Up @@ -262,6 +262,12 @@ static VALUE typecast(sqlite3_stmt *stmt, int i, VALUE type, int encoding) {
return ruby_value;
}

#ifdef HAVE_RUBY_ENCODING_H
rb_encoding * internal_encoding = rb_default_internal_encoding();
#else
void * internal_encoding = NULL;
#endif

if(type == Qnil) {
switch(original_type) {
case SQLITE_INTEGER: {
Expand All @@ -286,7 +292,7 @@ static VALUE typecast(sqlite3_stmt *stmt, int i, VALUE type, int encoding) {
if (type == rb_cInteger) {
return LL2NUM(sqlite3_column_int64(stmt, i));
} else if (type == rb_cString) {
return DO_STR_NEW((char*)sqlite3_column_text(stmt, i), length, encoding);
return DO_STR_NEW((char*)sqlite3_column_text(stmt, i), length, encoding, internal_encoding);
} else if (type == rb_cFloat) {
return rb_float_new(sqlite3_column_double(stmt, i));
} else if (type == rb_cBigDecimal) {
Expand All @@ -308,7 +314,7 @@ static VALUE typecast(sqlite3_stmt *stmt, int i, VALUE type, int encoding) {
} else if (type == rb_cNilClass) {
return Qnil;
} else {
return DO_STR_NEW((char*)sqlite3_column_text(stmt, i), length, encoding);
return DO_STR_NEW((char*)sqlite3_column_text(stmt, i), length, encoding, internal_encoding);
}
}

Expand Down
14 changes: 10 additions & 4 deletions do_sqlite3/ext/do_sqlite3/do_sqlite3.h
Expand Up @@ -12,30 +12,36 @@
#ifdef HAVE_RUBY_ENCODING_H
#include <ruby/encoding.h>

#define DO_STR_NEW2(str, encoding) \
#define DO_STR_NEW2(str, encoding, internal_encoding) \
({ \
VALUE _string = rb_str_new2((const char *)str); \
if(encoding != -1) { \
rb_enc_associate_index(_string, encoding); \
} \
if(internal_encoding) { \
_string = rb_str_export_to_enc(_string, internal_encoding); \
} \
_string; \
})

#define DO_STR_NEW(str, len, encoding) \
#define DO_STR_NEW(str, len, encoding, internal_encoding) \
({ \
VALUE _string = rb_str_new((const char *)str, (long)len); \
if(encoding != -1) { \
rb_enc_associate_index(_string, encoding); \
} \
if(internal_encoding) { \
_string = rb_str_export_to_enc(_string, internal_encoding); \
} \
_string; \
})

#else

#define DO_STR_NEW2(str, encoding) \
#define DO_STR_NEW2(str, encoding, internal_encoding) \
rb_str_new2((const char *)str)

#define DO_STR_NEW(str, len, encoding) \
#define DO_STR_NEW(str, len, encoding, internal_encoding) \
rb_str_new((const char *)str, (long)len)
#endif

Expand Down
3 changes: 2 additions & 1 deletion do_sqlite3/spec/encoding_spec.rb
Expand Up @@ -4,5 +4,6 @@
require 'data_objects/spec/encoding_spec'

describe DataObjects::Sqlite3::Connection do
behaves_like 'returning correctly encoded strings for the default encoding'
behaves_like 'returning correctly encoded strings for the default database encoding'
behaves_like 'returning correctly encoded strings for the default internal encoding'
end

0 comments on commit b1c2fe5

Please sign in to comment.