Skip to content

Commit 707291d

Browse files
committed
Fix bug in db.exec with queries that contain ';'
db.exec used the character ';' to split queries. But a single statement can contain a ';' character. Since the js string is not split anymore, you might also notice a small performance improvement while using db.exec with many different queries. Fix sql-js#73
1 parent 89f1b96 commit 707291d

File tree

2 files changed

+22
-5
lines changed

2 files changed

+22
-5
lines changed

coffee/api.coffee

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -307,12 +307,25 @@ class Database
307307
###
308308
'exec': (sql) ->
309309
if not @db then throw "Database closed"
310+
311+
stack = Runtime.stackSave()
312+
# Store the SQL string in memory. The string will be consumed, one statement
313+
# at a time, by sqlite3_prepare_v2_sqlptr.
314+
# Allocate at most 4 bytes per UTF8 char, +1 for the trailing '\0'
315+
nextSqlPtr = Runtime.stackAlloc(sql.length<<2 + 1)
316+
writeStringToMemory sql, nextSqlPtr
317+
# Used to store a pointer to the next SQL statement in the string
318+
pzTail = Runtime.stackAlloc(4)
319+
310320
results = []
311-
for sqlstr in sql.split ';'
312-
try stmt = @['prepare'] sqlstr
313-
catch err
314-
if err is 'Nothing to prepare' then continue
315-
else throw err
321+
while getValue(nextSqlPtr,'i8') isnt NULL
322+
setValue apiTemp, 0, 'i32'
323+
setValue pzTail, 0, 'i32'
324+
@handleError sqlite3_prepare_v2_sqlptr @db, nextSqlPtr, -1, apiTemp, pzTail
325+
pStmt = getValue apiTemp, 'i32' # pointer to a statement, or null
326+
nextSqlPtr = getValue pzTail, 'i32'
327+
if pStmt is NULL then continue # Empty statement
328+
stmt = new Statement pStmt, this
316329
curresult = null
317330
while stmt['step']()
318331
if curresult is null
@@ -322,6 +335,7 @@ class Database
322335
results.push curresult
323336
curresult['values'].push stmt['get']()
324337
stmt['free']()
338+
Runtime.stackRestore stack
325339
return results
326340

327341
### Execute an sql statement, and call a callback for each row of result.

coffee/exports.coffee

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ sqlite3_free = Module['cwrap'] 'sqlite3_free', '', ['number']
66
# Prepared statements
77
## prepare
88
sqlite3_prepare_v2 = Module['cwrap'] 'sqlite3_prepare_v2', 'number', ['number', 'string', 'number', 'number', 'number']
9+
# Version of sqlite3_prepare_v2 to which a pointer to a string that is already
10+
# in memory is passed.
11+
sqlite3_prepare_v2_sqlptr = Module['cwrap'] 'sqlite3_prepare_v2', 'number', ['number', 'number', 'number', 'number', 'number']
912
## Bind parameters
1013

1114
#int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));

0 commit comments

Comments
 (0)