Fix insertTablet serialization, add SessionDataSet iterator, and align query handling with Java/C# clients (#4) * Initial plan * Fix insertTablet serialization and add sql_dialect support - Fix insertTablet to serialize data column-by-column instead of row-by-row - Add bitmap support for null values after column data - Add sqlDialect field to Config interface - Pass sqlDialect in TSOpenSessionReq configuration - Default TableSessionPool to use sql_dialect = "table" * Update sql_dialect to be internal-only, retain USE DATABASE logic - Remove sqlDialect from public Config interface - Add InternalConfig with sqlDialect field for internal use only - SessionPool automatically sets sql_dialect="tree" - TableSessionPool automatically sets sql_dialect="table" - Retain USE DATABASE logic in TableSessionPool for database context - Users don't need to specify sql_dialect - it's determined by pool type * Fix string byte length serialization - Change string serialization to write byte length instead of character length - This ensures UTF-8 multi-byte characters are handled correctly * Fix endianness issue in TEXT/STRING/BLOB serialization - Change from little-endian (writeInt32LE) to big-endian (writeInt32BE) - Java's ReadWriteIOUtils expects big-endian byte order - This fixes BufferUnderflowException when inserting TEXT/STRING/BLOB data * Address code review feedback - Fix bitmap byte count calculation to use Math.ceil instead of floor+1 - Add database name validation to prevent SQL injection - Database names must only contain alphanumeric, underscores, hyphens, and dots * Migrate Thrift generation to TypeScript - Generate TypeScript declaration files (.d.ts) alongside JavaScript - Use official Apache Thrift compiler with ts option instead of @creditkarma/thrift-typescript - Update generate:thrift script to use: thrift --gen js:node,ts - Update GitHub workflow to generate TypeScript definitions - Add comprehensive thrift/README.md documentation - Remove @creditkarma/thrift-typescript dependency - Remove unused fix-thrift-int64.js script (not needed with official compiler) - Update build to copy both .js and .d.ts files to dist/ * Add TypeScript examples documentation and cleanup - Add docs/TYPESCRIPT_EXAMPLES.md with usage examples - Remove unused scripts/fix-thrift-int64.js (not needed with official compiler) - Document benefits of TypeScript support * Reorganize documentation structure - Move API docs to docs/: implementation.md, data-types.md, thrift.md, typescript-examples.md - Move development docs to docs/development/: build-infrastructure.md, debugging-e2e.md, test-database.md - Move project-status.md to docs/ - Delete obsolete summary files: CI_CD_SUMMARY.md, COMMENT_RESPONSE_SUMMARY.md, DATABASE_CONSOLIDATION_SUMMARY.md, DATA_TYPES_IMPLEMENTATION_SUMMARY.md, E2E_FIX_ANALYSIS.md, ESLINT_9_UPGRADE.md, GLOB_FIX_DETAILS.md, IMPROVEMENTS_SUMMARY.md, NPM_DEPRECATIONS_FIXED.md - Keep in root: README.md, CONTRIBUTING.md, CHANGELOG.md, LICENSE - Add docs/README.md with comprehensive index - Update main README.md with documentation links section * Implement SessionDataSet with iterator pattern - Add RowRecord class for representing individual query result rows - Add SessionDataSet class with hasNext()/next() iterator pattern - Add executeQuery() method that returns SessionDataSet - Support lazy loading - fetches more data on-demand - Proper resource management with close() method - Column access by name or index with type safety - Keep executeQueryStatement() for backward compatibility (deprecated) - Add comprehensive E2E tests for SessionDataSet - Export new classes in index.ts * Add comprehensive SessionDataSet documentation - Add sessiondataset-guide.md with complete usage guide - Update README.md with SessionDataSet quick start example - Add SessionDataSet section highlighting benefits - Update docs/README.md to include new guide - Document migration from old QueryResult pattern - Add performance tips and best practices - Include troubleshooting section * Replace executeQueryStatement to return SessionDataSet - Remove executeQuery() method, keep only executeQueryStatement() - executeQueryStatement() now returns SessionDataSet instead of QueryResult - Remove old parseQueryResult() and recursive fetchResults() methods - Update BaseSessionPool.executeQueryStatement() to return SessionDataSet - Update Session.test.ts to use SessionDataSet iterator pattern - Update SessionDataSet.test.ts to use executeQueryStatement() - Mark QueryResult as deprecated * Update AllDataTypes.test.ts to use SessionDataSet API pattern * Update LargeQuery.test.ts to use SessionDataSet pattern * Update MultiNode.test.ts to use SessionDataSet pattern * Update TableModelDataTypes.test.ts to use SessionDataSet pattern * Update TableSessionPool.test.ts to use SessionDataSet pattern * Update documentation for SessionDataSet API changes - Remove all references to executeQuery() (no longer exists) - Update README to show executeQueryStatement returns SessionDataSet - Update sessiondataset-guide.md with new API - Add migration section explaining breaking change - Add toArray() helper for small datasets - Remove deprecated QueryResult examples * Add queryResult support and fix session release timing - Add support for both queryDataSet and queryResult formats in query responses - Add parseQueryResult() method to handle TsBlock format (Buffer[]) - Update Session.executeQueryStatement() to handle both formats - Update SessionDataSet.fetchNextBatch() to handle both formats - Add cleanup callback mechanism to SessionDataSet - Fix BaseSessionPool to release session only when dataset.close() is called - Session is now held until dataset is closed, not released immediately after query * Fix parseQueryResult to handle queries without time column - Add ignoreTimeStamp parameter to parseQueryResult() method - Extract ignoreTimeStamp from TSExecuteStatementResp - Pass ignoreTimeStamp to SessionDataSet constructor - Handle cases where time column is not present (ignoreTimeStamp=true) - When ignoreTimeStamp is true, all queryResult buffers are value columns - When ignoreTimeStamp is false, queryResult[0] is time column - Add helper methods getDataTypeCode() and getRowCountFromBuffer() - Update fetchNextBatch() to pass ignoreTimeStamp when parsing results - Matches Java and C# client implementations * 修复数据读取逻辑 * 修复查询 * Fix column name handling and add Docker log collection on CI failure - Add support for both full and short column names in SessionDataSet - Extract short name (last segment) and register both mappings - Add getShortColumnNames() method for convenience - Update SessionDataSet test to use getShortColumnNames() - Add Docker log collection step in e2e-1c1d.yml workflow (on failure) - Add Docker log collection step in e2e-3c3d.yml workflow (on failure) - Docker logs saved to test-results/docker-logs/ and uploaded as artifacts * Remove getShortColumnNames() and update tests to use fully qualified column names - Remove getShortColumnNames() method from SessionDataSet - Remove extractShortColumnName() private method - Remove short name registration from column index map - Update SessionDataSet.test.ts to use fully qualified column names - Tests now use "root.test.d1.s1" instead of "s1" - Tests now use "root.test.large.d1.value" instead of "value" - Tests now use "root.test.column.d1.temperature" instead of "temperature" - All column name assertions updated to expect full paths * Fix tree model aggregation function names to use lowercase - Change MAX_VALUE to max_value in tree model queries - Change MIN_VALUE to min_value in tree model queries - Tree model uses lowercase function names (max_value, min_value) - Table model continues to use standard SQL (MAX, MIN) - Fixes "UDF MAX has not been registered" error in AllDataTypes.test.ts * Fix timestamp endianness in insertTablet - use big-endian - Change timestamp serialization from little-endian to big-endian - Use writeBigInt64BE instead of BigInt64Array for timestamps - IoTDB protocol expects big-endian byte order (Java standard) - Matches C# client which converts to big-endian: Array.Reverse(longBuff) - Fixes issue where timestamps appeared negative in database * Fix TSQueryDataSet deserialization to use big-endian byte order - Change all numeric type deserialization from little-endian to big-endian - INT32: Use readInt32BE instead of Int32Array (little-endian) - INT64: Use readBigInt64BE instead of BigInt64Array (little-endian) - FLOAT: Use readFloatBE instead of Float32Array (little-endian) - DOUBLE: Use readDoubleBE instead of Float64Array (little-endian) - TIMESTAMP: Use readBigInt64BE instead of BigInt64Array - DATE: Use readInt32BE instead of Int32Array - TEXT/STRING/BLOB: Use readInt32BE for length prefix - TSQueryDataSet format uses Java's big-endian byte order - TsBlock format (ColumnDecoder) already correctly uses little-endian - Fixes test failures where values were byte-swapped (e.g., 9 → 150994944) * Fix TsBlock deserialization to use big-endian byte order - Change ColumnDecoder to use big-endian for all numeric types - INT32/DATE: readInt32BE instead of readInt32LE - INT64/TIMESTAMP: readBigInt64BE instead of readBigInt64LE - FLOAT: readFloatBE instead of readFloatLE - DOUBLE: readDoubleBE instead of readDoubleBE - TEXT/STRING/BLOB: Already uses readInt32BE for length prefix - TsBlock format (queryResult) uses big-endian byte order - Matches C# client which reverses bytes from big-endian to little-endian - Fixes byte-swap errors where 100 was read as 1677721600 * Fix insertTablet serialization and migrate to 1C3D cluster setup Part 1: Fix insertTablet column data serialization - Change INT32 from Int32Array (LE) to writeInt32BE (BE) - Change INT64 from BigInt64Array (LE) to writeBigInt64BE (BE) - Change FLOAT from Float32Array (LE) to writeFloatBE (BE) - Change DOUBLE from Float64Array (LE) to writeDoubleBE (BE) - Change DATE from Int32Array (LE) to writeInt32BE (BE) - All insertTablet data now uses big-endian to match IoTDB protocol - Fixes last 1c1d test failure: Expected 300, received 738263040 Part 2: Migrate from 3C3D to 1C3D cluster configuration - Create docker-compose-1c3d.yml: 1 ConfigNode + 3 DataNodes - Set schema_replication_factor=3 (metadata replicas) - Set data_replication_factor=2 (data replicas) - Rename e2e-3c3d.yml workflow to e2e-1c3d.yml - Update workflow to use 1c3d docker-compose file - Update container names: iotdb-datanode-1/2/3 (not iotdb-datanode1/2/3) - CN count doesn't affect testing, reduces resource usage * Update all examples to use SessionDataSet iterator pattern - Update basic-session.ts to use hasNext()/next()/close() - Update session-pool.ts to use SessionDataSet API - Update table-session-pool.ts to use SessionDataSet API - Update multi-node.ts to use SessionDataSet API - Update ssl-connection.ts to use SessionDataSet API - Replace old QueryResult API (.rows, .columns) with modern iterator pattern - All examples now demonstrate proper resource cleanup with close() - Examples match new SessionDataSet documentation * Fix MultiNode E2E test failures - Add beforeEach() to clean up root.test database before each test - Ensure clean state prevents "already exists" errors - Fix "Should create database and timeseries" test to handle clean state - Reduce stress test operations from 30 to 10 per pool to avoid timeout - Add 30s timeout to stress test (was using default 5s) - Fix "Should handle queries across all DataNodes simultaneously" test: - Insert data before querying to ensure results exist - Add 500ms delay for data availability - Add 20s timeout (was using default 5s) - Tests now properly handle multi-node cluster operations without timeouts * Initial plan * Fix beforeEach timeout in MultiNode E2E tests Add 60000ms timeout to beforeEach hook to prevent timeout failures in multi-node cluster operations. The hook performs async operations (DROP DATABASE + setTimeout) that can take longer than Jest's default timeout, especially in multi-node environments. This fixes the failing tests: - "Should support nodeUrls configuration for multi-node setup" - "Should support nodeUrls configuration in object format" Follows the same pattern as beforeAll (60000ms) and afterAll (90000ms) in the same file. * Optimize MultiNode tests - remove unnecessary cleanup and reduce delays - Remove beforeEach() cleanup - handle "already exists" errors like other tests - Create database with try-catch to ignore "already exist" errors (matches AllDataTypes.test.ts pattern) - Reduce replication wait from 2000ms to 200ms (10x faster) - Reduce data availability wait from 500ms to 100ms (5x faster) - Total time savings: ~2.5 seconds per test run - Matches pattern used in AllDataTypes.test.ts and SessionPool.test.ts - Tests now run much faster while maintaining correctness * Fix MultiNode test timeouts with parallel operations - Reduce stress test operations from 10 to 5 per pool (15 total) - Close datasets in parallel using Promise.all() instead of sequential loops - Process query results in parallel for 3 DataNodes simultaneously - Add explicit 10s timeouts to nodeUrls configuration tests - Parallel dataset closing is ~3x faster than sequential - Tests now complete well within timeout limits * Reduce IoTDB startup wait time in CI workflows - Reduce 1c1d startup wait from 45s to 5s - Reduce 1c3d startup wait from 75s to 5s - Total CI time savings: ~65 seconds per workflow run - Port verification step ensures containers are ready before tests run ---------
A Node.js client for Apache IoTDB with support for SessionPool and TableSessionPool, providing efficient connection management and comprehensive query capabilities.
npm install iotdb-client-nodejs
import { Session } from 'iotdb-client-nodejs'; const session = new Session({ host: 'localhost', port: 6667, username: 'root', password: 'root', }); await session.open(); // Execute non-query statement await session.executeNonQueryStatement('CREATE DATABASE root.test'); // Execute query with SessionDataSet (iterator pattern - memory efficient) const dataSet = await session.executeQueryStatement('SELECT * FROM root.test.**'); while (await dataSet.hasNext()) { const row = dataSet.next(); console.log(row.getTimestamp(), row.getFields()); } await dataSet.close(); // Or use toArray() helper for small result sets (loads all into memory) const dataSet2 = await session.executeQueryStatement('SHOW DATABASES'); const allRows = await dataSet2.toArray(); // Returns [[timestamp, ...fields], ...] console.log('All rows:', allRows); // Execute query with custom timeout (30 seconds) const customDataSet = await session.executeQueryStatement('SELECT * FROM root.test.**', 30000); // ... iterate and close // Insert tablet data await session.insertTablet({ deviceId: 'root.test.device1', measurements: ['temperature', 'humidity'], dataTypes: [3, 3], // FLOAT timestamps: [Date.now(), Date.now() + 1000], values: [ [25.5, 60.0], [26.0, 61.5], ], }); await session.close();
The Builder pattern provides a more elegant and fluent API for configuration:
import { Session, ConfigBuilder } from 'iotdb-client-nodejs'; // Build a session configuration const session = new Session( new ConfigBuilder() .host('localhost') .port(6667) .username('root') .password('root') .fetchSize(1024) .timezone('UTC+8') .build() ); await session.open(); // ... use session await session.close();
The executeQueryStatement() method returns a SessionDataSet for efficient iteration through query results:
import { Session, SessionDataSet, RowRecord } from 'iotdb-client-nodejs'; const session = new Session({ host: 'localhost', port: 6667, username: 'root', password: 'root', fetchSize: 1024, // Rows per fetch }); await session.open(); // Execute query and get SessionDataSet const dataSet: SessionDataSet = await session.executeQueryStatement( 'SELECT temperature, humidity FROM root.test.device1' ); // Iterate through results efficiently while (await dataSet.hasNext()) { const row: RowRecord = dataSet.next(); // Access by column name const temp = row.getFloat('temperature'); const humidity = row.getFloat('humidity'); // Access by index const timestamp = row.getTimestamp(); console.log(`${timestamp}: temp=${temp}, humidity=${humidity}`); } // Always close the dataset await dataSet.close(); await session.close();
Benefits of SessionDataSet:
close()See SessionDataSet Guide for complete documentation.
import { SessionPool } from 'iotdb-client-nodejs'; const pool = new SessionPool('localhost', 6667, { username: 'root', password: 'root', maxPoolSize: 10, minPoolSize: 2, maxIdleTime: 60000, waitTimeout: 60000, }); await pool.init(); // Execute queries using the pool const result = await pool.executeQueryStatement('SELECT * FROM root.test.**'); // Execute non-query statements await pool.executeNonQueryStatement( 'CREATE TIMESERIES root.test.device1.temperature WITH DATATYPE=FLOAT' ); // Insert data await pool.insertTablet({ deviceId: 'root.test.device1', measurements: ['temperature'], dataTypes: [3], // FLOAT timestamps: [Date.now()], values: [[25.5]], }); // Get pool statistics console.log('Pool size:', pool.getPoolSize()); console.log('Available:', pool.getAvailableSize()); await pool.close();
For more control, you can explicitly get and release sessions from the pool:
import { SessionPool } from 'iotdb-client-nodejs'; const pool = new SessionPool('localhost', 6667, { username: 'root', password: 'root', maxPoolSize: 10, }); await pool.init(); // Get a session from the pool const session = await pool.getSession(); try { // Use the session for multiple operations await session.executeNonQueryStatement('CREATE DATABASE root.test'); const result = await session.executeQueryStatement('SHOW DATABASES'); await session.insertTablet({ deviceId: 'root.test.device1', measurements: ['temperature'], dataTypes: [3], timestamps: [Date.now()], values: [[25.5]], }); } finally { // Always release the session back to the pool pool.releaseSession(session); } await pool.close();
When nodes have different host:port combinations, use the nodeUrls configuration with string array format:
import { SessionPool, PoolConfigBuilder } from 'iotdb-client-nodejs'; // Using config object with string array (RECOMMENDED) const pool1 = new SessionPool({ nodeUrls: [ 'node1.example.com:6667', 'node2.example.com:6668', 'node3.example.com:6669', ], username: 'root', password: 'root', maxPoolSize: 15, minPoolSize: 3, }); // Or using Builder pattern with string array const pool2 = new SessionPool( new PoolConfigBuilder() .nodeUrls([ 'node1.example.com:6667', 'node2.example.com:6668', 'node3.example.com:6669', ]) .username('root') .password('root') .maxPoolSize(15) .minPoolSize(3) .build() ); await pool1.init(); // Connections will be distributed across all nodes using round-robin
You can also use the object format for nodeUrls:
const pool = new SessionPool({ nodeUrls: [ { host: 'node1.example.com', port: 6667 }, { host: 'node2.example.com', port: 6668 }, { host: 'node3.example.com', port: 6669 }, ], username: 'root', password: 'root', maxPoolSize: 15, });
When all nodes share the same port:
import { SessionPool } from 'iotdb-client-nodejs'; const pool = new SessionPool( ['node1.example.com', 'node2.example.com', 'node3.example.com'], 6667, { username: 'root', password: 'root', maxPoolSize: 15, } ); await pool.init(); // Connections will be distributed across all nodes using round-robin
import { Session } from 'iotdb-client-nodejs'; import * as fs from 'fs'; const session = new Session({ host: 'localhost', port: 6667, username: 'root', password: 'root', enableSSL: true, sslOptions: { ca: fs.readFileSync('/path/to/ca.crt'), cert: fs.readFileSync('/path/to/client.crt'), key: fs.readFileSync('/path/to/client.key'), rejectUnauthorized: true, }, }); await session.open();
import { TableSessionPool } from 'iotdb-client-nodejs'; const tablePool = new TableSessionPool('localhost', 6667, { username: 'root', password: 'root', database: 'my_database', // Set default database for table model maxPoolSize: 10, minPoolSize: 2, }); await tablePool.init(); // Execute queries in table mode const result = await tablePool.executeQueryStatement('SHOW DATABASES'); await tablePool.close();
Fluent API for building Session configurations:
import { ConfigBuilder } from 'iotdb-client-nodejs'; const config = new ConfigBuilder() .host('localhost') .port(6667) .username('root') .password('root') .database('mydb') .timezone('UTC+8') .fetchSize(2048) .enableSSL(false) .build();
Methods:
host(host: string): this - Set the hostport(port: number): this - Set the portnodeUrls(nodeUrls: EndPoint[]): this - Set multiple node URLsusername(username: string): this - Set the usernamepassword(password: string): this - Set the passworddatabase(database: string): this - Set the databasetimezone(timezone: string): this - Set the timezonefetchSize(fetchSize: number): this - Set the fetch sizeenableSSL(enable: boolean): this - Enable or disable SSLsslOptions(sslOptions: SSLOptions): this - Set SSL optionsbuild(): Config - Build and return the configurationFluent API for building SessionPool configurations (extends ConfigBuilder):
import { PoolConfigBuilder } from 'iotdb-client-nodejs'; const config = new PoolConfigBuilder() .host('localhost') .port(6667) .username('root') .password('root') .maxPoolSize(20) .minPoolSize(5) .maxIdleTime(30000) .waitTimeout(45000) .build();
Additional Methods:
maxPoolSize(size: number): this - Set maximum pool sizeminPoolSize(size: number): this - Set minimum pool sizemaxIdleTime(time: number): this - Set maximum idle time (ms)waitTimeout(timeout: number): this - Set wait timeout (ms)build(): PoolConfig - Build and return the pool configurationIoTDB Node.js client supports all IoTDB data types including BOOLEAN, INT32, INT64, FLOAT, DOUBLE, TEXT, BLOB, STRING, DATE, and TIMESTAMP. See DATA_TYPES.md for comprehensive documentation on:
Option 1: Using config object
new Session(config: Config)
Option 2: Using Builder pattern (Recommended)
new Session(new ConfigBuilder()...build())
The config must include either:
host and port for single node connectionnodeUrls for multi-node connection (uses first node)async open(): Promise<void> - Open the sessionasync close(): Promise<void> - Close the sessionasync executeQueryStatement(sql: string, timeoutMs?: number): Promise<QueryResult> - Execute a query with optional timeout (default: 60000ms)async executeNonQueryStatement(sql: string): Promise<void> - Execute a non-query statementasync insertTablet(tablet: Tablet): Promise<void> - Insert tablet dataisOpen(): boolean - Check if session is openOption 1: Traditional API (Backward compatible)
new SessionPool(hosts: string | string[], port: number, config?: Partial<PoolConfig>)
Option 2: Using config object with nodeUrls
new SessionPool(config: PoolConfig)
Option 3: Using Builder pattern (Recommended)
new SessionPool(new PoolConfigBuilder()...build())
Connection Management:
async init(): Promise<void> - Initialize the poolasync close(): Promise<void> - Close all connectionsAutomatic Session Management:
async executeQueryStatement(sql: string, timeoutMs?: number): Promise<QueryResult> - Execute a query with optional timeout (default: 60000ms)async executeNonQueryStatement(sql: string): Promise<void> - Execute a non-query statementasync insertTablet(tablet: Tablet): Promise<void> - Insert tablet dataExplicit Session Management:
async getSession(): Promise<Session> - Get a session from the pool (must be released)releaseSession(session: Session): void - Release a session back to the poolPool Statistics:
getPoolSize(): number - Get current pool sizegetAvailableSize(): number - Get available connectionsgetInUseSize(): number - Get number of sessions currently in useSame as SessionPool but optimized for table model operations. Automatically executes USE DATABASE when configured with a database. All query methods support the same timeout parameter (default: 60000ms).
Same constructor options as SessionPool.
interface Config { host?: string; port?: number; nodeUrls?: string[] | EndPoint[]; // String array format: ["host1:6667", "host2:6668"] username?: string; password?: string; database?: string; timezone?: string; fetchSize?: number; enableSSL?: boolean; sslOptions?: SSLOptions; }
Note: Either host/port OR nodeUrls must be provided.
nodeUrls in string array format (e.g., ["host1:6667", "host2:6668"]) for nodes with different ports (RECOMMENDED)[{ host, port }] is also supported for backward compatibilityinterface EndPoint { host: string; port: number; }
interface PoolConfig extends Config { maxPoolSize?: number; minPoolSize?: number; maxIdleTime?: number; waitTimeout?: number; }
interface Tablet { deviceId: string; measurements: string[]; dataTypes: number[]; // 0=BOOLEAN, 1=INT32, 2=INT64, 3=FLOAT, 4=DOUBLE, 5=TEXT timestamps: number[]; values: any[][]; }
interface QueryResult { columns: string[]; dataTypes: string[]; rows: any[][]; queryId?: number; }
When using insertTablet, specify data types using these constants:
0 - BOOLEAN1 - INT322 - INT643 - FLOAT4 - DOUBLE5 - TEXTThe new version maintains full backward compatibility while adding new features. No changes are required for existing code, but you may want to adopt the new features:
Old way (still works, but limited to same port):
const pool = new SessionPool( ['node1', 'node2', 'node3'], 6667, { username: 'root', password: 'root' } );
New way (supports different ports per node with string format - RECOMMENDED):
const pool = new SessionPool({ nodeUrls: [ 'node1:6667', 'node2:6668', 'node3:6669', ], username: 'root', password: 'root', });
Alternative (object format also supported):
const pool = new SessionPool({ nodeUrls: [ { host: 'node1', port: 6667 }, { host: 'node2', port: 6668 }, { host: 'node3', port: 6669 }, ], username: 'root', password: 'root', });
Old way (still works):
const session = new Session({ host: 'localhost', port: 6667, username: 'root', password: 'root', fetchSize: 2048, });
New way (more fluent):
import { ConfigBuilder } from 'iotdb-client-nodejs'; const session = new Session( new ConfigBuilder() .host('localhost') .port(6667) .username('root') .password('root') .fetchSize(2048) .build() );
Old way (still works):
// Pool automatically manages sessions const result = await pool.executeQueryStatement('SELECT ...');
New way (more control):
// Explicitly get and release sessions const session = await pool.getSession(); try { const result1 = await session.executeQueryStatement('SELECT ...'); const result2 = await session.executeQueryStatement('SELECT ...'); // ... multiple operations with same session } finally { pool.releaseSession(session); }
npm install
npm run build
# Run all tests npm test # Run unit tests only npm run test:unit # Run E2E tests (requires IoTDB instance) export IOTDB_HOST=localhost export IOTDB_PORT=6667 npm run test:e2e
npm run lint
See the examples/ directory for more usage examples:
examples/basic-session.ts - Basic session usageexamples/session-pool.ts - SessionPool usageexamples/table-session-pool.ts - TableSessionPool usageexamples/multi-node.ts - Multi-node configurationexamples/ssl-connection.ts - SSL/TLS connectionComprehensive documentation is available in the docs/ directory:
Contributions are welcome! Please feel free to submit a Pull Request.
See CONTRIBUTING.md for detailed guidelines.
Apache License 2.0