2014-10-13 16:47:11 +00:00
|
|
|
/*
|
|
|
|
* A mockup connector that extends SQL connector
|
|
|
|
*/
|
|
|
|
var util = require('util');
|
2015-05-13 17:14:44 +00:00
|
|
|
var SQLConnector = require('../../lib/sql');
|
2015-05-15 17:27:08 +00:00
|
|
|
var debug = require('debug')('loopback:connector:test-sql');
|
|
|
|
|
|
|
|
var transactionId = 0;
|
|
|
|
|
|
|
|
function MockTransaction(connector, name) {
|
|
|
|
this.connector = connector;
|
|
|
|
this.name = name;
|
2015-05-15 23:59:59 +00:00
|
|
|
this.data = {};
|
2015-05-15 17:27:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MockTransaction.prototype.commit = function(cb) {
|
|
|
|
var self = this;
|
2015-05-15 23:59:59 +00:00
|
|
|
// Merge data from this TX to the global data var
|
|
|
|
for (var m in this.data) {
|
|
|
|
self.connector.data[m] = self.connector.data[m] || [];
|
|
|
|
for (var i = 0, n = this.data[m].length; i < n; i++) {
|
|
|
|
self.connector.data[m].push(this.data[m]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.data = {};
|
2015-05-15 17:27:08 +00:00
|
|
|
cb();
|
|
|
|
};
|
|
|
|
|
|
|
|
MockTransaction.prototype.rollback = function(cb) {
|
2015-05-15 23:59:59 +00:00
|
|
|
this.data = {};
|
2015-05-15 17:27:08 +00:00
|
|
|
cb();
|
|
|
|
};
|
2014-10-13 16:47:11 +00:00
|
|
|
|
|
|
|
exports.initialize = function initializeDataSource(dataSource, callback) {
|
|
|
|
process.nextTick(function() {
|
2015-05-13 17:14:44 +00:00
|
|
|
if (callback) {
|
|
|
|
var connector = new TestConnector(dataSource.settings);
|
2014-10-13 16:47:11 +00:00
|
|
|
connector.dataSource = dataSource;
|
|
|
|
dataSource.connector = connector;
|
|
|
|
callback(null, connector);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-05-13 17:14:44 +00:00
|
|
|
function TestConnector(settings) {
|
|
|
|
SQLConnector.call(this, 'testdb', settings);
|
2014-10-13 16:47:11 +00:00
|
|
|
this._tables = {};
|
2015-05-15 23:59:59 +00:00
|
|
|
this.data = {};
|
2014-10-13 16:47:11 +00:00
|
|
|
}
|
|
|
|
|
2015-05-13 17:14:44 +00:00
|
|
|
util.inherits(TestConnector, SQLConnector);
|
|
|
|
|
|
|
|
TestConnector.prototype.escapeName = function(name) {
|
|
|
|
return '`' + name + '`';
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.dbName = function(name) {
|
|
|
|
return name.toUpperCase();
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.getPlaceholderForValue = function(key) {
|
|
|
|
return '$' + key;
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.escapeValue = function(value) {
|
|
|
|
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
if (typeof value === 'string') {
|
|
|
|
return "'" + value + "'";
|
|
|
|
}
|
|
|
|
if (value == null) {
|
|
|
|
return 'NULL';
|
|
|
|
}
|
|
|
|
if (typeof value === 'object') {
|
|
|
|
return String(value);
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.toColumnValue = function(prop, val) {
|
|
|
|
return val;
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype._buildLimit = function(model, limit, offset) {
|
|
|
|
if (isNaN(limit)) {
|
|
|
|
limit = 0;
|
|
|
|
}
|
|
|
|
if (isNaN(offset)) {
|
|
|
|
offset = 0;
|
|
|
|
}
|
|
|
|
if (!limit && !offset) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
return 'LIMIT ' + (offset ? (offset + ',' + limit) : limit);
|
|
|
|
};
|
|
|
|
|
2015-05-15 17:27:08 +00:00
|
|
|
TestConnector.prototype.applyPagination =
|
|
|
|
function(model, stmt, filter) {
|
|
|
|
/*jshint unused:false */
|
|
|
|
var limitClause = this._buildLimit(model, filter.limit,
|
|
|
|
filter.offset || filter.skip);
|
|
|
|
return stmt.merge(limitClause);
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.escapeName = function(name) {
|
|
|
|
return '`' + name + '`';
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.dbName = function(name) {
|
|
|
|
return name.toUpperCase();
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.getPlaceholderForValue = function(key) {
|
|
|
|
return '$' + key;
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.escapeValue = function(value) {
|
|
|
|
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
if (typeof value === 'string') {
|
|
|
|
return "'" + value + "'";
|
|
|
|
}
|
|
|
|
if (value == null) {
|
|
|
|
return 'NULL';
|
|
|
|
}
|
|
|
|
if (typeof value === 'object') {
|
|
|
|
return String(value);
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.toColumnValue = function(prop, val, escaping) {
|
|
|
|
return escaping ? this.escapeValue(val) : val;
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype._buildLimit = function(model, limit, offset) {
|
|
|
|
if (isNaN(limit)) {
|
|
|
|
limit = 0;
|
|
|
|
}
|
|
|
|
if (isNaN(offset)) {
|
|
|
|
offset = 0;
|
|
|
|
}
|
|
|
|
if (!limit && !offset) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
return 'LIMIT ' + (offset ? (offset + ',' + limit) : limit);
|
|
|
|
};
|
|
|
|
|
2015-05-13 17:14:44 +00:00
|
|
|
TestConnector.prototype.applyPagination =
|
|
|
|
function(model, stmt, filter) {
|
|
|
|
/*jshint unused:false */
|
|
|
|
var limitClause = this._buildLimit(model, filter.limit,
|
|
|
|
filter.offset || filter.skip);
|
|
|
|
return stmt.merge(limitClause);
|
|
|
|
};
|
2014-10-13 16:47:11 +00:00
|
|
|
|
|
|
|
TestConnector.prototype.dropTable = function(model, cb) {
|
|
|
|
var err;
|
|
|
|
var exists = model in this._tables;
|
|
|
|
if (!exists) {
|
|
|
|
err = new Error('Model doesn\'t exist: ' + model);
|
|
|
|
} else {
|
|
|
|
delete this._tables[model];
|
|
|
|
}
|
|
|
|
process.nextTick(function() {
|
|
|
|
cb(err);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.createTable = function(model, cb) {
|
|
|
|
var err;
|
|
|
|
var exists = model in this._tables;
|
|
|
|
if (exists) {
|
|
|
|
err = new Error('Model already exists: ' + model);
|
|
|
|
} else {
|
|
|
|
this._tables[model] = model;
|
|
|
|
}
|
|
|
|
process.nextTick(function() {
|
|
|
|
cb(err);
|
|
|
|
});
|
|
|
|
};
|
2015-05-13 17:14:44 +00:00
|
|
|
|
2015-05-15 17:27:08 +00:00
|
|
|
TestConnector.prototype.getInsertedId = function(model, info) {
|
|
|
|
return info;
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.fromColumnValue = function(propertyDef, value) {
|
|
|
|
return value;
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.beginTransaction = function(isolationLevel, cb) {
|
|
|
|
var name = 'tx_' + transactionId++;
|
|
|
|
cb(null, new MockTransaction(this, name));
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.commit = function(tx, cb) {
|
|
|
|
tx.commit(cb);
|
|
|
|
};
|
|
|
|
|
|
|
|
TestConnector.prototype.rollback = function(tx, cb) {
|
|
|
|
tx.rollback(cb);
|
|
|
|
};
|
|
|
|
|
2015-05-13 17:14:44 +00:00
|
|
|
TestConnector.prototype.executeSQL = function(sql, params, options, callback) {
|
2015-05-15 17:27:08 +00:00
|
|
|
var transaction = options.transaction;
|
2015-05-15 23:59:59 +00:00
|
|
|
var model = options.model;
|
2015-05-15 17:27:08 +00:00
|
|
|
if (transaction && transaction.connector === this && transaction.connection) {
|
|
|
|
if (sql.indexOf('INSERT') === 0) {
|
2015-05-15 23:59:59 +00:00
|
|
|
transaction.connection.data[model] =
|
|
|
|
transaction.connection.data[model] || [];
|
2016-04-09 18:35:52 +00:00
|
|
|
transaction.connection.data[model].push({ sql: sql, params: params });
|
2015-05-15 17:27:08 +00:00
|
|
|
debug('INSERT', transaction.connection.data, sql,
|
|
|
|
transaction.connection.name);
|
|
|
|
callback(null, 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
debug('SELECT', transaction.connection.data, sql,
|
|
|
|
transaction.connection.name);
|
2015-05-15 23:59:59 +00:00
|
|
|
callback(null, transaction.connection.data[model] || []);
|
2015-05-15 17:27:08 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (sql.indexOf('INSERT') === 0) {
|
2015-05-15 23:59:59 +00:00
|
|
|
this.data[model] = this.data[model] || [];
|
2016-04-09 18:35:52 +00:00
|
|
|
this.data[model].push({ sql: sql, params: params });
|
2015-05-15 23:59:59 +00:00
|
|
|
debug('INSERT', this.data, sql);
|
2015-05-15 17:27:08 +00:00
|
|
|
callback(null, 1);
|
|
|
|
} else {
|
2015-05-15 23:59:59 +00:00
|
|
|
debug('SELECT', this.data, sql);
|
|
|
|
callback(null, this.data[model] || []);
|
2015-05-15 17:27:08 +00:00
|
|
|
}
|
|
|
|
}
|
2015-05-13 17:14:44 +00:00
|
|
|
};
|