import { FragmentToken } from "../../tokens.js"; import { createSqlTag } from "../createSqlTag.js"; import test from "ava"; const sql = createSqlTag(); test("creates an unnest expression using primitive values (type name identifier)", (t) => { const query = sql.fragment`SELECT * FROM ${sql.unnest( [ [1, 2, 3], [4, 5, 6], ], ["int4", "int4", "int4"], )}`; t.deepEqual(query, { sql: 'SELECT * FROM unnest($slonik_1::"int4"[], $slonik_2::"int4"[], $slonik_3::"int4"[])', type: FragmentToken, values: [ [1, 4], [2, 5], [3, 6], ], }); }); test("creates an unnest expression using primitive values (sql token)", (t) => { const query = sql.fragment`SELECT * FROM ${sql.unnest( [ [1, 2, 3], [4, 5, 6], ], [sql.fragment`integer`, sql.fragment`integer`, sql.fragment`integer`], )}`; t.deepEqual(query, { sql: "SELECT * FROM unnest($slonik_1::integer[], $slonik_2::integer[], $slonik_3::integer[])", type: FragmentToken, values: [ [1, 4], [2, 5], [3, 6], ], }); }); test("treats type as sql.identifier", (t) => { const query = sql.fragment`SELECT bar, baz FROM ${sql.unnest( [ [1, 3], [2, 4], ], [ ["foo", "int4"], ["foo", "int4"], ], )} AS foo(bar, baz)`; t.deepEqual(query, { sql: 'SELECT bar, baz FROM unnest($slonik_1::"foo"."int4"[], $slonik_2::"foo"."int4"[]) AS foo(bar, baz)', type: FragmentToken, values: [ [1, 2], [3, 4], ], }); }); test("creates an unnest expression using arrays", (t) => { const query = sql.fragment`SELECT * FROM ${sql.unnest( [ [1, 2, 3], [4, 5, 6], ], ["int4", "int4", "int4"], )}`; t.deepEqual(query, { sql: 'SELECT * FROM unnest($slonik_1::"int4"[], $slonik_2::"int4"[], $slonik_3::"int4"[])', type: FragmentToken, values: [ [1, 4], [2, 5], [3, 6], ], }); }); test("creates incremental alias names if no alias names are provided", (t) => { const query = sql.fragment`SELECT * FROM ${sql.unnest( [ [1, 2, 3], [4, 5, 6], ], ["int4", "int4", "int4"], )}`; t.deepEqual(query, { sql: 'SELECT * FROM unnest($slonik_1::"int4"[], $slonik_2::"int4"[], $slonik_3::"int4"[])', type: FragmentToken, values: [ [1, 4], [2, 5], [3, 6], ], }); }); test("recognizes an array of arrays array", (t) => { const query = sql.fragment`SELECT * FROM ${sql.unnest([[[[1], [2], [3]]]], ["int4[]"])}`; t.deepEqual(query, { sql: 'SELECT * FROM unnest($slonik_1::"int4"[][])', type: FragmentToken, values: [[[[1], [2], [3]]]], }); }); test("throws if tuple member is not a primitive value expression", (t) => { const error = t.throws(() => { sql.fragment`SELECT * FROM ${sql.unnest( [ [() => {}, 2, 3], [4, 5], ], ["int4", "int4", "int4"], )}`; }); t.is(error?.message, "Invalid unnest tuple member type. Must be a primitive value expression."); }); test("throws if tuple member length varies in a list of tuples", (t) => { const error = t.throws(() => { sql.fragment`SELECT * FROM ${sql.unnest( [ [1, 2, 3], [4, 5], ], ["int4", "int4", "int4"], )}`; }); t.is(error?.message, "Each tuple in a list of tuples must have an equal number of members."); }); test("throws if tuple member length does not match column types length", (t) => { const error = t.throws(() => { sql.fragment`SELECT * FROM ${sql.unnest( [ [1, 2, 3], [4, 5, 6], ], ["int4", "int4"], )}`; }); t.is(error?.message, "Column types length must match tuple member length."); });