Comparing version 2.0.0-alpha9 to 2.0.0-rc1
@@ -7,2 +7,10 @@ # Changes | ||
## v2.0.0-rc1 (2013-11-30) | ||
* Transaction support | ||
* Expose SqlString.format as mysql.format() | ||
* Many bug fixes | ||
* Better support for dates in local time zone | ||
* Doc improvements | ||
## v2.0.0-alpha9 (2013-08-27) | ||
@@ -9,0 +17,0 @@ |
@@ -26,1 +26,2 @@ var Connection = require('./lib/Connection'); | ||
exports.escapeId = SqlString.escapeId; | ||
exports.format = SqlString.format; |
@@ -54,5 +54,6 @@ var Net = require('net'); | ||
// Connect either via a UNIX domain socket or a TCP socket. | ||
this._socket = (this.config.socketPath) | ||
? Net.createConnection(this.config.socketPath) | ||
: Net.createConnection(this.config.port, this.config.host); | ||
: Net.createConnection(this.config); | ||
@@ -77,2 +78,4 @@ // Node v0.10+ Switch socket into "old mode" (Streams2) | ||
Connection.prototype.changeUser = function(options, cb){ | ||
cb = cb || function() {}; | ||
this._implyConnect(); | ||
@@ -86,5 +89,7 @@ | ||
var charsetNumber = (options.charset) | ||
? Config.getCharsetNumber(options.charset) | ||
? ConnectionConfig.getCharsetNumber(options.charset) | ||
: this.config.charsetNumber; | ||
var self = this; | ||
return this._protocol.changeUser({ | ||
@@ -99,2 +104,29 @@ user : options.user || this.config.user, | ||
Connection.prototype.beginTransaction = function(cb) { | ||
this._implyConnect(); | ||
var query = Connection.createQuery('START TRANSACTION', cb); | ||
query._connection = this; | ||
return this._protocol._enqueue(query); | ||
}; | ||
Connection.prototype.commit = function(cb) { | ||
this._implyConnect(); | ||
var query = Connection.createQuery('COMMIT', cb); | ||
query._connection = this; | ||
return this._protocol._enqueue(query); | ||
}; | ||
Connection.prototype.rollback = function(cb) { | ||
this._implyConnect(); | ||
var query = Connection.createQuery('ROLLBACK', cb); | ||
query._connection = this; | ||
return this._protocol._enqueue(query); | ||
}; | ||
Connection.prototype.query = function(sql, values, cb) { | ||
@@ -101,0 +133,0 @@ this._implyConnect(); |
@@ -13,2 +13,3 @@ var urlParse = require('url').parse; | ||
this.port = options.port || 3306; | ||
this.localAddress = options.localAddress; | ||
this.socketPath = options.socketPath; | ||
@@ -21,2 +22,3 @@ this.user = options.user || undefined; | ||
this.bigNumberStrings = options.bigNumberStrings || false; | ||
this.dateStrings = options.dateStrings || false; | ||
this.debug = options.debug; | ||
@@ -23,0 +25,0 @@ this.stringifyObjects = options.stringifyObjects || false; |
@@ -108,3 +108,2 @@ var mysql = require('../'); | ||
calledBack = true; | ||
delete endCB; | ||
return cb(err); | ||
@@ -111,0 +110,0 @@ } |
@@ -67,2 +67,3 @@ var Pool = require('./Pool'); | ||
PoolCluster.prototype.getConnection = function(pattern, selector, cb) { | ||
var namespace; | ||
if (typeof pattern === 'function') { | ||
@@ -69,0 +70,0 @@ cb = pattern; |
@@ -19,2 +19,6 @@ var inherits = require('util').inherits | ||
PoolConnection.prototype.release = function () { | ||
if (!this._pool || this._pool._closed) { | ||
return; | ||
} | ||
return this._pool.releaseConnection(this); | ||
@@ -21,0 +25,0 @@ }; |
@@ -13,3 +13,3 @@ var Types = require('../constants/types'); | ||
var next = function () { | ||
return self._typeCast(fieldPacket, parser, connection.config.timezone, connection.config.supportBigNumbers, connection.config.bigNumberStrings); | ||
return self._typeCast(fieldPacket, parser, connection.config.timezone, connection.config.supportBigNumbers, connection.config.bigNumberStrings, connection.config.dateStrings); | ||
}; | ||
@@ -25,3 +25,3 @@ | ||
value = (typeCast) | ||
? this._typeCast(fieldPacket, parser, connection.config.timezone, connection.config.supportBigNumbers, connection.config.bigNumberStrings) | ||
? this._typeCast(fieldPacket, parser, connection.config.timezone, connection.config.supportBigNumbers, connection.config.bigNumberStrings, connection.config.dateStrings) | ||
: ( (fieldPacket.charsetNr === Charsets.BINARY) | ||
@@ -43,3 +43,3 @@ ? parser.parseLengthCodedBuffer() | ||
RowDataPacket.prototype._typeCast = function(field, parser, timeZone, supportBigNumbers, bigNumberStrings) { | ||
RowDataPacket.prototype._typeCast = function(field, parser, timeZone, supportBigNumbers, bigNumberStrings, dateStrings) { | ||
var numberString; | ||
@@ -53,2 +53,5 @@ | ||
var dateString = parser.parseLengthCodedString(); | ||
if (dateStrings) { | ||
return dateString; | ||
} | ||
var dt; | ||
@@ -60,13 +63,14 @@ | ||
if (timeZone != 'local') { | ||
if (field.type === Types.DATE) { | ||
dateString += ' 00:00:00 ' + timeZone; | ||
} else { | ||
dateString += ' ' + timeZone; | ||
} | ||
var originalString = dateString; | ||
if (field.type === Types.DATE) { | ||
dateString += ' 00:00:00'; | ||
} | ||
if (timeZone !== 'local') { | ||
dateString += ' ' + timeZone; | ||
} | ||
dt = new Date(dateString); | ||
if (isNaN(dt.getTime())) { | ||
return dateString; | ||
return originalString; | ||
} | ||
@@ -73,0 +77,0 @@ |
@@ -109,3 +109,3 @@ var Parser = require('./Parser'); | ||
this._parser.resetPacketNumber(); | ||
sequence.start(); | ||
this._startSequence(sequence); | ||
} | ||
@@ -118,13 +118,18 @@ | ||
var err; | ||
var prefix = 'Cannot enqueue ' + sequence.constructor.name + ' after '; | ||
var prefix = 'Cannot enqueue ' + sequence.constructor.name; | ||
var prefixBefore = prefix + ' before '; | ||
var prefixAfter = prefix + ' after '; | ||
if (this._quitSequence) { | ||
err = new Error(prefix + 'invoking quit.'); | ||
err = new Error(prefixAfter + 'invoking quit.'); | ||
err.code = 'PROTOCOL_ENQUEUE_AFTER_QUIT'; | ||
} else if (this._destroyed) { | ||
err = new Error(prefix + 'being destroyed.'); | ||
err = new Error(prefixAfter + 'being destroyed.'); | ||
err.code = 'PROTOCOL_ENQUEUE_AFTER_DESTROY'; | ||
} else if (this._handshakeSequence && sequence.constructor === Sequences.Handshake) { | ||
err = new Error(prefix + 'already enqueuing a Handshake.'); | ||
err = new Error(prefixAfter + 'already enqueuing a Handshake.'); | ||
err.code = 'PROTOCOL_ENQUEUE_HANDSHAKE_TWICE'; | ||
} else if (!this._handshakeSequence && sequence.constructor === Sequences.ChangeUser) { | ||
err = new Error(prefixBefore + 'a Handshake.'); | ||
err.code = 'PROTOCOL_ENQUEUE_BEFORE_HANDSHAKE'; | ||
} else { | ||
@@ -227,8 +232,11 @@ return true; | ||
if (sequence.constructor == Sequences.ChangeUser) { | ||
this._startSequence(sequence); | ||
}; | ||
Protocol.prototype._startSequence = function(sequence) { | ||
if (sequence.constructor === Sequences.ChangeUser) { | ||
sequence.start(this._handshakeInitializationPacket); | ||
return; | ||
} else { | ||
sequence.start(); | ||
} | ||
sequence.start(); | ||
}; | ||
@@ -235,0 +243,0 @@ |
var SqlString = exports; | ||
SqlString.escapeId = function (val, forbidQualified) { | ||
if (Array.isArray(val)) { | ||
return val.map(function(v) { | ||
return SqlString.escapeId(v, forbidQualified); | ||
}).join(', '); | ||
} | ||
if (forbidQualified) { | ||
@@ -5,0 +11,0 @@ return '`' + val.replace(/`/g, '``') + '`'; |
@@ -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-alpha9", | ||
"version": "2.0.0-rc1", | ||
"repository": { | ||
@@ -8,0 +8,0 @@ "type": "git", |
@@ -136,2 +136,3 @@ # node-mysql | ||
* `port`: The port number to connect to. (Default: `3306`) | ||
* `localAddress`: The source IP address to use for TCP connection. (Optional) | ||
* `socketPath`: The path to a unix domain socket to connect to. When used `host` | ||
@@ -159,2 +160,4 @@ and `port` are ignored. | ||
Number objects. This option is ignored if `supportBigNumbers` is disabled. | ||
* `dateStrings`: Force date types (TIMESTAMP, DATETIME, DATE) to be returned as strings rather then | ||
inflated into JavaScript Date objects. (Default: `false`) | ||
* `debug`: Prints protocol details to stdout. (Default: `false`) | ||
@@ -225,3 +228,3 @@ * `multipleStatements`: Allow multiple mysql statements per query. Be careful | ||
```js | ||
pool.on('connection', function(err, connection) { | ||
pool.on('connection', function(connection) { | ||
connection.query('SET SESSION auto_increment_increment=1') | ||
@@ -231,3 +234,3 @@ }); | ||
When you are done with a connection, just call `connection.end()` and the | ||
When you are done with a connection, just call `connection.release()` and the | ||
connection will return to the pool, ready to be used again by someone else. | ||
@@ -243,3 +246,3 @@ | ||
// And done with the connection. | ||
connection.end(); | ||
connection.release(); | ||
@@ -498,5 +501,9 @@ // Don't use the connection here, it has been returned to the pool. | ||
```js | ||
connection.query('SELECT * FROM ?? WHERE id = ?', ['users', userId], function(err, results) { | ||
var userId = 1; | ||
var columns = ['username', 'email']; | ||
var query = connection.query('SELECT ?? FROM ?? WHERE id = ?', [columns, 'users', userId], function(err, results) { | ||
// ... | ||
}); | ||
console.log(query.sql); // SELECT `username`, `email` FROM `users` WHERE id = 1 | ||
``` | ||
@@ -507,2 +514,14 @@ **Please note that this last character sequence is experimental and syntax might change** | ||
### Preparing Queries | ||
You can use mysql.format to prepare a query with multiple insertion points, utilizing the proper escaping for ids and values. A simple example of this follows: | ||
```js | ||
var sql = "SELECT * FROM ?? WHERE ?? = ?"; | ||
var inserts = ['users', 'id', userId]; | ||
sql = mysql.format(sql, inserts); | ||
``` | ||
Following this you then have a valid, escaped query that you can then send to the database safely. This is useful if you are looking to prepare the query before actually sending it to the database. As mysql.format is exposed from SqlString.format you also have the option (but are not required) to pass in stringifyObject and timezone, allowing you provide a custom means of turning objects into strings, as well as a location-specific/timezone-aware Date. | ||
### Custom format | ||
@@ -711,2 +730,41 @@ | ||
## Transactions | ||
Simple transaction support is available at the connection level: | ||
```js | ||
connection.beginTransaction(function(err) { | ||
if (err) { throw err; } | ||
connection.query('INSERT INTO posts SET title=?', title, function(err, result) { | ||
if (err) { | ||
connection.rollback(function() { | ||
throw err; | ||
}); | ||
} | ||
var log = 'Post ' + result.insertId + ' added'; | ||
connection.query('INSERT INTO log SET data=?', log, function(err, result) { | ||
if (err) { | ||
connection.rollback(function() { | ||
throw err; | ||
}); | ||
} | ||
connection.commit(function(err) { | ||
if (err) { | ||
connection.rollback(function() { | ||
throw err; | ||
}); | ||
} | ||
console.log('success!'); | ||
}); | ||
}); | ||
}); | ||
}); | ||
``` | ||
Please note that beginTransaction(), commit() and rollback() are simply convenience | ||
functions that execute the START TRANSACTION, COMMIT, and ROLLBACK commands respectively. | ||
It is important to understand that many commands in MySQL can cause an implicit commit, | ||
as described [in the MySQL documentation](http://dev.mysql.com/doc/refman/5.5/en/implicit-commit.html) | ||
## Error handling | ||
@@ -984,2 +1042,1 @@ | ||
* Support for encodings other than UTF-8 / ASCII | ||
* API support for transactions, similar to [php](http://www.php.net/manual/en/mysqli.quickstart.transactions.php) |
Sorry, the diff of this file is not supported yet
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
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 31 instances 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
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
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
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 9 instances in 1 package
2266923
1034
2
121
3714
32