Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Database#execute_batch properly handles non-ASCII strings #526

Merged
merged 1 commit into from
Apr 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Fixed

- Raise an exception if `Database#execute`, `#execute_batch`, or `#query` are passed multiple bind parameters that are not in an Array. In v2.0.0 these methods would silently swallow additional arguments. [#527] @flavorjones
- Fixed a regression in v2.0.0 that caused `Database#execute_batch` to raise an encoding exception when passed some non-ascii strings. As a result of this fix, `Database#prepare` now ensures the "remainder" string will always be encoded as UTF-8. [#524] @flavorjones


## 2.0.0 / 2024-04-17
Expand Down
2 changes: 1 addition & 1 deletion ext/sqlite3/statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ prepare(VALUE self, VALUE db, VALUE sql)
CHECK(db_ctx->db, status);
timespecclear(&db_ctx->stmt_deadline);

return rb_str_new2(tail);
return rb_utf8_str_new_cstr(tail);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to reuse the encoding of the original string?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regardless of the original encoding, the query ends up encoded as UTF-8 in Statement#initialize and the remainder string being returned from sqlite_prepare is also UTF-8.

This call isn't re-encoding anything, it's just telling Ruby that the C string is in fact UTF-8 (the default is otherwise ASCII-8BIT which is what led to the problem you reported).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. Alright, thanks for fixing this!

}

/* call-seq: stmt.close
Expand Down
18 changes: 18 additions & 0 deletions test/test_database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,24 @@ def test_block_prepare_does_not_double_close
assert_equal :foo, r
end

def test_prepare_batch_split
db = SQLite3::Database.new(":memory:")
s1 = db.prepare("select 'asdf'; select 'qwer'; select 'côté'")

assert_equal " select 'qwer'; select 'côté'", s1.remainder
assert_equal Encoding::UTF_8, s1.remainder.encoding

s2 = db.prepare(s1.remainder)

assert_equal " select 'côté'", s2.remainder
assert_equal Encoding::UTF_8, s2.remainder.encoding

s3 = db.prepare(s2.remainder)

assert_equal "", s3.remainder
assert_equal Encoding::UTF_8, s3.remainder.encoding
end

def test_total_changes
db = SQLite3::Database.new(":memory:")
db.execute("create table foo ( a integer primary key, b text )")
Expand Down
Loading