Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

safe-squel

hiddentao47.4k5.12.5TypeScript support: included

(safe version) SQL query string builder

sql, database, rdbms

readme

squel - SQL query string builder

Build Status CDNJS NPM module NPM downloads Join the chat at https://discord.gg/PBAR2Bz Follow on Twitter

A flexible and powerful SQL query string builder for Javascript.

Full documentation (guide and API) at https://hiddentao.com/squel/.

Features

  • Works in node.js and in the browser.
  • Supports the standard SQL queries: SELECT, UPDATE, INSERT and DELETE.
  • Supports non-standard commands for popular DB engines such as MySQL.
  • Supports paramterized queries for safe value escaping.
  • Can be customized to build any query or command of your choosing.
  • Uses method chaining for ease of use.
  • Small: ~7 KB minified and gzipped
  • And much more, see the guide..

WARNING: Do not ever pass queries generated on the client side to your web server for execution. Such a configuration would make it trivial for a casual attacker to execute arbitrary queries—as with an SQL-injection vector, but much easier to exploit and practically impossible to protect against.

Note: Squel is suitable for production use, but you may wish to consider more actively developed alternatives such as Knex

Installation

Install using npm:

$ npm install squel

Available files

  • squel.js - unminified version of Squel with the standard commands and all available non-standard commands added
  • squel.min.js - minified version of squel.js
  • squel-basic.js - unminified version of Squel with only the standard SQL commands
  • squel-basic.min.js - minified version of squel-basic.js

Examples

Before running the examples ensure you have squel installed and enabled at the top of your script:

var squel = require("squel");

SELECT

// SELECT * FROM table
squel.select()
    .from("table")
    .toString()

// SELECT t1.id, t2.name FROM table `t1` LEFT JOIN table2 `t2` ON (t1.id = t2.id) WHERE (t2.name <> 'Mark') AND (t2.name <> 'John') GROUP BY t1.id
squel.select()
    .from("table", "t1")
    .field("t1.id")
    .field("t2.name")
    .left_join("table2", "t2", "t1.id = t2.id")
    .group("t1.id")
    .where("t2.name <> 'Mark'")
    .where("t2.name <> 'John'")
    .toString()

// SELECT `t1`.`id`, `t1`.`name` as "My name", `t1`.`started` as "Date" FROM table `t1` WHERE age IN (RANGE(1, 1.2)) ORDER BY id ASC LIMIT 20
squel.select({ autoQuoteFieldNames: true })
    .from("table", "t1")
    .field("t1.id")
    .field("t1.name", "My name")
    .field("t1.started", "Date")
    .where("age IN ?", squel.str('RANGE(?, ?)', 1, 1.2))
    .order("id")
    .limit(20)
    .toString()

You can build parameterized queries:

/*
{
    text: "SELECT `t1`.`id`, `t1`.`name` as "My name", `t1`.`started` as "Date" FROM table `t1` WHERE age IN (RANGE(?, ?)) ORDER BY id ASC LIMIT 20",
    values: [1, 1.2]
}
*/
squel.select({ autoQuoteFieldNames: true })
    .from("table", "t1")
    .field("t1.id")
    .field("t1.name", "My name")
    .field("t1.started", "Date")
    .where("age IN ?", squel.str('RANGE(?, ?)', 1, 1.2))
    .order("id")
    .limit(20)
    .toParam()

You can use nested queries:

// SELECT s.id FROM (SELECT * FROM students) `s` INNER JOIN (SELECT id FROM marks) `m` ON (m.id = s.id)
squel.select()
    .from( squel.select().from('students'), 's' )
    .field('id')
    .join( squel.select().from('marks').field('id'), 'm', 'm.id = s.id' )
    .toString()

UPDATE

// UPDATE test SET f1 = 1
squel.update()
    .table("test")
    .set("f1", 1)
    .toString()

// UPDATE test, test2, test3 AS `a` SET test.id = 1, test2.val = 1.2, a.name = "Ram", a.email = NULL, a.count = a.count + 1
squel.update()
    .table("test")
    .set("test.id", 1)
    .table("test2")
    .set("test2.val", 1.2)
    .table("test3","a")
    .setFields({
        "a.name": "Ram",
        "a.email": null,
        "a.count = a.count + 1": undefined
    })
    .toString()

INSERT

// INSERT INTO test (f1) VALUES (1)
squel.insert()
    .into("test")
    .set("f1", 1)
    .toString()

// INSERT INTO test (name, age) VALUES ('Thomas', 29), ('Jane', 31)
squel.insert()
    .into("test")
    .setFieldsRows([
        { name: "Thomas", age: 29 },
        { name: "Jane", age: 31 }    
    ])
    .toString()

DELETE

// DELETE FROM test
squel.delete()
    .from("test")
    .toString()

// DELETE FROM table1 WHERE (table1.id = 2) ORDER BY id DESC LIMIT 2
squel.delete()
    .from("table1")
    .where("table1.id = ?", 2)
    .order("id", false)
    .limit(2)

Paramterized queries

Use the useParam() method to obtain a parameterized query with a separate list of formatted parameter values:

// { text: "INSERT INTO test (f1, f2, f3, f4, f5) VALUES (?, ?, ?, ?, ?)", values: [1, 1.2, "TRUE", "blah", "NULL"] }
squel.insert()
    .into("test")
    .set("f1", 1)
    .set("f2", 1.2)
    .set("f3", true)
    .set("f4", "blah")
    .set("f5", null)
    .toParam()

Expression builder

There is also an expression builder which allows you to build complex expressions for WHERE and ON clauses:

// test = 3 OR test = 4
squel.expr()
    .or("test = 3")
    .or("test = 4")
    .toString()

// test = 3 AND (inner = 1 OR inner = 2) OR (inner = 3 AND inner = 4 OR (inner IN ('str1, 'str2', NULL)))
squel.expr()
    .and("test = 3")
    .and(
        squel.expr()
            .or("inner = 1")
            .or("inner = 2")
    )
    .or(
        squel.expr()
            .and("inner = ?", 3)
            .and("inner = ?", 4)
            .or(
                squel.expr()
                    .and("inner IN ?", ['str1', 'str2', null])
            )
    )
    .toString()

// SELECT * FROM test INNER JOIN test2 ON (test.id = test2.id) WHERE (test = 3 OR test = 4)
squel.select()
    .join( "test2", null, squel.expr().and("test.id = test2.id") )
    .where( squel.expr().or("test = 3").or("test = 4") )

Custom value types

By default Squel does not support the use of object instances as field values. Instead it lets you tell it how you want specific object types to be handled:

// handler for objects of type Date
squel.registerValueHandler(Date, function(date) {
  return date.getFullYear() + '/' + (date.getMonth() + 1) + '/' + date.getDate();
});

squel.update().
  .table('students')
  .set('start_date', new Date(2013, 5, 1))
  .toString()

// UPDATE students SET start_date = '2013/6/1'

Note that custom value handlers can be overridden on a per-instance basis (see the docs)

Custom queries

Squel allows you to override the built-in query builders with your own as well as create your own types of queries:

// ------------------------------------------------------
// Setup the PRAGMA query builder
// ------------------------------------------------------
var util = require('util');   // to use util.inherits() from node.js

var CommandBlock = function() {};
util.inherits(CommandBlock, squel.cls.Block);

// private method - will not get exposed within the query builder
CommandBlock.prototype._command = function(_command) {
  this._command = _command;
}

// public method - will get exposed within the query builder
CommandBlock.prototype.compress = function() {
  this._command('compress');
};

CommandBlock.prototype.buildStr = function() {
  return this._command.toUpperCase();
};


// generic parameter block
var ParamBlock = function() {};
util.inherits(ParamBlock, squel.cls.Block);

ParamBlock.prototype.param = function(p) {
  this._p = p;
};

ParamBlock.prototype.buildStr = function() {
  return this._p;
};


// pragma query builder
var PragmaQuery = function(options) {
  squel.cls.QueryBuilder.call(this, options, [
      new squel.cls.StringBlock(options, 'PRAGMA'),
      new CommandBlock(),
      new ParamBlock()
  ]);
};
util.inherits(PragmaQuery, squel.cls.QueryBuilder);


// convenience method (we can override built-in squel methods this way too)
squel.pragma = function(options) {
  return new PragmaQuery(options)
};


// ------------------------------------------------------
// Build a PRAGMA query
// ------------------------------------------------------

squel.pragma()
  .compress()
  .param('test')
  .toString();

// 'PRAGMA COMPRESS test'

Examples of custom queries in the wild:

Non-standard SQL

Squel supports the standard SQL commands and reserved words. However a number of database engines provide their own non-standard commands. To make things easy Squel allows for different 'flavours' of SQL to be loaded and used.

At the moment Squel provides mysql, mssql and postgres flavours which augment query builders with additional commands (e.g. INSERT ... RETURNING for use with Postgres).

To use this in node.js:

var squel = require('squel').useFlavour('postgres');

For the browser:

<script type="text/javascript" src="https://rawgithub.com/hiddentao/squel/master/squel.min.js"></script>
<script type="text/javascript">
  squel = squel.useFlavour('postgres');
</script>

(Internally the flavour setup method simply utilizes the custom query mechanism to effect changes).

Read the the API docs to find out available commands. Flavours of SQL which get added to Squel in the future will be usable in the above manner.

Building it

To build the code and run the tests:

$ npm install
$ npm test <-- this will build the code and run the tests

Releasing it

Instructions for creating a new release of squel are in RELEASE.md.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md.

Older verions

Note: The latest Squel version only works on Node 0.12 or above. Please use Squel 4.4.1 for Node <0.12. The old 4.x docs are also still available.

Ports to other languages

License

MIT - see LICENSE.md

changelog

Changelog for squel

9 Jul 2018 (5.12.2)

  • Fix Node.js CVE (update growl dev dependency)

17 Jul 2017 (5.11.1)

  • 322 - Tyepscript definitions

  • 321 - Allow LIMIT and OFFSET with 0

  • 320 - Ensure string formatter doesn't get lost in cloning

17 May 2017 (5.10.0)

  • 317 - Postgres ON CONFLICT improvements, thanks alexturek

21 Apr 2017 (5.9.1)

  • Performance improvements (#309, #310) - thanks schmod

13 Apr 2017 (5.9.0)

  • Enable custom value handlers to return values that do not get automatically nested - #292

28 Feb 2017 (5.8.0)

  • 301 - Add rstr() to enable "raw" nesting of query builders

  • Renamed _isSquelBuilder() call to isSquelBuilder()

6 Feb 2017 (5.7.0)

  • 288 - more flexible RETURNING clauses

7 Jan 2017 (5.6.0)

  • 256 - expression nesting

24 Dec 2016 (5.5.1)

  • 255, #283 - mixing flavours

15 Oct 2016 (5.5.0)

  • 118 - pass extra formatting options (when available) to custom value handler

  • 273 - parameterized LIMIT and OFFSET queries

15 Sep 2016 (5.4.3)

  • 266 - Postgres ON CONFLICT support

27 Aug 2016 (5.4.2)

  • A better check for detecting when custom value formatting has been applied.
  • Allow for any builder to passed in as an expression

26 Aug 2016 (5.3.4)

  • 261 - passing a string for order clause

12 Jul 2016 (5.3.3)

  • 249 - Postgres DISTINCT ON clause

13 Jun 2016 (5.3.2)

  • 234 - Fix handling of expression field names

5 Jun 2016 (5.3.1)

  • 158, #239 - Support for CTE queries (WITH clause)

  • 242 - Fix auto-quoting table names

  • Removed bower.json

18 May 2016 (5.2.1)

  • Re-fix for #109 - custom string formatting wasn't quite working

18 May 2016 (5.2.0)

  • Fix for #109 - custom string formatting function enabled
  • Fix for #235 - fix a regression

14 May 2016 (5.1.0)

  • Fix for #231 - try not to add extra brackets
  • Fix for #233 - ability to specify target table in DELETE queries

17 Apr 2016 (5.0.4)

  • Fix for #227 - MSSQL insert without fields fails

13 Apr 2016 (5.0.3)

  • Fix for #225 - auto-quote field names had stopped working

11 Apr 2016 (5.0.2)

  • Fix for #226 - empty expressions in where clause

6 Apr 2016 (5.0.1)

  • Fix for #223 - array looping should not use for-in

29 Mar 2016 (5.0.0)

  • Complete architectural rewrite - see #201

23 Mar 2016 (4.4.2)

  • Fix for #220 and #221 and other similar issues

20 Mar 2016 (4.4.1)

  • Fixed for #219

19 Mar 2016 (4.4.0)

  • Ported coffeescript to ES6

29 Feb 2016 (4.3.3)

  • Fix for #216

24 Feb 2016 (4.3.2)

  • Fix for #210

18 Feb 2016 (4.3.1)

  • 208 - Rework expressions to allow for easier cloning.

18 Feb 2016 (4.3.0)

  • 207 - Added CASE clauses and useAsForTableAliasNames option.

17 Feb 2016 (4.2.4)

  • 199 - Added FROM to UPDATE for postgres flavour

20 Jan 2016 (4.2.3)

  • Placeholder parameter character is now configurable
  • Guide docs now print results below code
  • Re-instituted CHANGELOG.md
  • Can now get current flavour of Squel using flavour prop

13 Nov 2015 (4.2.2)

  • Merged #191

30 Aug 2014 (3.8.1)

  • 90 - custom value handlers with primitives

  • 87 - OrderBlock not compatible by values

11 Aug 2014 (3.7.0)

  • 76 - MSSQL flavour

  • 85 - Using expressions in .where() followed by .toParam()

30 July 2014 (3.6.1)

  • Better fix for #82
  • Treat * as a special case when auto-quoting field names
  • Fix for #84

19 July 2014 (3.5.0)

  • 82 - ON DUPLIATE KEY UPDATE enchancements

  • 25, #72, #73 - parameter substitution in expressions

  • 79 - smarter automatic fieldname quoting

  • 75 - disable automatic string quoting on a per-field basis

  • 55 - specify sub-query as a field

  • 80, #81 - Bugfixes

17 May 2014 (3.4.1)

  • 62 - can specify query separator string

15 May 2014 (3.3.0)

  • Shifted replaceSingleQuotes and related option into Squel core.

9 May 2014 (3.2.0)

  • Added DELETE..RETURNING for Postgres (#60)
  • Auto-generate version string (#61)
  • Don't commit docs/ folder anymore. Also don't auto-build docs as part of build.

21 Mar 2014 (3.1.1)

  • Don't format parameter values returned from the toParam() call, unless their custom value types (#54)

20 Mar 2014 (3.0.1)

  • Added setFields and setFieldRows to make setting multple fields and inserting multiple rows easier (#50)
  • Removed usingValuePlaceholders option that was deprecated in 2.0.0

16 Dec 2013 (2.0.0)

  • Added RETURNING clause to UPDATE queries for Postgres flavour (#42)
  • Added better support for parameterized queries (#34)
  • Added squel.VERSION constant

7 Oct 2013 (1.2.1)

  • Added ON DUPLICATE KEY UPDATE clause for MySQL flavour (#36)
  • Added single quote replacement option for Postgres flavour (#35)

2 Oct 2013 (1.2)

  • Switched from Make to Grunt
  • Added fields() method to SELECT builder (#29)
  • Expression trees can now be cloned (#31)
  • Added concept of SQL 'flavours' and merged in the Postgres RETURNING command #33

10 Jun 2013 (1.1.3)

  • Table names in SELECT queries can now be queries themselves (i.e. SQL sub statements)

2 Jun 2013 (1.1.2)

  • Parameterised WHERE clauses now supported.
  • Custom value types can now be handled in a special way. Global and per-instance handlers supported.

27 Mar 2013 (1.1)

  • Squel can now be customized to include proprietary commands and queries.
  • AMD support added.

4 Jan 2013 (1.0.6)

  • Squel can now be told to auto-quote table and field names.

3 Nov 2012 (1.0.5)

  • DELETE queries can now contain JOINs
  • Query builder instances can be clone()'d
  • Cleaner and more thorough tests (and replaced Vows with Mocha, Sinon and Chai)
  • Fixed documentation errors

17 Aug 2012 (1.0.4)

  • QueryBuilder base class for all query builders
  • Exporting query builders
  • Escaping strings with single quotes for PostgreSQL compatibility
  • Migrating to make

27 Jan 2012 (1.0.3)

  • Added 'usingValuePlaceholders' option for INSERT and UPDATE query builders.

20 Dec 2011 (1.0.0)

  • Initial version.