{"id":14973966,"url":"https://github.com/planetarydev/json-sql-builder2","last_synced_at":"2025-05-05T16:22:15.370Z","repository":{"id":48307532,"uuid":"112904570","full_name":"planetarydev/json-sql-builder2","owner":"planetarydev","description":"Level Up Your SQL-Queries","archived":false,"fork":false,"pushed_at":"2023-03-01T13:34:55.000Z","size":646,"stargazers_count":76,"open_issues_count":14,"forks_count":20,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-04-22T06:18:28.384Z","etag":null,"topics":["database","javascript","json","mariadb","mongo","mssql","mysql","nodejs","oracle","pgsql","postgresql","query","query-builder","sql","sqlite3","translate","transpiler"],"latest_commit_sha":null,"homepage":null,"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/planetarydev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-12-03T06:05:53.000Z","updated_at":"2025-02-09T21:19:11.000Z","dependencies_parsed_at":"2024-06-18T17:22:08.572Z","dependency_job_id":null,"html_url":"https://github.com/planetarydev/json-sql-builder2","commit_stats":{"total_commits":113,"total_committers":8,"mean_commits":14.125,"dds":"0.12389380530973448","last_synced_commit":"72e94109089a3e3bedf355d1766fe80d5e7acc98"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetarydev%2Fjson-sql-builder2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetarydev%2Fjson-sql-builder2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetarydev%2Fjson-sql-builder2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetarydev%2Fjson-sql-builder2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/planetarydev","download_url":"https://codeload.github.com/planetarydev/json-sql-builder2/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252531883,"owners_count":21763293,"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":["database","javascript","json","mariadb","mongo","mssql","mysql","nodejs","oracle","pgsql","postgresql","query","query-builder","sql","sqlite3","translate","transpiler"],"created_at":"2024-09-24T13:49:45.369Z","updated_at":"2025-05-05T16:22:15.348Z","avatar_url":"https://github.com/planetarydev.png","language":"JavaScript","readme":"# json-sql-builder2\n\nLevelup your Queries with `json-sql-builder2`.\n\n# Table of Content\n\n- [Why to use json-sql-builder2](#why-to-use-json-sql-builder2)\n- [Supported SQL-Dialects](#supported-sql-dialects)\n- [Documentation](#documentation)\n- [Getting Started](#getting-started)\n  - [Install](#install)\n  - [First Example](#first-example)\n  - [Setup SQLBuilder](#setup-sqlbuilder)\n  - [Support different Data Types](#support-different-data-types)\n  - [Using Keywords](#using-keywords)\n  - [More Examples](#more-examples)\n  - [Working with SQL-Functions](#working-with-sql-functions)\n- [Writing new Helpers and Operators](#writing-new-helpers-and-operators)\n  - [What are the differences between Operators and Helpers?](#what-are-the-differences-between-operators-and-helpers)\n  - [Using a Template](#using-a-template)\n    - [Example writing LEFT-Function Helper](#example-writing-left-function-helper)\n    - [Understanding, Writing the Syntax](#understanding-writing-the-syntax)\n      - [Sub-Syntaxing](#sub-syntaxing)\n    - [Native js Function support - using SQLBuiler.CALLEE](#native-js-function-support---using-sqlbuilercallee)\n    - [Dialect-Specific SQL-Parts](#dialect-specific-sql-parts)\n  - [Concating iterateable Informations](#concating-iterateable-informations)\n  - [BuiltIn Parameters](#builtin-parameters)\n  - [More Examples writing new stuff](#more-examples-writing-new-stuff)\n- [Tests](#tests)\n- [Generating docs](#generating-docs)\n- [License](#license)\n\n# Why to use json-sql-builder2\n\nYou are working with javascript and got the power of json, so why do you concat string by string or worry about query parameters.\nWhen you need to write dynamic queries defined by the user it is also much easier to use JSON instead of generating a string-based query.\n\nAnother point is that in most cases the readability and structuring the query is much better than using strings.\n\nWorking with the JSON DataType is also much easier (see JSON-Example below).\n\n# Supported SQL-Dialects\n\nBy default `json-sql-builder2` supports the follwing languages.\n- [x] MySQL\n- [x] MariaDB\n- [x] PostgreSQL\n- [x] SQLite\n- [x] Oracle\n- [x] Microsoft SQL Server\n\n# Documentation\nEach Operator and Helper is well documented. And you've got a lot of examples for each.\n\nFor further details on each Helper or Operators have a look at the complete\ndocumentation at [https://github.com/planetarydev/json-sql-builder2/tree/master/sql](https://github.com/planetarydev/json-sql-builder2/tree/master/sql) and search or browse through the directories.\n\n# Getting Started\n\n## Install\n\n```sh\nnpm install json-sql-builder2 --save\n```\n\n## First Example\n\n```javascript\nconst SQLBuilder = require('json-sql-builder2');\n// create a new instance of the SQLBuilder and load the language extension for mysql\nvar sql = new SQLBuilder('MySQL');\n\n// lets start some query fun\nvar totalSalary = sql.$select({\n    job_title: true,\n    total_salary: { $sum: 'salary' }\n    $from: 'people',\n    $where: {\n        job_title: { $in: ['Sales Manager', 'Account Manager'] },\n        age: { $gte: 18 },\n        country_code: 'US',\n    },\n    $groupBy: 'job_title',\n});\n\n```\n\n**Result**\n```javascript\n// totalSalary.sql\nSELECT\n    `job_title`,\n    SUM(`salary`) AS `total_salary`\nFROM\n    `people`\nWHERE\n    `job_title` IN (?, ?)\nAND `age` \u003e= ?\nAND `country_code` = ?\nGROUP BY\n    `job_title`\n\n// totalSalary.values\n['Sales Manager', 'Account Manager', 18, 'US']\n\n```\n\n\n## Setup SQLBuilder\n\nBy default you will create a new Instance of SQLBuilder by passing the language-dialect as String you would like to work with.\n\n```javascript\nconst SQLBuilder = require('json-sql-builder2');\n// Syntax:\n// SQLBuilder(\u003cdialect\u003e[, options]);\n//\n// dialect: String | Function\n// options: Object\n\n// Setup a new instance for MySQL\nvar sql = new SQLBuilder('MySQL');\n\n// Setup a new instance for MariaDB\nvar sql = new SQLBuilder('MariaDB');\n\n// Setup a new instance for PostgreSQL\nvar sql = new SQLBuilder('PostgreSQL');\n\n// Setup a new instance for SQLite\nvar sql = new SQLBuilder('SQLite');\n\n// Setup a new instance for Oracle\nvar sql = new SQLBuilder('Oracle');\n\n// Setup a new instance for SQLServer\nvar sql = new SQLBuilder('SQLServer');\n\n\n// Passing a function as dialect param to setup your individual needs\nvar sql = new SQLBuilder(function(sql) {\n    // set the name to one of the supported language-dialects\n    sql.setLanguage('SQLServer');\n\n    // set the left and right handed quoting character\n    sql.setQuoteChar('[', ']');\n    // if there the character is the same for left and right\n    sql.setQuoteChar('`');\n\n    // setup the placholder for each value pushed to the value-stack\n    sql.placeholder = function() {\n        return '@param' + sql._values.length;\n    }\n\n    // if neccessary turn the array of values to a object\n    sql.transformValueResult = function(valuesAsArray) {\n        let resultAsObj = {}\n        sql.forEach(valuesAsArray, (value, index) =\u003e {\n            resultAsObj['param' + index] = value\n        });\n        return resultAsObj;\n    }\n});\n```\n\n\n### Options\n\n- `quoteIdentifiers` true | false (Default=false)\n\nIf this option is `true` each identifier will be quoted. If this option is set to `false` only invalid, unsafe identifiers will be quoted.\n\n- `attachGlobal` true | false (Default=false)\n\nThis Option will attach each Operator like `$select` in uppercase `SELECT`, each callee like `left` in lowercase `$left` and each Keyword in uppercase letters to the `globals` Object, so you could write your code like:\n\n```javascript\nvar sql = new SQLBuilder('SQLServer', {\n    attachGlobal: true\n});\n\nlet myQuery = SELECT({\n    people_name: $concat($left($i('people.first_name'), 1), '. ', $i('people.last_name')),\n    $from: 'people',\n    $where: {\n        job_title: $in(['Sales Manager', 'Account Manager']),\n        last_name: $eq('Doe')\n    }\n});\n\n// Results\n// myQuery.sql\nSELECT\n    CONCAT(LEFT([people].[first_name], @param1), @param2, [people].[last_name]) AS [people_name]\nFROM\n    [people]\nWHERE\n    [job_title] IN (@param3, @param4)\nAND [last_name] = @param5\n\n// myQuery.values\n{\n    param1: 1,\n    param2: '. ',\n    param3: 'Sales Manager',\n    param4: 'Account Manager',\n    param5: 'Doe'\n}\n\n```\n\n- `useOuterKeywordOnJoin` true | false\n\nHave a look at the source of [/sql/helpers/queries/join/.joinhelper.js](./sql/helpers/queries/join/.joinhelper.js)\n\n\n\n## Support different Data Types\n\nEach Operator and Helper can be used with different Data Types, so it is easy to take the Type that fits your needs.\nHave a look at the README.md for the Helpers, Operator you like to use. Each of them are well documented and the file\nis located directly beside the source-code.\n\n```javascript\nmyQuery = sql.$insert({\n    $table: 'people',\n    $columns: {\n        first_name: true,\n        last_name: true,\n        age: true\n    },\n    $values: ['John', 'Doe', 40]\n});\n\n// is the same as:\nmyQuery = sql.$insert({\n    $table: 'people',\n    $columns: ['first_name', 'last_name', 'age'],\n    $values: ['John', 'Doe', 40]\n});\n\n// is the same as:\nmyQuery = sql.$insert({\n    $table: 'people',\n    $documents: {\n        first_name: 'John',\n        last_name: 'Doe',\n        age: 40\n    }\n});\n\n// SQL output\nINSERT INTO\n    people (first_name, last_name, age)\nVALUES\n    ($1, $2, $3)\n\n// Values\n{\n    \"$1\": \"John\",\n    \"$2\": \"Doe\",\n    \"$3\": 40\n}\n```\n\n\n### Using Keywords\n\nA complete List of all Keywords you will find at [./sql/keywords/](./sql/keywords/).\n\n:bulb: **Exmple using Keyword DEFAULT**\n```javascript\nmyQuery = sql.$insert({\n    $table: 'people',\n    $documents: {\n        first_name: 'John',\n        last_name: 'Doe',\n        age: sql.DEFAULT\n    }\n});\n\n// SQL output\nINSERT INTO\n    people (first_name, last_name, age)\nVALUES\n    ($1, $2, DEFAULT)\n\n// Values\n{\n    \"$1\": \"John\",\n    \"$2\": \"Doe\"\n}\n```\n\n## More Examples\n\n## Working with SQL-Functions\n\n```javascript\nmyQuery = sql.$select({\n    people_name: { $concat: ['~~first_name', ' ', '~~last_name'] },\n    $from: 'people'\n});\n\n// instead using $concat helper as js-function is also possible\nmyQuery = sql.$select({\n    people_name: sql.concat('~~first_name', ' ', '~~last_name'),\n    $from: 'people'\n});\n\n// SQL output\nSELECT\n    CONCAT(first_name, $1, last_name) AS people_name\nFROM\n    people\n\n// Values\n{\n    \"$1\": \" \"\n}\n```\n\n:bulb: **PostgreSQL update jsonb column**\n```javascript\nmyQuery = sql.$update({\n    $table: 'people',\n    $set: {\n        'data-\u003eprofile-\u003efirstName': 'John',\n        'data-\u003eprofile-\u003elastName': 'Doe'\n    },\n    $where: {\n        people_id: 456\n    }\n});\n\n// SQL output\nUPDATE\n    \"people\"\nSET\n    \"data\" = jsonb_set(jsonb_set(\"data\", $1, $2), $3, $4)\nWHERE\n    \"people_id\" = $5\n\n// Values\n{\n    \"$1\": \"{profile,firstName}\",\n    \"$2\": \"\\\"John\\\"\",\n    \"$3\": \"{profile,lastName}\",\n    \"$4\": \"\\\"Doe\\\"\",\n    \"$5\": 456\n}\n```\n\n# Writing new Helpers and Operators\n\n## What are the differences between Operators and Helpers?\nAny Operator can build a valid SQL result by it's own without additional stuff.\nSo each operator will be directly attached as `$\u003coperator-name\u003e` to the SQLBuilder instance.\nThat means you can directly call each Operator like:\n\n```javascript\n\n// standard build-call\nlet myQuery = sql.build({\n    // using '$select'-Operator\n    $select: {\n        $from: 'people'\n        // ...\n    }\n});\n\n// '$select' is an Operator and so you can use this directly\nlet myQuery = sql.$select({\n    $from: 'people'\n});\n\n// instead $from is a Helper\n// and this could'nt be directly called like sql.$from({...})\n\n```\n## Using a Template\n\n**A Template for writing new Helpers and Operators:**\n\nEach Operator should be located in `/sql/operators/\u003coperator-name/`.\n\nUse the following template to create a new Operator.\n\n```javascript\nclass \u003coperator-name\u003e extends SQLBuilder.[SQLOperator | SQLHelper] {\n    constructor(sql){\n        super(sql);\n\n        // definition of allowed types and it's SQL Syntax\n        // more details on writing your Syntax (see 'Define a new Syntax' below)\n        this.Types({\n            // simple Type-based Syntax\n            // where Type is String, Number, Boolean, Primitive, Object, Array, Function\n            [type]: { syntax: this.Syntax(...) },\n\n            // simple type-based Syntax as iterateable with defined sub/item-types\n            // type can be Object or Array\n            [type]: {\n                eachItemOf: {\n                    // type can be String, Number, Boolean, Primitive, Object, Array, Function\n                    \u003ctype\u003e: { syntax: this.Syntax(...) }\n                }\n            }\n\n            // type-value-based definitions:\n            // type can be String, Number, Boolean\n            [type]: {\n                syntax: {\n                    // List all values that are valid to use\n                    // with the current Helper or Operator\n                    [\u003cvalue-1\u003e: this.Syntax(...) [,\u003cvalue-n\u003e: ...]]\n                }\n            }\n\n            // type-based, iterateable and value-ased restricted Syntax\n            // type can be Object or Array\n            [type]: {\n                eachItemOf: {\n                    // type can be String, Number, Boolean, Primitive, Object, Array, Function\n                    \u003ctype\u003e: {\n                        syntax: {\n                            // List all values that are valid to use\n                            // with the current Helper or Operator\n                            [\u003cvalue-1\u003e: this.Syntax(...) [,\u003cvalue-n\u003e: ...]]\n                        }\n                    }\n                }\n            }\n\n        });\n\n        // optional declaration of Keywords\n        this.Keyword('\u003ckeyword\u003e');\n\n        // optional registration of private Helpers that are used inside the\n        // Syntax declared above with this.Types({...})\n        this.registerPrivateHelper('\u003chelper-name\u003e'); // the helper must be located in \"./private/\u003chelper-name\u003e/\u003chelper-name\u003e.js\"\n        // or register your private helper by your own\n        this.$\u003chelper-name\u003e = new \u003chelperClass\u003e(sql);\n    }\n\n    // optional function callee definition if the standard\n    // callee - generated by Syntax - doesn't fit\n    callee(/*args*/, identifier){\n        // ...\n        return sqlResultString;\n    }\n\n    // optional linker-method\n    link(query, identifier){\n        // ...\n    }\n\n    // optional preBuild-method\n    preBuild(query, identifier) {\n        // ...\n        return query;\n    }\n\n    // optional postBuild-method\n    postBuild(result, type, itemType){\n        // ...\n        return result;\n    }\n}\n\nmodule.exports = {\n    definition: \u003cclass-definition\u003e,\n    description: \u003cString: a short description of the new Helper or Operator\u003e,\n    supportedBy: {\n        // list all SQL-dialects that support this new Helper or Operator\n        // SQL-dialect can be: MySQL, MariaDB, PostgreSQL, SQLite, Oracle, SQLServer\n        \u003cSQL-dialect\u003e: \u003c'' | url to official docs\u003e\n        [, \u003canother SQL-dialect\u003e: \u003c'' | url to official docs\u003e]\n    },\n    examples: {\n        // write at minimum one Test \"Basic Usage\" for each Type of Syntax defined above\n        // using the same structure as used by this.Types({...}) in the class constructor.\n        // Additional Tests and Examples allways wellcome!\n\n        // Example of a Test-Case for the Type \"Object\":\n        Object: {\n            \"Basic Usage\": function(sql) {\n                return {\n                    // if the test is restricted to special SQL dialects\n                    [supportedBy: {\n                        // list all dialects (MySQL, MariaDB, PostgreSQL, SQLite, Oracle, SQLServer)\n                        // the Test is valid for\n                        \u003cSQL-dialect\u003e: true\n                    },]\n                    test: function() {\n                        return sql.build({\n                            $select: {\n                                $from: 'people'\n                            }\n                        });\n                    },\n                    expectedResults: {\n                        sql: 'SELECT * FROM people',\n                        values: {}\n\n                        // List any SQL-dialect if the Result on Test is different to the generell Result\n                        [,\u003cSQL-dialect\u003e: {\n                            sql: \u003cResult-String if there are different using a special SQL-dialect\u003e\n                            values: {\n                                $1: ...\n                                $2: ...\n                            }\n                        }]\n                    }\n                }\n            }\n            [, \"\u003cname of another Test\u003e\": function(sql){\n                // ...\n            }]\n        }\n    }\n}\n```\n\n### Example writing LEFT-Function Helper\n\nIf there is something missing you can easily extend all your required stuff.\n\n**If you will create a new Helper or Operator I would be glad if you will\ncontribute and share your magic stuff.**\n\nThe only thing you have to do is browse to the right place inside the `/sql/` directory\nand create a new folder and file named with the Helper or Operator.\n\nIn our Example we will create the `LEFT()` SQL-Function.\n\nThis file will be located at `/sql/helpers/functions/string/`:\n- create a new Folder `left`\n- create a new File `left/left.js`\n\nHere is the code you need to write for `left.js` using the Template:\n\n```javascript\n'use strict';\n\n// give the new Class the name of the Helper or Operator\nclass left extends SQLBuilder.SQLHelper {\n    constructor(sql){\n        // always call the construtor of SQLHelper first\n        super(sql);\n\n        // declare the possible types that can be used\n        this.Types({\n            Number: { syntax: this.Syntax('LEFT(\u003ckey-ident\u003e, \u003cvalue-param\u003e)') },\n            Object: { syntax: this.Syntax('LEFT(\u003c$str\u003e, \u003c$len\u003e)', SQLBuilder.CALLEE) },\n        });\n\n        // add each Helper defined in the Syntax as private, predefined Helper\n        this.$str = new SQLBuilder.SQLPredefined.StringValueParam(sql);\n        this.$len = new SQLBuilder.SQLPredefined.NumberValueParam(sql);\n    }\n}\n\n// export the new $left Helper\nmodule.exports = {\n    // exports the class-definition (this is used by SQLBuilder to setup the new Helper)\n    definition: left,\n\n    // add some description for the auto-generation of the docs README.MD\n    description: `Specifies the \\`LEFT\\` function.`,\n\n    // define the SQL-dialects that support this new Helper\n    // Each dialect listed by supported by can use this Helper. If you pass a string\n    // that starts with 'http://' or 'https://' inside the docs it automatically creates a link\n    // to the official docs\n    supportedBy: {\n        MySQL: 'https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_left',\n        MariaDB: 'https://mariadb.com/kb/en/library/left/',\n        PostgreSQL: 'https://www.postgresql.org/docs/9.1/static/functions-string.html',\n        // SQLite did not support the left() function at this time\n        // Oracle did not support the left() function at this time --\u003e instead we can use SUBSTR( string, start_position [, length ] ) defined as new SQLHelper\n        SQLServer: 'https://docs.microsoft.com/en-us/sql/t-sql/functions/left-transact-sql'\n    },\n\n    // Always add at least \"Basic Usage\" as test and example for each type you\n    // have declared by the new class using this.Types()\n    examples: {\n        Number: {\n            // Basic Usage is the Name of the Test and must always declared as function(sql)\n            // Parameter sql will be passed as instance of the SQLBuilder\n            \"Basic Usage\": function(sql) {\n                // the function always returns an Object {test: function() {}, expectedResults: {} [, supportedBy: { PostgreSQL: true, MySQL: true, ... }] }\n                return {\n                    // write your test and return always the result\n                    test: function(){\n                        return sql.$select({\n                            firstname: { $left: 1 }\n                        });\n                    },\n                    // define the expected results of the test with\n                    // sql as String and values as Object. If there are no values expected, so define an empty Object like values: {}\n                    expectedResults: {\n                        sql: 'SELECT LEFT(first_name, $1) AS first_name',\n                        values: {\n                            $1: 1\n                        }\n                    }\n                }\n            }\n        },\n        Object: {\n            // Basic Usage is the Name of the Test and must always declared as function(sql)\n            // where sql is the instance of the SQLBuilder\n            \"Basic Usage\": function(sql) {\n                // the function always returns an Object {test: function() {}, expectedResults: {} [, supportedBy: { PostgreSQL: true, MySQL: true, ... }] }\n                return {\n                    // write your test and return always the result\n                    test: function(){\n                        return sql.$select({\n                            test: { $left: { $str: 'Hello World', $len: 5 } }\n                        });\n                    },\n                    // define the expected results of the test with\n                    // sql as String and values as Object. If there are no values generated, so define an empty Object values: {}\n                    expectedResults: {\n                        sql: 'SELECT LEFT($1, $2) AS test',\n                        values: {\n                            $1: 'Hello World',\n                            $2: 5\n                        }\n                    }\n                }\n            },\n            // Optionally add some more Tests and Examples with a different name:\n            \"Usage of LEFT as Function\": function(sql) {\n                return {\n                    test: function(){\n                        return sql.$select({\n                            // The helper can directly used as native js-function because\n                            // we setup the Syntax for Type \"Object\" with SQLBuilder.CALLEE parameter as second (see above)\n                            test: sql.left('Hello World', 5)\n                        });\n                    },\n                    expectedResults: {\n                        sql: 'SELECT LEFT($1, $2) AS test',\n                        values:{\n                            $1: 'Hello World',\n                            $2: 5\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n### Understanding, Writing the Syntax\n\nEvery Helper or Operator will be defined by a Type, iterateable sub-Type and optionally value restrictions.\nFor each of this situation you have to support a valid Syntax, that will generate the\nSQL-Result-String for the Helper or Operator.\n\n**Example of SUBSTR-Syntax for Type Object**\n\n```javascript\nclass substr extends SQLBuilder.SQLHelper {\n    constructor() {\n        ...\n        this.Types({\n            Object: { syntax: this.Syntax('SUBSTR(\u003c$str\u003e FROM \u003c$start\u003e{ FOR [$len]})', SQLBuilder.CALLEE) }\n        }\n        ...\n    }\n}\n```\n\nOkay, lets explain the *magic* stuff we have declared above.\n\nBy defining only the Type `Object` you can only use the `$substr` Helper like `first_name: { $substr: {...} }`.\nIf you try to use it with a Number-Value like `first_name: { $substr: 5 }` the SQLBuilder will throw an Error like `Type Number is not allowed by Syntax`.\n\nIn our case we define two required Parameters (or better say Helpers). The first one is `\u003c$str\u003e` and the second one is `\u003c$start\u003e`.\nThe third `[$len]` Helper is optional. With this informations we could write the following examples:\n\n```javascript\nlet myQuery = sql.$select({\n    test: { $substr: { $str: 'Hello World', $start: 3 } }\n});\n\n// SQL-Output\nSELECT\n    SUBSTR($1 FROM $2) AS test\n```\n\n#### Sub-Syntaxing\n\nIn most cases of SQL there are optional parts that also include keywords. In our Example of the SUBSTR Function it's the `FOR` option\nthat specifies the length of the substring. So we need a *Sub-Syntax* that will only be generated when the Helper inside is supported.\nThe *Sub-Syntax* is defined by using curly braces like `{ FOR [$len]}`.\n\n\n### Native js Function support - using SQLBuiler.CALLEE\n\nWhat the hell is that?\n\nSometimes it's quite usefull to use a Helper as native js-Function like `test: sql.substr('Hello World', 3)`, so\nyou can specifiy one Syntax per Helper or Operator as callee by adding an optional parameter to the Syntax-Function `SQLBuiler.CALLEE`.\nThis option will automatically turn the Syntax into a native js-function located on the current instance of the SQLBuilder.\nIn our case the Syntax of the Function will be: `sql.substr(\u003cstr\u003e, \u003cstart\u003e [, options])` where **options** is an Object that could take all\noptional Helpers defined by the Syntax.\n\n**Example**\n```javascript\nlet myQuery = sql.$select({\n    test: sql.substr('Hello World', 3, {\n        $len: 5\n    })\n});\n\n// SQL-Output\nSELECT\n    SUBSTR($1 FROM $2 FOR $3) AS test\n```\n\n### Write an individual callee**\n\nSometimes the auto generated callee does not fit our rules, so you can easily write your own callee by adding a method named `callee` to the new Helper class.\nIn this case you could define each Function-Parameter by your own and add code to build the SQL-Result.\nJust a small Example how the substr-callee can look like.\n\n**Example**\n```javascript\nclass substr extends SQLBuilder.SQLHelper {\n    constructor() {\n        ...\n        this.Types({\n            Object: { syntax: this.Syntax('SUBSTR(\u003c$str\u003e FROM \u003c$start\u003e{ FOR [$len]})') } // remove this param: , SQLBuilder.CALLEE) }\n        }\n        ...\n    }\n\n    // add our own callee method\n    callee(str, start, len, identifier /*identifier will always be injected by SQLBuilder as last argument*/) {\n        // the callee-method will be executed\n        // in the context (this) of the current SQLBuilder instance\n        // !!! **this** is NOT the context of this class-Object\n        // so you have access to all useful methods of the SQlBuilder like:\n        // - isString(), isNumber() ...\n        // - isMySQL(), isPostgreSQL(), ...\n        // - quote(), addValue(), isCurrent(), isPreviousHelper(), ...\n        let sqlResult = 'SUBSTR(';\n\n        // check types\n        if (!this.isString(str) || !this.isNumber(start) || (len \u0026\u0026 !this.isNumber(len))) {\n            throw new Error('Using sql.substr failed because of wrong parameter type. Syntax is: sql.substr(str, start[,len])');\n        }\n\n        sqlResult += this.addValue(str) + ' FROM ' + start // we dont add start as parameter and put it directly into the SQL string //this.addValue(start);\n        if (len) {\n            sqlResult += ' FOR ' + len;\n        }\n        sqlResult += ')'\n\n        return sqlResult;\n    }\n}\n\n...\n\n// Using our new selfmade CALLEE\nlet myQuery = sql.$select({\n    test: sql.substr('Hello World', 3, 5)\n});\n\n// SQL-Output\nSELECT\n    SUBSTR($1 FROM 3 FOR 5) AS test\n```\n\n\n\n### Dialect-Specific SQL-Parts\n\nAbout 70% or 80% of all SQL comply with the ANSI SQL-Standard. So you can write code for each Helper and Operator for each SQL-dialect or\nyou can add your specific Helper-Syntax as dialect-specific expression.\n\n**Example**\n\n```javascript\nSELECT\n    { [$top]}--\u003e(SQLServer)\n    { DISTINCT[$distinct]}\n    { SQL_CALC_FOUND_ROWS[$calcFoundRows]}--\u003e(MySQL,MariaDB)\n\n    { \u003c$columns\u003e}\n        { [$into]}--\u003e(MySQL,MariaDB,SQLServer)\n\n    { FROM [$from]}    { [$join]}\n    { WHERE [$where]}\n    { GROUP BY [$groupBy]}\n        { WITH ROLLUP[$withRollup]}--\u003e(MariaDB,MySQL)\n    { HAVING [$having]}\n    { ORDER BY [$orderBy]}\n    { LIMIT [$limit]}--\u003e(MariaDB,MySQL,PostgreSQL,SQLite)\n    { OFFSET [$offset]}--\u003e(MariaDB,MySQL,PostgreSQL,SQLite)\n```\n\nThe Example shows the current Syntax of the `SELECT` Statement. Here you can see some\ndialect-specific Helpers marked with `--\u003e(\u003csql-dialect\u003e[,\u003csql-dialect\u003e,...])`.\n\nSo, if you are running SQLBuilder with PostgreSQL the `$info` Helper for the ` INTO ` clause\nis only supported by MySQL, MariaDB and SQLServer. If you write `$select: { $from: 'people', $into: ... }`\nthe SQLBuilder will throw an Error that `$into Helper is not permitted by Syntax`.\n\n\n\n### Concating iterateable Informations\n\nSometimes you need to define an Array of columns or an Object with column-identifiers and they all need to\nconcatenated by comma with the previouse one. To archive this you can specifiy a concatination-String or Joiner.\n\nLet's build a part of the `$columns` Helper from the `$select` Operator.\n\n```javascript\nlet myQuery = sql.$select({\n    $columns: {\n        first_name: true,\n        last_name: true,\n        ...\n    }\n})\n\n// SQL-Output\nSELECT\n    first_name,\n    last_name,\n    ...\n\n// This is the definition of the $columns Helper.\n// Have a look at the joiner \"[ , ... ]\" inside the Syntax.\nclass columns extends SQLBuilder.SQLHelper {\n    constructor(sql){\n        super(sql);\n\n        this.Types({\n            Object: {\n                // Here we have a iterateable...\n                eachItemOf: {\n                    // ...where each value should have one of the\n                    // following types listed:\n                    Boolean: {\n                        syntax: {\n                            true: this.Syntax('\u003ckey-ident\u003e[ , ... ]'),\n                            false: this.Syntax('')\n                        }\n                    },\n                    Number: {\n                        syntax: {\n                            1: this.Syntax('\u003ckey-ident\u003e[ , ... ]'),\n                            0: this.Syntax('')\n                        }\n                    },\n                    String: { syntax: this.Syntax('\u003ckey-ident\u003e AS \u003cvalue-ident\u003e[ , ... ]') },\n                    Object: { syntax: this.Syntax('\u003cvalue\u003e AS \u003cidentifier\u003e[ , ... ]') },\n                    Function: { syntax: this.Syntax('\u003cvalue\u003e AS \u003ckey-ident\u003e[ , ... ]') }\n                }\n            },\n            Array: {\n                eachItemOf: {\n                    String: { syntax: this.Syntax('\u003cvalue-ident\u003e[ , ... ]') },\n                    Object: { syntax: this.Syntax('\u003cvalue\u003e AS \u003ckey-ident\u003e[ , ... ]') }\n                }\n            },\n            String: { syntax: this.Syntax('\u003cvalue-ident\u003e') }\n        });\n    }\n}\n\n// Joiner [ , ... ] explained:\n// Each joiner has this style: \"[ \u003cjoiner-def\u003e... ]\"\n// ! note of the space chars \u003e---^---------------^\n```\n\nEvery time the Syntax includes such a declaration the SQLBuilder extracts the joiner-definition and concatenates each item with this string-definition.\n\nAnother Example of a joiner-Definition you will find at `/sql/helpers/locical/and/and.js` which is a Helper that is used by the $where Helper.\nThe joiner is defined as `[  AND ... ]`.\n\n### BuiltIn Parameters\n\nEach Syntax can take - so called BuiltIn-Params - to interact with the JSON-Data. For this\nyou have to following parameter definitions you could use inside each Syntax:\n\n- `\u003ckey\u003e`, `\u003ckey-ident\u003e` or `\u003ckey-param\u003e`\n- `\u003cvalue\u003e`, `\u003cvalue-ident\u003e` or `\u003cvalue-param\u003e`\n- `\u003cidentifier\u003e`\n\n`\u003ckey\u003e`, `\u003cvalue\u003e`:\n\nNative replacement for the Objects Key (or Index when using an Array) and replacement for the value of an Item.\n```javascript\nclass columns extends... {\n    ...\n    this.Types({\n        Object: {\n            eachItemOf: {\n                String: { syntax: this.Syntax('\u003ckey\u003e AS \u003cvalue\u003e') }\n            }\n        }\n    });\n    ...\n}\n\nlet myQuery = sql.$select({\n    $columns: {\n        my_key: 'my_string_value'\n    }\n})\n\n//SQL-Output\nSELECT\n    my_key AS my_string_value\n```\n\n\n`\u003ckey-ident\u003e`, `\u003cvalue-ident\u003e`:\n\nSafely quoted replacement for the Objects Key (or Index when using an Array - does not really make sense :-) ) and replacement for the value of an Item.\n```javascript\nclass columns extends... {\n    constructor(){\n        ...\n        this.Types({\n            Object: {\n                eachItemOf: {\n                    String: { syntax: this.Syntax('\u003ckey-ident\u003e AS \u003cvalue-ident\u003e') }\n                }\n            }\n        });\n        ...\n    }\n}\n\nlet myQuery = sql.$select({\n    $columns: {\n        my_key: 'my_string_value',\n        'my_schema.my_table.my_col': 'my_test_alias'\n    }\n})\n\n//SQL-Output for PostgreSQL\nSELECT\n    \"my_key\" AS \"my_string_value\",\n    \"my_schema\".\"my_table\".\"my_col\" AS \"my_test_alias\"\n\n//SQL-Output for MySQL\nSELECT\n    `my_key` AS `my_string_value`,\n    `my_schema`.`my_table`.`my_col` AS `my_test_alias`\n\n//SQL-Output for SQLServer\nSELECT\n    [my_key] AS [my_string_value],\n    [my_schema].[my_table].[my_col] AS [my_test_alias]\n```\n\n\n`\u003ckey-param\u003e`, `\u003cvalue-param\u003e`\n\nParameterized Key and Value replacement where the value itself is pushed to the value-stack.\n\n```javascript\nclass left extends... {\n    constructor(){\n        ...\n        this.Types({\n            Number: { syntax: this.Syntax('\u003ckey-ident\u003e AS \u003cvalue-param\u003e')\n        });\n        ...\n    }\n}\n\nlet myQuery = sql.$select({\n    $columns: {\n        first_name: { $left: 1 }\n    }\n})\n\n//SQL-Output for PostgreSQL\nSELECT\n    LEFT(\"first_name\", $1) AS \"first_name\"\n\n//SQL-Output for MySQL\nSELECT\n    LEFT(`first_name`, ?) AS `first_name`\n\n//SQL-Output for SQLServer\nSELECT\n    LEFT([first_name], @param1) AS [first_name]\n\n```\n\n## More Examples writing new stuff\n\n**For more informations browse through the `/sql/operator` or `/sql/helper` directories. There are a lot\nof Helpers and Operators and they all give you the best examples to write your own magic stuff.**\n\n# Tests\n\nAfter changing an existing Helper, Operator or maybe creating some new stuff you should run the Test.\nFor this use always:\n\n```sh\nnpm test\n```\n\nIf you like to Test only a specific language dialect or specific helper or operator you could pass arguments for that:\n\n```sh\nnpm test -- [ --language|dialect \u003cMySQL|MariaDB|PostgreSQL|SQLite|Oracle|SQLServer\u003e ] [ --helper|operator \u003cpath of helper located in ./sql\u003e ]\n\n# Test only the $left-helper for language-dialect MySQL\nnpm test -- --helper /helpers/functions/string/left/left.js --language MySQL\n```\n\n\n## Generating docs\n\nThe documentation will automatically rebuild with every successful Test run.\nPlease note that a successful Test will only be archived by running a complete Tests without a specific language, helper or operator.\n\n# License\n\nMIT License\n\nCopyright (c) 2017-2018 planetarydev\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplanetarydev%2Fjson-sql-builder2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplanetarydev%2Fjson-sql-builder2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplanetarydev%2Fjson-sql-builder2/lists"}