Skip to content

Commit 81cd2d7

Browse files
authored
Merge pull request #432 from casperisfine/typed-data
Convert SQLite3 objects to TypedData API
2 parents 61d8e1f + 4edffc3 commit 81cd2d7

File tree

5 files changed

+111
-63
lines changed

5 files changed

+111
-63
lines changed

ext/sqlite3/aggregator.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,11 @@ VALUE
206206
rb_sqlite3_define_aggregator2(VALUE self, VALUE aggregator, VALUE ruby_name)
207207
{
208208
/* define_aggregator is added as a method to SQLite3::Database in database.c */
209-
sqlite3RubyPtr ctx;
209+
sqlite3RubyPtr ctx = sqlite3_database_unwrap(self);
210210
int arity, status;
211211
VALUE aw;
212212
VALUE aggregators;
213213

214-
Data_Get_Struct(self, sqlite3Ruby, ctx);
215214
if (!ctx->db) {
216215
rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a closed database");
217216
}

ext/sqlite3/backup.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,29 @@
88

99
VALUE cSqlite3Backup;
1010

11-
static void deallocate(void * ctx)
11+
static size_t backup_memsize(const void *data)
1212
{
13-
sqlite3BackupRubyPtr c = (sqlite3BackupRubyPtr)ctx;
14-
xfree(c);
13+
sqlite3BackupRubyPtr ctx = (sqlite3BackupRubyPtr)data;
14+
// NB: can't account for ctx->p because the type is incomplete.
15+
return sizeof(*ctx);
1516
}
1617

18+
static const rb_data_type_t backup_type = {
19+
"SQLite3::Backup",
20+
{
21+
NULL,
22+
RUBY_TYPED_DEFAULT_FREE,
23+
backup_memsize,
24+
},
25+
0,
26+
0,
27+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
28+
};
29+
1730
static VALUE allocate(VALUE klass)
1831
{
19-
sqlite3BackupRubyPtr ctx = xcalloc((size_t)1, sizeof(sqlite3BackupRuby));
20-
return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
32+
sqlite3BackupRubyPtr ctx;
33+
return TypedData_Make_Struct(klass, sqlite3BackupRuby, &backup_type, ctx);
2134
}
2235

2336
/* call-seq: SQLite3::Backup.new(dstdb, dstname, srcdb, srcname)
@@ -62,9 +75,9 @@ static VALUE initialize(VALUE self, VALUE dstdb, VALUE dstname, VALUE srcdb, VAL
6275
sqlite3RubyPtr ddb_ctx, sdb_ctx;
6376
sqlite3_backup *pBackup;
6477

65-
Data_Get_Struct(self, sqlite3BackupRuby, ctx);
66-
Data_Get_Struct(dstdb, sqlite3Ruby, ddb_ctx);
67-
Data_Get_Struct(srcdb, sqlite3Ruby, sdb_ctx);
78+
TypedData_Get_Struct(self, sqlite3BackupRuby, &backup_type, ctx);
79+
ddb_ctx = sqlite3_database_unwrap(dstdb);
80+
sdb_ctx = sqlite3_database_unwrap(srcdb);
6881

6982
if(!sdb_ctx->db)
7083
rb_raise(rb_eArgError, "cannot backup from a closed database");
@@ -97,7 +110,7 @@ static VALUE step(VALUE self, VALUE nPage)
97110
sqlite3BackupRubyPtr ctx;
98111
int status;
99112

100-
Data_Get_Struct(self, sqlite3BackupRuby, ctx);
113+
TypedData_Get_Struct(self, sqlite3BackupRuby, &backup_type, ctx);
101114
REQUIRE_OPEN_BACKUP(ctx);
102115
status = sqlite3_backup_step(ctx->p, NUM2INT(nPage));
103116
return INT2NUM(status);
@@ -111,7 +124,7 @@ static VALUE finish(VALUE self)
111124
{
112125
sqlite3BackupRubyPtr ctx;
113126

114-
Data_Get_Struct(self, sqlite3BackupRuby, ctx);
127+
TypedData_Get_Struct(self, sqlite3BackupRuby, &backup_type, ctx);
115128
REQUIRE_OPEN_BACKUP(ctx);
116129
(void)sqlite3_backup_finish(ctx->p);
117130
ctx->p = NULL;
@@ -129,7 +142,7 @@ static VALUE remaining(VALUE self)
129142
{
130143
sqlite3BackupRubyPtr ctx;
131144

132-
Data_Get_Struct(self, sqlite3BackupRuby, ctx);
145+
TypedData_Get_Struct(self, sqlite3BackupRuby, &backup_type, ctx);
133146
REQUIRE_OPEN_BACKUP(ctx);
134147
return INT2NUM(sqlite3_backup_remaining(ctx->p));
135148
}
@@ -145,7 +158,7 @@ static VALUE pagecount(VALUE self)
145158
{
146159
sqlite3BackupRubyPtr ctx;
147160

148-
Data_Get_Struct(self, sqlite3BackupRuby, ctx);
161+
TypedData_Get_Struct(self, sqlite3BackupRuby, &backup_type, ctx);
149162
REQUIRE_OPEN_BACKUP(ctx);
150163
return INT2NUM(sqlite3_backup_pagecount(ctx->p));
151164
}

ext/sqlite3/database.c

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,29 @@ static void deallocate(void * ctx)
2121
xfree(c);
2222
}
2323

24+
static size_t database_memsize(const void *ctx)
25+
{
26+
const sqlite3RubyPtr c = (const sqlite3RubyPtr)ctx;
27+
// NB: can't account for ctx->db because the type is incomplete.
28+
return sizeof(*c);
29+
}
30+
31+
static const rb_data_type_t database_type = {
32+
"SQLite3::Backup",
33+
{
34+
NULL,
35+
deallocate,
36+
database_memsize,
37+
},
38+
0,
39+
0,
40+
RUBY_TYPED_WB_PROTECTED, // Not freed immediately because the dfree function do IOs.
41+
};
42+
2443
static VALUE allocate(VALUE klass)
2544
{
26-
sqlite3RubyPtr ctx = xcalloc((size_t)1, sizeof(sqlite3Ruby));
27-
return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
45+
sqlite3RubyPtr ctx;
46+
return TypedData_Make_Struct(klass, sqlite3Ruby, &database_type, ctx);
2847
}
2948

3049
static char *
@@ -37,12 +56,18 @@ utf16_string_value_ptr(VALUE str)
3756

3857
static VALUE sqlite3_rb_close(VALUE self);
3958

59+
sqlite3RubyPtr sqlite3_database_unwrap(VALUE database){
60+
sqlite3RubyPtr ctx;
61+
TypedData_Get_Struct(database, sqlite3Ruby, &database_type, ctx);
62+
return ctx;
63+
}
64+
4065
static VALUE rb_sqlite3_open_v2(VALUE self, VALUE file, VALUE mode, VALUE zvfs)
4166
{
4267
sqlite3RubyPtr ctx;
4368
int status;
4469

45-
Data_Get_Struct(self, sqlite3Ruby, ctx);
70+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
4671

4772
#if defined TAINTING_SUPPORT
4873
# if defined StringValueCStr
@@ -69,7 +94,7 @@ static VALUE rb_sqlite3_disable_quirk_mode(VALUE self)
6994
{
7095
#if defined SQLITE_DBCONFIG_DQS_DDL
7196
sqlite3RubyPtr ctx;
72-
Data_Get_Struct(self, sqlite3Ruby, ctx);
97+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
7398

7499
if(!ctx->db) return Qfalse;
75100

@@ -90,7 +115,7 @@ static VALUE sqlite3_rb_close(VALUE self)
90115
{
91116
sqlite3RubyPtr ctx;
92117
sqlite3 * db;
93-
Data_Get_Struct(self, sqlite3Ruby, ctx);
118+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
94119

95120
db = ctx->db;
96121
CHECK(db, sqlite3_close(ctx->db));
@@ -109,7 +134,7 @@ static VALUE sqlite3_rb_close(VALUE self)
109134
static VALUE closed_p(VALUE self)
110135
{
111136
sqlite3RubyPtr ctx;
112-
Data_Get_Struct(self, sqlite3Ruby, ctx);
137+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
113138

114139
if(!ctx->db) return Qtrue;
115140

@@ -124,7 +149,7 @@ static VALUE closed_p(VALUE self)
124149
static VALUE total_changes(VALUE self)
125150
{
126151
sqlite3RubyPtr ctx;
127-
Data_Get_Struct(self, sqlite3Ruby, ctx);
152+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
128153
REQUIRE_OPEN_DB(ctx);
129154

130155
return INT2NUM(sqlite3_total_changes(ctx->db));
@@ -150,7 +175,7 @@ static VALUE trace(int argc, VALUE *argv, VALUE self)
150175
sqlite3RubyPtr ctx;
151176
VALUE block;
152177

153-
Data_Get_Struct(self, sqlite3Ruby, ctx);
178+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
154179
REQUIRE_OPEN_DB(ctx);
155180

156181
rb_scan_args(argc, argv, "01", &block);
@@ -195,7 +220,7 @@ static VALUE busy_handler(int argc, VALUE *argv, VALUE self)
195220
VALUE block;
196221
int status;
197222

198-
Data_Get_Struct(self, sqlite3Ruby, ctx);
223+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
199224
REQUIRE_OPEN_DB(ctx);
200225

201226
rb_scan_args(argc, argv, "01", &block);
@@ -220,7 +245,7 @@ static VALUE busy_handler(int argc, VALUE *argv, VALUE self)
220245
static VALUE last_insert_row_id(VALUE self)
221246
{
222247
sqlite3RubyPtr ctx;
223-
Data_Get_Struct(self, sqlite3Ruby, ctx);
248+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
224249
REQUIRE_OPEN_DB(ctx);
225250

226251
return LL2NUM(sqlite3_last_insert_rowid(ctx->db));
@@ -340,7 +365,7 @@ static VALUE define_function_with_flags(VALUE self, VALUE name, VALUE flags)
340365
VALUE block;
341366
int status;
342367

343-
Data_Get_Struct(self, sqlite3Ruby, ctx);
368+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
344369
REQUIRE_OPEN_DB(ctx);
345370

346371
block = rb_block_proc();
@@ -380,7 +405,7 @@ static VALUE define_function(VALUE self, VALUE name)
380405
static VALUE interrupt(VALUE self)
381406
{
382407
sqlite3RubyPtr ctx;
383-
Data_Get_Struct(self, sqlite3Ruby, ctx);
408+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
384409
REQUIRE_OPEN_DB(ctx);
385410

386411
sqlite3_interrupt(ctx->db);
@@ -396,7 +421,7 @@ static VALUE interrupt(VALUE self)
396421
static VALUE errmsg(VALUE self)
397422
{
398423
sqlite3RubyPtr ctx;
399-
Data_Get_Struct(self, sqlite3Ruby, ctx);
424+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
400425
REQUIRE_OPEN_DB(ctx);
401426

402427
return rb_str_new2(sqlite3_errmsg(ctx->db));
@@ -410,7 +435,7 @@ static VALUE errmsg(VALUE self)
410435
static VALUE errcode_(VALUE self)
411436
{
412437
sqlite3RubyPtr ctx;
413-
Data_Get_Struct(self, sqlite3Ruby, ctx);
438+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
414439
REQUIRE_OPEN_DB(ctx);
415440

416441
return INT2NUM(sqlite3_errcode(ctx->db));
@@ -438,7 +463,7 @@ static VALUE complete_p(VALUE UNUSED(self), VALUE sql)
438463
static VALUE changes(VALUE self)
439464
{
440465
sqlite3RubyPtr ctx;
441-
Data_Get_Struct(self, sqlite3Ruby, ctx);
466+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
442467
REQUIRE_OPEN_DB(ctx);
443468

444469
return INT2NUM(sqlite3_changes(ctx->db));
@@ -483,7 +508,7 @@ static VALUE set_authorizer(VALUE self, VALUE authorizer)
483508
sqlite3RubyPtr ctx;
484509
int status;
485510

486-
Data_Get_Struct(self, sqlite3Ruby, ctx);
511+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
487512
REQUIRE_OPEN_DB(ctx);
488513

489514
status = sqlite3_set_authorizer(
@@ -510,7 +535,7 @@ static VALUE set_authorizer(VALUE self, VALUE authorizer)
510535
static VALUE set_busy_timeout(VALUE self, VALUE timeout)
511536
{
512537
sqlite3RubyPtr ctx;
513-
Data_Get_Struct(self, sqlite3Ruby, ctx);
538+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
514539
REQUIRE_OPEN_DB(ctx);
515540

516541
CHECK(ctx->db, sqlite3_busy_timeout(ctx->db, (int)NUM2INT(timeout)));
@@ -526,7 +551,7 @@ static VALUE set_busy_timeout(VALUE self, VALUE timeout)
526551
static VALUE set_extended_result_codes(VALUE self, VALUE enable)
527552
{
528553
sqlite3RubyPtr ctx;
529-
Data_Get_Struct(self, sqlite3Ruby, ctx);
554+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
530555
REQUIRE_OPEN_DB(ctx);
531556

532557
CHECK(ctx->db, sqlite3_extended_result_codes(ctx->db, RTEST(enable) ? 1 : 0));
@@ -571,7 +596,7 @@ int rb_comparator_func(void * ctx, int a_len, const void * a, int b_len, const v
571596
static VALUE collation(VALUE self, VALUE name, VALUE comparator)
572597
{
573598
sqlite3RubyPtr ctx;
574-
Data_Get_Struct(self, sqlite3Ruby, ctx);
599+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
575600
REQUIRE_OPEN_DB(ctx);
576601

577602
CHECK(ctx->db, sqlite3_create_collation(
@@ -600,7 +625,7 @@ static VALUE load_extension(VALUE self, VALUE file)
600625
int status;
601626
char *errMsg;
602627
VALUE errexp;
603-
Data_Get_Struct(self, sqlite3Ruby, ctx);
628+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
604629
REQUIRE_OPEN_DB(ctx);
605630

606631
status = sqlite3_load_extension(ctx->db, StringValuePtr(file), 0, &errMsg);
@@ -624,7 +649,7 @@ static VALUE enable_load_extension(VALUE self, VALUE onoff)
624649
{
625650
sqlite3RubyPtr ctx;
626651
int onoffparam;
627-
Data_Get_Struct(self, sqlite3Ruby, ctx);
652+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
628653
REQUIRE_OPEN_DB(ctx);
629654

630655
if (Qtrue == onoff) {
@@ -661,7 +686,7 @@ static VALUE db_encoding(VALUE self)
661686
sqlite3RubyPtr ctx;
662687
VALUE enc;
663688

664-
Data_Get_Struct(self, sqlite3Ruby, ctx);
689+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
665690
REQUIRE_OPEN_DB(ctx);
666691

667692
enc = rb_iv_get(self, "@encoding");
@@ -681,7 +706,7 @@ static VALUE db_encoding(VALUE self)
681706
static VALUE transaction_active_p(VALUE self)
682707
{
683708
sqlite3RubyPtr ctx;
684-
Data_Get_Struct(self, sqlite3Ruby, ctx);
709+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
685710
REQUIRE_OPEN_DB(ctx);
686711

687712
return sqlite3_get_autocommit(ctx->db) ? Qfalse : Qtrue;
@@ -740,7 +765,7 @@ static VALUE exec_batch(VALUE self, VALUE sql, VALUE results_as_hash)
740765
char *errMsg;
741766
VALUE errexp;
742767

743-
Data_Get_Struct(self, sqlite3Ruby, ctx);
768+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
744769
REQUIRE_OPEN_DB(ctx);
745770

746771
if(results_as_hash == Qtrue) {
@@ -768,7 +793,7 @@ static VALUE db_filename(VALUE self, VALUE db_name)
768793
{
769794
sqlite3RubyPtr ctx;
770795
const char * fname;
771-
Data_Get_Struct(self, sqlite3Ruby, ctx);
796+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
772797
REQUIRE_OPEN_DB(ctx);
773798

774799
fname = sqlite3_db_filename(ctx->db, StringValueCStr(db_name));
@@ -782,7 +807,7 @@ static VALUE rb_sqlite3_open16(VALUE self, VALUE file)
782807
int status;
783808
sqlite3RubyPtr ctx;
784809

785-
Data_Get_Struct(self, sqlite3Ruby, ctx);
810+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
786811

787812
#if defined TAINTING_SUPPORT
788813
#if defined StringValueCStr

ext/sqlite3/database.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ typedef sqlite3Ruby * sqlite3RubyPtr;
1212

1313
void init_sqlite3_database();
1414
void set_sqlite3_func_result(sqlite3_context * ctx, VALUE result);
15+
16+
sqlite3RubyPtr sqlite3_database_unwrap(VALUE database);
1517
VALUE sqlite3val2rb(sqlite3_value * val);
1618

1719
#endif

0 commit comments

Comments
 (0)