@ddn/json-sql
Version:
node.js json to sql queries mapper
1,180 lines (851 loc) • 20.8 kB
Markdown
# Documentation
## Table of contents
* [API](#api)
- [Initialization](#initialization)
- __[build(query)](#buildquery)__
- [configure(options)](#configureoptions)
- [setDialect(name)](#setdialectname)
* __[Queries](#queries)__
- [type: 'create'](#type-create)
- [type: 'select'](#type-select)
- [type: 'insert'](#type-insert)
- [type: 'update'](#type-update)
- [type: 'remove'](#type-remove)
- [type: 'union' | 'intersect' | 'except'](#type-union--intersect--except)
* __[Blocks](#blocks)__
* __[Condition operators](#condition-operators)__
## API
### Initialization
To create new instance of json-sql builder you can use factory function:
``` js
var jsonSql = require('json-sql')(options);
```
or create instance by class constructor:
``` js
var jsonSql = new (require('json-sql').Builder)(options);
```
`options` are similar to [configure method options](#available-options).
### build(query)
Create sql query from mongo-style query object.
`query` is a json object that has required property `type` and a set of query-specific properties. `type` property determines the type of query. List of available values of `type` property you can see at [Queries section](#queries).
Returns object with properties:
| Property | Description |
| -------- | ----------- |
| `query` | SQL query string |
| `value` | Array or object with values.<br>Exists only if `separatedValues = true`. |
| `prefixValues()` | Method to get values with `valuesPrefix`.<br>Exists only if `separatedValues = true`. |
| `getValuesArray()` | Method to get values as array.<br>Exists only if `separatedValues = true`. |
| `getValuesObject()` | Method to get values as object.<br>Exists only if `separatedValues = true`. |
### configure(options)
Set options of json-sql builder instance.
#### Available options
| Option name | Default value | Description |
| ----------- | ------------- | ----------- |
| `separatedValues` | `true` | If `true` - create placeholder for each string value and put it value to result `values`.<br>If `false` - put string values into sql query without placeholder (potential threat of sql injection). |
| `namedValues` | `true` | If `true` - create hash of values with placeholders p1, p2, ...<br>If `false` - put all values into array.<br>Option is used if `separatedValues = true`. |
| `valuesPrefix` | `'$'` | Prefix for values placeholders<br>Option is used if `namedValues = true`. |
| `dialect` | `'base'` | Active dialect. See setDialect for dialects list. |
| `wrappedIdentifiers` | `true` | If `true` - wrap all identifiers with dialect wrapper (name -> "name"). |
### setDialect(name)
Set active dialect, name can has value `'base'`, `'mssql'`, `'mysql'`, `'postrgresql'` or `'sqlite'`.
## Queries
### type: 'create'
>[ [tableFields](#tableFields) ]<br>
>[ [table](#table) ]<br>
>[ [foreignKeys](#foreignKeys) ]
__Example:__
``` js
var sql = jsonSql.build({
type: 'create',
table: 'users',
tableFields: [
{
name: "name",
type: "String",
length: 16,
not_null: true,
unique: true,
default: "empty"
}
]
});
sql.query
// create table if not exists "users"("name" varchar(16) NOT NULL default "empty" UNIQUE);
```
### type: 'select'
>[ [with](#with-withrecursive) | [withRecursive](#with-withrecursive) ]<br>
>[ [distinct](#distinct) ]<br>
>[ [fields](#fields) ]<br>
>[table](#table) | [query](#query) | [select](#select) | [expression](#expression)<br>
>[ [alias](#alias) ]<br>
>[ [join](#join) ]<br>
>[ [condition](#condition) ]<br>
>[ [group](#group) ]<br>
>[ [sort](#sort) ]<br>
>[ [limit](#limit) ]<br>
>[ [offset](#offset) ]
__Example:__
``` js
var sql = jsonSql.build({
type: 'select',
fields: ['a', 'b']
table: 'table'
});
sql.query
// select "a", "b" from "table";
```
If `fields` is not specified in query, result fields is `*` (all columns of the selected rows).
__Example:__
``` js
var sql = jsonSql.build({
type: 'select',
table: 'table'
});
sql.query
// select * from "table";
```
### type: 'insert'
>[ [with](#with-withrecursive) | [withRecursive](#with-withrecursive) ]<br>
>[ [or](#or) ]<br>
>[table](#table)<br>
>[values](#values)<br>
>[ [condition](#condition) ]<br>
>[ [returning](#returning) ]
__Example:__
``` js
var sql = jsonSql.build({
type: 'insert',
table: 'table',
values: {a: 4}
});
sql.query
// insert into "table" ("a") values (4);
```
### type: 'update'
>[ [with](#with-withrecursive) | [withRecursive](#with-withrecursive) ]<br>
>[ [or](#or) ]<br>
>[table](#table)<br>
>[modifier](#modifier)<br>
>[ [condition](#condition) ]<br>
>[ [returning](#returning) ]
__Example:__
``` js
var sql = jsonSql.build({
type: 'update',
table: 'table',
modifier: {a: 5}
});
sql.query
// update "table" set a = 5;
```
### type: 'remove'
>[ [with](#with-withrecursive) | [withRecursive](#with-withrecursive) ]<br>
>[table](#table)<br>
>[ [condition](#condition) ]<br>
>[ [returning](#returning) ]
__Example:__
``` js
var sql = jsonSql.build({
type: 'remove',
table: 'table'
});
sql.query
// delete from "table";
```
### type: 'union' | 'intersect' | 'except'
>[ [all](#all) ]<br>
>[ [with](#with-withrecursive) | [withRecursive](#with-withrecursive) ]<br>
>[queries](#queries)<br>
>[ [sort](#sort) ]<br>
>[ [limit](#limit) ]<br>
>[ [offset](#offset) ]
__`type: 'union'` example:__
``` js
var sql = jsonSql.build({
type: 'union',
queries: [
{type: 'select', table: 'table1'},
{type: 'select', table: 'table2'}
]
});
sql.query
// (select * from "table1") union (select * from "table2");
```
__`type: 'intersect'` example:__
``` js
var sql = jsonSql.build({
type: 'intersect',
queries: [
{type: 'select', table: 'table1'},
{type: 'select', table: 'table2'}
]
});
sql.query
// (select * from "table1") intersect (select * from "table2");
```
__`type: 'except'` example:__
``` js
var sql = jsonSql.build({
type: 'except',
queries: [
{type: 'select', table: 'table1'},
{type: 'select', table: 'table2'}
]
});
sql.query
// (select * from "table1") except (select * from "table2");
```
## Blocks
Blocks are small chunks of query.
### with, withRecursive
Should be an `array` or an `object`.
If value is an `array`, each item of array should be an `object` and should conform the scheme:
>name<br>
>[ [fields](#fields) ]<br>
>[query](#query) | [select](#select) | [expression](#expression)
__Example:__
``` js
var sql = jsonSql.build({
'with': [{
name: 'table',
select: {table: 'withTable'}
}],
table: 'table'
});
sql.query
// with "table" as (select * from "withTable") select * from "table";
```
If value is an `object`, keys of object interpret as names and each value should be an `object` and should conform the scheme:
>[ name ]<br>
>[ [fields](#fields) ]<br>
>[query](#query) | [select](#select) | [expression](#expression)
__Example:__
``` js
var sql = jsonSql.build({
'with': {
table: {
select: {table: 'withTable'}
}
},
table: 'table'
});
sql.query
// with "table" as (select * from "withTable") select * from "table";
```
### distinct
Should be a `boolean`:
```
distinct: true
```
__Example:__
``` js
var sql = jsonSql.build({
distinct: true,
table: 'table'
});
sql.query
// select distinct * from "table";
```
### tableFields
Should be an `array`
Contains array of table`s fields
### foreignKeys
Should be an `array`
__Example:__
``` js
var result = jsonSql.build({
type: 'create',
table: 'users',
tableFields: [
{
name: "name",
type: "String",
length: 16,
not_null: true,
primary_key: true
},
{
name: "age",
type: "Number",
not_null: true
}
],
foreignKeys: [
{
field: "name",
table: "person",
table_field: "id"
}
]
});
sql.query
// create table "users"(name varchar(16) NOT NULL PRIMARY KEY,age int NOT NULL, FOREIGN KEY (name) REFERENCES person(id));
```
### fields
Should be an `array` or an `object`.
If value is an `array`, each item interprets as [term block](#term).
__Example:__
``` js
var sql = jsonSql.build({
fields: [
'a',
{b: 'c'},
{table: 'd', name: 'e', alias: 'f'},
['g']
],
table: 'table'
});
sql.query
// select "a", "b" as "c", "d"."e" as "f", "g" from "table";
```
If value is an `object`, keys of object interpret as field names and each value should be an `object` and should conform the scheme:
>[ name ]<br>
>[ [table](#table) ]<br>
>[ cast ]<br>
>[ [alias](#alias) ]
__Example:__
``` js
var sql = jsonSql.build({
fields: {
a: 'b',
d: {table: 'c', alias: 'e'}
},
table: 'table'
});
sql.query
// select "a" as "b", "c"."d" as "e" from "table";
```
### term
Should be:
* a `string` - interprets as field name;
* another simple type or an `array` - interprets as value;
* an `object` - should conform the scheme:
>[query](#query) | [select](#select) | [field](#field) | [value](#value) | [func](#func) | [expression](#expression)<br>
>[ cast ]<br>
>[ [alias](#alias) ]
### field
Should be a `string` or an `object`.
If value is a `string`:
```
field: 'fieldName'
```
__Example:__
``` js
var sql = jsonSql.build({
fields: [{field: 'a'}],
table: 'table'
});
sql.query
// select "a" from "table";
```
If value is an `object` it should conform the scheme:
>name<br>
>[ [table](#table) ]
__Example:__
``` js
var sql = jsonSql.build({
fields: [{field: {name: 'a', table: 'table'}}],
table: 'table'
});
sql.query
// select "table"."a" from "table";
```
### value
Can have any type.
__Example:__
``` js
var sql = jsonSql.build({
fields: [
{value: 5},
{value: 'test'}
],
table: 'table'
});
sql.query
// select 5, $p1 from "table";
sql.values
// {p1: 'test'}
```
### table
Should be a `string`:
```
table: 'tableName'
```
__Example:__
``` js
var sql = jsonSql.build({
table: 'table'
});
sql.query
// select * from "table";
```
### query
Should be an `object`. Value interprets as sub-query and process recursively with [build(query)](#buildquery) method.
__Example:__
``` js
var sql = jsonSql.build({
query: {type: 'select', table: 'table'}
});
sql.query
// select * from (select * from "table");
```
### select
Should be an `object`. Value interprets as sub-select and process recursively with [build(query)](#buildquery) method.
__Example:__
``` js
var sql = jsonSql.build({
select: {table: 'table'}
});
sql.query
// select * from (select * from "table");
```
### func
Should be a `string` or an `object`.
If value is a `string`:
```
func: 'random'
```
__Example:__
``` js
var sql = jsonSql.build({
fields: [{func: 'random'}],
table: 'table'
});
sql.query
// select random() from "table";
```
If value is an `object` it should conform the scheme:
>name<br>
>[ args ]
where `name` is a `string` name of function, `args` is an `array` that contains it arguments.
__Example:__
``` js
var sql = jsonSql.build({
fields: [{
func: {
name: 'sum',
args: [{field: 'a'}]
}
}],
table: 'table'
});
sql.query
// select sum("a") from table;
```
### expression
Should be a `string` or an `object`.
If value is a `string`:
```
expression: 'random()'
```
__Example:__
``` js
var sql = jsonSql.build({
expression: 'generate_series(2, 4)'
});
sql.query
// select * from generate_series(2, 4);
```
If value is an `object` it should conform the scheme:
>pattern<br>
>[ values ]
where `pattern` is a `string` pattern with placeholders `{placeholderName}`, `values` is a hash that contains values for each `placeholderName`.
__Example:__
``` js
var sql = jsonSql.build({
expression: {
pattern: 'generate_series({start}, {stop})',
values: {start: 2, stop: 4}
}
});
sql.query
// select * from generate_series(2, 4);
```
### alias
Should be a `string` or an `object`.
If value is a `string`:
```
alias: 'aliasName'
```
__Example:__
``` js
var sql = jsonSql.build({
table: 'table',
alias: 'alias'
});
sql.query
// select * from "table" as "alias";
```
If value is an `object` it should conform the scheme:
>name<br>
>[ columns ]
__Example:__
``` js
var sql = jsonSql.build({
table: 'table',
alias: {name: 'alias'}
});
sql.query
// select * from "table" as "alias";
```
### join
Should be an `array` or an `object`.
If value is an `array`, each item of array should be an `object` and should conform the scheme:
>[ type ]<br>
>[table](#table) | [query](#query) | [select](#select) | [expression](#expression)<br>
>[ [alias](#alias) ]<br>
>[ on ]
__Example:__
``` js
var sql = jsonSql.build({
table: 'table',
join: [{
type: 'right',
table: 'joinTable',
on: {'table.a': 'joinTable.b'}
}]
});
sql.query
// select * from "table" right join "joinTable" on "table"."a" = "joinTable"."b";
```
If value is an `object`, keys of object interpret as table names and each value should be an `object` and should conform the scheme:
>[ type ]<br>
>[ [table](#table) | [query](#query) | [select](#select) | [expression](#expression) ]<br>
>[ [alias](#alias) ]<br>
>[ on ]
__Example:__
``` js
var sql = jsonSql.build({
table: 'table',
join: {
joinTable: {
type: 'inner',
on: {'table.a': 'joinTable.b'}
}
}]
});
sql.query
// select * from "table" inner join "joinTable" on "table"."a" = "joinTable"."b";
```
__Join with sub-select example:__
``` js
var sql = jsonSql.build({
table: 'table',
join: [{
select: {table: 'joinTable'},
alias: 'joinTable',
on: {'table.a': 'joinTable.b'}
}]
});
sql.query
// select * from "table" join (select * from "joinTable") as "joinTable" on "table"."a" = "joinTable"."b";
```
### condition
Should be an `array` or an `object`.
__`array` example:__
``` js
var sql = jsonSql.build({
table: 'table',
condition: [
{a: {$gt: 1}},
{b: {$lt: 10}}
]
});
sql.query
// select * from "table" where "a" > 1 and "b" < 10;
```
__`object` example:__
``` js
var sql = jsonSql.build({
table: 'table',
condition: {
a: {$gt: 1},
b: {$lt: 10}
}
});
sql.query
// select * from "table" where "a" > 1 and "b" < 10;
```
### group
Should be a `string` or an `array`.
If value is a `string`:
```
group: 'fieldName'
```
__Example:__
``` js
var sql = jsonSql.build({
table: 'table',
group: 'a'
});
sql.query
// select * from "table" group by "a";
```
If value is an `array`:
```
group: ['fieldName1', 'fieldName2']
```
__Example:__
``` js
var sql = jsonSql.build({
table: 'table',
group: ['a', 'b']
});
sql.query
// select * from "table" group by "a", "b";
```
### sort
Should be a `string`, an `array` or an `object`.
If value is a `string`:
```
sort: 'fieldName'
```
__Example:__
``` js
var sql = jsonSql.build({
table: 'table',
sort: 'a'
});
sql.query
// select * from "table" order by "a";
```
If value is an `array`:
```
sort: ['fieldName1', 'fieldName2']
```
__Example:__
``` js
var sql = jsonSql.build({
table: 'table',
sort: ['a', 'b']
});
sql.query
// select * from "table" order by "a", "b";
```
If value is an `object`:
```
sort: {
fieldName1: 1,
fieldName2: -1
}
```
__Example__:
``` js
var sql = jsonSql.build({
table: 'table',
sort: {a: 1, b: -1}
});
sql.query
// select * from "table" order by "a" asc, "b" desc;
```
### limit
Should be a `number`.
```
limit: limitValue
```
__Example:__
``` js
var sql = jsonSql.build({
table: 'table',
limit: 5
});
sql.query
// select * from "table" limit 5;
```
### offset
Should be a `number`.
```
offset: offsetValue
```
__Example:__
``` js
var sql = jsonSql.build({
table: 'table',
offset: 5
});
sql.query
// select * from "table" offset 5;
```
### or
Should be a `string`.
Available values: 'rollback', 'abort', 'replace', 'fail', 'ignore'.
```
or: 'orValue'
```
__Example:__
``` js
var sql = jsonSql.build({
type: 'insert',
or: 'replace',
table: 'table',
values: {a: 5}
});
sql.query
// insert or replace into "table" ("a") values (5);
```
### values
Should be an `array` or an `object`.
If value is an `array`, each item should be an `object` and interprets as single inserted row where keys are field names and corresponding values are field values.
__Example:__
``` js
var sql = jsonSql.build({
type: 'insert',
table: 'table',
values: [
{a: 5, b: 'text1'},
{a: 6, b: 'text2'}
]
});
sql.query
// insert into "table" ("a", "b") values (5, $p1), (6, $p2);
sql.values
// {p1: 'text1', p2: 'text2'}
```
If value is an `object`, it interprets as single inserted row where keys are field names and corresponding values are field values.
__Example:__
``` js
var sql = jsonSql.build({
type: 'insert',
table: 'table',
values: {a: 5, b: 'text'}
});
sql.query
// insert into "table" ("a", "b") values (5, $p1);
sql.values
// {p1: 'text'}
```
Also you can specify fields array. If there no key in value object it value is `null`.
__Example:__
``` js
var sql = jsonSql.build({
type: 'insert',
table: 'table',
fields: ['a', 'b', 'c'],
values: {c: 'text', b: 5}
});
sql.query
// insert into "table" ("a", "b", "c") values (null, 5, $p1);
sql.values
// {p1: 'text'}
```
### modifier
Should be an `object`.
You can specify modifier operator.
Available operators: `$set`, `$inc`, `$dec`, `$mul`, `$div`, `$default`.
__Example:__
``` js
var sql = jsonSql.build({
type: 'update',
table: 'table',
modifier: {
$set: {a: 5},
$default: {b: true},
$inc: {c: 10}
}
});
sql.query
// update "table" set "a" = 5, "b" = default, "c" = "c" + 10;
```
If modifier operator is not specified it uses default operator `$set`.
__Example:__
``` js
var sql = jsonSql.build({
type: 'update',
table: 'table',
modifier: {a: 5}
});
sql.query
// update "table" set "a" = 5;
```
### returning
Format is similar to [fields](#fields) block.
__Example:__
``` js
var sql = jsonSql.build({
type: 'insert',
table: 'table',
values: {a: 5},
returning: ['a']
});
sql.query
// insert into "table" ("a") values (5) returning "a";
```
### all
Should be a `boolean`.
__Example:__
``` js
var sql = jsonSql.build({
type: 'union',
all: true,
queries: [
{type: 'select', table: 'table1'},
{type: 'select', table: 'table2'}
]
});
sql.query
// (select * from "table1") union all (select * from "table2");
```
### queries
Should be an `array` with minimum 2 items. Each item interprets as sub-query and process recursively with [build(query)](#buildquery) method.
__Example:__
``` js
var sql = jsonSql.build({
type: 'union',
queries: [
{type: 'select', table: 'table1'},
{type: 'select', table: 'table2'}
]
});
sql.query
// (select * from "table1") union (select * from "table2");
//or for sqlite3
jsonSql.setDialect("sqlite");
var sql = jsonSql.build({
type: 'union',
unionqueries: [
{type: 'select', table: 'table1'},
{type: 'select', table: 'table2'}
]
});
sql.query
// select * from "table1" union select * from "table2";
```
## Condition operators
TODO: write this section