Spaces:
Running
Running
; | |
const core = require('./index.js'); | |
const EventEmitter = require('events').EventEmitter; | |
const parserCache = require('./lib/parsers/parser_cache.js'); | |
function makeDoneCb(resolve, reject, localErr) { | |
return function (err, rows, fields) { | |
if (err) { | |
localErr.message = err.message; | |
localErr.code = err.code; | |
localErr.errno = err.errno; | |
localErr.sql = err.sql; | |
localErr.sqlState = err.sqlState; | |
localErr.sqlMessage = err.sqlMessage; | |
reject(localErr); | |
} else { | |
resolve([rows, fields]); | |
} | |
}; | |
} | |
function inheritEvents(source, target, events) { | |
const listeners = {}; | |
target | |
.on('newListener', eventName => { | |
if (events.indexOf(eventName) >= 0 && !target.listenerCount(eventName)) { | |
source.on( | |
eventName, | |
(listeners[eventName] = function () { | |
const args = [].slice.call(arguments); | |
args.unshift(eventName); | |
target.emit.apply(target, args); | |
}) | |
); | |
} | |
}) | |
.on('removeListener', eventName => { | |
if (events.indexOf(eventName) >= 0 && !target.listenerCount(eventName)) { | |
source.removeListener(eventName, listeners[eventName]); | |
delete listeners[eventName]; | |
} | |
}); | |
} | |
class PromisePreparedStatementInfo { | |
constructor(statement, promiseImpl) { | |
this.statement = statement; | |
this.Promise = promiseImpl; | |
} | |
execute(parameters) { | |
const s = this.statement; | |
const localErr = new Error(); | |
return new this.Promise((resolve, reject) => { | |
const done = makeDoneCb(resolve, reject, localErr); | |
if (parameters) { | |
s.execute(parameters, done); | |
} else { | |
s.execute(done); | |
} | |
}); | |
} | |
close() { | |
return new this.Promise(resolve => { | |
this.statement.close(); | |
resolve(); | |
}); | |
} | |
} | |
class PromiseConnection extends EventEmitter { | |
constructor(connection, promiseImpl) { | |
super(); | |
this.connection = connection; | |
this.Promise = promiseImpl || Promise; | |
inheritEvents(connection, this, [ | |
'error', | |
'drain', | |
'connect', | |
'end', | |
'enqueue' | |
]); | |
} | |
release() { | |
this.connection.release(); | |
} | |
query(query, params) { | |
const c = this.connection; | |
const localErr = new Error(); | |
if (typeof params === 'function') { | |
throw new Error( | |
'Callback function is not available with promise clients.' | |
); | |
} | |
return new this.Promise((resolve, reject) => { | |
const done = makeDoneCb(resolve, reject, localErr); | |
if (params !== undefined) { | |
c.query(query, params, done); | |
} else { | |
c.query(query, done); | |
} | |
}); | |
} | |
execute(query, params) { | |
const c = this.connection; | |
const localErr = new Error(); | |
if (typeof params === 'function') { | |
throw new Error( | |
'Callback function is not available with promise clients.' | |
); | |
} | |
return new this.Promise((resolve, reject) => { | |
const done = makeDoneCb(resolve, reject, localErr); | |
if (params !== undefined) { | |
c.execute(query, params, done); | |
} else { | |
c.execute(query, done); | |
} | |
}); | |
} | |
end() { | |
return new this.Promise(resolve => { | |
this.connection.end(resolve); | |
}); | |
} | |
beginTransaction() { | |
const c = this.connection; | |
const localErr = new Error(); | |
return new this.Promise((resolve, reject) => { | |
const done = makeDoneCb(resolve, reject, localErr); | |
c.beginTransaction(done); | |
}); | |
} | |
commit() { | |
const c = this.connection; | |
const localErr = new Error(); | |
return new this.Promise((resolve, reject) => { | |
const done = makeDoneCb(resolve, reject, localErr); | |
c.commit(done); | |
}); | |
} | |
rollback() { | |
const c = this.connection; | |
const localErr = new Error(); | |
return new this.Promise((resolve, reject) => { | |
const done = makeDoneCb(resolve, reject, localErr); | |
c.rollback(done); | |
}); | |
} | |
ping() { | |
const c = this.connection; | |
const localErr = new Error(); | |
return new this.Promise((resolve, reject) => { | |
c.ping(err => { | |
if (err) { | |
localErr.message = err.message; | |
localErr.code = err.code; | |
localErr.errno = err.errno; | |
localErr.sqlState = err.sqlState; | |
localErr.sqlMessage = err.sqlMessage; | |
reject(localErr); | |
} else { | |
resolve(true); | |
} | |
}); | |
}); | |
} | |
connect() { | |
const c = this.connection; | |
const localErr = new Error(); | |
return new this.Promise((resolve, reject) => { | |
c.connect((err, param) => { | |
if (err) { | |
localErr.message = err.message; | |
localErr.code = err.code; | |
localErr.errno = err.errno; | |
localErr.sqlState = err.sqlState; | |
localErr.sqlMessage = err.sqlMessage; | |
reject(localErr); | |
} else { | |
resolve(param); | |
} | |
}); | |
}); | |
} | |
prepare(options) { | |
const c = this.connection; | |
const promiseImpl = this.Promise; | |
const localErr = new Error(); | |
return new this.Promise((resolve, reject) => { | |
c.prepare(options, (err, statement) => { | |
if (err) { | |
localErr.message = err.message; | |
localErr.code = err.code; | |
localErr.errno = err.errno; | |
localErr.sqlState = err.sqlState; | |
localErr.sqlMessage = err.sqlMessage; | |
reject(localErr); | |
} else { | |
const wrappedStatement = new PromisePreparedStatementInfo( | |
statement, | |
promiseImpl | |
); | |
resolve(wrappedStatement); | |
} | |
}); | |
}); | |
} | |
changeUser(options) { | |
const c = this.connection; | |
const localErr = new Error(); | |
return new this.Promise((resolve, reject) => { | |
c.changeUser(options, err => { | |
if (err) { | |
localErr.message = err.message; | |
localErr.code = err.code; | |
localErr.errno = err.errno; | |
localErr.sqlState = err.sqlState; | |
localErr.sqlMessage = err.sqlMessage; | |
reject(localErr); | |
} else { | |
resolve(); | |
} | |
}); | |
}); | |
} | |
get config() { | |
return this.connection.config; | |
} | |
get threadId() { | |
return this.connection.threadId; | |
} | |
} | |
function createConnection(opts) { | |
const coreConnection = core.createConnection(opts); | |
const createConnectionErr = new Error(); | |
const thePromise = opts.Promise || Promise; | |
if (!thePromise) { | |
throw new Error( | |
'no Promise implementation available.' + | |
'Use promise-enabled node version or pass userland Promise' + | |
" implementation as parameter, for example: { Promise: require('bluebird') }" | |
); | |
} | |
return new thePromise((resolve, reject) => { | |
coreConnection.once('connect', () => { | |
resolve(new PromiseConnection(coreConnection, thePromise)); | |
}); | |
coreConnection.once('error', err => { | |
createConnectionErr.message = err.message; | |
createConnectionErr.code = err.code; | |
createConnectionErr.errno = err.errno; | |
createConnectionErr.sqlState = err.sqlState; | |
reject(createConnectionErr); | |
}); | |
}); | |
} | |
// note: the callback of "changeUser" is not called on success | |
// hence there is no possibility to call "resolve" | |
// patching PromiseConnection | |
// create facade functions for prototype functions on "Connection" that are not yet | |
// implemented with PromiseConnection | |
// proxy synchronous functions only | |
(function (functionsToWrap) { | |
for (let i = 0; functionsToWrap && i < functionsToWrap.length; i++) { | |
const func = functionsToWrap[i]; | |
if ( | |
typeof core.Connection.prototype[func] === 'function' && | |
PromiseConnection.prototype[func] === undefined | |
) { | |
PromiseConnection.prototype[func] = (function factory(funcName) { | |
return function () { | |
return core.Connection.prototype[funcName].apply( | |
this.connection, | |
arguments | |
); | |
}; | |
})(func); | |
} | |
} | |
})([ | |
// synchronous functions | |
'close', | |
'createBinlogStream', | |
'destroy', | |
'escape', | |
'escapeId', | |
'format', | |
'pause', | |
'pipe', | |
'resume', | |
'unprepare' | |
]); | |
class PromisePoolConnection extends PromiseConnection { | |
constructor(connection, promiseImpl) { | |
super(connection, promiseImpl); | |
} | |
destroy() { | |
return core.PoolConnection.prototype.destroy.apply( | |
this.connection, | |
arguments | |
); | |
} | |
} | |
class PromisePool extends EventEmitter { | |
constructor(pool, thePromise) { | |
super(); | |
this.pool = pool; | |
this.Promise = thePromise || Promise; | |
inheritEvents(pool, this, ['acquire', 'connection', 'enqueue', 'release']); | |
} | |
getConnection() { | |
const corePool = this.pool; | |
return new this.Promise((resolve, reject) => { | |
corePool.getConnection((err, coreConnection) => { | |
if (err) { | |
reject(err); | |
} else { | |
resolve(new PromisePoolConnection(coreConnection, this.Promise)); | |
} | |
}); | |
}); | |
} | |
releaseConnection(connection) { | |
if (connection instanceof PromisePoolConnection) connection.release(); | |
} | |
query(sql, args) { | |
const corePool = this.pool; | |
const localErr = new Error(); | |
if (typeof args === 'function') { | |
throw new Error( | |
'Callback function is not available with promise clients.' | |
); | |
} | |
return new this.Promise((resolve, reject) => { | |
const done = makeDoneCb(resolve, reject, localErr); | |
if (args !== undefined) { | |
corePool.query(sql, args, done); | |
} else { | |
corePool.query(sql, done); | |
} | |
}); | |
} | |
execute(sql, args) { | |
const corePool = this.pool; | |
const localErr = new Error(); | |
if (typeof args === 'function') { | |
throw new Error( | |
'Callback function is not available with promise clients.' | |
); | |
} | |
return new this.Promise((resolve, reject) => { | |
const done = makeDoneCb(resolve, reject, localErr); | |
if (args) { | |
corePool.execute(sql, args, done); | |
} else { | |
corePool.execute(sql, done); | |
} | |
}); | |
} | |
end() { | |
const corePool = this.pool; | |
const localErr = new Error(); | |
return new this.Promise((resolve, reject) => { | |
corePool.end(err => { | |
if (err) { | |
localErr.message = err.message; | |
localErr.code = err.code; | |
localErr.errno = err.errno; | |
localErr.sqlState = err.sqlState; | |
localErr.sqlMessage = err.sqlMessage; | |
reject(localErr); | |
} else { | |
resolve(); | |
} | |
}); | |
}); | |
} | |
} | |
function createPool(opts) { | |
const corePool = core.createPool(opts); | |
const thePromise = opts.Promise || Promise; | |
if (!thePromise) { | |
throw new Error( | |
'no Promise implementation available.' + | |
'Use promise-enabled node version or pass userland Promise' + | |
" implementation as parameter, for example: { Promise: require('bluebird') }" | |
); | |
} | |
return new PromisePool(corePool, thePromise); | |
} | |
(function (functionsToWrap) { | |
for (let i = 0; functionsToWrap && i < functionsToWrap.length; i++) { | |
const func = functionsToWrap[i]; | |
if ( | |
typeof core.Pool.prototype[func] === 'function' && | |
PromisePool.prototype[func] === undefined | |
) { | |
PromisePool.prototype[func] = (function factory(funcName) { | |
return function () { | |
return core.Pool.prototype[funcName].apply(this.pool, arguments); | |
}; | |
})(func); | |
} | |
} | |
})([ | |
// synchronous functions | |
'escape', | |
'escapeId', | |
'format' | |
]); | |
class PromisePoolCluster extends EventEmitter { | |
constructor(poolCluster, thePromise) { | |
super(); | |
this.poolCluster = poolCluster; | |
this.Promise = thePromise || Promise; | |
inheritEvents(poolCluster, this, ['warn', 'remove']); | |
} | |
getConnection() { | |
const corePoolCluster = this.poolCluster; | |
return new this.Promise((resolve, reject) => { | |
corePoolCluster.getConnection((err, coreConnection) => { | |
if (err) { | |
reject(err); | |
} else { | |
resolve(new PromisePoolConnection(coreConnection, this.Promise)); | |
} | |
}); | |
}); | |
} | |
query(sql, args) { | |
const corePoolCluster = this.poolCluster; | |
const localErr = new Error(); | |
if (typeof args === 'function') { | |
throw new Error( | |
'Callback function is not available with promise clients.' | |
); | |
} | |
return new this.Promise((resolve, reject) => { | |
const done = makeDoneCb(resolve, reject, localErr); | |
corePoolCluster.query(sql, args, done); | |
}); | |
} | |
execute(sql, args) { | |
const corePoolCluster = this.poolCluster; | |
const localErr = new Error(); | |
if (typeof args === 'function') { | |
throw new Error( | |
'Callback function is not available with promise clients.' | |
); | |
} | |
return new this.Promise((resolve, reject) => { | |
const done = makeDoneCb(resolve, reject, localErr); | |
corePoolCluster.execute(sql, args, done); | |
}); | |
} | |
of(pattern, selector) { | |
return new PromisePoolCluster( | |
this.poolCluster.of(pattern, selector), | |
this.Promise | |
); | |
} | |
end() { | |
const corePoolCluster = this.poolCluster; | |
const localErr = new Error(); | |
return new this.Promise((resolve, reject) => { | |
corePoolCluster.end(err => { | |
if (err) { | |
localErr.message = err.message; | |
localErr.code = err.code; | |
localErr.errno = err.errno; | |
localErr.sqlState = err.sqlState; | |
localErr.sqlMessage = err.sqlMessage; | |
reject(localErr); | |
} else { | |
resolve(); | |
} | |
}); | |
}); | |
} | |
} | |
/** | |
* proxy poolCluster synchronous functions | |
*/ | |
(function (functionsToWrap) { | |
for (let i = 0; functionsToWrap && i < functionsToWrap.length; i++) { | |
const func = functionsToWrap[i]; | |
if ( | |
typeof core.PoolCluster.prototype[func] === 'function' && | |
PromisePoolCluster.prototype[func] === undefined | |
) { | |
PromisePoolCluster.prototype[func] = (function factory(funcName) { | |
return function () { | |
return core.PoolCluster.prototype[funcName].apply(this.poolCluster, arguments); | |
}; | |
})(func); | |
} | |
} | |
})([ | |
'add' | |
]); | |
function createPoolCluster(opts) { | |
const corePoolCluster = core.createPoolCluster(opts); | |
const thePromise = (opts && opts.Promise) || Promise; | |
if (!thePromise) { | |
throw new Error( | |
'no Promise implementation available.' + | |
'Use promise-enabled node version or pass userland Promise' + | |
" implementation as parameter, for example: { Promise: require('bluebird') }" | |
); | |
} | |
return new PromisePoolCluster(corePoolCluster, thePromise); | |
} | |
exports.createConnection = createConnection; | |
exports.createPool = createPool; | |
exports.createPoolCluster = createPoolCluster; | |
exports.escape = core.escape; | |
exports.escapeId = core.escapeId; | |
exports.format = core.format; | |
exports.raw = core.raw; | |
exports.PromisePool = PromisePool; | |
exports.PromiseConnection = PromiseConnection; | |
exports.PromisePoolConnection = PromisePoolConnection; | |
exports.__defineGetter__('Types', () => require('./lib/constants/types.js')); | |
exports.__defineGetter__('Charsets', () => | |
require('./lib/constants/charsets.js') | |
); | |
exports.__defineGetter__('CharsetToEncoding', () => | |
require('./lib/constants/charset_encodings.js') | |
); | |
exports.setMaxParserCache = function(max) { | |
parserCache.setMaxCache(max); | |
}; | |
exports.clearParserCache = function() { | |
parserCache.clearCache(); | |
}; | |