DMDB Database Driver for Node.js
DMDB is a native Node.js driver for the Dameng 8 (DM8) relational database, providing direct database connectivity and interaction. The current stable version is 1.0.48286 (as of March 2026), with a frequent release cadence, often monthly or bi-monthly, addressing bugs, performance, and new features. Key differentiators include its tight integration with the DM8 ecosystem, official support for Node.js versions 12 and above, and extensions for popular ORMs like TypeORM and Knex via `typeorm-dm` and `knex-dm` packages. The driver supports features like connection pooling, statement caching, and optional Snappy compression for internal communication. It also aims for compatibility with OracleDB-like API patterns, which is a significant aspect for developers migrating or working with similar database drivers.
Common errors
-
[6067] 字符串截断
cause Error when inserting strings of certain lengths using bind parameters, likely due to internal buffer handling or length calculation issues.fixUpgrade to dmdb v1.0.48286 or later. Ensure your string lengths are within defined database column limits. -
Bind param data failed by invalid param data type
cause Occurs when connecting to older database versions and attempting to insert long strings via bind parameters, indicating a mismatch in data type handling.fixUpgrade to dmdb v1.0.45146 or later. Consider upgrading your Dameng database server if the issue persists with older versions. -
[-2002] 执行未准备SQL语句
cause Executing arbitrary SQL statements between fetching a query result set and iterating through that result set can lead to this error. Also, concurrent operations on ResultSet or Lob objects are not supported.fixUpgrade to dmdb v1.0.45146 or later. Avoid interleaved SQL execution or concurrent operations on `ResultSet` and `Lob` objects. Process one result set completely before executing other queries or operating on another `ResultSet`. -
绑定参数个数过多
cause Providing more positional bind parameters than there are placeholders in the SQL statement.fixEnsure the number of bind parameters supplied in the `execute()` or `executeMany()` call exactly matches the number of placeholders (e.g., `:1`, `:2`, or `:name`) in your SQL statement. -
[6057] 长度或偏移错误
cause Occurs when reading large fields (LOBs) containing emoji characters in stream mode, indicating an issue with length or offset calculation for multi-byte characters.fixUpgrade to dmdb v1.0.46190 or later. Ensure your database character set is correctly configured to handle multi-byte characters like emojis.
Warnings
- breaking The format of `Results.outBinds` for `Connection.executeMany()` changed from row-grouped to column-grouped to align with OracleDB's behavior. Applications relying on the previous row-grouped format will need adjustment.
- breaking The `ResultSet.getRowCount()` interface has been removed because it is incompatible with forward-only result sets.
- breaking The default alias for connection pools has changed from `null` or `undefined` to `'default'`. Attempting to retrieve a pool without specifying an alias, or using a non-existent alias, will now result in an error.
- breaking The return format of `Result.outBinds`/`Results.outBinds` is no longer fixed as an array. It now depends on whether bind parameters were positioned (returns array) or named (returns object).
- breaking When binding `NaN`, `Infinity`, or `-Infinity` values as parameters, the driver now throws an error instead of implicitly binding them as `NULL`.
- breaking The default bind type for `number` parameters that represent integers has changed from `DOUBLE` to `BIGINT`. This may affect applications that rely on implicit type conversion or expect `DOUBLE` precision for integer values.
- gotcha The `snappy` and `snappyjs` dependencies are now optional. If Snappy compression is enabled on the DM8 server, one of these packages *must* be installed in your project, otherwise communication will fail.
- breaking A previous feature allowing `ExecuteOptions.outFormat` to control `Result.outBinds` format (array/object) was rolled back due to conflicts with `typeorm-dm`. `outBinds` are now fixed to return as arrays again. This can cause breaking changes if you adopted the short-lived `outFormat` option.
- gotcha The driver fixed an issue where date/time types had incorrect conversions in different time zones. Applications relying on the previous (incorrect) timezone behavior might see altered date/time values.
Install
-
npm install dmdb -
yarn add dmdb -
pnpm add dmdb
Imports
- dmdb
const dmdb = require('dmdb');import dmdb from 'dmdb';
- Connection
import { DmConnection } from 'dmdb';import { Connection } from 'dmdb'; - Pool
import { Pool } from 'dmdb'; - OUT_FORMAT_ARRAY
import { OUT_FORMAT_ARRAY } from 'dmdb';
Quickstart
import dmdb from 'dmdb';
interface MyQueryResult {
id: number;
name: string;
}
async function runDbOperations() {
let connection: dmdb.Connection | undefined;
let pool: dmdb.Pool | undefined;
try {
// Create a connection pool
pool = await dmdb.createPool({
user: process.env.DB_USER ?? 'SYSDBA',
password: process.env.DB_PASSWORD ?? 'SYSDBA',
connectString: process.env.DB_CONNECT_STRING ?? 'localhost:5236/DAMENG',
poolMin: 2,
poolMax: 4,
poolIncrement: 1,
poolAlias: 'default'
});
console.log('Connection pool created successfully.');
// Get a connection from the pool
connection = await pool.getConnection();
console.log('Connection obtained from pool.');
// Execute a simple query
const querySql = 'SELECT 1 AS id, \'Hello DMDB\' AS name FROM DUAL';
const result: dmdb.Result<MyQueryResult> = await connection.execute(querySql);
console.log('Query Result:', result.rows?.[0]);
// Execute a DML statement with bind parameters
const insertSql = 'INSERT INTO my_test_table (id, value) VALUES (:1, :2)';
const bindParams = [1001, 'Test Value'];
const insertResult = await connection.execute(insertSql, bindParams, { autoCommit: true });
console.log('Rows inserted:', insertResult.rowsAffected);
// Execute a query to fetch data from the inserted table
const fetchSql = 'SELECT id, value FROM my_test_table WHERE id = :id';
const fetchResult: dmdb.Result<{ id: number; value: string }> = await connection.execute(fetchSql, { id: 1001 });
console.log('Fetched data:', fetchResult.rows?.[0]);
} catch (err: any) {
console.error('Database operation failed:', err.message);
} finally {
if (connection) {
try {
await connection.close();
console.log('Connection released back to pool.');
} catch (closeErr: any) {
console.error('Error closing connection:', closeErr.message);
}
}
if (pool) {
try {
await pool.close();
console.log('Connection pool closed.');
} catch (poolCloseErr: any) {
console.error('Error closing pool:', poolCloseErr.message);
}
}
}
}
// A small helper to create the table if it doesn't exist
async function setupTable() {
let connection: dmdb.Connection | undefined;
try {
connection = await dmdb.getConnection({
user: process.env.DB_USER ?? 'SYSDBA',
password: process.env.DB_PASSWORD ?? 'SYSDBA',
connectString: process.env.DB_CONNECT_STRING ?? 'localhost:5236/DAMENG',
});
await connection.execute(`
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE my_test_table';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
`);
await connection.execute(`
CREATE TABLE my_test_table (
id NUMBER(10) PRIMARY KEY,
value VARCHAR2(50)
)
`);
console.log('Table my_test_table ensured.');
} catch (err: any) {
console.error('Table setup failed:', err.message);
} finally {
if (connection) {
await connection.close();
}
}
}
setupTable().then(() => runDbOperations());