Skip to content

Add template string tags #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ cache:
- node_modules
before_install:
# Setup Node.js version-specific dependencies
- "test $TRAVIS_NODE_VERSION '>' '1.0' || export FILTER='SqlString'"
- "test $TRAVIS_NODE_VERSION != '3.3' || export FILTER='SqlString'"
- "test $TRAVIS_NODE_VERSION != '0.6' || npm rm --save-dev nyc"
- "test $TRAVIS_NODE_VERSION != '0.8' || npm rm --save-dev nyc"
- "test $(echo $TRAVIS_NODE_VERSION | cut -d'.' -f1) -ge 4 || npm rm --save-dev eslint eslint-plugin-markdown"
Expand Down
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,19 @@ var sql = SqlString.format('INSERT INTO posts SET ?', post);
console.log(sql); // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'
```

There are also tags to be used with template strings in `sqlstring/tags`:

```js
/*eslint-env es6*/
var SqlStringTags = require('sqlstring/tags');
var userId = 1;
var bar = {bar: 'b'};
var sql = SqlStringTags.escape `UPDATE users SET foo = ${'a'}, ${bar}, baz = ${'c'} WHERE id = ${userId}`;
console.log(sql); // UPDATE users SET foo = 'a', bar = 'b', baz = 'c' WHERE id = 1
var sql = SqlStringTags.escapeStringifyObjects `UPDATE users SET foo = ${'a'}, ${bar}, baz = ${'c'} WHERE id = ${userId}`;
console.log(sql); // UPDATE users SET foo = 'a', '[object Object]', baz = 'c' WHERE id = 1
```

If you feel the need to escape queries by yourself, you can also use the escaping
function directly:

Expand Down Expand Up @@ -135,6 +148,18 @@ console.log(sql); // SELECT `username`, `email` FROM `users` WHERE id = 1
```
**Please note that this last character sequence is experimental and syntax might change**

There are also tags to be used with template strings in `sqlstring/tags`:

```js
/*eslint-env es6*/
var SqlStringTags = require('sqlstring/tags');
var columns = ['users.username', 'email'];
var sql = SqlStringTags.escapeId `SELECT ${columns} FROM ${'users'}`;
console.log(sql); // SELECT `users`.`username`, `email` FROM `users`
sql = SqlStringTags.escapeIdForbidQualified `SELECT ${columns} FROM ${'users'}`;
console.log(sql); // SELECT `users.username`, `email` FROM `users`
```

When you pass an Object to `.escape()` or `.format()`, `.escapeId()` is used to avoid SQL injection in object keys.

### Formatting queries
Expand All @@ -155,6 +180,22 @@ You also have the option (but are not required) to pass in `stringifyObject` and
allowing you provide a custom means of turning objects into strings, as well as a
location-specific/timezone-aware `Date`.

There are also tags to be used with template strings in `sqlstring/tags`:

```js
/*eslint-env es6*/
var SqlStringTags = require('sqlstring/tags');
var userId = 1;
var columns = ['users.username', 'email'];
var values = [userId, {givenname: 'example'}];
var sql = (SqlStringTags.generateFormatFunction `SELECT ${columns} FROM ${'users'} WHERE ${'id'} = ? AND ?`)(values);
console.log(sql); // SELECT `users`.`username`, `email` FROM `users` WHERE id = 1 AND givenname = 'example'
var sql = (SqlStringTags.generateFormatFunction(true) `SELECT ${columns} FROM ${'users'} WHERE ${'id'} = ? AND ?`)(values);
console.log(sql); // SELECT `users.username`, `email` FROM `users` WHERE id = 1 AND givenname = 'example'
var sql = (SqlStringTags.generateFormatFunction `SELECT ${columns} FROM ${'users'} WHERE ${'id'} = ? AND ?`)(values, true);
console.log(sql); // SELECT `users`.`username`, `email` FROM `users` WHERE id = 1 AND '[object Object]'
```

## License

[MIT](LICENSE)
Expand Down
70 changes: 70 additions & 0 deletions lib/tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
var SqlString = require('./SqlString');

module.exports.escapeId = function escapeId(strings) {
var values = [].slice.call(arguments).slice(1);

return values.map(function(value, i) {
return strings[i] + SqlString.escapeId(value);
}).join('') + strings[strings.length - 1];
};

module.exports.escapeIdForbidQualified = function escapeIdForbidQualified(strings) {
var values = [].slice.call(arguments).slice(1);

return values.map(function(value, i) {
return strings[i] + SqlString.escapeId(value, true);
}).join('') + strings[strings.length - 1];
};

module.exports.escapeWithOptions = function escapeWithOptions(stringifyObjects, timeZone) {
return function(strings) {
var values = [].slice.call(arguments).slice(1);

return values.map(function(value, i) {
return strings[i] + SqlString.escape(value, stringifyObjects, timeZone);
}).join('') + strings[strings.length - 1];
};
};
module.exports.escape = module.exports.escapeWithOptions();
module.exports.escapeStringifyObjects = module.exports.escapeWithOptions(true);

module.exports.generateFormatFunctionWithOptions = function generateFormatFunctionWithOptions(forbidQualified) {
return function generateFormatFunction(strings) {
var values = [].slice.call(arguments).slice(1);

var parts = values.map(function(value, i) {
var stringParts = strings[i].split('?');
stringParts[stringParts.length - 1] += SqlString.escapeId(value, forbidQualified);
return stringParts;
});
parts.push(strings[strings.length - 1].split('?'));

var prepared = parts.reduce(function(result, part) {
result[result.length - 1] += part.shift();
result.push.apply(result, part);
return result;
}, parts.shift());
var lastPrepared = prepared.pop();

return function(values, stringifyObjects, timeZone) {
if (!values) {
values = [];
}

if (!Array.isArray(values)) {
values = [values];
}

return prepared.map(function(string, i) {
var value = '?';
if (i < values.length) {
value = SqlString.escape(values[i], stringifyObjects, timeZone);
}

return string + value;
}).join('') + lastPrepared;
};
};
};
module.exports.generateFormatFunction = module.exports.generateFormatFunctionWithOptions();
module.exports.generateFormatFunctionForbidQualified = module.exports.generateFormatFunctionWithOptions(true);
1 change: 1 addition & 0 deletions tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./lib/tags');
Loading