From 44860d45718a7f19bebab4466d879ad43254f221 Mon Sep 17 00:00:00 2001 From: Jim Flood Date: Wed, 4 Nov 2015 20:49:47 -0800 Subject: [PATCH 1/6] BLOB function result when ASCII-8BIT encoding --- ext/sqlite3/database.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/ext/sqlite3/database.c b/ext/sqlite3/database.c index 35b8f97f..e1730ee1 100644 --- a/ext/sqlite3/database.c +++ b/ext/sqlite3/database.c @@ -322,12 +322,21 @@ static void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result) sqlite3_result_double(ctx, NUM2DBL(result)); break; case T_STRING: - sqlite3_result_text( - ctx, - (const char *)StringValuePtr(result), - (int)RSTRING_LEN(result), - SQLITE_TRANSIENT - ); + if (rb_enc_get_index(result) == rb_ascii8bit_encindex()) { + sqlite3_result_blob( + ctx, + (const void *)StringValuePtr(result), + (int)RSTRING_LEN(result), + SQLITE_TRANSIENT + ); + } else { + sqlite3_result_text( + ctx, + (const char *)StringValuePtr(result), + (int)RSTRING_LEN(result), + SQLITE_TRANSIENT + ); + } break; default: rb_raise(rb_eRuntimeError, "can't return %s", From 8537243093dcbba18be886e4f6373c6deab276ea Mon Sep 17 00:00:00 2001 From: Jim Flood Date: Thu, 5 Nov 2015 12:59:02 -0800 Subject: [PATCH 2/6] Limit change to if HAVE_RUBY_ENCODING_H --- ext/sqlite3/database.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/sqlite3/database.c b/ext/sqlite3/database.c index e1730ee1..16840bc2 100644 --- a/ext/sqlite3/database.c +++ b/ext/sqlite3/database.c @@ -322,6 +322,7 @@ static void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result) sqlite3_result_double(ctx, NUM2DBL(result)); break; case T_STRING: +#ifdef HAVE_RUBY_ENCODING_H if (rb_enc_get_index(result) == rb_ascii8bit_encindex()) { sqlite3_result_blob( ctx, @@ -330,13 +331,16 @@ static void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result) SQLITE_TRANSIENT ); } else { +#endif sqlite3_result_text( ctx, (const char *)StringValuePtr(result), (int)RSTRING_LEN(result), SQLITE_TRANSIENT ); +#ifdef HAVE_RUBY_ENCODING_H } +#endif break; default: rb_raise(rb_eRuntimeError, "can't return %s", From 7cc3cc6de486041d2940d852a9c50cd63e6ef9d0 Mon Sep 17 00:00:00 2001 From: Jim Flood Date: Fri, 4 Dec 2015 11:47:40 -0800 Subject: [PATCH 3/6] Add test to show problem with function returning BLOB --- test/test_database.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/test_database.rb b/test/test_database.rb index e37c15f2..d5b8ed10 100644 --- a/test/test_database.rb +++ b/test/test_database.rb @@ -261,12 +261,19 @@ def test_function_return end def test_function_return_types - [10, 2.2, nil, "foo"].each do |thing| + [10, 2.2, nil, "foo", Blob.new("foo\0bar")].each do |thing| @db.define_function("hello") { |a| thing } assert_equal [thing], @db.execute("select hello('world')").first end end + def test_function_return_type_round_trip + [10, 2.2, nil, "foo", Blob.new("foo\0bar")].each do |thing| + @db.define_function("hello") { |thing| thing } + assert_equal [thing], @db.execute("select hello(hello(?))", [thing]).first + end + end + def test_define_function_closed @db.close assert_raise(SQLite3::Exception) do From 73344ed865be89dbbe32c93f2362391b83a0894f Mon Sep 17 00:00:00 2001 From: Jim Flood Date: Fri, 4 Dec 2015 12:03:51 -0800 Subject: [PATCH 4/6] Fix warning from rake test --- test/test_database.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_database.rb b/test/test_database.rb index d5b8ed10..08bd3a84 100644 --- a/test/test_database.rb +++ b/test/test_database.rb @@ -269,7 +269,7 @@ def test_function_return_types def test_function_return_type_round_trip [10, 2.2, nil, "foo", Blob.new("foo\0bar")].each do |thing| - @db.define_function("hello") { |thing| thing } + @db.define_function("hello") { |a| a } assert_equal [thing], @db.execute("select hello(hello(?))", [thing]).first end end From deecab9f2e6f8a7c1691dbd1b53d5fde46343ae9 Mon Sep 17 00:00:00 2001 From: Jim Flood Date: Fri, 4 Dec 2015 12:04:22 -0800 Subject: [PATCH 5/6] Use CLASS_OF cSqlite3Blob too as done in statement.c --- ext/sqlite3/database.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/sqlite3/database.c b/ext/sqlite3/database.c index 16840bc2..e3d57818 100644 --- a/ext/sqlite3/database.c +++ b/ext/sqlite3/database.c @@ -322,8 +322,11 @@ static void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result) sqlite3_result_double(ctx, NUM2DBL(result)); break; case T_STRING: + if(CLASS_OF(result) == cSqlite3Blob #ifdef HAVE_RUBY_ENCODING_H - if (rb_enc_get_index(result) == rb_ascii8bit_encindex()) { + || rb_enc_get_index(result) == rb_ascii8bit_encindex() +#endif + ) { sqlite3_result_blob( ctx, (const void *)StringValuePtr(result), @@ -331,16 +334,13 @@ static void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result) SQLITE_TRANSIENT ); } else { -#endif sqlite3_result_text( ctx, (const char *)StringValuePtr(result), (int)RSTRING_LEN(result), SQLITE_TRANSIENT ); -#ifdef HAVE_RUBY_ENCODING_H } -#endif break; default: rb_raise(rb_eRuntimeError, "can't return %s", From 220c1947976770a0a12401a467899b79f1900640 Mon Sep 17 00:00:00 2001 From: Jim Flood Date: Fri, 4 Dec 2015 17:11:16 -0800 Subject: [PATCH 6/6] Wrap BLOB function parameters in SQLite3::Blob if encoding is not available. --- ext/sqlite3/database.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ext/sqlite3/database.c b/ext/sqlite3/database.c index e3d57818..a5d37947 100644 --- a/ext/sqlite3/database.c +++ b/ext/sqlite3/database.c @@ -288,7 +288,14 @@ static VALUE sqlite3val2rb(sqlite3_value * val) which is what we want, as blobs are binary */ int len = sqlite3_value_bytes(val); +#ifdef HAVE_RUBY_ENCODING_H return rb_tainted_str_new((const char *)sqlite3_value_blob(val), len); +#else + /* When encoding is not available, make it class SQLite3::Blob. */ + VALUE strargv[1]; + strargv[0] = rb_tainted_str_new((const char *)sqlite3_value_blob(val), len); + return rb_class_new_instance(1, strargv, cSqlite3Blob); +#endif break; } case SQLITE_NULL: