387 lines
37 KiB
JavaScript
387 lines
37 KiB
JavaScript
|
|
"use strict";
|
||
|
|
|
||
|
|
Object.defineProperty(exports, "__esModule", {
|
||
|
|
value: true
|
||
|
|
});
|
||
|
|
exports.default = void 0;
|
||
|
|
var _events = require("events");
|
||
|
|
var _errors = require("./errors");
|
||
|
|
var _types = require("./always-encrypted/types");
|
||
|
|
/**
|
||
|
|
* The callback is called when the request has completed, either successfully or with an error.
|
||
|
|
* If an error occurs during execution of the statement(s), then `err` will describe the error.
|
||
|
|
*
|
||
|
|
* As only one request at a time may be executed on a connection, another request should not
|
||
|
|
* be initiated until this callback is called.
|
||
|
|
*
|
||
|
|
* This callback is called before `requestCompleted` is emitted.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* ```js
|
||
|
|
* const { Request } = require('tedious');
|
||
|
|
* const request = new Request("select 42, 'hello world'", (err, rowCount) {
|
||
|
|
* // Request completion callback...
|
||
|
|
* });
|
||
|
|
* connection.execSql(request);
|
||
|
|
* ```
|
||
|
|
*/
|
||
|
|
class Request extends _events.EventEmitter {
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* This event, describing result set columns, will be emitted before row
|
||
|
|
* events are emitted. This event may be emitted multiple times when more
|
||
|
|
* than one recordset is produced by the statement.
|
||
|
|
*
|
||
|
|
* An array like object, where the columns can be accessed either by index
|
||
|
|
* or name. Columns with a name that is an integer are not accessible by name,
|
||
|
|
* as it would be interpreted as an array index.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The request has been prepared and can be used in subsequent calls to execute and unprepare.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The request encountered an error and has not been prepared.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* A row resulting from execution of the SQL statement.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* All rows from a result set have been provided (through `row` events).
|
||
|
|
*
|
||
|
|
* This token is used to indicate the completion of a SQL statement.
|
||
|
|
* As multiple SQL statements can be sent to the server in a single SQL batch, multiple `done` can be generated.
|
||
|
|
* An `done` event is emitted for each SQL statement in the SQL batch except variable declarations.
|
||
|
|
* For execution of SQL statements within stored procedures, `doneProc` and `doneInProc` events are used in place of `done`.
|
||
|
|
*
|
||
|
|
* If you are using [[Connection.execSql]] then SQL server may treat the multiple calls with the same query as a stored procedure.
|
||
|
|
* When this occurs, the `doneProc` and `doneInProc` events may be emitted instead. You must handle both events to ensure complete coverage.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* `request.on('doneInProc', function (rowCount, more, rows) { });`
|
||
|
|
*
|
||
|
|
* Indicates the completion status of a SQL statement within a stored procedure. All rows from a statement
|
||
|
|
* in a stored procedure have been provided (through `row` events).
|
||
|
|
*
|
||
|
|
* This event may also occur when executing multiple calls with the same query using [[execSql]].
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Indicates the completion status of a stored procedure. This is also generated for stored procedures
|
||
|
|
* executed through SQL statements.\
|
||
|
|
* This event may also occur when executing multiple calls with the same query using [[execSql]].
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* A value for an output parameter (that was added to the request with [[addOutputParameter]]).
|
||
|
|
* See also `Using Parameters`.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* This event gives the columns by which data is ordered, if `ORDER BY` clause is executed in SQL Server.
|
||
|
|
*/
|
||
|
|
|
||
|
|
on(event, listener) {
|
||
|
|
return super.on(event, listener);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
|
||
|
|
emit(event, ...args) {
|
||
|
|
return super.emit(event, ...args);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param sqlTextOrProcedure
|
||
|
|
* The SQL statement to be executed
|
||
|
|
*
|
||
|
|
* @param callback
|
||
|
|
* The callback to execute once the request has been fully completed.
|
||
|
|
*/
|
||
|
|
constructor(sqlTextOrProcedure, callback, options) {
|
||
|
|
super();
|
||
|
|
this.sqlTextOrProcedure = sqlTextOrProcedure;
|
||
|
|
this.parameters = [];
|
||
|
|
this.parametersByName = {};
|
||
|
|
this.preparing = false;
|
||
|
|
this.handle = undefined;
|
||
|
|
this.canceled = false;
|
||
|
|
this.paused = false;
|
||
|
|
this.error = undefined;
|
||
|
|
this.connection = undefined;
|
||
|
|
this.timeout = undefined;
|
||
|
|
this.userCallback = callback;
|
||
|
|
this.statementColumnEncryptionSetting = options && options.statementColumnEncryptionSetting || _types.SQLServerStatementColumnEncryptionSetting.UseConnectionSetting;
|
||
|
|
this.cryptoMetadataLoaded = false;
|
||
|
|
this.callback = function (err, rowCount, rows) {
|
||
|
|
if (this.preparing) {
|
||
|
|
this.preparing = false;
|
||
|
|
if (err) {
|
||
|
|
this.emit('error', err);
|
||
|
|
} else {
|
||
|
|
this.emit('prepared');
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
this.userCallback(err, rowCount, rows);
|
||
|
|
this.emit('requestCompleted');
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param name
|
||
|
|
* The parameter name. This should correspond to a parameter in the SQL,
|
||
|
|
* or a parameter that a called procedure expects. The name should not start with `@`.
|
||
|
|
*
|
||
|
|
* @param type
|
||
|
|
* One of the supported data types.
|
||
|
|
*
|
||
|
|
* @param value
|
||
|
|
* The value that the parameter is to be given. The Javascript type of the
|
||
|
|
* argument should match that documented for data types.
|
||
|
|
*
|
||
|
|
* @param options
|
||
|
|
* Additional type options. Optional.
|
||
|
|
*/
|
||
|
|
// TODO: `type` must be a valid TDS value type
|
||
|
|
addParameter(name, type, value, options) {
|
||
|
|
const {
|
||
|
|
output = false,
|
||
|
|
length,
|
||
|
|
precision,
|
||
|
|
scale
|
||
|
|
} = options ?? {};
|
||
|
|
const parameter = {
|
||
|
|
type: type,
|
||
|
|
name: name,
|
||
|
|
value: value,
|
||
|
|
output: output,
|
||
|
|
length: length,
|
||
|
|
precision: precision,
|
||
|
|
scale: scale
|
||
|
|
};
|
||
|
|
this.parameters.push(parameter);
|
||
|
|
this.parametersByName[name] = parameter;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param name
|
||
|
|
* The parameter name. This should correspond to a parameter in the SQL,
|
||
|
|
* or a parameter that a called procedure expects.
|
||
|
|
*
|
||
|
|
* @param type
|
||
|
|
* One of the supported data types.
|
||
|
|
*
|
||
|
|
* @param value
|
||
|
|
* The value that the parameter is to be given. The Javascript type of the
|
||
|
|
* argument should match that documented for data types
|
||
|
|
*
|
||
|
|
* @param options
|
||
|
|
* Additional type options. Optional.
|
||
|
|
*/
|
||
|
|
addOutputParameter(name, type, value, options) {
|
||
|
|
this.addParameter(name, type, value, {
|
||
|
|
...options,
|
||
|
|
output: true
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
makeParamsParameter(parameters) {
|
||
|
|
let paramsParameter = '';
|
||
|
|
for (let i = 0, len = parameters.length; i < len; i++) {
|
||
|
|
const parameter = parameters[i];
|
||
|
|
if (paramsParameter.length > 0) {
|
||
|
|
paramsParameter += ', ';
|
||
|
|
}
|
||
|
|
paramsParameter += '@' + parameter.name + ' ';
|
||
|
|
paramsParameter += parameter.type.declaration(parameter);
|
||
|
|
if (parameter.output) {
|
||
|
|
paramsParameter += ' OUTPUT';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return paramsParameter;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @private
|
||
|
|
*/
|
||
|
|
validateParameters(collation) {
|
||
|
|
for (let i = 0, len = this.parameters.length; i < len; i++) {
|
||
|
|
const parameter = this.parameters[i];
|
||
|
|
try {
|
||
|
|
parameter.value = parameter.type.validate(parameter.value, collation);
|
||
|
|
} catch (error) {
|
||
|
|
throw new _errors.RequestError('Validation failed for parameter \'' + parameter.name + '\'. ' + error.message, 'EPARAM', {
|
||
|
|
cause: error
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Temporarily suspends the flow of data from the database. No more `row` events will be emitted until [[resume] is called.
|
||
|
|
* If this request is already in a paused state, calling [[pause]] has no effect.
|
||
|
|
*/
|
||
|
|
pause() {
|
||
|
|
if (this.paused) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this.emit('pause');
|
||
|
|
this.paused = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Resumes the flow of data from the database.
|
||
|
|
* If this request is not in a paused state, calling [[resume]] has no effect.
|
||
|
|
*/
|
||
|
|
resume() {
|
||
|
|
if (!this.paused) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this.paused = false;
|
||
|
|
this.emit('resume');
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Cancels a request while waiting for a server response.
|
||
|
|
*/
|
||
|
|
cancel() {
|
||
|
|
if (this.canceled) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this.canceled = true;
|
||
|
|
this.emit('cancel');
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sets a timeout for this request.
|
||
|
|
*
|
||
|
|
* @param timeout
|
||
|
|
* The number of milliseconds before the request is considered failed,
|
||
|
|
* or `0` for no timeout. When no timeout is set for the request,
|
||
|
|
* the [[ConnectionOptions.requestTimeout]] of the [[Connection]] is used.
|
||
|
|
*/
|
||
|
|
setTimeout(timeout) {
|
||
|
|
this.timeout = timeout;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
var _default = exports.default = Request;
|
||
|
|
module.exports = Request;
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZXZlbnRzIiwicmVxdWlyZSIsIl9lcnJvcnMiLCJfdHlwZXMiLCJSZXF1ZXN0IiwiRXZlbnRFbWl0dGVyIiwib24iLCJldmVudCIsImxpc3RlbmVyIiwiZW1pdCIsImFyZ3MiLCJjb25zdHJ1Y3RvciIsInNxbFRleHRPclByb2NlZHVyZSIsImNhbGxiYWNrIiwib3B0aW9ucyIsInBhcmFtZXRlcnMiLCJwYXJhbWV0ZXJzQnlOYW1lIiwicHJlcGFyaW5nIiwiaGFuZGxlIiwidW5kZWZpbmVkIiwiY2FuY2VsZWQiLCJwYXVzZWQiLCJlcnJvciIsImNvbm5lY3Rpb24iLCJ0aW1lb3V0IiwidXNlckNhbGxiYWNrIiwic3RhdGVtZW50Q29sdW1uRW5jcnlwdGlvblNldHRpbmciLCJTUUxTZXJ2ZXJTdGF0ZW1lbnRDb2x1bW5FbmNyeXB0aW9uU2V0dGluZyIsIlVzZUNvbm5lY3Rpb25TZXR0aW5nIiwiY3J5cHRvTWV0YWRhdGFMb2FkZWQiLCJlcnIiLCJyb3dDb3VudCIsInJvd3MiLCJhZGRQYXJhbWV0ZXIiLCJuYW1lIiwidHlwZSIsInZhbHVlIiwib3V0cHV0IiwibGVuZ3RoIiwicHJlY2lzaW9uIiwic2NhbGUiLCJwYXJhbWV0ZXIiLCJwdXNoIiwiYWRkT3V0cHV0UGFyYW1ldGVyIiwibWFrZVBhcmFtc1BhcmFtZXRlciIsInBhcmFtc1BhcmFtZXRlciIsImkiLCJsZW4iLCJkZWNsYXJhdGlvbiIsInZhbGlkYXRlUGFyYW1ldGVycyIsImNvbGxhdGlvbiIsInZhbGlkYXRlIiwiUmVxdWVzdEVycm9yIiwibWVzc2FnZSIsImNhdXNlIiwicGF1c2UiLCJyZXN1bWUiLCJjYW5jZWwiLCJzZXRUaW1lb3V0IiwiX2RlZmF1bHQiLCJleHBvcnRzIiwiZGVmYXVsdCIsIm1vZHVsZSJdLCJzb3VyY2VzIjpbIi4uL3NyYy9yZXF1ZXN0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ2V2ZW50cyc7XG5pbXBvcnQgeyB0eXBlIFBhcmFtZXRlciwgdHlwZSBEYXRhVHlwZSB9IGZyb20gJy4vZGF0YS10eXBlJztcbmltcG9ydCB7IFJlcXVlc3RFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcblxuaW1wb3J0IENvbm5lY3Rpb24gZnJvbSAnLi9jb25uZWN0aW9uJztcbmltcG9ydCB7IHR5cGUgTWV0YWRhdGEgfSBmcm9tICcuL21ldGFkYXRhLXBhcnNlcic7XG5pbXBvcnQgeyBTUUxTZXJ2ZXJTdGF0ZW1lbnRDb2x1bW5FbmNyeXB0aW9uU2V0dGluZyB9IGZyb20gJy4vYWx3YXlzLWVuY3J5cHRlZC90eXBlcyc7XG5pbXBvcnQgeyB0eXBlIENvbHVtbk1ldGFkYXRhIH0gZnJvbSAnLi90b2tlbi9jb2xtZXRhZGF0YS10b2tlbi1wYXJzZXInO1xuaW1wb3J0IHsgQ29sbGF0aW9uIH0gZnJvbSAnLi9jb2xsYXRpb24nO1xuXG4vKipcbiAqIFRoZSBjYWxsYmFjayBpcyBjYWxsZWQgd2hlbiB0aGUgcmVxdWVzdCBoYXMgY29tcGxldGVkLCBlaXRoZXIgc3VjY2Vzc2Z1bGx5IG9yIHdpdGggYW4gZXJyb3IuXG4gKiBJZiBhbiBlcnJvciBvY2N1cnMgZHVyaW5nIGV4ZWN1dGlvbiBvZiB0aGUgc3RhdGVtZW50KHMpLCB0aGVuIGBlcnJgIHdpbGwgZGVzY3JpYmUgdGhlIGVycm9yLlxuICpcbiAqIEFzIG9ubHkgb25lIHJlcXVlc3QgYXQgYSB0aW1lIG1heSBiZSBleGVjdXRlZCBvbiBhIGNvbm5lY3Rpb24sIGFub3RoZXIgcmVxdWVzdCBzaG91bGQgbm90XG4gKiBiZSBpbml0aWF0ZWQgdW50aWwgdGhpcyBjYWxsYmFjayBpcyBjYWxsZWQuXG4gKlxuICogVGhpcyBjYWxsYmFjayBpcyBjYWxsZWQgYmVmb3JlIGByZXF1ZXN0Q29tcGxldGVkYCBpcyBlbWl0dGVkLlxuICovXG50eXBlIENvbXBsZXRpb25DYWxsYmFjayA9XG4gIC8qKlxuICAgKiBAcGFyYW0gZXJyb3JcbiAgICogICBJZiBhbiBlcnJvciBvY2N1cnJlZCwgYW4gZXJyb3Igb2JqZWN0LlxuICAgKlxuICAgKiBAcGFyYW0gcm93Q291bnRcbiAgICogICBUaGUgbnVtYmVyIG9mIHJvd3MgZW1pdHRlZCBhcyByZXN1bHQgb2YgZXhlY3V0aW5nIHRoZSBTUUwgc3RhdGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gcm93c1xuICAgKiAgIFJvd3MgYXMgYSByZXN1bHQgb2YgZXhlY3V0aW5nIHRoZSBTUUwgc3RhdGVtZW50LlxuICAgKiAgIFdpbGwgb25seSBiZSBhdmFpbGFibGUgaWYgW1tDb25uZWN0aW9uT3B0aW9ucy5yb3dDb2xsZWN0aW9uT25SZXF1ZXN0Q29tcGxldGlvbl1dIGlzIGB0cnVlYC5cbiAgICovXG4gIC8vIFRPRE86IEZpZ3VyZSBvdXQgaG93IHRvIHR5cGUgdGhlIGByb3dzYCBwYXJhbWV0ZXIgaGVyZS5cbiAgKGVycm9yOiBFcnJvciB8IG51bGwgfCB1bmRlZmluZWQsIHJvd0NvdW50PzogbnVtYmVyLCByb3dzPzogYW55KSA9PiB2b2lkO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBhcmFtZXRlck9wdGlvbnMge1xuICBvdXRwdXQ/OiBib29sZWFuO1xuICBsZW5ndGg/OiBudW1iZXI7XG4gIHByZWNpc2lvbj86IG51bWJlcjtcbiAgc2NhbGU/OiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBSZXF1ZXN0T3B0aW9ucyB7XG4gIHN0YXRlbWVudENvbHVtbkVuY3J5cHRpb25TZXR0aW5nPzogU1FMU2VydmVyU3RhdGVtZW50Q29sdW1uRW5jcnlwdGlvblNldHRpbmc7XG59XG5cbi8qKlxuICogYGBganNcbiAqIGNvbnN0IHsgUmVxdWVzdCB9ID0gcmVxdWlyZSgndGVkaW91cycpO1xuICogY29uc3QgcmVxdWVzdCA9IG5ldyBSZXF1ZXN0KFwic2VsZWN0IDQyLCAnaGVsbG8gd29ybGQnXCIsIChlcnIsIHJvd0NvdW50KSB7XG4gKiAgIC8vIFJlcXVlc3QgY29tcGxldGlvbiBjYWxsYmFjay4uLlxuICogfSk7XG4gKiBjb25uZWN0aW9uLmV4ZWNTcWwocmVxdWVzdCk7XG4gKiBgYGBcbiAqL1xuY2xhc3MgUmVxdWVzdCBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZGVjbGFyZSBzcWxUZXh0T3JQcm9jZWR1cmU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBkZWNsYXJlIHBhcmFtZXRlcnM6IFBhcmFtZXRlcltdO1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICovXG4gIGRlY2xhcmUgcGFyYW1ldGVyc0J5TmFtZTogeyBba2V5OiBzdHJpbmddOiBQYXJhbWV0ZXIgfTtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBkZWNsYXJ
|