Comparing version 0.1.0 to 0.1.5
@@ -16,4 +16,4 @@ var lookup = require('dns').lookup, | ||
pName = props[p]; | ||
Object.defineProperty(n, pName, Object.getOwnPropertyDescriptor(o, pName)); | ||
}; | ||
Object.defineProperty(n, pName, Object.getOwnPropertyDescriptor(o, pName)); | ||
} | ||
return n; | ||
@@ -25,4 +25,13 @@ } | ||
// for prepare() | ||
var RE_PARAM = /(?:\?)|(?::(\d+|(?:[a-zA-Z][a-zA-Z0-9_]*)))/g, | ||
DQUOTE = 34, | ||
SQUOTE = 39, | ||
BSLASH = 92, | ||
MAX_CACHE_SIZE = 30; | ||
function Client() { | ||
var self = this; | ||
this.queryCache = []; | ||
this.queryCache.keys = {}; | ||
this.threadId = undefined; | ||
@@ -49,2 +58,6 @@ this.connected = false; | ||
}); | ||
// doing everything in utf8 greatly simplifies things -- | ||
// end users can use iconv/iconv-lite if they need to convert to something | ||
// else | ||
self.query("SET NAMES 'utf8'", true, true); | ||
}); | ||
@@ -114,9 +127,2 @@ this._client.on('conn.error', function(err) { | ||
Client.prototype._reset = function() { | ||
this._closeOnEmpty = false; | ||
// TODO: do not empty queries if using an auto-reconnect algorithm | ||
this._queries = []; | ||
this._curResults = undefined; | ||
}; | ||
Client.prototype.isMariaDB = function() { | ||
@@ -154,4 +160,13 @@ return this._client.isMariaDB(); | ||
Client.prototype.query = function(query, useArray, promote) { | ||
var results = new Results(this, query, useArray); | ||
Client.prototype.query = function(query, values, useArray, promote) { | ||
var results; | ||
if (Array.isArray(values) || typeof values === 'object') | ||
query = this.prepare(query)(values); | ||
else { | ||
promote = useArray; | ||
useArray = values; | ||
} | ||
results = new Results(this, query, useArray); | ||
if (promote) | ||
@@ -169,2 +184,77 @@ this._queries.unshift(results); | ||
Client.prototype.prepare = function(query) { | ||
if (this.queryCache.keys[query] !== undefined) | ||
return this.queryCache[this.queryCache.keys[query]]; | ||
var ppos = RE_PARAM.exec(query), curpos = 0, start = 0, end, parts = [], | ||
i, chr, inQuote = false, escape = false, qchr, tokens = [], qcnt = 0, | ||
fn, self = this; | ||
if (ppos) { | ||
do { | ||
for (i=curpos,end=ppos.index; i<end; ++i) { | ||
chr = query.charCodeAt(i); | ||
if (chr === BSLASH) | ||
escape = !escape; | ||
else { | ||
if (escape) { | ||
escape = false; | ||
continue; | ||
} | ||
if (inQuote && chr === qchr) { | ||
if (query.charCodeAt(i + 1) === qchr) { | ||
// quote escaped via "" or '' | ||
++i; | ||
continue; | ||
} | ||
inQuote = false; | ||
} else if (chr === DQUOTE || chr === SQUOTE) { | ||
inQuote = true; | ||
qchr = chr; | ||
} | ||
} | ||
} | ||
if (!inQuote) { | ||
parts.push(query.substring(start, end)); | ||
tokens.push(ppos[0].length === 1 ? qcnt++ : ppos[1]); | ||
start = end + ppos[0].length; | ||
} | ||
curpos = end + ppos[0].length; | ||
} while (ppos = RE_PARAM.exec(query)); | ||
if (tokens.length) { | ||
if (curpos < query.length) | ||
parts.push(query.substring(curpos)); | ||
fn = function(values) { | ||
var ret = '', j, len, str; | ||
for (j=0,len=tokens.length; j<len; ++j) { | ||
if (Buffer.isBuffer(values[tokens[j]])) | ||
str = values[tokens[j]].toString('utf8'); | ||
else | ||
str = values[tokens[j]] + ''; | ||
ret += parts[j]; | ||
ret += "'"; | ||
ret += addon.escape(str); | ||
ret += "'"; | ||
} | ||
if (j < parts.length) | ||
ret += parts[j]; | ||
return ret; | ||
}; | ||
if (this.queryCache.length === MAX_CACHE_SIZE) | ||
delete this.queryCache.keys[this.queryCache.shift().orig]; | ||
fn.orig = query; | ||
this.queryCache.keys[query] = this.queryCache.push(fn) - 1; | ||
return fn; | ||
} | ||
} | ||
return function() { return query; }; | ||
} | ||
Client.prototype._reset = function() { | ||
this._closeOnEmpty = false; | ||
// TODO: do not empty queries if using an auto-reconnect algorithm | ||
this._queries = []; | ||
this._curResults = undefined; | ||
}; | ||
Client.prototype._processQueries = function() { | ||
@@ -180,4 +270,2 @@ if (this._curResults === undefined && this.connected) { | ||
Client.LIB_VERSION = addon.version(); | ||
function Query(parent) { | ||
@@ -215,3 +303,2 @@ this._removed = false; | ||
// remove from the queue if the query hasn't started executing yet | ||
var self = this; | ||
this.client._queries.splice(i, 1); | ||
@@ -223,4 +310,4 @@ } | ||
Client.Query = Query; | ||
Client.Results = Results; | ||
Client.LIB_VERSION = addon.version(); | ||
Client.escape = addon.escape; | ||
module.exports = Client; |
{ "name": "mariasql", | ||
"version": "0.1.0", | ||
"version": "0.1.5", | ||
"author": "Brian White <mscdex@mscdex.net>", | ||
@@ -4,0 +4,0 @@ "description": "A node.js binding to MariaDB's non-blocking (MySQL-compatible) client library", |
122
README.md
@@ -68,3 +68,3 @@ | ||
.on('end', function() { | ||
console.log('Done with all queries'); | ||
console.log('Done with all queries'); | ||
}); | ||
@@ -75,2 +75,108 @@ | ||
* Use placeholders in a query | ||
```javascript | ||
var inspect = require('util').inspect; | ||
var Client = require('mariasql'); | ||
var c = new Client(); | ||
c.connect({ | ||
host: '127.0.0.1', | ||
user: 'foo', | ||
password: 'bar', | ||
db: 'mydb' | ||
}); | ||
c.on('connect', function() { | ||
console.log('Client connected'); | ||
}) | ||
.on('error', function(err) { | ||
console.log('Client error: ' + err); | ||
}) | ||
.on('close', function(hadError) { | ||
console.log('Client closed'); | ||
}); | ||
c.query('SELECT * FROM users WHERE id = :id AND name = :name', | ||
{ id: 1337, name: 'Frylock' }) | ||
.on('result', function(res) { | ||
res.on('row', function(row) { | ||
console.log('Query row: ' + inspect(row)); | ||
}) | ||
.on('error', function(err) { | ||
console.log('Query error: ' + inspect(err)); | ||
}) | ||
.on('end', function(info) { | ||
console.log('Query finished successfully'); | ||
}); | ||
}) | ||
.on('end', function() { | ||
console.log('Done with all queries'); | ||
}); | ||
c.query('SELECT * FROM users WHERE id = ? AND name = ?', | ||
[ 1337, 'Frylock' ]) | ||
.on('result', function(res) { | ||
res.on('row', function(row) { | ||
console.log('Query row: ' + inspect(row)); | ||
}) | ||
.on('error', function(err) { | ||
console.log('Query error: ' + inspect(err)); | ||
}) | ||
.on('end', function(info) { | ||
console.log('Query finished successfully'); | ||
}); | ||
}) | ||
.on('end', function() { | ||
console.log('Done with all queries'); | ||
}); | ||
c.end(); | ||
``` | ||
* Explicitly generate a prepared query for later use | ||
```javascript | ||
var inspect = require('util').inspect; | ||
var Client = require('mariasql'); | ||
var c = new Client(); | ||
c.connect({ | ||
host: '127.0.0.1', | ||
user: 'foo', | ||
password: 'bar', | ||
db: 'mydb' | ||
}); | ||
c.on('connect', function() { | ||
console.log('Client connected'); | ||
}) | ||
.on('error', function(err) { | ||
console.log('Client error: ' + err); | ||
}) | ||
.on('close', function(hadError) { | ||
console.log('Client closed'); | ||
}); | ||
var pq = c.prepare('SELECT * FROM users WHERE id = :id AND name = :name'); | ||
c.query(pq({ id: 1337, name: 'Frylock' })) | ||
.on('result', function(res) { | ||
res.on('row', function(row) { | ||
console.log('Query row: ' + inspect(row)); | ||
}) | ||
.on('error', function(err) { | ||
console.log('Query error: ' + inspect(err)); | ||
}) | ||
.on('end', function(info) { | ||
console.log('Query finished successfully'); | ||
}); | ||
}) | ||
.on('end', function() { | ||
console.log('Done with all queries'); | ||
}); | ||
c.end(); | ||
``` | ||
* Abort the second query when doing multiple statements | ||
@@ -118,3 +224,3 @@ | ||
.on('end', function() { | ||
console.log('Done with all queries'); | ||
console.log('Done with all queries'); | ||
}); | ||
@@ -199,4 +305,6 @@ | ||
* **query**(<_string_>query[, <_boolean_>useArray=false]) - <_Results_> - Enqueues the given `query` and returns a _Results_ object. If `useArray` is set to true, then an array of field values are returned instead of an object of fieldName=>fieldValue pairs. (Note: using arrays performs much faster) | ||
* **query**(<_string_>query[, <_mixed_>values[, <_boolean_>useArray=false]]) - <_Results_> - Enqueues the given `query` and returns a _Results_ object. `values` can be an object or array containing values to be used when replacing placeholders in `query` (see prepare()). If `useArray` is set to true, then an array of field values are returned instead of an object of fieldName=>fieldValue pairs. (Note: using arrays performs much faster) | ||
* **prepare**(<_string_>query) - <_function_> - Generates a re-usable function for `query` when it contains placeholders (can be simple `?` position-based or named `:foo_bar1` placeholders or any combination of the two). In the case that the function does contain placeholders, the generated function is cached per-connection if it is not already in the cache (currently the cache will hold at most **30** prepared queries). The returned function takes an object or array and returns the query with the placeholders replaced by the values in the object or array. **Note:** Every value is converted to a (utf8) string when filling the placeholders. | ||
* **escape**(<_string_>value) - <_string_> - Escapes `value` for use in queries. **_This method requires a live connection_**. | ||
@@ -211,2 +319,8 @@ | ||
Client static methods | ||
--------------------- | ||
* **escape**(<_string_>value) - <_string_> - Escapes `value` for use in queries. **_This method does not take into account character encodings_**. | ||
Results events | ||
@@ -253,4 +367,2 @@ -------------- | ||
* Method to change character set | ||
* Periodic ping to keep connection alive | ||
@@ -257,0 +369,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
19395495
282
367