Comparing version 2.0.0-alpha8 to 2.0.0-alpha9
@@ -7,2 +7,12 @@ # Changes | ||
## v2.0.0-alpha9 (2013-08-27) | ||
* Add query to pool to execute queries directly using the pool | ||
* Pool option to set queue limit | ||
* Pool sends 'connection' event when it opens a new connection | ||
* Added stringifyObjects option to treat input as strings rather than objects (#501) | ||
* Support for poolClusters | ||
* Datetime improvements | ||
* Bug fixes | ||
## v2.0.0-alpha8 (2013-04-30) | ||
@@ -9,0 +19,0 @@ |
@@ -7,2 +7,3 @@ var Connection = require('./lib/Connection'); | ||
var PoolConfig = require('./lib/PoolConfig'); | ||
var PoolCluster = require('./lib/PoolCluster'); | ||
@@ -17,2 +18,6 @@ exports.createConnection = function(config) { | ||
exports.createPoolCluster = function(config) { | ||
return new PoolCluster(config); | ||
}; | ||
exports.createQuery = Connection.createQuery; | ||
@@ -19,0 +24,0 @@ |
var Net = require('net'); | ||
var ConnectionConfig = require('./ConnectionConfig'); | ||
var Pool = require('./Pool'); | ||
var Protocol = require('./protocol/Protocol'); | ||
@@ -108,3 +107,2 @@ var SqlString = require('./protocol/SqlString'); | ||
query.sql = this.format(query.sql, query.values || []); | ||
delete query.values; | ||
@@ -154,3 +152,3 @@ return this._protocol._enqueue(query); | ||
} | ||
return SqlString.format(sql, values, this.config.timezone); | ||
return SqlString.format(sql, values, this.config.stringifyObjects, this.config.timezone); | ||
}; | ||
@@ -157,0 +155,0 @@ |
@@ -21,2 +21,3 @@ var urlParse = require('url').parse; | ||
this.debug = options.debug; | ||
this.stringifyObjects = options.stringifyObjects || false; | ||
this.timezone = options.timezone || 'local'; | ||
@@ -23,0 +24,0 @@ this.flags = options.flags || ''; |
183
lib/Pool.js
@@ -1,7 +0,12 @@ | ||
var Mysql = require('../'); | ||
var mysql = require('../'); | ||
var Connection = require('./Connection'); | ||
var EventEmitter = require('events').EventEmitter; | ||
var Util = require('util'); | ||
var PoolConnection = require('./PoolConnection'); | ||
module.exports = Pool; | ||
Util.inherits(Pool, EventEmitter); | ||
function Pool(options) { | ||
EventEmitter.call(this); | ||
this.config = options.config; | ||
@@ -16,44 +21,63 @@ this.config.connectionConfig.pool = this; | ||
Pool.prototype.getConnection = function(cb) { | ||
Pool.prototype.getConnection = function (cb) { | ||
if (this._closed) { | ||
cb(new Error('Pool is closed.')); | ||
return; | ||
return process.nextTick(function(){ | ||
return cb(new Error('Pool is closed.')); | ||
}); | ||
} | ||
var connection; | ||
if (this._freeConnections.length > 0) { | ||
var connection = this._freeConnections[0]; | ||
this._freeConnections.shift(); | ||
cb(null, connection); | ||
} else if (this.config.connectionLimit == 0 || this._allConnections.length < this.config.connectionLimit) { | ||
var self = this; | ||
var connection = this._createConnection(); | ||
connection = this._freeConnections.shift(); | ||
return process.nextTick(function(){ | ||
return cb(null, connection); | ||
}); | ||
} | ||
if (this.config.connectionLimit === 0 || this._allConnections.length < this.config.connectionLimit) { | ||
connection = new PoolConnection(this, { config: this.config.connectionConfig }); | ||
this._allConnections.push(connection); | ||
connection.connect(function(err) { | ||
if (self._closed) { | ||
cb(new Error('Pool is closed.')); | ||
return connection.connect(function(err) { | ||
if (this._closed) { | ||
return cb(new Error('Pool is closed.')); | ||
} | ||
else if (err) { | ||
cb(err); | ||
} else { | ||
cb(null, connection); | ||
if (err) { | ||
return cb(err); | ||
} | ||
this.emit('connection', connection); | ||
return cb(null, connection); | ||
}.bind(this)); | ||
} | ||
if (!this.config.waitForConnections) { | ||
return process.nextTick(function(){ | ||
return cb(new Error('No connections available.')); | ||
}); | ||
} else if (this.config.waitForConnections) { | ||
this._connectionQueue.push(cb); | ||
} else { | ||
cb(new Error('No connections available.')); | ||
} | ||
if (this.config.queueLimit && this._connectionQueue.length >= this.config.queueLimit) { | ||
return cb(new Error('Queue limit reached.')); | ||
} | ||
this._connectionQueue.push(cb); | ||
}; | ||
Pool.prototype.releaseConnection = function(connection) { | ||
if (connection._poolRemoved) { | ||
Pool.prototype.releaseConnection = function (connection) { | ||
var cb; | ||
if (!connection._pool) { | ||
// The connection has been removed from the pool and is no longer good. | ||
if (this._connectionQueue.length) { | ||
var cb = this._connectionQueue[0]; | ||
this._connectionQueue.shift(); | ||
cb = this._connectionQueue.shift(); | ||
process.nextTick(this.getConnection.bind(this, cb)); | ||
} | ||
} else if (this._connectionQueue.length) { | ||
var cb = this._connectionQueue[0]; | ||
this._connectionQueue.shift(); | ||
cb = this._connectionQueue.shift(); | ||
process.nextTick(cb.bind(null, null, connection)); | ||
@@ -65,79 +89,57 @@ } else { | ||
Pool.prototype.end = function(cb) { | ||
Pool.prototype.end = function (cb) { | ||
this._closed = true; | ||
cb = cb || function(err) { if( err ) throw err; }; | ||
var self = this; | ||
if (typeof cb != "function") { | ||
cb = function (err) { | ||
if (err) throw err; | ||
}; | ||
} | ||
var calledBack = false; | ||
var closedConnections = 0; | ||
var calledBack = false; | ||
var connection; | ||
var endCB = function(err) { | ||
if (calledBack) { | ||
return; | ||
} else if (err) { | ||
} | ||
if (err || ++closedConnections >= this._allConnections.length) { | ||
calledBack = true; | ||
delete endCB; | ||
cb(err); | ||
} else if (++closedConnections >= self._allConnections.length) { | ||
calledBack = true; | ||
delete endCB; | ||
cb(); | ||
return cb(err); | ||
} | ||
}; | ||
}.bind(this); | ||
if (this._allConnections.length == 0) { | ||
endCB(); | ||
return; | ||
if (this._allConnections.length === 0) { | ||
return endCB(); | ||
} | ||
for (var i = 0; i < this._allConnections.length; ++i) { | ||
var connection = this._allConnections[i]; | ||
connection.destroy = connection._realDestroy; | ||
connection.end = connection._realEnd; | ||
connection.end(endCB); | ||
for (var i = 0; i < this._allConnections.length; i++) { | ||
connection = this._allConnections[i]; | ||
connection._realEnd(endCB); | ||
} | ||
}; | ||
Pool.prototype._createConnection = function() { | ||
var self = this; | ||
var connection = (this.config.createConnection) | ||
? this.config.createConnection(this.config.connectionConfig) | ||
: Mysql.createConnection(this.config.connectionConfig); | ||
Pool.prototype.query = function (sql, values, cb) { | ||
if (typeof values === 'function') { | ||
cb = values; | ||
values = null; | ||
} | ||
connection._realEnd = connection.end; | ||
connection.end = function(cb) { | ||
self.releaseConnection(connection); | ||
if (cb) cb(); | ||
}; | ||
this.getConnection(function (err, conn) { | ||
if (err) return cb(err); | ||
connection._realDestroy = connection.destroy; | ||
connection.destroy = function() { | ||
self._removeConnection(connection); | ||
connection.destroy(); | ||
}; | ||
// When a fatal error occurs the connection's protocol ends, which will cause | ||
// the connection to end as well, thus we only need to watch for the end event | ||
// and we will be notified of disconnects. | ||
connection.on('end', this._handleConnectionEnd.bind(this, connection)); | ||
connection.on('error', this._handleConnectionError.bind(this, connection)); | ||
return connection; | ||
conn.query(sql, values, function () { | ||
conn.release(); | ||
cb.apply(this, arguments); | ||
}); | ||
}); | ||
}; | ||
Pool.prototype._handleConnectionEnd = function(connection) { | ||
if (this._closed || connection._poolRemoved) { | ||
return; | ||
} | ||
this._removeConnection(connection); | ||
}; | ||
Pool.prototype._removeConnection = function(connection) { | ||
var i; | ||
Pool.prototype._handleConnectionError = function(connection) { | ||
if (this._closed || connection._poolRemoved) { | ||
return; | ||
} | ||
this._removeConnection(connection); | ||
}; | ||
Pool.prototype._removeConnection = function(connection) { | ||
connection._poolRemoved = true; | ||
for (var i = 0; i < this._allConnections.length; ++i) { | ||
for (i = 0; i < this._allConnections.length; i++) { | ||
if (this._allConnections[i] === connection) { | ||
@@ -148,3 +150,4 @@ this._allConnections.splice(i, 1); | ||
} | ||
for (var i = 0; i < this._freeConnections.length; ++i) { | ||
for (i = 0; i < this._freeConnections.length; i++) { | ||
if (this._freeConnections[i] === connection) { | ||
@@ -156,5 +159,7 @@ this._freeConnections.splice(i, 1); | ||
connection.end = connection._realEnd; | ||
connection.destroy = connection._realDestroy; | ||
this.releaseConnection(connection); | ||
}; | ||
Pool.prototype.escape = function(value) { | ||
return mysql.escape(value, this.config.connectionConfig.stringifyObjects, this.config.connectionConfig.timezone); | ||
}; |
@@ -7,3 +7,2 @@ | ||
this.connectionConfig = new ConnectionConfig(options); | ||
this.createConnection = options.createConnection || undefined; | ||
this.waitForConnections = (options.waitForConnections === undefined) | ||
@@ -15,2 +14,5 @@ ? true | ||
: Number(options.connectionLimit); | ||
this.queueLimit = (options.queueLimit === undefined) | ||
? 0 | ||
: Number(options.queueLimit); | ||
} |
@@ -24,3 +24,3 @@ module.exports = ComChangeUserPacket; | ||
writer.writeNullTerminatedString(this.database); | ||
writer.writeUnsignedNumber(1, this.charsetNumber); | ||
writer.writeUnsignedNumber(2, this.charsetNumber); | ||
}; |
@@ -8,2 +8,3 @@ var Types = require('../constants/types'); | ||
this.parser = options.parser; | ||
this.packet = options.packet; | ||
this.db = options.packet.db; | ||
@@ -10,0 +11,0 @@ this.table = options.packet.table; |
@@ -33,3 +33,3 @@ module.exports = FieldPacket; | ||
this.charsetNr = parser.parseUnsignedNumber(2); | ||
this.fieldLength = parser.parseUnsignedNumber(4); | ||
this.length = parser.parseUnsignedNumber(4); | ||
this.type = parser.parseUnsignedNumber(1); | ||
@@ -51,3 +51,3 @@ this.flags = parser.parseUnsignedNumber(2); | ||
this.name = parser.parseLengthCodedString(); | ||
this.fieldLength = parser.parseUnsignedNumber(parser.parseUnsignedNumber(1)); | ||
this.length = parser.parseUnsignedNumber(parser.parseUnsignedNumber(1)); | ||
this.type = parser.parseUnsignedNumber(parser.parseUnsignedNumber(1)); | ||
@@ -67,3 +67,3 @@ } | ||
writer.writeUnsignedNumber(2, this.charsetNr || 0); | ||
writer.writeUnsignedNumber(4, this.fieldLength || 0); | ||
writer.writeUnsignedNumber(4, this.length || 0); | ||
writer.writeUnsignedNumber(1, this.type || 0); | ||
@@ -81,3 +81,3 @@ writer.writeUnsignedNumber(2, this.flags || 0); | ||
writer.writeUnsignedNumber(1, 0x01); | ||
writer.writeUnsignedNumber(1, this.fieldLength); | ||
writer.writeUnsignedNumber(1, this.length); | ||
writer.writeUnsignedNumber(1, 0x01); | ||
@@ -84,0 +84,0 @@ writer.writeUnsignedNumber(1, this.type); |
@@ -60,3 +60,3 @@ var Types = require('../constants/types'); | ||
} else { | ||
dateString += timeZone; | ||
dateString += ' ' + timeZone; | ||
} | ||
@@ -63,0 +63,0 @@ } |
@@ -34,2 +34,4 @@ var Util = require('util'); | ||
err.code = code; | ||
err.errno = packet.errno; | ||
err.sqlState = packet.sqlState; | ||
@@ -59,2 +61,9 @@ return err; | ||
// Without this we are leaking memory. This problem was introduced in | ||
// 8189925374e7ce3819bbe88b64c7b15abac96b16. I suspect that the error object | ||
// causes a cyclic reference that the GC does not detect properly, but I was | ||
// unable to produce a standalone version of this leak. This would be a great | ||
// challenge for somebody interested in difficult problems : )! | ||
delete this._callSite; | ||
// try...finally for exception safety | ||
@@ -61,0 +70,0 @@ try { |
@@ -21,3 +21,3 @@ var SqlString = exports; | ||
if (val instanceof Date) { | ||
val = SqlString.dateToString(val, timeZone || "Z"); | ||
val = SqlString.dateToString(val, timeZone || 'local'); | ||
} | ||
@@ -57,3 +57,3 @@ | ||
return array.map(function(v) { | ||
if (Array.isArray(v)) return '(' + SqlString.arrayToList(v) + ')'; | ||
if (Array.isArray(v)) return '(' + SqlString.arrayToList(v, timeZone) + ')'; | ||
return SqlString.escape(v, true, timeZone); | ||
@@ -63,3 +63,3 @@ }).join(', '); | ||
SqlString.format = function(sql, values, timeZone) { | ||
SqlString.format = function(sql, values, stringifyObjects, timeZone) { | ||
values = [].concat(values); | ||
@@ -75,3 +75,3 @@ | ||
} | ||
return SqlString.escape(values.shift(), false, timeZone); | ||
return SqlString.escape(values.shift(), stringifyObjects, timeZone); | ||
}); | ||
@@ -93,9 +93,10 @@ }; | ||
var year = dt.getFullYear(); | ||
var month = zeroPad(dt.getMonth() + 1); | ||
var day = zeroPad(dt.getDate()); | ||
var hour = zeroPad(dt.getHours()); | ||
var minute = zeroPad(dt.getMinutes()); | ||
var second = zeroPad(dt.getSeconds()); | ||
var month = zeroPad(dt.getMonth() + 1, 2); | ||
var day = zeroPad(dt.getDate(), 2); | ||
var hour = zeroPad(dt.getHours(), 2); | ||
var minute = zeroPad(dt.getMinutes(), 2); | ||
var second = zeroPad(dt.getSeconds(), 2); | ||
var millisecond = zeroPad(dt.getMilliseconds(), 3); | ||
return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second; | ||
return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second + '.' + millisecond; | ||
}; | ||
@@ -132,4 +133,9 @@ | ||
function zeroPad(number) { | ||
return (number < 10) ? '0' + number : number; | ||
function zeroPad(number, length) { | ||
number = number.toString(); | ||
while (number.length < length) { | ||
number = '0' + number; | ||
} | ||
return number; | ||
} | ||
@@ -136,0 +142,0 @@ |
@@ -5,3 +5,3 @@ { | ||
"description": "A node.js driver for mysql. It is written in JavaScript, does not require compiling, and is 100% MIT licensed.", | ||
"version": "2.0.0-alpha8", | ||
"version": "2.0.0-alpha9", | ||
"repository": { | ||
@@ -8,0 +8,0 @@ "type": "git", |
165
Readme.md
@@ -8,3 +8,3 @@ # node-mysql | ||
```bash | ||
npm install mysql@2.0.0-alpha8 | ||
npm install mysql@2.0.0-alpha9 | ||
``` | ||
@@ -142,4 +142,6 @@ | ||
* `database`: Name of the database to use for this connection (Optional). | ||
* `charset`: The charset for the connection. (Default: `'UTF8_GENERAL_CI'`) | ||
* `charset`: The charset for the connection. (Default: `'UTF8_GENERAL_CI'`. Value needs to be all in upper case letters!) | ||
* `timezone`: The timezone used to store local dates. (Default: `'local'`) | ||
* `stringifyObjects`: Stringify objects instead of converting to values. See | ||
issue [#501](https://github.com/felixge/node-mysql/issues/501). (Default: `'false'`) | ||
* `insecureAuth`: Allow connecting to MySQL instances that ask for the old | ||
@@ -211,3 +213,3 @@ (insecure) authentication method. (Default: `false`) | ||
user : 'bob', | ||
password : 'secret' | ||
password : 'secret', | ||
}); | ||
@@ -220,2 +222,11 @@ | ||
If you need to set session variables on the connection before it gets used, | ||
you can listen to the `connection` event. | ||
```js | ||
pool.on('connection', function(err, connection) { | ||
connection.query('SET SESSION auto_increment_increment=1') | ||
}); | ||
``` | ||
When you are done with a connection, just call `connection.end()` and the | ||
@@ -262,3 +273,62 @@ connection will return to the pool, ready to be used again by someone else. | ||
(Default: `10`) | ||
* `queueLimit`: The maximum number of connection requests the pool will queue | ||
before returning an error from `getConnection`. If set to `0`, there is no | ||
limit to the number of queued connection requests. (Default: `0`) | ||
## PoolCluster | ||
PoolCluster provides multiple hosts connection. (group & retry & selector) | ||
```js | ||
// create | ||
var poolCluster = mysql.createPoolCluster(); | ||
poolCluster.add(config); // anonymous group | ||
poolCluster.add('MASTER', masterConfig); | ||
poolCluster.add('SLAVE1', slave1Config); | ||
poolCluster.add('SLAVE2', slave2Config); | ||
// Target Group : ALL(anonymous, MASTER, SLAVE1-2), Selector : round-robin(default) | ||
poolCluster.getConnection(function (err, connection) {}); | ||
// Target Group : MASTER, Selector : round-robin | ||
poolCluster.getConnection('MASTER', function (err, connection) {}); | ||
// Target Group : SLAVE1-2, Selector : order | ||
// If can't connect to SLAVE1, return SLAVE2. (remove SLAVE1 in the cluster) | ||
poolCluster.on('remove', function (nodeId) { | ||
console.log('REMOVED NODE : ' + nodeId); // nodeId = SLAVE1 | ||
}); | ||
poolCluster.getConnection('SLAVE*', 'ORDER', function (err, connection) {}); | ||
// of namespace : of(pattern, selector) | ||
poolCluster.of('*').getConnection(function (err, connection) {}); | ||
var pool = poolCluster.of('SLAVE*', 'RANDOM'); | ||
pool.getConnection(function (err, connection) {}); | ||
pool.getConnection(function (err, connection) {}); | ||
// destroy | ||
poolCluster.end(); | ||
``` | ||
## PoolCluster Option | ||
* `canRetry`: If `true`, `PoolCluster` will attempt to reconnect when connection fails. (Default: `true`) | ||
* `removeNodeErrorCount`: If connection fails, node's `errorCount` increases. | ||
When `errorCount` is greater than `removeNodeErrorCount`, remove a node in the `PoolCluster`. (Default: `5`) | ||
* `defaultSelector`: The default selector. (Default: `RR`) | ||
* `RR`: Select one alternately. (Round-Robin) | ||
* `RANDOM`: Select the node by random function. | ||
* `ORDER`: Select the first node available unconditionally. | ||
```js | ||
var clusterConfig = { | ||
removeNodeErrorCount: 1, // Remove the node immediately when connection fails. | ||
defaultSelector: 'ORDER', | ||
}; | ||
var poolCluster = mysql.createPoolCluster(clusterConfig); | ||
``` | ||
## Switching users / altering connection state | ||
@@ -291,29 +361,41 @@ | ||
You may lose the connection to a MySQL server due to network problems, the | ||
server timing you out, or the server crashing. All of these events are | ||
considered fatal errors, and will have the `err.code = | ||
server timing you out, the server being restarted, or crashing. All of these | ||
events are considered fatal errors, and will have the `err.code = | ||
'PROTOCOL_CONNECTION_LOST'`. See the [Error Handling](#error-handling) section | ||
for more information. | ||
The best way to handle such unexpected disconnects is shown below: | ||
A good way to handle such unexpected disconnects is shown below: | ||
```js | ||
function handleDisconnect(connection) { | ||
connection.on('error', function(err) { | ||
if (!err.fatal) { | ||
return; | ||
} | ||
var db_config = { | ||
host: 'localhost', | ||
user: 'root', | ||
password: '', | ||
database: 'example' | ||
}; | ||
if (err.code !== 'PROTOCOL_CONNECTION_LOST') { | ||
throw err; | ||
} | ||
var connection; | ||
console.log('Re-connecting lost connection: ' + err.stack); | ||
function handleDisconnect() { | ||
connection = mysql.createConnection(db_config); // Recreate the connection, since | ||
// the old one cannot be reused. | ||
connection = mysql.createConnection(connection.config); | ||
handleDisconnect(connection); | ||
connection.connect(); | ||
connection.connect(function(err) { // The server is either down | ||
if(err) { // or restarting (takes a while sometimes). | ||
console.log('error when connecting to db:', err); | ||
setTimeout(handleDisconnect, 2000); // We introduce a delay before attempting to reconnect, | ||
} // to avoid a hot loop, and to allow our node script to | ||
}); // process asynchronous requests in the meantime. | ||
// If you're also serving http, display a 503 error. | ||
connection.on('error', function(err) { | ||
console.log('db error', err); | ||
if(err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually | ||
handleDisconnect(); // lost due to either server restart, or a | ||
} else { // connnection idle timeout (the wait_timeout | ||
throw err; // server variable configures this) | ||
} | ||
}); | ||
} | ||
handleDisconnect(connection); | ||
handleDisconnect(); | ||
``` | ||
@@ -332,3 +414,3 @@ | ||
provided data before using it inside a SQL query. You can do so using the | ||
`connection.escape()` method: | ||
`connection.escape()` or `pool.escape()` methods: | ||
@@ -623,3 +705,3 @@ ```js | ||
table2_fieldA: '...', | ||
table2_fieldB: '...' | ||
table2_fieldB: '...', | ||
}, ...] | ||
@@ -772,3 +854,3 @@ */ | ||
}): | ||
}); | ||
``` | ||
@@ -790,8 +872,20 @@ | ||
} | ||
}) | ||
}); | ||
``` | ||
__WARNING: YOU MUST INVOKE the parser using one of these three field functions in your custom typeCast callback. They can only be called once.( see #539 for discussion)__ | ||
If you need a buffer there's also a `.buffer()` function and also a `.geometry()` one | ||
both used by the default type cast that you can use. | ||
``` | ||
field.string() | ||
field.buffer() | ||
field.geometry() | ||
``` | ||
are aliases for | ||
``` | ||
parser.parseLengthCodedString() | ||
parser.parseLengthCodedBuffer() | ||
parser.parseGeometryValue() | ||
``` | ||
__You can find which field function you need to use by looking at: [RowDataPacket.prototype._typeCast](https://github.com/felixge/node-mysql/blob/master/lib/protocol/packets/RowDataPacket.js#L41)__ | ||
## Connection Flags | ||
@@ -812,3 +906,3 @@ | ||
```js | ||
var connection = mysql.createConnection("mysql://localhost/test?flags=-FOUND_ROWS") | ||
var connection = mysql.createConnection("mysql://localhost/test?flags=-FOUND_ROWS"); | ||
``` | ||
@@ -869,2 +963,21 @@ | ||
## Running unit tests | ||
Set the environment variables `MYSQL_DATABASE`, `MYSQL_HOST`, `MYSQL_PORT`, `MYSQL_USER` and `MYSQL_PASSWORD`. (You may want to put these in a `config.sh` file and source it when you run the tests). Then run `make test`. | ||
For example, if you have an installation of mysql running on localhost:3306 and no password set for the `root` user, run: | ||
``` | ||
mysql -u root -e "CREATE DATABASE IF NOT EXISTS node_mysql_test" | ||
MYSQL_HOST=localhost MYSQL_PORT=3306 MYSQL_DATABASE=node_mysql_test MYSQL_USER=root MYSQL_PASSWORD= make test | ||
``` | ||
## Running unit tests on windows | ||
* Edit the variables in the file ```make.bat``` according to your system and mysql-settings. | ||
* Make sure the database (e.g. 'test') you want to use exists and the user you entered has the proper rights to use the test database. (E.g. do not forget to execute the SQL-command ```FLUSH PRIVILEGES``` after you have created the user.) | ||
* In a DOS-box (or CMD-shell) in the folder of your application run ```npm install mysql --dev``` or in the mysql folder (```node_modules\mysql```), run ```npm install --dev```. (This will install additional developer-dependencies for node-mysql.) | ||
* Run ```npm test mysql``` in your applications folder or ```npm test``` in the mysql subfolder. | ||
* If you want to log the output into a file use ```npm test mysql > test.log``` or ```npm test > test.log```. | ||
## Todo | ||
@@ -871,0 +984,0 @@ |
@@ -34,6 +34,12 @@ var common = exports; | ||
config = mergeTestConfig(config); | ||
config.createConnection = common.createConnection; | ||
config.connectionConfig = mergeTestConfig(config.connectionConfig); | ||
return Mysql.createPool(config); | ||
}; | ||
common.createPoolCluster = function(config) { | ||
config = mergeTestConfig(config); | ||
config.createConnection = common.createConnection; | ||
return Mysql.createPoolCluster(config); | ||
}; | ||
common.createFakeServer = function(options) { | ||
@@ -49,4 +55,8 @@ return new FakeServer(_.extend({}, options)); | ||
connection.query('USE ' + common.testDatabase); | ||
} | ||
}; | ||
common.getTestConfig = function(config) { | ||
return mergeTestConfig(config); | ||
}; | ||
function mergeTestConfig(config) { | ||
@@ -53,0 +63,0 @@ if (common.isTravis()) { |
@@ -0,1 +1,10 @@ | ||
/** | ||
* This test is skipped, if the environment variable "windir" is set. | ||
* It assumes that it runs on a windows system then. | ||
*/ | ||
if (process.env.windir) { | ||
return console.log('Skipping "test-unix-domain-socket.js" - Environment' | ||
+ ' variable "windir" is set. Skipping this, because we seem to be on' | ||
+ ' a windows system'); | ||
} | ||
var common = require('../../common'); | ||
@@ -7,2 +16,3 @@ var connection = common.createConnection({socketPath: common.fakeServerSocket}); | ||
var didConnect = false; | ||
server.listen(common.fakeServerSocket, function(err) { | ||
@@ -31,4 +41,4 @@ if (err) throw err; | ||
process.on('exit', function() { | ||
assert.equal(didConnect, true); | ||
assert.equal(hadConnection, true); | ||
assert.equal(didConnect, true); | ||
assert.equal(hadConnection, true); | ||
}); |
@@ -24,4 +24,4 @@ var common = require('../../common'); | ||
shouldGetConnection = true; | ||
connection.end(); | ||
connection.release(); | ||
}); | ||
}); |
@@ -12,7 +12,5 @@ var common = require('../../common'); | ||
assert.ok(pool._allConnections.length == 0); | ||
assert.ok(connection._poolRemoved); | ||
assert.strictEqual(connection.end, Connection.prototype.end); | ||
assert.strictEqual(connection.destroy, Connection.prototype.destroy); | ||
assert.ok(!connection._pool); | ||
pool.end(); | ||
}); |
@@ -88,5 +88,5 @@ var common = require('../../common'); | ||
'dates are converted to YYYY-MM-DD HH:II:SS': function() { | ||
var expected = '2012-05-07 11:42:03'; | ||
var date = new Date(Date.UTC(2012, 4, 7, 11, 42, 3)); | ||
'dates are converted to YYYY-MM-DD HH:II:SS.sss': function() { | ||
var expected = '2012-05-07 11:42:03.002'; | ||
var date = new Date(2012, 4, 7, 11, 42, 3, 2); | ||
var string = SqlString.escape(date); | ||
@@ -133,2 +133,15 @@ | ||
}, | ||
'objects is converted to values': function () { | ||
var sql = SqlString.format('?', { 'hello': 'world' }, false) | ||
assert.equal(sql, "`hello` = 'world'") | ||
}, | ||
'objects is not converted to values': function () { | ||
var sql = SqlString.format('?', { 'hello': 'world' }, true) | ||
assert.equal(sql, "'[object Object]'") | ||
var sql = SqlString.format('?', { toString: function () { return 'hello' } }, true) | ||
assert.equal(sql, "'hello'") | ||
} | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
259393
136
6074
977
28
4