mohair
Version:
sql query builder
489 lines (336 loc) • 7.77 kB
Markdown
# mohair
sql query builder for nodejs
*write elegant code to generate sql queries - instead of concatenating strings and pushing to endless parameter lists*
### Install
npm install mohair
### Use mohair with node-mysql
```coffeescript
mysql = require 'mysql'
connection = mysql.createConnection
user: 'mysql-username'
password: 'mysql-password'
database: 'mysql-database'
connection.connect()
m = require('mohair')()
m.insert 'project',
name: 'Amazing Project'
owner_id: 5
hidden: false
client.query m.sql(), m.params(), (err, result) ->
throw err if err?
console.log result
client.end()
```
### Queries
#### insert a single row
```coffeescript
m = require('mohair')()
m.insert 'project',
name: 'Amazing Project'
owner_id: 5
hidden: false
```
`m.sql()` returns:
```sql
INSERT INTO `project` (`name`, `owner_id`, `hidden`) VALUES (?, ?, ?);
```
`m.params()` returns:
```coffeescript
['Amazing Project', 5, false]
```
#### insert multiple rows at once
```coffeescript
{insert, sql, params} = require('mohair')()
insert 'project', [
{name: 'First project', hidden: true},
{name: 'Second project', hidden: false}
]
```
`sql()` returns:
```sql
INSERT INTO `project` (`name`, `hidden`) VALUES (?, ?), (?, ?);
```
`params()` returns:
```coffeescript
['First project', true, 'Second project', false]
```
**Note:** all inserted objects must have the same keys.
#### call some sql function inside the insert
```coffeescript
m = require('mohair')()
m.insert 'project',
name: 'Another Project'
created_on: -> m.raw 'NOW()'
user_id: -> m.raw 'LAST_INSERT_ID()'
```
`m.sql()` returns:
```sql
INSERT INTO `project` (`name,` `created_on`, `user_id`) VALUES (?, NOW(), LAST_INSERT_ID());
```
`m.params()` returns:
```coffeescript
['Another Project']
```
#### update on duplicate key
use the optional third parameter:
```coffeescript
m = require('mohair')()
m.insert 'project', {
id: 'foo'
name: 'bar'
}, {
name: 'bar'
update_count: -> m.raw 'update_count + 1'
}
```
`m.sql()` returns:
```sql
INSERT INTO `project` (`id`, `name`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `name` = ?, `update_count` = update_count + 1;
```
`m.params()` returns:
```coffeescript
['foo', 'bar', 'bar']
```
#### update a row
```coffeescript
m = require('mohair')()
m.update 'project', {
name: 'Even more amazing project'
hidden: true
}, {id: 7}
```
**Note:** the last argument is a query object. see section `Query language` below for details.
`m.sql()` returns:
```sql
UPDATE `project` SET `name` = ?, `hidden` = ? WHERE `id` = ?;
```
`m.params()` returns:
```coffeescript
['Even more amazing project', true, 7]
```
#### select everything
```coffeescript
m = require('mohair')()
m.select 'project'
```
`m.sql()` returns:
```sql
SELECT * FROM `project`;
```
`m.params()` returns:
```coffeescript
[]
```
#### select specific columns with a condition
```coffeescript
m = require('mohair')()
m.select 'project', ['name', 'id'], {hidden: true}
```
**Note:** the last argument is a query object. see section `Query language` below for details.
**Note:** the second argument can also be a string.
`m.sql()` returns:
```sql
SELECT name, id FROM `project` WHERE `hidden` = ?;
```
`m.params()` returns:
```coffeescript
[true]
```
#### join, groupBy and orderBy
```coffeescript
m = require('mohair')()
m.select 'project', ['count(task.id) AS taskCount', 'project.*'], ->
m.leftJoin 'task', 'project.id' , 'task.project_id'
m.where {'project.visible': true}
m.groupBy 'project.id'
m.orderBy 'project.created_on DESC'
m.limit 5
m.skip -> m.raw '6'
```
`m.sql()` returns:
```sql
SELECT
count(task.id) AS taskCount,
project.*
FROM `project`
LEFT JOIN `task` ON `project`.`id` = `task`.`project_id`
WHERE `project`.`visible` = ?
GROUP BY `project`.`id`
ORDER BY `project`.`created_on` DESC
LIMIT ?
SKIP 6;
```
`m.params()` returns:
```coffeescript
[true, 5]
```
**Note:** use `join`, `leftJoin`, `rightJoin`, and `innerJoin` as needed.
**Note:** `where` takes a query object. see section `Query language` below for details.
#### delete
```coffeescript
m = require('mohair')()
m.delete 'project', {id: 7, hidden: true}
```
`m.sql()` returns:
```sql
DELETE FROM `project` WHERE `id` = ? AND `hidden` = ?;
```
`m.params()` returns:
```coffeescript
[7, true]
```
**Note:** the last argument is a query object. see section `Query language` below for details.
#### transactions
```coffeescript
m = require('mohair')()
m.transaction ->
m.remove 'project', {id: 7}
m.update 'project', {name: 'New name'}, {id: 8}
```
`m.sql()` returns:
```sql
BEGIN;
DELETE FROM `project` WHERE `id` = ?;
UPDATE `project` SET `name` = ? WHERE `id` = ?;
COMMIT;
```
`m.params()` returns:
```coffeescript
[7, 'New name', 8]
```
#### fall back to raw sql with optional parameter bindings
```coffeescript
m = require('mohair')()
m.raw 'SELECT * FROM `project` WHERE `id` = ?;', 7
```
`m.sql()` returns:
```sql
SELECT * FROM `project` WHERE `id` = ?;
```
`m.params()` returns:
```coffeescript
[7]
```
### Query language
inspired by the [mongo query language](http://www.mongodb.org/display/DOCS/Advanced+Queries)
#### query objects
sql is generated from query objects by using the keys as column names,
binding or calling the values and interspersing 'AND':
```coffeescript
m = require('mohair')()
m.query
id: 7
hidden: true
name: -> m.quoted 'Another project'
```
`m.sql()` returns:
```sql
`id` = ? AND `hidden` = ? AND `name` = 'Another project'
```
`m.params()` returns:
```coffeescript
[7, true]
```
#### comparison operators
you can change the default comparison operator '=' as follows:
```coffeescript
m = require('mohair')()
m.query
id: 7
name: {$ne: -> quoted 'Another project'}
owner_id: {$lt: 10}
category_id: {$lte: 4}
deadline: {$gt: -> m.raw 'NOW()'}
cost: {$gte: 7000}
```
`m.sql()` returns:
```sql
`id` = ? AND
`name` != 'Another project' AND
`owner_id` < ? AND
`category_id` <= ? AND
`deadline` > NOW() AND
`cost` >= ?
```
`params()` returns:
```coffeescript
[7, 10, 4, 7000]
```
##### $in
select rows where column `id` has one of the values: `3, 5, 8, 9`:
```coffeescript
m = require('mohair')()
m.query
id: {$in: [3, 5, 8, 9]}
```
`m.sql()` returns:
```sql
`id` IN (?, ?, ?, ?)
```
`m.params()` returns:
```coffeescript
[3, 5, 8, 9]
```
##### $nin = not in
##### $not
the special key `$not` takes a query object and negates it:
```coffeescript
m = require('mohair')()
m.query
$not: {id: {$in: [3, 5, 8, 9]}}
```
`m.sql()` returns:
```sql
NOT (`id` IN (?, ?, ?, ?))
```
`m.params()` returns:
```coffeescript
[3, 5, 8, 9]
```
##### $or
the special key `$or` takes an array of query objects and generates a querystring
where only one of the queries must match:
```coffeescript
m = require('mohair')()
m.query
$or: [
{id: 7}
{name: -> quoted 'Another project'}
{owner_id: 10}
]
```
`m.sql()` returns:
```sql
`id` = ? OR `name` = 'Another project' OR `owner_id` = ?
```
`m.params()` returns:
```coffeescript
[7, 10]
```
##### $nor
shorthand for `{$not: {$or: ...}}`
##### $and
the special key `$and` takes an array of query objects and generates a querystring
where all of the queries must match.
`$and` and `$or` can be nested:
```coffeescript
m = require('mohair')()
m.query
id: 7
$or: [
{owner_id: 10}
$and: [
{cost: {$gt: 500}}
{cost: {$lt: 1000}}
]
]
```
`m.sql()` returns:
```sql
`id` = ? AND (`owner_id` = ? OR `cost` > ? AND `cost` < ?)
```
`m.params()` returns:
```coffeescript
[7, 10, 500, 1000]
```
### License: MIT