Table of contents
  1. sql - As Function
  2. sql - As String Template Literal
    1. String Literal
    2. String Interpolation
    3. Number Interpolation
    4. Array Interpolation
    5. Select Interpolation
    6. Compound Interpolation
    7. Composition
  3. Convert Raw String to Safe String
  4. Accessing string content
  5. Common used helpers
    1. Equals
    2. OR
  6. Extending
import {
    fromNothing,
    dsql as sql,
    unionAll,
    SafeString,
    castSafe,
    buildSerializer,
    buildSql,
} from "../../src";

sql - As Function

fromNothing({
    string: sql("abc"),
    number: sql(123),
    null: sql(null),
}).stringify();
SELECT
  'abc' AS `string`,
  123 AS `number`,
  NULL AS `null`

sql - As String Template Literal

String Literal

fromNothing({
    it: sql`system.tables`,
}).stringify();
SELECT
  system.tables AS `it`

String Interpolation

const name = "Lucas";
fromNothing({
    it: sql`'a' = ${name}`,
}).stringify();
SELECT
  'a' = 'Lucas' AS `it`

Number Interpolation

const n = 456;
fromNothing({
    it: sql`123 = ${n}`,
}).stringify();
SELECT
  123 = 456 AS `it`

Array Interpolation

const nums = [1, 2, 3];

fromNothing({
    it: sql`1 IN (${nums})`,
}).stringify();
SELECT
  1 IN (1, 2, 3) AS `it`

Select Interpolation

const q0 = fromNothing({
    it: sql`123 = 456`,
});
fromNothing({
    isIn: sql`something IN ${q0}`,
}).stringify();
SELECT
  something IN (
    SELECT
      123 = 456 AS `it`
  ) AS `isIn`

Compound Interpolation

const q1 = fromNothing({
    it: sql`123 = 456`,
});
const q2 = fromNothing({
    it: sql`1 > 0`,
});
const u = unionAll([q1, q2]);
fromNothing({
    isIn: sql`something IN ${u}`,
}).stringify();
SELECT
  something IN (
    SELECT
      123 = 456 AS `it`
    UNION ALL
    SELECT
      1 > 0 AS `it`
  ) AS `isIn`

Composition

const square = (it: SafeString): SafeString => sql`((${it}) * (${it}))`;

const four = square(sql(2));

fromNothing({
    four,
    it: square(square(square(sql`system.tables + ${four}`))),
}).stringify();
SELECT
  ((2) * (2)) AS `four`,
  (
    (
      (
        (
          (
            (system.tables + ((2) * (2))) * (system.tables + ((2) * (2)))
          )
        ) * (
          (
            (system.tables + ((2) * (2))) * (system.tables + ((2) * (2)))
          )
        )
      )
    ) * (
      (
        (
          (
            (system.tables + ((2) * (2))) * (system.tables + ((2) * (2)))
          )
        ) * (
          (
            (system.tables + ((2) * (2))) * (system.tables + ((2) * (2)))
          )
        )
      )
    )
  ) AS `it`

Convert Raw String to Safe String

const str = `aFunction(123)`;
const filter = castSafe(str);
fromNothing({ it: filter }).stringify();
SELECT
  aFunction(123) AS `it`
const str2 = `aFunction(123)`;
const filter2 = sql`${str2}`;
fromNothing({ it: filter2 }).stringify();
SELECT
  'aFunction(123)' AS `it`

Accessing string content

const b = "b";
const it = sql`a = ${b}`;
it.content;
a = 'b'

Common used helpers

Equals

const equals = (
    a: SafeString | number | string,
    b: SafeString | number | string
): SafeString => sql`${a} = ${b}`;

equals(1, 2);
{ "_tag": "SafeString", "content": "1 = 2" }

OR

const OR = (...cases: SafeString[]): SafeString => {
    const j = cases.map((it) => it.content).join(" OR ");
    return castSafe(`(${j})`);
};
OR(equals(1, 2), equals(3, 4), equals("a", "b"));
{ "_tag": "SafeString", "content": "(1 = 2 OR 3 = 4 OR 'a' = 'b')" }

Extending

const boolSerializer = buildSerializer({
    check: (it: unknown): it is boolean => typeof it == "boolean",
    serialize: (it: boolean): string => (it ? "1" : "0"),
});

const sql2 = buildSql([boolSerializer]);
sql2(true);
{ "_tag": "SafeString", "content": "1" }
sql2(false);
{ "_tag": "SafeString", "content": "0" }
sql2`${true} == ${false} == ${123} == ${"abc"}`;
{ "_tag": "SafeString", "content": "1 == 0 == 123 == 'abc'" }

This document used eval-md