mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-10 01:02:56 +03:00
167 lines
7.6 KiB
JavaScript
167 lines
7.6 KiB
JavaScript
/*
|
|
2022-05-22
|
|
|
|
The author disclaims copyright to this source code. In place of a
|
|
legal notice, here is a blessing:
|
|
|
|
* May you do good and not evil.
|
|
* May you find forgiveness for yourself and forgive others.
|
|
* May you share freely, never taking more than you give.
|
|
|
|
***********************************************************************
|
|
|
|
This file is intended to be loaded after loading
|
|
sqlite3-module.wasm. It sets one of any number of potential
|
|
bindings using that API, this one as closely matching the C-native
|
|
API as is feasible.
|
|
|
|
Note that this file is not named sqlite3.js because that file gets
|
|
generated by emscripten as the JS-glue counterpart of sqlite3.wasm.
|
|
|
|
The API gets installed as self.sqlite3, where self is expected to be
|
|
either the global window or Worker object.
|
|
|
|
Because using this API properly requires some degree of WASM-related
|
|
magic, it is not recommended that this API be used as-is in
|
|
client-level code, but instead is intended to be used as a basis for
|
|
APIs more appropriate for high-level client code.
|
|
|
|
This file installs namespace.sqlite3, where namespace is `self`,
|
|
meaning either the global window or worker, depending on where this
|
|
is loaded from.
|
|
*/
|
|
(function(namespace){
|
|
/* For reference: sql.js does essentially everything we want and
|
|
it solves much of the wasm-related voodoo, but we'll need a
|
|
different structure because we want the db connection to run in
|
|
a worker thread and feed data back into the main
|
|
thread. Regardless of those differences, it makes a great point
|
|
of reference:
|
|
|
|
https://github.com/sql-js/sql.js
|
|
|
|
Some of the specific design goals here:
|
|
|
|
- Bind a low-level sqlite3 API which is close to the native one
|
|
in terms of usage.
|
|
|
|
- Create a higher-level one, more akin to sql.js and
|
|
node.js-style implementations. This one would speak directly
|
|
to the low-level API. This API could be used by clients who
|
|
import the low-level API directly into their main thread
|
|
(which we don't want to recommend but also don't want to
|
|
outright forbid).
|
|
|
|
- Create a second higher-level one which speaks to the
|
|
low-level API via worker messages. This one would be intended
|
|
for use in the main thread, talking to the low-level UI via
|
|
worker messages. Because workers have only a single message
|
|
channel, some acrobatics will be needed here to feed async
|
|
work results back into client-side callbacks (as those
|
|
callbacks cannot simply be passed to the worker). Exactly
|
|
what those acrobatics should look like is not yet entirely
|
|
clear and much experimentation is pending.
|
|
*/
|
|
|
|
/**
|
|
Set up the main sqlite3 binding API here, mimicking the C API as
|
|
closely as we can.
|
|
|
|
Attribution: though not a direct copy/paste, much of what
|
|
follows is strongly influenced by the sql.js implementation.
|
|
*/
|
|
const api = {
|
|
/* It is important that the following integer values match
|
|
those from the C code. Ideally we could fetch them from the
|
|
C API, e.g., in the form of a JSON object, but getting that
|
|
JSON string constructed within our current confised is
|
|
currently not worth the effort. */
|
|
/* Minimum subset of sqlite result codes we'll need. */
|
|
SQLITE_OK: 0,
|
|
SQLITE_ROW: 100,
|
|
SQLITE_DONE: 101,
|
|
/* sqlite data types */
|
|
SQLITE_INTEGER: 1,
|
|
SQLITE_FLOAT: 2,
|
|
SQLITE_TEXT: 3,
|
|
SQLITE_BLOB: 4,
|
|
SQLITE_NULL: 5,
|
|
/* sqlite encodings, used for creating UDFs, noting that we
|
|
will only support UTF8. */
|
|
SQLITE_UTF8: 1
|
|
};
|
|
const cwrap = Module.cwrap;
|
|
[/* C-side functions to bind. Each entry is an array with 3 or 4
|
|
elements:
|
|
|
|
["c-side name",
|
|
"result type" (cwrap() syntax),
|
|
[arg types in cwrap() syntax]
|
|
]
|
|
|
|
If it has 4 elements, the first one is an alternate name to
|
|
use for the JS-side binding. That's required when overloading
|
|
a binding for two different uses.
|
|
*/
|
|
["sqlite3_bind_blob","number",["number", "number", "number", "number", "number"]],
|
|
["sqlite3_bind_double","number",["number", "number", "number"]],
|
|
["sqlite3_bind_int","number",["number", "number", "number"]],
|
|
["sqlite3_bind_int64","number",["number", "number", "number"]],
|
|
["sqlite3_bind_null","void",["number"]],
|
|
["sqlite3_bind_parameter_index","number",["number", "string"]],
|
|
["sqlite3_bind_text","number",["number", "number", "number", "number", "number"]],
|
|
["sqlite3_changes", "number", ["number"]],
|
|
["sqlite3_clear_bindings","number",["number"]],
|
|
["sqlite3_close_v2", "number", ["number"]],
|
|
["sqlite3_column_blob","number", ["number", "number"]],
|
|
["sqlite3_column_bytes","number",["number", "number"]],
|
|
["sqlite3_column_count", "number", ["number"]],
|
|
["sqlite3_column_count","number",["number"]],
|
|
["sqlite3_column_double","number",["number", "number"]],
|
|
["sqlite3_column_name","string",["number", "number"]],
|
|
["sqlite3_column_text","string",["number", "number"]],
|
|
["sqlite3_column_type","number",["number", "number"]],
|
|
["sqlite3_create_function_v2", "number",
|
|
["number", "string", "number", "number","number",
|
|
"number", "number", "number", "number"]],
|
|
["sqlite3_data_count", "number", ["number"]],
|
|
["sqlite3_db_filename", "string", ["number", "string"]],
|
|
["sqlite3_errmsg", "string", ["number"]],
|
|
["sqlite3_exec", "number", ["number", "string", "number", "number", "number"]],
|
|
["sqlite3_finalize", "number", ["number"]],
|
|
["sqlite3_interrupt", "void", ["number"]],
|
|
["sqlite3_libversion", "string", []],
|
|
["sqlite3_open", "number", ["string", "number"]],
|
|
["sqlite3_prepare_v2", "number", ["number", "string", "number", "number", "number"]],
|
|
["sqlite3_prepare_v2_sqlptr", "sqlite3_prepare_v2",
|
|
/* Impl which requires that the 2nd argument be a pointer to
|
|
the SQL, instead of a string. This is used for cases where
|
|
we require a non-NULL value for the final argument. We may
|
|
or may not need this, depending on how our higher-level
|
|
API shapes up, but this code's spiritual guide (sql.js)
|
|
uses it we we'll include it. */
|
|
"number", ["number", "number", "number", "number", "number"]],
|
|
["sqlite3_reset", "number", ["number"]],
|
|
["sqlite3_result_blob",null,["number", "number", "number", "number"]],
|
|
["sqlite3_result_double",null,["number", "number"]],
|
|
["sqlite3_result_error",null,["number", "string", "number"]],
|
|
["sqlite3_result_int",null,["number", "number"]],
|
|
["sqlite3_result_null",null,["number"]],
|
|
["sqlite3_result_text",null,["number", "string", "number", "number"]],
|
|
["sqlite3_sourceid", "string", []],
|
|
["sqlite3_step", "number", ["number"]],
|
|
["sqlite3_value_blob", "number", ["number"]],
|
|
["sqlite3_value_bytes","number",["number"]],
|
|
["sqlite3_value_double","number",["number"]],
|
|
["sqlite3_value_text", "string", ["number"]],
|
|
["sqlite3_value_type", "number", ["number"]]
|
|
//["sqlite3_sql", "string", ["number"]],
|
|
//["sqlite3_normalized_sql", "string", ["number"]]
|
|
].forEach(function(a){
|
|
const k = (4==a.length) ? a.shift() : a[0];
|
|
api[k] = cwrap.apply(this, a);
|
|
});
|
|
//console.debug("libversion =",api.sqlite3_libversion());
|
|
namespace.sqlite3 = api;
|
|
})(self/*worker or window*/);
|