Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
sqliterally
Advanced tools
Composable and safe parameterized queries using tagged template literals
SQLiterally makes it easy to compose safe parameterized SQL queries using template literals. Clauses are automatically arranged which means you can re-use, subquery and append new clauses as you like – order doesn't matter. All queries are well formatted and ready to be passed directly to node-pg
and mysql
.
Use SQLiterally as a lightweight alternative to extensive query builders like Knex.js
or when big ORMs are over-kill.
OBS: SQLiterally provides a lot of freedom by design and it's not meant to reduce the SQL learning curve. It won't prevent you from writing incorrect queries.
node-pg
and mysql
This module exposes two module definitions:
dist/sqliterally.mjs
dist/sqliterally.js
npm install sqliterally --save
The module exposes two functions:
import {sql, query} from 'sqliterally';
let movie = 'Memento', year = 2001;
sql`SELECT director FROM movies WHERE title = ${movie}`;
// => {
// text: 'SELECT director FROM movies WHERE title = $1'
// sql => 'SELECT director FROM movies WHERE title = ?'
// values => ['Memento']
// }
let q = query
.select`director`
.select`year`
.from`movies`
.where`title = ${movie}`
.limit`5`;
if (year) q = q.where`year >= ${year}`;
if (writers) q = q.select`writers`;
q.build();
// => {
// text: `SELECT director, year FROM movies WHERE title = $1 AND year >= $2 LIMIT 5'
// sql => 'SELECT director, year FROM movies WHERE title = ? AND year >= ? LIMIT 5'
// values => ['Memento', 2001]
// }
Returns: Object
The string can contain nested SQLiterally query
and sql
objects.
Indexes and values are taken care of automatically.
You can pass this directly to node-pg
and mysql
.
let name = 'Harry Potter';
let max = 10, min = 0;
sub = sql`age > ${min} AND age < ${max}`;
sql`SELECT * FROM x WHERE name = ${name} OR (${sub}) LIMIT 2`;
// => {
// text: 'SELECT * FROM x WHERE name = $1 OR (age > $2 OR age < $3) LIMIT 2',
// sql: 'SELECT * FROM x WHERE name = ? OR (age > ? OR age < ?) LIMIT 2',
// values: ['Harry Potter', 0, 10]
// }
let script = sql`
CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.modified = now();
RETURN NEW;
END;
$$ language 'plpgsql';
`
// => { text: 'CREATE OR REPL...', sql: 'CREATE OR REPL...' values: [] }
Type: String
Getter that returns the parameterized string for Postgres.
Type: String
Getter that returns the parameterized string for MySQL.
Type: Array
Getter that returns the corresponding values in order.
Build a query by adding clauses. The order in which clauses are added doesn't matter. The final output is sorted and returned in the correct order no matter what order you call the methods in.
You can nest as many query
and sql
as you like. You don't have to build sub-queries before nesting them.
query
is immutable and all method calls return a new instance. This means you can build up a base query and re-use it. For example, with conditional where clauses or joins.
OBS: If you call a method multiple times, the values are concatenated in the same order you called them.
let age = 13, limit = 10, page = 1, paginate = false;
let sub = query
.select`id`
.from`customers`
.where`salary > 45000`;
let main = query
.select`*`
.from`customers`
.where`age > '${age}'`
.where`id IN (${sub})`;
main = paginate ? main.limit`${limit} OFFSET ${limit * page}` : main;
main.build();
Constructs the final query and returns a sql
query object ready for node-pg
and mysql
.
You can still append to the returned
sql
object or use it as a sub-query. You don't have to call.build()
when nesting queries – there's no reason to call build before you need the parameterized string and values.
Type: String
Default: \n
Change the delimiter used to combine clauses. The default is a line break.
Returns: query
All .select
calls get reduced and joined with ,
on .build()
.
query.select`*`.build()
// => SELECT *
query.select`cat`.select`zebra`.build()
// => SELECT cat, zebra
query.select`cat, dog`.select`zebra`.build()
// => SELECT cat, dog, zebra
query.select`something`.select`5 * 3 AS result`.build()
// => SELECT something, 5 * 3 AS result
Returns: query
Calling .update
more than once result in the clause being overwritten.
query.update`film`.build()
// => UPDATE film
query.update`film`.update`books`.build()
// => UPDATE books
Returns: query
All .set
calls get reduced and joined with ,
on .build()
.
query.set`a = b`.build()
// => SET a = b
query.set`a = b`.set`z = y`.build()
// => SET a = b, z = y
Returns: query
Calling .from
more than once result in the clause being overwritten.
query.from`film`.build()
// => FROM film
query.from`film AS f`.build()
// => FROM film AS f
query.from`film`.from`books`.build()
// => FROM books
Returns: query
query.join`c ON d`.build()
// => JOIN c ON d
query.join`a ON b.id`.join`c ON d`.build()
// => JOIN a ON b.id\nJOIN c ON d
query.leftJoin`c ON d`.build()
// => LEFT JOIN c ON d
query.leftJoin`a ON b.id`.leftJoin`c ON d`.build()
// => LEFT JOIN a ON b.id\nLEFT JOIN c ON d
Returns: query
All .where
calls get reduced and joined with AND
on .build()
.
query.where`a < b`.build()
// => WHERE a < b
query.where`a < b`.where`z = y`.build()
// => WHERE a < b AND z = y
query.where`a = z OR a = y`.build()
// => WHERE a = z OR a = y
Returns: query
All .orWhere
calls get reduced and joined with OR
on .build()
.
query.orWhere`a < b`.build()
// => WHERE a < b
query.orWhere`a < b`.orWhere`z = y`.build()
// => WHERE a < b OR z = y
Returns: query
All .having
calls get reduced and joined with AND
on .build()
.
query.having`MAX (list_price) > 4000`
// => HAVING MAX (list_price) > 4000
query.having`MAX (list_price) > 4000`.having`MIN (list_price) < 500`
// => HAVING MAX (list_price) > 4000 AND MIN (list_price) < 500'
Returns: query
All .orHaving
calls get reduced and joined with OR
on .build()
.
query.orHaving`MAX (list_price) > 4000`
// => HAVING MAX (list_price) > 4000
query.orHaving`MAX (list_price) > 4000`.orHaving`MIN (list_price) < 500`
// => HAVING MAX (list_price) > 4000 OR MIN (list_price) < 500'
Returns: query
All .groupBy
calls get reduced and joined with ,
on .build()
.
query.groupBy`a, b`.groupBy`c`.groupBy`d`.build()
// => GROUP BY a, b, c, d
Returns: query
All .orderBy
calls get reduced and joined with ,
on .build()
.
query.orderBy`a, b`.orderBy`COUNT(c) DESC`.orderBy`d`.build()
// => ORDER BY a, b, COUNT(c) DESC, d
Returns: query
Calling .limit
more than once result on the clause being overwritten.
query.limit`5`.build()
// => LIMIT 5
query.limit`5 OFFSET 2`.build()
// => LIMIT 5 OFFSET 2
query.limit`5`.limit`10`.build()
// => LIMIT 10
Returns: query
All .returning
calls get reduced and joined with ,
on .build()
.
query.returning`a, b`.returning`c`.returning`d`.build()
// => RETURNING a, b, c, d
Returns: query
Getter method. Multiple invocations get ignored.
query.lockInShareMode.build()
// => LOCK IN SHARE MODE
query.select`*`.from`x`.lockInShareMode.build()
// => SELECT * FROM x LOCK IN SHARE MODE
Returns: query
Getter method. Multiple invocations get ignored.
query.forUpdate.build()
// => FOR UPDATE
query.select`*`.from`x`.forUpdate.build()
// => SELECT * FROM x FOR UPDATE
query.select`*`.from`x`.lockInShareMode.forUpdate.build()
// => SELECT * FROM x LOCK IN SHARE MODE FOR UPDATE
This module is inspired by sql-concat but with a different implementation, support for Postgres, single queries and with a reduced API.
The sql
function and merge algorithm are based on prepare-sql.
MIT © Terkel Gjervig
FAQs
Lightweight SQL query builder
The npm package sqliterally receives a total of 29 weekly downloads. As such, sqliterally popularity was classified as not popular.
We found that sqliterally demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.