1 | #include "sqlite3.h" |
2 | |
3 | #include <ctype.h> |
4 | #include <duckdb.hpp> |
5 | #include <stdio.h> |
6 | #include <stdlib.h> |
7 | #include <string.h> |
8 | #include <time.h> |
9 | #include <string> |
10 | #include <chrono> |
11 | |
12 | using namespace duckdb; |
13 | using namespace std; |
14 | |
15 | #define SOURCE_ID DUCKDB_SOURCE_ID |
16 | #define LIB_VERSION "DuckDB" |
17 | |
18 | static char *sqlite3_strdup(const char *str); |
19 | |
20 | struct sqlite3_string_buffer { |
21 | //! String data |
22 | unique_ptr<char[]> data; |
23 | }; |
24 | |
25 | struct sqlite3_stmt { |
26 | //! The DB object that this statement belongs to |
27 | sqlite3 *db; |
28 | //! The query string |
29 | string query_string; |
30 | //! The prepared statement object, if successfully prepared |
31 | unique_ptr<PreparedStatement> prepared; |
32 | //! The result object, if successfully executed |
33 | unique_ptr<QueryResult> result; |
34 | //! The current chunk that we are iterating over |
35 | unique_ptr<DataChunk> current_chunk; |
36 | //! The current row into the current chunk that we are iterating over |
37 | int64_t current_row; |
38 | //! Bound values, used for binding to the prepared statement |
39 | vector<Value> bound_values; |
40 | //! Names of the prepared parameters |
41 | vector<string> bound_names; |
42 | //! The current column values converted to string, used and filled by sqlite3_column_text |
43 | unique_ptr<sqlite3_string_buffer[]> current_text; |
44 | }; |
45 | |
46 | struct sqlite3 { |
47 | unique_ptr<DuckDB> db; |
48 | unique_ptr<Connection> con; |
49 | string last_error; |
50 | }; |
51 | |
52 | void sqlite3_randomness(int N, void *pBuf) { |
53 | static bool init = false; |
54 | if (!init) { |
55 | srand(time(NULL)); |
56 | init = true; |
57 | } |
58 | unsigned char *zBuf = (unsigned char *)pBuf; |
59 | while (N--) { |
60 | unsigned char nextByte = rand() % 255; |
61 | zBuf[N] = nextByte; |
62 | } |
63 | } |
64 | |
65 | int sqlite3_open(const char *filename, /* Database filename (UTF-8) */ |
66 | sqlite3 **ppDb /* OUT: SQLite db handle */ |
67 | ) { |
68 | if (filename && strcmp(filename, ":memory:" ) == 0) { |
69 | filename = NULL; |
70 | } |
71 | *ppDb = nullptr; |
72 | |
73 | sqlite3 *pDb = nullptr; |
74 | try { |
75 | pDb = new sqlite3(); |
76 | pDb->db = make_unique<DuckDB>(filename); |
77 | pDb->con = make_unique<Connection>(*pDb->db); |
78 | } catch (std::exception &ex) { |
79 | if (pDb) { |
80 | pDb->last_error = ex.what(); |
81 | } |
82 | return SQLITE_ERROR; |
83 | } |
84 | *ppDb = pDb; |
85 | return SQLITE_OK; |
86 | } |
87 | |
88 | int sqlite3_open_v2(const char *filename, /* Database filename (UTF-8) */ |
89 | sqlite3 **ppDb, /* OUT: SQLite db handle */ |
90 | int flags, /* Flags */ |
91 | const char *zVfs /* Name of VFS module to use */ |
92 | ) { |
93 | return sqlite3_open(filename, ppDb); |
94 | } |
95 | |
96 | int sqlite3_close(sqlite3 *db) { |
97 | if (db) { |
98 | delete db; |
99 | } |
100 | return SQLITE_OK; |
101 | } |
102 | |
103 | int sqlite3_shutdown(void) { |
104 | return SQLITE_OK; |
105 | } |
106 | |
107 | /* In SQLite this function compiles the query into VDBE bytecode, |
108 | * in the implementation it currently executes the query */ |
109 | // TODO: prepare the statement instead of executing right away |
110 | int sqlite3_prepare_v2(sqlite3 *db, /* Database handle */ |
111 | const char *zSql, /* SQL statement, UTF-8 encoded */ |
112 | int nByte, /* Maximum length of zSql in bytes. */ |
113 | sqlite3_stmt **ppStmt, /* OUT: Statement handle */ |
114 | const char **pzTail /* OUT: Pointer to unused portion of zSql */ |
115 | ) { |
116 | if (!db || !ppStmt || !zSql) { |
117 | return SQLITE_MISUSE; |
118 | } |
119 | *ppStmt = nullptr; |
120 | string query = nByte < 0 ? zSql : string(zSql, nByte); |
121 | if (pzTail) { |
122 | *pzTail = zSql + query.size(); |
123 | } |
124 | |
125 | try { |
126 | // extract the statements from the SQL query |
127 | auto statements = db->con->ExtractStatements(query); |
128 | if (statements.size() == 0) { |
129 | // no statements to prepare! |
130 | return SQLITE_OK; |
131 | } |
132 | |
133 | // extract the first statement |
134 | auto statement = statements[0].get(); |
135 | // extract the remainder |
136 | bool set_remainder = statement->stmt_location + statement->stmt_length < query.size(); |
137 | query = query.substr(statement->stmt_location, statement->stmt_length); |
138 | |
139 | // now prepare the query |
140 | auto prepared = db->con->Prepare(query); |
141 | if (!prepared->success) { |
142 | // failed to prepare: set the error message |
143 | db->last_error = prepared->error; |
144 | return SQLITE_ERROR; |
145 | } |
146 | |
147 | // create the statement entry |
148 | unique_ptr<sqlite3_stmt> stmt = make_unique<sqlite3_stmt>(); |
149 | stmt->db = db; |
150 | stmt->query_string = query; |
151 | stmt->prepared = move(prepared); |
152 | stmt->current_row = -1; |
153 | for (idx_t i = 0; i < stmt->prepared->n_param; i++) { |
154 | stmt->bound_names.push_back("$" + to_string(i + 1)); |
155 | stmt->bound_values.push_back(Value()); |
156 | } |
157 | |
158 | // extract the remainder of the query and assign it to the pzTail |
159 | if (pzTail && set_remainder) { |
160 | *pzTail = zSql + query.size() + 1; |
161 | } |
162 | |
163 | *ppStmt = stmt.release(); |
164 | return SQLITE_OK; |
165 | } catch (std::exception &ex) { |
166 | db->last_error = ex.what(); |
167 | return SQLITE_ERROR; |
168 | } |
169 | } |
170 | |
171 | bool sqlite3_display_result(StatementType type) { |
172 | switch (type) { |
173 | case StatementType::EXECUTE_STATEMENT: |
174 | case StatementType::EXPLAIN_STATEMENT: |
175 | case StatementType::PRAGMA_STATEMENT: |
176 | case StatementType::SELECT_STATEMENT: |
177 | return true; |
178 | default: |
179 | return false; |
180 | } |
181 | } |
182 | |
183 | /* Prepare the next result to be retrieved */ |
184 | int sqlite3_step(sqlite3_stmt *pStmt) { |
185 | if (!pStmt) { |
186 | return SQLITE_MISUSE; |
187 | } |
188 | if (!pStmt->prepared) { |
189 | pStmt->db->last_error = "Attempting sqlite3_step() on a non-successfully prepared statement" ; |
190 | return SQLITE_ERROR; |
191 | } |
192 | pStmt->current_text = nullptr; |
193 | if (!pStmt->result) { |
194 | // no result yet! call Execute() |
195 | pStmt->result = pStmt->prepared->Execute(pStmt->bound_values); |
196 | if (!pStmt->result->success) { |
197 | // error in execute: clear prepared statement |
198 | pStmt->db->last_error = pStmt->result->error; |
199 | pStmt->prepared = nullptr; |
200 | return SQLITE_ERROR; |
201 | } |
202 | // fetch a chunk |
203 | pStmt->current_chunk = pStmt->result->Fetch(); |
204 | pStmt->current_row = -1; |
205 | if (!sqlite3_display_result(pStmt->prepared->type)) { |
206 | // only SELECT statements return results |
207 | sqlite3_reset(pStmt); |
208 | } |
209 | } |
210 | if (!pStmt->current_chunk) { |
211 | return SQLITE_DONE; |
212 | } |
213 | pStmt->current_row++; |
214 | if (pStmt->current_row >= (int32_t)pStmt->current_chunk->size()) { |
215 | // have to fetch again! |
216 | pStmt->current_row = 0; |
217 | pStmt->current_chunk = pStmt->result->Fetch(); |
218 | if (!pStmt->current_chunk || pStmt->current_chunk->size() == 0) { |
219 | sqlite3_reset(pStmt); |
220 | return SQLITE_DONE; |
221 | } |
222 | } |
223 | return SQLITE_ROW; |
224 | } |
225 | |
226 | /* Execute multiple semicolon separated SQL statements |
227 | * and execute the passed callback for each produced result, |
228 | * largely copied from the original sqlite3 source */ |
229 | int sqlite3_exec(sqlite3 *db, /* The database on which the SQL executes */ |
230 | const char *zSql, /* The SQL to be executed */ |
231 | sqlite3_callback xCallback, /* Invoke this callback routine */ |
232 | void *pArg, /* First argument to xCallback() */ |
233 | char **pzErrMsg /* Write error messages here */ |
234 | ) { |
235 | int rc = SQLITE_OK; /* Return code */ |
236 | const char *zLeftover; /* Tail of unprocessed SQL */ |
237 | sqlite3_stmt *pStmt = nullptr; /* The current SQL statement */ |
238 | char **azCols = nullptr; /* Names of result columns */ |
239 | char **azVals = nullptr; /* Result values */ |
240 | |
241 | if (zSql == nullptr) { |
242 | zSql = "" ; |
243 | } |
244 | |
245 | while (rc == SQLITE_OK && zSql[0]) { |
246 | int nCol; |
247 | |
248 | pStmt = nullptr; |
249 | rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); |
250 | if (rc != SQLITE_OK) { |
251 | if (pzErrMsg) { |
252 | auto errmsg = sqlite3_errmsg(db); |
253 | *pzErrMsg = errmsg ? sqlite3_strdup(errmsg) : nullptr; |
254 | } |
255 | continue; |
256 | } |
257 | if (!pStmt) { |
258 | /* this happens for a comment or white-space */ |
259 | zSql = zLeftover; |
260 | continue; |
261 | } |
262 | |
263 | nCol = sqlite3_column_count(pStmt); |
264 | azCols = (char **)malloc(nCol * sizeof(const char *)); |
265 | azVals = (char **)malloc(nCol * sizeof(const char *)); |
266 | if (!azCols || !azVals) { |
267 | goto exec_out; |
268 | } |
269 | for (int i = 0; i < nCol; i++) { |
270 | azCols[i] = (char *)sqlite3_column_name(pStmt, i); |
271 | } |
272 | |
273 | while (true) { |
274 | rc = sqlite3_step(pStmt); |
275 | |
276 | /* Invoke the callback function if required */ |
277 | if (xCallback && rc == SQLITE_ROW) { |
278 | for (int i = 0; i < nCol; i++) { |
279 | azVals[i] = (char *)sqlite3_column_text(pStmt, i); |
280 | if (!azVals[i] && sqlite3_column_type(pStmt, i) != SQLITE_NULL) { |
281 | fprintf(stderr, "sqlite3_exec: out of memory.\n" ); |
282 | goto exec_out; |
283 | } |
284 | } |
285 | if (xCallback(pArg, nCol, azVals, azCols)) { |
286 | /* EVIDENCE-OF: R-38229-40159 If the callback function to |
287 | ** sqlite3_exec() returns non-zero, then sqlite3_exec() will |
288 | ** return SQLITE_ABORT. */ |
289 | rc = SQLITE_ABORT; |
290 | sqlite3_finalize(pStmt); |
291 | pStmt = 0; |
292 | fprintf(stderr, "sqlite3_exec: callback returned non-zero. " |
293 | "Aborting.\n" ); |
294 | goto exec_out; |
295 | } |
296 | } |
297 | if (rc == SQLITE_DONE) { |
298 | rc = sqlite3_finalize(pStmt); |
299 | pStmt = nullptr; |
300 | zSql = zLeftover; |
301 | while (isspace(zSql[0])) |
302 | zSql++; |
303 | break; |
304 | } else if (rc != SQLITE_ROW) { |
305 | // error |
306 | if (pzErrMsg) { |
307 | auto errmsg = sqlite3_errmsg(db); |
308 | *pzErrMsg = errmsg ? sqlite3_strdup(errmsg) : nullptr; |
309 | } |
310 | goto exec_out; |
311 | } |
312 | } |
313 | |
314 | sqlite3_free(azCols); |
315 | sqlite3_free(azVals); |
316 | azCols = nullptr; |
317 | azVals = nullptr; |
318 | } |
319 | |
320 | exec_out: |
321 | if (pStmt) { |
322 | sqlite3_finalize(pStmt); |
323 | } |
324 | sqlite3_free(azCols); |
325 | sqlite3_free(azVals); |
326 | if (rc != SQLITE_OK && pzErrMsg && !*pzErrMsg) { |
327 | // error but no error message set |
328 | *pzErrMsg = sqlite3_strdup("Unknown error in DuckDB!" ); |
329 | } |
330 | return rc; |
331 | } |
332 | |
333 | /* Return the text of the SQL that was used to prepare the statement */ |
334 | const char *sqlite3_sql(sqlite3_stmt *pStmt) { |
335 | return pStmt->query_string.c_str(); |
336 | } |
337 | |
338 | int sqlite3_column_count(sqlite3_stmt *pStmt) { |
339 | if (!pStmt) { |
340 | return 0; |
341 | } |
342 | return (int)pStmt->prepared->types.size(); |
343 | } |
344 | |
345 | //////////////////////////// |
346 | // sqlite3_column // |
347 | //////////////////////////// |
348 | int sqlite3_column_type(sqlite3_stmt *pStmt, int iCol) { |
349 | if (!pStmt || !pStmt->result || !pStmt->current_chunk) { |
350 | return 0; |
351 | } |
352 | if (FlatVector::IsNull(pStmt->current_chunk->data[iCol], pStmt->current_row)) { |
353 | return SQLITE_NULL; |
354 | } |
355 | auto column_type = pStmt->result->sql_types[iCol]; |
356 | switch (column_type.id) { |
357 | case SQLTypeId::BOOLEAN: |
358 | case SQLTypeId::TINYINT: |
359 | case SQLTypeId::SMALLINT: |
360 | case SQLTypeId::INTEGER: |
361 | case SQLTypeId::BIGINT: /* TODO: Maybe blob? */ |
362 | return SQLITE_INTEGER; |
363 | case SQLTypeId::FLOAT: |
364 | case SQLTypeId::DOUBLE: |
365 | case SQLTypeId::DECIMAL: |
366 | return SQLITE_FLOAT; |
367 | case SQLTypeId::DATE: |
368 | case SQLTypeId::TIME: |
369 | case SQLTypeId::TIMESTAMP: |
370 | case SQLTypeId::VARCHAR: |
371 | case SQLTypeId::LIST: |
372 | case SQLTypeId::STRUCT: |
373 | return SQLITE_BLOB; |
374 | default: |
375 | return 0; |
376 | } |
377 | return 0; |
378 | } |
379 | |
380 | const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N) { |
381 | if (!pStmt) { |
382 | return nullptr; |
383 | } |
384 | return pStmt->prepared->names[N].c_str(); |
385 | } |
386 | |
387 | static bool sqlite3_column_has_value(sqlite3_stmt *pStmt, int iCol, SQLType target_type, Value &val) { |
388 | if (!pStmt || !pStmt->result || !pStmt->current_chunk) { |
389 | return false; |
390 | } |
391 | if (iCol < 0 || iCol >= (int)pStmt->result->sql_types.size()) { |
392 | return false; |
393 | } |
394 | if (FlatVector::IsNull(pStmt->current_chunk->data[iCol], pStmt->current_row)) { |
395 | return false; |
396 | } |
397 | try { |
398 | val = pStmt->current_chunk->data[iCol] |
399 | .GetValue(pStmt->current_row) |
400 | .CastAs(pStmt->result->sql_types[iCol], target_type); |
401 | } catch (...) { |
402 | return false; |
403 | } |
404 | return true; |
405 | } |
406 | |
407 | double sqlite3_column_double(sqlite3_stmt *stmt, int iCol) { |
408 | Value val; |
409 | if (!sqlite3_column_has_value(stmt, iCol, SQLTypeId::DOUBLE, val)) { |
410 | return 0; |
411 | } |
412 | return val.value_.double_; |
413 | } |
414 | |
415 | int sqlite3_column_int(sqlite3_stmt *stmt, int iCol) { |
416 | Value val; |
417 | if (!sqlite3_column_has_value(stmt, iCol, SQLTypeId::INTEGER, val)) { |
418 | return 0; |
419 | } |
420 | return val.value_.integer; |
421 | } |
422 | |
423 | sqlite3_int64 sqlite3_column_int64(sqlite3_stmt *stmt, int iCol) { |
424 | Value val; |
425 | if (!sqlite3_column_has_value(stmt, iCol, SQLTypeId::BIGINT, val)) { |
426 | return 0; |
427 | } |
428 | return val.value_.bigint; |
429 | } |
430 | |
431 | const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int iCol) { |
432 | Value val; |
433 | if (!sqlite3_column_has_value(pStmt, iCol, SQLTypeId::VARCHAR, val)) { |
434 | return nullptr; |
435 | } |
436 | try { |
437 | if (!pStmt->current_text) { |
438 | pStmt->current_text = |
439 | unique_ptr<sqlite3_string_buffer[]>(new sqlite3_string_buffer[pStmt->result->sql_types.size()]); |
440 | } |
441 | auto &entry = pStmt->current_text[iCol]; |
442 | if (!entry.data) { |
443 | // not initialized yet, convert the value and initialize it |
444 | entry.data = unique_ptr<char[]>(new char[val.str_value.size() + 1]); |
445 | memcpy(entry.data.get(), val.str_value.c_str(), val.str_value.size() + 1); |
446 | } |
447 | return (const unsigned char *)entry.data.get(); |
448 | } catch (...) { |
449 | // memory error! |
450 | return nullptr; |
451 | } |
452 | } |
453 | |
454 | //////////////////////////// |
455 | // sqlite3_bind // |
456 | //////////////////////////// |
457 | int sqlite3_bind_parameter_count(sqlite3_stmt *stmt) { |
458 | if (!stmt) { |
459 | return 0; |
460 | } |
461 | return stmt->prepared->n_param; |
462 | } |
463 | |
464 | const char *sqlite3_bind_parameter_name(sqlite3_stmt *stmt, int idx) { |
465 | if (!stmt) { |
466 | return nullptr; |
467 | } |
468 | if (idx < 1 || idx > (int)stmt->prepared->n_param) { |
469 | return nullptr; |
470 | } |
471 | return stmt->bound_names[idx - 1].c_str(); |
472 | } |
473 | |
474 | int sqlite3_bind_parameter_index(sqlite3_stmt *stmt, const char *zName) { |
475 | if (!stmt || !zName) { |
476 | return 0; |
477 | } |
478 | for (idx_t i = 0; i < stmt->bound_names.size(); i++) { |
479 | if (stmt->bound_names[i] == string(zName)) { |
480 | return i + 1; |
481 | } |
482 | } |
483 | return 0; |
484 | } |
485 | |
486 | int sqlite3_internal_bind_value(sqlite3_stmt *stmt, int idx, Value value) { |
487 | if (!stmt || !stmt->prepared || stmt->result) { |
488 | return SQLITE_MISUSE; |
489 | } |
490 | if (idx < 1 || idx > (int)stmt->prepared->n_param) { |
491 | return SQLITE_RANGE; |
492 | } |
493 | stmt->bound_values[idx - 1] = value; |
494 | return SQLITE_OK; |
495 | } |
496 | |
497 | int sqlite3_bind_int(sqlite3_stmt *stmt, int idx, int val) { |
498 | return sqlite3_internal_bind_value(stmt, idx, Value::INTEGER(val)); |
499 | } |
500 | |
501 | int sqlite3_bind_int64(sqlite3_stmt *stmt, int idx, sqlite3_int64 val) { |
502 | return sqlite3_internal_bind_value(stmt, idx, Value::BIGINT(val)); |
503 | } |
504 | |
505 | int sqlite3_bind_double(sqlite3_stmt *stmt, int idx, double val) { |
506 | return sqlite3_internal_bind_value(stmt, idx, Value::DOUBLE(val)); |
507 | } |
508 | |
509 | int sqlite3_bind_null(sqlite3_stmt *stmt, int idx) { |
510 | return sqlite3_internal_bind_value(stmt, idx, Value()); |
511 | } |
512 | |
513 | int sqlite3_bind_text(sqlite3_stmt *stmt, int idx, const char *val, int length, void (*free_func)(void *)) { |
514 | if (!val) { |
515 | return SQLITE_MISUSE; |
516 | } |
517 | string value; |
518 | if (length < 0) { |
519 | value = string(val); |
520 | } else { |
521 | value = string(val, val + length); |
522 | } |
523 | if (free_func && ((ptrdiff_t)free_func) != -1) { |
524 | free_func((void *)val); |
525 | } |
526 | return sqlite3_internal_bind_value(stmt, idx, Value(value)); |
527 | } |
528 | |
529 | int sqlite3_clear_bindings(sqlite3_stmt *stmt) { |
530 | if (!stmt) { |
531 | return SQLITE_MISUSE; |
532 | } |
533 | return SQLITE_OK; |
534 | } |
535 | |
536 | int sqlite3_initialize(void) { |
537 | return SQLITE_OK; |
538 | } |
539 | |
540 | int sqlite3_finalize(sqlite3_stmt *pStmt) { |
541 | if (pStmt) { |
542 | if (pStmt->result && !pStmt->result->success) { |
543 | pStmt->db->last_error = string(pStmt->result->error); |
544 | delete pStmt; |
545 | return SQLITE_ERROR; |
546 | } |
547 | |
548 | delete pStmt; |
549 | } |
550 | return SQLITE_OK; |
551 | } |
552 | |
553 | /* |
554 | ** Some systems have stricmp(). Others have strcasecmp(). Because |
555 | ** there is no consistency, we will define our own. |
556 | ** |
557 | ** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and |
558 | ** sqlite3_strnicmp() APIs allow applications and extensions to compare |
559 | ** the contents of two buffers containing UTF-8 strings in a |
560 | ** case-independent fashion, using the same definition of "case |
561 | ** independence" that SQLite uses internally when comparing identifiers. |
562 | */ |
563 | |
564 | const unsigned char sqlite3UpperToLower[] = { |
565 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, |
566 | 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, |
567 | 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, |
568 | 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, |
569 | 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, |
570 | 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, |
571 | 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, |
572 | 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, |
573 | 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, |
574 | 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, |
575 | 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, |
576 | 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}; |
577 | |
578 | int sqlite3StrICmp(const char *zLeft, const char *zRight) { |
579 | unsigned char *a, *b; |
580 | int c; |
581 | a = (unsigned char *)zLeft; |
582 | b = (unsigned char *)zRight; |
583 | for (;;) { |
584 | c = (int)sqlite3UpperToLower[*a] - (int)sqlite3UpperToLower[*b]; |
585 | if (c || *a == 0) |
586 | break; |
587 | a++; |
588 | b++; |
589 | } |
590 | return c; |
591 | } |
592 | |
593 | SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight) { |
594 | if (zLeft == 0) { |
595 | return zRight ? -1 : 0; |
596 | } else if (zRight == 0) { |
597 | return 1; |
598 | } |
599 | return sqlite3StrICmp(zLeft, zRight); |
600 | } |
601 | |
602 | SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N) { |
603 | unsigned char *a, *b; |
604 | if (zLeft == 0) { |
605 | return zRight ? -1 : 0; |
606 | } else if (zRight == 0) { |
607 | return 1; |
608 | } |
609 | a = (unsigned char *)zLeft; |
610 | b = (unsigned char *)zRight; |
611 | while (N-- > 0 && *a != 0 && sqlite3UpperToLower[*a] == sqlite3UpperToLower[*b]) { |
612 | a++; |
613 | b++; |
614 | } |
615 | return N < 0 ? 0 : sqlite3UpperToLower[*a] - sqlite3UpperToLower[*b]; |
616 | } |
617 | |
618 | char *sqlite3_strdup(const char *str) { |
619 | char *result = (char *)sqlite3_malloc64(strlen(str) + 1); |
620 | strcpy(result, str); |
621 | return result; |
622 | } |
623 | |
624 | void *sqlite3_malloc64(sqlite3_uint64 n) { |
625 | return malloc(n); |
626 | } |
627 | void sqlite3_free(void *pVoid) { |
628 | free(pVoid); |
629 | } |
630 | |
631 | void *sqlite3_malloc(int n) { |
632 | return sqlite3_malloc64(n); |
633 | } |
634 | |
635 | void *sqlite3_realloc(void *ptr, int n) { |
636 | return sqlite3_realloc64(ptr, n); |
637 | } |
638 | |
639 | void *sqlite3_realloc64(void *ptr, sqlite3_uint64 n) { |
640 | return realloc(ptr, n); |
641 | } |
642 | |
643 | // TODO: stub |
644 | int sqlite3_config(int i, ...) { |
645 | return SQLITE_OK; |
646 | } |
647 | |
648 | int sqlite3_errcode(sqlite3 *db) { |
649 | if (!db) { |
650 | return SQLITE_MISUSE; |
651 | } |
652 | return db->last_error.empty() ? SQLITE_OK : SQLITE_ERROR; |
653 | } |
654 | |
655 | int sqlite3_extended_errcode(sqlite3 *db) { |
656 | return sqlite3_errcode(db); |
657 | } |
658 | |
659 | const char *sqlite3_errmsg(sqlite3 *db) { |
660 | if (!db) { |
661 | return "" ; |
662 | } |
663 | return db->last_error.c_str(); |
664 | } |
665 | |
666 | void sqlite3_interrupt(sqlite3 *db) { |
667 | if (db) { |
668 | db->con->Interrupt(); |
669 | } |
670 | } |
671 | |
672 | const char *sqlite3_libversion(void) { |
673 | return LIB_VERSION; |
674 | } |
675 | const char *sqlite3_sourceid(void) { |
676 | return SOURCE_ID; |
677 | } |
678 | |
679 | int sqlite3_reset(sqlite3_stmt *stmt) { |
680 | if (stmt) { |
681 | stmt->result = nullptr; |
682 | stmt->current_chunk = nullptr; |
683 | } |
684 | return SQLITE_OK; |
685 | } |
686 | |
687 | // support functions for shell.c |
688 | // most are dummies, we don't need them really |
689 | |
690 | // TODO use re2 here? |
691 | int sqlite3_strglob(const char *zGlobPattern, const char *zString) { |
692 | fprintf(stderr, "sqlite3_strglob: unsupported.\n" ); |
693 | |
694 | return -1; |
695 | } |
696 | |
697 | int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc) { |
698 | fprintf(stderr, "sqlite3_strlike: unsupported.\n" ); |
699 | |
700 | return -1; |
701 | } |
702 | |
703 | int sqlite3_db_status(sqlite3 *, int op, int *pCur, int *pHiwtr, int resetFlg) { |
704 | fprintf(stderr, "sqlite3_db_status: unsupported.\n" ); |
705 | return -1; |
706 | } |
707 | |
708 | // TODO these should eventually be implemented |
709 | |
710 | int sqlite3_changes(sqlite3 *db) { |
711 | fprintf(stderr, "sqlite3_changes: unsupported.\n" ); |
712 | return 0; |
713 | } |
714 | |
715 | int sqlite3_total_changes(sqlite3 *) { |
716 | fprintf(stderr, "sqlite3_total_changes: unsupported.\n" ); |
717 | return 0; |
718 | } |
719 | |
720 | // checks if input ends with ; |
721 | int sqlite3_complete(const char *sql) { |
722 | // FIXME fprintf(stderr, "sqlite3_complete: unsupported.\n"); |
723 | return -1; |
724 | } |
725 | |
726 | int sqlite3_bind_blob(sqlite3_stmt *, int, const void *, int n, void (*)(void *)) { |
727 | fprintf(stderr, "sqlite3_bind_blob: unsupported.\n" ); |
728 | return -1; |
729 | } |
730 | |
731 | const void *sqlite3_column_blob(sqlite3_stmt *, int iCol) { |
732 | fprintf(stderr, "sqlite3_column_blob: unsupported.\n" ); |
733 | return nullptr; |
734 | } |
735 | |
736 | // length of varchar or blob value |
737 | int sqlite3_column_bytes(sqlite3_stmt *, int iCol) { |
738 | fprintf(stderr, "sqlite3_column_bytes: unsupported.\n" ); |
739 | return -1; |
740 | } |
741 | |
742 | sqlite3_value *sqlite3_column_value(sqlite3_stmt *, int iCol) { |
743 | fprintf(stderr, "sqlite3_column_value: unsupported.\n" ); |
744 | return nullptr; |
745 | } |
746 | |
747 | int sqlite3_db_config(sqlite3 *, int op, ...) { |
748 | fprintf(stderr, "sqlite3_db_config: unsupported.\n" ); |
749 | return -1; |
750 | } |
751 | |
752 | int sqlite3_get_autocommit(sqlite3 *db) { |
753 | return 1; |
754 | // TODO fix this |
755 | // return db->con->context->transaction.IsAutoCommit(); |
756 | fprintf(stderr, "sqlite3_get_autocommit: unsupported.\n" ); |
757 | } |
758 | |
759 | int sqlite3_limit(sqlite3 *, int id, int newVal) { |
760 | fprintf(stderr, "sqlite3_limit: unsupported.\n" ); |
761 | return -1; |
762 | } |
763 | |
764 | int sqlite3_stmt_readonly(sqlite3_stmt *pStmt) { |
765 | fprintf(stderr, "sqlite3_stmt_readonly: unsupported.\n" ); |
766 | return -1; |
767 | } |
768 | |
769 | // TODO pretty easy schema lookup |
770 | int sqlite3_table_column_metadata(sqlite3 *db, /* Connection handle */ |
771 | const char *zDbName, /* Database name or NULL */ |
772 | const char *zTableName, /* Table name */ |
773 | const char *zColumnName, /* Column name */ |
774 | char const **pzDataType, /* OUTPUT: Declared data type */ |
775 | char const **pzCollSeq, /* OUTPUT: Collation sequence name */ |
776 | int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ |
777 | int *pPrimaryKey, /* OUTPUT: True if column part of PK */ |
778 | int *pAutoinc /* OUTPUT: True if column is auto-increment */ |
779 | ) { |
780 | fprintf(stderr, "sqlite3_table_column_metadata: unsupported.\n" ); |
781 | return -1; |
782 | } |
783 | |
784 | const char *sqlite3_column_decltype(sqlite3_stmt *stmt, int col) { |
785 | fprintf(stderr, "sqlite3_column_decltype: unsupported.\n" ); |
786 | return nullptr; |
787 | } |
788 | |
789 | int sqlite3_status64(int op, sqlite3_int64 *pCurrent, sqlite3_int64 *pHighwater, int resetFlag) { |
790 | fprintf(stderr, "sqlite3_status64: unsupported.\n" ); |
791 | return -1; |
792 | } |
793 | |
794 | int sqlite3_status64(sqlite3 *, int op, int *pCur, int *pHiwtr, int resetFlg) { |
795 | fprintf(stderr, "sqlite3_status64: unsupported.\n" ); |
796 | return -1; |
797 | } |
798 | |
799 | int sqlite3_stmt_status(sqlite3_stmt *, int op, int resetFlg) { |
800 | fprintf(stderr, "sqlite3_stmt_status: unsupported.\n" ); |
801 | return -1; |
802 | } |
803 | |
804 | int sqlite3_file_control(sqlite3 *, const char *zDbName, int op, void *) { |
805 | fprintf(stderr, "sqlite3_file_control: unsupported.\n" ); |
806 | return -1; |
807 | } |
808 | |
809 | int sqlite3_declare_vtab(sqlite3 *, const char *zSQL) { |
810 | fprintf(stderr, "sqlite3_declare_vtab: unsupported.\n" ); |
811 | return -1; |
812 | } |
813 | |
814 | const char *sqlite3_vtab_collation(sqlite3_index_info *, int) { |
815 | fprintf(stderr, "sqlite3_vtab_collation: unsupported.\n" ); |
816 | return nullptr; |
817 | } |
818 | |
819 | int sqlite3_sleep(int) { |
820 | fprintf(stderr, "sqlite3_sleep: unsupported.\n" ); |
821 | return -1; |
822 | } |
823 | |
824 | int sqlite3_busy_timeout(sqlite3 *, int ms) { |
825 | fprintf(stderr, "sqlite3_busy_timeout: unsupported.\n" ); |
826 | return -1; |
827 | } |
828 | |
829 | // unlikely to be supported |
830 | |
831 | int sqlite3_trace_v2(sqlite3 *, unsigned uMask, int (*xCallback)(unsigned, void *, void *, void *), void *pCtx) { |
832 | fprintf(stderr, "sqlite3_trace_v2: unsupported.\n" ); |
833 | return -1; |
834 | } |
835 | |
836 | int sqlite3_test_control(int op, ...) { |
837 | fprintf(stderr, "sqlite3_test_control: unsupported.\n" ); |
838 | return -1; |
839 | } |
840 | |
841 | int sqlite3_enable_load_extension(sqlite3 *db, int onoff) { |
842 | // fprintf(stderr, "sqlite3_enable_load_extension: unsupported.\n"); |
843 | return -1; |
844 | } |
845 | |
846 | int sqlite3_load_extension(sqlite3 *db, /* Load the extension into this database connection */ |
847 | const char *zFile, /* Name of the shared library containing extension */ |
848 | const char *zProc, /* Entry point. Derived from zFile if 0 */ |
849 | char **pzErrMsg /* Put error message here if not 0 */ |
850 | ) { |
851 | // fprintf(stderr, "sqlite3_load_extension: unsupported.\n"); |
852 | return -1; |
853 | } |
854 | |
855 | int sqlite3_create_module(sqlite3 *db, /* SQLite connection to register module with */ |
856 | const char *zName, /* Name of the module */ |
857 | const sqlite3_module *p, /* Methods for the module */ |
858 | void *pClientData /* Client data for xCreate/xConnect */ |
859 | ) { |
860 | // fprintf(stderr, "sqlite3_create_module: unsupported.\n"); |
861 | return -1; |
862 | } |
863 | |
864 | int sqlite3_create_function(sqlite3 *db, const char *zFunctionName, int nArg, int eTextRep, void *pApp, |
865 | void (*xFunc)(sqlite3_context *, int, sqlite3_value **), |
866 | void (*xStep)(sqlite3_context *, int, sqlite3_value **), |
867 | void (*xFinal)(sqlite3_context *)) { |
868 | // fprintf(stderr, "sqlite3_create_function: unsupported.\n"); |
869 | return -1; |
870 | } |
871 | |
872 | int sqlite3_set_authorizer(sqlite3 *, int (*xAuth)(void *, int, const char *, const char *, const char *, const char *), |
873 | void *pUserData) { |
874 | fprintf(stderr, "sqlite3_set_authorizer: unsupported.\n" ); |
875 | return -1; |
876 | } |
877 | |
878 | // needed in shell timer |
879 | static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow) { |
880 | using namespace std::chrono; |
881 | *piNow = (sqlite3_int64)duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); |
882 | return SQLITE_OK; |
883 | } |
884 | |
885 | // virtual file system, providing some dummies to avoid crashes |
886 | sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName) { |
887 | // return a dummy because the shell does not check the return code. |
888 | // fprintf(stderr, "sqlite3_vfs_find: unsupported.\n"); |
889 | sqlite3_vfs *res = (sqlite3_vfs *)sqlite3_malloc(sizeof(sqlite3_vfs)); |
890 | res->xCurrentTimeInt64 = unixCurrentTimeInt64; |
891 | res->iVersion = 2; |
892 | res->zName = "dummy" ; |
893 | res->pNext = nullptr; |
894 | assert(res); |
895 | return res; |
896 | } |
897 | int sqlite3_vfs_register(sqlite3_vfs *, int makeDflt) { |
898 | // fprintf(stderr, "sqlite3_vfs_register: unsupported.\n"); |
899 | return -1; |
900 | } |
901 | |
902 | // backups, unused |
903 | |
904 | int sqlite3_backup_step(sqlite3_backup *p, int nPage) { |
905 | fprintf(stderr, "sqlite3_backup_step: unsupported.\n" ); |
906 | return -1; |
907 | } |
908 | int sqlite3_backup_finish(sqlite3_backup *p) { |
909 | fprintf(stderr, "sqlite3_backup_finish: unsupported.\n" ); |
910 | return -1; |
911 | } |
912 | |
913 | sqlite3_backup *sqlite3_backup_init(sqlite3 *pDest, /* Destination database handle */ |
914 | const char *zDestName, /* Destination database name */ |
915 | sqlite3 *pSource, /* Source database handle */ |
916 | const char *zSourceName /* Source database name */ |
917 | ) { |
918 | fprintf(stderr, "sqlite3_backup_init: unsupported.\n" ); |
919 | return nullptr; |
920 | } |
921 | |
922 | // UDF support stuff, unused for now. These cannot be called as create_function above is disabled |
923 | |
924 | SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *) { |
925 | return nullptr; |
926 | } |
927 | |
928 | void *sqlite3_user_data(sqlite3_context *) { |
929 | return nullptr; |
930 | } |
931 | |
932 | #ifdef _WIN32 |
933 | #include <windows.h> |
934 | |
935 | static void *sqlite3MallocZero(size_t n) { |
936 | auto res = sqlite3_malloc(n); |
937 | assert(res); |
938 | memset(res, 0, n); |
939 | return res; |
940 | } |
941 | |
942 | static LPWSTR winUtf8ToUnicode(const char *zText) { |
943 | int nChar; |
944 | LPWSTR zWideText; |
945 | |
946 | nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0); |
947 | if (nChar == 0) { |
948 | return 0; |
949 | } |
950 | zWideText = (LPWSTR)sqlite3MallocZero(nChar * sizeof(WCHAR)); |
951 | if (zWideText == 0) { |
952 | return 0; |
953 | } |
954 | nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText, nChar); |
955 | if (nChar == 0) { |
956 | sqlite3_free(zWideText); |
957 | zWideText = 0; |
958 | } |
959 | return zWideText; |
960 | } |
961 | |
962 | static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi) { |
963 | int nByte; |
964 | char *zText; |
965 | int codepage = useAnsi ? CP_ACP : CP_OEMCP; |
966 | |
967 | nByte = WideCharToMultiByte(codepage, 0, zWideText, -1, 0, 0, 0, 0); |
968 | if (nByte == 0) { |
969 | return 0; |
970 | } |
971 | zText = (char *)sqlite3MallocZero(nByte); |
972 | if (zText == 0) { |
973 | return 0; |
974 | } |
975 | nByte = WideCharToMultiByte(codepage, 0, zWideText, -1, zText, nByte, 0, 0); |
976 | if (nByte == 0) { |
977 | sqlite3_free(zText); |
978 | zText = 0; |
979 | } |
980 | return zText; |
981 | } |
982 | |
983 | static char *winUtf8ToMbcs(const char *zText, int useAnsi) { |
984 | char *zTextMbcs; |
985 | LPWSTR zTmpWide; |
986 | |
987 | zTmpWide = winUtf8ToUnicode(zText); |
988 | if (zTmpWide == 0) { |
989 | return 0; |
990 | } |
991 | zTextMbcs = winUnicodeToMbcs(zTmpWide, useAnsi); |
992 | sqlite3_free(zTmpWide); |
993 | return zTextMbcs; |
994 | } |
995 | |
996 | SQLITE_API char *sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi) { |
997 | return winUtf8ToMbcs(zText, useAnsi); |
998 | } |
999 | |
1000 | LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText) { |
1001 | return winUtf8ToUnicode(zText); |
1002 | } |
1003 | |
1004 | static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi) { |
1005 | int nByte; |
1006 | LPWSTR zMbcsText; |
1007 | int codepage = useAnsi ? CP_ACP : CP_OEMCP; |
1008 | |
1009 | nByte = MultiByteToWideChar(codepage, 0, zText, -1, NULL, 0) * sizeof(WCHAR); |
1010 | if (nByte == 0) { |
1011 | return 0; |
1012 | } |
1013 | zMbcsText = (LPWSTR)sqlite3MallocZero(nByte * sizeof(WCHAR)); |
1014 | if (zMbcsText == 0) { |
1015 | return 0; |
1016 | } |
1017 | nByte = MultiByteToWideChar(codepage, 0, zText, -1, zMbcsText, nByte); |
1018 | if (nByte == 0) { |
1019 | sqlite3_free(zMbcsText); |
1020 | zMbcsText = 0; |
1021 | } |
1022 | return zMbcsText; |
1023 | } |
1024 | |
1025 | static char *winUnicodeToUtf8(LPCWSTR zWideText) { |
1026 | int nByte; |
1027 | char *zText; |
1028 | |
1029 | nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0); |
1030 | if (nByte == 0) { |
1031 | return 0; |
1032 | } |
1033 | zText = (char *)sqlite3MallocZero(nByte); |
1034 | if (zText == 0) { |
1035 | return 0; |
1036 | } |
1037 | nByte = WideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte, 0, 0); |
1038 | if (nByte == 0) { |
1039 | sqlite3_free(zText); |
1040 | zText = 0; |
1041 | } |
1042 | return zText; |
1043 | } |
1044 | |
1045 | static char *winMbcsToUtf8(const char *zText, int useAnsi) { |
1046 | char *zTextUtf8; |
1047 | LPWSTR zTmpWide; |
1048 | |
1049 | zTmpWide = winMbcsToUnicode(zText, useAnsi); |
1050 | if (zTmpWide == 0) { |
1051 | return 0; |
1052 | } |
1053 | zTextUtf8 = winUnicodeToUtf8(zTmpWide); |
1054 | sqlite3_free(zTmpWide); |
1055 | return zTextUtf8; |
1056 | } |
1057 | |
1058 | SQLITE_API char *sqlite3_win32_mbcs_to_utf8_v2(const char *zText, int useAnsi) { |
1059 | return winMbcsToUtf8(zText, useAnsi); |
1060 | } |
1061 | |
1062 | SQLITE_API char *sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText) { |
1063 | return winUnicodeToUtf8(zWideText); |
1064 | } |
1065 | |
1066 | #endif |
1067 | |
1068 | // TODO complain |
1069 | SQLITE_API void sqlite3_result_blob(sqlite3_context *, const void *, int, void (*)(void *)) { |
1070 | } |
1071 | SQLITE_API void sqlite3_result_blob64(sqlite3_context *, const void *, sqlite3_uint64, void (*)(void *)) { |
1072 | } |
1073 | SQLITE_API void sqlite3_result_double(sqlite3_context *, double) { |
1074 | } |
1075 | SQLITE_API void sqlite3_result_error(sqlite3_context *, const char *, int) { |
1076 | } |
1077 | SQLITE_API void sqlite3_result_error16(sqlite3_context *, const void *, int) { |
1078 | } |
1079 | SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *) { |
1080 | } |
1081 | SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *) { |
1082 | } |
1083 | SQLITE_API void sqlite3_result_error_code(sqlite3_context *, int) { |
1084 | } |
1085 | SQLITE_API void sqlite3_result_int(sqlite3_context *, int) { |
1086 | } |
1087 | SQLITE_API void sqlite3_result_int64(sqlite3_context *, sqlite3_int64) { |
1088 | } |
1089 | SQLITE_API void sqlite3_result_null(sqlite3_context *) { |
1090 | } |
1091 | SQLITE_API void sqlite3_result_text(sqlite3_context *, const char *, int, void (*)(void *)) { |
1092 | } |
1093 | SQLITE_API void sqlite3_result_text64(sqlite3_context *, const char *, sqlite3_uint64, void (*)(void *), |
1094 | unsigned char encoding) { |
1095 | } |
1096 | SQLITE_API void sqlite3_result_text16(sqlite3_context *, const void *, int, void (*)(void *)) { |
1097 | } |
1098 | SQLITE_API void sqlite3_result_text16le(sqlite3_context *, const void *, int, void (*)(void *)) { |
1099 | } |
1100 | SQLITE_API void sqlite3_result_text16be(sqlite3_context *, const void *, int, void (*)(void *)) { |
1101 | } |
1102 | SQLITE_API void sqlite3_result_value(sqlite3_context *, sqlite3_value *) { |
1103 | } |
1104 | SQLITE_API void sqlite3_result_pointer(sqlite3_context *, void *, const char *, void (*)(void *)) { |
1105 | } |
1106 | SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *, int n) { |
1107 | } |
1108 | SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *, sqlite3_uint64 n) { |
1109 | return -1; |
1110 | } |
1111 | |
1112 | // TODO complain |
1113 | const void *sqlite3_value_blob(sqlite3_value *) { |
1114 | return nullptr; |
1115 | } |
1116 | double sqlite3_value_double(sqlite3_value *) { |
1117 | return 0; |
1118 | } |
1119 | int sqlite3_value_int(sqlite3_value *) { |
1120 | return 0; |
1121 | } |
1122 | sqlite3_int64 sqlite3_value_int64(sqlite3_value *) { |
1123 | return 0; |
1124 | } |
1125 | void *sqlite3_value_pointer(sqlite3_value *, const char *) { |
1126 | return nullptr; |
1127 | } |
1128 | const unsigned char *sqlite3_value_text(sqlite3_value *) { |
1129 | return nullptr; |
1130 | } |
1131 | SQLITE_API const void *sqlite3_value_text16(sqlite3_value *) { |
1132 | return nullptr; |
1133 | } |
1134 | SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *) { |
1135 | return nullptr; |
1136 | } |
1137 | SQLITE_API const void *sqlite3_value_text16be(sqlite3_value *) { |
1138 | return nullptr; |
1139 | } |
1140 | SQLITE_API int sqlite3_value_bytes(sqlite3_value *) { |
1141 | return 0; |
1142 | } |
1143 | SQLITE_API int sqlite3_value_bytes16(sqlite3_value *) { |
1144 | return 0; |
1145 | } |
1146 | SQLITE_API int sqlite3_value_type(sqlite3_value *) { |
1147 | return 0; |
1148 | } |
1149 | SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *) { |
1150 | return 0; |
1151 | } |
1152 | SQLITE_API int sqlite3_value_nochange(sqlite3_value *) { |
1153 | return 0; |
1154 | } |
1155 | |