Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
124 changes: 124 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,64 @@ odbc.connect(`${process.env.CONNECTION_STRING}`, (error, connection) => {

---

### `.cancel(callback?)`

Cancels all operations currently running on the connection (queries and procedure calls) by calling `SQLCancel` on their statement handles. The cancelled operations return with SQLSTATE HY008 ("Operation canceled"), so their promises reject (or their callbacks are called with an error). If no operations are running, `.cancel` is a no-op.

#### Parameters:
* **callback?**: The function called when `.cancel` has finished execution. If no callback function is given, `.cancel` will return a native JavaScript `Promise`. Callback signature is:
* error: The error that occured in execution, or `null` if no error

#### Examples:

**Promises**

```javascript
const odbc = require('odbc');

// can only use await keyword in an async function
async function cancelExample() {
const connection = await odbc.connect(`${process.env.CONNECTION_STRING}`);

// cancel the query if it is still running after 10 seconds
const timer = setTimeout(() => {
connection.cancel();
}, 10000);

try {
const result = await connection.query('SELECT * FROM HUGE_TABLE');
console.log(result);
} catch (error) {
// if cancelled, error contains an odbcError with state 'HY008'
} finally {
clearTimeout(timer);
}
}

cancelExample();
```

**Callbacks**

```javascript
const odbc = require('odbc');

odbc.connect(`${process.env.CONNECTION_STRING}`, (error, connection) => {
const timer = setTimeout(() => {
connection.cancel((cancelError) => {
if (cancelError) { return; } // handle
});
}, 10000);

connection.query('SELECT * FROM HUGE_TABLE', (queryError, result) => {
clearTimeout(timer);
// if cancelled, queryError contains an odbcError with state 'HY008'
});
});
```

---

### `.close(callback?)`

Closes an open connection. Any transactions on the connection that have not been ended will be rolledback.
Expand Down Expand Up @@ -1027,6 +1085,72 @@ odbc.connect(`${process.env.CONNECTION_STRING}`, (error, connection) => {

---

### `.cancel(callback?)`

Cancels any operation currently running on the Statement (e.g. a long `.execute()`) by calling `SQLCancel` on its handle. The cancelled operation returns with SQLSTATE HY008 ("Operation canceled").

#### Parameters:
* **callback?**: The function called when `.cancel` has finished execution. If no callback function is given, `.cancel` will return a native JavaScript `Promise`. Callback signature is:
* error: The error that occured in execution, or `null` if no error

#### Examples:

**Promises**

```javascript
const odbc = require('odbc');

// can only use await keyword in an async function
async function cancelExample() {
const connection = await odbc.connect(`${process.env.CONNECTION_STRING}`);
const statement = await connection.createStatement();
await statement.prepare('SELECT * FROM HUGE_TABLE WHERE FIELD_1 = ?');
await statement.bind([1]);

// cancel the execution if it is still running after 10 seconds
const timer = setTimeout(() => {
statement.cancel();
}, 10000);

try {
const result = await statement.execute();
console.log(result);
} catch (error) {
// if cancelled, error contains an odbcError with state 'HY008'
} finally {
clearTimeout(timer);
}
}

cancelExample();
```

**Callbacks**

```javascript
const odbc = require('odbc');

odbc.connect(`${process.env.CONNECTION_STRING}`, (error, connection) => {
connection.createStatement((error1, statement) => {
if (error1) { return; } // handle
statement.prepare('SELECT * FROM HUGE_TABLE', (error2) => {
if (error2) { return; } // handle
const timer = setTimeout(() => {
statement.cancel((cancelError) => {
if (cancelError) { return; } // handle
});
}, 10000);
statement.execute((error3, result) => {
clearTimeout(timer);
// if cancelled, error3 contains an odbcError with state 'HY008'
});
});
});
});
```

---

### `.close(callback?)`

Closes the Statement, freeing the statement handle. Running functions on the statement after closing will result in an error.
Expand Down
38 changes: 38 additions & 0 deletions lib/Connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,44 @@ class Connection {
});
}

/**
* Cancels all operations currently running on this connection (queries and
* procedure calls) by calling SQLCancel on their statement handles. The
* cancelled operations return with SQLSTATE HY008 ("Operation canceled").
* Asynchronous, can be used either with a callback function or a Promise.
* @param {function} [callback] - Callback function. If not passed, a Promise will be returned.
*/
cancel(callback = undefined) {
// type-checking
if (typeof callback !== 'function' && typeof callback !== 'undefined') {
throw new TypeError('[node-odbc]: Incorrect function signature for call to connection.cancel({function}[optional]).');
}

// promise...
if (callback === undefined) {
if (!this.odbcConnection)
{
throw new Error(Connection.CONNECTION_CLOSED_ERROR);
}
return new Promise((resolve, reject) => {
this.odbcConnection.cancel((error) => {
if (error) {
reject(error);
} else {
resolve();
}
});
});
}

// ...or callback
if (!this.odbcConnection)
{
return callback(new Error(Connection.CONNECTION_CLOSED_ERROR));
}
return this.odbcConnection.cancel((error) => callback(error));
}

// TODO: Documentation
primaryKeys(catalog, schema, table, callback = undefined) {
// promise...
Expand Down
35 changes: 34 additions & 1 deletion lib/Statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,43 @@ class Statement {
}
}

/**
* Cancels any operation currently running on this statement (e.g. a long
* execute()) by calling SQLCancel on its handle. The cancelled operation
* returns with SQLSTATE HY008 ("Operation canceled").
* @param {function} [callback] - The callback function that returns the result. If omitted, uses a Promise.
*/
cancel(callback = undefined) {
if (typeof callback !== 'function' && typeof callback !== 'undefined') {
throw new TypeError('[node-odbc]: Incorrect function signature for call to statement.cancel({function}[optional]).');
}

if (typeof callback === 'undefined') {
if (!this.odbcStatement) {
throw new Error(Statement.STATEMENT_CLOSED_ERROR);
}
return new Promise((resolve, reject) => {
this.odbcStatement.cancel((error) => {
if (error) {
reject(error);
} else {
resolve();
}
});
});
}

// ...or callback
if (!this.odbcStatement) {
return callback(new Error(Statement.STATEMENT_CLOSED_ERROR));
}
return this.odbcStatement.cancel((error) => callback(error));
}

/**
* Closes the statement, deleting the prepared statement and freeing the handle, making further
* calls on the object invalid.
* @param {function} [callback] - The callback function that returns the result. If omitted, uses a Promise.
* @param {function} [callback] - The callback function that returns the result. If omitted, uses a Promise.
*/
close(callback = undefined) {
if (typeof callback !== 'function' && typeof callback !== 'undefined') {
Expand Down
8 changes: 8 additions & 0 deletions lib/odbc.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ declare namespace odbc {

execute<T>(callback: (error: NodeOdbcError, result: Result<T>) => undefined): undefined;

cancel(callback: (error: NodeOdbcError) => undefined): undefined;

close(callback: (error: NodeOdbcError) => undefined): undefined;

////////////////////////////////////////////////////////////////////////////
Expand All @@ -51,6 +53,8 @@ declare namespace odbc {

execute<T>(): Promise<Result<T>>;

cancel(): Promise<void>;

close(): Promise<void>;
}

Expand Down Expand Up @@ -112,6 +116,8 @@ declare namespace odbc {

rollback(callback: (error: NodeOdbcError) => undefined): undefined;

cancel(callback: (error: NodeOdbcError) => undefined): undefined;

close(callback: (error: NodeOdbcError) => undefined): undefined;

////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -142,6 +148,8 @@ declare namespace odbc {

rollback(): Promise<void>;

cancel(): Promise<void>;

close(): Promise<void>;

connected(): boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/odbc.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ typedef struct StatementData {

SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt;
SQLHSTMT hstmt = SQL_NULL_HANDLE;

QueryOptions query_options;

Expand Down
Loading