extralite-bundle 1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/test.yml +26 -0
- data/.gitignore +57 -0
- data/CHANGELOG.md +96 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +37 -0
- data/LICENSE +21 -0
- data/README.md +248 -0
- data/Rakefile +46 -0
- data/TODO.md +0 -0
- data/bin/update_sqlite_source +26 -0
- data/ext/extralite/common.c +347 -0
- data/ext/extralite/database.c +385 -0
- data/ext/extralite/extconf-bundle.rb +9 -0
- data/ext/extralite/extconf.rb +115 -0
- data/ext/extralite/extralite.h +64 -0
- data/ext/extralite/extralite_ext.c +7 -0
- data/ext/extralite/extralite_sqlite3.c +3 -0
- data/ext/extralite/prepared_statement.c +238 -0
- data/ext/sqlite3/sqlite3.c +239246 -0
- data/ext/sqlite3/sqlite3.h +12802 -0
- data/extralite-bundle.gemspec +8 -0
- data/extralite.gemspec +8 -0
- data/gemspec.rb +26 -0
- data/lib/extralite/version.rb +3 -0
- data/lib/extralite.rb +21 -0
- data/lib/sequel/adapters/extralite.rb +380 -0
- data/test/extensions/text.dylib +0 -0
- data/test/extensions/text.so +0 -0
- data/test/helper.rb +7 -0
- data/test/perf_ary.rb +51 -0
- data/test/perf_hash.rb +51 -0
- data/test/perf_prepared.rb +64 -0
- data/test/run.rb +5 -0
- data/test/test_database.rb +247 -0
- data/test/test_extralite.rb +9 -0
- data/test/test_prepared_statement.rb +165 -0
- data/test/test_sequel.rb +24 -0
- metadata +160 -0
@@ -0,0 +1,238 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include "extralite.h"
|
3
|
+
|
4
|
+
VALUE cPreparedStatement;
|
5
|
+
|
6
|
+
static size_t PreparedStatement_size(const void *ptr) {
|
7
|
+
return sizeof(PreparedStatement_t);
|
8
|
+
}
|
9
|
+
|
10
|
+
static void PreparedStatement_mark(void *ptr) {
|
11
|
+
PreparedStatement_t *stmt = ptr;
|
12
|
+
rb_gc_mark(stmt->db);
|
13
|
+
rb_gc_mark(stmt->sql);
|
14
|
+
}
|
15
|
+
|
16
|
+
static void PreparedStatement_free(void *ptr) {
|
17
|
+
PreparedStatement_t *stmt = ptr;
|
18
|
+
if (stmt->stmt) sqlite3_finalize(stmt->stmt);
|
19
|
+
free(ptr);
|
20
|
+
}
|
21
|
+
|
22
|
+
static const rb_data_type_t PreparedStatement_type = {
|
23
|
+
"Database",
|
24
|
+
{PreparedStatement_mark, PreparedStatement_free, PreparedStatement_size,},
|
25
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
26
|
+
};
|
27
|
+
|
28
|
+
static VALUE PreparedStatement_allocate(VALUE klass) {
|
29
|
+
PreparedStatement_t *stmt = ALLOC(PreparedStatement_t);
|
30
|
+
stmt->db = Qnil;
|
31
|
+
stmt->sqlite3_db = NULL;
|
32
|
+
stmt->stmt = NULL;
|
33
|
+
return TypedData_Wrap_Struct(klass, &PreparedStatement_type, stmt);
|
34
|
+
}
|
35
|
+
|
36
|
+
#define GetPreparedStatement(obj, stmt) \
|
37
|
+
TypedData_Get_Struct((obj), PreparedStatement_t, &PreparedStatement_type, (stmt))
|
38
|
+
|
39
|
+
/* call-seq: initialize(db, sql)
|
40
|
+
*
|
41
|
+
* Initializes a new SQLite prepared statement with the given path.
|
42
|
+
*/
|
43
|
+
VALUE PreparedStatement_initialize(VALUE self, VALUE db, VALUE sql) {
|
44
|
+
// int rc;
|
45
|
+
PreparedStatement_t *stmt;
|
46
|
+
GetPreparedStatement(self, stmt);
|
47
|
+
|
48
|
+
sql = rb_funcall(sql, ID_STRIP, 0);
|
49
|
+
if (!RSTRING_LEN(sql))
|
50
|
+
rb_raise(cError, "Cannot prepare an empty SQL query");
|
51
|
+
|
52
|
+
stmt->db = db;
|
53
|
+
stmt->sqlite3_db = Database_sqlite3_db(db);
|
54
|
+
stmt->sql = sql;
|
55
|
+
|
56
|
+
// TODO: setup stmt
|
57
|
+
prepare_single_stmt(stmt->sqlite3_db, &stmt->stmt, sql);
|
58
|
+
|
59
|
+
return Qnil;
|
60
|
+
}
|
61
|
+
|
62
|
+
static inline VALUE PreparedStatement_perform_query(int argc, VALUE *argv, VALUE self, VALUE (*call)(query_ctx *)) {
|
63
|
+
PreparedStatement_t *stmt;
|
64
|
+
GetPreparedStatement(self, stmt);
|
65
|
+
|
66
|
+
sqlite3_reset(stmt->stmt);
|
67
|
+
sqlite3_clear_bindings(stmt->stmt);
|
68
|
+
bind_all_parameters(stmt->stmt, argc, argv);
|
69
|
+
query_ctx ctx = { self, stmt->sqlite3_db, stmt->stmt };
|
70
|
+
return call(&ctx);
|
71
|
+
}
|
72
|
+
|
73
|
+
/* call-seq:
|
74
|
+
* query(sql, *parameters, &block) -> [...]
|
75
|
+
* query_hash(sql, *parameters, &block) -> [...]
|
76
|
+
*
|
77
|
+
* Runs a query returning rows as hashes (with symbol keys). If a block is
|
78
|
+
* given, it will be called for each row. Otherwise, an array containing all
|
79
|
+
* rows is returned.
|
80
|
+
*
|
81
|
+
* Query parameters to be bound to placeholders in the query can be specified as
|
82
|
+
* a list of values or as a hash mapping parameter names to values. When
|
83
|
+
* parameters are given as a least, the query should specify parameters using
|
84
|
+
* `?`:
|
85
|
+
*
|
86
|
+
* db.query('select * from foo where x = ?', 42)
|
87
|
+
*
|
88
|
+
* Named placeholders are specified using `:`. The placeholder values are
|
89
|
+
* specified using a hash, where keys are either strings are symbols. String
|
90
|
+
* keys can include or omit the `:` prefix. The following are equivalent:
|
91
|
+
*
|
92
|
+
* db.query('select * from foo where x = :bar', bar: 42)
|
93
|
+
* db.query('select * from foo where x = :bar', 'bar' => 42)
|
94
|
+
* db.query('select * from foo where x = :bar', ':bar' => 42)
|
95
|
+
*/
|
96
|
+
VALUE PreparedStatement_query_hash(int argc, VALUE *argv, VALUE self) {
|
97
|
+
return PreparedStatement_perform_query(argc, argv, self, safe_query_hash);
|
98
|
+
}
|
99
|
+
|
100
|
+
/* call-seq:
|
101
|
+
* stmt.query_ary(sql, *parameters, &block) -> [...]
|
102
|
+
*
|
103
|
+
* Runs a query returning rows as arrays. If a block is given, it will be called
|
104
|
+
* for each row. Otherwise, an array containing all rows is returned.
|
105
|
+
*
|
106
|
+
* Query parameters to be bound to placeholders in the query can be specified as
|
107
|
+
* a list of values or as a hash mapping parameter names to values. When
|
108
|
+
* parameters are given as a least, the query should specify parameters using
|
109
|
+
* `?`:
|
110
|
+
*
|
111
|
+
* db.query_ary('select * from foo where x = ?', 42)
|
112
|
+
*
|
113
|
+
* Named placeholders are specified using `:`. The placeholder values are
|
114
|
+
* specified using a hash, where keys are either strings are symbols. String
|
115
|
+
* keys can include or omit the `:` prefix. The following are equivalent:
|
116
|
+
*
|
117
|
+
* db.query_ary('select * from foo where x = :bar', bar: 42)
|
118
|
+
* db.query_ary('select * from foo where x = :bar', 'bar' => 42)
|
119
|
+
* db.query_ary('select * from foo where x = :bar', ':bar' => 42)
|
120
|
+
*/
|
121
|
+
VALUE PreparedStatement_query_ary(int argc, VALUE *argv, VALUE self) {
|
122
|
+
return PreparedStatement_perform_query(argc, argv, self, safe_query_ary);
|
123
|
+
}
|
124
|
+
|
125
|
+
/* call-seq:
|
126
|
+
* stmt.query_single_row(sql, *parameters) -> {...}
|
127
|
+
*
|
128
|
+
* Runs a query returning a single row as a hash.
|
129
|
+
*
|
130
|
+
* Query parameters to be bound to placeholders in the query can be specified as
|
131
|
+
* a list of values or as a hash mapping parameter names to values. When
|
132
|
+
* parameters are given as a least, the query should specify parameters using
|
133
|
+
* `?`:
|
134
|
+
*
|
135
|
+
* db.query_single_row('select * from foo where x = ?', 42)
|
136
|
+
*
|
137
|
+
* Named placeholders are specified using `:`. The placeholder values are
|
138
|
+
* specified using a hash, where keys are either strings are symbols. String
|
139
|
+
* keys can include or omit the `:` prefix. The following are equivalent:
|
140
|
+
*
|
141
|
+
* db.query_single_row('select * from foo where x = :bar', bar: 42)
|
142
|
+
* db.query_single_row('select * from foo where x = :bar', 'bar' => 42)
|
143
|
+
* db.query_single_row('select * from foo where x = :bar', ':bar' => 42)
|
144
|
+
*/
|
145
|
+
VALUE PreparedStatement_query_single_row(int argc, VALUE *argv, VALUE self) {
|
146
|
+
return PreparedStatement_perform_query(argc, argv, self, safe_query_single_row);
|
147
|
+
}
|
148
|
+
|
149
|
+
/* call-seq:
|
150
|
+
* stmt.query_single_column(sql, *parameters, &block) -> [...]
|
151
|
+
*
|
152
|
+
* Runs a query returning single column values. If a block is given, it will be called
|
153
|
+
* for each value. Otherwise, an array containing all values is returned.
|
154
|
+
*
|
155
|
+
* Query parameters to be bound to placeholders in the query can be specified as
|
156
|
+
* a list of values or as a hash mapping parameter names to values. When
|
157
|
+
* parameters are given as a least, the query should specify parameters using
|
158
|
+
* `?`:
|
159
|
+
*
|
160
|
+
* db.query_single_column('select x from foo where x = ?', 42)
|
161
|
+
*
|
162
|
+
* Named placeholders are specified using `:`. The placeholder values are
|
163
|
+
* specified using a hash, where keys are either strings are symbols. String
|
164
|
+
* keys can include or omit the `:` prefix. The following are equivalent:
|
165
|
+
*
|
166
|
+
* db.query_single_column('select x from foo where x = :bar', bar: 42)
|
167
|
+
* db.query_single_column('select x from foo where x = :bar', 'bar' => 42)
|
168
|
+
* db.query_single_column('select x from foo where x = :bar', ':bar' => 42)
|
169
|
+
*/
|
170
|
+
VALUE PreparedStatement_query_single_column(int argc, VALUE *argv, VALUE self) {
|
171
|
+
return PreparedStatement_perform_query(argc, argv, self, safe_query_single_column);
|
172
|
+
}
|
173
|
+
|
174
|
+
/* call-seq:
|
175
|
+
* stmt.query_single_value(sql, *parameters) -> value
|
176
|
+
*
|
177
|
+
* Runs a query returning a single value from the first row.
|
178
|
+
*
|
179
|
+
* Query parameters to be bound to placeholders in the query can be specified as
|
180
|
+
* a list of values or as a hash mapping parameter names to values. When
|
181
|
+
* parameters are given as a least, the query should specify parameters using
|
182
|
+
* `?`:
|
183
|
+
*
|
184
|
+
* db.query_single_value('select x from foo where x = ?', 42)
|
185
|
+
*
|
186
|
+
* Named placeholders are specified using `:`. The placeholder values are
|
187
|
+
* specified using a hash, where keys are either strings are symbols. String
|
188
|
+
* keys can include or omit the `:` prefix. The following are equivalent:
|
189
|
+
*
|
190
|
+
* db.query_single_value('select x from foo where x = :bar', bar: 42)
|
191
|
+
* db.query_single_value('select x from foo where x = :bar', 'bar' => 42)
|
192
|
+
* db.query_single_value('select x from foo where x = :bar', ':bar' => 42)
|
193
|
+
*/
|
194
|
+
VALUE PreparedStatement_query_single_value(int argc, VALUE *argv, VALUE self) {
|
195
|
+
return PreparedStatement_perform_query(argc, argv, self, safe_query_single_value);
|
196
|
+
}
|
197
|
+
|
198
|
+
/* call-seq:
|
199
|
+
* stmt.database -> database
|
200
|
+
* stmt.db -> database
|
201
|
+
*
|
202
|
+
* Returns the database associated with the prepared statement.
|
203
|
+
*/
|
204
|
+
VALUE PreparedStatement_database(VALUE self) {
|
205
|
+
PreparedStatement_t *stmt;
|
206
|
+
GetPreparedStatement(self, stmt);
|
207
|
+
return stmt->db;
|
208
|
+
}
|
209
|
+
|
210
|
+
/* call-seq:
|
211
|
+
* stmt.sql -> sql
|
212
|
+
*
|
213
|
+
* Returns the SQL query used for the prepared statement.
|
214
|
+
*/
|
215
|
+
VALUE PreparedStatement_sql(VALUE self) {
|
216
|
+
PreparedStatement_t *stmt;
|
217
|
+
GetPreparedStatement(self, stmt);
|
218
|
+
return stmt->sql;
|
219
|
+
}
|
220
|
+
|
221
|
+
void Init_ExtralitePreparedStatement() {
|
222
|
+
VALUE mExtralite = rb_define_module("Extralite");
|
223
|
+
|
224
|
+
cPreparedStatement = rb_define_class_under(mExtralite, "PreparedStatement", rb_cObject);
|
225
|
+
rb_define_alloc_func(cPreparedStatement, PreparedStatement_allocate);
|
226
|
+
|
227
|
+
rb_define_method(cPreparedStatement, "initialize", PreparedStatement_initialize, 2);
|
228
|
+
rb_define_method(cPreparedStatement, "database", PreparedStatement_database, 0);
|
229
|
+
rb_define_method(cPreparedStatement, "db", PreparedStatement_database, 0);
|
230
|
+
rb_define_method(cPreparedStatement, "sql", PreparedStatement_sql, 0);
|
231
|
+
|
232
|
+
rb_define_method(cPreparedStatement, "query", PreparedStatement_query_hash, -1);
|
233
|
+
rb_define_method(cPreparedStatement, "query_hash", PreparedStatement_query_hash, -1);
|
234
|
+
rb_define_method(cPreparedStatement, "query_ary", PreparedStatement_query_ary, -1);
|
235
|
+
rb_define_method(cPreparedStatement, "query_single_row", PreparedStatement_query_single_row, -1);
|
236
|
+
rb_define_method(cPreparedStatement, "query_single_column", PreparedStatement_query_single_column, -1);
|
237
|
+
rb_define_method(cPreparedStatement, "query_single_value", PreparedStatement_query_single_value, -1);
|
238
|
+
}
|