@vuept/loopback-connector-mssql
Version:
Microsoft SQL Server connector for LoopBack
305 lines (256 loc) • 9.28 kB
JavaScript
'use strict';
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var EventEmitter = require('events').EventEmitter;
var WritableTrackingBuffer = require('./tracking-buffer/writable-tracking-buffer');
var TOKEN_TYPE = require('./token/token').TYPE;
var FLAGS = {
nullable: 1 << 0,
caseSen: 1 << 1,
updateableReadWrite: 1 << 2,
updateableUnknown: 1 << 3,
identity: 1 << 4,
computed: 1 << 5, // introduced in TDS 7.2
fixedLenCLRType: 1 << 8, // introduced in TDS 7.2
sparseColumnSet: 1 << 10, // introduced in TDS 7.3.B
hidden: 1 << 13, // introduced in TDS 7.2
key: 1 << 14, // introduced in TDS 7.2
nullableUnknown: 1 << 15 // introduced in TDS 7.2
};
var DONE_STATUS = {
FINAL: 0x00,
MORE: 0x1,
ERROR: 0x2,
INXACT: 0x4,
COUNT: 0x10,
ATTN: 0x20,
SRVERROR: 0x100
};
module.exports = function (_EventEmitter) {
(0, _inherits3.default)(BulkLoad, _EventEmitter);
function BulkLoad(table, connectionOptions, _ref, callback) {
var _ref$checkConstraints = _ref.checkConstraints,
checkConstraints = _ref$checkConstraints === undefined ? false : _ref$checkConstraints,
_ref$fireTriggers = _ref.fireTriggers,
fireTriggers = _ref$fireTriggers === undefined ? false : _ref$fireTriggers,
_ref$keepNulls = _ref.keepNulls,
keepNulls = _ref$keepNulls === undefined ? false : _ref$keepNulls,
_ref$lockTable = _ref.lockTable,
lockTable = _ref$lockTable === undefined ? false : _ref$lockTable;
(0, _classCallCheck3.default)(this, BulkLoad);
var _this = (0, _possibleConstructorReturn3.default)(this, (BulkLoad.__proto__ || (0, _getPrototypeOf2.default)(BulkLoad)).call(this));
_this.error = undefined;
_this.canceled = false;
_this.table = table;
_this.options = connectionOptions;
_this.callback = callback;
_this.columns = [];
_this.columnsByName = {};
_this.rowsData = new WritableTrackingBuffer(1024, 'ucs2', true);
_this.firstRowWritten = false;
if (typeof checkConstraints !== 'boolean') {
throw new TypeError('The "options.checkConstraints" property must be of type boolean.');
}
if (typeof fireTriggers !== 'boolean') {
throw new TypeError('The "options.fireTriggers" property must be of type boolean.');
}
if (typeof keepNulls !== 'boolean') {
throw new TypeError('The "options.keepNulls" property must be of type boolean.');
}
if (typeof lockTable !== 'boolean') {
throw new TypeError('The "options.lockTable" property must be of type boolean.');
}
_this.bulkOptions = { checkConstraints, fireTriggers, keepNulls, lockTable };
return _this;
}
(0, _createClass3.default)(BulkLoad, [{
key: 'addColumn',
value: function addColumn(name, type, options) {
if (options == null) {
options = {};
}
if (this.firstRowWritten) {
throw new Error('Columns cannot be added to bulk insert after the first row has been written.');
}
var column = {
type: type,
name: name,
value: null,
output: options.output || (options.output = false),
length: options.length,
precision: options.precision,
scale: options.scale,
objName: options.objName || name,
nullable: options.nullable
};
if ((type.id & 0x30) === 0x20) {
if (column.length == undefined && type.resolveLength) {
column.length = type.resolveLength(column);
}
}
if (type.hasPrecision) {
if (column.precision == undefined && type.resolvePrecision) {
column.precision = type.resolvePrecision(column);
}
}
if (type.hasScale) {
if (column.scale == undefined && type.resolveScale) {
column.scale = type.resolveScale(column);
}
}
this.columns.push(column);
this.columnsByName[name] = column;
}
}, {
key: 'addRow',
value: function addRow(row) {
this.firstRowWritten = true;
if (arguments.length > 1 || !row || typeof row !== 'object') {
// convert arguments to array in a way the optimizer can handle
var arrTemp = new Array(arguments.length);
for (var i = 0, len = arguments.length; i < len; i++) {
var c = arguments[i];
arrTemp[i] = c;
}
row = arrTemp;
}
// write row token
this.rowsData.writeUInt8(TOKEN_TYPE.ROW);
// write each column
var arr = row instanceof Array;
for (var _i = 0, _len = this.columns.length; _i < _len; _i++) {
var _c = this.columns[_i];
_c.type.writeParameterData(this.rowsData, {
length: _c.length,
scale: _c.scale,
precision: _c.precision,
value: row[arr ? _i : _c.objName]
}, this.options);
}
}
}, {
key: 'getOptionsSql',
value: function getOptionsSql() {
var addOptions = [];
if (this.bulkOptions.checkConstraints) {
addOptions.push('CHECK_CONSTRAINTS');
}
if (this.bulkOptions.fireTriggers) {
addOptions.push('FIRE_TRIGGERS');
}
if (this.bulkOptions.keepNulls) {
addOptions.push('KEEP_NULLS');
}
if (this.bulkOptions.lockTable) {
addOptions.push('TABLOCK');
}
if (addOptions.length > 0) {
return ` WITH (${addOptions.join(',')})`;
} else {
return '';
}
}
}, {
key: 'getBulkInsertSql',
value: function getBulkInsertSql() {
var sql = 'insert bulk ' + this.table + '(';
for (var i = 0, len = this.columns.length; i < len; i++) {
var c = this.columns[i];
if (i !== 0) {
sql += ', ';
}
sql += '[' + c.name + '] ' + c.type.declaration(c);
}
sql += ')';
sql += this.getOptionsSql();
return sql;
}
}, {
key: 'getTableCreationSql',
value: function getTableCreationSql() {
var sql = 'CREATE TABLE ' + this.table + '(\n';
for (var i = 0, len = this.columns.length; i < len; i++) {
var c = this.columns[i];
if (i !== 0) {
sql += ',\n';
}
sql += '[' + c.name + '] ' + c.type.declaration(c);
if (c.nullable !== undefined) {
sql += ' ' + (c.nullable ? 'NULL' : 'NOT NULL');
}
}
sql += '\n)';
return sql;
}
}, {
key: 'getPayload',
value: function getPayload() {
// Create COLMETADATA token
var metaData = this.getColMetaData();
var length = metaData.length;
// row data
var rows = this.rowsData.data;
length += rows.length;
// Create DONE token
// It might be nice to make DoneToken a class if anything needs to create them, but for now, just do it here
var tBuf = new WritableTrackingBuffer(this.options.tdsVersion < '7_2' ? 9 : 13);
tBuf.writeUInt8(TOKEN_TYPE.DONE);
var status = DONE_STATUS.FINAL;
tBuf.writeUInt16LE(status);
tBuf.writeUInt16LE(0); // CurCmd (TDS ignores this)
tBuf.writeUInt32LE(0); // row count - doesn't really matter
if (this.options.tdsVersion >= '7_2') {
tBuf.writeUInt32LE(0); // row count is 64 bits in >= TDS 7.2
}
var done = tBuf.data;
length += done.length;
// composite payload
var payload = new WritableTrackingBuffer(length);
payload.copyFrom(metaData);
payload.copyFrom(rows);
payload.copyFrom(done);
return payload;
}
}, {
key: 'getColMetaData',
value: function getColMetaData() {
var tBuf = new WritableTrackingBuffer(100, null, true);
// TokenType
tBuf.writeUInt8(TOKEN_TYPE.COLMETADATA);
// Count
tBuf.writeUInt16LE(this.columns.length);
for (var j = 0, len = this.columns.length; j < len; j++) {
var c = this.columns[j];
// UserType
if (this.options.tdsVersion < '7_2') {
tBuf.writeUInt16LE(0);
} else {
tBuf.writeUInt32LE(0);
}
// Flags
var flags = FLAGS.updateableReadWrite;
if (c.nullable) {
flags |= FLAGS.nullable;
} else if (c.nullable === undefined && this.options.tdsVersion >= '7_2') {
flags |= FLAGS.nullableUnknown;
}
tBuf.writeUInt16LE(flags);
// TYPE_INFO
c.type.writeTypeInfo(tBuf, c, this.options);
// ColName
tBuf.writeBVarchar(c.name, 'ucs2');
}
return tBuf.data;
}
}]);
return BulkLoad;
}(EventEmitter);