Comparing version 2.0.0-alpha2 to 2.0.0-alpha3
@@ -5,2 +5,3 @@ var lib = __dirname + '/../lib'; | ||
var PacketWriter = require(lib + '/protocol/PacketWriter'); | ||
var Parser = require(lib + '/protocol/Parser'); | ||
@@ -15,2 +16,4 @@ var options = { | ||
function createBuffers() { | ||
var parser = new Parser(); | ||
process.stderr.write('Creating row buffers ... '); | ||
@@ -23,13 +26,13 @@ | ||
var buffers = [ | ||
createPacketBuffer(number++, new Packets.ResultSetHeaderPacket({fieldCount: 2})), | ||
createPacketBuffer(number++, new Packets.FieldPacket({catalog: 'foo', name: 'id'})), | ||
createPacketBuffer(number++, new Packets.FieldPacket({catalog: 'foo', name: 'text'})), | ||
createPacketBuffer(number++, new Packets.EofPacket()), | ||
createPacketBuffer(parser, new Packets.ResultSetHeaderPacket({fieldCount: 2})), | ||
createPacketBuffer(parser, new Packets.FieldPacket({catalog: 'foo', name: 'id'})), | ||
createPacketBuffer(parser, new Packets.FieldPacket({catalog: 'foo', name: 'text'})), | ||
createPacketBuffer(parser, new Packets.EofPacket()), | ||
]; | ||
for (var i = 0; i < options.rows; i++) { | ||
buffers.push(createRowDataPacketBuffer(id++, number++)); | ||
buffers.push(createRowDataPacketBuffer(parser, number++)); | ||
} | ||
buffers.push(createPacketBuffer(number++, new Packets.EofPacket)); | ||
buffers.push(createPacketBuffer(parser, new Packets.EofPacket)); | ||
@@ -49,15 +52,15 @@ buffers = mergeBuffers(buffers); | ||
function createPacketBuffer(number, packet) { | ||
var writer = new PacketWriter(number % 256); | ||
function createPacketBuffer(parser, packet) { | ||
var writer = new PacketWriter(); | ||
packet.write(writer); | ||
return writer.toBuffer(); | ||
return writer.toBuffer(parser); | ||
} | ||
function createRowDataPacketBuffer(id, number) { | ||
var writer = new PacketWriter(number++ % 256); | ||
function createRowDataPacketBuffer(parser, number) { | ||
var writer = new PacketWriter(); | ||
writer.writeLengthCodedString(id); | ||
writer.writeLengthCodedString(parser._nextPacketNumber); | ||
writer.writeLengthCodedString('Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has sur'); | ||
return writer.toBuffer(); | ||
return writer.toBuffer(parser); | ||
} | ||
@@ -64,0 +67,0 @@ |
@@ -7,6 +7,22 @@ # Changes | ||
## v2.0.0-alpha2 (unreleased) | ||
## v2.0.0-alpha3 (2012-06-12) | ||
* Implement support for `LOAD DATA LOCAL INFILE` queries (#182). | ||
* Support OLD\_PASSWORD() accounts like 0.9.x did. You should still upgrade any | ||
user accounts in your your MySQL user table that has short (16 byte) Password | ||
values. Connecting to those accounts is not secure. (#204) | ||
* Ignore function values when escaping objects, allows to use RowDataPacket | ||
objects as query arguments. (Alex Gorbatchev, #213) | ||
* Handle initial error packets from server such as `ER_HOST_NOT_PRIVILEGED`. | ||
* Treat `utf8\_bin` as a String, not Buffer. (#214) | ||
* Handle empty strings in first row column value. (#222) | ||
* Honor Connection#nestTables setting for queries. (#221) | ||
* Remove `CLIENT_INTERACTIVE` flag from config. Improves #225. | ||
* Improve docs for connections settings. | ||
* Implement url string support for Connection configs. | ||
## v2.0.0-alpha2 (2012-05-31) | ||
* Specify escaping before for NaN / Infinity (they are as unquoted constants). | ||
* Support for unix domain socket connections (use: {socketPath: '...'}) | ||
* Support for unix domain socket connections (use: {socketPath: '...'}). | ||
* Fix type casting for NULL values for Date/Number fields | ||
@@ -20,3 +36,3 @@ * Add `fields` argument to `query()` as well as `'fields'` event. This is | ||
with overlapping column names. | ||
* Fix ? placeholder mechanism for values containing '?' characters(#205) | ||
* Fix ? placeholder mechanism for values containing '?' characters (#205). | ||
* Detect when `connect()` is called more than once on a connection and provide | ||
@@ -27,3 +43,3 @@ the user with a good error message for it (#204). | ||
and also make the charset user configurable. | ||
* Fix BLOB type casting for `TINY_BLOG`, `MEDIUM_BLOB` and `LONG_BLOB` | ||
* Fix BLOB type casting for `TINY_BLOG`, `MEDIUM_BLOB` and `LONG_BLOB`. | ||
* Add support for sending and receiving large (> 16 MB) packets. | ||
@@ -30,0 +46,0 @@ |
@@ -0,1 +1,2 @@ | ||
var urlParse = require('url').parse; | ||
var ClientConstants = require('./protocol/constants/client'); | ||
@@ -6,10 +7,15 @@ var Charsets = require('./protocol/constants/charsets'); | ||
function Config(options) { | ||
this.host = options.host || 'localhost'; | ||
this.port = options.port || 3306; | ||
this.socketPath = options.socketPath; | ||
this.user = options.user || undefined; | ||
this.password = options.password || undefined; | ||
this.database = options.database; | ||
this.debug = options.debug; | ||
this.typeCast = (options.typeCast === undefined) | ||
if (typeof options === 'string') { | ||
options = Config.parseUrl(options); | ||
} | ||
this.host = options.host || 'localhost'; | ||
this.port = options.port || 3306; | ||
this.socketPath = options.socketPath; | ||
this.user = options.user || undefined; | ||
this.password = options.password || undefined; | ||
this.database = options.database; | ||
this.insecureAuth = options.insecureAuth || false; | ||
this.debug = options.debug; | ||
this.typeCast = (options.typeCast === undefined) | ||
? true | ||
@@ -32,3 +38,2 @@ : options.typeCast; | ||
ClientConstants.CLIENT_PROTOCOL_41 | | ||
ClientConstants.CLIENT_INTERACTIVE | | ||
ClientConstants.CLIENT_IGNORE_SIGPIPE | | ||
@@ -44,1 +49,33 @@ ClientConstants.CLIENT_TRANSACTIONS | | ||
} | ||
Config.parseUrl = function(url) { | ||
url = urlParse(url, true); | ||
var options = { | ||
host : url.hostname, | ||
port : url.port, | ||
database : url.pathname.substr(1), | ||
}; | ||
if (url.auth) { | ||
var auth = url.auth.split(':'); | ||
options.user = auth[0]; | ||
options.password = auth[1]; | ||
} | ||
if (url.query) { | ||
for (var key in url.query) { | ||
var value = url.query[key]; | ||
try { | ||
// Try to parse this as a JSON expression first | ||
options[key] = JSON.parse(value); | ||
} catch (err) { | ||
// Otherwise assume it is a plain string | ||
options[key] = value; | ||
} | ||
} | ||
} | ||
return options; | ||
}; |
module.exports = ErrorPacket; | ||
function ErrorPacket() { | ||
this.fieldCount = undefined; | ||
this.errno = undefined; | ||
this.sqlStateMarker = undefined; | ||
this.sqlState = undefined; | ||
this.message = undefined; | ||
function ErrorPacket(options) { | ||
options = options || {}; | ||
this.fieldCount = options.fieldCount; | ||
this.errno = options.errno; | ||
this.sqlStateMarker = options.sqlStateMarker; | ||
this.sqlState = options.sqlState; | ||
this.message = options.message; | ||
} | ||
@@ -17,1 +19,9 @@ | ||
}; | ||
ErrorPacket.prototype.write = function(writer) { | ||
writer.writeUnsignedNumber(1, 0xff); | ||
writer.writeUnsignedNumber(2, this.errno); | ||
writer.writeString(this.sqlStateMarker || '#'); | ||
writer.writeString(this.sqlState || '12345'); | ||
writer.writeString(this.message); | ||
}; |
@@ -12,7 +12,7 @@ module.exports = ResultSetHeaderPacket; | ||
if (parser.reachedPacketEnd()) { | ||
return; | ||
} | ||
if (parser.reachedPacketEnd()) return; | ||
this.extra = parser.parseLengthCodedNumber(); | ||
this.extra = (this.fieldCount === null) | ||
? parser.parsePacketTerminatedString() | ||
: parser.parseLengthCodedNumber(); | ||
}; | ||
@@ -19,0 +19,0 @@ |
@@ -1,3 +0,3 @@ | ||
var Types = require('../constants/types'); | ||
var FieldFlags = require('../constants/field_flags'); | ||
var Types = require('../constants/types'); | ||
var Charsets = require('../constants/charsets'); | ||
@@ -54,3 +54,3 @@ module.exports = RowDataPacket; | ||
case Types.BLOB: | ||
return (field.flags & FieldFlags.BINARY_FLAG) | ||
return (field.charsetNr === Charsets.BINARY) | ||
? parser.parseLengthCodedBuffer() | ||
@@ -57,0 +57,0 @@ : parser.parseLengthCodedString(); |
@@ -10,3 +10,3 @@ var BIT_16 = Math.pow(2, 16); | ||
function PacketWriter() { | ||
this._buffer = null; | ||
this._buffer = new Buffer(0); | ||
this._offset = 0; | ||
@@ -13,0 +13,0 @@ } |
@@ -15,6 +15,14 @@ var Sequence = require('./Sequence'); | ||
Handshake.prototype.determinePacket = function() { | ||
Handshake.prototype.determinePacket = function(firstByte) { | ||
if (firstByte === 0xff) { | ||
return Packets.ErrorPacket; | ||
} | ||
if (!this._handshakeInitializationPacket) { | ||
return Packets.HandshakeInitializationPacket; | ||
} | ||
if (firstByte === 0xfe) { | ||
return Packets.UseOldPasswordPacket; | ||
} | ||
}; | ||
@@ -35,2 +43,21 @@ | ||
Handshake.prototype['UseOldPasswordPacket'] = function(packet) { | ||
if (!this._config.insecureAuth) { | ||
var err = new Error( | ||
'MySQL server is requesting the old and insecure pre-4.1 auth mechanism.' + | ||
'Upgrade the user password or use the {insecureAuth: true} option.' | ||
); | ||
err.code = 'HANDSHAKE_INSECURE_AUTH'; | ||
err.fatal = true; | ||
this.end(err); | ||
return; | ||
} | ||
this.emit('packet', new Packets.OldPasswordPacket({ | ||
scrambleBuff : Auth.scramble323(this._handshakeInitializationPacket.scrambleBuff(), this._config.password), | ||
})); | ||
}; | ||
Handshake.prototype['ErrorPacket'] = function(packet) { | ||
@@ -37,0 +64,0 @@ var err = this._packetToError(packet, true); |
@@ -6,2 +6,3 @@ var Sequence = require('./Sequence'); | ||
var ServerStatus = require('../constants/server_status'); | ||
var fs = require('fs'); | ||
@@ -17,3 +18,3 @@ module.exports = Query; | ||
: options.typeCast; | ||
this.nestTables = false; | ||
this.nestTables = options.nestTables || false; | ||
@@ -24,2 +25,3 @@ this._resultSet = null; | ||
this._index = 0; | ||
this._loadError = null; | ||
} | ||
@@ -32,3 +34,13 @@ | ||
Query.prototype.determinePacket = function(firstByte, parser) { | ||
if (firstByte === 0 || firstByte === 255) { | ||
if (firstByte === 0) { | ||
// If we have a resultSet and got one eofPacket | ||
if (this._resultSet && this._resultSet.eofPackets.length === 1) { | ||
// Then this is a RowDataPacket with an empty string in the first column. | ||
// See: https://github.com/felixge/node-mysql/issues/222 | ||
} else { | ||
return; | ||
} | ||
} | ||
if (firstByte === 255) { | ||
return; | ||
@@ -82,2 +94,7 @@ } | ||
this._resultSet = new ResultSet(packet); | ||
// used by LOAD DATA LOCAL INFILE queries | ||
if (packet.fieldCount === null) { | ||
this._sendLocalDataFile(packet.extra); | ||
} | ||
}; | ||
@@ -123,3 +140,3 @@ | ||
this.end(null, results, fields); | ||
this.end(this._loadError, results, fields); | ||
}; | ||
@@ -133,5 +150,17 @@ | ||
} else { | ||
// @TODO Multiple results | ||
this.emit('result', packet, this._index); | ||
} | ||
}; | ||
Query.prototype._sendLocalDataFile = function(path) { | ||
var self = this; | ||
fs.readFile(path, 'utf-8', function(err, data) { | ||
if (err) { | ||
self._loadError = err; | ||
} else { | ||
self.emit('packet', new Packets.LocalDataFilePacket(data)); | ||
} | ||
self.emit('packet', new Packets.EmptyPacket()); | ||
}); | ||
}; |
@@ -95,2 +95,6 @@ var SqlString = exports; | ||
var value = object[key]; | ||
if(typeof value === 'function') { | ||
continue; | ||
} | ||
values.push('`' + key + '` = ' + SqlString.escape(value, true)); | ||
@@ -97,0 +101,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-alpha2", | ||
"version": "2.0.0-alpha3", | ||
"repository": { | ||
@@ -8,0 +8,0 @@ "url": "" |
@@ -5,2 +5,20 @@ # node-mysql | ||
## Install | ||
```bash | ||
npm install mysql@2.0.0-alpha3 | ||
``` | ||
Despite the alpha tag, this is the recommended version for new applications. | ||
For information about the previous 0.9.x releases, visit the [v0.9 branch][]. | ||
Sometimes I may also ask you to install the latest version from Github to check | ||
if a bugfix is working. In this case, please do: | ||
``` | ||
npm install git://github.com/felixge/node-mysql.git | ||
``` | ||
[v0.9 branch]: https://github.com/felixge/node-mysql/tree/v0.9 | ||
## Introduction | ||
@@ -57,2 +75,4 @@ | ||
* [Transloadit](http://transloadit.com) (my startup, we do file uploading & | ||
video encoding as a service, check it out) | ||
* [Joyent](http://www.joyent.com/) | ||
@@ -84,11 +104,5 @@ * [pinkbike.com](http://pinkbike.com/) | ||
var connection = mysql.createConnection({ | ||
host : String, // defaults to 'localhost' | ||
port : Number, // defaults to 3306 | ||
socketPath : String, // defaults to undefined | ||
user : String, // defaults to undefined | ||
password : String, // defaults to undefined | ||
database : String, // defaults to undefined | ||
charset : String, // defaults to 'UTF8_GENERAL_CI' | ||
typeCast : Boolean, // defaults to true | ||
debug : Boolean, // defaults to false | ||
host : 'example.org', | ||
user : 'bob', | ||
password : 'secret', | ||
}); | ||
@@ -117,2 +131,33 @@ | ||
## Connection options | ||
When establishing a connection, you can set the following options: | ||
* `host`: The hostname of the database you are connecting to. (Default: | ||
`localhost`) | ||
* `port`: The port number to connect to. (Default: `3306`) | ||
* `socketPath`: The path to a unix domain socket to connect to. When used `host` | ||
and `port` are ignored. | ||
* `user`: The MySQL user to authenticate as. | ||
* `password`: The passqword of that MySQL user. | ||
* `database`: Name of the database to use for this connection (Optional). | ||
* `charset`: The charset for the connection. (Default: `'UTF8_GENERAL_CI'`) | ||
* `insecureAuth`: Allow connecting to MySQL instances that ask for the old | ||
(insecure) authentication method. (Default: `false`) | ||
* `typeCast`: Determines if column values should be converted to native | ||
JavaScript types. (Default: `true`) | ||
* `debug`: Prints protocol details to stdout. (Default: `false`) | ||
* `multipleStatements`: Allow multiple mysql statements per query. Be careful | ||
with this, it exposes you to SQL injection attacks. (Default: `false) | ||
In addition to passing these options as an object, you can also use a url | ||
string. For example: | ||
```js | ||
var connection = mysql.createConnection('mysql://user:pass@host/db?debug=true&charset=BIG5_CHINESE_CI'); | ||
``` | ||
Note: The query values are first attempted to be parsed as JSON, and if that | ||
fails assumed to be plaintext strings. | ||
## Terminating connections | ||
@@ -532,14 +577,2 @@ | ||
## FAQ | ||
I have yet to write this, but it will include: | ||
* What benefits does this driver have over compiled alternatives? (portability, | ||
license, docs) | ||
* How is the performance of this module compared to the alternatives? (great) | ||
* Is there commercial support for this driver? (nodefirm?) | ||
* What features are missing? (stored procedures, transactions, pause, etc.) | ||
* How can I contribute? (explain) | ||
* What are the goals of this project? | ||
## Todo | ||
@@ -546,0 +579,0 @@ |
@@ -6,3 +6,4 @@ var common = exports; | ||
common.lib = path.join(__dirname, '../lib'); | ||
common.lib = path.join(__dirname, '../lib'); | ||
common.fixtures = path.join(__dirname, 'fixtures'); | ||
@@ -9,0 +10,0 @@ // Useful for triggering ECONNREFUSED errors on connect() |
@@ -8,2 +8,3 @@ // An experimental fake MySQL server for tricky integration tests. Expanded | ||
var Parser = require('../lib/protocol/Parser'); | ||
var Auth = require('../lib/protocol/Auth'); | ||
var EventEmitter = require('events').EventEmitter; | ||
@@ -46,3 +47,6 @@ var Util = require('util'); | ||
this._clientAuthenticationPacket = false; | ||
this._handshakeInitializationPacket = null; | ||
this._clientAuthenticationPacket = null; | ||
this._oldPasswordPacket = null; | ||
this._handshakeOptions = {}; | ||
@@ -52,6 +56,17 @@ socket.on('data', this._handleData.bind(this)); | ||
FakeConnection.prototype.handshake = function() { | ||
this._sendPacket(new Packets.HandshakeInitializationPacket({ | ||
FakeConnection.prototype.handshake = function(options) { | ||
this._handshakeOptions = options || {}; | ||
this._handshakeInitializationPacket = new Packets.HandshakeInitializationPacket({ | ||
scrambleBuff1: new Buffer(8), | ||
scrambleBuff2: new Buffer(12), | ||
}); | ||
this._sendPacket(this._handshakeInitializationPacket); | ||
}; | ||
FakeConnection.prototype.deny = function(message, errno) { | ||
this._sendPacket(new Packets.ErrorPacket({ | ||
message: message, | ||
errno: errno, | ||
})); | ||
@@ -79,3 +94,30 @@ }; | ||
this._clientAuthenticationPacket = packet; | ||
this._sendPacket(new Packets.OkPacket()); | ||
if (this._handshakeOptions.oldPassword) { | ||
this._sendPacket(new Packets.UseOldPasswordPacket()); | ||
} else { | ||
if (this._handshakeOptions.user || this._handshakeOptions.password) { | ||
throw new Error('not implemented'); | ||
} | ||
this._sendPacket(new Packets.OkPacket()); | ||
this._parser.resetPacketNumber(); | ||
} | ||
break; | ||
case Packets.OldPasswordPacket: | ||
this._oldPasswordPacket = packet; | ||
var expected = Auth.scramble323(this._handshakeInitializationPacket.scrambleBuff(), this._handshakeOptions.password); | ||
var got = packet.scrambleBuff; | ||
var toString = function(buffer) { | ||
return Array.prototype.slice.call(buffer).join(','); | ||
}; | ||
if (toString(expected) === toString(got)) { | ||
this._sendPacket(new Packets.OkPacket()); | ||
} else { | ||
this._sendPacket(new Packets.ErrorPacket()); | ||
} | ||
this._parser.resetPacketNumber(); | ||
@@ -94,2 +136,4 @@ break; | ||
return Packets.ClientAuthenticationPacket; | ||
} else if (this._handshakeOptions.oldPassword && !this._oldPasswordPacket) { | ||
return Packets.OldPasswordPacket; | ||
} | ||
@@ -96,0 +140,0 @@ |
@@ -18,4 +18,9 @@ var common = require('../common'); | ||
var options = { | ||
nestTables: true, | ||
sql: 'SELECT * FROM ' + table, | ||
}; | ||
var rows; | ||
var query = connection.query('SELECT * FROM ' + table, function(err, _rows) { | ||
var query = connection.query(options, function(err, _rows) { | ||
if (err) throw err; | ||
@@ -26,4 +31,2 @@ | ||
query.nestTables = true; | ||
connection.end(); | ||
@@ -30,0 +33,0 @@ |
@@ -7,52 +7,50 @@ var common = require('../common'); | ||
var expected = { | ||
'DECIMAL' : '0.330', | ||
'TINYINT' : 1, | ||
'SMALLINT' : 2, | ||
'INT' : 3, | ||
'FLOAT' : 4.5, | ||
'DOUBLE' : 5.5, | ||
'BIGINT' : '6', | ||
'MEDIUMINT' : 7, | ||
'YEAR' : 2012, | ||
'TIMESTAMP' : new Date('2012-05-12 11:00:23'), | ||
'DATETIME' : new Date('2012-05-12 11:02:32'), | ||
'DATE' : new Date('2012-05-12'), | ||
'TIME' : '13:13:23', | ||
'BINARY' : new Buffer([0, 1, 254, 255]), | ||
'VARBINARY' : new Buffer([0, 1, 254, 255]), | ||
'TINYBLOB' : new Buffer([0, 1, 254, 255]), | ||
'MEDIUMBLOB' : new Buffer([0, 1, 254, 255]), | ||
'LONGBLOB' : new Buffer([0, 1, 254, 255]), | ||
'BLOB' : new Buffer([0, 1, 254, 255]), | ||
'BIT' : new Buffer([0, 1, 254, 255]), | ||
'CHAR' : 'Hello', | ||
'VARCHAR' : 'Hello', | ||
'TINYTEXT' : 'Hello World', | ||
'MEDIUMTEXT' : 'Hello World', | ||
'LONGTEXT' : 'Hello World', | ||
'TEXT' : 'Hello World', | ||
}; | ||
var tests = [ | ||
{type: 'decimal(3,3)', insert: '0.330'}, | ||
{type: 'decimal(3,3)', insert: 0.33, expect: '0.330'}, | ||
{type: 'tinyint', insert: 1}, | ||
{type: 'smallint', insert: 2}, | ||
{type: 'int', insert: 3}, | ||
{type: 'float', insert: 4.5}, | ||
{type: 'double', insert: 5.5}, | ||
{type: 'bigint', insert: '6'}, | ||
{type: 'bigint', insert: 6, expect: '6'}, | ||
{type: 'mediumint', insert: 7}, | ||
{type: 'year', insert: 2012}, | ||
{type: 'timestamp', insert: new Date('2012-05-12 11:00:23')}, | ||
{type: 'datetime', insert: new Date('2012-05-12 12:00:23')}, | ||
{type: 'date', insert: new Date('2012-05-12')}, | ||
{type: 'time', insert: '13:13:23'}, | ||
{type: 'binary(4)', insert: new Buffer([0, 1, 254, 255])}, | ||
{type: 'varbinary(4)', insert: new Buffer([0, 1, 254, 255])}, | ||
{type: 'tinyblob', insert: new Buffer([0, 1, 254, 255])}, | ||
{type: 'mediumblob', insert: new Buffer([0, 1, 254, 255])}, | ||
{type: 'longblob', insert: new Buffer([0, 1, 254, 255])}, | ||
{type: 'blob', insert: new Buffer([0, 1, 254, 255])}, | ||
{type: 'bit(32)', insert: new Buffer([0, 1, 254, 255])}, | ||
{type: 'char(5)', insert: 'Hello'}, | ||
{type: 'varchar(5)', insert: 'Hello'}, | ||
{type: 'varchar(3) character set utf8 collate utf8_bin', insert: 'bin'}, | ||
{type: 'tinytext', insert: 'Hello World'}, | ||
{type: 'mediumtext', insert: 'Hello World'}, | ||
{type: 'longtext', insert: 'Hello World'}, | ||
{type: 'text', insert: 'Hello World'}, | ||
]; | ||
var table = 'type_casting'; | ||
var schema = []; | ||
var inserts = []; | ||
for (var key in expected) { | ||
var value = expected[key]; | ||
var type = key; | ||
if (type === 'DECIMAL') { | ||
type = type + '(3,3)'; | ||
} else if (/binary|char/i.test(type)) { | ||
type = type + '(' + value.length + ')'; | ||
} else if (/bit/i.test(type)) { | ||
type = type + '(' + (value.length * 8) + ')'; | ||
} | ||
var escaped = connection.escape(value); | ||
tests.forEach(function(test, index) { | ||
var escaped = connection.escape(test.insert); | ||
schema.push('`' + key + '` ' + type + ','); | ||
inserts.push('`' + key + '` = ' + escaped); | ||
} | ||
test.columnName = test.type + '_' + index; | ||
connection.query([ | ||
'CREATE TEMPORARY TABLE `type_casting` (', | ||
schema.push('`' + test.columnName + '` ' + test.type + ','); | ||
inserts.push('`' + test.columnName + '` = ' + escaped); | ||
}); | ||
var createTable = [ | ||
'CREATE TEMPORARY TABLE `' + table + '` (', | ||
'`id` int(11) unsigned NOT NULL AUTO_INCREMENT,', | ||
@@ -62,6 +60,8 @@ ].concat(schema).concat([ | ||
') ENGINE=InnoDB DEFAULT CHARSET=utf8' | ||
]).join('\n')); | ||
]).join('\n'); | ||
connection.query('INSERT INTO type_casting SET' + inserts.join(',\n')); | ||
connection.query(createTable); | ||
connection.query('INSERT INTO ' + table + ' SET' + inserts.join(',\n')); | ||
var row; | ||
@@ -77,16 +77,22 @@ connection.query('SELECT * FROM type_casting', function(err, rows) { | ||
process.on('exit', function() { | ||
for (var key in expected) { | ||
var expectedValue = expected[key]; | ||
var actualValue = row[key]; | ||
tests.forEach(function(test) { | ||
var expected = test.expect || test.insert; | ||
var got = row[test.columnName]; | ||
if (expectedValue instanceof Date) { | ||
expectedValue = Number(expectedValue); | ||
actualValue = Number(actualValue); | ||
} else if (Buffer.isBuffer(expectedValue)) { | ||
expectedValue = Array.prototype.slice.call(expectedValue)+''; | ||
actualValue = Array.prototype.slice.call(actualValue)+''; | ||
if (expected instanceof Date) { | ||
assert.equal(got instanceof Date, true, test.type); | ||
expected = String(expected); | ||
got = String(got); | ||
} else if (Buffer.isBuffer(expected)) { | ||
assert.equal(Buffer.isBuffer(got), true, test.type); | ||
expected = String(Array.prototype.slice.call(expected)); | ||
got = String(Array.prototype.slice.call(got)); | ||
} | ||
assert.strictEqual(actualValue, expectedValue, key + ': ' + actualValue + ' !== ' + expectedValue); | ||
} | ||
var message = | ||
'got: "' + got + '" expected: "' + expected + '" test: ' + test.type + ''; | ||
assert.strictEqual(expected, got, message); | ||
}); | ||
}); |
@@ -28,2 +28,6 @@ var common = require('../../common'); | ||
'objects function properties are ignored': function() { | ||
assert.equal(SqlString.escape({a: 'b', c: function() {}}), "`a` = 'b'"); | ||
}, | ||
'nested objects are cast to strings': function() { | ||
@@ -30,0 +34,0 @@ assert.equal(SqlString.escape({a: {nested: true}}), "`a` = '[object Object]'"); |
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
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
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
168646
95
4060
580
17