Compare commits
69 Commits
Author | SHA1 | Date |
---|---|---|
Timothy Warren | 9fa2ddefa1 | |
Timothy Warren | 16da54cb63 | |
Timothy Warren | 960d7f5051 | |
Timothy Warren | 00c193a22a | |
Timothy Warren | 4064a99419 | |
Timothy Warren | a94038cd47 | |
Timothy Warren | 806a1e1702 | |
Timothy Warren | 15371e49e8 | |
Timothy Warren | 5479a71614 | |
Timothy Warren | 22f047b5ed | |
Timothy Warren | 32b2a68b51 | |
Timothy Warren | 7edb5f1df0 | |
Timothy Warren | a5eb0795c9 | |
Timothy Warren | 26febfd7ab | |
Timothy Warren | cdc5dcfa17 | |
Timothy Warren | b54e69570f | |
Timothy Warren | 7f22eee84d | |
Timothy Warren | 3460abdd96 | |
Timothy Warren | cc6a3bb80b | |
Timothy Warren | ad91099706 | |
Timothy Warren | 31b0aedc9e | |
Timothy Warren | b6d9faf008 | |
Timothy Warren | 499e15ff81 | |
Timothy Warren | d4a8231947 | |
Timothy Warren | 2e661e24ff | |
Timothy Warren | c034604c94 | |
Timothy Warren | c90b1b1ba0 | |
Timothy Warren | 17dfebad4e | |
Timothy Warren | b13ad2a23d | |
Timothy Warren | 0ee092abd9 | |
Timothy Warren | 5dd42e07a7 | |
Timothy Warren | 7fbbff41c8 | |
Timothy Warren | 3ffe111df1 | |
Timothy Warren | 7b2482ad99 | |
Timothy Warren | 692c07ba74 | |
Timothy Warren | 8d7e4aaa8c | |
Timothy Warren | d3e5da66c4 | |
Timothy Warren | 2a4fedf03c | |
Timothy Warren | a8d7daf02a | |
Timothy Warren | 5576737caf | |
Timothy Warren | 5a7d0b9934 | |
Timothy Warren | 961a026868 | |
Timothy Warren | fd512894e4 | |
Timothy Warren | 189b02e60f | |
Timothy Warren | 14e7aaf5eb | |
Timothy Warren | e7d4f64889 | |
Timothy Warren | 9326992f8b | |
Timothy Warren | 43cc0a451e | |
Timothy Warren | 24dd5c057e | |
Timothy Warren | dc750c5cdb | |
Timothy Warren | b19dff4142 | |
Timothy Warren | 23fe7b19bc | |
Timothy Warren | 0350a165c7 | |
Timothy Warren | aeb665cf44 | |
Timothy Warren | 2b80fcfc62 | |
Timothy Warren | 8f0a392505 | |
Timothy Warren | 85c6d2a417 | |
Timothy Warren | 58008b46c0 | |
Timothy Warren | 137f8ec693 | |
Timothy Warren | 8f0b394d3c | |
Timothy Warren | a389a0d12e | |
Timothy Warren | 29bc4d4574 | |
Timothy Warren | 6dba16ac24 | |
Timothy Warren | f431463c9a | |
Timothy Warren | 74c28a112b | |
Timothy Warren | 5ecd9d523a | |
Timothy Warren | 26e3bdbf50 | |
Timothy Warren | 7f982a4c2b | |
Timothy Warren | 7afb44dc20 |
|
@ -0,0 +1,29 @@
|
|||
# EditorConfig is awesome: http://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
# Matches multiple files with brace expansion notation
|
||||
# Set default charset
|
||||
[*]
|
||||
charset = utf-8
|
||||
|
||||
# Tab indentation (no size specified)
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
# Indentation override for all JS under lib directory
|
||||
[*.js]
|
||||
indent_size = 2
|
||||
|
||||
# Matches the exact files either package.json or .travis.yml
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"env": {
|
||||
"commonjs": true,
|
||||
"es6": true,
|
||||
"jest": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": ["eslint:recommended", "happiness"],
|
||||
"rules": {
|
||||
"arrow-parens": ["error", "as-needed"],
|
||||
"callback-return": ["warn"],
|
||||
"constructor-super": ["error"],
|
||||
"curly" : ["error", "multi-line"],
|
||||
"no-case-declarations": "off",
|
||||
"no-console": ["warn"],
|
||||
"no-constant-condition": ["warn"],
|
||||
"no-dupe-args": ["error"],
|
||||
"no-dupe-class-members": ["error"],
|
||||
"no-dupe-keys": ["error"],
|
||||
"no-eval": ["error"],
|
||||
"no-extra-semi": ["warn"],
|
||||
"no-func-assign": ["warn"],
|
||||
"no-implied-eval": ["error"],
|
||||
"no-invalid-this": ["error"],
|
||||
"no-irregular-whitespace": ["warn"],
|
||||
"no-new-func": ["error"],
|
||||
"no-new-wrappers": ["error"],
|
||||
"no-obj-calls": ["error"],
|
||||
"no-this-before-super": ["error"],
|
||||
"no-unexpected-multiline" : ["error"],
|
||||
"no-unneeded-ternary": ["error"],
|
||||
"no-unreachable": ["warn"],
|
||||
"no-var": ["error"],
|
||||
"no-with": ["error"],
|
||||
"object-shorthand": ["warn", "methods"],
|
||||
"prefer-arrow-callback": ["warn"],
|
||||
"prefer-template": ["warn"],
|
||||
"radix": ["error"],
|
||||
"strict": ["error", "global"],
|
||||
"valid-jsdoc": ["warn"]
|
||||
},
|
||||
"parser": "babel-eslint"
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
build/*
|
||||
coverage
|
||||
coverage/*
|
||||
npm-debug.log
|
||||
tests/FB_TEST_DB.FD
|
||||
node_modules/*
|
||||
node_modules/*
|
||||
.sonar/*
|
||||
test/config.json
|
||||
.DS_store
|
||||
/.idea/
|
||||
yarn.lock
|
|
@ -0,0 +1,35 @@
|
|||
before_script:
|
||||
# Install dependencies
|
||||
- sh test/docker_install.sh > /dev/null
|
||||
- yarn
|
||||
|
||||
services:
|
||||
- mariadb:latest
|
||||
- postgres:alpine
|
||||
|
||||
variables:
|
||||
MYSQL_ROOT_PASSWORD: foo-bar-baz
|
||||
MYSQL_DATABASE: test
|
||||
MYSQL_USER: test
|
||||
MYSQL_PASSWORD: test
|
||||
POSTGRES_DB: test
|
||||
POSTGRES_USER: test
|
||||
POSTGRES_PASSWORD: test
|
||||
|
||||
# This folder is cached between builds
|
||||
# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
|
||||
cache:
|
||||
paths:
|
||||
- node_modules/
|
||||
|
||||
test:8:
|
||||
image: node:8-alpine
|
||||
script: yarn run test
|
||||
|
||||
test:9:
|
||||
image: node:9-alpine
|
||||
script: yarn run test
|
||||
|
||||
test:latest:
|
||||
image: node:alpine
|
||||
script: yarn run test
|
|
@ -1,6 +0,0 @@
|
|||
reporting:
|
||||
reports:
|
||||
- lcov
|
||||
- lcovonly
|
||||
report-config:
|
||||
lcovonly: {file: ../coverage/lcov.info}
|
7
.jscsrc
7
.jscsrc
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"preset": "airbnb",
|
||||
"validateIndentation": null,
|
||||
"requireLineFeedAtFileEnd": null,
|
||||
"disallowSpaceAfterPrefixUnaryOperators": null,
|
||||
"disallowMultipleVarDecl": null
|
||||
}
|
30
.travis.yml
30
.travis.yml
|
@ -1,30 +0,0 @@
|
|||
language: node_js
|
||||
sudo: false
|
||||
|
||||
node_js:
|
||||
- "node"
|
||||
- "5.6"
|
||||
- "5.5"
|
||||
- "5.4"
|
||||
- "5.3"
|
||||
- "5.2"
|
||||
- "5.1"
|
||||
- "5.0"
|
||||
- "4.3"
|
||||
- "4.2"
|
||||
- "4.1"
|
||||
- "4.0"
|
||||
|
||||
before_script:
|
||||
- npm install -g gulp
|
||||
- npm install -g codeclimate-test-reporter
|
||||
- psql -c 'DROP DATABASE IF EXISTS test;' -U postgres
|
||||
- psql -c 'create database test;' -U postgres
|
||||
- mysql -e 'create database IF NOT EXISTS test;'
|
||||
- mysql -v -uroot test < ./test/sql/mysql.sql
|
||||
- psql test postgres -f ./test/sql/pgsql.sql
|
||||
|
||||
script: gulp
|
||||
|
||||
after_script:
|
||||
- CODECLIMATE_REPO_TOKEN=aa39789a53f6f8fd84747a98968c9f79795e890d55a533daa943b1042f81687f codeclimate-test-reporter < coverage/lcov.info
|
867
API.md
867
API.md
|
@ -1,26 +1,73 @@
|
|||
# NodeQuery
|
||||
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
||||
|
||||
### Table of Contents
|
||||
|
||||
- [NodeQuery](#nodequery)
|
||||
- [getQuery](#getquery)
|
||||
- [QueryBuilder](#querybuilder)
|
||||
- [queryFile](#queryfile)
|
||||
- [query](#query)
|
||||
- [resetQuery](#resetquery)
|
||||
- [truncate](#truncate)
|
||||
- [end](#end)
|
||||
- [select](#select)
|
||||
- [from](#from)
|
||||
- [like](#like)
|
||||
- [notLike](#notlike)
|
||||
- [orLike](#orlike)
|
||||
- [orNotLike](#ornotlike)
|
||||
- [having](#having)
|
||||
- [orHaving](#orhaving)
|
||||
- [where](#where)
|
||||
- [orWhere](#orwhere)
|
||||
- [whereIsNull](#whereisnull)
|
||||
- [whereIsNotNull](#whereisnotnull)
|
||||
- [orWhereIsNull](#orwhereisnull)
|
||||
- [orWhereIsNotNull](#orwhereisnotnull)
|
||||
- [whereIn](#wherein)
|
||||
- [orWhereIn](#orwherein)
|
||||
- [whereNotIn](#wherenotin)
|
||||
- [orWhereNotIn](#orwherenotin)
|
||||
- [set](#set)
|
||||
- [join](#join)
|
||||
- [groupBy](#groupby)
|
||||
- [orderBy](#orderby)
|
||||
- [limit](#limit)
|
||||
- [groupStart](#groupstart)
|
||||
- [orGroupStart](#orgroupstart)
|
||||
- [orNotGroupStart](#ornotgroupstart)
|
||||
- [groupEnd](#groupend)
|
||||
- [get](#get)
|
||||
- [insert](#insert)
|
||||
- [insertBatch](#insertbatch)
|
||||
- [update](#update)
|
||||
- [updateBatch](#updatebatch)
|
||||
- [delete](#delete)
|
||||
- [getCompiledSelect](#getcompiledselect)
|
||||
- [getCompiledInsert](#getcompiledinsert)
|
||||
- [getCompiledUpdate](#getcompiledupdate)
|
||||
- [getCompiledDelete](#getcompileddelete)
|
||||
- [Result](#result)
|
||||
- [rowCount](#rowcount)
|
||||
- [columnCount](#columncount)
|
||||
|
||||
## NodeQuery
|
||||
|
||||
Class for connection management
|
||||
|
||||
## getQuery
|
||||
**Parameters**
|
||||
|
||||
- `config` **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** connection parameters
|
||||
|
||||
### getQuery
|
||||
|
||||
Return an existing query builder instance
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object
|
||||
|
||||
## init
|
||||
## QueryBuilder
|
||||
|
||||
Create a query builder object
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `driverType` **String** The name of the database type, eg. mysql or pg
|
||||
- `connObject` **Object** A connection object from the database library you are connecting with
|
||||
- `connLib` **[String]** The name of the db connection library you are using, eg. mysql or mysql2. Optional if the same as driverType
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object
|
||||
|
||||
# QueryBuilder
|
||||
**Extends QueryBuilderBase**
|
||||
|
||||
Main object that builds SQL queries.
|
||||
|
||||
|
@ -29,368 +76,57 @@ Main object that builds SQL queries.
|
|||
- `Driver` **Driver** The syntax driver for the database
|
||||
- `Adapter` **Adapter** The database module adapter for running queries
|
||||
|
||||
## delete
|
||||
### queryFile
|
||||
|
||||
Run the generated delete query
|
||||
Run a set of queries from a file
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **String** The table to insert into
|
||||
- `where` **[Object]** Where clause for delete statement
|
||||
- `callback` **[Function]** Callback for handling response from the database
|
||||
- `file` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The path to the sql file
|
||||
- `separator` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The character separating each query (optional, default `';'`)
|
||||
|
||||
Returns **void or Promise** If no callback is passed, a promise is returned
|
||||
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)** The result of all the queries
|
||||
|
||||
## end
|
||||
### query
|
||||
|
||||
Closes the database connection for the current adapter
|
||||
|
||||
Returns **void**
|
||||
|
||||
## from
|
||||
|
||||
Specify the database table to select from
|
||||
Run an arbitrary sql query. Run as a prepared statement.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `tableName` **String** The table to use for the current query
|
||||
- `sql` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The sql to execute
|
||||
- `params` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** The query parameters
|
||||
|
||||
**Examples**
|
||||
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)** Promise with result of query
|
||||
|
||||
```javascript
|
||||
query.from('tableName');
|
||||
```
|
||||
|
||||
```javascript
|
||||
query.from('tableName t'); // Select the table with an alias
|
||||
```
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## get
|
||||
|
||||
Get the results of the compiled query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **[String]** The table to select from
|
||||
- `limit` **[Number]** A limit for the query
|
||||
- `offset` **[Number]** An offset for the query
|
||||
- `callback` **[Function]** A callback for receiving the result
|
||||
|
||||
**Examples**
|
||||
|
||||
```javascript
|
||||
query.get('table_name').then(promiseCallback); // Get all the rows in the table
|
||||
```
|
||||
|
||||
```javascript
|
||||
query.get('table_name', 5, callback); // Get 5 rows from the table
|
||||
```
|
||||
|
||||
```javascript
|
||||
query.get(callback); // Get the results of a query generated with other methods
|
||||
```
|
||||
|
||||
Returns **void or Promise** If no callback is passed, a promise is returned
|
||||
|
||||
## getCompiledDelete
|
||||
|
||||
Return generated delete query SQL
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **String** the name of the table to delete from
|
||||
- `reset` **[Boolean]** Whether to reset the query builder so another query can be built (optional, default `true`)
|
||||
|
||||
Returns **String** The compiled sql statement
|
||||
|
||||
## getCompiledInsert
|
||||
|
||||
Return generated insert query SQL
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **String** the name of the table to insert into
|
||||
- `reset` **[Boolean]** Whether to reset the query builder so another query can be built (optional, default `true`)
|
||||
|
||||
Returns **String** The compiled sql statement
|
||||
|
||||
## getCompiledSelect
|
||||
|
||||
Return generated select query SQL
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **[String]** the name of the table to retrieve from
|
||||
- `reset` **[Boolean]** Whether to reset the query builder so another query can be built (optional, default `true`)
|
||||
|
||||
Returns **String** The compiled sql statement
|
||||
|
||||
## getCompiledUpdate
|
||||
|
||||
Return generated update query SQL
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **String** the name of the table to update
|
||||
- `reset` **[Boolean]** Whether to reset the query builder so another query can be built (optional, default `true`)
|
||||
|
||||
Returns **String** The compiled sql statement
|
||||
|
||||
## groupBy
|
||||
|
||||
Group the results by the selected field(s)
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **String or Array** The name of the field to group by
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## groupEnd
|
||||
|
||||
Ends a logical grouping started with one of the groupStart methods
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## groupStart
|
||||
|
||||
Adds an open paren to the current query for logical grouping
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## having
|
||||
|
||||
Add a 'having' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **String or Object** The name of the field and the comparision operator, or an object
|
||||
- `val` **[String or Number]** The value to compare if the value of key is a string
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## insert
|
||||
|
||||
Run the generated insert query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **String** The table to insert into
|
||||
- `data` **[Object]** Data to insert, if not already added with the 'set' method
|
||||
- `callback` **[Function]** Callback for handling response from the database
|
||||
|
||||
Returns **void or Promise** If no callback is passed, a promise is returned
|
||||
|
||||
## insertBatch
|
||||
|
||||
Insert multiple sets of rows at a time
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **String** The table to insert into
|
||||
- `data` **Array** The array of objects containing data rows to insert
|
||||
- `callback` **[Function]** Callback for handling database response
|
||||
|
||||
**Examples**
|
||||
|
||||
```javascript
|
||||
query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}], callbackFunction);
|
||||
```
|
||||
|
||||
```javascript
|
||||
query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}])
|
||||
.then(promiseCallback);
|
||||
```
|
||||
|
||||
Returns **void or Promise** If no callback is passed, a promise is returned
|
||||
|
||||
## join
|
||||
|
||||
Add a join clause to the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **String** The table you are joining
|
||||
- `cond` **String** The join condition.
|
||||
- `type` **[String]** The type of join, which defaults to inner (optional, default `'inner'`)
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## like
|
||||
|
||||
Add a 'like/ and like' clause to the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **String** The name of the field to compare to
|
||||
- `val` **String** The value to compare to
|
||||
- `pos` **[String]** The placement of the wildcard character(s): before, after, or both (optional, default `both`)
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## limit
|
||||
|
||||
Put a limit on the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `limit` **Number** The maximum number of rows to fetch
|
||||
- `offset` **[Number]** The row number to start from
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## notLike
|
||||
|
||||
Add a 'not like/ and not like' clause to the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **String** The name of the field to compare to
|
||||
- `val` **String** The value to compare to
|
||||
- `pos` **[String]** The placement of the wildcard character(s): before, after, or both (optional, default `both`)
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## orGroupStart
|
||||
|
||||
Adds an open paren to the current query for logical grouping,
|
||||
prefixed with 'OR'
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## orHaving
|
||||
|
||||
Add an 'or having' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **String or Object** The name of the field and the comparision operator, or an object
|
||||
- `val` **[String or Number]** The value to compare if the value of key is a string
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## orLike
|
||||
|
||||
Add an 'or like' clause to the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **String** The name of the field to compare to
|
||||
- `val` **String** The value to compare to
|
||||
- `pos` **[String]** The placement of the wildcard character(s): before, after, or both (optional, default `both`)
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## orNotGroupStart
|
||||
|
||||
Adds an open paren to the current query for logical grouping,
|
||||
prefixed with 'OR NOT'
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## orNotLike
|
||||
|
||||
Add an 'or not like' clause to the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **String** The name of the field to compare to
|
||||
- `val` **String** The value to compare to
|
||||
- `pos` **[String]** The placement of the wildcard character(s): before, after, or both (optional, default `both`)
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## orWhere
|
||||
|
||||
Set a 'or where' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **String or Object** The name of the field and the comparision operator, or an object
|
||||
- `val` **[String or Number]** The value to compare if the value of key is a string
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## orWhereIn
|
||||
|
||||
Set a 'or where in' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **String** the field to search
|
||||
- `values` **Array** the array of items to search in
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## orWhereIsNotNull
|
||||
|
||||
Field is not null prefixed with 'OR'
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **String** The name of the field
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## orWhereIsNull
|
||||
|
||||
Field is null prefixed with 'OR'
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **String** The name of the field
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## orWhereNotIn
|
||||
|
||||
Set a 'or where not in' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **String** the field to search
|
||||
- `values` **Array** the array of items to search in
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## orderBy
|
||||
|
||||
Order the results by the selected field(s)
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **String** The field(s) to order by
|
||||
- `type` **[String]** The order direction, ASC or DESC (optional, default `'ASC'`)
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
|
||||
## query
|
||||
|
||||
Manually make an sql query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `sql` **string** The sql to execute
|
||||
- `params` **[array]** The query parameters
|
||||
- `callback` **[function]** Optional callback
|
||||
|
||||
Returns **void or Promise** Returns a promise if no callback is supplied
|
||||
|
||||
## resetQuery
|
||||
### resetQuery
|
||||
|
||||
Reset the object state for a new query
|
||||
|
||||
Returns **void**
|
||||
|
||||
## select
|
||||
### truncate
|
||||
|
||||
Empties the selected database table
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the name of the table to truncate
|
||||
|
||||
Returns **(void | [Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise))** Returns a promise if no callback is supplied
|
||||
|
||||
### end
|
||||
|
||||
Closes the database connection for the current adapter
|
||||
|
||||
Returns **void**
|
||||
|
||||
### select
|
||||
|
||||
Specify rows to select in the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `fields` **String or Array** The fields to select from the current table
|
||||
- `fields` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array))** The fields to select from the current table
|
||||
|
||||
**Examples**
|
||||
|
||||
|
@ -402,16 +138,212 @@ query.select('foo, bar'); // Select multiple fields with a string
|
|||
query.select(['foo', 'bar']); // Select multiple fileds with an array
|
||||
```
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
## set
|
||||
### from
|
||||
|
||||
Specify the database table to select from
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `tableName` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The table to use for the current query
|
||||
|
||||
**Examples**
|
||||
|
||||
```javascript
|
||||
query.from('tableName');
|
||||
```
|
||||
|
||||
```javascript
|
||||
query.from('tableName t'); // Select the table with an alias
|
||||
```
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### like
|
||||
|
||||
Add a 'like/ and like' clause to the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The name of the field to compare to
|
||||
- `val` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The value to compare to
|
||||
- `pos` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The placement of the wildcard character(s): before, after, or both (optional, default `both`)
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### notLike
|
||||
|
||||
Add a 'not like/ and not like' clause to the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The name of the field to compare to
|
||||
- `val` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The value to compare to
|
||||
- `pos` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The placement of the wildcard character(s): before, after, or both (optional, default `both`)
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### orLike
|
||||
|
||||
Add an 'or like' clause to the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The name of the field to compare to
|
||||
- `val` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The value to compare to
|
||||
- `pos` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The placement of the wildcard character(s): before, after, or both (optional, default `both`)
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### orNotLike
|
||||
|
||||
Add an 'or not like' clause to the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The name of the field to compare to
|
||||
- `val` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The value to compare to
|
||||
- `pos` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The placement of the wildcard character(s): before, after, or both (optional, default `both`)
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### having
|
||||
|
||||
Add a 'having' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object))** The name of the field and the comparision operator, or an object
|
||||
- `val` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number))?** The value to compare if the value of key is a string (optional, default `null`)
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### orHaving
|
||||
|
||||
Add an 'or having' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object))** The name of the field and the comparision operator, or an object
|
||||
- `val` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number))?** The value to compare if the value of key is a string (optional, default `null`)
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### where
|
||||
|
||||
Set a 'where' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object))** The name of the field and the comparision operator, or an object
|
||||
- `val` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number))?** The value to compare if the value of key is a string
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### orWhere
|
||||
|
||||
Set a 'or where' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object))** The name of the field and the comparision operator, or an object
|
||||
- `val` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number))?** The value to compare if the value of key is a string
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### whereIsNull
|
||||
|
||||
Select a field that is Null
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The name of the field that has a NULL value
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### whereIsNotNull
|
||||
|
||||
Specify that a field IS NOT NULL
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The name so the field that is not to be null
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### orWhereIsNull
|
||||
|
||||
Field is null prefixed with 'OR'
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The name of the field
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### orWhereIsNotNull
|
||||
|
||||
Field is not null prefixed with 'OR'
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The name of the field
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### whereIn
|
||||
|
||||
Set a 'where in' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the field to search
|
||||
- `values` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)** the array of items to search in
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### orWhereIn
|
||||
|
||||
Set a 'or where in' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the field to search
|
||||
- `values` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)** the array of items to search in
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### whereNotIn
|
||||
|
||||
Set a 'where not in' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the field to search
|
||||
- `values` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)** the array of items to search in
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### orWhereNotIn
|
||||
|
||||
Set a 'or where not in' clause
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the field to search
|
||||
- `values` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)** the array of items to search in
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### set
|
||||
|
||||
Set values for insertion or updating
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **String or Object** The key or object to use
|
||||
- `val` **[String]** The value if using a scalar key
|
||||
- `key` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object))** The key or object to use
|
||||
- `val` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** The value if using a scalar key
|
||||
|
||||
**Examples**
|
||||
|
||||
|
@ -423,69 +355,228 @@ query.set('foo', 'bar'); // Set a key, value pair
|
|||
query.set({foo:'bar'}); // Set with an object
|
||||
```
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
## update
|
||||
### join
|
||||
|
||||
Add a join clause to the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The table you are joining
|
||||
- `cond` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The join condition.
|
||||
- `type` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The type of join, which defaults to inner (optional, default `'inner'`)
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### groupBy
|
||||
|
||||
Group the results by the selected field(s)
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array))** The name of the field to group by
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### orderBy
|
||||
|
||||
Order the results by the selected field(s)
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The field(s) to order by
|
||||
- `type` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The order direction, ASC or DESC (optional, default `'ASC'`)
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### limit
|
||||
|
||||
Put a limit on the query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `limit` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** The maximum number of rows to fetch
|
||||
- `offset` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** The row number to start from
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### groupStart
|
||||
|
||||
Adds an open paren to the current query for logical grouping
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### orGroupStart
|
||||
|
||||
Adds an open paren to the current query for logical grouping,
|
||||
prefixed with 'OR'
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### orNotGroupStart
|
||||
|
||||
Adds an open paren to the current query for logical grouping,
|
||||
prefixed with 'OR NOT'
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### groupEnd
|
||||
|
||||
Ends a logical grouping started with one of the groupStart methods
|
||||
|
||||
Returns **[QueryBuilder](#querybuilder)** The Query Builder object, for chaining
|
||||
|
||||
### get
|
||||
|
||||
Get the results of the compiled query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** The table to select from
|
||||
- `limit` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** A limit for the query
|
||||
- `offset` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** An offset for the query
|
||||
|
||||
**Examples**
|
||||
|
||||
```javascript
|
||||
query.get('table_name').then(promiseCallback); // Get all the rows in the table
|
||||
```
|
||||
|
||||
```javascript
|
||||
query.get('table_name', 5); // Get 5 rows from the table
|
||||
```
|
||||
|
||||
```javascript
|
||||
query.get(); // Get the results of a query generated with other methods
|
||||
```
|
||||
|
||||
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[Result](#result)>** Promise containing the result of the query
|
||||
|
||||
### insert
|
||||
|
||||
Run the generated insert query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The table to insert into
|
||||
- `data` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Data to insert, if not already added with the 'set' method
|
||||
|
||||
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[Result](#result)>** Promise containing the result of the query
|
||||
|
||||
### insertBatch
|
||||
|
||||
Insert multiple sets of rows at a time
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The table to insert into
|
||||
- `data` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)** The array of objects containing data rows to insert
|
||||
|
||||
**Examples**
|
||||
|
||||
```javascript
|
||||
query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}])
|
||||
.then(promiseCallback);
|
||||
```
|
||||
|
||||
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[Result](#result)>** Promise containing the result of the query
|
||||
|
||||
### update
|
||||
|
||||
Run the generated update query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **String** The table to insert into
|
||||
- `data` **[Object]** Data to insert, if not already added with the 'set' method
|
||||
- `callback` **[Function]** Callback for handling response from the database
|
||||
- `table` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The table to insert into
|
||||
- `data` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Data to insert, if not already added with the 'set' method
|
||||
|
||||
Returns **void or Promise** If no callback is passed, a promise is returned
|
||||
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[Result](#result)>** Promise containing the result of the query
|
||||
|
||||
## where
|
||||
### updateBatch
|
||||
|
||||
Set a 'where' clause
|
||||
Creates a batch update sql statement
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **String or Object** The name of the field and the comparision operator, or an object
|
||||
- `val` **[String or Number]** The value to compare if the value of key is a string
|
||||
- `table` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The table to update
|
||||
- `data` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** Batch insert data
|
||||
- `updateKey` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The field in the table to compare against for updating
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
Returns **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of rows updated
|
||||
|
||||
## whereIn
|
||||
### delete
|
||||
|
||||
Set a 'where in' clause
|
||||
Run the generated delete query
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **String** the field to search
|
||||
- `values` **Array** the array of items to search in
|
||||
- `table` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The table to insert into
|
||||
- `where` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Where clause for delete statement
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[Result](#result)>** Promise containing the result of the query
|
||||
|
||||
## whereIsNotNull
|
||||
### getCompiledSelect
|
||||
|
||||
Specify that a field IS NOT NULL
|
||||
Return generated select query SQL
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **String** The name so the field that is not to be null
|
||||
- `table` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** the name of the table to retrieve from
|
||||
- `reset` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Whether to reset the query builder so another query can be built (optional, default `true`)
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The compiled sql statement
|
||||
|
||||
## whereIsNull
|
||||
### getCompiledInsert
|
||||
|
||||
Select a field that is Null
|
||||
Return generated insert query SQL
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `field` **String** The name of the field that has a NULL value
|
||||
- `table` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the name of the table to insert into
|
||||
- `reset` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Whether to reset the query builder so another query can be built (optional, default `true`)
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The compiled sql statement
|
||||
|
||||
## whereNotIn
|
||||
### getCompiledUpdate
|
||||
|
||||
Set a 'where not in' clause
|
||||
Return generated update query SQL
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `key` **String** the field to search
|
||||
- `values` **Array** the array of items to search in
|
||||
- `table` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the name of the table to update
|
||||
- `reset` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Whether to reset the query builder so another query can be built (optional, default `true`)
|
||||
|
||||
Returns **QueryBuilder** The Query Builder object, for chaining
|
||||
Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The compiled sql statement
|
||||
|
||||
### getCompiledDelete
|
||||
|
||||
Return generated delete query SQL
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `table` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the name of the table to delete from
|
||||
- `reset` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Whether to reset the query builder so another query can be built (optional, default `true`)
|
||||
|
||||
Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The compiled sql statement
|
||||
|
||||
## Result
|
||||
|
||||
Query result object
|
||||
|
||||
**Parameters**
|
||||
|
||||
- `rows` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)** the data rows of the result (optional, default `[]`)
|
||||
- `columns` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)** the column names in the result (optional, default `[]`)
|
||||
|
||||
### rowCount
|
||||
|
||||
Get the number of rows returned by the query
|
||||
|
||||
Returns **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** the number of rows in the result
|
||||
|
||||
### columnCount
|
||||
|
||||
Get the number of columns returned by the query
|
||||
|
||||
Returns **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** the number of columns in the result
|
||||
|
|
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -1,8 +1,18 @@
|
|||
# Changelog
|
||||
|
||||
# 5.0.0
|
||||
* Re-added firebird as a database
|
||||
* Replaced all callback interfaces with promises
|
||||
|
||||
## 4.0.0
|
||||
* Changed connection setup to just use a config object - the appropriate adapter object is created by the library.
|
||||
* Removed mysql adapter, as mysql2 is very similar and does proper prepared statements
|
||||
* Removed firebird entirely
|
||||
* Created a standard result object
|
||||
|
||||
## 3.2.0
|
||||
* Added public `query` method for making arbitrary sql calls
|
||||
* Added back tests for `node-query` adapter. Using this adapter with promises is not currently supported.
|
||||
* Added back tests for `node-firebird` adapter. Using this adapter with promises is not currently supported.
|
||||
|
||||
## 3.1.0
|
||||
* Added support for promises on query execution methods
|
||||
* Added support for promises on query execution methods
|
||||
|
|
77
README.md
77
README.md
|
@ -3,20 +3,15 @@
|
|||
A node query builder for various SQL databases, based on [CodeIgniter](http://www.codeigniter.com/user_guide/database/query_builder.html)'s query builder.
|
||||
|
||||
[![Build Status](https://jenkins.timshomepage.net/buildStatus/icon?job=node-query)](https://jenkins.timshomepage.net/job/node-query/)
|
||||
[![Build Status](https://travis-ci.org/timw4mail/node-query.svg?branch=master)](https://travis-ci.org/timw4mail/node-query)
|
||||
[![Code Climate](https://codeclimate.com/github/timw4mail/node-query/badges/gpa.svg)](https://codeclimate.com/github/timw4mail/node-query)
|
||||
[![Test Coverage](https://codeclimate.com/github/timw4mail/node-query/badges/coverage.svg)](https://codeclimate.com/github/timw4mail/node-query/coverage)
|
||||
|
||||
### Features
|
||||
* Callback and Promise API for making database calls.
|
||||
|
||||
### Supported adapters
|
||||
### Supported databases
|
||||
|
||||
* mysql
|
||||
* mysql2
|
||||
* pg
|
||||
* dblite
|
||||
* node-firebird (Not supported as of version 3.1.0, as the adapter is very difficult to test)
|
||||
* Mysql (via `mysql2`)
|
||||
* PostgreSQL (via `pg`)
|
||||
* Sqlite (via `dblite`)
|
||||
|
||||
### Installation
|
||||
|
||||
|
@ -24,36 +19,28 @@ A node query builder for various SQL databases, based on [CodeIgniter](http://ww
|
|||
|
||||
[![NPM](https://nodei.co/npm/ci-node-query.png?downloads=true&downloadRank=true)](https://nodei.co/npm/ci-node-query/)
|
||||
|
||||
(Versions 3.x and below work differently. Their documentation is [here](https://git.timshomepage.net/timw4mail/node-query/tree/v3#README))
|
||||
|
||||
### Basic use
|
||||
```javascript
|
||||
var nodeQuery = require('ci-node-query');
|
||||
|
||||
var connection = ... // Database module connection
|
||||
// Set the database connection details
|
||||
const nodeQuery = require('ci-node-query')({
|
||||
"driver": "mysql",
|
||||
"connection": {
|
||||
"host": "localhost",
|
||||
"user": "test",
|
||||
"password": "",
|
||||
"database": "test"
|
||||
}
|
||||
});
|
||||
|
||||
// Three arguments: database type, database connection, database connection library
|
||||
var query = nodeQuery.init('mysql', connection, 'mysql2');
|
||||
|
||||
// The third argument is optional if the database connection library has the same name as the adapter, eg..
|
||||
nodeQuery.init('mysql', connection, 'mysql');
|
||||
// Can be instead
|
||||
nodeQuery.init('mysql', connection);
|
||||
|
||||
// You can also retrieve the instance later
|
||||
query = nodeQuery.getQuery();
|
||||
|
||||
query.select('foo')
|
||||
.from('bar')
|
||||
.where('x', 3)
|
||||
.orWhere({y: 2})
|
||||
.join('baz', 'baz.boo = bar.foo', 'left')
|
||||
.orderBy('x', 'DESC')
|
||||
.limit(2, 3)
|
||||
.get(function(/* Adapter dependent arguments */) {
|
||||
// Database module result handling
|
||||
});
|
||||
// Get the query builder
|
||||
const query = nodeQuery.getQuery();
|
||||
|
||||
// As of version 3.1.0, you can also get promises
|
||||
var queryPromise = query.select('foo')
|
||||
// Version 5.0.0 removes all callback interfaces
|
||||
const queryPromise = query.select('foo')
|
||||
.from('bar')
|
||||
.where('x', 3)
|
||||
.orWhere({y: 2})
|
||||
|
@ -67,6 +54,26 @@ queryPromise.then(function(res) {
|
|||
});
|
||||
```
|
||||
|
||||
### Result object
|
||||
As of version 4, all adapters return a standard result object, which looks similar to this:
|
||||
|
||||
```javascript
|
||||
// Result object
|
||||
{
|
||||
rows: [{
|
||||
columnName1: value1,
|
||||
columnName2: value2,
|
||||
}],
|
||||
|
||||
columns: ['column1', 'column2'],
|
||||
}
|
||||
```
|
||||
|
||||
In addition to the rows, and columns properties,
|
||||
the result object has two methods, `rowCount` and `columnCount`.
|
||||
These methods return the number of rows and columns columns in the current result.
|
||||
|
||||
|
||||
### Security notes
|
||||
As of version 2, `where` and `having` type methods parse the values passed to look for function calls. While values passed are still passed as query parameters, take care to avoid passing these kinds of methods unfiltered input. SQL function arguments are not currently parsed, so they need to be properly escaped for the current database.
|
||||
|
||||
|
@ -76,5 +83,7 @@ As of version 2, `where` and `having` type methods parse the values passed to lo
|
|||
* Generated documentation is in the docs/ folder
|
||||
* The API is documented in [API.md](./API.md)
|
||||
* The `tests/adapters` folder contains examples of how to set up a connection for the appropriate database library
|
||||
* The documentation generated for the latest dev build is also [Available](https://github.timshomepage.net/node-query/docs/)
|
||||
* The documentation generated for the latest dev build is also [Available](https://github.timshomepage.net/node-query/docs/index.html)
|
||||
|
||||
[![js-happiness-style](https://cdn.rawgit.com/JedWatson/happiness/master/badge.svg)](https://github.com/JedWatson/happiness)
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
mariadb:
|
||||
image: mariadb:latest
|
||||
environment:
|
||||
- MYSQL_USER=test
|
||||
- MYSQL_PASSWORD=test
|
||||
- MYSQL_DATABASE=test
|
||||
- MYSQL_RANDOM_ROOT_PASSWORD=yes
|
||||
ports:
|
||||
- 3306:3306
|
||||
|
||||
postgresql:
|
||||
image: postgres:latest
|
||||
environment:
|
||||
- POSTGRES_USER=test
|
||||
- POSTGRES_PASSWORD=test
|
||||
- POSTGRES_DB=test
|
||||
ports:
|
||||
- 5432:5432
|
||||
|
||||
sqlserver:
|
||||
image: microsoft/mssql-server-linux
|
||||
environment:
|
||||
- ACCEPT_EULA=Y
|
||||
- SA_PASSWORD=t3571ng0n1y
|
||||
ports:
|
||||
- 1433:1433
|
||||
|
||||
firebird:
|
||||
image: itherz/firebird3:latest
|
||||
ports:
|
||||
- 5040:5040
|
||||
volumes:
|
||||
- ./test:/databases
|
|
@ -1,197 +1,350 @@
|
|||
/*!
|
||||
* AnchorJS - v1.2.1 - 2015-07-02
|
||||
* AnchorJS - v4.0.0 - 2017-06-02
|
||||
* https://github.com/bryanbraun/anchorjs
|
||||
* Copyright (c) 2015 Bryan Braun; Licensed MIT
|
||||
* Copyright (c) 2017 Bryan Braun; Licensed MIT
|
||||
*/
|
||||
/* eslint-env amd, node */
|
||||
|
||||
function AnchorJS(options) {
|
||||
// https://github.com/umdjs/umd/blob/master/templates/returnExports.js
|
||||
(function(root, factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([], factory);
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
// Node. Does not work with strict CommonJS, but
|
||||
// only CommonJS-like environments that support module.exports,
|
||||
// like Node.
|
||||
module.exports = factory();
|
||||
} else {
|
||||
// Browser globals (root is window)
|
||||
root.AnchorJS = factory();
|
||||
root.anchors = new root.AnchorJS();
|
||||
}
|
||||
})(this, function() {
|
||||
'use strict';
|
||||
function AnchorJS(options) {
|
||||
this.options = options || {};
|
||||
this.elements = [];
|
||||
|
||||
this.options = options || {};
|
||||
/**
|
||||
* Assigns options to the internal options object, and provides defaults.
|
||||
* @param {Object} opts - Options object
|
||||
*/
|
||||
function _applyRemainingDefaultOptions(opts) {
|
||||
opts.icon = opts.hasOwnProperty('icon') ? opts.icon : '\ue9cb'; // Accepts characters (and also URLs?), like '#', '¶', '❡', or '§'.
|
||||
opts.visible = opts.hasOwnProperty('visible') ? opts.visible : 'hover'; // Also accepts 'always' & 'touch'
|
||||
opts.placement = opts.hasOwnProperty('placement')
|
||||
? opts.placement
|
||||
: 'right'; // Also accepts 'left'
|
||||
opts.class = opts.hasOwnProperty('class') ? opts.class : ''; // Accepts any class name.
|
||||
// Using Math.floor here will ensure the value is Number-cast and an integer.
|
||||
opts.truncate = opts.hasOwnProperty('truncate')
|
||||
? Math.floor(opts.truncate)
|
||||
: 64; // Accepts any value that can be typecast to a number.
|
||||
}
|
||||
|
||||
this._applyRemainingDefaultOptions = function(opts) {
|
||||
this.options.icon = this.options.hasOwnProperty('icon') ? opts.icon : '\ue9cb'; // Accepts characters (and also URLs?), like '#', '¶', '❡', or '§'.
|
||||
this.options.visible = this.options.hasOwnProperty('visible') ? opts.visible : 'hover'; // Also accepts 'always'
|
||||
this.options.placement = this.options.hasOwnProperty('placement') ? opts.placement : 'right'; // Also accepts 'left'
|
||||
this.options.class = this.options.hasOwnProperty('class') ? opts.class : ''; // Accepts any class name.
|
||||
};
|
||||
_applyRemainingDefaultOptions(this.options);
|
||||
|
||||
this._applyRemainingDefaultOptions(options);
|
||||
/**
|
||||
* Checks to see if this device supports touch. Uses criteria pulled from Modernizr:
|
||||
* https://github.com/Modernizr/Modernizr/blob/da22eb27631fc4957f67607fe6042e85c0a84656/feature-detects/touchevents.js#L40
|
||||
* @returns {Boolean} - true if the current device supports touch.
|
||||
*/
|
||||
this.isTouchDevice = function() {
|
||||
return !!(
|
||||
'ontouchstart' in window ||
|
||||
(window.DocumentTouch && document instanceof DocumentTouch)
|
||||
);
|
||||
};
|
||||
|
||||
this.add = function(selector) {
|
||||
var elements,
|
||||
/**
|
||||
* Add anchor links to page elements.
|
||||
* @param {String|Array|Nodelist} selector - A CSS selector for targeting the elements you wish to add anchor links
|
||||
* to. Also accepts an array or nodeList containing the relavant elements.
|
||||
* @returns {this} - The AnchorJS object
|
||||
*/
|
||||
this.add = function(selector) {
|
||||
var elements,
|
||||
elsWithIds,
|
||||
idList,
|
||||
elementID,
|
||||
i,
|
||||
roughText,
|
||||
tidyText,
|
||||
index,
|
||||
count,
|
||||
tidyText,
|
||||
newTidyText,
|
||||
readableID,
|
||||
anchor;
|
||||
anchor,
|
||||
visibleOptionToUse,
|
||||
indexesToDrop = [];
|
||||
|
||||
this._applyRemainingDefaultOptions(this.options);
|
||||
// We reapply options here because somebody may have overwritten the default options object when setting options.
|
||||
// For example, this overwrites all options but visible:
|
||||
//
|
||||
// anchors.options = { visible: 'always'; }
|
||||
_applyRemainingDefaultOptions(this.options);
|
||||
|
||||
// Provide a sensible default selector, if none is given.
|
||||
if (!selector) {
|
||||
selector = 'h1, h2, h3, h4, h5, h6';
|
||||
} else if (typeof selector !== 'string') {
|
||||
throw new Error('The selector provided to AnchorJS was invalid.');
|
||||
}
|
||||
visibleOptionToUse = this.options.visible;
|
||||
if (visibleOptionToUse === 'touch') {
|
||||
visibleOptionToUse = this.isTouchDevice() ? 'always' : 'hover';
|
||||
}
|
||||
|
||||
elements = document.querySelectorAll(selector);
|
||||
if (elements.length === 0) {
|
||||
return false;
|
||||
}
|
||||
// Provide a sensible default selector, if none is given.
|
||||
if (!selector) {
|
||||
selector = 'h2, h3, h4, h5, h6';
|
||||
}
|
||||
|
||||
this._addBaselineStyles();
|
||||
elements = _getElements(selector);
|
||||
|
||||
// We produce a list of existing IDs so we don't generate a duplicate.
|
||||
elsWithIds = document.querySelectorAll('[id]');
|
||||
idList = [].map.call(elsWithIds, function assign(el) {
|
||||
return el.id;
|
||||
});
|
||||
if (elements.length === 0) {
|
||||
return this;
|
||||
}
|
||||
|
||||
for (i = 0; i < elements.length; i++) {
|
||||
_addBaselineStyles();
|
||||
|
||||
if (elements[i].hasAttribute('id')) {
|
||||
elementID = elements[i].getAttribute('id');
|
||||
} else {
|
||||
roughText = elements[i].textContent;
|
||||
// We produce a list of existing IDs so we don't generate a duplicate.
|
||||
elsWithIds = document.querySelectorAll('[id]');
|
||||
idList = [].map.call(elsWithIds, function assign(el) {
|
||||
return el.id;
|
||||
});
|
||||
|
||||
// Refine it so it makes a good ID. Strip out non-safe characters, replace
|
||||
// spaces with hyphens, truncate to 32 characters, and make toLowerCase.
|
||||
//
|
||||
// Example string: // '⚡⚡⚡ Unicode icons are cool--but they definitely don't belong in a URL fragment.'
|
||||
tidyText = roughText.replace(/[^\w\s-]/gi, '') // ' Unicode icons are cool--but they definitely dont belong in a URL fragment'
|
||||
.replace(/\s+/g, '-') // '-Unicode-icons-are-cool--but-they-definitely-dont-belong-in-a-URL-fragment'
|
||||
.replace(/-{2,}/g, '-') // '-Unicode-icons-are-cool-but-they-definitely-dont-belong-in-a-URL-fragment'
|
||||
.substring(0, 64) // '-Unicode-icons-are-cool-but-they-definitely-dont-belong-in-a-URL'
|
||||
.replace(/^-+|-+$/gm, '') // 'Unicode-icons-are-cool-but-they-definitely-dont-belong-in-a-URL'
|
||||
.toLowerCase(); // 'unicode-icons-are-cool-but-they-definitely-dont-belong-in-a-url'
|
||||
for (i = 0; i < elements.length; i++) {
|
||||
if (this.hasAnchorJSLink(elements[i])) {
|
||||
indexesToDrop.push(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compare our generated ID to existing IDs (and increment it if needed)
|
||||
// before we add it to the page.
|
||||
newTidyText = tidyText;
|
||||
count = 0;
|
||||
do {
|
||||
if (index !== undefined) {
|
||||
newTidyText = tidyText + '-' + count;
|
||||
if (elements[i].hasAttribute('id')) {
|
||||
elementID = elements[i].getAttribute('id');
|
||||
} else if (elements[i].hasAttribute('data-anchor-id')) {
|
||||
elementID = elements[i].getAttribute('data-anchor-id');
|
||||
} else {
|
||||
tidyText = this.urlify(elements[i].textContent);
|
||||
|
||||
// Compare our generated ID to existing IDs (and increment it if needed)
|
||||
// before we add it to the page.
|
||||
newTidyText = tidyText;
|
||||
count = 0;
|
||||
do {
|
||||
if (index !== undefined) {
|
||||
newTidyText = tidyText + '-' + count;
|
||||
}
|
||||
|
||||
index = idList.indexOf(newTidyText);
|
||||
count += 1;
|
||||
} while (index !== -1);
|
||||
index = undefined;
|
||||
idList.push(newTidyText);
|
||||
|
||||
elements[i].setAttribute('id', newTidyText);
|
||||
elementID = newTidyText;
|
||||
}
|
||||
|
||||
readableID = elementID.replace(/-/g, ' ');
|
||||
|
||||
// The following code builds the following DOM structure in a more effiecient (albeit opaque) way.
|
||||
// '<a class="anchorjs-link ' + this.options.class + '" href="#' + elementID + '" aria-label="Anchor link for: ' + readableID + '" data-anchorjs-icon="' + this.options.icon + '"></a>';
|
||||
anchor = document.createElement('a');
|
||||
anchor.className = 'anchorjs-link ' + this.options.class;
|
||||
anchor.href = '#' + elementID;
|
||||
anchor.setAttribute('aria-label', 'Anchor link for: ' + readableID);
|
||||
anchor.setAttribute('data-anchorjs-icon', this.options.icon);
|
||||
|
||||
if (visibleOptionToUse === 'always') {
|
||||
anchor.style.opacity = '1';
|
||||
}
|
||||
|
||||
if (this.options.icon === '\ue9cb') {
|
||||
anchor.style.font = '1em/1 anchorjs-icons';
|
||||
|
||||
// We set lineHeight = 1 here because the `anchorjs-icons` font family could otherwise affect the
|
||||
// height of the heading. This isn't the case for icons with `placement: left`, so we restore
|
||||
// line-height: inherit in that case, ensuring they remain positioned correctly. For more info,
|
||||
// see https://github.com/bryanbraun/anchorjs/issues/39.
|
||||
if (this.options.placement === 'left') {
|
||||
anchor.style.lineHeight = 'inherit';
|
||||
}
|
||||
// .indexOf is supported in IE9+.
|
||||
index = idList.indexOf(newTidyText);
|
||||
count += 1;
|
||||
} while (index !== -1);
|
||||
index = undefined;
|
||||
idList.push(newTidyText);
|
||||
}
|
||||
|
||||
// Assign it to our element.
|
||||
// Currently the setAttribute element is only supported in IE9 and above.
|
||||
elements[i].setAttribute('id', newTidyText);
|
||||
|
||||
elementID = newTidyText;
|
||||
if (this.options.placement === 'left') {
|
||||
anchor.style.position = 'absolute';
|
||||
anchor.style.marginLeft = '-1em';
|
||||
anchor.style.paddingRight = '0.5em';
|
||||
elements[i].insertBefore(anchor, elements[i].firstChild);
|
||||
} else {
|
||||
// if the option provided is `right` (or anything else).
|
||||
anchor.style.paddingLeft = '0.375em';
|
||||
elements[i].appendChild(anchor);
|
||||
}
|
||||
}
|
||||
|
||||
readableID = elementID.replace(/-/g, ' ');
|
||||
for (i = 0; i < indexesToDrop.length; i++) {
|
||||
elements.splice(indexesToDrop[i] - i, 1);
|
||||
}
|
||||
this.elements = this.elements.concat(elements);
|
||||
|
||||
// The following code builds the following DOM structure in a more effiecient (albeit opaque) way.
|
||||
// '<a class="anchorjs-link ' + this.options.class + '" href="#' + elementID + '" aria-label="Anchor link for: ' + readableID + '" data-anchorjs-icon="' + this.options.icon + '"></a>';
|
||||
anchor = document.createElement('a');
|
||||
anchor.className = 'anchorjs-link ' + this.options.class;
|
||||
anchor.href = '#' + elementID;
|
||||
anchor.setAttribute('aria-label', 'Anchor link for: ' + readableID);
|
||||
anchor.setAttribute('data-anchorjs-icon', this.options.icon);
|
||||
return this;
|
||||
};
|
||||
|
||||
if (this.options.visible === 'always') {
|
||||
anchor.style.opacity = '1';
|
||||
/**
|
||||
* Removes all anchorjs-links from elements targed by the selector.
|
||||
* @param {String|Array|Nodelist} selector - A CSS selector string targeting elements with anchor links,
|
||||
* OR a nodeList / array containing the DOM elements.
|
||||
* @returns {this} - The AnchorJS object
|
||||
*/
|
||||
this.remove = function(selector) {
|
||||
var index,
|
||||
domAnchor,
|
||||
elements = _getElements(selector);
|
||||
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
domAnchor = elements[i].querySelector('.anchorjs-link');
|
||||
if (domAnchor) {
|
||||
// Drop the element from our main list, if it's in there.
|
||||
index = this.elements.indexOf(elements[i]);
|
||||
if (index !== -1) {
|
||||
this.elements.splice(index, 1);
|
||||
}
|
||||
// Remove the anchor from the DOM.
|
||||
elements[i].removeChild(domAnchor);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes all anchorjs links. Mostly used for tests.
|
||||
*/
|
||||
this.removeAll = function() {
|
||||
this.remove(this.elements);
|
||||
};
|
||||
|
||||
/**
|
||||
* Urlify - Refine text so it makes a good ID.
|
||||
*
|
||||
* To do this, we remove apostrophes, replace nonsafe characters with hyphens,
|
||||
* remove extra hyphens, truncate, trim hyphens, and make lowercase.
|
||||
*
|
||||
* @param {String} text - Any text. Usually pulled from the webpage element we are linking to.
|
||||
* @returns {String} - hyphen-delimited text for use in IDs and URLs.
|
||||
*/
|
||||
this.urlify = function(text) {
|
||||
// Regex for finding the nonsafe URL characters (many need escaping): & +$,:;=?@"#{}|^~[`%!'<>]./()*\
|
||||
var nonsafeChars = /[& +$,:;=?@"#{}|^~[`%!'<>\]\.\/\(\)\*\\]/g,
|
||||
urlText;
|
||||
|
||||
// The reason we include this _applyRemainingDefaultOptions is so urlify can be called independently,
|
||||
// even after setting options. This can be useful for tests or other applications.
|
||||
if (!this.options.truncate) {
|
||||
_applyRemainingDefaultOptions(this.options);
|
||||
}
|
||||
|
||||
if (this.options.icon === '\ue9cb') {
|
||||
anchor.style.fontFamily = 'anchorjs-icons';
|
||||
anchor.style.fontStyle = 'normal';
|
||||
anchor.style.fontVariant = 'normal';
|
||||
anchor.style.fontWeight = 'normal';
|
||||
anchor.style.lineHeight = 1;
|
||||
}
|
||||
// Note: we trim hyphens after truncating because truncating can cause dangling hyphens.
|
||||
// Example string: // " ⚡⚡ Don't forget: URL fragments should be i18n-friendly, hyphenated, short, and clean."
|
||||
urlText = text
|
||||
.trim() // "⚡⚡ Don't forget: URL fragments should be i18n-friendly, hyphenated, short, and clean."
|
||||
.replace(/\'/gi, '') // "⚡⚡ Dont forget: URL fragments should be i18n-friendly, hyphenated, short, and clean."
|
||||
.replace(nonsafeChars, '-') // "⚡⚡-Dont-forget--URL-fragments-should-be-i18n-friendly--hyphenated--short--and-clean-"
|
||||
.replace(/-{2,}/g, '-') // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated-short-and-clean-"
|
||||
.substring(0, this.options.truncate) // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated-"
|
||||
.replace(/^-+|-+$/gm, '') // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated"
|
||||
.toLowerCase(); // "⚡⚡-dont-forget-url-fragments-should-be-i18n-friendly-hyphenated"
|
||||
|
||||
if (this.options.placement === 'left') {
|
||||
anchor.style.position = 'absolute';
|
||||
anchor.style.marginLeft = '-1em';
|
||||
anchor.style.paddingRight = '0.5em';
|
||||
elements[i].insertBefore(anchor, elements[i].firstChild);
|
||||
} else { // if the option provided is `right` (or anything else).
|
||||
anchor.style.paddingLeft = '0.375em';
|
||||
elements[i].appendChild(anchor);
|
||||
return urlText;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if this element already has an AnchorJS link on it.
|
||||
* Uses this technique: http://stackoverflow.com/a/5898748/1154642
|
||||
* @param {HTMLElemnt} el - a DOM node
|
||||
* @returns {Boolean} true/false
|
||||
*/
|
||||
this.hasAnchorJSLink = function(el) {
|
||||
var hasLeftAnchor =
|
||||
el.firstChild &&
|
||||
(' ' + el.firstChild.className + ' ').indexOf(' anchorjs-link ') > -1,
|
||||
hasRightAnchor =
|
||||
el.lastChild &&
|
||||
(' ' + el.lastChild.className + ' ').indexOf(' anchorjs-link ') > -1;
|
||||
|
||||
return hasLeftAnchor || hasRightAnchor || false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Turns a selector, nodeList, or array of elements into an array of elements (so we can use array methods).
|
||||
* It also throws errors on any other inputs. Used to handle inputs to .add and .remove.
|
||||
* @param {String|Array|Nodelist} input - A CSS selector string targeting elements with anchor links,
|
||||
* OR a nodeList / array containing the DOM elements.
|
||||
* @returns {Array} - An array containing the elements we want.
|
||||
*/
|
||||
function _getElements(input) {
|
||||
var elements;
|
||||
if (typeof input === 'string' || input instanceof String) {
|
||||
// See https://davidwalsh.name/nodelist-array for the technique transforming nodeList -> Array.
|
||||
elements = [].slice.call(document.querySelectorAll(input));
|
||||
// I checked the 'input instanceof NodeList' test in IE9 and modern browsers and it worked for me.
|
||||
} else if (Array.isArray(input) || input instanceof NodeList) {
|
||||
elements = [].slice.call(input);
|
||||
} else {
|
||||
throw new Error('The selector provided to AnchorJS was invalid.');
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
this.remove = function(selector) {
|
||||
var domAnchor,
|
||||
elements = document.querySelectorAll(selector);
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
domAnchor = elements[i].querySelector('.anchorjs-link');
|
||||
if (domAnchor) {
|
||||
elements[i].removeChild(domAnchor);
|
||||
/**
|
||||
* _addBaselineStyles
|
||||
* Adds baseline styles to the page, used by all AnchorJS links irregardless of configuration.
|
||||
*/
|
||||
function _addBaselineStyles() {
|
||||
// We don't want to add global baseline styles if they've been added before.
|
||||
if (document.head.querySelector('style.anchorjs') !== null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
this._addBaselineStyles = function() {
|
||||
// We don't want to add global baseline styles if they've been added before.
|
||||
if (document.head.querySelector('style.anchorjs') !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var style = document.createElement('style'),
|
||||
var style = document.createElement('style'),
|
||||
linkRule =
|
||||
' .anchorjs-link {' +
|
||||
' opacity: 0;' +
|
||||
' text-decoration: none;' +
|
||||
' -webkit-font-smoothing: antialiased;' +
|
||||
' -moz-osx-font-smoothing: grayscale;' +
|
||||
' }',
|
||||
' .anchorjs-link {' +
|
||||
' opacity: 0;' +
|
||||
' text-decoration: none;' +
|
||||
' -webkit-font-smoothing: antialiased;' +
|
||||
' -moz-osx-font-smoothing: grayscale;' +
|
||||
' }',
|
||||
hoverRule =
|
||||
' *:hover > .anchorjs-link,' +
|
||||
' .anchorjs-link:focus {' +
|
||||
' opacity: 1;' +
|
||||
' }',
|
||||
' *:hover > .anchorjs-link,' +
|
||||
' .anchorjs-link:focus {' +
|
||||
' opacity: 1;' +
|
||||
' }',
|
||||
anchorjsLinkFontFace =
|
||||
' @font-face {' +
|
||||
' font-family: "anchorjs-icons";' +
|
||||
' font-style: normal;' +
|
||||
' font-weight: normal;' + // Icon from icomoon; 10px wide & 10px tall; 2 empty below & 4 above
|
||||
' src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBTUAAAC8AAAAYGNtYXAWi9QdAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5Zgq29TcAAAF4AAABNGhlYWQEZM3pAAACrAAAADZoaGVhBhUDxgAAAuQAAAAkaG10eASAADEAAAMIAAAAFGxvY2EAKACuAAADHAAAAAxtYXhwAAgAVwAAAygAAAAgbmFtZQ5yJ3cAAANIAAAB2nBvc3QAAwAAAAAFJAAAACAAAwJAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpywPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6cv//f//AAAAAAAg6cv//f//AAH/4xY5AAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAACADEARAJTAsAAKwBUAAABIiYnJjQ/AT4BMzIWFxYUDwEGIicmND8BNjQnLgEjIgYPAQYUFxYUBw4BIwciJicmND8BNjIXFhQPAQYUFx4BMzI2PwE2NCcmNDc2MhcWFA8BDgEjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAEAAAABAACiToc1Xw889QALBAAAAAAA0XnFFgAAAADRecUWAAAAAAJTAsAAAAAIAAIAAAAAAAAAAQAAA8D/wAAABAAAAAAAAlMAAQAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAACAAAAAoAAMQAAAAAACgAUAB4AmgABAAAABQBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEADgAAAAEAAAAAAAIABwCfAAEAAAAAAAMADgBLAAEAAAAAAAQADgC0AAEAAAAAAAUACwAqAAEAAAAAAAYADgB1AAEAAAAAAAoAGgDeAAMAAQQJAAEAHAAOAAMAAQQJAAIADgCmAAMAAQQJAAMAHABZAAMAAQQJAAQAHADCAAMAAQQJAAUAFgA1AAMAAQQJAAYAHACDAAMAAQQJAAoANAD4YW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzVmVyc2lvbiAxLjAAVgBlAHIAcwBpAG8AbgAgADEALgAwYW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzYW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzUmVndWxhcgBSAGUAZwB1AGwAYQByYW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzRm9udCBnZW5lcmF0ZWQgYnkgSWNvTW9vbi4ARgBvAG4AdAAgAGcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format("truetype");' +
|
||||
' }',
|
||||
' @font-face {' +
|
||||
' font-family: "anchorjs-icons";' + // Icon from icomoon; 10px wide & 10px tall; 2 empty below & 4 above
|
||||
' src: url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype");' +
|
||||
' }',
|
||||
pseudoElContent =
|
||||
' [data-anchorjs-icon]::after {' +
|
||||
' content: attr(data-anchorjs-icon);' +
|
||||
' }',
|
||||
' [data-anchorjs-icon]::after {' +
|
||||
' content: attr(data-anchorjs-icon);' +
|
||||
' }',
|
||||
firstStyleEl;
|
||||
|
||||
style.className = 'anchorjs';
|
||||
style.appendChild(document.createTextNode('')); // Necessary for Webkit.
|
||||
style.className = 'anchorjs';
|
||||
style.appendChild(document.createTextNode('')); // Necessary for Webkit.
|
||||
|
||||
// We place it in the head with the other style tags, if possible, so as to
|
||||
// not look out of place. We insert before the others so these styles can be
|
||||
// overridden if necessary.
|
||||
firstStyleEl = document.head.querySelector('[rel="stylesheet"], style');
|
||||
if (firstStyleEl === undefined) {
|
||||
document.head.appendChild(style);
|
||||
} else {
|
||||
document.head.insertBefore(style, firstStyleEl);
|
||||
// We place it in the head with the other style tags, if possible, so as to
|
||||
// not look out of place. We insert before the others so these styles can be
|
||||
// overridden if necessary.
|
||||
firstStyleEl = document.head.querySelector('[rel="stylesheet"], style');
|
||||
if (firstStyleEl === undefined) {
|
||||
document.head.appendChild(style);
|
||||
} else {
|
||||
document.head.insertBefore(style, firstStyleEl);
|
||||
}
|
||||
|
||||
style.sheet.insertRule(linkRule, style.sheet.cssRules.length);
|
||||
style.sheet.insertRule(hoverRule, style.sheet.cssRules.length);
|
||||
style.sheet.insertRule(pseudoElContent, style.sheet.cssRules.length);
|
||||
style.sheet.insertRule(anchorjsLinkFontFace, style.sheet.cssRules.length);
|
||||
}
|
||||
}
|
||||
|
||||
style.sheet.insertRule(linkRule, style.sheet.cssRules.length);
|
||||
style.sheet.insertRule(hoverRule, style.sheet.cssRules.length);
|
||||
style.sheet.insertRule(pseudoElContent, style.sheet.cssRules.length);
|
||||
style.sheet.insertRule(anchorjsLinkFontFace, style.sheet.cssRules.length);
|
||||
};
|
||||
}
|
||||
|
||||
var anchors = new AnchorJS();
|
||||
return AnchorJS;
|
||||
});
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
.input {
|
||||
font-family: inherit;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 2rem;
|
||||
padding: .5rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid #ccc;
|
||||
font-size: .875rem;
|
||||
border-radius: 3px;
|
||||
box-sizing: border-box;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,93 @@
|
|||
Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
|
||||
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,23 @@
|
|||
@font-face{
|
||||
font-family: 'Source Code Pro';
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
src: url('EOT/SourceCodePro-Regular.eot') format('embedded-opentype'),
|
||||
url('WOFF2/TTF/SourceCodePro-Regular.ttf.woff2') format('woff2'),
|
||||
url('WOFF/OTF/SourceCodePro-Regular.otf.woff') format('woff'),
|
||||
url('OTF/SourceCodePro-Regular.otf') format('opentype'),
|
||||
url('TTF/SourceCodePro-Regular.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face{
|
||||
font-family: 'Source Code Pro';
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
src: url('EOT/SourceCodePro-Bold.eot') format('embedded-opentype'),
|
||||
url('WOFF2/TTF/SourceCodePro-Bold.ttf.woff2') format('woff2'),
|
||||
url('WOFF/OTF/SourceCodePro-Bold.otf.woff') format('woff'),
|
||||
url('OTF/SourceCodePro-Bold.otf') format('opentype'),
|
||||
url('TTF/SourceCodePro-Bold.ttf') format('truetype');
|
||||
}
|
|
@ -2,39 +2,167 @@
|
|||
|
||||
// add anchor links to headers
|
||||
anchors.options.placement = 'left';
|
||||
anchors.add().remove('.no-anchor');
|
||||
anchors.add('h3');
|
||||
|
||||
// Filter UI
|
||||
var tocElements = document.getElementById('toc').getElementsByTagName('a');
|
||||
document.getElementById('filter-input').addEventListener('keyup', function(e) {
|
||||
var tocElements = document.getElementById('toc').getElementsByTagName('li');
|
||||
|
||||
var i, element;
|
||||
document.getElementById('filter-input').addEventListener('keyup', function(e) {
|
||||
var i, element, children;
|
||||
|
||||
// enter key
|
||||
if (e.keyCode === 13) {
|
||||
// go to the first displayed item in the toc
|
||||
for (i = 0; i < tocElements.length; i++) {
|
||||
element = tocElements[i];
|
||||
if (!element.classList.contains('hide')) {
|
||||
location.replace(element.href);
|
||||
if (!element.classList.contains('display-none')) {
|
||||
location.replace(element.firstChild.href);
|
||||
return e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var match = function() { return true; },
|
||||
value = this.value.toLowerCase();
|
||||
var match = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
var value = this.value.toLowerCase();
|
||||
|
||||
if (!value.match(/^\s*$/)) {
|
||||
match = function(text) { return text.toLowerCase().indexOf(value) !== -1; };
|
||||
match = function(element) {
|
||||
var html = element.firstChild.innerHTML;
|
||||
return html && html.toLowerCase().indexOf(value) !== -1;
|
||||
};
|
||||
}
|
||||
|
||||
for (i = 0; i < tocElements.length; i++) {
|
||||
element = tocElements[i];
|
||||
if (match(element.innerHTML)) {
|
||||
element.classList.remove('hide');
|
||||
children = Array.from(element.getElementsByTagName('li'));
|
||||
if (match(element) || children.some(match)) {
|
||||
element.classList.remove('display-none');
|
||||
} else {
|
||||
element.classList.add('hide');
|
||||
element.classList.add('display-none');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var items = document.getElementsByClassName('toggle-sibling');
|
||||
for (var j = 0; j < items.length; j++) {
|
||||
items[j].addEventListener('click', toggleSibling);
|
||||
}
|
||||
|
||||
function toggleSibling() {
|
||||
var stepSibling = this.parentNode.getElementsByClassName('toggle-target')[0];
|
||||
var icon = this.getElementsByClassName('icon')[0];
|
||||
var klass = 'display-none';
|
||||
if (stepSibling.classList.contains(klass)) {
|
||||
stepSibling.classList.remove(klass);
|
||||
icon.innerHTML = '▾';
|
||||
} else {
|
||||
stepSibling.classList.add(klass);
|
||||
icon.innerHTML = '▸';
|
||||
}
|
||||
}
|
||||
|
||||
function showHashTarget(targetId) {
|
||||
if (targetId) {
|
||||
var hashTarget = document.getElementById(targetId);
|
||||
// new target is hidden
|
||||
if (
|
||||
hashTarget &&
|
||||
hashTarget.offsetHeight === 0 &&
|
||||
hashTarget.parentNode.parentNode.classList.contains('display-none')
|
||||
) {
|
||||
hashTarget.parentNode.parentNode.classList.remove('display-none');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scrollIntoView(targetId) {
|
||||
// Only scroll to element if we don't have a stored scroll position.
|
||||
if (targetId && !history.state) {
|
||||
var hashTarget = document.getElementById(targetId);
|
||||
if (hashTarget) {
|
||||
hashTarget.scrollIntoView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function gotoCurrentTarget() {
|
||||
showHashTarget(location.hash.substring(1));
|
||||
scrollIntoView(location.hash.substring(1));
|
||||
}
|
||||
|
||||
window.addEventListener('hashchange', gotoCurrentTarget);
|
||||
gotoCurrentTarget();
|
||||
|
||||
var toclinks = document.getElementsByClassName('pre-open');
|
||||
for (var k = 0; k < toclinks.length; k++) {
|
||||
toclinks[k].addEventListener('mousedown', preOpen, false);
|
||||
}
|
||||
|
||||
function preOpen() {
|
||||
showHashTarget(this.hash.substring(1));
|
||||
}
|
||||
|
||||
var split_left = document.querySelector('#split-left');
|
||||
var split_right = document.querySelector('#split-right');
|
||||
var split_parent = split_left.parentNode;
|
||||
var cw_with_sb = split_left.clientWidth;
|
||||
split_left.style.overflow = 'hidden';
|
||||
var cw_without_sb = split_left.clientWidth;
|
||||
split_left.style.overflow = '';
|
||||
|
||||
Split(['#split-left', '#split-right'], {
|
||||
elementStyle: function(dimension, size, gutterSize) {
|
||||
return {
|
||||
'flex-basis': 'calc(' + size + '% - ' + gutterSize + 'px)'
|
||||
};
|
||||
},
|
||||
gutterStyle: function(dimension, gutterSize) {
|
||||
return {
|
||||
'flex-basis': gutterSize + 'px'
|
||||
};
|
||||
},
|
||||
gutterSize: 20,
|
||||
sizes: [33, 67]
|
||||
});
|
||||
|
||||
// Chrome doesn't remember scroll position properly so do it ourselves.
|
||||
// Also works on Firefox and Edge.
|
||||
|
||||
function updateState() {
|
||||
history.replaceState(
|
||||
{
|
||||
left_top: split_left.scrollTop,
|
||||
right_top: split_right.scrollTop
|
||||
},
|
||||
document.title
|
||||
);
|
||||
}
|
||||
|
||||
function loadState(ev) {
|
||||
if (ev) {
|
||||
// Edge doesn't replace change history.state on popstate.
|
||||
history.replaceState(ev.state, document.title);
|
||||
}
|
||||
if (history.state) {
|
||||
split_left.scrollTop = history.state.left_top;
|
||||
split_right.scrollTop = history.state.right_top;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
// Restore after Firefox scrolls to hash.
|
||||
setTimeout(function() {
|
||||
loadState();
|
||||
// Update with initial scroll position.
|
||||
updateState();
|
||||
// Update scroll positions only after we've loaded because Firefox
|
||||
// emits an initial scroll event with 0.
|
||||
split_left.addEventListener('scroll', updateState);
|
||||
split_right.addEventListener('scroll', updateState);
|
||||
}, 1);
|
||||
});
|
||||
|
||||
window.addEventListener('popstate', loadState);
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
.gutter {
|
||||
background-color: #f5f5f5;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50%;
|
||||
}
|
||||
|
||||
.gutter.gutter-vertical {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII=');
|
||||
cursor: ns-resize;
|
||||
}
|
||||
|
||||
.gutter.gutter-horizontal {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
|
||||
cursor: ew-resize;
|
||||
}
|
|
@ -0,0 +1,586 @@
|
|||
/*! Split.js - v1.3.5 */
|
||||
// https://github.com/nathancahill/Split.js
|
||||
// Copyright (c) 2017 Nathan Cahill; Licensed MIT
|
||||
|
||||
(function(global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined'
|
||||
? (module.exports = factory())
|
||||
: typeof define === 'function' && define.amd
|
||||
? define(factory)
|
||||
: (global.Split = factory());
|
||||
})(this, function() {
|
||||
'use strict';
|
||||
// The programming goals of Split.js are to deliver readable, understandable and
|
||||
// maintainable code, while at the same time manually optimizing for tiny minified file size,
|
||||
// browser compatibility without additional requirements, graceful fallback (IE8 is supported)
|
||||
// and very few assumptions about the user's page layout.
|
||||
var global = window;
|
||||
var document = global.document;
|
||||
|
||||
// Save a couple long function names that are used frequently.
|
||||
// This optimization saves around 400 bytes.
|
||||
var addEventListener = 'addEventListener';
|
||||
var removeEventListener = 'removeEventListener';
|
||||
var getBoundingClientRect = 'getBoundingClientRect';
|
||||
var NOOP = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
// Figure out if we're in IE8 or not. IE8 will still render correctly,
|
||||
// but will be static instead of draggable.
|
||||
var isIE8 = global.attachEvent && !global[addEventListener];
|
||||
|
||||
// This library only needs two helper functions:
|
||||
//
|
||||
// The first determines which prefixes of CSS calc we need.
|
||||
// We only need to do this once on startup, when this anonymous function is called.
|
||||
//
|
||||
// Tests -webkit, -moz and -o prefixes. Modified from StackOverflow:
|
||||
// http://stackoverflow.com/questions/16625140/js-feature-detection-to-detect-the-usage-of-webkit-calc-over-calc/16625167#16625167
|
||||
var calc =
|
||||
['', '-webkit-', '-moz-', '-o-']
|
||||
.filter(function(prefix) {
|
||||
var el = document.createElement('div');
|
||||
el.style.cssText = 'width:' + prefix + 'calc(9px)';
|
||||
|
||||
return !!el.style.length;
|
||||
})
|
||||
.shift() + 'calc';
|
||||
|
||||
// The second helper function allows elements and string selectors to be used
|
||||
// interchangeably. In either case an element is returned. This allows us to
|
||||
// do `Split([elem1, elem2])` as well as `Split(['#id1', '#id2'])`.
|
||||
var elementOrSelector = function(el) {
|
||||
if (typeof el === 'string' || el instanceof String) {
|
||||
return document.querySelector(el);
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
// The main function to initialize a split. Split.js thinks about each pair
|
||||
// of elements as an independant pair. Dragging the gutter between two elements
|
||||
// only changes the dimensions of elements in that pair. This is key to understanding
|
||||
// how the following functions operate, since each function is bound to a pair.
|
||||
//
|
||||
// A pair object is shaped like this:
|
||||
//
|
||||
// {
|
||||
// a: DOM element,
|
||||
// b: DOM element,
|
||||
// aMin: Number,
|
||||
// bMin: Number,
|
||||
// dragging: Boolean,
|
||||
// parent: DOM element,
|
||||
// isFirst: Boolean,
|
||||
// isLast: Boolean,
|
||||
// direction: 'horizontal' | 'vertical'
|
||||
// }
|
||||
//
|
||||
// The basic sequence:
|
||||
//
|
||||
// 1. Set defaults to something sane. `options` doesn't have to be passed at all.
|
||||
// 2. Initialize a bunch of strings based on the direction we're splitting.
|
||||
// A lot of the behavior in the rest of the library is paramatized down to
|
||||
// rely on CSS strings and classes.
|
||||
// 3. Define the dragging helper functions, and a few helpers to go with them.
|
||||
// 4. Loop through the elements while pairing them off. Every pair gets an
|
||||
// `pair` object, a gutter, and special isFirst/isLast properties.
|
||||
// 5. Actually size the pair elements, insert gutters and attach event listeners.
|
||||
var Split = function(ids, options) {
|
||||
if (options === void 0) options = {};
|
||||
|
||||
var dimension;
|
||||
var clientDimension;
|
||||
var clientAxis;
|
||||
var position;
|
||||
var paddingA;
|
||||
var paddingB;
|
||||
var elements;
|
||||
|
||||
// All DOM elements in the split should have a common parent. We can grab
|
||||
// the first elements parent and hope users read the docs because the
|
||||
// behavior will be whacky otherwise.
|
||||
var parent = elementOrSelector(ids[0]).parentNode;
|
||||
var parentFlexDirection = global.getComputedStyle(parent).flexDirection;
|
||||
|
||||
// Set default options.sizes to equal percentages of the parent element.
|
||||
var sizes =
|
||||
options.sizes ||
|
||||
ids.map(function() {
|
||||
return 100 / ids.length;
|
||||
});
|
||||
|
||||
// Standardize minSize to an array if it isn't already. This allows minSize
|
||||
// to be passed as a number.
|
||||
var minSize = options.minSize !== undefined ? options.minSize : 100;
|
||||
var minSizes = Array.isArray(minSize)
|
||||
? minSize
|
||||
: ids.map(function() {
|
||||
return minSize;
|
||||
});
|
||||
var gutterSize = options.gutterSize !== undefined ? options.gutterSize : 10;
|
||||
var snapOffset = options.snapOffset !== undefined ? options.snapOffset : 30;
|
||||
var direction = options.direction || 'horizontal';
|
||||
var cursor =
|
||||
options.cursor ||
|
||||
(direction === 'horizontal' ? 'ew-resize' : 'ns-resize');
|
||||
var gutter =
|
||||
options.gutter ||
|
||||
function(i, gutterDirection) {
|
||||
var gut = document.createElement('div');
|
||||
gut.className = 'gutter gutter-' + gutterDirection;
|
||||
return gut;
|
||||
};
|
||||
var elementStyle =
|
||||
options.elementStyle ||
|
||||
function(dim, size, gutSize) {
|
||||
var style = {};
|
||||
|
||||
if (typeof size !== 'string' && !(size instanceof String)) {
|
||||
if (!isIE8) {
|
||||
style[dim] = calc + '(' + size + '% - ' + gutSize + 'px)';
|
||||
} else {
|
||||
style[dim] = size + '%';
|
||||
}
|
||||
} else {
|
||||
style[dim] = size;
|
||||
}
|
||||
|
||||
return style;
|
||||
};
|
||||
var gutterStyle =
|
||||
options.gutterStyle ||
|
||||
function(dim, gutSize) {
|
||||
return (obj = {}), (obj[dim] = gutSize + 'px'), obj;
|
||||
var obj;
|
||||
};
|
||||
|
||||
// 2. Initialize a bunch of strings based on the direction we're splitting.
|
||||
// A lot of the behavior in the rest of the library is paramatized down to
|
||||
// rely on CSS strings and classes.
|
||||
if (direction === 'horizontal') {
|
||||
dimension = 'width';
|
||||
clientDimension = 'clientWidth';
|
||||
clientAxis = 'clientX';
|
||||
position = 'left';
|
||||
paddingA = 'paddingLeft';
|
||||
paddingB = 'paddingRight';
|
||||
} else if (direction === 'vertical') {
|
||||
dimension = 'height';
|
||||
clientDimension = 'clientHeight';
|
||||
clientAxis = 'clientY';
|
||||
position = 'top';
|
||||
paddingA = 'paddingTop';
|
||||
paddingB = 'paddingBottom';
|
||||
}
|
||||
|
||||
// 3. Define the dragging helper functions, and a few helpers to go with them.
|
||||
// Each helper is bound to a pair object that contains it's metadata. This
|
||||
// also makes it easy to store references to listeners that that will be
|
||||
// added and removed.
|
||||
//
|
||||
// Even though there are no other functions contained in them, aliasing
|
||||
// this to self saves 50 bytes or so since it's used so frequently.
|
||||
//
|
||||
// The pair object saves metadata like dragging state, position and
|
||||
// event listener references.
|
||||
|
||||
function setElementSize(el, size, gutSize) {
|
||||
// Split.js allows setting sizes via numbers (ideally), or if you must,
|
||||
// by string, like '300px'. This is less than ideal, because it breaks
|
||||
// the fluid layout that `calc(% - px)` provides. You're on your own if you do that,
|
||||
// make sure you calculate the gutter size by hand.
|
||||
var style = elementStyle(dimension, size, gutSize);
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
Object.keys(style).forEach(function(prop) {
|
||||
return (el.style[prop] = style[prop]);
|
||||
});
|
||||
}
|
||||
|
||||
function setGutterSize(gutterElement, gutSize) {
|
||||
var style = gutterStyle(dimension, gutSize);
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
Object.keys(style).forEach(function(prop) {
|
||||
return (gutterElement.style[prop] = style[prop]);
|
||||
});
|
||||
}
|
||||
|
||||
// Actually adjust the size of elements `a` and `b` to `offset` while dragging.
|
||||
// calc is used to allow calc(percentage + gutterpx) on the whole split instance,
|
||||
// which allows the viewport to be resized without additional logic.
|
||||
// Element a's size is the same as offset. b's size is total size - a size.
|
||||
// Both sizes are calculated from the initial parent percentage,
|
||||
// then the gutter size is subtracted.
|
||||
function adjust(offset) {
|
||||
var a = elements[this.a];
|
||||
var b = elements[this.b];
|
||||
var percentage = a.size + b.size;
|
||||
|
||||
a.size = offset / this.size * percentage;
|
||||
b.size = percentage - offset / this.size * percentage;
|
||||
|
||||
setElementSize(a.element, a.size, this.aGutterSize);
|
||||
setElementSize(b.element, b.size, this.bGutterSize);
|
||||
}
|
||||
|
||||
// drag, where all the magic happens. The logic is really quite simple:
|
||||
//
|
||||
// 1. Ignore if the pair is not dragging.
|
||||
// 2. Get the offset of the event.
|
||||
// 3. Snap offset to min if within snappable range (within min + snapOffset).
|
||||
// 4. Actually adjust each element in the pair to offset.
|
||||
//
|
||||
// ---------------------------------------------------------------------
|
||||
// | | <- a.minSize || b.minSize -> | |
|
||||
// | | | <- this.snapOffset || this.snapOffset -> | | |
|
||||
// | | | || | | |
|
||||
// | | | || | | |
|
||||
// ---------------------------------------------------------------------
|
||||
// | <- this.start this.size -> |
|
||||
function drag(e) {
|
||||
var offset;
|
||||
|
||||
if (!this.dragging) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the offset of the event from the first side of the
|
||||
// pair `this.start`. Supports touch events, but not multitouch, so only the first
|
||||
// finger `touches[0]` is counted.
|
||||
if ('touches' in e) {
|
||||
offset = e.touches[0][clientAxis] - this.start;
|
||||
} else {
|
||||
offset = e[clientAxis] - this.start;
|
||||
}
|
||||
|
||||
// If within snapOffset of min or max, set offset to min or max.
|
||||
// snapOffset buffers a.minSize and b.minSize, so logic is opposite for both.
|
||||
// Include the appropriate gutter sizes to prevent overflows.
|
||||
if (offset <= elements[this.a].minSize + snapOffset + this.aGutterSize) {
|
||||
offset = elements[this.a].minSize + this.aGutterSize;
|
||||
} else if (
|
||||
offset >=
|
||||
this.size - (elements[this.b].minSize + snapOffset + this.bGutterSize)
|
||||
) {
|
||||
offset = this.size - (elements[this.b].minSize + this.bGutterSize);
|
||||
}
|
||||
|
||||
// Actually adjust the size.
|
||||
adjust.call(this, offset);
|
||||
|
||||
// Call the drag callback continously. Don't do anything too intensive
|
||||
// in this callback.
|
||||
if (options.onDrag) {
|
||||
options.onDrag();
|
||||
}
|
||||
}
|
||||
|
||||
// Cache some important sizes when drag starts, so we don't have to do that
|
||||
// continously:
|
||||
//
|
||||
// `size`: The total size of the pair. First + second + first gutter + second gutter.
|
||||
// `start`: The leading side of the first element.
|
||||
//
|
||||
// ------------------------------------------------
|
||||
// | aGutterSize -> ||| |
|
||||
// | ||| |
|
||||
// | ||| |
|
||||
// | ||| <- bGutterSize |
|
||||
// ------------------------------------------------
|
||||
// | <- start size -> |
|
||||
function calculateSizes() {
|
||||
// Figure out the parent size minus padding.
|
||||
var a = elements[this.a].element;
|
||||
var b = elements[this.b].element;
|
||||
|
||||
this.size =
|
||||
a[getBoundingClientRect]()[dimension] +
|
||||
b[getBoundingClientRect]()[dimension] +
|
||||
this.aGutterSize +
|
||||
this.bGutterSize;
|
||||
this.start = a[getBoundingClientRect]()[position];
|
||||
}
|
||||
|
||||
// stopDragging is very similar to startDragging in reverse.
|
||||
function stopDragging() {
|
||||
var self = this;
|
||||
var a = elements[self.a].element;
|
||||
var b = elements[self.b].element;
|
||||
|
||||
if (self.dragging && options.onDragEnd) {
|
||||
options.onDragEnd();
|
||||
}
|
||||
|
||||
self.dragging = false;
|
||||
|
||||
// Remove the stored event listeners. This is why we store them.
|
||||
global[removeEventListener]('mouseup', self.stop);
|
||||
global[removeEventListener]('touchend', self.stop);
|
||||
global[removeEventListener]('touchcancel', self.stop);
|
||||
|
||||
self.parent[removeEventListener]('mousemove', self.move);
|
||||
self.parent[removeEventListener]('touchmove', self.move);
|
||||
|
||||
// Delete them once they are removed. I think this makes a difference
|
||||
// in memory usage with a lot of splits on one page. But I don't know for sure.
|
||||
delete self.stop;
|
||||
delete self.move;
|
||||
|
||||
a[removeEventListener]('selectstart', NOOP);
|
||||
a[removeEventListener]('dragstart', NOOP);
|
||||
b[removeEventListener]('selectstart', NOOP);
|
||||
b[removeEventListener]('dragstart', NOOP);
|
||||
|
||||
a.style.userSelect = '';
|
||||
a.style.webkitUserSelect = '';
|
||||
a.style.MozUserSelect = '';
|
||||
a.style.pointerEvents = '';
|
||||
|
||||
b.style.userSelect = '';
|
||||
b.style.webkitUserSelect = '';
|
||||
b.style.MozUserSelect = '';
|
||||
b.style.pointerEvents = '';
|
||||
|
||||
self.gutter.style.cursor = '';
|
||||
self.parent.style.cursor = '';
|
||||
}
|
||||
|
||||
// startDragging calls `calculateSizes` to store the inital size in the pair object.
|
||||
// It also adds event listeners for mouse/touch events,
|
||||
// and prevents selection while dragging so avoid the selecting text.
|
||||
function startDragging(e) {
|
||||
// Alias frequently used variables to save space. 200 bytes.
|
||||
var self = this;
|
||||
var a = elements[self.a].element;
|
||||
var b = elements[self.b].element;
|
||||
|
||||
// Call the onDragStart callback.
|
||||
if (!self.dragging && options.onDragStart) {
|
||||
options.onDragStart();
|
||||
}
|
||||
|
||||
// Don't actually drag the element. We emulate that in the drag function.
|
||||
e.preventDefault();
|
||||
|
||||
// Set the dragging property of the pair object.
|
||||
self.dragging = true;
|
||||
|
||||
// Create two event listeners bound to the same pair object and store
|
||||
// them in the pair object.
|
||||
self.move = drag.bind(self);
|
||||
self.stop = stopDragging.bind(self);
|
||||
|
||||
// All the binding. `window` gets the stop events in case we drag out of the elements.
|
||||
global[addEventListener]('mouseup', self.stop);
|
||||
global[addEventListener]('touchend', self.stop);
|
||||
global[addEventListener]('touchcancel', self.stop);
|
||||
|
||||
self.parent[addEventListener]('mousemove', self.move);
|
||||
self.parent[addEventListener]('touchmove', self.move);
|
||||
|
||||
// Disable selection. Disable!
|
||||
a[addEventListener]('selectstart', NOOP);
|
||||
a[addEventListener]('dragstart', NOOP);
|
||||
b[addEventListener]('selectstart', NOOP);
|
||||
b[addEventListener]('dragstart', NOOP);
|
||||
|
||||
a.style.userSelect = 'none';
|
||||
a.style.webkitUserSelect = 'none';
|
||||
a.style.MozUserSelect = 'none';
|
||||
a.style.pointerEvents = 'none';
|
||||
|
||||
b.style.userSelect = 'none';
|
||||
b.style.webkitUserSelect = 'none';
|
||||
b.style.MozUserSelect = 'none';
|
||||
b.style.pointerEvents = 'none';
|
||||
|
||||
// Set the cursor, both on the gutter and the parent element.
|
||||
// Doing only a, b and gutter causes flickering.
|
||||
self.gutter.style.cursor = cursor;
|
||||
self.parent.style.cursor = cursor;
|
||||
|
||||
// Cache the initial sizes of the pair.
|
||||
calculateSizes.call(self);
|
||||
}
|
||||
|
||||
// 5. Create pair and element objects. Each pair has an index reference to
|
||||
// elements `a` and `b` of the pair (first and second elements).
|
||||
// Loop through the elements while pairing them off. Every pair gets a
|
||||
// `pair` object, a gutter, and isFirst/isLast properties.
|
||||
//
|
||||
// Basic logic:
|
||||
//
|
||||
// - Starting with the second element `i > 0`, create `pair` objects with
|
||||
// `a = i - 1` and `b = i`
|
||||
// - Set gutter sizes based on the _pair_ being first/last. The first and last
|
||||
// pair have gutterSize / 2, since they only have one half gutter, and not two.
|
||||
// - Create gutter elements and add event listeners.
|
||||
// - Set the size of the elements, minus the gutter sizes.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// | i=0 | i=1 | i=2 | i=3 |
|
||||
// | | isFirst | | isLast |
|
||||
// | pair 0 pair 1 pair 2 |
|
||||
// | | | | |
|
||||
// -----------------------------------------------------------------------
|
||||
var pairs = [];
|
||||
elements = ids.map(function(id, i) {
|
||||
// Create the element object.
|
||||
var element = {
|
||||
element: elementOrSelector(id),
|
||||
size: sizes[i],
|
||||
minSize: minSizes[i]
|
||||
};
|
||||
|
||||
var pair;
|
||||
|
||||
if (i > 0) {
|
||||
// Create the pair object with it's metadata.
|
||||
pair = {
|
||||
a: i - 1,
|
||||
b: i,
|
||||
dragging: false,
|
||||
isFirst: i === 1,
|
||||
isLast: i === ids.length - 1,
|
||||
direction: direction,
|
||||
parent: parent
|
||||
};
|
||||
|
||||
// For first and last pairs, first and last gutter width is half.
|
||||
pair.aGutterSize = gutterSize;
|
||||
pair.bGutterSize = gutterSize;
|
||||
|
||||
if (pair.isFirst) {
|
||||
pair.aGutterSize = gutterSize / 2;
|
||||
}
|
||||
|
||||
if (pair.isLast) {
|
||||
pair.bGutterSize = gutterSize / 2;
|
||||
}
|
||||
|
||||
// if the parent has a reverse flex-direction, switch the pair elements.
|
||||
if (
|
||||
parentFlexDirection === 'row-reverse' ||
|
||||
parentFlexDirection === 'column-reverse'
|
||||
) {
|
||||
var temp = pair.a;
|
||||
pair.a = pair.b;
|
||||
pair.b = temp;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the size of the current element. IE8 is supported by
|
||||
// staticly assigning sizes without draggable gutters. Assigns a string
|
||||
// to `size`.
|
||||
//
|
||||
// IE9 and above
|
||||
if (!isIE8) {
|
||||
// Create gutter elements for each pair.
|
||||
if (i > 0) {
|
||||
var gutterElement = gutter(i, direction);
|
||||
setGutterSize(gutterElement, gutterSize);
|
||||
|
||||
gutterElement[addEventListener](
|
||||
'mousedown',
|
||||
startDragging.bind(pair)
|
||||
);
|
||||
gutterElement[addEventListener](
|
||||
'touchstart',
|
||||
startDragging.bind(pair)
|
||||
);
|
||||
|
||||
parent.insertBefore(gutterElement, element.element);
|
||||
|
||||
pair.gutter = gutterElement;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the element size to our determined size.
|
||||
// Half-size gutters for first and last elements.
|
||||
if (i === 0 || i === ids.length - 1) {
|
||||
setElementSize(element.element, element.size, gutterSize / 2);
|
||||
} else {
|
||||
setElementSize(element.element, element.size, gutterSize);
|
||||
}
|
||||
|
||||
var computedSize = element.element[getBoundingClientRect]()[dimension];
|
||||
|
||||
if (computedSize < element.minSize) {
|
||||
element.minSize = computedSize;
|
||||
}
|
||||
|
||||
// After the first iteration, and we have a pair object, append it to the
|
||||
// list of pairs.
|
||||
if (i > 0) {
|
||||
pairs.push(pair);
|
||||
}
|
||||
|
||||
return element;
|
||||
});
|
||||
|
||||
function setSizes(newSizes) {
|
||||
newSizes.forEach(function(newSize, i) {
|
||||
if (i > 0) {
|
||||
var pair = pairs[i - 1];
|
||||
var a = elements[pair.a];
|
||||
var b = elements[pair.b];
|
||||
|
||||
a.size = newSizes[i - 1];
|
||||
b.size = newSize;
|
||||
|
||||
setElementSize(a.element, a.size, pair.aGutterSize);
|
||||
setElementSize(b.element, b.size, pair.bGutterSize);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
pairs.forEach(function(pair) {
|
||||
pair.parent.removeChild(pair.gutter);
|
||||
elements[pair.a].element.style[dimension] = '';
|
||||
elements[pair.b].element.style[dimension] = '';
|
||||
});
|
||||
}
|
||||
|
||||
if (isIE8) {
|
||||
return {
|
||||
setSizes: setSizes,
|
||||
destroy: destroy
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
setSizes: setSizes,
|
||||
getSizes: function getSizes() {
|
||||
return elements.map(function(element) {
|
||||
return element.size;
|
||||
});
|
||||
},
|
||||
collapse: function collapse(i) {
|
||||
if (i === pairs.length) {
|
||||
var pair = pairs[i - 1];
|
||||
|
||||
calculateSizes.call(pair);
|
||||
|
||||
if (!isIE8) {
|
||||
adjust.call(pair, pair.size - pair.bGutterSize);
|
||||
}
|
||||
} else {
|
||||
var pair$1 = pairs[i];
|
||||
|
||||
calculateSizes.call(pair$1);
|
||||
|
||||
if (!isIE8) {
|
||||
adjust.call(pair$1, pair$1.aGutterSize);
|
||||
}
|
||||
}
|
||||
},
|
||||
destroy: destroy
|
||||
};
|
||||
};
|
||||
|
||||
return Split;
|
||||
});
|
|
@ -1,68 +1,59 @@
|
|||
.documentation a {
|
||||
.documentation {
|
||||
font-family: Helvetica, sans-serif;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.black {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.bg-white {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin: 20px 0 10px 0;
|
||||
}
|
||||
|
||||
.documentation h3 {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.border-bottom {
|
||||
border-color: #ddd;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #1184CE;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.documentation .suppress-p-margin p {
|
||||
margin:0;
|
||||
.documentation a[href]:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.force-inline, .force-inline p {
|
||||
display: inline;
|
||||
color: #222;
|
||||
a:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.container-small {
|
||||
max-width: 58rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
.py1-ul li {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.max-height-100 {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.fade {
|
||||
opacity:0.50;
|
||||
}
|
||||
|
||||
.button-indent {
|
||||
padding: .25rem 1.5rem;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.section-indent {
|
||||
border-left: 2px solid #eee;
|
||||
}
|
||||
|
||||
.bg-cloudy {
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.force-inline * {
|
||||
display:inline;
|
||||
.height-viewport-100 {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
section:target h3 {
|
||||
font-weight:700;
|
||||
}
|
||||
|
||||
.documentation,
|
||||
.documentation h1,
|
||||
.documentation h2,
|
||||
.documentation h3,
|
||||
.documentation h4,
|
||||
.documentation h5,
|
||||
.documentation h6 {
|
||||
font-family: 'Source Sans Pro', Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.documentation pre,
|
||||
.documentation code,
|
||||
.documentation samp {
|
||||
font-family: 'Source Code Pro', monospace;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.documentation td,
|
||||
.documentation th {
|
||||
padding: .25rem .25rem;
|
||||
|
@ -75,12 +66,9 @@ h4:hover .anchorjs-link {
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
.collapsible .collapser {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.collapsible:target .collapser {
|
||||
display: block;
|
||||
.fix-3 {
|
||||
width: 25%;
|
||||
max-width: 244px;
|
||||
}
|
||||
|
||||
.fix-3 {
|
||||
|
@ -93,3 +81,60 @@ h4:hover .anchorjs-link {
|
|||
margin-left: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
.pre, pre, code, .code {
|
||||
font-family: Source Code Pro,Menlo,Consolas,Liberation Mono,monospace;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.fill-light {
|
||||
background: #F9F9F9;
|
||||
}
|
||||
|
||||
.width2 {
|
||||
width: 1rem;
|
||||
}
|
||||
|
||||
.input {
|
||||
font-family: inherit;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 2rem;
|
||||
padding: .5rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid #ccc;
|
||||
font-size: .875rem;
|
||||
border-radius: 3px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.prose table th,
|
||||
.prose table td {
|
||||
text-align: left;
|
||||
padding:8px;
|
||||
border:1px solid #ddd;
|
||||
}
|
||||
|
||||
.prose table th:nth-child(1) { border-right: none; }
|
||||
.prose table th:nth-child(2) { border-left: none; }
|
||||
|
||||
.prose table {
|
||||
border:1px solid #ddd;
|
||||
}
|
||||
|
||||
.prose-big {
|
||||
font-size: 18px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.quiet {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.minishadow {
|
||||
box-shadow: 2px 2px 10px #f3f3f3;
|
||||
}
|
||||
|
|
5871
docs/index.html
5871
docs/index.html
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,99 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: Adapter.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: Adapter.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/**
|
||||
* Class that wraps database connection libraries
|
||||
*
|
||||
* @private
|
||||
* @param {Promise} instance - The connection object
|
||||
*/
|
||||
class Adapter {
|
||||
/**
|
||||
* Invoke an adapter
|
||||
*
|
||||
* @constructor
|
||||
* @param {Promise} instance - Promise holding connection object
|
||||
*/
|
||||
constructor (instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the sql query as a prepared statement
|
||||
*
|
||||
* @param {String} sql - The sql with placeholders
|
||||
* @param {Array} params - The values to insert into the query
|
||||
* @return {Promise} - returns a promise resolving to the result of the database query
|
||||
*/
|
||||
execute (sql, params) {
|
||||
throw new Error('Correct adapter not defined for query execution');
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the adapter's result into a standard format
|
||||
*
|
||||
* @param {*} originalResult - the original result object from the driver
|
||||
* @return {Result} - the new result object
|
||||
*/
|
||||
transformResult (originalResult) {
|
||||
throw new Error('Result transformer method not defined for current adapter');
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the current database connection
|
||||
* @return {void}
|
||||
*/
|
||||
close () {
|
||||
this.instance.then(conn => conn.end());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Adapter;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,220 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: Helpers.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: Helpers.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const fs = require('fs');
|
||||
|
||||
/**
|
||||
* Various internal helper functions
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
class Helpers {
|
||||
/**
|
||||
* Get the contents of a file
|
||||
*
|
||||
* @param {string} file - The path to the file
|
||||
* @return {Promise<string>} - Promise resolving to the contents of the file
|
||||
*/
|
||||
static readFile (file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(file, (err, data) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
return resolve(Buffer.from(data).toString());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap String.prototype.trim in a way that is easily mappable
|
||||
*
|
||||
* @param {String} str - The string to trim
|
||||
* @return {String} - The trimmed string
|
||||
*/
|
||||
static stringTrim (str) {
|
||||
return str.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the variable passed
|
||||
*
|
||||
* @see https://techblog.badoo.com/blog/2013/11/01/type-checking-in-javascript/
|
||||
* @see http://toddmotto.com/understanding-javascript-types-and-reliable-type-checking/
|
||||
* @param {mixed} o - Object to type check
|
||||
* @return {String} - Type of the object
|
||||
*/
|
||||
static type (o) {
|
||||
const type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
|
||||
|
||||
// handle NaN and Infinity
|
||||
if (type === 'number') {
|
||||
if (isNaN(o)) {
|
||||
return 'nan';
|
||||
}
|
||||
|
||||
if (!isFinite(o)) {
|
||||
return 'infinity';
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether an object is scalar
|
||||
*
|
||||
* @param {mixed} obj - Object to test
|
||||
* @return {boolean} - Is object scalar
|
||||
*/
|
||||
static isScalar (obj) {
|
||||
return ['string', 'number', 'boolean'].includes(Helpers.type(obj));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of values with a common key from an array of objects
|
||||
*
|
||||
* @param {Array} arr - The array of objects to search
|
||||
* @param {String} key - The key of the object to get
|
||||
* @return {Array} - The new array of plucked values
|
||||
*/
|
||||
static arrayPluck (arr, key) {
|
||||
const output = [];
|
||||
|
||||
// Empty case
|
||||
if (arr.length === 0) {
|
||||
return output;
|
||||
}
|
||||
|
||||
arr.forEach(obj => {
|
||||
if (!Helpers.isUndefined(obj[key])) {
|
||||
output.push(obj[key]);
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a value matching the passed regular expression is
|
||||
* in the passed array
|
||||
*
|
||||
* @param {Array} arr - The array to search
|
||||
* @param {RegExp} pattern - The pattern to match
|
||||
* @return {Boolean} - If an array item matches the pattern
|
||||
*/
|
||||
static regexInArray (arr, pattern) {
|
||||
// Empty case(s)
|
||||
if (!Helpers.isArray(arr) || arr.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const l = arr.length;
|
||||
for (let i = 0; i < l; i++) {
|
||||
// Short circuit if any items match
|
||||
if (pattern.test(arr[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the first constter of the string uppercase
|
||||
*
|
||||
* @param {String} str - The string to modify
|
||||
* @return {String} - The modified string
|
||||
*/
|
||||
static upperCaseFirst (str) {
|
||||
str += '';
|
||||
const first = str.charAt(0).toUpperCase();
|
||||
return first + str.substr(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Define an 'is' method for each type
|
||||
const types = [
|
||||
'Null',
|
||||
'Undefined',
|
||||
'Object',
|
||||
'Array',
|
||||
'String',
|
||||
'Number',
|
||||
'Boolean',
|
||||
'Function',
|
||||
'RegExp',
|
||||
'NaN',
|
||||
'Infinite',
|
||||
'Promise'
|
||||
];
|
||||
types.forEach(t => {
|
||||
/**
|
||||
* Determine whether a variable is of the type specified in the
|
||||
* function name, eg isNumber
|
||||
*
|
||||
* Types available are Null, Undefined, Object, Array, String, Number,
|
||||
* Boolean, Function, RegExp, NaN, Infinite, Promise
|
||||
*
|
||||
* @private
|
||||
* @param {mixed} o - The object to check its type
|
||||
* @return {Boolean} - If the type matches
|
||||
*/
|
||||
Helpers[`is${t}`] = function (o) {
|
||||
if (t.toLowerCase() === 'infinite') {
|
||||
t = 'infinity';
|
||||
}
|
||||
|
||||
return Helpers.type(o) === t.toLowerCase();
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = Helpers;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,333 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Class: NodeQuery</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Class: NodeQuery</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
<h2><span class="attribs"><span class="type-signature"></span></span>NodeQuery<span class="signature">(config)</span><span class="type-signature"></span></h2>
|
||||
|
||||
<div class="class-description">Class for connection management</div>
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Constructor</h2>
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="NodeQuery"><span class="type-signature"></span>new NodeQuery<span class="signature">(config)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Constructor
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>config</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">object</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">connection parameters</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="NodeQuery.js.html">NodeQuery.js</a>, <a href="NodeQuery.js.html#line24">line 24</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Methods</h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="getQuery"><span class="type-signature"></span>getQuery<span class="signature">()</span><span class="type-signature"> → {<a href="QueryBuilder.html">QueryBuilder</a>}</span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Return an existing query builder instance
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="NodeQuery.js.html">NodeQuery.js</a>, <a href="NodeQuery.js.html#line71">line 71</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Returns:</h5>
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
- The Query Builder object
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type"><a href="QueryBuilder.html">QueryBuilder</a></span>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,131 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: NodeQuery.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: NodeQuery.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const QueryBuilder = require('./QueryBuilder');
|
||||
|
||||
// Map config driver name to code class name
|
||||
const dbDriverMap = new Map([
|
||||
['my', 'Mysql'],
|
||||
['mysql', 'Mysql'],
|
||||
['maria', 'Mysql'],
|
||||
['mariadb', 'Mysql'],
|
||||
['firebird', 'Firebird'],
|
||||
['postgresql', 'Pg'],
|
||||
['postgres', 'Pg'],
|
||||
['pg', 'Pg'],
|
||||
['sqlite3', 'Sqlite'],
|
||||
['sqlite', 'Sqlite'],
|
||||
['sqlserver', 'MSSQLServer'],
|
||||
['mssql', 'MSSQLServer']
|
||||
]);
|
||||
|
||||
/**
|
||||
* Class for connection management
|
||||
*
|
||||
* @param {object} config - connection parameters
|
||||
*/
|
||||
class NodeQuery {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param {object} config - connection parameters
|
||||
* @param {string} config.driver - the database driver to use, such as mysql, sqlite, mssql, or pgsql
|
||||
* @param {object|string} config.connection - the connection options for the database
|
||||
* @param {string} config.connection.host - the ip or hostname of the database server
|
||||
* @param {string} config.connection.user - the user to log in as
|
||||
* @param {string} config.connection.password - the password to log in with
|
||||
* @param {string} config.connection.database - the name of the database to connect to
|
||||
* @example let nodeQuery = require('ci-node-query')({
|
||||
* driver: 'mysql',
|
||||
* connection: {
|
||||
* host: 'localhost',
|
||||
* user: 'root',
|
||||
* password: '',
|
||||
* database: 'mysql'
|
||||
* }
|
||||
* });
|
||||
* @example let nodeQuery = require('ci-node-query')({
|
||||
* driver: 'sqlite',
|
||||
* connection: ':memory:'
|
||||
* });
|
||||
*/
|
||||
constructor (config) {
|
||||
this.instance = null;
|
||||
|
||||
if (config !== undefined) {
|
||||
const driverName = dbDriverMap.get(config.driver);
|
||||
|
||||
if (!driverName) {
|
||||
throw new Error(`Selected driver (${config.driver}) does not exist!`);
|
||||
}
|
||||
|
||||
const driver = require(`./drivers/${driverName}`);
|
||||
const Adapter = require(`./adapters/${driverName}`);
|
||||
|
||||
this.instance = new QueryBuilder(driver, Adapter(config));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an existing query builder instance
|
||||
*
|
||||
* @return {QueryBuilder} - The Query Builder object
|
||||
*/
|
||||
getQuery () {
|
||||
if (this.instance == null) {
|
||||
throw new Error('No Query Builder instance to return');
|
||||
}
|
||||
|
||||
return this.instance;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = config => new NodeQuery(config);
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,708 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: QueryBuilder.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: QueryBuilder.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const Helpers = require('./Helpers');
|
||||
const QueryBuilderBase = require('./QueryBuilderBase');
|
||||
|
||||
/**
|
||||
* Main object that builds SQL queries.
|
||||
*
|
||||
* @param {Driver} Driver - The syntax driver for the database
|
||||
* @param {Adapter} Adapter - The database module adapter for running queries
|
||||
* @extends QueryBuilderBase
|
||||
*/
|
||||
class QueryBuilder extends QueryBuilderBase {
|
||||
// ----------------------------------------------------------------------------
|
||||
// ! Miscellaneous Methods
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Run a set of queries from a file
|
||||
*
|
||||
* @param {string} file - The path to the sql file
|
||||
* @param {string} [separator=';'] - The character separating each query
|
||||
* @return {Promise} - The result of all the queries
|
||||
*/
|
||||
queryFile (file, separator = ';') {
|
||||
return Helpers.readFile(file).then(sqlFile => {
|
||||
const queries = sqlFile.split(separator);
|
||||
const results = [];
|
||||
|
||||
queries.forEach(sql => {
|
||||
results.push(this.query(sql));
|
||||
});
|
||||
|
||||
return Promise.all(results);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an arbitrary sql query. Run as a prepared statement.
|
||||
*
|
||||
* @param {string} sql - The sql to execute
|
||||
* @param {Array} [params] - The query parameters
|
||||
* @return {Promise} - Promise with result of query
|
||||
*/
|
||||
query (sql, params) {
|
||||
return this.adapter.execute(sql, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the object state for a new query
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
resetQuery () {
|
||||
this._resetState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current class state for testing or other purposes
|
||||
*
|
||||
* @private
|
||||
* @return {Object} - The State object
|
||||
*/
|
||||
getState () {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties the selected database table
|
||||
*
|
||||
* @param {string} table - the name of the table to truncate
|
||||
* @return {void|Promise} - Returns a promise if no callback is supplied
|
||||
*/
|
||||
truncate (table) {
|
||||
return this.query(this.driver.truncate(table));
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the database connection for the current adapter
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
end () {
|
||||
this.adapter.close();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ! Query Builder Methods
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Specify rows to select in the query
|
||||
*
|
||||
* @param {String|Array} fields - The fields to select from the current table
|
||||
* @example query.select('foo, bar'); // Select multiple fields with a string
|
||||
* @example query.select(['foo', 'bar']); // Select multiple fileds with an array
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
select (fields) {
|
||||
// Split/trim fields by comma
|
||||
fields = (Array.isArray(fields))
|
||||
? fields
|
||||
: fields.split(',').map(Helpers.stringTrim);
|
||||
|
||||
// Split on 'As'
|
||||
fields.forEach((field, index) => {
|
||||
if (/as/i.test(field)) {
|
||||
fields[index] = field.split(/ as /i).map(Helpers.stringTrim);
|
||||
}
|
||||
});
|
||||
|
||||
const safeArray = this.driver.quoteIdentifiers(fields);
|
||||
|
||||
// Join the strings back together
|
||||
safeArray.forEach((field, index) => {
|
||||
if (Array.isArray(field)) {
|
||||
safeArray[index] = safeArray[index].join(' AS ');
|
||||
}
|
||||
});
|
||||
|
||||
this.state.selectString += safeArray.join(', ');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the database table to select from
|
||||
*
|
||||
* @param {String} tableName - The table to use for the current query
|
||||
* @example query.from('tableName');
|
||||
* @example query.from('tableName t'); // Select the table with an alias
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
from (tableName) {
|
||||
// Split identifiers on spaces
|
||||
let identArray = tableName.trim().split(' ').map(Helpers.stringTrim);
|
||||
|
||||
// Quote/prefix identifiers
|
||||
identArray[0] = this.driver.quoteTable(identArray[0]);
|
||||
identArray = this.driver.quoteIdentifiers(identArray);
|
||||
|
||||
// Put it back together
|
||||
this.state.fromString = identArray.join(' ');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a 'like/ and like' clause to the query
|
||||
*
|
||||
* @param {String} field - The name of the field to compare to
|
||||
* @param {String} val - The value to compare to
|
||||
* @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
like (field, val, pos) {
|
||||
this._like(field, val, pos, ' LIKE ', 'AND');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a 'not like/ and not like' clause to the query
|
||||
*
|
||||
* @param {String} field - The name of the field to compare to
|
||||
* @param {String} val - The value to compare to
|
||||
* @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
notLike (field, val, pos) {
|
||||
this._like(field, val, pos, ' NOT LIKE ', 'AND');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an 'or like' clause to the query
|
||||
*
|
||||
* @param {String} field - The name of the field to compare to
|
||||
* @param {String} val - The value to compare to
|
||||
* @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orLike (field, val, pos) {
|
||||
this._like(field, val, pos, ' LIKE ', 'OR');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an 'or not like' clause to the query
|
||||
*
|
||||
* @param {String} field - The name of the field to compare to
|
||||
* @param {String} val - The value to compare to
|
||||
* @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orNotLike (field, val, pos) {
|
||||
this._like(field, val, pos, ' NOT LIKE ', 'OR');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a 'having' clause
|
||||
*
|
||||
* @param {String|Object} key - The name of the field and the comparision operator, or an object
|
||||
* @param {String|Number} [val] - The value to compare if the value of key is a string
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
having (key, val = null) {
|
||||
this._having(key, val, 'AND');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an 'or having' clause
|
||||
*
|
||||
* @param {String|Object} key - The name of the field and the comparision operator, or an object
|
||||
* @param {String|Number} [val] - The value to compare if the value of key is a string
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orHaving (key, val = null) {
|
||||
this._having(key, val, 'OR');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a 'where' clause
|
||||
*
|
||||
* @param {String|Object} key - The name of the field and the comparision operator, or an object
|
||||
* @param {String|Number} [val] - The value to compare if the value of key is a string
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
where (key, val) {
|
||||
this._where(key, val, 'AND');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a 'or where' clause
|
||||
*
|
||||
* @param {String|Object} key - The name of the field and the comparision operator, or an object
|
||||
* @param {String|Number} [val] - The value to compare if the value of key is a string
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orWhere (key, val) {
|
||||
this._where(key, val, 'OR');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a field that is Null
|
||||
*
|
||||
* @param {String} field - The name of the field that has a NULL value
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
whereIsNull (field) {
|
||||
this._whereNull(field, 'IS NULL', 'AND');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that a field IS NOT NULL
|
||||
*
|
||||
* @param {String} field - The name so the field that is not to be null
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
whereIsNotNull (field) {
|
||||
this._whereNull(field, 'IS NOT NULL', 'AND');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field is null prefixed with 'OR'
|
||||
*
|
||||
* @param {String} field - The name of the field
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orWhereIsNull (field) {
|
||||
this._whereNull(field, 'IS NULL', 'OR');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field is not null prefixed with 'OR'
|
||||
*
|
||||
* @param {String} field - The name of the field
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orWhereIsNotNull (field) {
|
||||
this._whereNull(field, 'IS NOT NULL', 'OR');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a 'where in' clause
|
||||
*
|
||||
* @param {String} key - the field to search
|
||||
* @param {Array} values - the array of items to search in
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
whereIn (key, values) {
|
||||
this._whereIn(key, values, 'IN', 'AND');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a 'or where in' clause
|
||||
*
|
||||
* @param {String} key - the field to search
|
||||
* @param {Array} values - the array of items to search in
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orWhereIn (key, values) {
|
||||
this._whereIn(key, values, 'IN', 'OR');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a 'where not in' clause
|
||||
*
|
||||
* @param {String} key - the field to search
|
||||
* @param {Array} values - the array of items to search in
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
whereNotIn (key, values) {
|
||||
this._whereIn(key, values, 'NOT IN', 'AND');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a 'or where not in' clause
|
||||
*
|
||||
* @param {String} key - the field to search
|
||||
* @param {Array} values - the array of items to search in
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orWhereNotIn (key, values) {
|
||||
this._whereIn(key, values, 'NOT IN', 'OR');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set values for insertion or updating
|
||||
*
|
||||
* @param {String|Object} key - The key or object to use
|
||||
* @param {String} [val] - The value if using a scalar key
|
||||
* @example query.set('foo', 'bar'); // Set a key, value pair
|
||||
* @example query.set({foo:'bar'}); // Set with an object
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
set (key, val) {
|
||||
// Set the appropriate state variables
|
||||
this._mixedSet('setArrayKeys', 'key', key, val);
|
||||
this._mixedSet('values', 'value', key, val);
|
||||
|
||||
// Use the keys of the array to make the insert/update string
|
||||
// and escape the field names
|
||||
this.state.setArrayKeys = this.state.setArrayKeys.map(this.driver._quote);
|
||||
|
||||
// Generate the "set" string
|
||||
this.state.setString = this.state.setArrayKeys.join('=?,');
|
||||
this.state.setString += '=?';
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a join clause to the query
|
||||
*
|
||||
* @param {String} table - The table you are joining
|
||||
* @param {String} cond - The join condition.
|
||||
* @param {String} [type='inner'] - The type of join, which defaults to inner
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
join (table, cond, type) {
|
||||
type = type || 'inner';
|
||||
|
||||
// Prefix/quote table name
|
||||
table = table.split(' ').map(Helpers.stringTrim);
|
||||
table[0] = this.driver.quoteTable(table[0]);
|
||||
table = table.map(this.driver.quoteIdentifiers);
|
||||
table = table.join(' ');
|
||||
|
||||
// Parse out the join condition
|
||||
const parsedCondition = this.parser.compileJoin(cond);
|
||||
const condition = `${table} ON ${parsedCondition}`;
|
||||
|
||||
// Append the join condition to the query map
|
||||
this._appendMap(`\n${type.toUpperCase()} JOIN `, condition, 'join');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group the results by the selected field(s)
|
||||
*
|
||||
* @param {String|Array} field - The name of the field to group by
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
groupBy (field) {
|
||||
if (!Helpers.isScalar(field)) {
|
||||
const newGroupArray = field.map(this.driver.quoteIdentifiers);
|
||||
this.state.groupArray = this.state.groupArray.concat(newGroupArray);
|
||||
} else {
|
||||
this.state.groupArray.push(this.driver.quoteIdentifiers(field));
|
||||
}
|
||||
|
||||
this.state.groupString = ` GROUP BY ${this.state.groupArray.join(',')}`;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Order the results by the selected field(s)
|
||||
*
|
||||
* @param {String} field - The field(s) to order by
|
||||
* @param {String} [type='ASC'] - The order direction, ASC or DESC
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orderBy (field, type) {
|
||||
type = type || 'ASC';
|
||||
|
||||
// Set the fields for later manipulation
|
||||
field = this.driver.quoteIdentifiers(field);
|
||||
|
||||
this.state.orderArray[field] = type;
|
||||
|
||||
const orderClauses = [];
|
||||
|
||||
// Flatten key/val pairs into an array of space-separated pairs
|
||||
Object.keys(this.state.orderArray).forEach(key => {
|
||||
orderClauses.push(`${key} ${this.state.orderArray[key].toUpperCase()}`);
|
||||
});
|
||||
|
||||
// Set the final string
|
||||
this.state.orderString = ` ORDER BY ${orderClauses.join(', ')}`;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a limit on the query
|
||||
*
|
||||
* @param {Number} limit - The maximum number of rows to fetch
|
||||
* @param {Number} [offset] - The row number to start from
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
limit (limit, offset) {
|
||||
this.state.limit = limit;
|
||||
this.state.offset = offset || null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an open paren to the current query for logical grouping
|
||||
*
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
groupStart () {
|
||||
const conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ' AND ';
|
||||
this._appendMap(conj, '(', 'groupStart');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an open paren to the current query for logical grouping,
|
||||
* prefixed with 'OR'
|
||||
*
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orGroupStart () {
|
||||
this._appendMap('', ' OR (', 'groupStart');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an open paren to the current query for logical grouping,
|
||||
* prefixed with 'OR NOT'
|
||||
*
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orNotGroupStart () {
|
||||
this._appendMap('', ' OR NOT (', 'groupStart');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a logical grouping started with one of the groupStart methods
|
||||
*
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
groupEnd () {
|
||||
this._appendMap('', ')', 'groupEnd');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ! Result Methods
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get the results of the compiled query
|
||||
*
|
||||
* @param {String} [table] - The table to select from
|
||||
* @param {Number} [limit] - A limit for the query
|
||||
* @param {Number} [offset] - An offset for the query
|
||||
* @example query.get('table_name').then(promiseCallback); // Get all the rows in the table
|
||||
* @example query.get('table_name', 5); // Get 5 rows from the table
|
||||
* @example query.get(); // Get the results of a query generated with other methods
|
||||
* @return {Promise<Result>} - Promise containing the result of the query
|
||||
*/
|
||||
get (table, limit, offset) {
|
||||
if (table) {
|
||||
this.from(table);
|
||||
}
|
||||
|
||||
if (limit) {
|
||||
this.limit(limit, offset);
|
||||
}
|
||||
|
||||
// Run the query
|
||||
return this._run('get', table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the generated insert query
|
||||
*
|
||||
* @param {String} table - The table to insert into
|
||||
* @param {Object} [data] - Data to insert, if not already added with the 'set' method
|
||||
* @return {Promise<Result>} - Promise containing the result of the query
|
||||
*/
|
||||
insert (table, data) {
|
||||
if (data) {
|
||||
this.set(data);
|
||||
}
|
||||
|
||||
// Run the query
|
||||
return this._run('insert', this.driver.quoteTable(table));
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert multiple sets of rows at a time
|
||||
*
|
||||
* @param {String} table - The table to insert into
|
||||
* @param {Array} data - The array of objects containing data rows to insert
|
||||
* @example query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}])
|
||||
*.then(promiseCallback);
|
||||
* @return {Promise<Result>} - Promise containing the result of the query
|
||||
*/
|
||||
insertBatch (table, data) {
|
||||
const batch = this.driver.insertBatch(table, data);
|
||||
|
||||
// Run the query
|
||||
return this.query(batch.sql, batch.values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the generated update query
|
||||
*
|
||||
* @param {String} table - The table to insert into
|
||||
* @param {Object} [data] - Data to insert, if not already added with the 'set' method
|
||||
* @return {Promise<Result>} - Promise containing the result of the query
|
||||
*/
|
||||
update (table, data) {
|
||||
if (data) {
|
||||
this.set(data);
|
||||
}
|
||||
|
||||
// Run the query
|
||||
return this._run('update', this.driver.quoteTable(table));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a batch update sql statement
|
||||
*
|
||||
* @param {String} table - The table to update
|
||||
* @param {Object} data - Batch insert data
|
||||
* @param {String} updateKey - The field in the table to compare against for updating
|
||||
* @return {Number} Number of rows updated
|
||||
*/
|
||||
updateBatch (table, data, updateKey) {
|
||||
const [sql, insertData, affectedRows] = this.driver.updateBatch(table, data, updateKey);
|
||||
this._run('', table, sql, insertData);
|
||||
return affectedRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the generated delete query
|
||||
*
|
||||
* @param {String} table - The table to insert into
|
||||
* @param {Object} [where] - Where clause for delete statement
|
||||
* @return {Promise<Result>} - Promise containing the result of the query
|
||||
*/
|
||||
delete (table, where) {
|
||||
if (where) {
|
||||
this.where(where);
|
||||
}
|
||||
|
||||
// Run the query
|
||||
return this._run('delete', this.driver.quoteTable(table));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ! Methods returning SQL
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return generated select query SQL
|
||||
*
|
||||
* @param {String} [table] - the name of the table to retrieve from
|
||||
* @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
|
||||
* @return {String} - The compiled sql statement
|
||||
*/
|
||||
getCompiledSelect (table, reset = true) {
|
||||
if (table) {
|
||||
this.from(table);
|
||||
}
|
||||
|
||||
return this._getCompile('get', table, reset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return generated insert query SQL
|
||||
*
|
||||
* @param {String} table - the name of the table to insert into
|
||||
* @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
|
||||
* @return {String} - The compiled sql statement
|
||||
*/
|
||||
getCompiledInsert (table, reset = true) {
|
||||
return this._getCompile('insert', this.driver.quoteTable(table), reset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return generated update query SQL
|
||||
*
|
||||
* @param {String} table - the name of the table to update
|
||||
* @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
|
||||
* @return {String} - The compiled sql statement
|
||||
*/
|
||||
getCompiledUpdate (table, reset = true) {
|
||||
return this._getCompile('update', this.driver.quoteTable(table), reset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return generated delete query SQL
|
||||
*
|
||||
* @param {String} table - the name of the table to delete from
|
||||
* @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
|
||||
* @return {String} - The compiled sql statement
|
||||
*/
|
||||
getCompiledDelete (table, reset = true) {
|
||||
return this._getCompile('delete', this.driver.quoteTable(table), reset);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = QueryBuilder;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,298 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: QueryParser.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: QueryParser.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const XRegExp = require('xregexp');
|
||||
const Helpers = require('./Helpers');
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Internal object for parsing query fragments
|
||||
*
|
||||
* @private
|
||||
* @param {Driver} driver - The driver object for the database in use
|
||||
*/
|
||||
class QueryParser {
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @param {Driver} driver - The driver object for the database in use
|
||||
* @return {void}
|
||||
*/
|
||||
constructor (driver) {
|
||||
this.driver = driver;
|
||||
|
||||
const matchPatterns = {
|
||||
function: /([a-z0-9_]+\((.*)\))/i,
|
||||
operator: /!=?|=|\+|&&?|~|\|\|?|\^|\/|<>|>=?|<=?|-|%|OR|AND|NOT|XOR/ig,
|
||||
literal: /([0-9]+)|'(.*?)'|true|false/ig
|
||||
};
|
||||
|
||||
// Full pattern for identifiers
|
||||
// Making sure that literals and functions aren't matched
|
||||
matchPatterns.identifier = XRegExp(
|
||||
`(
|
||||
(?!
|
||||
${matchPatterns['function'].source}|
|
||||
${matchPatterns.literal.source}
|
||||
)
|
||||
([a-z_-]+[0-9]*\\.?)
|
||||
)+`, 'igx');
|
||||
|
||||
// Full pattern for determining ordering of the pieces
|
||||
matchPatterns.joinCombined = XRegExp(
|
||||
`${matchPatterns['function'].source}+| # functions
|
||||
${matchPatterns.literal.source}+| # literal values
|
||||
${matchPatterns.identifier.source} # identifiers
|
||||
|(${matchPatterns.operator.source})+`, 'igx');
|
||||
|
||||
this.matchPatterns = matchPatterns;
|
||||
this.identifierBlacklist = ['true', 'false', 'null'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter matched patterns
|
||||
*
|
||||
* @param {Array} array - Set of possible matches
|
||||
* @return {Array|null} - Filtered set of possible matches
|
||||
*/
|
||||
filterMatches (array) {
|
||||
const output = [];
|
||||
|
||||
// Return non-array matches
|
||||
if (Helpers.isNull(array)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
array.forEach(item => {
|
||||
output.push(item);
|
||||
});
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string contains an operator, and if so, return the operator(s).
|
||||
* If there are no matches, return null
|
||||
*
|
||||
* @param {String} string - the string to check
|
||||
* @return {Array|null} - List of operators
|
||||
*/
|
||||
hasOperator (string) {
|
||||
return this.filterMatches(string.match(this.matchPatterns.operator));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tokenize the sql into parts for additional processing
|
||||
*
|
||||
* @param {String} sql - Join sql to parse
|
||||
* @return {Object} - Join condition components
|
||||
*/
|
||||
parseJoin (sql) {
|
||||
const matches = {};
|
||||
const output = {
|
||||
functions: [],
|
||||
identifiers: [],
|
||||
operators: [],
|
||||
literals: []
|
||||
};
|
||||
|
||||
// Get clause components
|
||||
matches.functions = sql.match(new RegExp(this.matchPatterns['function'].source, 'ig'));
|
||||
matches.identifiers = sql.match(this.matchPatterns.identifier);
|
||||
matches.operators = sql.match(this.matchPatterns.operator);
|
||||
matches.literals = sql.match(this.matchPatterns.literal);
|
||||
|
||||
// Get everything at once for ordering
|
||||
matches.combined = sql.match(this.matchPatterns.joinCombined);
|
||||
|
||||
// Flatten the matches to increase relevance
|
||||
Object.keys(matches).forEach(key => {
|
||||
output[key] = this.filterMatches(matches[key]);
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the output of the parsing of the join condition
|
||||
*
|
||||
* @param {String} condition - The join condition to evaluate
|
||||
* @return {String} - The parsed/escaped join condition
|
||||
*/
|
||||
compileJoin (condition) {
|
||||
const parts = this.parseJoin(condition);
|
||||
|
||||
// Quote the identifiers
|
||||
parts.combined.forEach((part, i) => {
|
||||
if (parts.identifiers.indexOf(part) !== -1 && !Helpers.isNumber(part)) {
|
||||
parts.combined[i] = this.driver.quoteIdentifiers(part);
|
||||
}
|
||||
});
|
||||
|
||||
return parts.combined.join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a where clause to separate functions from values
|
||||
*
|
||||
* @param {Driver} driver - The current db driver
|
||||
* @param {State} state - Query Builder state object
|
||||
* @return {String} - The parsed/escaped where condition
|
||||
*/
|
||||
parseWhere (driver, state) {
|
||||
const whereMap = state.whereMap;
|
||||
let whereValues = state.rawWhereValues;
|
||||
|
||||
const outputMap = [];
|
||||
const outputValues = [];
|
||||
|
||||
Object.keys(whereMap).forEach(key => {
|
||||
// Combine fields, operators, functions and values into a full clause
|
||||
// to have a common starting flow
|
||||
let fullClause = '';
|
||||
|
||||
// Add an explicit = sign where one is inferred
|
||||
if (!this.hasOperator(key)) {
|
||||
fullClause = `${key} = ${whereMap[key]}`;
|
||||
} else if (whereMap[key] === key) {
|
||||
fullClause = key;
|
||||
} else {
|
||||
fullClause = `${key} ${whereMap[key]}`;
|
||||
}
|
||||
|
||||
// Separate the clause into separate pieces
|
||||
const parts = this.parseJoin(fullClause);
|
||||
|
||||
// Filter explicit literals from lists of matches
|
||||
if (whereValues.indexOf(whereMap[key]) !== -1) {
|
||||
const value = whereMap[key];
|
||||
const identIndex = parts.identifiers.indexOf(value);
|
||||
const litIndex = (Helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1;
|
||||
const combIndex = parts.combined.indexOf(value);
|
||||
const funcIndex = (Helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1;
|
||||
let inOutputArray = outputValues.includes(value);
|
||||
|
||||
// Remove the identifier in question,
|
||||
// and add to the output values array
|
||||
if (identIndex !== -1) {
|
||||
parts.identifiers.splice(identIndex, 1);
|
||||
|
||||
if (!inOutputArray) {
|
||||
outputValues.push(value);
|
||||
inOutputArray = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the value from the literals list
|
||||
// so it is not added twice
|
||||
if (litIndex !== -1) {
|
||||
parts.literals.splice(litIndex, 1);
|
||||
|
||||
if (!inOutputArray) {
|
||||
outputValues.push(value);
|
||||
inOutputArray = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the value from the combined list
|
||||
// and replace it with a placeholder
|
||||
if (combIndex !== -1 && funcIndex === -1) {
|
||||
// Make sure to skip functions when replacing values
|
||||
parts.combined[combIndex] = '?';
|
||||
}
|
||||
}
|
||||
|
||||
// Filter false positive identifiers
|
||||
parts.identifiers = parts.identifiers.filter(item => {
|
||||
const isInCombinedMatches = parts.combined.indexOf(item) !== -1;
|
||||
const isNotInBlackList = this.identifierBlacklist.indexOf(item.toLowerCase()) === -1;
|
||||
|
||||
return isInCombinedMatches && isNotInBlackList;
|
||||
}, this);
|
||||
|
||||
// Quote identifiers
|
||||
if (Helpers.isArray(parts.identifiers)) {
|
||||
parts.identifiers.forEach(ident => {
|
||||
const index = parts.combined.indexOf(ident);
|
||||
if (index !== -1) {
|
||||
parts.combined[index] = driver.quoteIdentifiers(ident);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Replace each literal with a placeholder in the map
|
||||
// and add the literal to the values,
|
||||
// This should only apply to literal values that are not
|
||||
// explicitly mapped to values, but have to be parsed from
|
||||
// a where condition,
|
||||
if (Helpers.isArray(parts.literals)) {
|
||||
parts.literals.forEach(lit => {
|
||||
const litIndex = parts.combined.indexOf(lit);
|
||||
|
||||
if (litIndex !== -1) {
|
||||
parts.combined[litIndex] = '?';
|
||||
outputValues.push(lit);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
outputMap.push(parts.combined.join(' '));
|
||||
});
|
||||
|
||||
state.rawWhereValues = [];
|
||||
state.whereValues = state.whereValues.concat(outputValues);
|
||||
state.whereMap = outputMap;
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = QueryParser;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,464 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Class: Result</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Class: Result</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
<h2><span class="attribs"><span class="type-signature"></span></span>Result<span class="signature">(rows, columns)</span><span class="type-signature"></span></h2>
|
||||
|
||||
<div class="class-description">Query result object</div>
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Constructor</h2>
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="Result"><span class="type-signature"></span>new Result<span class="signature">(rows, columns)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Create a result object
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>rows</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Array</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">the data rows of the result</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>columns</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Array</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">the column names in the result</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="Result.js.html">Result.js</a>, <a href="Result.js.html#line9">line 9</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Methods</h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="columnCount"><span class="type-signature"></span>columnCount<span class="signature">()</span><span class="type-signature"> → {Number}</span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Get the number of columns returned by the query
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="Result.js.html">Result.js</a>, <a href="Result.js.html#line88">line 88</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Returns:</h5>
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
- the number of columns in the result
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type">Number</span>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="rowCount"><span class="type-signature"></span>rowCount<span class="signature">()</span><span class="type-signature"> → {Number}</span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Get the number of rows returned by the query
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="Result.js.html">Result.js</a>, <a href="Result.js.html#line79">line 79</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Returns:</h5>
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
- the number of rows in the result
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type">Number</span>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,144 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: Result.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: Result.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const Helpers = require('./Helpers');
|
||||
|
||||
/**
|
||||
* Query result object
|
||||
*
|
||||
* @param {Array} rows - the data rows of the result
|
||||
* @param {Array} columns - the column names in the result
|
||||
*/
|
||||
class Result {
|
||||
/**
|
||||
* Create a result object
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [rows] - the data rows of the result
|
||||
* @param {Array} [columns] - the column names in the result
|
||||
*/
|
||||
constructor (rows = [], columns = []) {
|
||||
this._rows = rows;
|
||||
this._columns = columns;
|
||||
|
||||
// If columns aren't explicitly given,
|
||||
// get the list from the first row's keys
|
||||
if (
|
||||
this._columns.length === 0 &&
|
||||
this._rows.length > 0 &&
|
||||
Helpers.isObject(rows[0])
|
||||
) {
|
||||
this.columns = Object.keys(rows[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the result rows
|
||||
*
|
||||
* @private
|
||||
* @return {Array} - the data rows of the result
|
||||
*/
|
||||
get rows () {
|
||||
return this._rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the result rows for the result object
|
||||
*
|
||||
* @private
|
||||
* @param {Array} rows - the data rows of the result
|
||||
* @return {void}
|
||||
*/
|
||||
set rows (rows) {
|
||||
this._rows = rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the result columns
|
||||
*
|
||||
* @private
|
||||
* @return {Array} - the column names in the result
|
||||
*/
|
||||
get columns () {
|
||||
return this._columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the result columns for the result object
|
||||
*
|
||||
* @private
|
||||
* @param {Array} cols - the array of columns for the current result
|
||||
* @return {void}
|
||||
*/
|
||||
set columns (cols) {
|
||||
this._columns = cols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of rows returned by the query
|
||||
*
|
||||
* @return {Number} - the number of rows in the result
|
||||
*/
|
||||
rowCount () {
|
||||
return this._rows.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of columns returned by the query
|
||||
*
|
||||
* @return {Number} - the number of columns in the result
|
||||
*/
|
||||
columnCount () {
|
||||
return this._columns.length;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Result;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,100 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: adapters/Mysql/mysql2.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: adapters/Mysql/mysql2.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const Adapter = require('../../Adapter');
|
||||
const Result = require('../../Result');
|
||||
const Helpers = require('../../Helpers');
|
||||
const mysql2 = require('mysql2/promise');
|
||||
|
||||
class Mysql extends Adapter {
|
||||
constructor (config) {
|
||||
const instance = mysql2.createConnection(config);
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the adapter's result into a standard format
|
||||
*
|
||||
* @param {*} result - original driver result object
|
||||
* @return {Result} - standard result object
|
||||
*/
|
||||
transformResult (result) {
|
||||
// For insert and update queries, the result object
|
||||
// works differently. Just apply the properties of
|
||||
// this special result to the standard result object.
|
||||
if (Helpers.type(result) === 'object') {
|
||||
let r = new Result();
|
||||
|
||||
Object.keys(result).forEach(key => {
|
||||
r[key] = result[key];
|
||||
});
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
return new Result(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the sql query as a prepared statement
|
||||
*
|
||||
* @param {String} sql - The sql with placeholders
|
||||
* @param {Array} params - The values to insert into the query
|
||||
* @return {Promise} Result of query
|
||||
*/
|
||||
execute (sql, params) {
|
||||
return this.instance
|
||||
.then(conn => conn.execute(sql, params))
|
||||
.then(result => this.transformResult(result));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Mysql;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,154 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: adapters/Pg/Pg.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: adapters/Pg/Pg.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const Adapter = require('../../Adapter');
|
||||
const Result = require('../../Result');
|
||||
const Helpers = require('../../Helpers');
|
||||
const pg = require('pg');
|
||||
const url = require('url');
|
||||
|
||||
class Pg extends Adapter {
|
||||
constructor (config) {
|
||||
let instance = null;
|
||||
let connectionString = Pg.formatConnectionString(config);
|
||||
|
||||
if (connectionString !== '') {
|
||||
const conn = new pg.Client(connectionString);
|
||||
conn.connect(err => {
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
});
|
||||
|
||||
instance = Promise.resolve(conn);
|
||||
}
|
||||
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the connection object to a connection string
|
||||
*
|
||||
* @param {Object} config - the configuration object
|
||||
* @return {String} - the connection string
|
||||
*/
|
||||
static formatConnectionString (config) {
|
||||
let connectionString = '';
|
||||
|
||||
if (Helpers.isObject(config)) {
|
||||
const host = config.host || 'localhost';
|
||||
const user = config.user || 'postgres';
|
||||
const password = `:${config.password}` || '';
|
||||
const port = config.port || 5432;
|
||||
|
||||
const conn = {
|
||||
protocol: 'postgres',
|
||||
slashes: true,
|
||||
host: `${host}:${port}`,
|
||||
auth: `${user}${password}`,
|
||||
pathname: config.database
|
||||
};
|
||||
|
||||
connectionString = url.format(conn);
|
||||
} else if (Helpers.isString(config)) {
|
||||
connectionString = config;
|
||||
}
|
||||
|
||||
return connectionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the adapter's result into a standard format
|
||||
*
|
||||
* @param {*} result - original driver result object
|
||||
* @return {Result} - standard result object
|
||||
*/
|
||||
transformResult (result) {
|
||||
if (result == null) {
|
||||
return new Result();
|
||||
}
|
||||
|
||||
const cols = [];
|
||||
result.fields.forEach(field => {
|
||||
cols.push(field.name);
|
||||
});
|
||||
|
||||
return new Result(result.rows, cols);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the sql query as a prepared statement
|
||||
*
|
||||
* @param {String} sql - The sql with placeholders
|
||||
* @param {Array} params - The values to insert into the query
|
||||
* @return {void|Promise} - Returns a promise if no callback is provided
|
||||
*/
|
||||
execute (sql, params) {
|
||||
// Replace question marks with numbered placeholders, because this adapter is different...
|
||||
let count = 0;
|
||||
sql = sql.replace(/\?/g, () => {
|
||||
count++;
|
||||
return `$${count}`;
|
||||
});
|
||||
|
||||
return this.instance.then(conn => {
|
||||
return new Promise((resolve, reject) => {
|
||||
conn.query(sql, params, (err, result) =>
|
||||
(err)
|
||||
? reject(err)
|
||||
: resolve(this.transformResult(result))
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Pg;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,116 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: adapters/Sqlite/dblite.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: adapters/Sqlite/dblite.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const Adapter = require('../../Adapter');
|
||||
const Result = require('../../Result');
|
||||
const Helpers = require('../../Helpers');
|
||||
const dbliteAdapter = require('dblite');
|
||||
|
||||
class SqliteDblite extends Adapter {
|
||||
constructor (config) {
|
||||
const file = (Helpers.isString(config)) ? config : config.file;
|
||||
|
||||
const instance = new Promise((resolve, reject) => {
|
||||
const conn = dbliteAdapter(file);
|
||||
|
||||
// Stop the stupid 'bye bye' message being output
|
||||
conn.on('close', () => {});
|
||||
|
||||
conn.on('error', err => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
// Make sure to actually pass on the connection!
|
||||
return resolve(conn);
|
||||
});
|
||||
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the sql query as a prepared statement
|
||||
*
|
||||
* @param {String} sql - The sql with placeholders
|
||||
* @param {Array} params - The values to insert into the query
|
||||
* @return {Promise} - Returns a promise if no callback is provided
|
||||
*/
|
||||
execute (sql, params) {
|
||||
return this.instance.then(conn => new Promise((resolve, reject) => {
|
||||
return conn.query(sql, params, (err, rows) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
return resolve(this.transformResult(rows));
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the adapter's result into a standard format
|
||||
*
|
||||
* @param {*} originalResult - the original result object from the driver
|
||||
* @return {Result} - the new result object
|
||||
*/
|
||||
transformResult (originalResult) {
|
||||
return new Result(originalResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the current database connection
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
close () {
|
||||
this.instance.then(conn => conn.close());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SqliteDblite;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,112 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: adapters/Sqlite/sqlite3.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: adapters/Sqlite/sqlite3.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>const Adapter = require('../../Adapter');
|
||||
const Result = require('../../Result');
|
||||
const Helpers = require('../../Helpers');
|
||||
const sqlite3 = require('sqlite3').verbose();
|
||||
|
||||
class SqliteSqlite3 extends Adapter {
|
||||
constructor (config) {
|
||||
const file = (Helpers.isString(config)) ? config : config.file;
|
||||
|
||||
const instance = new Promise((resolve, reject) => {
|
||||
const conn = new sqlite3.Database(file, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, err => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
|
||||
conn.on('open', resolve(conn));
|
||||
});
|
||||
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the adapter's result into a standard format
|
||||
*
|
||||
* @param {*} result - original driver result object
|
||||
* @return {Result} - standard result object
|
||||
*/
|
||||
transformResult (result) {
|
||||
return new Result(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the sql query as a prepared statement
|
||||
*
|
||||
* @param {String} sql - The sql with placeholders
|
||||
* @param {Array} params - The values to insert into the query
|
||||
* @return {Promise} - Returns a promise if no callback is provided
|
||||
*/
|
||||
execute (sql, params) {
|
||||
return this.instance.then(conn => new Promise((resolve, reject) => {
|
||||
conn.all(sql, params, (err, rows) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
return resolve(this.transformResult(rows));
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the current database connection
|
||||
|
||||
* @return {void}
|
||||
*/
|
||||
close () {
|
||||
this.instance.then(conn => conn.close());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SqliteSqlite3;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: drivers/MSSQLDriver.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: drivers/MSSQLDriver.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/**
|
||||
* Driver for Microsoft SQL Server databases
|
||||
*
|
||||
* @module drivers/MSSQLDriver
|
||||
*/
|
||||
module.exports = (() => {
|
||||
delete require.cache[require.resolve('../Driver')];
|
||||
const driver = require('../Driver');
|
||||
|
||||
driver.identifierStartChar = '[';
|
||||
driver.identifierEndChar = ']';
|
||||
|
||||
return driver;
|
||||
})();
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,57 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: drivers/MariaDB.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: drivers/MariaDB.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/**
|
||||
* Driver for MariaDB databases
|
||||
*
|
||||
* @module drivers/MariaDB
|
||||
*/
|
||||
module.exports = require('./Mysql');
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,82 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: drivers/Mysql.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: drivers/Mysql.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/**
|
||||
* Driver for MySQL databases
|
||||
*
|
||||
* @module drivers/Mysql
|
||||
*/
|
||||
module.exports = (() => {
|
||||
delete require.cache[require.resolve('../Driver')];
|
||||
const driver = require('../Driver');
|
||||
const Helpers = require('../Helpers');
|
||||
|
||||
driver.identifierStartChar = '`';
|
||||
driver.identifierEndChar = '`';
|
||||
|
||||
/**
|
||||
* Set the limit clause
|
||||
*
|
||||
* @param {String} sql - SQL statement to modify
|
||||
* @param {Number} limit - Maximum number of rows to fetch
|
||||
* @param {Number|null} offset - Number of rows to skip
|
||||
* @return {String} - Modified SQL statement
|
||||
*/
|
||||
driver.limit = (sql, limit, offset) => {
|
||||
sql += (Helpers.isNumber(offset))
|
||||
? ` LIMIT ${offset},${limit}`
|
||||
: ` LIMIT ${limit}`;
|
||||
|
||||
return sql;
|
||||
};
|
||||
|
||||
return driver;
|
||||
})();
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,60 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: drivers/Pg.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: drivers/Pg.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/**
|
||||
* Driver for PostgreSQL databases
|
||||
*
|
||||
* @module drivers/Pg
|
||||
*/
|
||||
module.exports = (() => {
|
||||
delete require.cache[require.resolve('../Driver')];
|
||||
return require('../Driver');
|
||||
})();
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,111 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: drivers/Sqlite.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: drivers/Sqlite.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/**
|
||||
* Driver for SQLite databases
|
||||
*
|
||||
* @module drivers/Sqlite
|
||||
*/
|
||||
module.exports = (() => {
|
||||
delete require.cache[require.resolve('../Driver')];
|
||||
const driver = require('../Driver');
|
||||
|
||||
// Sqlite doesn't have a truncate command
|
||||
driver.hasTruncate = false;
|
||||
|
||||
/**
|
||||
* SQL to insert a group of rows
|
||||
* Override default to have better compatibility
|
||||
*
|
||||
* @param {String} table - The table to insert to
|
||||
* @param {Array} [data] - The array of object containing data to insert
|
||||
* @return {String} - The generated sql statement
|
||||
*/
|
||||
driver.insertBatch = (table, data) => {
|
||||
// Get the data values to insert, so they can
|
||||
// be parameterized
|
||||
let sql = '';
|
||||
const first = data.shift();
|
||||
|
||||
const vals = [];
|
||||
data.forEach(obj => {
|
||||
const row = [];
|
||||
Object.keys(obj).forEach(key => {
|
||||
row.push(obj[key]);
|
||||
});
|
||||
vals.push(row);
|
||||
});
|
||||
|
||||
sql += `INSERT INTO ${driver.quoteTable(table)}\n`;
|
||||
|
||||
// Get the field names from the keys of the first
|
||||
// object to be inserted
|
||||
const fields = Object.keys(first);
|
||||
const cols = [];
|
||||
fields.forEach(key => {
|
||||
cols.push(`'${driver._quote(first[key])}' AS ${driver.quoteIdentifiers(key)}`);
|
||||
});
|
||||
|
||||
sql += `SELECT ${cols.join(', ')}\n`;
|
||||
|
||||
vals.forEach(rowValues => {
|
||||
const quoted = rowValues.map(value => String(value).replace('\'', '\'\''));
|
||||
sql += `UNION ALL SELECT '${quoted.join('\', \'')}'\n`;
|
||||
});
|
||||
|
||||
return {
|
||||
sql: sql,
|
||||
values: undefined
|
||||
};
|
||||
};
|
||||
|
||||
return driver;
|
||||
})();
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 116 KiB |
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 118 KiB |
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 120 KiB |
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 114 KiB |
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 120 KiB |
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 117 KiB |
Binary file not shown.
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Home</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Home</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3> </h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,163 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Module: drivers/MSSQLDriver</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Module: drivers/MSSQLDriver</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
<div class="description">Driver for Microsoft SQL Server databases</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="drivers_MSSQLDriver.js.html">drivers/MSSQLDriver.js</a>, <a href="drivers_MSSQLDriver.js.html#line1">line 1</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,163 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Module: drivers/MariaDB</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Module: drivers/MariaDB</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
<div class="description">Driver for MariaDB databases</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="drivers_MariaDB.js.html">drivers/MariaDB.js</a>, <a href="drivers_MariaDB.js.html#line1">line 1</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,163 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Module: drivers/Mysql</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Module: drivers/Mysql</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
<div class="description">Driver for MySQL databases</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="drivers_Mysql.js.html">drivers/Mysql.js</a>, <a href="drivers_Mysql.js.html#line1">line 1</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,163 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Module: drivers/Pg</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Module: drivers/Pg</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
<div class="description">Driver for PostgreSQL databases</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="drivers_Pg.js.html">drivers/Pg.js</a>, <a href="drivers_Pg.js.html#line1">line 1</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,163 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Module: drivers/Sqlite</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Module: drivers/Sqlite</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
<div class="description">Driver for SQLite databases</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="drivers_Sqlite.js.html">drivers/Sqlite.js</a>, <a href="drivers_Sqlite.js.html#line1">line 1</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-drivers_MariaDB.html">drivers/MariaDB</a></li><li><a href="module-drivers_MSSQLDriver.html">drivers/MSSQLDriver</a></li><li><a href="module-drivers_Mysql.html">drivers/Mysql</a></li><li><a href="module-drivers_Pg.html">drivers/Pg</a></li><li><a href="module-drivers_Sqlite.html">drivers/Sqlite</a></li></ul><h3>Classes</h3><ul><li><a href="NodeQuery.html">NodeQuery</a></li><li><a href="QueryBuilder.html">QueryBuilder</a></li><li><a href="Result.html">Result</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Mon Feb 12 2018 14:58:25 GMT-0500 (EST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,25 @@
|
|||
/*global document */
|
||||
(function() {
|
||||
var source = document.getElementsByClassName('prettyprint source linenums');
|
||||
var i = 0;
|
||||
var lineNumber = 0;
|
||||
var lineId;
|
||||
var lines;
|
||||
var totalLines;
|
||||
var anchorHash;
|
||||
|
||||
if (source && source[0]) {
|
||||
anchorHash = document.location.hash.substring(1);
|
||||
lines = source[0].getElementsByTagName('li');
|
||||
totalLines = lines.length;
|
||||
|
||||
for (; i < totalLines; i++) {
|
||||
lineNumber++;
|
||||
lineId = 'line' + lineNumber;
|
||||
lines[i].id = lineId;
|
||||
if (lineId === anchorHash) {
|
||||
lines[i].className += ' selected';
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,2 @@
|
|||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
|
||||
/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);
|
|
@ -0,0 +1,28 @@
|
|||
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
|
||||
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
|
||||
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
|
||||
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
|
||||
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
|
||||
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
|
||||
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
|
||||
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
|
||||
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
|
||||
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
|
||||
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
|
||||
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
|
||||
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
|
||||
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
|
||||
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
|
||||
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
|
||||
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
|
||||
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
|
||||
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
|
||||
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
|
||||
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
|
||||
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
|
||||
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
|
||||
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
|
||||
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
|
||||
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
|
||||
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
|
||||
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();
|
|
@ -0,0 +1,358 @@
|
|||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
src: url('../fonts/OpenSans-Regular-webfont.eot');
|
||||
src:
|
||||
local('Open Sans'),
|
||||
local('OpenSans'),
|
||||
url('../fonts/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('../fonts/OpenSans-Regular-webfont.woff') format('woff'),
|
||||
url('../fonts/OpenSans-Regular-webfont.svg#open_sansregular') format('svg');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans Light';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
src: url('../fonts/OpenSans-Light-webfont.eot');
|
||||
src:
|
||||
local('Open Sans Light'),
|
||||
local('OpenSans Light'),
|
||||
url('../fonts/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('../fonts/OpenSans-Light-webfont.woff') format('woff'),
|
||||
url('../fonts/OpenSans-Light-webfont.svg#open_sanslight') format('svg');
|
||||
}
|
||||
|
||||
html
|
||||
{
|
||||
overflow: auto;
|
||||
background-color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
line-height: 1.5;
|
||||
color: #4d4e53;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
a, a:visited, a:active {
|
||||
color: #0095dd;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
header
|
||||
{
|
||||
display: block;
|
||||
padding: 0px 4px;
|
||||
}
|
||||
|
||||
tt, code, kbd, samp {
|
||||
font-family: Consolas, Monaco, 'Andale Mono', monospace;
|
||||
}
|
||||
|
||||
.class-description {
|
||||
font-size: 130%;
|
||||
line-height: 140%;
|
||||
margin-bottom: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.class-description:empty {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#main {
|
||||
float: left;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
article dl {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
article img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
section
|
||||
{
|
||||
display: block;
|
||||
background-color: #fff;
|
||||
padding: 12px 24px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.variation {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.signature-attributes {
|
||||
font-size: 60%;
|
||||
color: #aaa;
|
||||
font-style: italic;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
nav
|
||||
{
|
||||
display: block;
|
||||
float: right;
|
||||
margin-top: 28px;
|
||||
width: 30%;
|
||||
box-sizing: border-box;
|
||||
border-left: 1px solid #ccc;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif;
|
||||
font-size: 100%;
|
||||
line-height: 17px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
nav ul a, nav ul a:visited, nav ul a:active {
|
||||
font-family: Consolas, Monaco, 'Andale Mono', monospace;
|
||||
line-height: 18px;
|
||||
color: #4D4E53;
|
||||
}
|
||||
|
||||
nav h3 {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
nav li {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
footer {
|
||||
display: block;
|
||||
padding: 6px;
|
||||
margin-top: 12px;
|
||||
font-style: italic;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-weight: 200;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1
|
||||
{
|
||||
font-family: 'Open Sans Light', sans-serif;
|
||||
font-size: 48px;
|
||||
letter-spacing: -2px;
|
||||
margin: 12px 24px 20px;
|
||||
}
|
||||
|
||||
h2, h3.subsection-title
|
||||
{
|
||||
font-size: 30px;
|
||||
font-weight: 700;
|
||||
letter-spacing: -1px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
h3
|
||||
{
|
||||
font-size: 24px;
|
||||
letter-spacing: -0.5px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
h4
|
||||
{
|
||||
font-size: 18px;
|
||||
letter-spacing: -0.33px;
|
||||
margin-bottom: 12px;
|
||||
color: #4d4e53;
|
||||
}
|
||||
|
||||
h5, .container-overview .subsection-title
|
||||
{
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
letter-spacing: -0.01em;
|
||||
margin: 8px 0 3px 0;
|
||||
}
|
||||
|
||||
h6
|
||||
{
|
||||
font-size: 100%;
|
||||
letter-spacing: -0.01em;
|
||||
margin: 6px 0 3px 0;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
border-spacing: 0;
|
||||
border: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td, th
|
||||
{
|
||||
border: 1px solid #ddd;
|
||||
margin: 0px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
padding: 4px 6px;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
thead tr
|
||||
{
|
||||
background-color: #ddd;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
th { border-right: 1px solid #aaa; }
|
||||
tr > th:last-child { border-right: 1px solid #ddd; }
|
||||
|
||||
.ancestors, .attribs { color: #999; }
|
||||
.ancestors a, .attribs a
|
||||
{
|
||||
color: #999 !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.clear
|
||||
{
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.important
|
||||
{
|
||||
font-weight: bold;
|
||||
color: #950B02;
|
||||
}
|
||||
|
||||
.yes-def {
|
||||
text-indent: -1000px;
|
||||
}
|
||||
|
||||
.type-signature {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.name, .signature {
|
||||
font-family: Consolas, Monaco, 'Andale Mono', monospace;
|
||||
}
|
||||
|
||||
.details { margin-top: 14px; border-left: 2px solid #DDD; }
|
||||
.details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; }
|
||||
.details dd { margin-left: 70px; }
|
||||
.details ul { margin: 0; }
|
||||
.details ul { list-style-type: none; }
|
||||
.details li { margin-left: 30px; padding-top: 6px; }
|
||||
.details pre.prettyprint { margin: 0 }
|
||||
.details .object-value { padding-top: 0; }
|
||||
|
||||
.description {
|
||||
margin-bottom: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.code-caption
|
||||
{
|
||||
font-style: italic;
|
||||
font-size: 107%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.prettyprint
|
||||
{
|
||||
border: 1px solid #ddd;
|
||||
width: 80%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.prettyprint.source {
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
.prettyprint code
|
||||
{
|
||||
font-size: 100%;
|
||||
line-height: 18px;
|
||||
display: block;
|
||||
padding: 4px 12px;
|
||||
margin: 0;
|
||||
background-color: #fff;
|
||||
color: #4D4E53;
|
||||
}
|
||||
|
||||
.prettyprint code span.line
|
||||
{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.prettyprint.linenums
|
||||
{
|
||||
padding-left: 70px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.prettyprint.linenums ol
|
||||
{
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.prettyprint.linenums li
|
||||
{
|
||||
border-left: 3px #ddd solid;
|
||||
}
|
||||
|
||||
.prettyprint.linenums li.selected,
|
||||
.prettyprint.linenums li.selected *
|
||||
{
|
||||
background-color: lightyellow;
|
||||
}
|
||||
|
||||
.prettyprint.linenums li *
|
||||
{
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
-ms-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.params .name, .props .name, .name code {
|
||||
color: #4D4E53;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', monospace;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.params td.description > p:first-child,
|
||||
.props td.description > p:first-child
|
||||
{
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.params td.description > p:last-child,
|
||||
.props td.description > p:last-child
|
||||
{
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
color: #454545;
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/* JSDoc prettify.js theme */
|
||||
|
||||
/* plain text */
|
||||
.pln {
|
||||
color: #000000;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* string content */
|
||||
.str {
|
||||
color: #006400;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a keyword */
|
||||
.kwd {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a comment */
|
||||
.com {
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* a type name */
|
||||
.typ {
|
||||
color: #000000;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a literal value */
|
||||
.lit {
|
||||
color: #006400;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* punctuation */
|
||||
.pun {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* lisp open bracket */
|
||||
.opn {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* lisp close bracket */
|
||||
.clo {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a markup tag name */
|
||||
.tag {
|
||||
color: #006400;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a markup attribute name */
|
||||
.atn {
|
||||
color: #006400;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a markup attribute value */
|
||||
.atv {
|
||||
color: #006400;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a declaration */
|
||||
.dec {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a variable name */
|
||||
.var {
|
||||
color: #000000;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a function name */
|
||||
.fun {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* Specify class=linenums on a pre to get line numbering */
|
||||
ol.linenums {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/* Tomorrow Theme */
|
||||
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
|
||||
/* Pretty printing styles. Used with prettify.js. */
|
||||
/* SPAN elements with the classes below are added by prettyprint. */
|
||||
/* plain text */
|
||||
.pln {
|
||||
color: #4d4d4c; }
|
||||
|
||||
@media screen {
|
||||
/* string content */
|
||||
.str {
|
||||
color: #718c00; }
|
||||
|
||||
/* a keyword */
|
||||
.kwd {
|
||||
color: #8959a8; }
|
||||
|
||||
/* a comment */
|
||||
.com {
|
||||
color: #8e908c; }
|
||||
|
||||
/* a type name */
|
||||
.typ {
|
||||
color: #4271ae; }
|
||||
|
||||
/* a literal value */
|
||||
.lit {
|
||||
color: #f5871f; }
|
||||
|
||||
/* punctuation */
|
||||
.pun {
|
||||
color: #4d4d4c; }
|
||||
|
||||
/* lisp open bracket */
|
||||
.opn {
|
||||
color: #4d4d4c; }
|
||||
|
||||
/* lisp close bracket */
|
||||
.clo {
|
||||
color: #4d4d4c; }
|
||||
|
||||
/* a markup tag name */
|
||||
.tag {
|
||||
color: #c82829; }
|
||||
|
||||
/* a markup attribute name */
|
||||
.atn {
|
||||
color: #f5871f; }
|
||||
|
||||
/* a markup attribute value */
|
||||
.atv {
|
||||
color: #3e999f; }
|
||||
|
||||
/* a declaration */
|
||||
.dec {
|
||||
color: #f5871f; }
|
||||
|
||||
/* a variable name */
|
||||
.var {
|
||||
color: #c82829; }
|
||||
|
||||
/* a function name */
|
||||
.fun {
|
||||
color: #4271ae; } }
|
||||
/* Use higher contrast and text-weight for printable form. */
|
||||
@media print, projection {
|
||||
.str {
|
||||
color: #060; }
|
||||
|
||||
.kwd {
|
||||
color: #006;
|
||||
font-weight: bold; }
|
||||
|
||||
.com {
|
||||
color: #600;
|
||||
font-style: italic; }
|
||||
|
||||
.typ {
|
||||
color: #404;
|
||||
font-weight: bold; }
|
||||
|
||||
.lit {
|
||||
color: #044; }
|
||||
|
||||
.pun, .opn, .clo {
|
||||
color: #440; }
|
||||
|
||||
.tag {
|
||||
color: #006;
|
||||
font-weight: bold; }
|
||||
|
||||
.atn {
|
||||
color: #404; }
|
||||
|
||||
.atv {
|
||||
color: #060; } }
|
||||
/* Style */
|
||||
/*
|
||||
pre.prettyprint {
|
||||
background: white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px; }
|
||||
*/
|
||||
|
||||
/* Specify class=linenums on a pre to get line numbering */
|
||||
ol.linenums {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0; }
|
||||
|
||||
/* IE indents via margin-left */
|
||||
li.L0,
|
||||
li.L1,
|
||||
li.L2,
|
||||
li.L3,
|
||||
li.L4,
|
||||
li.L5,
|
||||
li.L6,
|
||||
li.L7,
|
||||
li.L8,
|
||||
li.L9 {
|
||||
/* */ }
|
||||
|
||||
/* Alternate shading for lines */
|
||||
li.L1,
|
||||
li.L3,
|
||||
li.L5,
|
||||
li.L7,
|
||||
li.L9 {
|
||||
/* */ }
|
132
gulpfile.js
132
gulpfile.js
|
@ -1,132 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const documentation = require('gulp-documentation'),
|
||||
eslint = require('gulp-eslint'),
|
||||
gulp = require('gulp'),
|
||||
istanbul = require('gulp-istanbul'),
|
||||
jscs = require('gulp-jscs'),
|
||||
mocha = require('gulp-mocha'),
|
||||
pipe = require('gulp-pipe'),
|
||||
sloc = require('gulp-sloc');
|
||||
|
||||
const SRC_FILES = ['lib/**/*.js'];
|
||||
const TEST_FILES = [
|
||||
'test/*_test.js',
|
||||
'test/adapters/*_test.js'
|
||||
];
|
||||
|
||||
const ESLINT_SETTINGS = {
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"rules": {
|
||||
"arrow-parens": [2, "as-needed"],
|
||||
"no-console": [1],
|
||||
"no-constant-condition": [1],
|
||||
"no-extra-semi": [1],
|
||||
"no-func-assign": [1],
|
||||
"no-obj-calls": [2],
|
||||
"no-unexpected-multiline" : [2],
|
||||
"no-unneeded-ternary": [2],
|
||||
"radix": [2],
|
||||
"no-with": [2],
|
||||
"no-eval": [2],
|
||||
"no-unreachable": [1],
|
||||
"no-irregular-whitespace": [1],
|
||||
"no-new-wrappers": [2],
|
||||
"no-new-func": [2],
|
||||
"curly" : [2, "multi-line"],
|
||||
"no-implied-eval": [2],
|
||||
"no-invalid-this": [2],
|
||||
"constructor-super": [2],
|
||||
"no-dupe-args": [2],
|
||||
"no-dupe-keys": [2],
|
||||
"no-dupe-class-members": [2],
|
||||
"no-this-before-super": [2],
|
||||
"prefer-arrow-callback": [1],
|
||||
"no-var": [2],
|
||||
"valid-jsdoc": [1],
|
||||
"strict": [2, "global"],
|
||||
"callback-return": [1],
|
||||
"object-shorthand": [1, "methods"],
|
||||
"prefer-template": [1]
|
||||
}
|
||||
};
|
||||
|
||||
const MOCHA_OPTIONS = {
|
||||
ui: 'tdd',
|
||||
bail: true,
|
||||
reporter: 'dot',
|
||||
timeout: 10000,
|
||||
};
|
||||
|
||||
gulp.task('lint', () => {
|
||||
pipe(gulp.src(SRC_FILES), [
|
||||
eslint(ESLINT_SETTINGS),
|
||||
eslint.format(),
|
||||
eslint.failAfterError()
|
||||
]);
|
||||
pipe(gulp.src(SRC_FILES), [
|
||||
jscs(),
|
||||
jscs.reporter()
|
||||
]);
|
||||
});
|
||||
|
||||
gulp.task('lint-tests', ['lint'], () => {
|
||||
pipe(gulp.src(['test/**/*.js']), [
|
||||
eslint(ESLINT_SETTINGS),
|
||||
eslint.format(),
|
||||
eslint.failAfterError()
|
||||
]);
|
||||
pipe(gulp.src(['test/**/*.js']), [
|
||||
jscs(),
|
||||
jscs.reporter()
|
||||
]);
|
||||
});
|
||||
|
||||
gulp.task('sloc', () => gulp.src(SRC_FILES).pipe(sloc()));
|
||||
gulp.task('test-sloc', () => gulp.src(TEST_FILES).pipe(sloc()));
|
||||
|
||||
gulp.task('docs', () => {
|
||||
gulp.src(['lib/*.js'])
|
||||
.pipe(documentation({format: 'html'}))
|
||||
.pipe(gulp.dest('docs'));
|
||||
gulp.src(['lib/*.js'])
|
||||
.pipe(documentation({format: 'md'}))
|
||||
.pipe(gulp.dest('.'));
|
||||
});
|
||||
|
||||
gulp.task('mocha', ['lint-tests', 'sloc'], () => {
|
||||
return gulp.src(TEST_FILES)
|
||||
.pipe(mocha(MOCHA_OPTIONS))
|
||||
.once('error', () => {
|
||||
process.exit(1);
|
||||
})
|
||||
.once('end', () => {
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('test', ['test-sloc', 'lint-tests'], function(cb) {
|
||||
return pipe(gulp.src(SRC_FILES), [
|
||||
istanbul(),
|
||||
istanbul.hookRequire()
|
||||
]).on('finish', () => {
|
||||
pipe(gulp.src(TEST_FILES), [
|
||||
mocha(MOCHA_OPTIONS),
|
||||
istanbul.writeReports({
|
||||
dir: './coverage',
|
||||
reporters: ['lcov', 'lcovonly', 'html', 'text']
|
||||
})
|
||||
.once('error', () => {
|
||||
process.exit(1);
|
||||
})
|
||||
.once('end', () => {
|
||||
process.exit();
|
||||
})
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('default', ['lint', 'sloc', 'docs', 'test']);
|
|
@ -1,20 +1,17 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Class that wraps database connection libraries
|
||||
*
|
||||
* @private
|
||||
* @param {Object} instance - The connection object
|
||||
* @param {Promise} instance - The connection object
|
||||
*/
|
||||
class Adapter {
|
||||
/**
|
||||
* Invoke an adapter
|
||||
*
|
||||
* @constructor
|
||||
* @param {Object} instance - The connection object
|
||||
* @param {Promise} instance - Promise holding connection object
|
||||
*/
|
||||
constructor(instance) {
|
||||
constructor (instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
|
@ -23,20 +20,29 @@ class Adapter {
|
|||
*
|
||||
* @param {String} sql - The sql with placeholders
|
||||
* @param {Array} params - The values to insert into the query
|
||||
* @param {Function} [callback] - Callback to run when a response is recieved
|
||||
* @return {void|Promise} - returns a promise if no callback is passed
|
||||
* @return {Promise} - returns a promise resolving to the result of the database query
|
||||
*/
|
||||
execute(/*sql, params, callback*/) {
|
||||
execute (sql, params) {
|
||||
throw new Error('Correct adapter not defined for query execution');
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the adapter's result into a standard format
|
||||
*
|
||||
* @param {*} originalResult - the original result object from the driver
|
||||
* @return {Result} - the new result object
|
||||
*/
|
||||
transformResult (originalResult) {
|
||||
throw new Error('Result transformer method not defined for current adapter');
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the current database connection
|
||||
* @return {void}
|
||||
*/
|
||||
close() {
|
||||
this.instance.end();
|
||||
close () {
|
||||
this.instance.then(conn => conn.end());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Adapter;
|
||||
module.exports = Adapter;
|
||||
|
|
152
lib/Driver.js
152
lib/Driver.js
|
@ -1,13 +1,11 @@
|
|||
'use strict';
|
||||
|
||||
const helpers = require('./helpers');
|
||||
const Helpers = require('./Helpers');
|
||||
|
||||
/**
|
||||
* Base Database Driver
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
let Driver = {
|
||||
const Driver = {
|
||||
identifierStartChar: '"',
|
||||
identifierEndChar: '"',
|
||||
tablePrefix: null,
|
||||
|
@ -20,25 +18,26 @@ let Driver = {
|
|||
* @return {String} - The quoted sql fragment
|
||||
* @private
|
||||
*/
|
||||
_quote(str) {
|
||||
return (helpers.isString(str) && ! (str.startsWith(Driver.identifierStartChar) || str.endsWith(Driver.identifierEndChar)))
|
||||
_quote (str) {
|
||||
return (Helpers.isString(str) &&
|
||||
!(str.startsWith(Driver.identifierStartChar) || str.endsWith(Driver.identifierEndChar))
|
||||
)
|
||||
? `${Driver.identifierStartChar}${str}${Driver.identifierEndChar}`
|
||||
: str;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the limit clause
|
||||
|
||||
* @private
|
||||
* @param {String} sql - SQL statement to modify
|
||||
* @param {Number} limit - Maximum number of rows to fetch
|
||||
* @param {Number} [offset] - Number of rows to skip
|
||||
* @return {String} - Modified SQL statement
|
||||
*/
|
||||
limit(sql, limit, offset) {
|
||||
sql += ` LIMIT ${limit}`;
|
||||
limit (sql, limit, offset) {
|
||||
sql += ` LIMIT ${limit}`;
|
||||
|
||||
if (helpers.isNumber(offset))
|
||||
{
|
||||
if (Helpers.isNumber(offset)) {
|
||||
sql += ` OFFSET ${offset}`;
|
||||
}
|
||||
|
||||
|
@ -48,10 +47,11 @@ let Driver = {
|
|||
/**
|
||||
* Quote database table name, and set prefix
|
||||
*
|
||||
* @private
|
||||
* @param {String} table - Table name to quote
|
||||
* @return {String} - Quoted table name
|
||||
*/
|
||||
quoteTable(table) {
|
||||
quoteTable (table) {
|
||||
// Quote after prefix
|
||||
return Driver.quoteIdentifiers(table);
|
||||
},
|
||||
|
@ -59,43 +59,43 @@ let Driver = {
|
|||
/**
|
||||
* Use the driver's escape character to quote identifiers
|
||||
*
|
||||
* @private
|
||||
* @param {String|Array} str - String or array of strings to quote identifiers
|
||||
* @return {String|Array} - Quoted identifier(s)
|
||||
*/
|
||||
quoteIdentifiers(str) {
|
||||
let hiers, raw;
|
||||
let pattern = new RegExp(
|
||||
`${Driver.identifierStartChar}(`
|
||||
+ '([a-zA-Z0-9_]+)' + '(\((.*?)\))'
|
||||
+ `)${Driver.identifierEndChar}`, 'ig');
|
||||
quoteIdentifiers (str) {
|
||||
const pattern = new RegExp(
|
||||
`${Driver.identifierStartChar}(` +
|
||||
'([a-zA-Z0-9_]+)' + '(((.*?)))' +
|
||||
`)${Driver.identifierEndChar}`, 'ig');
|
||||
|
||||
// Recurse for arrays of identifiiers
|
||||
if (Array.isArray(str))
|
||||
{
|
||||
// Recurse for arrays of identifiers
|
||||
if (Array.isArray(str)) {
|
||||
return str.map(Driver.quoteIdentifiers);
|
||||
}
|
||||
|
||||
// cast to string so that you don't have undefined method errors with junk data
|
||||
str = String(str);
|
||||
|
||||
// Handle commas
|
||||
if (str.includes(','))
|
||||
{
|
||||
let parts = str.split(',').map(helpers.stringTrim);
|
||||
if (str.includes(',')) {
|
||||
const parts = str.split(',').map(Helpers.stringTrim);
|
||||
str = parts.map(Driver.quoteIdentifiers).join(',');
|
||||
}
|
||||
|
||||
// Split identifiers by period
|
||||
hiers = str.split('.').map(Driver._quote);
|
||||
raw = hiers.join('.');
|
||||
const hierarchies = str.split('.').map(Driver._quote);
|
||||
let raw = hierarchies.join('.');
|
||||
|
||||
// Fix functions
|
||||
if (raw.includes('(') && raw.includes(')'))
|
||||
{
|
||||
let funcs = pattern.exec(raw);
|
||||
if (raw.includes('(') && raw.includes(')')) {
|
||||
const functionCalls = pattern.exec(raw);
|
||||
|
||||
// Unquote the function
|
||||
raw = raw.replace(funcs[0], funcs[1]);
|
||||
raw = raw.replace(functionCalls[0], functionCalls[1]);
|
||||
|
||||
// Quote the identifiers inside of the parens
|
||||
let inParens = funcs[3].substring(1, funcs[3].length - 1);
|
||||
const inParens = functionCalls[3].substring(1, functionCalls[3].length - 1);
|
||||
raw = raw.replace(inParens, Driver.quoteIdentifiers(inParens));
|
||||
}
|
||||
|
||||
|
@ -105,10 +105,11 @@ let Driver = {
|
|||
/**
|
||||
* Generate SQL to truncate the passed table
|
||||
*
|
||||
* @private
|
||||
* @param {String} table - Table to truncate
|
||||
* @return {String} - Truncation SQL
|
||||
*/
|
||||
truncate(table) {
|
||||
truncate (table) {
|
||||
let sql = (Driver.hasTruncate)
|
||||
? 'TRUNCATE '
|
||||
: 'DELETE FROM ';
|
||||
|
@ -121,23 +122,21 @@ let Driver = {
|
|||
/**
|
||||
* Generate SQL to insert a group of rows
|
||||
*
|
||||
* @private
|
||||
* @param {String} table - The table to insert to
|
||||
* @param {Array} [data] - The array of object containing data to insert
|
||||
* @return {String} - Query and data to insert
|
||||
*/
|
||||
insertBatch(table, data) {
|
||||
let vals = [],
|
||||
fields = Object.keys(data[0]),
|
||||
sql = '',
|
||||
params = [],
|
||||
paramString = '',
|
||||
paramList = [];
|
||||
insertBatch (table, data) {
|
||||
const values = [];
|
||||
const fields = Object.keys(data[0]);
|
||||
let sql = '';
|
||||
|
||||
// Get the data values to insert, so they can
|
||||
// be parameterized
|
||||
data.forEach(obj => {
|
||||
Object.keys(obj).forEach(key => {
|
||||
vals.push(obj[key]);
|
||||
values.push(obj[key]);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -148,17 +147,80 @@ let Driver = {
|
|||
sql += `INSERT INTO ${table} (${Driver.quoteIdentifiers(fields).join(',')}) VALUES `;
|
||||
|
||||
// Create placeholder groups
|
||||
params = Array(fields.length).fill('?');
|
||||
paramString = `(${params.join(',')})`;
|
||||
paramList = Array(data.length).fill(paramString);
|
||||
const params = Array(fields.length).fill('?');
|
||||
const paramString = `(${params.join(',')})`;
|
||||
const paramList = Array(data.length).fill(paramString);
|
||||
|
||||
sql += paramList.join(',');
|
||||
|
||||
return {
|
||||
sql: sql,
|
||||
values: vals,
|
||||
values: values
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a batch update sql statement
|
||||
*
|
||||
* @private
|
||||
* @param {String} table - The name of the table to update
|
||||
* @param {Array<Object>} data - Array of objects containing the update data
|
||||
* @param {String} updateKey - the field name to update based on
|
||||
* @return {Array<String,Object,Number>} - array of parameters passed to run the query
|
||||
*/
|
||||
updateBatch (table, data, updateKey) {
|
||||
let affectedRows = 0;
|
||||
let insertData = [];
|
||||
const fieldLines = [];
|
||||
|
||||
let sql = `UPDATE ${Driver.quoteTable(table)} SET `;
|
||||
|
||||
// get the keys of the current set of data, except the one used to
|
||||
// set the update condition
|
||||
const fields = data.reduce((previous, current) => {
|
||||
affectedRows++;
|
||||
const keys = Object.keys(current).filter(key => {
|
||||
return key !== updateKey && !previous.includes(key);
|
||||
});
|
||||
return previous.concat(keys);
|
||||
}, []);
|
||||
|
||||
// Create the CASE blocks for each data set
|
||||
fields.forEach(field => {
|
||||
let line = `${Driver.quoteIdentifiers(field)} = CASE\n`;
|
||||
const cases = [];
|
||||
data.forEach(currentCase => {
|
||||
insertData.push(currentCase[updateKey]);
|
||||
insertData.push(currentCase[field]);
|
||||
|
||||
const newCase = `WHEN ${Driver.quoteIdentifiers(updateKey)} =? THEN ? `;
|
||||
cases.push(newCase);
|
||||
});
|
||||
|
||||
line += `${cases.join('\n')}\n`;
|
||||
line += `ELSE ${Driver.quoteIdentifiers(field)} END`;
|
||||
|
||||
fieldLines.push(line);
|
||||
});
|
||||
|
||||
sql += `${fieldLines.join(',\n')}\n`;
|
||||
|
||||
const whereValues = [];
|
||||
data.forEach(entry => {
|
||||
const insertValue = entry[updateKey];
|
||||
whereValues.push(insertValue);
|
||||
insertData.push(insertValue);
|
||||
});
|
||||
|
||||
// Create the placeholders for the WHERE IN clause
|
||||
const placeholders = Array(whereValues.length);
|
||||
placeholders.fill('?');
|
||||
|
||||
sql += `WHERE ${Driver.quoteIdentifiers(updateKey)} IN `;
|
||||
sql += `( ${placeholders.join(',')} )`;
|
||||
|
||||
return [sql, insertData, affectedRows];
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Driver;
|
||||
module.exports = Driver;
|
||||
|
|
|
@ -1,18 +1,38 @@
|
|||
'use strict';
|
||||
const fs = require('fs');
|
||||
|
||||
/**
|
||||
* Various internal helper functions
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
let helpers = {
|
||||
class Helpers {
|
||||
/**
|
||||
* Get the contents of a file
|
||||
*
|
||||
* @param {string} file - The path to the file
|
||||
* @return {Promise<string>} - Promise resolving to the contents of the file
|
||||
*/
|
||||
static readFile (file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(file, (err, data) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
return resolve(Buffer.from(data).toString());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap String.prototype.trim in a way that is easily mappable
|
||||
*
|
||||
* @param {String} str - The string to trim
|
||||
* @return {String} - The trimmed string
|
||||
*/
|
||||
stringTrim: str => str.trim(),
|
||||
static stringTrim (str) {
|
||||
return str.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the variable passed
|
||||
*
|
||||
|
@ -21,8 +41,8 @@ let helpers = {
|
|||
* @param {mixed} o - Object to type check
|
||||
* @return {String} - Type of the object
|
||||
*/
|
||||
type: o => {
|
||||
let type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
|
||||
static type (o) {
|
||||
const type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
|
||||
|
||||
// handle NaN and Infinity
|
||||
if (type === 'number') {
|
||||
|
@ -36,17 +56,18 @@ let helpers = {
|
|||
}
|
||||
|
||||
return type;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether an object is scalar
|
||||
*
|
||||
* @param {mixed} obj - Object to test
|
||||
* @return {bool} - Is object scalar
|
||||
* @return {boolean} - Is object scalar
|
||||
*/
|
||||
isScalar: obj => {
|
||||
let scalar = ['string', 'number', 'boolean'];
|
||||
return scalar.indexOf(helpers.type(obj)) !== -1;
|
||||
},
|
||||
static isScalar (obj) {
|
||||
return ['string', 'number', 'boolean'].includes(Helpers.type(obj));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of values with a common key from an array of objects
|
||||
*
|
||||
|
@ -54,8 +75,8 @@ let helpers = {
|
|||
* @param {String} key - The key of the object to get
|
||||
* @return {Array} - The new array of plucked values
|
||||
*/
|
||||
arrayPluck: (arr, key) => {
|
||||
let output = [];
|
||||
static arrayPluck (arr, key) {
|
||||
const output = [];
|
||||
|
||||
// Empty case
|
||||
if (arr.length === 0) {
|
||||
|
@ -63,13 +84,14 @@ let helpers = {
|
|||
}
|
||||
|
||||
arr.forEach(obj => {
|
||||
if (! helpers.isUndefined(obj[key])) {
|
||||
if (!Helpers.isUndefined(obj[key])) {
|
||||
output.push(obj[key]);
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a value matching the passed regular expression is
|
||||
* in the passed array
|
||||
|
@ -78,15 +100,14 @@ let helpers = {
|
|||
* @param {RegExp} pattern - The pattern to match
|
||||
* @return {Boolean} - If an array item matches the pattern
|
||||
*/
|
||||
regexInArray: (arr, pattern) => {
|
||||
static regexInArray (arr, pattern) {
|
||||
// Empty case(s)
|
||||
if (! helpers.isArray(arr) || arr.length === 0) {
|
||||
if (!Helpers.isArray(arr) || arr.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let i, l = arr.length;
|
||||
|
||||
for (i = 0; i < l; i++) {
|
||||
const l = arr.length;
|
||||
for (let i = 0; i < l; i++) {
|
||||
// Short circuit if any items match
|
||||
if (pattern.test(arr[i])) {
|
||||
return true;
|
||||
|
@ -94,22 +115,23 @@ let helpers = {
|
|||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the first letter of the string uppercase
|
||||
* Make the first constter of the string uppercase
|
||||
*
|
||||
* @param {String} str - The string to modify
|
||||
* @return {String} - The modified string
|
||||
*/
|
||||
upperCaseFirst: str => {
|
||||
static upperCaseFirst (str) {
|
||||
str += '';
|
||||
let first = str.charAt(0).toUpperCase();
|
||||
const first = str.charAt(0).toUpperCase();
|
||||
return first + str.substr(1);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Define an 'is' method for each type
|
||||
let types = [
|
||||
const types = [
|
||||
'Null',
|
||||
'Undefined',
|
||||
'Object',
|
||||
|
@ -121,25 +143,27 @@ let types = [
|
|||
'RegExp',
|
||||
'NaN',
|
||||
'Infinite',
|
||||
'Promise'
|
||||
];
|
||||
types.forEach(t => {
|
||||
/**
|
||||
* Determine whether a variable is of the type specified in the
|
||||
* function name, eg isNumber
|
||||
*
|
||||
* Types available are Null, Undefined, Object, Array, String, Number, Boolean, Function, RegExp, NaN and Infinite
|
||||
* Types available are Null, Undefined, Object, Array, String, Number,
|
||||
* Boolean, Function, RegExp, NaN, Infinite, Promise
|
||||
*
|
||||
* @private
|
||||
* @param {mixed} o - The object to check its type
|
||||
* @return {Boolean} - If the type matches
|
||||
*/
|
||||
helpers[`is${t}`] = function (o) {
|
||||
Helpers[`is${t}`] = function (o) {
|
||||
if (t.toLowerCase() === 'infinite') {
|
||||
t = 'infinity';
|
||||
}
|
||||
|
||||
return helpers.type(o) === t.toLowerCase();
|
||||
};
|
||||
return Helpers.type(o) === t.toLowerCase();
|
||||
};
|
||||
});
|
||||
|
||||
module.exports = helpers;
|
||||
module.exports = Helpers;
|
|
@ -1,57 +1,66 @@
|
|||
'use strict';
|
||||
const QueryBuilder = require('./QueryBuilder');
|
||||
|
||||
let fs = require('fs'),
|
||||
helpers = require('./helpers'),
|
||||
QueryBuilder = require('./QueryBuilder');
|
||||
// Map config driver name to code class name
|
||||
const dbDriverMap = new Map([
|
||||
['my', 'Mysql'],
|
||||
['mysql', 'Mysql'],
|
||||
['maria', 'Mysql'],
|
||||
['mariadb', 'Mysql'],
|
||||
['firebird', 'Firebird'],
|
||||
['postgresql', 'Pg'],
|
||||
['postgres', 'Pg'],
|
||||
['pg', 'Pg'],
|
||||
['sqlite3', 'Sqlite'],
|
||||
['sqlite', 'Sqlite'],
|
||||
['sqlserver', 'MSSQLServer'],
|
||||
['mssql', 'MSSQLServer']
|
||||
]);
|
||||
|
||||
/**
|
||||
* Class for connection management
|
||||
*
|
||||
* @param {object} config - connection parameters
|
||||
*/
|
||||
class NodeQuery {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @private
|
||||
* @constructor
|
||||
* @param {object} config - connection parameters
|
||||
* @param {string} config.driver - the database driver to use, such as mysql, sqlite, mssql, or pgsql
|
||||
* @param {object|string} config.connection - the connection options for the database
|
||||
* @param {string} config.connection.host - the ip or hostname of the database server
|
||||
* @param {string} config.connection.user - the user to log in as
|
||||
* @param {string} config.connection.password - the password to log in with
|
||||
* @param {string} config.connection.database - the name of the database to connect to
|
||||
* @example let nodeQuery = require('ci-node-query')({
|
||||
* driver: 'mysql',
|
||||
* connection: {
|
||||
* host: 'localhost',
|
||||
* user: 'root',
|
||||
* password: '',
|
||||
* database: 'mysql'
|
||||
* }
|
||||
* });
|
||||
* @example let nodeQuery = require('ci-node-query')({
|
||||
* driver: 'sqlite',
|
||||
* connection: ':memory:'
|
||||
* });
|
||||
*/
|
||||
constructor() {
|
||||
constructor (config) {
|
||||
this.instance = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a query builder object
|
||||
*
|
||||
* @param {String} driverType - The name of the database type, eg. mysql or pg
|
||||
* @param {Object} connObject - A connection object from the database library you are connecting with
|
||||
* @param {String} [connLib] - The name of the db connection library you are using, eg. mysql or mysql2. Optional if the same as driverType
|
||||
* @return {QueryBuilder} - The Query Builder object
|
||||
*/
|
||||
init(driverType, connObject, connLib) {
|
||||
connLib = connLib || driverType;
|
||||
if (config !== undefined) {
|
||||
const driverName = dbDriverMap.get(config.driver);
|
||||
|
||||
let paths = {
|
||||
driver: `${__dirname}/drivers/${helpers.upperCaseFirst(driverType)}`,
|
||||
adapter: `${__dirname}/adapters/${connLib}`,
|
||||
};
|
||||
|
||||
Object.keys(paths).forEach(type => {
|
||||
try {
|
||||
fs.statSync(`${paths[type]}.js`);
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`Selected ${type} (${helpers.upperCaseFirst(driverType)}) does not exist!`
|
||||
);
|
||||
if (!driverName) {
|
||||
throw new Error(`Selected driver (${config.driver}) does not exist!`);
|
||||
}
|
||||
});
|
||||
|
||||
let driver = require(paths.driver);
|
||||
let $adapter = require(paths.adapter);
|
||||
let adapter = new $adapter(connObject);
|
||||
const driver = require(`./drivers/${driverName}`);
|
||||
const Adapter = require(`./adapters/${driverName}`);
|
||||
|
||||
this.instance = new QueryBuilder(driver, adapter);
|
||||
|
||||
return this.instance;
|
||||
this.instance = new QueryBuilder(driver, Adapter(config));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,7 +68,7 @@ class NodeQuery {
|
|||
*
|
||||
* @return {QueryBuilder} - The Query Builder object
|
||||
*/
|
||||
getQuery() {
|
||||
getQuery () {
|
||||
if (this.instance == null) {
|
||||
throw new Error('No Query Builder instance to return');
|
||||
}
|
||||
|
@ -68,4 +77,4 @@ class NodeQuery {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = new NodeQuery();
|
||||
module.exports = config => new NodeQuery(config);
|
||||
|
|
|
@ -1,322 +1,47 @@
|
|||
'use strict';
|
||||
|
||||
const getArgs = require('getargs');
|
||||
const helpers = require('./helpers');
|
||||
const State = require('./State');
|
||||
const QueryParser = require('./QueryParser');
|
||||
|
||||
class QueryBuilderBase {
|
||||
/**
|
||||
* @private
|
||||
* @constructor
|
||||
* @param {Driver} Driver - The syntax driver for the database
|
||||
* @param {Adapter} Adapter - The database module adapter for running queries
|
||||
*/
|
||||
constructor(Driver, Adapter) {
|
||||
this.driver = Driver;
|
||||
this.adapter = Adapter;
|
||||
this.parser = new QueryParser(this.driver);
|
||||
this.state = new State();
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the sql building based on the type provided
|
||||
*
|
||||
* @private
|
||||
* @param {String} type - Type of SQL query
|
||||
* @param {String} table - The table to run the query on
|
||||
* @return {String} - The compiled sql
|
||||
*/
|
||||
_compile(type, table) {
|
||||
// Put together the basic query
|
||||
let sql = this._compileType(type, table);
|
||||
|
||||
// Set each subClause
|
||||
['queryMap', 'groupString', 'orderString', 'havingMap'].forEach(clause => {
|
||||
let param = this.state[clause];
|
||||
|
||||
if (! helpers.isScalar(param)) {
|
||||
Object.keys(param).forEach(part => {
|
||||
sql += param[part].conjunction + param[part].string;
|
||||
});
|
||||
} else {
|
||||
sql += param;
|
||||
}
|
||||
});
|
||||
|
||||
// Append the limit, if it exists
|
||||
if (helpers.isNumber(this.state.limit)) {
|
||||
sql = this.driver.limit(sql, this.state.limit, this.state.offset);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
_compileType(type, table) {
|
||||
let sql = '';
|
||||
|
||||
switch (type) {
|
||||
case 'insert':
|
||||
let params = Array(this.state.setArrayKeys.length).fill('?');
|
||||
|
||||
sql = `INSERT INTO ${table} (`;
|
||||
sql += this.state.setArrayKeys.join(',');
|
||||
sql += `) VALUES (${params.join(',')})`;
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
sql = `UPDATE ${table} SET ${this.state.setString}`;
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
sql = `DELETE FROM ${table}`;
|
||||
break;
|
||||
|
||||
default:
|
||||
sql = `SELECT * FROM ${this.state.fromString}`;
|
||||
|
||||
// Set the select string
|
||||
if (this.state.selectString.length > 0) {
|
||||
// Replace the star with the selected fields
|
||||
sql = sql.replace('*', this.state.selectString);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
_like(field, val, pos, like, conj) {
|
||||
field = this.driver.quoteIdentifiers(field);
|
||||
|
||||
like = `${field} ${like} ?`;
|
||||
|
||||
if (pos === 'before') {
|
||||
val = `%${val}`;
|
||||
} else if (pos === 'after') {
|
||||
val = `${val}%`;
|
||||
} else {
|
||||
val = `%${val}%`;
|
||||
}
|
||||
|
||||
conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ` ${conj} `;
|
||||
this._appendMap(conj, like, 'like');
|
||||
|
||||
this.state.whereValues.push(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a clause to the query map
|
||||
*
|
||||
* @private
|
||||
* @param {String} conjunction - linking keyword for the clause
|
||||
* @param {String} string - pre-compiled sql fragment
|
||||
* @param {String} type - type of sql clause
|
||||
* @return {void}
|
||||
*/
|
||||
_appendMap(conjunction, string, type) {
|
||||
this.state.queryMap.push({
|
||||
type: type,
|
||||
conjunction: conjunction,
|
||||
string: string,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle key/value pairs in an object the same way as individual arguments,
|
||||
* when appending to state
|
||||
*
|
||||
* @private
|
||||
* @return {Array} - modified state array
|
||||
*/
|
||||
_mixedSet(/* $letName, $valType, $key, [$val] */) {
|
||||
let args = getArgs('$letName:string, $valType:string, $key:object|string|number, [$val]', arguments);
|
||||
|
||||
let obj = {};
|
||||
|
||||
if (helpers.isScalar(args.$key) && !helpers.isUndefined(args.$val)) {
|
||||
// Convert key/val pair to a simple object
|
||||
obj[args.$key] = args.$val;
|
||||
} else if (helpers.isScalar(args.$key) && helpers.isUndefined(args.$val)) {
|
||||
// If just a string for the key, and no value, create a simple object with duplicate key/val
|
||||
obj[args.$key] = args.$key;
|
||||
} else {
|
||||
obj = args.$key;
|
||||
}
|
||||
|
||||
Object.keys(obj).forEach(k => {
|
||||
// If a single value for the return
|
||||
if (['key', 'value'].indexOf(args.$valType) !== -1) {
|
||||
let pushVal = (args.$valType === 'key') ? k : obj[k];
|
||||
this.state[args.$letName].push(pushVal);
|
||||
} else {
|
||||
this.state[args.$letName][k] = obj[k];
|
||||
}
|
||||
});
|
||||
|
||||
return this.state[args.$letName];
|
||||
}
|
||||
|
||||
_whereMixedSet(/*key, val*/) {
|
||||
let args = getArgs('key:string|object, [val]', arguments);
|
||||
|
||||
this.state.whereMap = [];
|
||||
this.state.rawWhereValues = [];
|
||||
|
||||
this._mixedSet('whereMap', 'both', args.key, args.val);
|
||||
this._mixedSet('rawWhereValues', 'value', args.key, args.val);
|
||||
}
|
||||
|
||||
_fixConjunction(conj) {
|
||||
let lastItem = this.state.queryMap[this.state.queryMap.length - 1];
|
||||
let conjunctionList = helpers.arrayPluck(this.state.queryMap, 'conjunction');
|
||||
|
||||
if (this.state.queryMap.length === 0 || (! helpers.regexInArray(conjunctionList, /^ ?WHERE/i))) {
|
||||
conj = ' WHERE ';
|
||||
} else if (lastItem.type === 'groupStart') {
|
||||
conj = '';
|
||||
} else {
|
||||
conj = ` ${conj} `;
|
||||
}
|
||||
|
||||
return conj;
|
||||
}
|
||||
|
||||
_where(key, val, defaultConj) {
|
||||
// Normalize key and value and insert into this.state.whereMap
|
||||
this._whereMixedSet(key, val);
|
||||
|
||||
// Parse the where condition to account for operators,
|
||||
// functions, identifiers, and literal values
|
||||
this.state = this.parser.parseWhere(this.driver, this.state);
|
||||
|
||||
this.state.whereMap.forEach(clause => {
|
||||
let conj = this._fixConjunction(defaultConj);
|
||||
this._appendMap(conj, clause, 'where');
|
||||
});
|
||||
|
||||
this.state.whereMap = {};
|
||||
}
|
||||
|
||||
_whereNull(field, stmt, conj) {
|
||||
field = this.driver.quoteIdentifiers(field);
|
||||
let item = `${field} ${stmt}`;
|
||||
|
||||
this._appendMap(this._fixConjunction(conj), item, 'whereNull');
|
||||
}
|
||||
|
||||
_having(/*key, val, conj*/) {
|
||||
let args = getArgs('key:string|object, [val]:string|number, [conj]:string', arguments);
|
||||
args.conj = args.conj || 'AND';
|
||||
args.val = args.val || null;
|
||||
|
||||
// Normalize key/val and put in state.whereMap
|
||||
this._whereMixedSet(args.key, args.val);
|
||||
|
||||
// Parse the having condition to account for operators,
|
||||
// functions, identifiers, and literal values
|
||||
this.state = this.parser.parseWhere(this.driver, this.state);
|
||||
|
||||
this.state.whereMap.forEach(clause => {
|
||||
// Put in the having map
|
||||
this.state.havingMap.push({
|
||||
conjunction: (this.state.havingMap.length > 0) ? ` ${args.conj} ` : ' HAVING ',
|
||||
string: clause,
|
||||
});
|
||||
});
|
||||
|
||||
// Clear the where Map
|
||||
this.state.whereMap = {};
|
||||
|
||||
}
|
||||
|
||||
_whereIn(/*key, val, inClause, conj*/) {
|
||||
let args = getArgs('key:string, val:array, inClause:string, conj:string', arguments);
|
||||
|
||||
args.key = this.driver.quoteIdentifiers(args.key);
|
||||
let params = Array(args.val.length);
|
||||
params.fill('?');
|
||||
|
||||
args.val.forEach(value => {
|
||||
this.state.whereValues.push(value);
|
||||
});
|
||||
|
||||
args.conj = (this.state.queryMap.length > 0) ? ` ${args.conj} ` : ' WHERE ';
|
||||
let str = `${args.key} ${args.inClause} (${params.join(',')}) `;
|
||||
|
||||
this._appendMap(args.conj, str, 'whereIn');
|
||||
}
|
||||
|
||||
_run(type, table, callback, sql, vals) {
|
||||
|
||||
if (! sql) {
|
||||
sql = this._compile(type, table);
|
||||
}
|
||||
|
||||
if (! vals) {
|
||||
vals = this.state.values.concat(this.state.whereValues);
|
||||
}
|
||||
|
||||
// Reset the state so another query can be built
|
||||
this._resetState();
|
||||
|
||||
// Pass the sql and values to the adapter to run on the database
|
||||
if (callback) {
|
||||
return this.query(sql, vals, callback);
|
||||
} else {
|
||||
return this.query(sql, vals);
|
||||
}
|
||||
}
|
||||
|
||||
_getCompile(type, table, reset) {
|
||||
reset = reset || false;
|
||||
|
||||
let sql = this._compile(type, table);
|
||||
|
||||
if (reset) {
|
||||
this._resetState();
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
_resetState() {
|
||||
this.state = new State();
|
||||
}
|
||||
}
|
||||
const Helpers = require('./Helpers');
|
||||
const QueryBuilderBase = require('./QueryBuilderBase');
|
||||
|
||||
/**
|
||||
* Main object that builds SQL queries.
|
||||
*
|
||||
* @param {Driver} Driver - The syntax driver for the database
|
||||
* @param {Adapter} Adapter - The database module adapter for running queries
|
||||
* @extends QueryBuilderBase
|
||||
*/
|
||||
class QueryBuilder extends QueryBuilderBase {
|
||||
/**
|
||||
* @private
|
||||
* @constructor
|
||||
* @param {Driver} Driver - The syntax driver for the database
|
||||
* @param {Adapter} Adapter - The database module adapter for running queries
|
||||
*/
|
||||
constructor(Driver, Adapter) {
|
||||
super(Driver, Adapter);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ! Miscellaneous Methods
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Manually make an sql query
|
||||
* Run a set of queries from a file
|
||||
*
|
||||
* @param {string} file - The path to the sql file
|
||||
* @param {string} [separator=';'] - The character separating each query
|
||||
* @return {Promise} - The result of all the queries
|
||||
*/
|
||||
queryFile (file, separator = ';') {
|
||||
return Helpers.readFile(file).then(sqlFile => {
|
||||
const queries = sqlFile.split(separator);
|
||||
const results = [];
|
||||
|
||||
queries.forEach(sql => {
|
||||
results.push(this.query(sql));
|
||||
});
|
||||
|
||||
return Promise.all(results);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an arbitrary sql query. Run as a prepared statement.
|
||||
*
|
||||
* @param {string} sql - The sql to execute
|
||||
* @param {array} [params] - The query parameters
|
||||
* @param {function} [callback] - Optional callback
|
||||
* @return {void|Promise} - Returns a promise if no callback is supplied
|
||||
* @param {Array} [params] - The query parameters
|
||||
* @return {Promise} - Promise with result of query
|
||||
*/
|
||||
query(/*sql:string, [params]:array, [callback]:function*/) {
|
||||
return this.adapter.execute.apply(this.adapter, arguments);
|
||||
query (sql, params) {
|
||||
return this.adapter.execute(sql, params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -324,7 +49,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
*
|
||||
* @return {void}
|
||||
*/
|
||||
resetQuery() {
|
||||
resetQuery () {
|
||||
this._resetState();
|
||||
}
|
||||
|
||||
|
@ -334,16 +59,26 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @private
|
||||
* @return {Object} - The State object
|
||||
*/
|
||||
getState() {
|
||||
getState () {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties the selected database table
|
||||
*
|
||||
* @param {string} table - the name of the table to truncate
|
||||
* @return {void|Promise} - Returns a promise if no callback is supplied
|
||||
*/
|
||||
truncate (table) {
|
||||
return this.query(this.driver.truncate(table));
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the database connection for the current adapter
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
end() {
|
||||
end () {
|
||||
this.adapter.close();
|
||||
}
|
||||
|
||||
|
@ -359,21 +94,20 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @example query.select(['foo', 'bar']); // Select multiple fileds with an array
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
select(fields) {
|
||||
|
||||
select (fields) {
|
||||
// Split/trim fields by comma
|
||||
fields = (Array.isArray(fields))
|
||||
? fields
|
||||
: fields.split(',').map(helpers.stringTrim);
|
||||
: fields.split(',').map(Helpers.stringTrim);
|
||||
|
||||
// Split on 'As'
|
||||
fields.forEach((field, index) => {
|
||||
if (field.match(/as/i)) {
|
||||
fields[index] = field.split(/ as /i).map(helpers.stringTrim);
|
||||
if (/as/i.test(field)) {
|
||||
fields[index] = field.split(/ as /i).map(Helpers.stringTrim);
|
||||
}
|
||||
});
|
||||
|
||||
let safeArray = this.driver.quoteIdentifiers(fields);
|
||||
const safeArray = this.driver.quoteIdentifiers(fields);
|
||||
|
||||
// Join the strings back together
|
||||
safeArray.forEach((field, index) => {
|
||||
|
@ -395,9 +129,9 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @example query.from('tableName t'); // Select the table with an alias
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
from(tableName) {
|
||||
from (tableName) {
|
||||
// Split identifiers on spaces
|
||||
let identArray = tableName.trim().split(' ').map(helpers.stringTrim);
|
||||
let identArray = tableName.trim().split(' ').map(Helpers.stringTrim);
|
||||
|
||||
// Quote/prefix identifiers
|
||||
identArray[0] = this.driver.quoteTable(identArray[0]);
|
||||
|
@ -417,7 +151,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
like(field, val, pos) {
|
||||
like (field, val, pos) {
|
||||
this._like(field, val, pos, ' LIKE ', 'AND');
|
||||
return this;
|
||||
}
|
||||
|
@ -430,7 +164,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
notLike(field, val, pos) {
|
||||
notLike (field, val, pos) {
|
||||
this._like(field, val, pos, ' NOT LIKE ', 'AND');
|
||||
return this;
|
||||
}
|
||||
|
@ -443,7 +177,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orLike(field, val, pos) {
|
||||
orLike (field, val, pos) {
|
||||
this._like(field, val, pos, ' LIKE ', 'OR');
|
||||
return this;
|
||||
}
|
||||
|
@ -456,7 +190,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orNotLike(field, val, pos) {
|
||||
orNotLike (field, val, pos) {
|
||||
this._like(field, val, pos, ' NOT LIKE ', 'OR');
|
||||
return this;
|
||||
}
|
||||
|
@ -468,10 +202,8 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String|Number} [val] - The value to compare if the value of key is a string
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
having(/*key, [val]*/) {
|
||||
let args = getArgs('key:string|object, [val]:string|number', arguments);
|
||||
|
||||
this._having(args.key, args.val, 'AND');
|
||||
having (key, val = null) {
|
||||
this._having(key, val, 'AND');
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -482,10 +214,8 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String|Number} [val] - The value to compare if the value of key is a string
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orHaving(/*key, [val]*/) {
|
||||
let args = getArgs('key:string|object, [val]:string|number', arguments);
|
||||
|
||||
this._having(args.key, args.val, 'OR');
|
||||
orHaving (key, val = null) {
|
||||
this._having(key, val, 'OR');
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -496,7 +226,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String|Number} [val] - The value to compare if the value of key is a string
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
where(key, val) {
|
||||
where (key, val) {
|
||||
this._where(key, val, 'AND');
|
||||
return this;
|
||||
}
|
||||
|
@ -508,7 +238,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String|Number} [val] - The value to compare if the value of key is a string
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orWhere(key, val) {
|
||||
orWhere (key, val) {
|
||||
this._where(key, val, 'OR');
|
||||
return this;
|
||||
}
|
||||
|
@ -519,7 +249,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String} field - The name of the field that has a NULL value
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
whereIsNull(field) {
|
||||
whereIsNull (field) {
|
||||
this._whereNull(field, 'IS NULL', 'AND');
|
||||
return this;
|
||||
}
|
||||
|
@ -530,7 +260,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String} field - The name so the field that is not to be null
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
whereIsNotNull(field) {
|
||||
whereIsNotNull (field) {
|
||||
this._whereNull(field, 'IS NOT NULL', 'AND');
|
||||
return this;
|
||||
}
|
||||
|
@ -541,7 +271,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String} field - The name of the field
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orWhereIsNull(field) {
|
||||
orWhereIsNull (field) {
|
||||
this._whereNull(field, 'IS NULL', 'OR');
|
||||
return this;
|
||||
}
|
||||
|
@ -552,7 +282,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String} field - The name of the field
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orWhereIsNotNull(field) {
|
||||
orWhereIsNotNull (field) {
|
||||
this._whereNull(field, 'IS NOT NULL', 'OR');
|
||||
return this;
|
||||
}
|
||||
|
@ -564,7 +294,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {Array} values - the array of items to search in
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
whereIn(key, values) {
|
||||
whereIn (key, values) {
|
||||
this._whereIn(key, values, 'IN', 'AND');
|
||||
return this;
|
||||
}
|
||||
|
@ -576,7 +306,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {Array} values - the array of items to search in
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orWhereIn(key, values) {
|
||||
orWhereIn (key, values) {
|
||||
this._whereIn(key, values, 'IN', 'OR');
|
||||
return this;
|
||||
}
|
||||
|
@ -588,7 +318,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {Array} values - the array of items to search in
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
whereNotIn(key, values) {
|
||||
whereNotIn (key, values) {
|
||||
this._whereIn(key, values, 'NOT IN', 'AND');
|
||||
return this;
|
||||
}
|
||||
|
@ -600,7 +330,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {Array} values - the array of items to search in
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orWhereNotIn(key, values) {
|
||||
orWhereNotIn (key, values) {
|
||||
this._whereIn(key, values, 'NOT IN', 'OR');
|
||||
return this;
|
||||
}
|
||||
|
@ -614,12 +344,10 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @example query.set({foo:'bar'}); // Set with an object
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
set(/* $key, [$val] */) {
|
||||
let args = getArgs('$key, [$val]', arguments);
|
||||
|
||||
set (key, val) {
|
||||
// Set the appropriate state variables
|
||||
this._mixedSet('setArrayKeys', 'key', args.$key, args.$val);
|
||||
this._mixedSet('values', 'value', args.$key, args.$val);
|
||||
this._mixedSet('setArrayKeys', 'key', key, val);
|
||||
this._mixedSet('values', 'value', key, val);
|
||||
|
||||
// Use the keys of the array to make the insert/update string
|
||||
// and escape the field names
|
||||
|
@ -640,18 +368,18 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String} [type='inner'] - The type of join, which defaults to inner
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
join(table, cond, type) {
|
||||
join (table, cond, type) {
|
||||
type = type || 'inner';
|
||||
|
||||
// Prefix/quote table name
|
||||
table = table.split(' ').map(helpers.stringTrim);
|
||||
table = table.split(' ').map(Helpers.stringTrim);
|
||||
table[0] = this.driver.quoteTable(table[0]);
|
||||
table = table.map(this.driver.quoteIdentifiers);
|
||||
table = table.join(' ');
|
||||
|
||||
// Parse out the join condition
|
||||
let parsedCondition = this.parser.compileJoin(cond);
|
||||
let condition = `${table} ON ${parsedCondition}`;
|
||||
const parsedCondition = this.parser.compileJoin(cond);
|
||||
const condition = `${table} ON ${parsedCondition}`;
|
||||
|
||||
// Append the join condition to the query map
|
||||
this._appendMap(`\n${type.toUpperCase()} JOIN `, condition, 'join');
|
||||
|
@ -665,9 +393,9 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String|Array} field - The name of the field to group by
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
groupBy(field) {
|
||||
if (! helpers.isScalar(field)) {
|
||||
let newGroupArray = field.map(this.driver.quoteIdentifiers);
|
||||
groupBy (field) {
|
||||
if (!Helpers.isScalar(field)) {
|
||||
const newGroupArray = field.map(this.driver.quoteIdentifiers);
|
||||
this.state.groupArray = this.state.groupArray.concat(newGroupArray);
|
||||
} else {
|
||||
this.state.groupArray.push(this.driver.quoteIdentifiers(field));
|
||||
|
@ -685,7 +413,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String} [type='ASC'] - The order direction, ASC or DESC
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orderBy(field, type) {
|
||||
orderBy (field, type) {
|
||||
type = type || 'ASC';
|
||||
|
||||
// Set the fields for later manipulation
|
||||
|
@ -693,7 +421,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
|
||||
this.state.orderArray[field] = type;
|
||||
|
||||
let orderClauses = [];
|
||||
const orderClauses = [];
|
||||
|
||||
// Flatten key/val pairs into an array of space-separated pairs
|
||||
Object.keys(this.state.orderArray).forEach(key => {
|
||||
|
@ -713,7 +441,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {Number} [offset] - The row number to start from
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
limit(limit, offset) {
|
||||
limit (limit, offset) {
|
||||
this.state.limit = limit;
|
||||
this.state.offset = offset || null;
|
||||
|
||||
|
@ -725,8 +453,8 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
*
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
groupStart() {
|
||||
let conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ' AND ';
|
||||
groupStart () {
|
||||
const conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ' AND ';
|
||||
this._appendMap(conj, '(', 'groupStart');
|
||||
|
||||
return this;
|
||||
|
@ -738,7 +466,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
*
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orGroupStart() {
|
||||
orGroupStart () {
|
||||
this._appendMap('', ' OR (', 'groupStart');
|
||||
|
||||
return this;
|
||||
|
@ -750,7 +478,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
*
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
orNotGroupStart() {
|
||||
orNotGroupStart () {
|
||||
this._appendMap('', ' OR NOT (', 'groupStart');
|
||||
|
||||
return this;
|
||||
|
@ -761,7 +489,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
*
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
groupEnd() {
|
||||
groupEnd () {
|
||||
this._appendMap('', ')', 'groupEnd');
|
||||
|
||||
return this;
|
||||
|
@ -777,25 +505,22 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {String} [table] - The table to select from
|
||||
* @param {Number} [limit] - A limit for the query
|
||||
* @param {Number} [offset] - An offset for the query
|
||||
* @param {Function} [callback] - A callback for receiving the result
|
||||
* @example query.get('table_name').then(promiseCallback); // Get all the rows in the table
|
||||
* @example query.get('table_name', 5, callback); // Get 5 rows from the table
|
||||
* @example query.get(callback); // Get the results of a query generated with other methods
|
||||
* @return {void|Promise} - If no callback is passed, a promise is returned
|
||||
* @example query.get('table_name', 5); // Get 5 rows from the table
|
||||
* @example query.get(); // Get the results of a query generated with other methods
|
||||
* @return {Promise<Result>} - Promise containing the result of the query
|
||||
*/
|
||||
get(/* [table], [limit], [offset], [callback] */) {
|
||||
let args = getArgs('[table]:string, [limit]:number, [offset]:number, [callback]:function', arguments);
|
||||
|
||||
if (args.table) {
|
||||
this.from(args.table);
|
||||
get (table, limit, offset) {
|
||||
if (table) {
|
||||
this.from(table);
|
||||
}
|
||||
|
||||
if (args.limit) {
|
||||
this.limit(args.limit, args.offset);
|
||||
if (limit) {
|
||||
this.limit(limit, offset);
|
||||
}
|
||||
|
||||
// Run the query
|
||||
return this._run('get', args.table, args.callback);
|
||||
return this._run('get', table);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -803,18 +528,15 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
*
|
||||
* @param {String} table - The table to insert into
|
||||
* @param {Object} [data] - Data to insert, if not already added with the 'set' method
|
||||
* @param {Function} [callback] - Callback for handling response from the database
|
||||
* @return {void|Promise} - If no callback is passed, a promise is returned
|
||||
* @return {Promise<Result>} - Promise containing the result of the query
|
||||
*/
|
||||
insert(/* table, data, callback */) {
|
||||
let args = getArgs('table:string, [data]:object, [callback]:function', arguments);
|
||||
|
||||
if (args.data) {
|
||||
this.set(args.data);
|
||||
insert (table, data) {
|
||||
if (data) {
|
||||
this.set(data);
|
||||
}
|
||||
|
||||
// Run the query
|
||||
return this._run('insert', this.driver.quoteTable(args.table), args.callback);
|
||||
return this._run('insert', this.driver.quoteTable(table));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -822,18 +544,15 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
*
|
||||
* @param {String} table - The table to insert into
|
||||
* @param {Array} data - The array of objects containing data rows to insert
|
||||
* @param {Function} [callback] - Callback for handling database response
|
||||
* @example query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}], callbackFunction);
|
||||
* @example query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}])
|
||||
*.then(promiseCallback);
|
||||
* @return {void|Promise} - If no callback is passed, a promise is returned
|
||||
* @return {Promise<Result>} - Promise containing the result of the query
|
||||
*/
|
||||
insertBatch(/* table, data, callback */) {
|
||||
let args = getArgs('table:string, data:array, [callback]:function', arguments);
|
||||
let batch = this.driver.insertBatch(args.table, args.data);
|
||||
insertBatch (table, data) {
|
||||
const batch = this.driver.insertBatch(table, data);
|
||||
|
||||
// Run the query
|
||||
return this._run('', '', args.callback, batch.sql, batch.values);
|
||||
return this.query(batch.sql, batch.values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -841,18 +560,29 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
*
|
||||
* @param {String} table - The table to insert into
|
||||
* @param {Object} [data] - Data to insert, if not already added with the 'set' method
|
||||
* @param {Function} [callback] - Callback for handling response from the database
|
||||
* @return {void|Promise} - If no callback is passed, a promise is returned
|
||||
* @return {Promise<Result>} - Promise containing the result of the query
|
||||
*/
|
||||
update(/*table, data, callback*/) {
|
||||
let args = getArgs('table:string, [data]:object, [callback]:function', arguments);
|
||||
|
||||
if (args.data) {
|
||||
this.set(args.data);
|
||||
update (table, data) {
|
||||
if (data) {
|
||||
this.set(data);
|
||||
}
|
||||
|
||||
// Run the query
|
||||
return this._run('update', this.driver.quoteTable(args.table), args.callback);
|
||||
return this._run('update', this.driver.quoteTable(table));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a batch update sql statement
|
||||
*
|
||||
* @param {String} table - The table to update
|
||||
* @param {Object} data - Batch insert data
|
||||
* @param {String} updateKey - The field in the table to compare against for updating
|
||||
* @return {Number} Number of rows updated
|
||||
*/
|
||||
updateBatch (table, data, updateKey) {
|
||||
const [sql, insertData, affectedRows] = this.driver.updateBatch(table, data, updateKey);
|
||||
this._run('', table, sql, insertData);
|
||||
return affectedRows;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -860,18 +590,15 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
*
|
||||
* @param {String} table - The table to insert into
|
||||
* @param {Object} [where] - Where clause for delete statement
|
||||
* @param {Function} [callback] - Callback for handling response from the database
|
||||
* @return {void|Promise} - If no callback is passed, a promise is returned
|
||||
* @return {Promise<Result>} - Promise containing the result of the query
|
||||
*/
|
||||
delete(/*table, [where], callback*/) {
|
||||
let args = getArgs('table:string, [where]:object, [callback]:function', arguments);
|
||||
|
||||
if (args.where) {
|
||||
this.where(args.where);
|
||||
delete (table, where) {
|
||||
if (where) {
|
||||
this.where(where);
|
||||
}
|
||||
|
||||
// Run the query
|
||||
return this._run('delete', this.driver.quoteTable(args.table), args.callback);
|
||||
return this._run('delete', this.driver.quoteTable(table));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -885,13 +612,12 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
|
||||
* @return {String} - The compiled sql statement
|
||||
*/
|
||||
getCompiledSelect(/*table, reset*/) {
|
||||
let args = getArgs('[table]:string, [reset]:boolean', arguments);
|
||||
if (args.table) {
|
||||
this.from(args.table);
|
||||
getCompiledSelect (table, reset = true) {
|
||||
if (table) {
|
||||
this.from(table);
|
||||
}
|
||||
|
||||
return this._getCompile('get', args.table, args.reset);
|
||||
return this._getCompile('get', table, reset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -901,7 +627,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
|
||||
* @return {String} - The compiled sql statement
|
||||
*/
|
||||
getCompiledInsert(table, reset) {
|
||||
getCompiledInsert (table, reset = true) {
|
||||
return this._getCompile('insert', this.driver.quoteTable(table), reset);
|
||||
}
|
||||
|
||||
|
@ -912,7 +638,7 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
|
||||
* @return {String} - The compiled sql statement
|
||||
*/
|
||||
getCompiledUpdate(table, reset) {
|
||||
getCompiledUpdate (table, reset = true) {
|
||||
return this._getCompile('update', this.driver.quoteTable(table), reset);
|
||||
}
|
||||
|
||||
|
@ -923,9 +649,9 @@ class QueryBuilder extends QueryBuilderBase {
|
|||
* @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
|
||||
* @return {String} - The compiled sql statement
|
||||
*/
|
||||
getCompiledDelete(table, reset) {
|
||||
getCompiledDelete (table, reset = true) {
|
||||
return this._getCompile('delete', this.driver.quoteTable(table), reset);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = QueryBuilder;
|
||||
module.exports = QueryBuilder;
|
||||
|
|
|
@ -0,0 +1,274 @@
|
|||
const Helpers = require('./Helpers');
|
||||
const QueryParser = require('./QueryParser');
|
||||
const State = require('./State');
|
||||
|
||||
class QueryBuilderBase {
|
||||
/**
|
||||
* @private
|
||||
* @constructor
|
||||
* @param {Driver} Driver - The syntax driver for the database
|
||||
* @param {Adapter} Adapter - The database module adapter for running queries
|
||||
*/
|
||||
constructor (Driver, Adapter) {
|
||||
this.driver = Driver;
|
||||
this.adapter = Adapter;
|
||||
this.parser = new QueryParser(this.driver);
|
||||
this.state = new State();
|
||||
}
|
||||
|
||||
_like (field, val, pos, like, conj) {
|
||||
field = this.driver.quoteIdentifiers(field);
|
||||
|
||||
like = `${field} ${like} ?`;
|
||||
|
||||
if (pos === 'before') {
|
||||
val = `%${val}`;
|
||||
} else if (pos === 'after') {
|
||||
val = `${val}%`;
|
||||
} else {
|
||||
val = `%${val}%`;
|
||||
}
|
||||
|
||||
conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ` ${conj} `;
|
||||
this._appendMap(conj, like, 'like');
|
||||
|
||||
this.state.whereValues.push(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a clause to the query map
|
||||
*
|
||||
* @private
|
||||
* @param {String} conjunction - linking keyword for the clause
|
||||
* @param {String} string - pre-compiled sql fragment
|
||||
* @param {String} type - type of sql clause
|
||||
* @return {void}
|
||||
*/
|
||||
_appendMap (conjunction, string, type) {
|
||||
this.state.queryMap.push({
|
||||
type: type,
|
||||
conjunction: conjunction,
|
||||
string: string
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle key/value pairs in an object the same way as individual arguments,
|
||||
* when appending to state
|
||||
*
|
||||
* @private
|
||||
* @param {mixed} letName Lorem Ipsum
|
||||
* @param {mixed} valType Lorem Ipsum
|
||||
* @param {mixed} key Lorem Ipsum
|
||||
* @param {mixed} val Lorem Ipsum
|
||||
* @return {Array} - modified state array
|
||||
*/
|
||||
_mixedSet (letName, valType, key, val) {
|
||||
let obj = {};
|
||||
|
||||
if (Helpers.isScalar(key) && !Helpers.isUndefined(val)) {
|
||||
// Convert key/val pair to a simple object
|
||||
obj[key] = val;
|
||||
} else if (Helpers.isScalar(key) && Helpers.isUndefined(val)) {
|
||||
// If just a string for the key, and no value, create a simple object with duplicate key/val
|
||||
obj[key] = key;
|
||||
} else {
|
||||
obj = key;
|
||||
}
|
||||
|
||||
Object.keys(obj).forEach(k => {
|
||||
// If a single value for the return
|
||||
if (['key', 'value'].indexOf(valType) !== -1) {
|
||||
const pushVal = (valType === 'key') ? k : obj[k];
|
||||
this.state[letName].push(pushVal);
|
||||
} else {
|
||||
this.state[letName][k] = obj[k];
|
||||
}
|
||||
});
|
||||
|
||||
return this.state[letName];
|
||||
}
|
||||
|
||||
_whereMixedSet (key, val) {
|
||||
this.state.whereMap = [];
|
||||
this.state.rawWhereValues = [];
|
||||
|
||||
this._mixedSet('whereMap', 'both', key, val);
|
||||
this._mixedSet('rawWhereValues', 'value', key, val);
|
||||
}
|
||||
|
||||
_fixConjunction (conj) {
|
||||
const lastItem = this.state.queryMap[this.state.queryMap.length - 1];
|
||||
const conjunctionList = Helpers.arrayPluck(this.state.queryMap, 'conjunction');
|
||||
|
||||
if (this.state.queryMap.length === 0 || (!Helpers.regexInArray(conjunctionList, /^ ?WHERE/i))) {
|
||||
conj = ' WHERE ';
|
||||
} else if (lastItem.type === 'groupStart') {
|
||||
conj = '';
|
||||
} else {
|
||||
conj = ` ${conj} `;
|
||||
}
|
||||
|
||||
return conj;
|
||||
}
|
||||
|
||||
_where (key, val, defaultConj) {
|
||||
// Normalize key and value and insert into this.state.whereMap
|
||||
this._whereMixedSet(key, val);
|
||||
|
||||
// Parse the where condition to account for operators,
|
||||
// functions, identifiers, and literal values
|
||||
this.state = this.parser.parseWhere(this.driver, this.state);
|
||||
|
||||
this.state.whereMap.forEach(clause => {
|
||||
const conj = this._fixConjunction(defaultConj);
|
||||
this._appendMap(conj, clause, 'where');
|
||||
});
|
||||
|
||||
this.state.whereMap = {};
|
||||
}
|
||||
|
||||
_whereNull (field, stmt, conj) {
|
||||
field = this.driver.quoteIdentifiers(field);
|
||||
const item = `${field} ${stmt}`;
|
||||
|
||||
this._appendMap(this._fixConjunction(conj), item, 'whereNull');
|
||||
}
|
||||
|
||||
_having (key, val = null, conj = 'AND') {
|
||||
// Normalize key/val and put in state.whereMap
|
||||
this._whereMixedSet(key, val);
|
||||
|
||||
// Parse the having condition to account for operators,
|
||||
// functions, identifiers, and literal values
|
||||
this.state = this.parser.parseWhere(this.driver, this.state);
|
||||
|
||||
this.state.whereMap.forEach(clause => {
|
||||
// Put in the having map
|
||||
this.state.havingMap.push({
|
||||
conjunction: (this.state.havingMap.length > 0) ? ` ${conj} ` : ' HAVING ',
|
||||
string: clause
|
||||
});
|
||||
});
|
||||
|
||||
// Clear the where Map
|
||||
this.state.whereMap = {};
|
||||
}
|
||||
|
||||
_whereIn (key, val, inClause, conj) {
|
||||
key = this.driver.quoteIdentifiers(key);
|
||||
const params = Array(val.length);
|
||||
params.fill('?');
|
||||
|
||||
val.forEach(value => {
|
||||
this.state.whereValues.push(value);
|
||||
});
|
||||
|
||||
conj = (this.state.queryMap.length > 0) ? ` ${conj} ` : ' WHERE ';
|
||||
const str = `${key} ${inClause} (${params.join(',')}) `;
|
||||
|
||||
this._appendMap(conj, str, 'whereIn');
|
||||
}
|
||||
|
||||
_run (type, table, sql, vals) {
|
||||
if (!sql) {
|
||||
sql = this._compile(type, table);
|
||||
}
|
||||
|
||||
if (!vals) {
|
||||
vals = this.state.values.concat(this.state.whereValues);
|
||||
}
|
||||
|
||||
// Reset the state so another query can be built
|
||||
this._resetState();
|
||||
|
||||
// Pass the sql and values to the adapter to run on the database
|
||||
return this.query(sql, vals);
|
||||
}
|
||||
|
||||
_getCompile (type, table, reset) {
|
||||
reset = reset || false;
|
||||
|
||||
const sql = this._compile(type, table);
|
||||
|
||||
if (reset) {
|
||||
this._resetState();
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the sql building based on the type provided
|
||||
*
|
||||
* @private
|
||||
* @param {String} type - Type of SQL query
|
||||
* @param {String} table - The table to run the query on
|
||||
* @return {String} - The compiled sql
|
||||
*/
|
||||
_compile (type, table) {
|
||||
// Put together the basic query
|
||||
let sql = this._compileType(type, table);
|
||||
|
||||
// Set each subClause
|
||||
['queryMap', 'groupString', 'orderString', 'havingMap'].forEach(clause => {
|
||||
const param = this.state[clause];
|
||||
|
||||
if (!Helpers.isScalar(param)) {
|
||||
Object.keys(param).forEach(part => {
|
||||
sql += param[part].conjunction + param[part].string;
|
||||
});
|
||||
} else {
|
||||
sql += param;
|
||||
}
|
||||
});
|
||||
|
||||
// Append the limit, if it exists
|
||||
if (Helpers.isNumber(this.state.limit)) {
|
||||
sql = this.driver.limit(sql, this.state.limit, this.state.offset);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
_compileType (type, table) {
|
||||
let sql = '';
|
||||
|
||||
switch (type) {
|
||||
case 'insert':
|
||||
const params = Array(this.state.setArrayKeys.length).fill('?');
|
||||
|
||||
sql = `INSERT INTO ${table} (`;
|
||||
sql += this.state.setArrayKeys.join(',');
|
||||
sql += `) VALUES (${params.join(',')})`;
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
sql = `UPDATE ${table} SET ${this.state.setString}`;
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
sql = `DELETE FROM ${table}`;
|
||||
break;
|
||||
|
||||
default:
|
||||
sql = `SELECT * FROM ${this.state.fromString}`;
|
||||
|
||||
// Set the select string
|
||||
if (this.state.selectString.length > 0) {
|
||||
// Replace the star with the selected fields
|
||||
sql = sql.replace('*', this.state.selectString);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
_resetState () {
|
||||
this.state = new State();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = QueryBuilderBase;
|
|
@ -1,7 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
const XRegExp = require('xregexp');
|
||||
const helpers = require('./helpers');
|
||||
const Helpers = require('./Helpers');
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
|
@ -18,13 +16,13 @@ class QueryParser {
|
|||
* @param {Driver} driver - The driver object for the database in use
|
||||
* @return {void}
|
||||
*/
|
||||
constructor(driver) {
|
||||
constructor (driver) {
|
||||
this.driver = driver;
|
||||
|
||||
const matchPatterns = {
|
||||
function: /([a-z0-9_]+\((.*)\))/i,
|
||||
operator: /\!=?|\=|\+|&&?|~|\|\|?|\^|\/|<>|>=?|<=?|\-|%|OR|AND|NOT|XOR/ig,
|
||||
literal: /([0-9]+)|'(.*?)'|true|false/ig,
|
||||
operator: /!=?|=|\+|&&?|~|\|\|?|\^|\/|<>|>=?|<=?|-|%|OR|AND|NOT|XOR/ig,
|
||||
literal: /([0-9]+)|'(.*?)'|true|false/ig
|
||||
};
|
||||
|
||||
// Full pattern for identifiers
|
||||
|
@ -35,7 +33,7 @@ class QueryParser {
|
|||
${matchPatterns['function'].source}|
|
||||
${matchPatterns.literal.source}
|
||||
)
|
||||
([a-z_\-]+[0-9]*\\.?)
|
||||
([a-z_-]+[0-9]*\\.?)
|
||||
)+`, 'igx');
|
||||
|
||||
// Full pattern for determining ordering of the pieces
|
||||
|
@ -55,11 +53,11 @@ class QueryParser {
|
|||
* @param {Array} array - Set of possible matches
|
||||
* @return {Array|null} - Filtered set of possible matches
|
||||
*/
|
||||
filterMatches(array) {
|
||||
let output = [];
|
||||
filterMatches (array) {
|
||||
const output = [];
|
||||
|
||||
// Return non-array matches
|
||||
if (helpers.isNull(array)) {
|
||||
if (Helpers.isNull(array)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -76,7 +74,7 @@ class QueryParser {
|
|||
* @param {String} string - the string to check
|
||||
* @return {Array|null} - List of operators
|
||||
*/
|
||||
hasOperator(string) {
|
||||
hasOperator (string) {
|
||||
return this.filterMatches(string.match(this.matchPatterns.operator));
|
||||
}
|
||||
|
||||
|
@ -86,13 +84,13 @@ class QueryParser {
|
|||
* @param {String} sql - Join sql to parse
|
||||
* @return {Object} - Join condition components
|
||||
*/
|
||||
parseJoin(sql) {
|
||||
let matches = {};
|
||||
let output = {
|
||||
parseJoin (sql) {
|
||||
const matches = {};
|
||||
const output = {
|
||||
functions: [],
|
||||
identifiers: [],
|
||||
operators: [],
|
||||
literals: [],
|
||||
literals: []
|
||||
};
|
||||
|
||||
// Get clause components
|
||||
|
@ -115,15 +113,15 @@ class QueryParser {
|
|||
/**
|
||||
* Return the output of the parsing of the join condition
|
||||
*
|
||||
* @param {String} condition - The join condition to evalate
|
||||
* @param {String} condition - The join condition to evaluate
|
||||
* @return {String} - The parsed/escaped join condition
|
||||
*/
|
||||
compileJoin(condition) {
|
||||
let parts = this.parseJoin(condition);
|
||||
compileJoin (condition) {
|
||||
const parts = this.parseJoin(condition);
|
||||
|
||||
// Quote the identifiers
|
||||
parts.combined.forEach((part, i) => {
|
||||
if (parts.identifiers.indexOf(part) !== -1 && ! helpers.isNumber(part)) {
|
||||
if (parts.identifiers.indexOf(part) !== -1 && !Helpers.isNumber(part)) {
|
||||
parts.combined[i] = this.driver.quoteIdentifiers(part);
|
||||
}
|
||||
});
|
||||
|
@ -138,12 +136,12 @@ class QueryParser {
|
|||
* @param {State} state - Query Builder state object
|
||||
* @return {String} - The parsed/escaped where condition
|
||||
*/
|
||||
parseWhere(driver, state) {
|
||||
let whereMap = state.whereMap;
|
||||
parseWhere (driver, state) {
|
||||
const whereMap = state.whereMap;
|
||||
let whereValues = state.rawWhereValues;
|
||||
|
||||
let outputMap = [];
|
||||
let outputValues = [];
|
||||
const outputMap = [];
|
||||
const outputValues = [];
|
||||
|
||||
Object.keys(whereMap).forEach(key => {
|
||||
// Combine fields, operators, functions and values into a full clause
|
||||
|
@ -151,7 +149,7 @@ class QueryParser {
|
|||
let fullClause = '';
|
||||
|
||||
// Add an explicit = sign where one is inferred
|
||||
if (! this.hasOperator(key)) {
|
||||
if (!this.hasOperator(key)) {
|
||||
fullClause = `${key} = ${whereMap[key]}`;
|
||||
} else if (whereMap[key] === key) {
|
||||
fullClause = key;
|
||||
|
@ -160,23 +158,23 @@ class QueryParser {
|
|||
}
|
||||
|
||||
// Separate the clause into separate pieces
|
||||
let parts = this.parseJoin(fullClause);
|
||||
const parts = this.parseJoin(fullClause);
|
||||
|
||||
// Filter explicit literals from lists of matches
|
||||
if (whereValues.indexOf(whereMap[key]) !== -1) {
|
||||
let value = whereMap[key];
|
||||
let identIndex = parts.identifiers.indexOf(value);
|
||||
let litIndex = (helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1;
|
||||
let combIndex = parts.combined.indexOf(value);
|
||||
let funcIndex = (helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1;
|
||||
let inOutputArray = outputValues.indexOf(value) !== -1;
|
||||
const value = whereMap[key];
|
||||
const identIndex = parts.identifiers.indexOf(value);
|
||||
const litIndex = (Helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1;
|
||||
const combIndex = parts.combined.indexOf(value);
|
||||
const funcIndex = (Helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1;
|
||||
let inOutputArray = outputValues.includes(value);
|
||||
|
||||
// Remove the identifier in question,
|
||||
// and add to the output values array
|
||||
if (identIndex !== -1) {
|
||||
parts.identifiers.splice(identIndex, 1);
|
||||
|
||||
if (! inOutputArray) {
|
||||
if (!inOutputArray) {
|
||||
outputValues.push(value);
|
||||
inOutputArray = true;
|
||||
}
|
||||
|
@ -187,7 +185,7 @@ class QueryParser {
|
|||
if (litIndex !== -1) {
|
||||
parts.literals.splice(litIndex, 1);
|
||||
|
||||
if (! inOutputArray) {
|
||||
if (!inOutputArray) {
|
||||
outputValues.push(value);
|
||||
inOutputArray = true;
|
||||
}
|
||||
|
@ -203,16 +201,16 @@ class QueryParser {
|
|||
|
||||
// Filter false positive identifiers
|
||||
parts.identifiers = parts.identifiers.filter(item => {
|
||||
let isInCombinedMatches = parts.combined.indexOf(item) !== -1;
|
||||
let isNotInBlackList = this.identifierBlacklist.indexOf(item.toLowerCase()) === -1;
|
||||
const isInCombinedMatches = parts.combined.indexOf(item) !== -1;
|
||||
const isNotInBlackList = this.identifierBlacklist.indexOf(item.toLowerCase()) === -1;
|
||||
|
||||
return isInCombinedMatches && isNotInBlackList;
|
||||
}, this);
|
||||
|
||||
// Quote identifiers
|
||||
if (helpers.isArray(parts.identifiers)) {
|
||||
if (Helpers.isArray(parts.identifiers)) {
|
||||
parts.identifiers.forEach(ident => {
|
||||
let index = parts.combined.indexOf(ident);
|
||||
const index = parts.combined.indexOf(ident);
|
||||
if (index !== -1) {
|
||||
parts.combined[index] = driver.quoteIdentifiers(ident);
|
||||
}
|
||||
|
@ -224,9 +222,9 @@ class QueryParser {
|
|||
// This should only apply to literal values that are not
|
||||
// explicitly mapped to values, but have to be parsed from
|
||||
// a where condition,
|
||||
if (helpers.isArray(parts.literals)) {
|
||||
if (Helpers.isArray(parts.literals)) {
|
||||
parts.literals.forEach(lit => {
|
||||
let litIndex = parts.combined.indexOf(lit);
|
||||
const litIndex = parts.combined.indexOf(lit);
|
||||
|
||||
if (litIndex !== -1) {
|
||||
parts.combined[litIndex] = '?';
|
||||
|
@ -246,4 +244,4 @@ class QueryParser {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = QueryParser;
|
||||
module.exports = QueryParser;
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
const Helpers = require('./Helpers');
|
||||
|
||||
/**
|
||||
* Query result object
|
||||
*
|
||||
* @param {Array} rows - the data rows of the result
|
||||
* @param {Array} columns - the column names in the result
|
||||
*/
|
||||
class Result {
|
||||
/**
|
||||
* Create a result object
|
||||
*
|
||||
* @private
|
||||
* @param {Array} [rows] - the data rows of the result
|
||||
* @param {Array} [columns] - the column names in the result
|
||||
*/
|
||||
constructor (rows = [], columns = []) {
|
||||
this._rows = rows;
|
||||
this._columns = columns;
|
||||
|
||||
// If columns aren't explicitly given,
|
||||
// get the list from the first row's keys
|
||||
if (
|
||||
this._columns.length === 0 &&
|
||||
this._rows.length > 0 &&
|
||||
Helpers.isObject(rows[0])
|
||||
) {
|
||||
this.columns = Object.keys(rows[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the result rows
|
||||
*
|
||||
* @private
|
||||
* @return {Array} - the data rows of the result
|
||||
*/
|
||||
get rows () {
|
||||
return this._rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the result rows for the result object
|
||||
*
|
||||
* @private
|
||||
* @param {Array} rows - the data rows of the result
|
||||
* @return {void}
|
||||
*/
|
||||
set rows (rows) {
|
||||
this._rows = rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the result columns
|
||||
*
|
||||
* @private
|
||||
* @return {Array} - the column names in the result
|
||||
*/
|
||||
get columns () {
|
||||
return this._columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the result columns for the result object
|
||||
*
|
||||
* @private
|
||||
* @param {Array} cols - the array of columns for the current result
|
||||
* @return {void}
|
||||
*/
|
||||
set columns (cols) {
|
||||
this._columns = cols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of rows returned by the query
|
||||
*
|
||||
* @return {Number} - the number of rows in the result
|
||||
*/
|
||||
rowCount () {
|
||||
return this._rows.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of columns returned by the query
|
||||
*
|
||||
* @return {Number} - the number of columns in the result
|
||||
*/
|
||||
columnCount () {
|
||||
return this._columns.length;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Result;
|
|
@ -1,11 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Class for objects containing the query builder state
|
||||
* @private
|
||||
*/
|
||||
class State {
|
||||
constructor() {
|
||||
constructor () {
|
||||
// Arrays/maps
|
||||
this.queryMap = [];
|
||||
this.values = [];
|
||||
|
@ -31,5 +29,3 @@ class State {
|
|||
}
|
||||
|
||||
module.exports = State;
|
||||
|
||||
// End of module State
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = config => {
|
||||
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
module.exports = require('../Mysql');
|
|
@ -0,0 +1,5 @@
|
|||
const Mysql2 = require('./mysql2');
|
||||
|
||||
module.exports = config => {
|
||||
return new Mysql2(config.connection);
|
||||
};
|
|
@ -0,0 +1,49 @@
|
|||
const Adapter = require('../../Adapter');
|
||||
const Result = require('../../Result');
|
||||
const Helpers = require('../../Helpers');
|
||||
const mysql2 = require('mysql2/promise');
|
||||
|
||||
class Mysql extends Adapter {
|
||||
constructor (config) {
|
||||
const instance = mysql2.createConnection(config);
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the adapter's result into a standard format
|
||||
*
|
||||
* @param {*} result - original driver result object
|
||||
* @return {Result} - standard result object
|
||||
*/
|
||||
transformResult (result) {
|
||||
// For insert and update queries, the result object
|
||||
// works differently. Just apply the properties of
|
||||
// this special result to the standard result object.
|
||||
if (Helpers.type(result) === 'object') {
|
||||
let r = new Result();
|
||||
|
||||
Object.keys(result).forEach(key => {
|
||||
r[key] = result[key];
|
||||
});
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
return new Result(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the sql query as a prepared statement
|
||||
*
|
||||
* @param {String} sql - The sql with placeholders
|
||||
* @param {Array} params - The values to insert into the query
|
||||
* @return {Promise} Result of query
|
||||
*/
|
||||
execute (sql, params) {
|
||||
return this.instance
|
||||
.then(conn => conn.execute(sql, params))
|
||||
.then(result => this.transformResult(result));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Mysql;
|
|
@ -0,0 +1,103 @@
|
|||
const Adapter = require('../../Adapter');
|
||||
const Result = require('../../Result');
|
||||
const Helpers = require('../../Helpers');
|
||||
const pg = require('pg');
|
||||
const url = require('url');
|
||||
|
||||
class Pg extends Adapter {
|
||||
constructor (config) {
|
||||
let instance = null;
|
||||
let connectionString = Pg.formatConnectionString(config);
|
||||
|
||||
if (connectionString !== '') {
|
||||
const conn = new pg.Client(connectionString);
|
||||
conn.connect(err => {
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
});
|
||||
|
||||
instance = Promise.resolve(conn);
|
||||
}
|
||||
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the connection object to a connection string
|
||||
*
|
||||
* @param {Object} config - the configuration object
|
||||
* @return {String} - the connection string
|
||||
*/
|
||||
static formatConnectionString (config) {
|
||||
let connectionString = '';
|
||||
|
||||
if (Helpers.isObject(config)) {
|
||||
const host = config.host || 'localhost';
|
||||
const user = config.user || 'postgres';
|
||||
const password = `:${config.password}` || '';
|
||||
const port = config.port || 5432;
|
||||
|
||||
const conn = {
|
||||
protocol: 'postgres',
|
||||
slashes: true,
|
||||
host: `${host}:${port}`,
|
||||
auth: `${user}${password}`,
|
||||
pathname: config.database
|
||||
};
|
||||
|
||||
connectionString = url.format(conn);
|
||||
} else if (Helpers.isString(config)) {
|
||||
connectionString = config;
|
||||
}
|
||||
|
||||
return connectionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the adapter's result into a standard format
|
||||
*
|
||||
* @param {*} result - original driver result object
|
||||
* @return {Result} - standard result object
|
||||
*/
|
||||
transformResult (result) {
|
||||
if (result == null) {
|
||||
return new Result();
|
||||
}
|
||||
|
||||
const cols = [];
|
||||
result.fields.forEach(field => {
|
||||
cols.push(field.name);
|
||||
});
|
||||
|
||||
return new Result(result.rows, cols);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the sql query as a prepared statement
|
||||
*
|
||||
* @param {String} sql - The sql with placeholders
|
||||
* @param {Array} params - The values to insert into the query
|
||||
* @return {void|Promise} - Returns a promise if no callback is provided
|
||||
*/
|
||||
execute (sql, params) {
|
||||
// Replace question marks with numbered placeholders, because this adapter is different...
|
||||
let count = 0;
|
||||
sql = sql.replace(/\?/g, () => {
|
||||
count++;
|
||||
return `$${count}`;
|
||||
});
|
||||
|
||||
return this.instance.then(conn => {
|
||||
return new Promise((resolve, reject) => {
|
||||
conn.query(sql, params, (err, result) =>
|
||||
(err)
|
||||
? reject(err)
|
||||
: resolve(this.transformResult(result))
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Pg;
|
|
@ -0,0 +1,2 @@
|
|||
const Pg = require('./Pg');
|
||||
module.exports = config => new Pg(config.connection);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue