extralite-bundle 1.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }