Skip to content

Commit d4e61bd

Browse files
committed
test(javascript/driver-manager): add test suite
1 parent 9fbce52 commit d4e61bd

8 files changed

Lines changed: 733 additions & 0 deletions

File tree

javascript/__test__/bind.spec.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
import { test, before, after } from 'node:test'
19+
import assert from 'node:assert/strict'
20+
import { createSqliteDatabase, createTestTable } from './test_utils'
21+
import { AdbcDatabase, AdbcConnection, AdbcStatement } from '../lib/index.js'
22+
import { tableFromArrays, Table } from 'apache-arrow'
23+
24+
let db: AdbcDatabase
25+
let conn: AdbcConnection
26+
let stmt: AdbcStatement
27+
28+
before(async () => {
29+
db = await createSqliteDatabase()
30+
conn = await db.connect()
31+
stmt = await conn.createStatement()
32+
await createTestTable(stmt, 'bind_test')
33+
})
34+
35+
after(async () => {
36+
try {
37+
await stmt?.close()
38+
await conn?.close()
39+
await db?.close()
40+
} catch {
41+
// ignore
42+
}
43+
})
44+
45+
test('statement: bind and query data', async () => {
46+
const recordBatchToBind = tableFromArrays({
47+
id: [null],
48+
name: ['test_name'],
49+
})
50+
51+
assert.strictEqual(recordBatchToBind.numRows, 1)
52+
await stmt.bind(recordBatchToBind)
53+
54+
await stmt.setSqlQuery('INSERT INTO bind_test (id, name) VALUES (?, ?)')
55+
const insertResult = await stmt.executeUpdate()
56+
assert.strictEqual(insertResult, 1)
57+
58+
await stmt.setSqlQuery('SELECT id, name FROM bind_test')
59+
const reader = await stmt.executeQuery()
60+
61+
let rowCount = 0
62+
for await (const batch of reader) {
63+
rowCount += batch.numRows
64+
const idVector = batch.getChild('id')
65+
const nameVector = batch.getChild('name')
66+
assert.strictEqual(idVector?.get(0), null)
67+
assert.strictEqual(nameVector?.get(0), 'test_name')
68+
}
69+
70+
assert.strictEqual(rowCount, 1)
71+
})
72+
73+
test('statement: bind multi-batch table throws descriptive error', async () => {
74+
// Both batches must share the same schema instance for Table to accept them
75+
const base = tableFromArrays({ id: [10], name: ['first'] })
76+
const batch1 = base.batches[0]
77+
const batch2 = base.batches[0] // same schema, reused to construct a multi-batch Table
78+
const multiTable = new Table([batch1, batch2])
79+
assert.strictEqual(multiTable.batches.length, 2)
80+
81+
const stmt2 = await conn.createStatement()
82+
const error = await stmt2.bind(multiTable).catch((e) => e)
83+
assert.ok(error instanceof Error)
84+
assert.match(error.message, /bind\(\).*batches|batches.*bind\(\)/i)
85+
await stmt2.close()
86+
})
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
import { test, before, after } from 'node:test'
19+
import assert from 'node:assert/strict'
20+
import { createSqliteDatabase } from './test_utils'
21+
import { AdbcDatabase, AdbcConnection, AdbcStatement, AdbcError } from '../lib/index.js'
22+
23+
let db: AdbcDatabase
24+
let conn: AdbcConnection
25+
let stmt: AdbcStatement
26+
27+
before(async () => {
28+
db = await createSqliteDatabase()
29+
conn = await db.connect()
30+
stmt = await conn.createStatement()
31+
})
32+
33+
after(async () => {
34+
try {
35+
await stmt?.close()
36+
await conn?.close()
37+
await db?.close()
38+
} catch {
39+
// ignore
40+
}
41+
})
42+
43+
test('error: invalid sql syntax', async () => {
44+
await stmt.setSqlQuery('SELECT * FROM') // Syntax error
45+
46+
let error: unknown
47+
try {
48+
const reader = await stmt.executeQuery()
49+
for await (const _ of reader) {
50+
}
51+
} catch (e) {
52+
error = e
53+
}
54+
55+
assert.ok(error instanceof AdbcError)
56+
assert.match(error.message, /syntax error|incomplete input/i)
57+
assert.ok(error.sqlState)
58+
})
59+
60+
test('error: table not found', async () => {
61+
await stmt.setSqlQuery('SELECT * FROM non_existent_table')
62+
63+
let error: unknown
64+
try {
65+
const reader = await stmt.executeQuery()
66+
for await (const _ of reader) {
67+
}
68+
} catch (e) {
69+
error = e
70+
}
71+
72+
assert.ok(error instanceof AdbcError)
73+
assert.match(error.message, /no such table/i)
74+
})
75+
76+
test('error: constraint violation', async () => {
77+
const setupStmt = await conn.createStatement()
78+
await setupStmt.setSqlQuery('CREATE TABLE IF NOT EXISTS err_test (id INTEGER PRIMARY KEY)')
79+
await setupStmt.executeUpdate()
80+
await setupStmt.setSqlQuery('INSERT INTO err_test (id) VALUES (1)')
81+
await setupStmt.executeUpdate()
82+
await setupStmt.close()
83+
84+
await stmt.setSqlQuery('INSERT INTO err_test (id) VALUES (1)')
85+
let error: unknown
86+
try {
87+
await stmt.executeUpdate()
88+
} catch (e) {
89+
error = e
90+
}
91+
92+
assert.ok(error instanceof AdbcError)
93+
assert.match(error.code, /AlreadyExists|Integrity|IO/)
94+
})
95+
96+
test('error: unsupported option', () => {
97+
// SQLite does not support the read_only connection option at runtime
98+
let error: unknown
99+
try {
100+
conn.setOption('adbc.connection.read_only', 'true')
101+
} catch (e) {
102+
error = e
103+
}
104+
105+
assert.ok(error instanceof AdbcError)
106+
assert.strictEqual(error.code, 'NotImplemented')
107+
})
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
import { test, before, after } from 'node:test'
19+
import assert from 'node:assert/strict'
20+
import { createSqliteDatabase, createTestTable, dumpReader } from './test_utils'
21+
import { AdbcDatabase, AdbcConnection, AdbcStatement } from '../lib/index.js'
22+
23+
let db: AdbcDatabase
24+
let conn: AdbcConnection
25+
let stmt: AdbcStatement
26+
27+
before(async () => {
28+
db = await createSqliteDatabase()
29+
conn = await db.connect()
30+
stmt = await conn.createStatement()
31+
await createTestTable(stmt, 'metadata_test')
32+
})
33+
34+
after(async () => {
35+
try {
36+
await stmt?.close()
37+
await conn?.close()
38+
await db?.close()
39+
} catch (e) {
40+
console.error('Error cleaning up test resources:', e)
41+
}
42+
})
43+
44+
test('metadata: getTableTypes', async () => {
45+
const tableTypes = await dumpReader(await conn.getTableTypes())
46+
47+
// Sort actual results for consistent comparison
48+
tableTypes.sort((a, b) => (a.table_type || '').localeCompare(b.table_type || ''))
49+
50+
assert.strictEqual(tableTypes[0].table_type, 'table')
51+
assert.strictEqual(tableTypes[1].table_type, 'view')
52+
})
53+
54+
test('metadata: getTableSchema', async () => {
55+
const schema = await conn.getTableSchema({ tableName: 'metadata_test' })
56+
57+
assert.strictEqual(schema.fields[0].name, 'id')
58+
assert.strictEqual(schema.fields[0].nullable, true)
59+
assert.strictEqual(schema.fields[1].name, 'name')
60+
assert.strictEqual(schema.fields[1].nullable, true)
61+
})
62+
63+
test('metadata: getObjects', async () => {
64+
// SQLite structure: Catalog (null/main) -> Schemas (null/main) -> Tables
65+
const objects = await dumpReader(
66+
await conn.getObjects({
67+
depth: 3,
68+
tableName: 'metadata_test',
69+
tableType: ['table', 'view'],
70+
}),
71+
)
72+
73+
const tables = objects[0].catalog_db_schemas[0].db_schema_tables
74+
assert.ok(tables.some((t: { table_name: string }) => t.table_name === 'metadata_test'))
75+
})
76+
77+
test('metadata: getInfo', async () => {
78+
const info = await dumpReader(await conn.getInfo())
79+
80+
assert.strictEqual(info[0].info_name, 0)
81+
assert.strictEqual(info[0].info_value, 'SQLite')
82+
})
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
import { test, before, after } from 'node:test'
19+
import assert from 'node:assert/strict'
20+
import { createSqliteDatabase } from './test_utils'
21+
import { AdbcDatabase, AdbcConnection, AdbcStatement, AdbcError } from '../lib/index.js'
22+
23+
let db: AdbcDatabase
24+
let conn: AdbcConnection
25+
let stmt: AdbcStatement
26+
27+
before(async () => {
28+
db = await createSqliteDatabase()
29+
conn = await db.connect()
30+
stmt = await conn.createStatement()
31+
})
32+
33+
after(async () => {
34+
try {
35+
await stmt?.close()
36+
await conn?.close()
37+
await db?.close()
38+
} catch {
39+
// ignore
40+
}
41+
})
42+
43+
test('options: connection setOption', () => {
44+
// Test setting autocommit via canonical ADBC key (supported by SQLite)
45+
assert.doesNotThrow(() => {
46+
conn.setOption('adbc.connection.autocommit', 'true')
47+
})
48+
49+
// Test setting read_only via canonical ADBC key (not supported by SQLite at runtime)
50+
let errorReadOnly: unknown
51+
try {
52+
conn.setOption('adbc.connection.read_only', 'false')
53+
} catch (e) {
54+
errorReadOnly = e
55+
}
56+
assert.ok(errorReadOnly instanceof AdbcError)
57+
assert.strictEqual(errorReadOnly.code, 'NotImplemented')
58+
assert.match(errorReadOnly.message, /Unknown connection option/i)
59+
60+
// Test setting generic option (SQLite driver is strict and rejects unknown options)
61+
let errorCustom: unknown
62+
try {
63+
conn.setOption('custom_option', 'custom_value')
64+
} catch (e) {
65+
errorCustom = e
66+
}
67+
assert.ok(errorCustom instanceof AdbcError)
68+
assert.strictEqual(errorCustom.code, 'NotImplemented')
69+
})
70+
71+
test('options: statement setOption', () => {
72+
// Test setting an unknown statement option (SQLite driver is strict)
73+
let error: unknown
74+
try {
75+
stmt.setOption('adbc.stmt.some_option', 'value')
76+
} catch (e) {
77+
error = e
78+
}
79+
assert.ok(error instanceof AdbcError)
80+
assert.strictEqual(error.code, 'NotImplemented')
81+
assert.match(error.message, /Unknown statement option/i)
82+
})

0 commit comments

Comments
 (0)