Update to latest emscripten, add new methods

This commit is contained in:
Jérôme Laban 2018-09-19 16:40:31 -04:00
Родитель 1948f8873c
Коммит 24f88259dd
10 изменённых файлов: 164 добавлений и 59 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -4,3 +4,4 @@ temp/
debug/ debug/
dist/ dist/
node_modules/ node_modules/
/package-lock.json

Просмотреть файл

@ -6,7 +6,7 @@ SQLITE_AMALGAMATION_ZIP_SHA1 = e9dc46fc55a512b5d2ef97fd548b7ab4beb2d3e3
EXTENSION_FUNCTIONS = extension-functions.c EXTENSION_FUNCTIONS = extension-functions.c
EXTENSION_FUNCTIONS_URL = http://www.sqlite.org/contrib/download/extension-functions.c?get=25 EXTENSION_FUNCTIONS_URL = http://www.sqlite.org/contrib/download/extension-functions.c?get=25
EXTENSION_FUNCTIONS_SHA1 = c68fa706d6d9ff98608044c00212473f9c14892f EXTENSION_FUNCTIONS_SHA1 = da39a3ee5e6b4b0d3255bfef95601890afd80709
# source files # source files
@ -30,10 +30,14 @@ CFLAGS = \
EMFLAGS = \ EMFLAGS = \
-s ALLOW_MEMORY_GROWTH=1 \ -s ALLOW_MEMORY_GROWTH=1 \
-s EXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS_JSON) \ -s EXPORTED_FUNCTIONS="`cat $(EXPORTED_FUNCTIONS_JSON) | tr '\n' ' '`" \
-s RESERVED_FUNCTION_POINTERS=64 \ -s RESERVED_FUNCTION_POINTERS=64 \
-s EXTRA_EXPORTED_RUNTIME_METHODS="[\"cwrap\", \"getValue\", \"setValue\", \"addFunction\", \"removeFunction\", \"UTF8ToString\", \"print\"]" \
-s WASM=1 \ -s WASM=1 \
--post-js temp/api.js \ -s MODULARIZE=1 \
-s EXPORT_NAME="'SQLite'" \
--memory-init-file 0 \
--post-js temp/api.js \
EMFLAGS_DEBUG = \ EMFLAGS_DEBUG = \
-s INLINING_LIMIT=10 \ -s INLINING_LIMIT=10 \
@ -41,7 +45,7 @@ EMFLAGS_DEBUG = \
EMFLAGS_DIST = \ EMFLAGS_DIST = \
-s INLINING_LIMIT=50 \ -s INLINING_LIMIT=50 \
--closure 1 \ -s IGNORE_CLOSURE_COMPILER_ERRORS=1 \
-O3 -O3
# directories # directories

Просмотреть файл

@ -10,7 +10,7 @@
"author": "", "author": "",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@types/emscripten": "0.0.30", "@types/emscripten": "0.0.31",
"typescript": "^2.5.2" "typescript": "^2.5.2"
} }
} }

Просмотреть файл

@ -13,6 +13,8 @@
"_sqlite3_bind_int", "_sqlite3_bind_int",
"_sqlite3_bind_parameter_index", "_sqlite3_bind_parameter_index",
"_sqlite3_step", "_sqlite3_step",
"_sqlite3_last_insert_rowid",
"_sqlite3_bind_text16",
"_sqlite3_data_count", "_sqlite3_data_count",
"_sqlite3_column_double", "_sqlite3_column_double",
"_sqlite3_column_text", "_sqlite3_column_text",
@ -20,6 +22,8 @@
"_sqlite3_column_bytes", "_sqlite3_column_bytes",
"_sqlite3_column_type", "_sqlite3_column_type",
"_sqlite3_column_name", "_sqlite3_column_name",
"_sqlite3_column_count",
"_sqlite3_step",
"_sqlite3_reset", "_sqlite3_reset",
"_sqlite3_clear_bindings", "_sqlite3_clear_bindings",
"_sqlite3_finalize", "_sqlite3_finalize",

Просмотреть файл

@ -9,43 +9,64 @@ namespace Module {
} }
export class Connection { export class Connection {
private pDb: ptr<sqlite3> private databaseHandle: ptr<sqlite3>
public readonly "uri": string
constructor(public readonly filename: string, options: ConnectionOptions = {}) { public readonly uri: string
const opts = []
const vfs = options["vfs"] constructor(public readonly data: Uint8Array, options: ConnectionOptions = {}) {
if (vfs != null) { opts.push(`vfs=${encodeURIComponent(vfs)}`) }
const mode = options["mode"] const opts = this.buildOptions(options);
if (mode != null) { opts.push(`mode=${encodeURIComponent(mode)}`) } const filename = 'dbfile_' + (0xffffffff * Math.random() >>> 0);
const cache = options["cache"] const uri = this.uri = `file:${encodeURI(filename)}${opts ? "?" + opts : ""}`
if (cache != null) { opts.push(`cache=${encodeURIComponent(cache)}`) }
const psow = options["psow"]
if (psow != null) { opts.push(`psow=${Number(psow)}`) }
const nolock = options["nolock"]
if (nolock != null) { opts.push(`nolock=${Number(nolock)}`) }
const immutable = options["immutable"]
if (immutable != null) { opts.push(`nolock=${Number(immutable)}`) }
const q = opts.join("&")
const uri = this["uri"] = `file:${encodeURI(filename)}${q ? "?" + q : ""}`
const stack = stackSave() const stack = stackSave()
const ppDb = stackAlloc<ptr<sqlite3>>(4) const ppDb = stackAlloc<ptr<sqlite3>>(4)
const code = sqlite3_open(uri, ppDb) const code = sqlite3_open(uri, ppDb)
const pDb = Module["getValue"](ppDb, "*") const databaseHandle = Module["getValue"](ppDb, "*")
stackRestore(stack) stackRestore(stack)
if (code) { throw new SQLiteError(code) } if (code) {
throw new SQLiteError(code)
}
this.pDb = pDb as ptr<sqlite3> this.databaseHandle = databaseHandle as ptr<sqlite3>
} }
"close"(): void { public get id(): number {
const code = sqlite3_close_v2(this.pDb) return this.databaseHandle as number;
if (code) { throw new SQLiteError(code) }
delete this.pDb
} }
"exec"<T>( close(): void {
const code = sqlite3_close_v2(this.databaseHandle)
if (code) { throw new SQLiteError(code) }
delete this.databaseHandle
}
preparev2(sql: string) : Statement {
const stack = stackSave()
const ppStatement = stackAlloc<ptr<sqlite3>>(4)
const code = sqlite3_prepare2(this.databaseHandle, sql, -1, ppStatement, <ptr<sqlite3>>0);
const statementHandle = Module["getValue"](ppStatement, "*")
stackRestore(stack)
if (code) {
throw new SQLiteError(code)
}
return new Statement(statementHandle as ptr<sqlite3>);
}
getChanges(): number {
return sqlite3_changes(this.databaseHandle);
}
getLastInsertRowId(): number {
return sqlite3_last_insert_rowid(this.databaseHandle);
}
exec<T>(
sql: string, sql: string,
callback?: ((columns: {[k in string]: string}) => T | undefined), callback?: ((columns: {[k in string]: string}) => T | undefined),
): T | undefined { ): T | undefined {
@ -74,7 +95,7 @@ namespace Module {
const stack = stackSave() const stack = stackSave()
const ppErrmsg = stackAlloc(4) as ptr<sqlite3_ptr<string>> const ppErrmsg = stackAlloc(4) as ptr<sqlite3_ptr<string>>
const code = sqlite3_exec(this.pDb, sql, pCallback, 0, ppErrmsg) const code = sqlite3_exec(this.databaseHandle, sql, pCallback, 0, ppErrmsg)
const pErrmsg = Module["getValue"](ppErrmsg, "*") const pErrmsg = Module["getValue"](ppErrmsg, "*")
stackRestore(stack) stackRestore(stack)
@ -88,5 +109,23 @@ namespace Module {
if (code) { throw new SQLiteError(code, errmsg) } if (code) { throw new SQLiteError(code, errmsg) }
return result return result
} }
private buildOptions(options: ConnectionOptions): string {
const opts = []
const vfs = options["vfs"]
if (vfs != null) { opts.push(`vfs=${encodeURIComponent(vfs)}`) }
const mode = options["mode"]
if (mode != null) { opts.push(`mode=${encodeURIComponent(mode)}`) }
const cache = options["cache"]
if (cache != null) { opts.push(`cache=${encodeURIComponent(cache)}`) }
const psow = options["psow"]
if (psow != null) { opts.push(`psow=${Number(psow)}`) }
const nolock = options["nolock"]
if (nolock != null) { opts.push(`nolock=${Number(nolock)}`) }
const immutable = options["immutable"]
if (immutable != null) { opts.push(`nolock=${Number(immutable)}`) }
return opts.join("&")
}
} }
} }

Просмотреть файл

@ -1,15 +1,5 @@
namespace Module { namespace Module {
export declare var onRuntimeInitialized: () => void export declare var onRuntimeInitialized: () => void
Module["onRuntimeInitialized"] = function () { Module["onRuntimeInitialized"] = function () {
const conn1 = new Connection("db", { mode: "memory", cache: "shared" })
const conn2 = new Connection("db", { mode: "memory", cache: "shared" })
Module["print"](conn1.uri)
conn1.exec(`create table t (x, y); insert into t values (1, 2), (3, 4);`)
conn2.exec(`select * from t;`, (columns) => {
Module["print"](JSON.stringify(columns))
})
conn1.close()
conn2.close()
} }
} }

Просмотреть файл

@ -13,19 +13,9 @@ namespace Module {
export declare function UTF8ToString(ptr: ptr<string>): string export declare function UTF8ToString(ptr: ptr<string>): string
export declare function stringToUTF8(str: string, outPtr: ptr<string>, maxBytesToWrite: number): void export declare function stringToUTF8(str: string, outPtr: ptr<string>, maxBytesToWrite: number): void
export const stackSave export declare function stackSave(): stack;
: () => stack export declare function stackRestore(stack: stack): void;
= Module["Runtime"].stackSave export declare function stackAlloc<T extends sized>(size: number & T["__size__"]): ptr<T>;
export const stackRestore export declare function addFunction<T extends Function>(func: T): ptr<T>;
: (stack: stack) => void export declare function removeFunction<T extends Function>(ptr: ptr<T>): void;
= Module["Runtime"].stackRestore
export const stackAlloc
: <T extends sized>(size: number & T["__size__"]) => ptr<T>
= Module["Runtime"].stackAlloc
export const addFunction
: <T extends Function>(func: T) => ptr<T>
= Module["Runtime"].addFunction
export const removeFunction
: <T extends Function>(ptr: ptr<T>) => void
= Module["Runtime"].removeFunction
} }

Просмотреть файл

@ -2,9 +2,47 @@ namespace Module {
export const sqlite3_open export const sqlite3_open
: (filename: string, ppDb: ptr<ptr<sqlite3>>) => SQLiteResult : (filename: string, ppDb: ptr<ptr<sqlite3>>) => SQLiteResult
= Module["cwrap"]("sqlite3_open", "number", ["string", "number"]) = Module["cwrap"]("sqlite3_open", "number", ["string", "number"])
export const sqlite3_last_insert_rowid
: (pDb: ptr<sqlite3>) => number
= Module["cwrap"]("sqlite3_last_insert_rowid", "number", ["number"])
export const sqlite3_prepare2
: (pDb: ptr<sqlite3>, sql: string, numBytes: number, pStatement: ptr<ptr<sqlite3>>, pzTail: ptr<sqlite3>) => SQLiteResult
= Module["cwrap"]("sqlite3_prepare_v2", "number", ["number", "string", "number", "number", "number"])
export const sqlite3_column_count
: (pStatement: ptr<sqlite3>) => number
= Module["cwrap"]("sqlite3_column_count", "number", ["number"])
export const sqlite3_step
: (pStatement: ptr<sqlite3>) => SQLiteResult
= Module["cwrap"]("sqlite3_step", "number", ["number"])
export const sqlite3_finalize
: (pStatement: ptr<sqlite3>) => SQLiteResult
= Module["cwrap"]("sqlite3_finalize", "number", ["number"])
export const sqlite3_reset
: (pStatement: ptr<sqlite3>) => SQLiteResult
= Module["cwrap"]("sqlite3_reset", "number", ["number"])
export const sqlite3_column_name
: (pStatement: ptr<sqlite3>, index: number) => string
= Module["cwrap"]("sqlite3_column_name", "number", ["number", "number"])
export const sqlite3_bind_text16
: (pStatement: ptr<sqlite3>, index: number, val: string, n: number, pFree: ptr<sqlite3>) => number
= Module["cwrap"]("sqlite3_bind_text16", "number", ["number", "number", "string", "number", "number"])
export const sqlite3_changes
: (pStatement: ptr<sqlite3>) => number
= Module["cwrap"]("sqlite3_changes", "number", ["number"])
export const sqlite3_close_v2 export const sqlite3_close_v2
: (pDb: ptr<sqlite3>) => SQLiteResult : (pDb: ptr<sqlite3>) => SQLiteResult
= Module["cwrap"]("sqlite3_close_v2", "number", ["number"]) = Module["cwrap"]("sqlite3_close_v2", "number", ["number"])
export const sqlite3_exec export const sqlite3_exec
: <T extends number>( : <T extends number>(
pDb: ptr<sqlite3>, pDb: ptr<sqlite3>,
@ -14,6 +52,7 @@ namespace Module {
errmsg: ptr<sqlite3_ptr<string>> | null errmsg: ptr<sqlite3_ptr<string>> | null
) => SQLiteResult ) => SQLiteResult
= Module["cwrap"]("sqlite3_exec", "number", ["number", "string", "number", "number", "number"]) = Module["cwrap"]("sqlite3_exec", "number", ["number", "string", "number", "number", "number"])
export const sqlite3_free export const sqlite3_free
: (ptr: sqlite3_ptr<any> | 0) => void : (ptr: sqlite3_ptr<any> | 0) => void
= Module["cwrap"]("sqlite3_free", "", ["number"]) = Module["cwrap"]("sqlite3_free", "", ["number"])

38
src/ts/statement.ts Normal file
Просмотреть файл

@ -0,0 +1,38 @@
namespace Module {
export class Statement {
private statementHandle: ptr<sqlite3>
constructor(statementHandle: ptr<sqlite3>) {
this.statementHandle = statementHandle;
}
public get id(): number {
return this.statementHandle as number;
}
getColumnCount(): number {
return sqlite3_column_count(this.statementHandle);
}
step(): SQLiteResult {
return sqlite3_step(this.statementHandle);
}
finalize(): SQLiteResult {
return sqlite3_finalize(this.statementHandle);
}
reset(): SQLiteResult {
return sqlite3_reset(this.statementHandle);
}
getColumnName(index: number): string {
return sqlite3_column_name(this.statementHandle, index);
}
bindText(index: number, value: string): number {
return sqlite3_bind_text16(this.statementHandle, index, value, -1, <ptr<sqlite3>>0);
}
}
}

Просмотреть файл

@ -1,7 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"alwaysStrict": false, "alwaysStrict": false,
"target": "es5", "target": "es6",
"module": "none", "module": "none",
"strict": true, "strict": true,
"outFile": "temp/api.js", "outFile": "temp/api.js",