4 Commits

Author SHA1 Message Date
c1fa069dcb feat!: add workaround for wasi-libc reactor/command model (#13)
* feat: add workaround for wasi-libc reactor/command model
2023-02-24 00:57:22 +03:00
c7ea490286 feat!: reexport heap limit (#12)
feat: reexport heap limit
2023-02-24 00:41:00 +03:00
b1fc30b608 fix: VM-225 Readme update (#11)
fix: Readme update [Fixes VM-225]
2023-02-22 14:32:24 +03:00
5f3121395c fix: xDel special semmantics patch (#10)
Sqlite has a number of special custom memory deallocators, namely SQLITE_STATIC and SQLITE_TRANSIENT. Sqlite calls noop freeing memory with the special deallocators.
    Sqlite virtual tables, e.g. FTS5 implicitly creates aux tables. There are number of SQLITE_STATIC allocated empty lines or 0 size blobs that were previously freed with free. This free op spoils sqlite virtual table state  and renders VT unusable [fixes VM-239]
2023-02-17 16:04:24 +03:00
4 changed files with 449 additions and 407 deletions

View File

@ -36,6 +36,8 @@ EXPORT_FUNCS = \
--export=sqlite3_column_int64,$\
--export=sqlite3_column_blob_,$\
--export=sqlite3_column_bytes,$\
--export=sqlite3_soft_heap_limit64,$\
--export=sqlite3_hard_heap_limit64,$\
--export=sqlite3_finalize
SQLITE_SRC = \
src/alter.c\

133
Readme.md
View File

@ -1,87 +1,106 @@
# SQLite
Sqlite fork ported to WebAssembly and adapted for the Fluence network. Could be launched and played on the Fluence [dashboard](http://dash.fluence.network/deploy/sqlite).
Based on SQlite version 3.40.1.
## Overview
SQLite fork adapted to work with Fluence the protocol. The current version is based on SQLite version 3.40.1. The artifact is SQLite WASM module:
- that is compiled following [Marine runtime ABI conventions](https://fluence.dev/docs/marine-book/marine-rust-sdk/module-abi)
- to be used with [Marine runtime](https://github.com/fluencelabs/marine)
## How to build
Wasm module can be built with either docker-compose
# How to build
This app could be built either with docker
```bash
docker-compose up
```
or by Makefile with [wasi-sdk](https://github.com/WebAssembly/wasi-sdk) installed
or using this [Makefile](./Makefile) with GNU make. There are prerequisites to be installed following this path, namely [wasi-sdk](https://github.com/WebAssembly/wasi-sdk) and marine crate. Take a look at the Dockerfile for the details.
```bash
make
```
# How to use
At now, this fork exports five API functions:
```cpp
/**
* Executes given SQL request and returns result in as a pointer to the following structure: | result size (4 bytes, le)| result (size bytes) |.
*
* @param sql a pointer to the supplied sql request
* @param length a size of the supplied sql request
* @return a pointer to the struct contains result_size and result
*/
char *invoke(const char *sql, size_t length);
## How to use
/**
* Allocates a memory region of a given size. Could be used by Wasm execution environments for byte array passing.
*
* @param size a size of allocated memory region
* @return a pointer to the allocated memory region
*/
void *allocate(size_t size);
/**
* Frees a memory region. Could be used by Wasm execution environments for freeing previous memory allocated by `allocate` function.
*
* @param ptr a pointer to the previously allocated memory region
* @param size a size of the previously allocated memory region
*/
void deallocate(void *ptr, size_t size);
/**
* Stores one byte by a given address in the module memory.
*
* @param ptr a address where byte should be stored
* @param value a byte to be stored
*/
void store(void *ptr, char value);
The SQLite Wasm module exports a set of SQLite C API functions. The easiest way to try this module is to run it with Marine REPL.
You can find MREPL output for a simple "CREATE-INSERT-SELECT" scenario below. Mind the second argument to sqlite3_open_v2() that is an OR-ed SQLite flag values. The value "6" in this context means `SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE`.
```bash
$cargo install mrepl
...
$mrepl -q Config.toml
1> call sqlite3 sqlite3_open_v2 [":memory:",6,""]
result: {
"db_handle": 198600,
"ret_code": 0
}
elapsed time: 357.556µs
2> call sqlite3 sqlite3_exec [198600, "CREATE TABLE tab1(i bigint);", 0, 0]
result: {
"err_msg": "",
"ret_code": 0
}
elapsed time: 1.736661ms
3> call sqlite3 sqlite3_exec [198600, "INSERT INTO tab1 VALUES (42);", 0, 0]
result: {
"err_msg": "",
"ret_code": 0
}
elapsed time: 330.098µs
4> call sqlite3 sqlite3_prepare_v2 [198600, "SELECT * FROM tab1;"]
result: {
"ret_code": 0,
"stmt_handle": 244584,
"tail": 268147
}
elapsed time: 280.668µs
5> call sqlite3 sqlite3_step [244584]
result: 100
elapsed time: 124.122µs
6> call sqlite3 sqlite3_column_int64 [244584,0]
result: 42
elapsed time: 72.483µs
/**
* Returns one byte by a given address in the module memory.
*
* @param ptr a address at which the needed byte is located
* @return the byte at the given address
*/
char load(void *ptr);
```
Given char string `sql` as the request, the general scheme to use it is following:
1. `void *ptr = allocate(strlen(sql))` that returns a pointer to the memory region enough for the string
2. `void *res = invoke(ptr, strlen(sql))` to execute the request
3. read a result from the `res` by reading 4 bytes as little-endian `result_size` and the read `result_size` bytes as the final result.
4. `deallocate(res, strlen(sql))` to clean memory.
Depends on your Wasm execution environment, `load`/`store` could be used for reading and writing a module memory.
You can also try the SQLite Wasm module using Rust together with [this Sqlite connector](https://github.com/fluencelabs/sqlite-wasm-connector). [Here](https://github.com/fluencelabs/examples/tree/main/marine-examples/sqlite) you can find a simple SQL REPL utility example built into a Wasm module.
## More insights
## Support
At Fluence, we use WebAssembly (Wasm) to run applications in a trustless network of independent nodes. This trustless environment mandates that every piece of the code executed by any network node must be verified by another node to check whether the execution was performed correctly. In order to be verifiable, every computation must be made deterministic, which means that to run WebAssembly code in a trustless network, we need to make its execution deterministic.
Please, [file an issue](https://github.com/fluencelabs/sqlite/issues) if you find a bug. You can also contact us at [Discord](https://discord.com/invite/5qSnPZKh7u) or [Telegram](https://t.me/fluence_project). We will do our best to resolve the issue ASAP.
There are three primary sources of nondeterminism in WebAssembly: external functions invocation, NaN payloads, and VM resource exhaustion. The first one is the most problematic; currently, we deal with it by simply prohibiting any interactions with the host environment from Wasm programs. This means that submitted WebAssembly code should not contain any external imports.
The main purpose of this fork is to compile to Wasm without any imports. SQlite is famous for it embeddability and allows to configure itself by variety of macros. E.g. multithreading that produces a lot of imports of host functions could be completely disabled by setting SQLITE_THREADSAFE to 0. Also this fork has been patched to use only memory database without any interaction with a hard disk. So, now it is Wasm in-memory database.
## Contributing
More information about ways of porting C/C++ code to Wasm could be found in our [article](https://medium.com/fluence-network/porting-redis-to-webassembly-with-clang-wasi-af99b264ca8) about porting of Redis.
Any interested person is welcome to contribute to the project. Please, make sure you read and follow some basic [rules](https://github.com/fluencelabs/rust-peer/blob/master/CONTRIBUTING.md).
## Future plans
We are working on supporting of subset of WASI syscalls and interface types support for more convinient parameter passing scheme.
## License
All software code is copyright (c) Fluence Labs, Inc. under the [Apache-2.0](https://github.com/fluencelabs/rust-peer/blob/master/LICENSE) license.

View File

@ -1,4 +1,4 @@
(@interface it_version "0.20.0")
(@interface it_version "0.24.1")
;; Types
(@interface type (func
@ -13,18 +13,18 @@
(param $result_size: i32) )) ;; 4
(@interface type (func
(param $result_ptr: i32) )) ;; 5
(@interface type (record $DBExecDescriptor (
(@interface type (record $DBOpenDescriptor (
field $ret_code: s32
field $err_msg: string
field $db_handle: u32
))) ;; 6
(@interface type (record $DBPrepareDescriptor (
field $ret_code: s32
field $stmt_handle: u32
field $tail: u32
))) ;; 7
(@interface type (record $DBOpenDescriptor (
(@interface type (record $DBExecDescriptor (
field $ret_code: s32
field $db_handle: u32
field $err_msg: string
))) ;; 8
(@interface type (record $SecurityTetraplet (
field $peer_pk: string
@ -32,279 +32,196 @@
field $function_name: string
field $json_path: string
))) ;; 9
(@interface type (record $CallParameters (
field $init_peer_id: string
field $service_id: string
field $service_creator_peer_id: string
field $host_id: string
field $particle_id: string
field $tetraplets: array (array (record 9))
))) ;; 10
(@interface type (func
(param $stmt_handle: u32 $icol: u32)
(result string))) ;; 11
(param $stmt_handle: u32 $pos: s32 $value: s64)
(result s32))) ;; 10
(@interface type (func
(param $stmt_handle: u32 $pos: s32 $value: s64)
(result s32))) ;; 11
(@interface type (func
(param $stmt_handle: u32 $icol: u32)
(result string))) ;; 12
(@interface type (func
(param $stmt_handle: u32 $icol: u32)
(result s32))) ;; 13
(result string))) ;; 13
(@interface type (func
(param $stmt_handle: u32 $icol: u32)
(result s32))) ;; 14
(param $db_handle: u32 $sql: string)
(result record 7))) ;; 14
(@interface type (func
(param $db_handle: u32)
(result s32))) ;; 15
(param $db_handle: u32 $sql: string)
(result record 7))) ;; 15
(@interface type (func
(param $db_handle: u32)
(result s32))) ;; 16
(@interface type (func
(param $stmt_handle: u32 $pos: s32 $value: f64)
(param $db_handle: u32)
(result s32))) ;; 17
(@interface type (func
(param $stmt_handle: u32 $pos: s32 $value: f64)
(result s32))) ;; 18
(@interface type (func
(param $filename: string $flags: s32 $vfs: string)
(result record 8))) ;; 19
(param $stmt_handle: u32 $pos: s32 $value: f64)
(result s32))) ;; 19
(@interface type (func
(param $filename: string $flags: s32 $vfs: string)
(result record 8))) ;; 20
(result record 6))) ;; 20
(@interface type (func
(param $db_handle: u32)
(result s32))) ;; 21
(param $filename: string $flags: s32 $vfs: string)
(result record 6))) ;; 21
(@interface type (func
(param $db_handle: u32)
(result s32))) ;; 22
(@interface type (func
(param $stmt_handle: u32)
(param $db_handle: u32)
(result s32))) ;; 23
(@interface type (func
(param $stmt_handle: u32)
(result s32))) ;; 24
(@interface type (func
(param $stmt_handle: u32 $icol: u32)
(result s64))) ;; 25
(param $stmt_handle: u32)
(result s32))) ;; 25
(@interface type (func
(param $stmt_handle: u32 $icol: u32)
(result s64))) ;; 26
(param $stmt_handle: u32)
(result s32))) ;; 26
(@interface type (func
(param $db: u32)
(param $stmt_handle: u32)
(result s32))) ;; 27
(@interface type (func
(param $size: s64)
(result s64))) ;; 28
(@interface type (func
(param $size: s64)
(result s64))) ;; 29
(@interface type (func
(param $db: u32)
(result s32))) ;; 28
(result s32))) ;; 30
(@interface type (func
(param $stmt_handle: u32 $icol: s32)
(result f64))) ;; 29
(@interface type (func
(param $stmt_handle: u32 $icol: s32)
(result f64))) ;; 30
(@interface type (func
(param $db_handle: u32 $ms: u32)
(param $db: u32)
(result s32))) ;; 31
(@interface type (func
(param $db_handle: u32 $ms: u32)
(result s32))) ;; 32
(param $db_handle: u32 $sql: string $callback_id: s32 $callback_arg: s32)
(result record 8))) ;; 32
(@interface type (func
(param $db_handle: u32)
(result string))) ;; 33
(param $db_handle: u32 $sql: string $callback_id: s32 $callback_arg: s32)
(result record 8))) ;; 33
(@interface type (func
(param $db_handle: u32)
(result string))) ;; 34
(param $stmt_handle: u32 $icol: s32)
(result f64))) ;; 34
(@interface type (func
(param $stmt_handle: u32 $pos: s32 $value: s64)
(result s32))) ;; 35
(param $stmt_handle: u32 $icol: s32)
(result f64))) ;; 35
(@interface type (func
(param $stmt_handle: u32 $pos: s32 $value: s64)
(param $stmt_handle: u32 $icol: u32)
(result s32))) ;; 36
(@interface type (func
(param $stmt_handle: u32)
(param $stmt_handle: u32 $icol: u32)
(result s32))) ;; 37
(@interface type (func
(param $stmt_handle: u32)
(param $stmt_handle: u32 $pos: s32)
(result s32))) ;; 38
(@interface type (func
(param $db_handle: u32 $sql: string)
(result record 7))) ;; 39
(@interface type (func
(param $db_handle: u32 $sql: string)
(result record 7))) ;; 40
(@interface type (func
(param $stmt_handle: u32 $pos: s32)
(result s32))) ;; 39
(@interface type (func
(param $stmt_handle: u32 $pos: s32 $blob: array (u8) $xDel: s32)
(result s32))) ;; 40
(@interface type (func
(param $stmt_handle: u32 $pos: s32 $blob: array (u8) $xDel: s32)
(result s32))) ;; 41
(@interface type (func
(param $stmt_handle: u32 $pos: s32)
(param $db_handle: u32)
(result s32))) ;; 42
(@interface type (func
(param $stmt_handle: u32)
(param $db_handle: u32)
(result s32))) ;; 43
(@interface type (func
(param $stmt_handle: u32)
(result s32))) ;; 44
(@interface type (func
(param $stmt_handle: u32 $pos: s32 $blob: array (u8) $xDel: s32)
(param $stmt_handle: u32)
(result s32))) ;; 45
(@interface type (func
(param $stmt_handle: u32 $pos: s32 $blob: array (u8) $xDel: s32)
(param $stmt_handle: u32 $pos: s32 $text: string $xDel: s32)
(result s32))) ;; 46
(@interface type (func
(param $db_handle: u32)
(param $stmt_handle: u32 $pos: s32 $text: string $xDel: s32)
(result s32))) ;; 47
(@interface type (func
(param $db_handle: u32)
(param $stmt_handle: u32)
(result s32))) ;; 48
(@interface type (func
(param $stmt_handle: u32 $pos: s32 $text: string $xDel: s32)
(param $stmt_handle: u32)
(result s32))) ;; 49
(@interface type (func
(param $stmt_handle: u32 $pos: s32 $text: string $xDel: s32)
(result s32))) ;; 50
(param $size: s64)
(result s64))) ;; 50
(@interface type (func
(param $stmt_handle: u32)
(result s32))) ;; 51
(param $size: s64)
(result s64))) ;; 51
(@interface type (func
(param $stmt_handle: u32)
(result s32))) ;; 52
(@interface type (func
(param $db_handle: u32 $sql: string $callback_id: s32 $callback_arg: s32)
(result record 6))) ;; 53
(result s32))) ;; 53
(@interface type (func
(param $db_handle: u32 $sql: string $callback_id: s32 $callback_arg: s32)
(result record 6))) ;; 54
(param $stmt_handle: u32 $icol: u32)
(result s64))) ;; 54
(@interface type (func
(result s32))) ;; 55
(param $stmt_handle: u32 $icol: u32)
(result s64))) ;; 55
(@interface type (func
(param $db_handle: u32 $ms: u32)
(result s32))) ;; 56
(@interface type (func
(param $stmt_handle: u32 $icol: s32)
(result array (u8)))) ;; 57
(param $db_handle: u32 $ms: u32)
(result s32))) ;; 57
(@interface type (func
(param $stmt_handle: u32 $icol: s32)
(result array (u8)))) ;; 58
(@interface type (func
(param $stmt_handle: u32 $N: u32)
(result string))) ;; 59
(param $stmt_handle: u32 $icol: s32)
(result array (u8)))) ;; 59
(@interface type (func
(param $stmt_handle: u32 $N: u32)
(result string))) ;; 60
(@interface type (func
(param $stmt_handle: u32 $icol: u32)
(result s32))) ;; 61
(param $stmt_handle: u32 $N: u32)
(result string))) ;; 61
(@interface type (func
(param $stmt_handle: u32 $icol: u32)
(result s32))) ;; 62
(@interface type (func
(param $stmt_handle: u32 $icol: u32)
(result s32))) ;; 63
(@interface type (func
(param $db_handle: u32)
(result string))) ;; 64
(@interface type (func
(param $db_handle: u32)
(result string))) ;; 65
;; Adapters
(@interface func (type 11)
arg.get 0
i32.from_u32
arg.get 1
i32.from_u32
call-core 6
call-core 3
call-core 2
string.lift_memory
call-core 1)
(@interface func (type 13)
arg.get 0
i32.from_u32
arg.get 1
i32.from_u32
call-core 7
s32.from_i32)
(@interface func (type 15)
arg.get 0
i32.from_u32
call-core 8
s32.from_i32)
(@interface func (type 17)
arg.get 0
i32.from_u32
arg.get 1
i32.from_s32
arg.get 2
call-core 9
s32.from_i32)
(@interface func (type 19)
arg.get 0
string.size
i32.push 1
call-core 0
arg.get 0
string.lower_memory
arg.get 1
i32.from_s32
arg.get 2
string.size
i32.push 1
call-core 0
arg.get 2
string.lower_memory
call-core 10
call-core 3
record.lift_memory 8
call-core 1)
(@interface func (type 21)
arg.get 0
i32.from_u32
call-core 11
s32.from_i32)
(@interface func (type 23)
arg.get 0
i32.from_u32
call-core 12
s32.from_i32)
(@interface func (type 25)
arg.get 0
i32.from_u32
arg.get 1
i32.from_u32
call-core 13
s64.from_i64)
(@interface func (type 27)
arg.get 0
i32.from_u32
call-core 14
s32.from_i32)
(@interface func (type 29)
arg.get 0
i32.from_u32
arg.get 1
i32.from_s32
call-core 15)
(@interface func (type 31)
arg.get 0
i32.from_u32
arg.get 1
i32.from_u32
call-core 16
s32.from_i32)
(@interface func (type 33)
arg.get 0
i32.from_u32
call-core 17
call-core 3
call-core 2
string.lift_memory
call-core 1)
(@interface func (type 35)
(@interface func (type 10)
arg.get 0
i32.from_u32
arg.get 1
i32.from_s32
arg.get 2
i64.from_s64
call-core 18
call-core 6
s32.from_i32)
(@interface func (type 37)
(@interface func (type 12)
arg.get 0
i32.from_u32
call-core 19
s32.from_i32)
(@interface func (type 39)
arg.get 1
i32.from_u32
call-core 7
call-core 3
call-core 2
string.lift_memory
call-core 1)
(@interface func (type 14)
arg.get 0
i32.from_u32
arg.get 1
@ -313,23 +230,105 @@
call-core 0
arg.get 1
string.lower_memory
call-core 20
call-core 8
call-core 3
record.lift_memory 7
call-core 1)
(@interface func (type 41)
(@interface func (type 16)
arg.get 0
i32.from_u32
call-core 9
s32.from_i32)
(@interface func (type 18)
arg.get 0
i32.from_u32
arg.get 1
i32.from_s32
call-core 21
arg.get 2
call-core 10
s32.from_i32)
(@interface func (type 43)
(@interface func (type 20)
arg.get 0
string.size
i32.push 1
call-core 0
arg.get 0
string.lower_memory
arg.get 1
i32.from_s32
arg.get 2
string.size
i32.push 1
call-core 0
arg.get 2
string.lower_memory
call-core 11
call-core 3
record.lift_memory 6
call-core 1)
(@interface func (type 22)
arg.get 0
i32.from_u32
call-core 22
call-core 12
s32.from_i32)
(@interface func (type 45)
(@interface func (type 24)
arg.get 0
i32.from_u32
call-core 13
s32.from_i32)
(@interface func (type 26)
arg.get 0
i32.from_u32
call-core 14
s32.from_i32)
(@interface func (type 28)
arg.get 0
i64.from_s64
call-core 15
s64.from_i64)
(@interface func (type 30)
arg.get 0
i32.from_u32
call-core 16
s32.from_i32)
(@interface func (type 32)
arg.get 0
i32.from_u32
arg.get 1
string.size
i32.push 1
call-core 0
arg.get 1
string.lower_memory
arg.get 2
i32.from_s32
arg.get 3
i32.from_s32
call-core 17
call-core 3
record.lift_memory 8
call-core 1)
(@interface func (type 34)
arg.get 0
i32.from_u32
arg.get 1
i32.from_s32
call-core 18)
(@interface func (type 36)
arg.get 0
i32.from_u32
arg.get 1
i32.from_u32
call-core 19
s32.from_i32)
(@interface func (type 38)
arg.get 0
i32.from_u32
arg.get 1
i32.from_s32
call-core 20
s32.from_i32)
(@interface func (type 40)
arg.get 0
i32.from_u32
arg.get 1
@ -338,80 +337,95 @@
array.lower_memory u8
arg.get 3
i32.from_s32
call-core 21
s32.from_i32)
(@interface func (type 42)
arg.get 0
i32.from_u32
call-core 22
s32.from_i32)
(@interface func (type 44)
arg.get 0
i32.from_u32
call-core 23
s32.from_i32)
(@interface func (type 47)
(@interface func (type 46)
arg.get 0
i32.from_u32
arg.get 1
i32.from_s32
arg.get 2
string.size
i32.push 1
call-core 0
arg.get 2
string.lower_memory
arg.get 3
i32.from_s32
call-core 24
s32.from_i32)
(@interface func (type 49)
(@interface func (type 48)
arg.get 0
i32.from_u32
arg.get 1
i32.from_s32
arg.get 2
string.size
i32.push 1
call-core 0
arg.get 2
string.lower_memory
arg.get 3
i32.from_s32
call-core 25
s32.from_i32)
(@interface func (type 51)
(@interface func (type 50)
arg.get 0
i32.from_u32
i64.from_s64
call-core 26
s32.from_i32)
(@interface func (type 53)
arg.get 0
i32.from_u32
arg.get 1
string.size
i32.push 1
call-core 0
arg.get 1
string.lower_memory
arg.get 2
i32.from_s32
arg.get 3
i32.from_s32
s64.from_i64)
(@interface func (type 52)
call-core 27
call-core 3
record.lift_memory 6
call-core 1)
(@interface func (type 55)
call-core 28
s32.from_i32)
(@interface func (type 57)
(@interface func (type 54)
arg.get 0
i32.from_u32
arg.get 1
i32.from_u32
call-core 28
s64.from_i64)
(@interface func (type 56)
arg.get 0
i32.from_u32
arg.get 1
i32.from_u32
call-core 29
s32.from_i32)
(@interface func (type 58)
arg.get 0
i32.from_u32
arg.get 1
i32.from_s32
call-core 29
call-core 30
call-core 3
call-core 2
byte_array.lift_memory
call-core 1)
(@interface func (type 59)
arg.get 0
i32.from_u32
arg.get 1
i32.from_u32
call-core 30
call-core 3
call-core 2
string.lift_memory
call-core 1)
(@interface func (type 61)
(@interface func (type 60)
arg.get 0
i32.from_u32
arg.get 1
i32.from_u32
call-core 31
call-core 3
call-core 2
string.lift_memory
call-core 1)
(@interface func (type 62)
arg.get 0
i32.from_u32
arg.get 1
i32.from_u32
call-core 32
s32.from_i32)
(@interface func (type 64)
arg.get 0
i32.from_u32
call-core 33
call-core 3
call-core 2
string.lift_memory
call-core 1)
;; Exports
(@interface export "allocate" (func 0))
@ -420,57 +434,61 @@
(@interface export "get_result_ptr" (func 3))
(@interface export "set_result_size" (func 4))
(@interface export "set_result_ptr" (func 5))
(@interface export "sqlite3_column_text" (func 12))
(@interface export "sqlite3_column_bytes" (func 14))
(@interface export "sqlite3_close" (func 16))
(@interface export "sqlite3_bind_double" (func 18))
(@interface export "sqlite3_open_v2" (func 20))
(@interface export "sqlite3_changes" (func 22))
(@interface export "sqlite3_step" (func 24))
(@interface export "sqlite3_column_int64" (func 26))
(@interface export "sqlite3_errcode" (func 28))
(@interface export "sqlite3_column_double" (func 30))
(@interface export "sqlite3_busy_timeout" (func 32))
(@interface export "sqlite3_errmsg" (func 34))
(@interface export "sqlite3_bind_int64" (func 36))
(@interface export "sqlite3_finalize" (func 38))
(@interface export "sqlite3_prepare_v2" (func 40))
(@interface export "sqlite3_bind_null" (func 42))
(@interface export "sqlite3_column_count" (func 44))
(@interface export "sqlite3_bind_blob" (func 46))
(@interface export "sqlite3_total_changes" (func 48))
(@interface export "sqlite3_bind_text" (func 50))
(@interface export "sqlite3_reset" (func 52))
(@interface export "sqlite3_exec" (func 54))
(@interface export "sqlite3_libversion_number" (func 56))
(@interface export "sqlite3_column_blob" (func 58))
(@interface export "sqlite3_column_name" (func 60))
(@interface export "sqlite3_column_type" (func 62))
(@interface export "sqlite3_bind_int64" (func 11))
(@interface export "sqlite3_column_text" (func 13))
(@interface export "sqlite3_prepare_v2" (func 15))
(@interface export "sqlite3_close" (func 17))
(@interface export "sqlite3_bind_double" (func 19))
(@interface export "sqlite3_open_v2" (func 21))
(@interface export "sqlite3_changes" (func 23))
(@interface export "sqlite3_column_count" (func 25))
(@interface export "sqlite3_finalize" (func 27))
(@interface export "sqlite3_soft_heap_limit64" (func 29))
(@interface export "sqlite3_errcode" (func 31))
(@interface export "sqlite3_exec" (func 33))
(@interface export "sqlite3_column_double" (func 35))
(@interface export "sqlite3_column_bytes" (func 37))
(@interface export "sqlite3_bind_null" (func 39))
(@interface export "sqlite3_bind_blob" (func 41))
(@interface export "sqlite3_total_changes" (func 43))
(@interface export "sqlite3_step" (func 45))
(@interface export "sqlite3_bind_text" (func 47))
(@interface export "sqlite3_reset" (func 49))
(@interface export "sqlite3_hard_heap_limit64" (func 51))
(@interface export "sqlite3_libversion_number" (func 53))
(@interface export "sqlite3_column_int64" (func 55))
(@interface export "sqlite3_busy_timeout" (func 57))
(@interface export "sqlite3_column_blob" (func 59))
(@interface export "sqlite3_column_name" (func 61))
(@interface export "sqlite3_column_type" (func 63))
(@interface export "sqlite3_errmsg" (func 65))
;; Implementations
(@interface implement (func 12) (func 11))
(@interface implement (func 14) (func 13))
(@interface implement (func 16) (func 15))
(@interface implement (func 18) (func 17))
(@interface implement (func 20) (func 19))
(@interface implement (func 22) (func 21))
(@interface implement (func 24) (func 23))
(@interface implement (func 26) (func 25))
(@interface implement (func 28) (func 27))
(@interface implement (func 30) (func 29))
(@interface implement (func 32) (func 31))
(@interface implement (func 34) (func 33))
(@interface implement (func 36) (func 35))
(@interface implement (func 38) (func 37))
(@interface implement (func 40) (func 39))
(@interface implement (func 42) (func 41))
(@interface implement (func 44) (func 43))
(@interface implement (func 46) (func 45))
(@interface implement (func 48) (func 47))
(@interface implement (func 50) (func 49))
(@interface implement (func 52) (func 51))
(@interface implement (func 54) (func 53))
(@interface implement (func 56) (func 55))
(@interface implement (func 58) (func 57))
(@interface implement (func 60) (func 59))
(@interface implement (func 62) (func 61))
(@interface implement (func 11) (func 10))
(@interface implement (func 13) (func 12))
(@interface implement (func 15) (func 14))
(@interface implement (func 17) (func 16))
(@interface implement (func 19) (func 18))
(@interface implement (func 21) (func 20))
(@interface implement (func 23) (func 22))
(@interface implement (func 25) (func 24))
(@interface implement (func 27) (func 26))
(@interface implement (func 29) (func 28))
(@interface implement (func 31) (func 30))
(@interface implement (func 33) (func 32))
(@interface implement (func 35) (func 34))
(@interface implement (func 37) (func 36))
(@interface implement (func 39) (func 38))
(@interface implement (func 41) (func 40))
(@interface implement (func 43) (func 42))
(@interface implement (func 45) (func 44))
(@interface implement (func 47) (func 46))
(@interface implement (func 49) (func 48))
(@interface implement (func 51) (func 50))
(@interface implement (func 53) (func 52))
(@interface implement (func 55) (func 54))
(@interface implement (func 57) (func 56))
(@interface implement (func 59) (func 58))
(@interface implement (func 61) (func 60))
(@interface implement (func 63) (func 62))
(@interface implement (func 65) (func 64))

View File

@ -65,7 +65,10 @@ void write_le_int(unsigned char *array, unsigned int offset, unsigned int value)
array[offset + 3] = (value >> 24) & 0xff;
}
extern void __wasm_call_ctors();
int main() {
// the main purpose of this empty main is to initialize WASI subsystem
__wasm_call_ctors(); // for more details see https://github.com/WebAssembly/WASI/issues/471
return 0;
}