Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
59bc177
Add sql.js fallback for sqlite in wasm
BobdenOs Apr 23, 2024
f456747
Update package.json
BobdenOs Apr 24, 2024
3a56fe1
Adding sql.js test pipeline
BobdenOs Apr 24, 2024
e44a447
Double checking that the fallback is tested
BobdenOs Apr 24, 2024
9b1281a
Adjust better-sqlite3 removal
BobdenOs Apr 24, 2024
3ebf2f4
Remove debug logging
BobdenOs Apr 24, 2024
1f5d2c7
Merge branch 'main' into sqlite/wasm
BobdenOs Apr 24, 2024
c4e2562
Merge branch 'main' into sqlite/wasm
BobdenOs May 28, 2024
6546a7d
Remove linting warning
BobdenOs May 28, 2024
8bc8319
merge
BobdenOs Sep 17, 2025
19f4043
Bump sql.js version and fix streaming support
BobdenOs Sep 17, 2025
54c4b27
Run sql.js tests after all other tests
BobdenOs Sep 17, 2025
4235bf9
sync
BobdenOs Feb 26, 2026
8f4a3e0
make better-sqlite3 an optional dependency
BobdenOs Feb 26, 2026
15aa62b
add driver option for sqlite
BobdenOs Feb 26, 2026
2123ecf
polyfill missing math functions for sql.js
BobdenOs Feb 26, 2026
6644bfe
retain CDS_REQUIRES_DB_DRIVER for tests
BobdenOs Feb 26, 2026
a3367fa
add non default sqlite driver tests
BobdenOs Feb 26, 2026
7c00fa9
Merge branch 'main' into sqlite/wasm
BobdenOs Feb 26, 2026
5c17a7c
make better-sqlite3 a normal dependency again
BobdenOs Feb 26, 2026
51fa585
Merge branch 'sqlite/wasm' of https://github.com/cap-js/cds-dbs into …
BobdenOs Feb 26, 2026
12be223
add sql.js as dev dependency for testing
BobdenOs Feb 26, 2026
94d2df2
Apply suggestion from @johannes-vogel
johannes-vogel Feb 27, 2026
2f8ce65
Merge branch 'main' into sqlite/wasm
sjvans Mar 2, 2026
03a4dcb
move common env variables to job level
BobdenOs Mar 2, 2026
d67fd65
Merge branch 'sqlite/wasm' of https://github.com/cap-js/cds-dbs into …
BobdenOs Mar 2, 2026
0055a0d
Merge branch 'main' into sqlite/wasm
BobdenOs Mar 2, 2026
149df0b
rm legacy
johannes-vogel Mar 2, 2026
8764066
Disable builtin pool for Postgres tests
BobdenOs Mar 3, 2026
f8d2604
Merge branch 'sqlite/wasm' of https://github.com/cap-js/cds-dbs into …
BobdenOs Mar 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/sqlite-wasm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Tests WASM

on:
push:
branches: [main]
pull_request:
types: [opened, synchronize, reopened, auto_merge_enabled]

# Allow parallel jobs on `main`, so that each commit is tested. For PRs, run only the latest commit.
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 5
name: Node.js ${{ matrix.node }}

strategy:
fail-fast: true
matrix:
node: [18]

steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: 'npm'

- run: npm ci
# Remove better-sqlite3 to force switching to sql.js
- run: npm install sql.js && rm -rf node_modules/better-sqlite3/
- run: npm test -w sqlite -- --maxWorkers=1
env:
FORCE_COLOR: true
Comment thread Fixed
16 changes: 13 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 14 additions & 7 deletions sqlite/lib/SQLiteService.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
const { SQLService } = require('@cap-js/db-service')
const cds = require('@sap/cds')
const sqlite = require('better-sqlite3')
const cds = require('@sap/cds/lib')
let sqlite
try {
sqlite = require('better-sqlite3')
} catch (err) {

Check warning on line 6 in sqlite/lib/SQLiteService.js

View workflow job for this annotation

GitHub Actions / Tests (22)

'err' is defined but never used
// When failing to load better-sqlite3 it fallsback to sql.js (wasm version of sqlite)
sqlite = require('./sql.js.js')
}

const $session = Symbol('dbc.session')
const sessionVariableMap = require('./session.json') // Adjust the path as necessary for your project
const convStrm = require('stream/consumers')
Expand Down Expand Up @@ -28,9 +35,11 @@
get factory() {
return {
options: { max: 1, ...this.options.pool },
create: tenant => {
create: async tenant => {
const database = this.url4(tenant)
const dbc = new sqlite(database, this.options.client)
await dbc.ready

const deterministic = { deterministic: true }
dbc.function('session_context', key => dbc[$session][key])
dbc.function('regexp', deterministic, (re, x) => (RegExp(re).test(x) ? 1 : 0))
Expand Down Expand Up @@ -134,10 +143,8 @@
}

async _allStream(stmt, binding_params, one, objectMode) {
stmt = stmt.constructor.name === 'Statement' ? stmt : stmt.__proto__
stmt.raw(true)
const get = stmt.get(binding_params)
if (!get) return []
stmt = stmt.iterate ? stmt : stmt.__proto__
stmt.raw?.(true)
const rs = stmt.iterate(binding_params)
const stream = Readable.from(objectMode ? this._iteratorObjectMode(rs) : this._iteratorRaw(rs, one), { objectMode })
const close = () => rs.return() // finish result set when closed early
Expand Down
90 changes: 90 additions & 0 deletions sqlite/lib/sql.js.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
const initSqlJs = require('sql.js');

const init = initSqlJs({})

class WasmSqlite {
constructor(/*database*/) {
// TODO: load / store database file contents
this.ready = init
.then(SQL => { this.db = new SQL.Database() })

this.memory = true
this.gc = new FinalizationRegistry(stmt => { stmt.free() })
}

prepare(sql) {
const stmt = this.db.prepare(sql)
const ret = {
run(params) {
try {
stmt.bind(params)
stmt.step()
return { changes: stmt.db.getRowsModified(stmt) }
} catch (err) {
if (err.message.indexOf('NOT NULL constraint failed:') === 0) {
err.code = 'SQLITE_CONSTRAINT_NOTNULL'
}
throw err
}
},
get(params) {
const columns = stmt.getColumnNames()
stmt.bind(params)
stmt.step()
const row = stmt.get()
const ret = {}
for (let i = 0; i < columns.length; i++) {
ret[columns[i]] = row[i]
}
return ret
},
all(params) {
const columns = stmt.getColumnNames()
const ret = []
stmt.bind(params)
while (stmt.step()) {
const row = stmt.get()
const obj = {}
for (let i = 0; i < columns.length; i++) {
obj[columns[i]] = row[i]
}
ret.push(obj)
}
return ret
},
*iterate(params) {
stmt.bind(params)
while (stmt.step()) {
yield stmt.get()
}
}
}
this.gc.register(ret, stmt)
return ret
}

exec(sql) {
try {
const { columns, values } = this.db.exec(sql)
return !Array.isArray(values) ? values : values.map(val => {
const ret = {}
for (let i = 0; i < columns.length; i++) {
ret[columns[i]] = val[i]
}
return ret
})
} catch (err) {
// REVISIT: address transaction errors
if (sql === 'BEGIN' || sql === 'ROLLBACK') { return }
throw err
}
}

function(name, config, func) {
this.db.create_function(name, func || config)
}

close() { this.db.close() }
}

module.exports = WasmSqlite
8 changes: 7 additions & 1 deletion sqlite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@
"better-sqlite3": "^12.0.0"
},
"peerDependencies": {
"@sap/cds": ">=9"
"@sap/cds": ">=9",
"sql.js": "^1.13.0"
},
"peerDependenciesMeta": {
"sql.js": {
"optional": true
}
},
"cds": {
"requires": {
Expand Down
Loading