Skip to content

Commit d15fdc6

Browse files
committed
use SQLite3::Exception classes consistently
- Pragmas methods were raising StandardError - Database#execute_batch2 was raising RuntimeError - Database#load_extension was raising RuntimeError - the fallback for unknown errors was RuntimeError - use SQLite3::Exception classes consistently
1 parent 1586ca5 commit d15fdc6

File tree

8 files changed

+50
-25
lines changed

8 files changed

+50
-25
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ This release drops support for Ruby 2.7. [#453] @flavorjones
2828

2929
### Changed
3030

31-
- Raise `StandardError` in a few places where `Exception` was previously raised. [#467] @flavorjones
31+
- Consistently use `SQLite3::Exception` or subclasses. Previously some `Pragmas` methods raised `Exception`, and `Database#execute_batch2` and `Database#load_extension` raised `RuntimeError`. [#467] @flavorjones
3232
- `Database#columns` returns a list of frozen strings. [#474] @tenderlove
3333
- Freeze results that come from the database. [#480] @tenderlove
3434
- The encoding of a Database is no longer cached. [#485] @tenderlove

ext/sqlite3/aggregator.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,7 @@ rb_sqlite3_define_aggregator2(VALUE self, VALUE aggregator, VALUE ruby_name)
251251
rb_sqlite3_aggregator_final
252252
);
253253

254-
if (status != SQLITE_OK) {
255-
rb_sqlite3_raise(ctx->db, status);
256-
return self; // just in case rb_sqlite3_raise returns.
257-
}
254+
CHECK(ctx->db, status);
258255

259256
rb_ary_push(aggregators, aw);
260257

ext/sqlite3/database.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -668,16 +668,13 @@ load_extension(VALUE self, VALUE file)
668668
sqlite3RubyPtr ctx;
669669
int status;
670670
char *errMsg;
671-
VALUE errexp;
671+
672672
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
673673
REQUIRE_OPEN_DB(ctx);
674674

675675
status = sqlite3_load_extension(ctx->db, StringValuePtr(file), 0, &errMsg);
676-
if (status != SQLITE_OK) {
677-
errexp = rb_exc_new2(rb_eRuntimeError, errMsg);
678-
sqlite3_free(errMsg);
679-
rb_exc_raise(errexp);
680-
}
676+
677+
CHECK_MSG(ctx->db, status, errMsg);
681678

682679
return self;
683680
}
@@ -779,7 +776,6 @@ exec_batch(VALUE self, VALUE sql, VALUE results_as_hash)
779776
int status;
780777
VALUE callback_ary = rb_ary_new();
781778
char *errMsg;
782-
VALUE errexp;
783779

784780
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
785781
REQUIRE_OPEN_DB(ctx);
@@ -794,11 +790,7 @@ exec_batch(VALUE self, VALUE sql, VALUE results_as_hash)
794790
&errMsg);
795791
}
796792

797-
if (status != SQLITE_OK) {
798-
errexp = rb_exc_new2(rb_eRuntimeError, errMsg);
799-
sqlite3_free(errMsg);
800-
rb_exc_raise(errexp);
801-
}
793+
CHECK_MSG(ctx->db, status, errMsg);
802794

803795
return callback_ary;
804796
}

ext/sqlite3/exception.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,28 @@ rb_sqlite3_raise(sqlite3 *db, int status)
9090
klass = rb_path2class("SQLite3::NotADatabaseException");
9191
break;
9292
default:
93-
klass = rb_eRuntimeError;
93+
klass = rb_path2class("SQLite3::Exception");
9494
}
9595

9696
klass = rb_exc_new2(klass, sqlite3_errmsg(db));
9797
rb_iv_set(klass, "@code", INT2FIX(status));
9898
rb_exc_raise(klass);
9999
}
100+
101+
/*
102+
* accepts a sqlite3 error message as the final argument, which will be `sqlite3_free`d
103+
*/
104+
void
105+
rb_sqlite3_raise_msg(sqlite3 *db, int status, const char* msg)
106+
{
107+
VALUE exception;
108+
109+
if (status == SQLITE_OK) {
110+
return;
111+
}
112+
113+
exception = rb_exc_new2(rb_path2class("SQLite3::Exception"), msg);
114+
sqlite3_free((void*)msg);
115+
rb_iv_set(exception, "@code", INT2FIX(status));
116+
rb_exc_raise(exception);
117+
}

ext/sqlite3/exception.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
#define SQLITE3_EXCEPTION_RUBY
33

44
#define CHECK(_db, _status) rb_sqlite3_raise(_db, _status);
5+
#define CHECK_MSG(_db, _status, _msg) rb_sqlite3_raise_msg(_db, _status, _msg);
56

67
void rb_sqlite3_raise(sqlite3 *db, int status);
8+
void rb_sqlite3_raise_msg(sqlite3 *db, int status, const char* msg);
79

810
#endif

lib/sqlite3/pragmas.rb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,14 @@ def set_boolean_pragma(name, mode)
2222
when "on", "yes", "true", "y", "t" then mode = "'ON'"
2323
when "off", "no", "false", "n", "f" then mode = "'OFF'"
2424
else
25-
raise StandardError,
26-
"unrecognized pragma parameter #{mode.inspect}"
25+
raise SQLite3::Exception, "unrecognized pragma parameter #{mode.inspect}"
2726
end
2827
when true, 1
2928
mode = "ON"
3029
when false, 0, nil
3130
mode = "OFF"
3231
else
33-
raise StandardError,
34-
"unrecognized pragma parameter #{mode.inspect}"
32+
raise SQLite3::Exception, "unrecognized pragma parameter #{mode.inspect}"
3533
end
3634

3735
execute("PRAGMA #{name}=#{mode}")
@@ -62,8 +60,7 @@ def get_enum_pragma(name)
6260
def set_enum_pragma(name, mode, enums)
6361
match = enums.find { |p| p.find { |i| i.to_s.downcase == mode.to_s.downcase } }
6462
unless match
65-
raise StandardError,
66-
"unrecognized #{name} #{mode.inspect}"
63+
raise SQLite3::Exception, "unrecognized #{name} #{mode.inspect}"
6764
end
6865
execute("PRAGMA #{name}='#{match.first.upcase}'")
6966
end

test/test_database.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def test_execute_batch2
200200
end
201201
assert_equal [[1, 50], [2, 60]], return_value
202202

203-
assert_raises(RuntimeError) do
203+
assert_raises(SQLite3::Exception) do
204204
# "names" is not a valid column
205205
@db.execute_batch2 'INSERT INTO items (names) VALUES ("bazz")'
206206
end
@@ -631,6 +631,11 @@ def test_load_extension_with_nonstring_argument
631631
assert_raises(TypeError) { db.load_extension(Pathname.new("foo.so")) }
632632
end
633633

634+
def test_load_extension_error
635+
db = SQLite3::Database.new(":memory:")
636+
assert_raises(SQLite3::Exception) { db.load_extension("path/to/foo.so") }
637+
end
638+
634639
def test_raw_float_infinity
635640
# https://github.com/sparklemotion/sqlite3-ruby/issues/396
636641
skip if SQLite3::SQLITE_LOADED_VERSION >= "3.43.0"

test/test_pragmas.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ def setup
77
@db = SQLite3::Database.new(":memory:")
88
end
99

10+
def test_pragma_errors
11+
assert_raises(SQLite3::Exception) do
12+
@db.set_enum_pragma("foo", "bar", [])
13+
end
14+
15+
assert_raises(SQLite3::Exception) do
16+
@db.set_boolean_pragma("read_uncommitted", "foo")
17+
end
18+
19+
assert_raises(SQLite3::Exception) do
20+
@db.set_boolean_pragma("read_uncommitted", 42)
21+
end
22+
end
23+
1024
def test_get_boolean_pragma
1125
refute(@db.get_boolean_pragma("read_uncommitted"))
1226
end

0 commit comments

Comments
 (0)