npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

knight-sql

v2.2.2

Published

A data structure to work with SQL

Downloads

6

Readme

Knight SQL by Coderitter

A data structure to create SQL queries. It mainly concatenates given strings which can be combined with objects that do magic while being rendered to strings.

Related packages

Use knight-orm if you are looking for a powerful solution to access a database.

Install

npm install knight-sql

Overview

INSERT, SELECT, UPDATE, DELETE (ISUD)

import sql from 'knight-sql'

sql.insertInto('table').value('name', 'Josa')
sql.select('*').from('table').where('id = 1')
sql.update('table').set('name', 'Sebastian').where('id = 1')
sql.deleteFrom('table').where('id = 1')

The parameter of insertInto, update and deleteFrom is just a string. You can input anything you like.

sql.update('ONLY table AS t')
// UPDATE ONLY table AS t

The parameter of select is a list of strings that will be concatenated with seperating commas. Here, you also can input anything you like.

sql.select('DISTINCT ON (a) a', 'b, c')
// SELECT DISTINCT ON (a) a, b, c

Render to SQL and get values array

import { parameter } from 'knight-sql'

let query = sql.select('*').from('table').where('id =', parameter(1))

// create MySQL string
query.mysql() == 'SELECT * FROM table WHERE id = ?'

// create PostgreSQL string
query.postgres() == 'SELECT * FROM table WHERE id = $1'

// get the values as an array
query.values() == [ 1 ]

FROM

// set a table
sql.select('*').from('table')

// add an alias
sql.select('*').from('table', 't')

// use an expression
sql.select('*').from('table t')
sql.select('*').from('table AS t')

JOIN

let query = sql.select('t1.id, t2.name').from('table1 t1').join('table2 t2', 't1.id = t2.table1Id')
let query = sql.select('t1.id, t2.name').from('table1 t1').join('table2', 't2', 't1.id = t2.table1Id')

query.sql() == 'SELECT t1.id, t2.name FROM table1 t1 JOIN table2 t2 ON t1.id = t2.table1Id'
let query = sql.select('t1.id, t2.name').from('table1 t1').join('left', 'table2 t2', 't1.id = t2.table1Id')
let query = sql.select('t1.id, t2.name').from('table1 t1').join('left', 'table2', 't2', 't1.id = t2.table1Id')

query.sql() == 'SELECT t1.id, t2.name FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.table1Id'

Condition

A condition is used for WHERE and HAVING clauses. It is basically an array which can contain value of any type. The following will happen.

  • Strings and numbers are concatenated into the resulting SQL string
  • An object of type Query will be surrounded with brackets to represent a sub query
  • There can be objects following the CustomSqlPiece interface which can to magic while rendering to SQL strings
  • A null value is becoming an SQL NULL
  • An array will be converted to (value1, value2, ...)
  • Any other values like of type Date will be replaced through a parameter token

Strings and numbers

A condition can be a list of strings or numbers that will be concatenated together.

sql.select('*').from('table').where('id', '=', '1')
sql.select('*').from('table').where('id =', '1')
sql.select('*').from('table').where('id', '= 1')
sql.select('*').from('table').where('id = 1')
sql.select('*').from('table').where('id', '=', 1)
sql.select('*').from('table').where('id =', 1)

// all of these definitions yield the same result

query.mysql() == 'SELECT * FROM table WHERE id = 1'
query.postgres() == 'SELECT * FROM table WHERE id = 1'

query.values() == []

Values

You can also denote that a value will be replaced through a parameter token.

sql.select('*').from('table').where('id =', parameter(1))

query.mysql() == 'SELECT * FROM table WHERE id = ?'
query.postgres() == 'SELECT * FROM table WHERE id = $1'

query.values() == [ 1 ]

Aliases

You can give aliases seperately and they will be concatenated to the next string without a space.

sql.select('*').from('table AS t').where('t.', 'id =', parameter(1))

query.mysql() == 'SELECT * FROM table AS t WHERE t.id = ?'
query.postgres() == 'SELECT * FROM table AS t WHERE t.id = $1'

query.values() == [ 1 ]

Custom SQL piece

An object of type CustomSqlPiece renders to SQL. It is used to do some magic while converting to an SQL string.

Here is a simple example for a new class implemented by you.

import sql, { ParameterToken, CustomSqlPiece } from 'knight-sql'

class MoreIntelligent extends CustomSqlPiece {

  iq: number

  constructor(iq: number) {
    super()
    this.iq = iq
  }

  // return the SQL string which can include parameters
  abstract sql(db: string, parameterToken: ParameterToken = new ParameterToken): string {
    return 'iq > ' + parameterToken.sql(db)
  }
  
  // return the values for parameters contained in the SQL string
  abstract values(): any[] {
    return [ this.iq ]
  }
}

The class ParameterToken creates a parameter token specific to the used database system. In the case of PostgreSQL it also keeps track of the last parameter index to create the parameter tokens like $1, $2 and $3.

Comparison

The class Comparison helps in creating simple comparisons which follow the pattern <column> <operator> <value>.

import { comparison } from `knight-sql`

let c1 = comparison('iq', 100)
c1.mysql() == 'iq = ?'
c1.values() == [ 100 ]

let c2 = comparison('iq', '>', 100)
c2.mysql() == 'iq > ?'
c2.values() == [ 100 ]

It will also help with IS NULL and IS NOT NULL.

let c1 = comparison('iq', null)
c1.mysql() == 'iq IS NULL'
c1.values() == []

let c2 = comparison('iq', '=', null)
c2.mysql() == 'iq IS NULL'
c2.values() == []

let c3 = comparison('iq', '!=', null)
c3.mysql() == 'iq IS NOT NULL'
c3.values() == []

let c4 = comparison('iq', '<>', null)
c4.mysql() == 'iq IS NOT NULL'
c4.values() == []

And it will help with the IN operator.

let c1 = comparison('iq', [ 100 ])
c1.mysql() == 'iq IN (?)'
c1.values() == [ 100 ]

let c2 = comparison('iq', '=', [ 100 ])
c2.mysql() == 'iq IN (?)'
c2.values() == [ 100 ]

let c3 = comparison('iq', '!=', [ 100 ])
c3.mysql() == 'iq NOT IN (?)'
c3.values() == []

let c4 = comparison('iq', '<>', [])
c4.mysql() == 'iq NOT IN (?)'
c4.values() == []

// in the case the array is empty, undefined or null,
// the value of the column is never inside the given set
let c5 = comparison('iq', '=', [])
c5.mysql() == '1 = 2'
c5.values() == []

// in the case the array is empty, undefined or null,
// the value of the column is never not inside the given set
let c5 = comparison('iq', '!=', [])
c5.mysql() == '1 = 1'
c5.values() == []

AND, OR, XOR

You can easily add logical operators.

sql.select('*').from('table').where('id > 10').and('id < 20')
sql.select('*').from('table').where('id > 10', 'AND', 'id < 20')
sql.select('*').from('table').where('id > 10 AND id < 20')

query.mysql() == 'SELECT * FROM table WHERE id > 10 AND id < 20'
query.postgres()) == 'SELECT * FROM table WHERE id > 10 AND id < 20'

query.values() == []

Another more complex example.

sql.select('*').from('table')
  .where('age >', value(10))
  .and('(')
  .where('name LIKE', value('%ert%'))
  .or('name LIKE ', value('%tre%'))
  .where(')')

query.mysql() == 'SELECT * FROM table WHERE age > ? AND (name LIKE ? OR name LIKE ?)'
query.postgres()) == 'SELECT * FROM table WHERE age > $1 AND (name LIKE $2 OR name LIKE $3)'

query.values() == [ 10, '%ert%', '%tre%' ]

Sub queries

sql.select('*').from('table')
  .where(
    'id =', 
    select('MAX(id)').from('table').where('age >', value(30)), 
    'AND name LIKE',
    value('%ert%')
  )

query.mysql() == 'SELECT * FROM table WHERE id = (SELECT MAX(id) FROM table WHERE age > ?) AND name LIKE ?'
query.postgres()) == 'SELECT * FROM table WHERE id = (SELECT MAX(id) FROM table WHERE age > $1) AND name LIKE $2'

query.values() == [ 30, '%ert%' ]

Arbitrary value

Arbitrary values like of type Date will be replaced by a parameter token and are put into the array of values.

let birthday = new Date(1982, 3, 28)
let query = sql.select('*').from('table').where('birthday =', birthday)

query.mysql() == 'SELECT * FROM table WHERE birthday = ?'
query.values() == [ birthday ]

GROUP BY

sql.select('*').from('table').groupBy('id', 'name, email')
// SELECT * FROM table GROUP BY id, name, email

The parameters for groupBy is just a list of strings that will be concatenated separated by a comma.

ORDER BY, LIMIT, OFFSET

sql.select('*').from('table').orderBy('id', 'name DESC', 'age, email ASC').limit(10).offset(100)
// SELECT * FROM table ORDER BY id, name DESC, age, email ASC LIMIT 10 OFFSET 100

The parameters for orderBy is just a list of strings that will be concatenated separated by a comma.

RETURNING (Postgres)

sql.select('*').from('table').returning('*')
// SELECT * FROM table RETURNING *