{"id":28555880,"url":"https://github.com/totaljs/node-sqlagent","last_synced_at":"2025-07-04T04:31:48.138Z","repository":{"id":20054499,"uuid":"23323016","full_name":"totaljs/node-sqlagent","owner":"totaljs","description":"SQL Agent is a missing ORM for Node.js + Total.js","archived":false,"fork":false,"pushed_at":"2020-01-14T13:53:05.000Z","size":845,"stargazers_count":50,"open_issues_count":2,"forks_count":22,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-06-10T06:08:13.860Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.totaljs.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/totaljs.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-25T17:51:41.000Z","updated_at":"2024-06-21T02:58:26.000Z","dependencies_parsed_at":"2022-09-02T13:40:50.906Z","dependency_job_id":null,"html_url":"https://github.com/totaljs/node-sqlagent","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/totaljs/node-sqlagent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totaljs%2Fnode-sqlagent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totaljs%2Fnode-sqlagent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totaljs%2Fnode-sqlagent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totaljs%2Fnode-sqlagent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/totaljs","download_url":"https://codeload.github.com/totaljs/node-sqlagent/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totaljs%2Fnode-sqlagent/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263445916,"owners_count":23467642,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-10T06:08:08.100Z","updated_at":"2025-07-04T04:31:48.124Z","avatar_url":"https://github.com/totaljs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# A very helpful ORM for node.js\n\n[![Professional Support](https://www.totaljs.com/img/badge-support.svg)](https://www.totaljs.com/support/) [![Chat with contributors](https://www.totaljs.com/img/badge-chat.svg)](https://messenger.totaljs.com) [![NPM version][npm-version-image]][npm-url] [![NPM downloads][npm-downloads-image]][npm-url] [![MIT License][license-image]][license-url]\n\n- installation `$ npm install sqlagent`\n\n---\n\n- for PostgreSQL `$ npm install pg`\n- for MySQL `$ npm install mysql`\n- for MS SQL Server `$ npm install mssql`\n- for MongoDB `$ npm install mongodb`\n\n---\n\n- Currently supports __PostgreSQL__, __MySQL__, __SQL Server__ and __MongoDB__\n- Simple and powerful\n- Best use with [Total.js - web framework for Node.js](https://www.totaljs.com)\n\n__IMPORTANT__:\n\n- the code is executed as is added\n- `rollback` is executed automatically when is the transaction enabled\n- SQL Server: pagination works only in `SQL SERVER \u003e=2012`\n- `SqlBuilder` is a global object\n- `undefined` values are skipped\n\n## Initialization\n\n### Basic initialization\n\n#### PostgreSQL\n\n```javascript\n// Example: postgresql://user:password@127.0.0.1/database\nvar Agent = require('sqlagent/pg').connect('connetion-string-to-postgresql');\n\n/*\n// It's executed when the datbase returns an unexpected error\nAgent.error = function(err, type, query) {\n\n};\n*/\n\n// Agent() returns new instance of SQL Agent\nvar sql = Agent();\n```\n\n__Additional configuration__:\n\n```\npostgresql://user:password@127.0.0.1/database?native=true\u0026ssl=true\n```\n\n- `native` {Boolean} enables PG C native binding (faster than JavaScript binding, default: `false`)\n- `ssl` {Boolean} enables SSL (default: `false`)\n- `max` {Number} max. pools (default: `20`)\n- `min` {Number} min. pools (default: `4`)\n- `idleTimeoutMillis` {Number} idle timeout (default: `1000`)\n\n#### MySQL\n\n```javascript\n// Example: mysql://user:password@127.0.0.1/database\nvar Agent = require('sqlagent/mysql').connect('connetion-string-to-mysql');\nvar sql = new Agent();\n```\n\n#### SQL Server (MSSQL)\n\n```javascript\n// Example: mssql://user:password@127.0.0.1/database\n// Example with name of instance: mssql://user:password@localhost_SQLEXPRESS/database\nvar Agent = require('sqlagent/sqlserver').connect('connetion-string-to-mssql');\nvar sql = new Agent();\n```\n\n#### MongoDB\n\n```javascript\n// Example: mongodb://user:password@127.0.0.1/database\nvar Agent = require('sqlagent/mongodb').connect('connetion-string-to-mongodb');\nvar nosql = new Agent();\n```\n\n### Initialization for Total.js\n\nCreate a definition file:\n\n```javascript\n// Below code rewrites total.js database prototype\nrequire('sqlagent/pg').init('connetion-string-to-postgresql', [debug]); // debug is by default: false\nrequire('sqlagent/mysql').init('connetion-string-to-mysql', [debug]); // debug is by default: false\nrequire('sqlagent/sqlserver').init('connetion-string-to-sqlserver', [debug]); // debug is by default: false\nrequire('sqlagent/mongodb').init('connetion-string-to-mongodb', [debug]); // debug is by default: false\n```\n\nUsage:\n\n```javascript\n// When you use RDMBS:\n// var sql = DATABASE([ErrorBuilder]);\nvar sql = DATABASE();\n// sql === SqlAgent\n\n// +v9.9.6 enable debugging\nsql.debug = true;\n\n// When you use MongoDB:\n// var nosql = DATABASE([ErrorBuilder]);\nvar nosql = DATABASE();\n// nosql === SqlAgent\n```\n\n### IMPORTANT\n\nIn order for mysql to return Boolean values please set the data type in db to BIT(1) and use bellow code for initialization.\n```javascript\nvar Agent = require('sqlagent/mysql').connect({\n    host: \"localhost\",\n    user: \"root\",\n    password: \"\",\n    database: \"test\",\n    typeCast: function castField( field, useDefaultTypeCasting ) {\n        if ( ( field.type === \"BIT\" ) \u0026\u0026 ( field.length === 1 ) ) {\n            var bytes = field.buffer();\n            return( bytes[ 0 ] === 1 );\n        }\n        return( useDefaultTypeCasting() );\n    }\n});\nvar sql = new Agent();\n```\n\n## Usage\n\n### Select\n\n```plain\ninstance.select([name], table)\n```\n\n- `name` (String) is an identificator for results, optional (default: internal indexer)\n- `table` (String) table name, the library automatically creates SQL query\n- __returns__ SqlBuilder\n\n```javascript\nsql.select('users', 'tbl_user').make(function(builder) {\n    builder.where('id', '\u003e', 5);\n    builder.page(10, 10);\n});\n\nsql.select('orders', 'tbl_order').make(function(builder) {\n    builder.where('isremoved', false);\n    builder.page(10, 10);\n    builder.fields('amount', 'datecreated');\n});\n\nsql.select('products', 'tbl_products').make(function(builder) {\n    builder.between('price', 30, 50);\n    builder.and();\n    builder.where('isremoved', false);\n    builder.limit(20);\n    builder.fields('id', 'name');\n});\n\nsql.exec(function(err, response) {\n    console.log(response.users);\n    console.log(response.products);\n    console.log(response.admin);\n});\n```\n\n### Push (only for MongoDB)\n\n```plain\ninstance.push([name], collection, fn(collection, callback(err, response))\n```\n\n```javascript\nsql.push('users', 'users', function(collection, callback) {\n\n    var $group = {};\n    $group._id = {};\n    $group._id = '$category';\n    $group.count = { $sum: 1 };\n\n    var $match = {};\n    $match.isremoved = false;\n\n    var pipeline = [];\n    pipeline.push({ $match: $match });\n    pipeline.push({ $group: $group });\n\n    collection.aggregate(pipeline, callback);\n});\n\n// OR\n\nsql.push('users', 'users', function(collection, callback) {\n    collection.findOne({ name: 'Peter' }, { name: 1, age: 1 }).toArray(callback);\n});\n```\n\n### Listing\n\n```plain\ninstance.listing([name], table)\n```\n\n- `name` (String) is an identificator for results, optional (default: internal indexer)\n- `table` (String) table name, the library automatically creates SQL query\n- __returns__ SqlBuilder\n\n```javascript\nsql.listing('users', 'tbl_user').make(function(builder) {\n    builder.where('id', '\u003e', 5);\n    builder.page(10, 10);\n});\n\nsql.exec(function(err, response) {\n\n    // users will contain:\n    // .count --\u003e count of all users according to the filter\n    // .items --\u003e selected items\n    // .page  --\u003e a page number (+v11.0.0)\n    // .pages --\u003e page count (+v11.0.0)\n    // .limit --\u003e items limit per page (+v11.0.0)\n\n    console.log(response.users.count);\n    console.log(response.users.items);\n});\n```\n\n\n### Save\n\n```plain\ninstance.save([name], table, isINSERT, prepare(builder, isINSERT));\n```\n\n```javascript\nsql.save('user', 'tbl_user', somemodel.id === 0, function(builder, isINSERT) {\n\n    builder.set('name', somemodel.name);\n\n    if (isINSERT) {\n        builder.set('datecreated', new Date());\n        return;\n    }\n\n    builder.inc('countupdate', 1);\n    builder.where('id', somemodel.id);\n});\n```\n\n### Insert\n\n```plain\ninstance.insert([name], table)\n```\n\n- `name` (String) is an identificator for results, optional (default: internal indexer)\n- `table` (String) table name, the library automatically creates SQL query\n- __returns__ if value is undefined then __SqlBuilder__ otherwise __SqlAgent__\n\n```javascript\nsql.insert('user', 'tbl_user').make(function(builder) {\n    builder.set({ name: 'Peter', age: 30 });\n});\n\nsql.insert('log', 'tbl_logs').make(function(builder) {\n    builder.set('message', 'Some log message.');\n    builder.set('created', new Date());\n});\n\nsql.exec(function(err, response) {\n    console.log(response.user); // response.user.identity (INSERTED IDENTITY)\n    console.log(response.log); // response.log.identity (INSERTED IDENTITY)\n});\n```\n\n__IMPORTANT__: `identity` works only with auto-increment in MS SQL SERVER.\n\n### Update\n\n```plain\ninstance.update([name], table)\n```\n\n- `name` (String) is an identificator for results, optional (default: internal indexer)\n- `table` (String) table name, the library automatically creates SQL query\n- __returns__ if value is undefined then __SqlBuilder__ otherwise __SqlAgent__\n\n```javascript\nsql.update('user1', 'tbl_user').make(function(builder) {\n    builder.set({ name: 'Peter', age: 30 });\n    builder.where('id', 1);\n});\n\n// is same as\nsql.update('user2', 'tbl_user').make(function(builder) {\n    builder.where('id', 1);\n    builder.set('name', 'Peter');\n    builder.set('age', 30);\n});\n\nsql.exec(function(err, response) {\n    console.log(response.user1); // returns {Number} (count of changed rows)\n    console.log(response.user2); // returns {Number} (count of changed rows)\n});\n```\n\n### Delete\n\n```plain\ninstance.delete([name], table)\ninstance.remove([name], table)\n```\n\n- `name` (String) is an identificator for results, optional (default: internal indexer)\n- `table` (String) table name, the library automatically creates SQL query\n- __returns__ SqlBuilder\n\n```javascript\nsql.remove('user', 'tbl_user').make(function(builder) {\n    builder.where('id', 1);\n});\n\nsql.exec(function(err, response) {\n    console.log(response.user); // returns {Number} (count of deleted rows)\n});\n```\n\n### Query\n\n```plain\ninstance.query([name], query)\n```\n\n- `name` (String) is an identificator for results, optional (default: internal indexer)\n- `query` (String) SQL query\n- `params` (Array) SQL additional params (each DB has own SQL implementation e.g. PG `WHERE id=$1`, MySQL `WHERE id=?`, etc.)\n- __returns__ if params is undefined then __SqlBuilder__ otherwise __SqlAgent__\n\n```javascript\nsql.query('user', 'SELECT * FROM tbl_user').make(function(builder) {\n    builder.where('id', 1);\n});\n\nsql.exec(function(err, response) {\n    console.log(response.user);\n});\n```\n\n### Aggregation\n\n```plain\ninstance.count([name], table)\n```\n\n- __returns__ SqlBuilder\n\n```javascript\nvar count = sql.count('users', 'tbl_user');\ncount.between('age', 20, 40);\n\nsql.exec(function(err, response) {\n    console.log(response.users); // response.users === number\n});\n```\n\n---\n\n```plain\ninstance.max([name], table, column)\ninstance.min([name], table, column)\ninstance.avg([name], table, column)\n```\n\n- __returns__ SqlBuilder\n\n```javascript\nvar max = sql.max('users', 'tbl_user', 'age');\nmax.where('isremoved', false);\n\nsql.exec(function(err, response) {\n    console.log(response.users); // response.users === number\n});\n```\n\n### Exists\n\n```plain\ninstance.exists([name], table)\n```\n\n- __returns__ SqlBuilder\n\n```javascript\nvar exists = sql.exists('user', 'tbl_user');\nexists.where('id', 35);\n\nsql.exec(function(err, response) {\n    console.log(response.user); // response.user === Boolean (in correct case otherwise undefined)\n});\n```\n\n### Compare\n\n```plain\ninstance.compare([name], table, value, [keys])\n```\n\n- the module compares values between DB and `value`\n- the response can be `false` or `{ diff: ['name'], record: Object, value: Object }`\n- works with `sql.ifexists()` and `sql.ifnot()`\n- __returns__ SqlBuilder\n\n```javascript\nvar compare = sql.compare('user', 'tbl_user', { name: 'Peter', age: 33 });\n// OR: var compare = sql.compare('user', 'tbl_user', { name: 'Peter', age: 33 }, ['name']); --\u003e compares only name field\n// OR: compare.fields('name', 'age'); --\u003e compares these fields (if aren't defined \"keys\")\n\ncompare.where('id', 35);\n\nsql.exec(function(err, response) {\n\n    if (response.user) {\n        // shows the property names which were changed\n        console.log(response.user.diff);\n    }\n\n});\n```\n\n---\n\n```plain\ninstance.max([name], table, column)\ninstance.min([name], table, column)\ninstance.avg([name], table, column) // doesn't work with Mongo\n```\n\n- __returns__ SqlBuilder\n\n```javascript\nvar max = sql.max('users', 'tbl_user', 'age');\nmax.where('isremoved', false);\n\nsql.exec(function(err, response) {\n    console.log(response.users); // response.users === number\n});\n```\n\n### Transactions\n\n- doesn't work with MongoDB\n- rollback is performed automatically\n\n```javascript\nsql.begin();\nsql.insert('tbl_user', { name: 'Peter' });\nsql.commit();\n```\n\n## Special cases\n\n### How to set the primary key?\n\n- doesn't work with MongoDB\n\n```javascript\n// instance.primary('column name') is same as instance.primaryKey('column name')\n\ninstance.primary('userid');\ninstance.insert('tbl_user', ...);\n\ninstance.primary('productid');\ninstance.insert('tbl_product', ...);\n\ninstance.primary(); // back to default \"id\"\n```\n\n- default `primary key name` is `id`\n- works only in PostgreSQL because INSERT ... RETURNING __must have specific column name__\n\n### How to use latest primary id value for relations?\n\n```javascript\n// primary key is id + autoincrement\nvar user = sql.insert('user', 'tbl_user');\nuser.set('name', 'Peter');\n\nvar address = sql.insert('tbl_user_address');\naddress.set('id', sql.$$);\naddress.set('country', 'Slovakia');\n\nsql.exec();\n```\n\n### How to use latest primary id value for multiple relations?\n\n```javascript\n// primary key is id + autoincrement\nvar user = sql.insert('user', 'tbl_user');\nuser.set('name', 'Peter');\n\n// Lock latest inserted identificator\nsql.lock();\n// is same as\n// sql.put(sql.$$);\n\nvar address = sql.insert('tbl_user_address');\naddress.set('iduser', sql.$$); // adds latest primary id value\naddress.set('country', 'Slovakia');\n\nvar email = sql.insert('tbl_user_email');\nemail.set('iduser', sql.$$); // adds locked value\nemail.set('email', 'petersirka@gmail.com');\nsql.unlock();\n\nsql.exec();\n```\n\n### If not or If exists\n\n```javascript\ninstance.ifnot('user', function(error, response, value) {\n    // error === ErrorBuilder\n    // It will be executed when the results `user` contains a negative value or array.length === 0\n    // Is executed in order\n});\n\ninstance.ifexists('user', function(error, response, value) {\n    // error === ErrorBuilder\n    // It will be executed when the results `user` contains a positive value or array.length \u003e 0\n    // Is executed in order\n});\n```\n\n### Default values\n\n- you can set default values\n- values are bonded immediately (not in order)\n\n```javascript\nsql.default(function(response) {\n    response.count = 0;\n    response.user = {};\n    response.user.id = 1;\n});\n\n// ...\n// ...\n\nsql.exec(function(err, response) {\n    console.log(response);\n});\n```\n\n### Modify results\n\n- values are bonded in an order\n\n```javascript\nsql.select(...);\nsql.insert(...);\n\nsql.modify(function(response) {\n    response.user = {};\n    response.user.identity = 10;\n});\n\n// ...\n// ...\n\n// Calling:\n// 1. select\n// 2. insert\n// 3. modify\n// 4. other commands\nsql.exec(function(err, response) {\n    console.log(response);\n});\n```\n\n### Preparing (dependencies)\n\n- you can use multiple `sql.prepare()`\n\n```javascript\nvar user = sql.update('user', 'tbl_user');\nuser.where('id', 20);\nuser.set('name', 'Peter');\n\nvar select = sql.select('address', 'tbl_address');\nselect.where('isremoved', false);\nselect.and();\nselect.where('city', 'Bratislava');\nselect.limit(1);\n\n// IMPORTANT:\nsql.prepare(function(error, response, resume) {\n    // error === ErrorBuilder\n    sql.builder('address').set('idaddress', response.address.id);\n    resume();\n});\n\nvar address = sql.update('address', 'tbl_user_address');\naddress.where('iduser', 20);\n\nsql.exec();\n```\n\n### Validation\n\n- you can use multiple `sql.validate()`\n\n```plain\nsql.validate(fn)\n```\n\n```javascript\nvar select = sql.select('address', 'tbl_address');\nselect.where('isremoved', false);\nselect.and();\nselect.where('city', 'Bratislava');\nselect.limit(1);\n\n// IMPORTANT:\nsql.validate(function(error, response, resume) {\n\n    // error === ErrorBuilder\n\n    if (!response.address) {\n        error.push('Sorry, address not found');\n        // cancel pending queries\n        return resume(false);\n    }\n\n    sql.builder('user').set('idaddress', response.id);\n\n    // continue\n    resume();\n});\n\nvar user = sql.update('user', 'tbl_user');\nuser.where('id', 20);\nuser.set('name', 'Peter');\n\nsql.exec();\n```\n\n__Validation alternative (+v4.0.0)__\n\n```javascript\n// IMPORTANT:\nsql.validate(function(error, response) {\n\n    // error === ErrorBuilder\n\n    if (!response.address) {\n        error.push('Sorry, address not found');\n        return false;\n    }\n\n    sql.builder('user').set('idaddress', response.id);\n    return true;\n});\n```\n\n---\n\n```plain\nsql.validate([result_name_for_validation], error_message, [reverse]);\n```\n\n- `result_name_for_validation` (String) a result to compare.\n- `error_message` (String) an error message\n- `reverse` (Boolean) a reverse comparison (false: result must exist (default), true: result must be empty)\n__\n\nIf the function throw error then SqlAgent cancel all pending queris (perform Rollback if the agent is in transaction mode) and executes callback with error.\n\n```javascript\nvar select = sql.select('address', 'tbl_address');\nselect.where('isremoved', false);\nselect.and();\nselect.where('city', 'Bratislava');\nselect.limit(1);\n\n// IMPORTANT:\nsql.validate('Sorry, address not found');\n\nvar user = sql.select('user', 'tbl_user');\nuser.where('id', 20);\n\nsql.validate('Sorry, user not found');\nsql.validate('Sorry, address not found for the current user', 'address');\n\nsql.exec();\n```\n\n__Validation alternative (+v8.0.0)__\n\n```javascript\nsql.validate('products', n =\u003e n.length \u003e 0, 'error-products');\nsql.validate('detail', n =\u003e !n, 'error-detail');\n```\n\n\n## Global\n\n### Stored procedures\n\n```javascript\nsql.query('myresult', 'exec myprocedure');\n\n// with params\n// sql.query('myresult', 'exec myprocedure $1', [3403]);\n\nsql.exec(function(err, response) {\n    console.log(response.myresult);\n});\n```\n\n### Skipper\n\n```javascript\nsql.select('users', 'tbl_users');\nsql.skip(); // skip orders\nsql.select('orders', 'tbl_orders');\n\nsql.bookmark(function(error, response) {\n    // error === ErrorBuilder\n    // skip logs\n    sql.skip('logs');\n});\n\nsql.select('logs', 'tbl_logs');\n\nsql.exec(function(err, response) {\n    console.log(response); // --- response will be contain only { users: [] }\n});\n```\n\n### Bookmarks\n\nBookmark is same as `sql.prepare()` function but without `resume` argument.\n\n```javascript\nsql.select('users', 'tbl_users');\n\nsql.bookmark(function(error, response) {\n    // error === ErrorBuilder\n    console.log(response);\n    response['custom'] = 'Peter';\n});\n\nsql.select('orders', 'tbl_orders');\n\nsql.exec(function(err, response) {\n    response.users;\n    response.orders;\n    response.custom; // === Peter\n});\n```\n\n### Error handling\n\n```javascript\nsql.select('users', 'tbl_users');\n\nsql.validate(function(error, response, resume) {\n\n    // error === ErrorBuilder\n\n    if (!response.users || respone.users.length === 0)\n        error.push(new Error('This is error'));\n\n    // total.js:\n    // error.push('error-users-empty');\n\n    resume();\n});\n\nsql.select('orders', 'tbl_orders');\n\n// sql.validate([error message], [result name for validation])\nsql.validate('error-orders-empty');\n// is same as:\n// sql.validate('error-orders-empty', 'orders');\n\nsql.validate('error-users-empty', 'users');\n```\n\n### Escaping values\n\n- doesn't work with MongoDB\n\n```javascript\nvar escaped1 = Agent.escape(value);\n\n// or ...\n\nvar sql = new Agent();\nvar escaped2 = sql.escape(value);\n```\n\n### Predefined queries\n\n- doesn't work with MongoDB\n\n```plain\nAgent.query(name, query);\n```\n\n```javascript\nAgent.query('users', 'SELECT * FROM tbl_users');\nAgent.query('allorders', 'SELECT * FROM view_orders');\n\nsql.query('users').where('id', '\u003e', 20);\nsql.query('orders', 'allorders').limit(5);\n\nsql.exec(function(err, response) {\n    console.log(response[0]); // users\n    console.log(response.orders); // orders\n});\n```\n\n### Waiting for specified values\n\n- `+3.1.0`\n\n```javascript\nsql.when('users', function(error, response, value) {\n    console.log(value);\n});\n\nsql.when('orders', function(error, response, value) {\n    console.log(value);\n});\n\nsql.select('users', 'tbl_users');\nsql.select('orders', 'tbl_orders');\nsql.exec();\n```\n\n## Bonus\n\n### How to get latest inserted ID?\n\n- doesn't work with MongoDB\n\n```javascript\nsql.insert('user', 'tbl_user').set('name', 'Peter');\n\nsql.bookmark(function() {\n    console.log(sql.id);\n});\n\nsql.exec();\n```\n\n### Expected values? No problem\n\n- __MongoDB__ supports expected values only in conditions.\n\n```plain\nsql.expected(name, index, property); // gets a specific value from the array\nsql.expected(name, property);\n```\n\n```javascript\nsql.select('user', 'tbl_user').where('id', 1).first();\nsql.select('products', 'tbl_product').where('iduser', sql.expected('user', 'id'));\n\nsql.exec();\n```\n\n### Measuring time\n\n```javascript\nsql.exec(function(err, response) {\n    console.log(sql.time + ' ms');\n    // or\n    // console.log(this.time)\n});\n```\n\n### Events\n\n```javascript\nsql.on('query', function(name, query, params){});\nsql.on('data', function(name, response){});\nsql.on('end', function(err, response, time){});\n```\n\n### Generators in total.js\n\n```javascript\nfunction *some_action() {\n    var sql = DB();\n\n    sql.select('users', 'tbl_user').make(function(select) {\n        select.where('id', '\u003e', 100);\n        select.and();\n        select.where('id', '\u003c', 1000);\n        select.limit(10);\n    });\n\n    sql.select('products', 'tbl_product').make(function(select) {\n        select.where('price', '\u003c\u003e', 10);\n        select.limit(10);\n    });\n\n    // get all results\n    var results = yield sync(sql.$$exec())();\n    console.log(results);\n\n    // or get a specific result:\n    var result = yield sync(sql.$$exec('users'))();\n    console.log(result);\n}\n```\n\n### Priority\n\nSet a command priority, so the command will be processed next round.\n\n```javascript\nsql.select('... processed as second')\nsql.select('... processed as first');\nsql.priority(); // --\u003e takes last item in queue and inserts it as first (sorts it immediately).\n```\n\n\n### Debug mode\n\nDebug mode writes each query to console.\n\n```javascript\nsql.debug = true;\n```\n\n### We need to return into the callback only one value from the response object\n\n```javascript\nsql.exec(callback, 0); // --\u003e returns first value from response (if isn't error)\nsql.exec(callback, 'users'); // --\u003e returns response.users (if is isn't error)\n\nsql.exec(function(err, response) {\n    if (err)\n        throw err;\n    console.log(response); // response will contain only orders\n}, 'orders');\n```\n\n## SqlBuilder\n\n- automatically adds `and` if is not added between e.g. 2x where\n\n```javascript\n// Creates SqlBuilder\nvar builder = sql.$;\n\nbuilder.where('id', '\u003c\u003e', 20);\nbuilder.set('isconfirmed', true);\n\n// e.g.:\nsql.update('users', 'tbl_users', builder);\nsql.exec(function(err, response) {\n    console.log(response.users);\n})\n```\n\n---\n\n#### builder.callback(fn)\n\n```plain\nbuilder.callback(function(err, response) {\n\n});\n```\n\n`+v11.0.0` returns a value from DB\n\n\n---\n\n#### builder.set()\n\n```plain\nbuilder.set(name, value)\n```\n\nadds a value for update or insert\n\n- `name` (String) column name\n- `value` (Object) value\n\n---\n\n#### builder.raw()\n\n```plain\nbuilder.raw(name, value)\n```\n\nadds a raw value for update or insert without SQL encoding\n\n- `name` (String) column name\n- `value` (Object) value\n\n---\n\n```plain\nbuilder.set(obj)\n```\nadds an object for update or insert value collection\n\n```javascript\nbuilder.set({ name: 'Peter', age: 30 });\n// is same as\n// builder.set('name', 'Peter');\n// builder.set('age', 30);\n```\n\n---\n\n#### builder.inc()\n\n```plain\nbuilder.set(name, [type], value)\n```\n\nadds a value for update or insert\n\n- `name` (String) column name\n- `type` (String) increment type (`+` (default), `-`, `*`, `/`)\n- `value` (Number) value\n\n```javascript\nbuilder.inc('countupdate', 1);\nbuilder.inc('countview', '+', 1);\nbuilder.inc('credits', '-', 1);\n\n// Short write\nbuilder.inc('countupdate', '+1');\nbuilder.inc('credits', '-1');\n```\n\n---\n\n#### builder.rem()\n\n```plain\nbuilder.rem(name)\n```\nremoves an value for inserting or updating.\n\n```javascript\nbuilder.set('name', 'Peter');\nbuilder.rem('name');\n```\n\n---\n\n#### builder.sort()\n\n```plain\nbuilder.sort(name, [desc])\nbuilder.order(name, [desc])\n```\nadds sorting\n\n- `name` (String) column name\n- `desc` (Boolean), default: false\n\n#### builder.random()\n\n```plain\nbuilder.random()\n```\n\nReads random rows. __IMPORTANT__: MongoDB doesn't support this feature.\n\n---\n\n#### builder.skip()\n\n```plain\nbuilder.skip(value)\n```\nskips records\n\n- `value` (Number or String), string is automatically converted into number\n\n---\n\n#### builder.take()\n\n```plain\nbuilder.take(value)\nbuilder.limit(value)\n```\ntakes records\n\n- `value` (Number or String), string is automatically converted into number\n\n---\n\n#### builder.page()\n\n```plain\nbuilder.page(page, maxItemsPerPage)\n```\nsets automatically sql.skip() and sql.take()\n\n- `page` (Number or String), string is automatically converted into number\n- `maxItemsPerPage` (Number or String), string is automatically converted into number\n\n---\n\n#### builder.first()\n\n```plain\nbuilder.first()\n```\nsets sql.take(1)\n\n---\n\n#### builder.join()\n\n- doesn't work with MongoDB\n\n```plain\nbuilder.join(name, on, [type])\n```\n\nadds a value for update or insert\n\n- `name` (String) table name\n- `on` (String) condition\n- `type` (String) optional, inner type `inner`, `left` (default), `right`\n\n```javascript\nbuilder.join('address', 'address.id=user.idaddress');\n```\n\n---\n\n#### builder.where()\n\n```plain\nbuilder.where(name, [operator], value)\nbuilder.push(name, [operator], value)\n```\nadd a condition after SQL WHERE\n\n- `name` (String) column name\n- `operator` (String), optional `\u003e`, `\u003c`, `\u003c\u003e`, `=` (default)\n- `value` (Object)\n\n---\n\n#### builder.group()\n\n- doesn't work with MongoDB\n\n```plain\nbuilder.group(name)\nbuilder.group(name1, name2, name3); // +v2.9.1\n```\ncreates a group by in SQL query\n\n- `name` (String or String Array)\n\n---\n\n#### builder.having()\n\n- doesn't work with MongoDB\n\n```plain\nbuilder.having(condition)\n```\nadds having in SQL query\n\n- `condition` (String), e.g. `MAX(Id)\u003e0`\n\n---\n\n#### builder.and()\n\n```plain\nbuilder.and()\n```\nadds AND to SQL query. __IMPORTANT__: In MongoDB has to be this operator used before all queries.\n\n---\n\n#### builder.or()\n\n```plain\nbuilder.or()\n```\nadds OR to SQL query. __IMPORTANT__: In MongoDB has to be this operator used before all queries.\n\n---\n\n#### builder.in()\n\n```plain\nbuilder.in(name, value)\n```\nadds IN to SQL query\n\n- `name` (String), column name\n- `value` (String, Number or String Array, Number Array)\n\n---\n\n#### builder.between()\n\n```plain\nbuilder.between(name, a, b)\n```\nadds between to SQL query\n\n- `name` (String), column name\n- `a` (Number)\n- `b` (Number)\n\n---\n\n#### builder.overlaps()\n\n```plain\nbuilder.overlaps(valueA, valueB, columnA, columnB)\n```\n- __only for PostgreSQL__\n\nadds overlaps to SQL query\n\n- `valueA` (String, Number, Date)\n- `valueB` (String, Number, Date)\n- `columnA` (String), column A name\n- `columnB` (String), column B name\n\n---\n\n#### builder.like()\n\n```plain\nbuilder.like(name, value, [where])\n```\nadds like command\n\n- `name` (String) column name\n- `value` (String) value to search\n- `where` (String) optional, e.g. `beg`, `end`, `*` ==\u003e %search (beg), search% (end), %search% (*)\n\n---\n\n#### builder.sql()\n\n- doesn't work with MongoDB\n\n```plain\nbuilder.sql(query, [param1], [param2], [param..n])\n```\nadds a custom SQL to SQL query\n\n- `query` (String)\n\n```javascript\nbuilder.sql('age=? AND name=?', 20, 'Peter');\n```\n\n#### builder.query()\n\n- works with MongoDB\n\n```plain\nbuilder.query(fieldname, filter)\n```\nadds a custom QUERY to filter.\n\n```javascript\nbuilder.query('tags', { $size: 0 });\n```\n\n---\n\n#### builder.scope()\n\n```plain\nbuilder.scope(fn);\n```\nadds a scope `()`\n\n```javascript\nbuilder.where('user', 'person');\nbuilder.and();\n\n// RDMBS:\nbuilder.scope(function() {\n    builder.where('type', 20);\n    builder.or();\n    builder.where('age', '\u003c', 20);\n});\n\n// MongoDB:\nbuilder.scope(function() {\n    builder.or();\n    builder.where('type', 20);\n    builder.where('age', '\u003c', 20);\n});\n\n// creates: user='person' AND (type=20 OR age\u003c20)\n```\n\n#### builder.define()\n\n```plain\nbuilder.define(name, SQL_TYPE_LOWERCASE);\n```\n- __only for SQL SERVER__\n- change the param type\n\n```javascript\nvar insert = sql.insert('user', 'tbl_user');\n\ninsert.set('name', 'Peter Širka');\ninsert.define('name', 'varchar');\ninsert.set('credit', 340.34);\ninsert.define('credit', 'money');\nsql.exec();\n```\n\n---\n\n#### builder.schema()\n\n- doesn't work with MongoDB\n\n```plain\nbuilder.schema()\n```\nsets current schema for `where`, `in`, `between`, `field`, `fields`, `like`\n\n```javascript\nbuilder.schema('b');\nbuilder.fields('name', 'age'); // --\u003e b.\"name\", b.\"age\"\nbuilder.schema('a');\nbuilder.fields('name', 'age'); // --\u003e a.\"name\", a.\"age\"\nbuilder.fields('!COUNT(id) as count') // --\u003e a.COUNT()\n```\n\n#### builder.escape()\n\n- doesn't work with MongoDB\n\n```plain\nbuilder.escape(string)\n```\nescapes value as prevention for SQL injection\n\n#### builder.fields()\n\n```plain\nbuilder.fields()\n```\nsets fields for data selecting.\n\n```javascript\nbuilder.fields('name', 'age'); // \"name\", \"age\"\nbuilder.fields('!COUNT(id)'); // Raw field: COUNT(id)\nbuilder.fields('!COUNT(id) --\u003e number'); // Raw field with casting: COUNT(id)::int (in PG), CAST(COUNT(id) as INT) (in SQL SERVER), etc.\n```\n\n#### builder.replace()\n\n```plain\nbuilder.replace(builder, [reference])\n```\nreplaces current instance of SqlBuilder with new. The argument `reference` (default: `false`) when is `true` creates a reference to `builder` (it doesn't clone it). Better performance with lower memory.\n\n- `builder` (SqlBuilder) Another instance of SqlBuilder.\n\n\n---\n\n#### builder.toString()\n\n- doesn't work with MongoDB\n\n```plain\nbuilder.toString()\n```\ncreates escaped SQL query (internal)\n\n## Blob\n\n### PostgreSQL\n\n- all file operations are executed just-in-time (you don't need to call `sql.exec()`)\n- all file operations aren't executed in queue\n\n```javascript\n// sql.writeStream(filestream, [buffersize](default: 16384), callback(err, loid))\nsql.writeStream(Fs.createReadStream('/file.png'), function(err, loid) {\n    // Now is the file inserted\n    // Where is the file stored?\n\n    // loid === NUMBER\n    // SELECT * FROM pg_largeobject WHERE loid=loid\n});\n\n// sql.writeBuffer(buffer, callback(err, loid))\nsql.writeBuffer(Buffer.from('Peter Širka', 'utf8'), function(err, loid) {\n    // Now is the buffer inserted\n    // Where is the buffer stored?\n\n    // loid === NUMBER\n    // SELECT * FROM pg_largeobject WHERE loid=loid\n});\n\n// sql.readStream(loid, [buffersize](default: 16384), callback(err, stream, size))\nsql.readStream(loid, function(err, stream, size) {\n    // stream is created\n});\n```\n\n### MongoDB\n\n- all file operations are executed immediately, there's no need to call sql.exec()\n\n```javascript\n// nosql.writeStream(id, stream, filename, [metadata], [options], callback)\nnosql.writeStream(new ObjectID(), Fs.createReadStream('logo.png'), 'logo.png', function(err) {\n    // Now is the stream inserted\n});\n\n// nosql.readStream(id, [options], callback(err, stream, metadata, size, filename))\nnosql.readStream(id, function(err, stream, metadata, size, filename) {\n    stream.pipe(Fs.createWriteStream('myfile.png'));\n});\n\n// get file info\nnosql.select('fs.files').make(function(builder){\n    // available fields - _id,filename,contentType,length,chunkSize,uploadDate,aliases,metadata,md5\n    builder.fields('filename', 'metadata');\n});\n\nnosql.exec(function(err, results){\n    console.log(results);\n});\n```\n\n## Global events\n\n__Global events__:\n\n```javascript\nON('database', function() {\n    // Database is ready\n});\n```\n\n## Async/Await\n\n`+v12.0.0` supports `sql.promise([name], [callback(response)])` for using of async/await.\n\n- `sql.promise()` performs `sql.exec()`\n- look to example below:\n\n```javascript\nvar Agent = require('sqlagent/pg').connect('...');\n\nasync function data() {\n    var b = new Agent();\n    b.select('users', 'tbl_users');\n    var users = await b.promise('users');\n    console.log(users);\n}\n\ndata();\n```\n\n## Contributors\n\n| Contributor | Type | E-mail |\n|-------------|------|--------|\n| [Peter Širka](https://github.com/JozefGula) | author + support | \u003cpetersirka@gmail.com\u003e |\n| [Martin Smola](https://github.com/molda) | contributor + support | \u003csmola.martin@gmail.com\u003e |\n| [Jay Kelkar](https://github.com/jkelkar) | contributor | \u003cjkelkar@gmail.com\u003e |\n| [Aidan Dunn](https://github.com/Aidan-Chey) | contributor | \u003caidancheyd@gmail.com\u003e |\n\n## Contact\n\nDo you have any questions? Contact us \u003chttps://www.totaljs.com/contact/\u003e\n\n[![Professional Support](https://www.totaljs.com/img/badge-support.svg)](https://www.totaljs.com/support/) [![Chat with contributors](https://www.totaljs.com/img/badge-chat.svg)](https://messenger.totaljs.com)\n\n[license-image]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat\n[license-url]: license.txt\n\n[npm-url]: https://npmjs.org/package/sqlagent\n[npm-version-image]: https://img.shields.io/npm/v/sqlagent.svg?style=flat\n[npm-downloads-image]: https://img.shields.io/npm/dm/sqlagent.svg?style=flat\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftotaljs%2Fnode-sqlagent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftotaljs%2Fnode-sqlagent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftotaljs%2Fnode-sqlagent/lists"}