UNPKG

yesql

Version:

Read named SQL statements from .sql files. Also named parameters for prepared statements.

271 lines (223 loc) 7.95 kB
const yesql = require('./yesql.js') const assert = require('assert-diff') it('pg simple one parameter', () => { assert.deepEqual( yesql.pg('SELECT * from pokemon WHERE id = :id;')({id: 5}), { text: 'SELECT * from pokemon WHERE id = $1;', values: [5] }) }) it('pg type cast with multiple parameters', () => { const query = 'SELECT id::int FROM user WHERE id=:id and born > :year;' const data = {id: '5', year: 2000} const expected = { text: 'SELECT id::int FROM user WHERE id=$1 and born > $2;', values: ['5', 2000] }; assert.deepEqual(yesql.pg(query)(data), expected) }) it('pg bind variable with type cast', () => { const query = 'SELECT id::int FROM user WHERE id=:id::int and born > :year;' const data = {id: 1, year: 2000} const expected = { text: 'SELECT id::int FROM user WHERE id=$1::int and born > $2;', values: [1, 2000] }; assert.deepEqual(yesql.pg(query)(data), expected) }) it('pg bind array using ANY clause with type cast', () => { const query = 'SELECT id::int FROM user WHERE id=any(:idList::int[]) and born > :year;' const data = {idList: [1, 2, 3], year: 2000} const expected = { text: 'SELECT id::int FROM user WHERE id=any($1::int[]) and born > $2;', values: [[1, 2, 3], 2000] }; assert.deepEqual(yesql.pg(query)(data), expected) }) it('pg date format https://github.com/pihvi/yesql/issues/13', () => { const query = `select name, value, to_char(created_at, 'YYYY-MM-DD HH24:MI:SS') from table1 where created_at > :from and created_at <= :to;` const data = {from: new Date(0), to: new Date()} const expected = { text: `select name, value, to_char(created_at, 'YYYY-MM-DD HH24:MI:SS') from table1 where created_at > $1 and created_at <= $2;`, values: [data.from, data.to] }; assert.deepEqual(yesql.pg(query)(data), expected) }) it('mysql', () => { assert.deepEqual( yesql.mysql('SELECT * from ::ptable WHERE id = :id;')({id: 5, ptable: 'pokemon'}), { sql: 'SELECT * from ?? WHERE id = ?;', values: ['pokemon', 5] }) }) it('mysql from file', () => { const sql = yesql('./', {type: 'mysql'}) assert.deepEqual( sql.updatePokemon({price: 6}), { sql: '-- updatePokemon\nUPDATE pokemon SET price=?;', values: [6] }) }) it('pg from file', () => { const sql = yesql('./', {type: 'pg'}) assert.deepEqual( sql.updatePokemon({price: 6}), { text: 'UPDATE pokemon SET price=$1;', values: [6] }) }) it('raw from file', () => { const sql = yesql('./') assert.equal(sql.updatePokemon, '-- updatePokemon\nUPDATE pokemon SET price=:price;') assert.equal(sql.dual, ' --dual\nselect * from dual;\n') let boom = sql.comments assert.equal(sql.comments, '-- comments\nselect\n :foo ::INT,\n -- TODO do not hard code this eventually\n :bar ::INT,\n -- TODO I suppose we are ok now\n\n :bar::INT,\n\n /*\n now we are really asking for it\n */\n :foo ::INT') }) it('Missing parameter throws error', () => { ['pg', 'mysql'].forEach(type => { let msg = '' try { yesql.pg('select * from persons where name=:name;')({}) } catch (e) { msg = e.message } assert(msg.startsWith('Missing value for statement.\nname')) }) }) it('mysql with nulls for missing', () => { const query = 'SELECT * from pokemon WHERE id = :id and name=:name;' const options = {useNullForMissing: true} assert.deepEqual(yesql.mysql(query, options)({id: 5}), { sql: 'SELECT * from pokemon WHERE id = ? and name=?;', values: [5, null] }) assert.deepEqual(yesql('./', {type: 'mysql', useNullForMissing: true}).updatePokemon({}), { sql: '-- updatePokemon\nUPDATE pokemon SET price=?;', values: [null] }) assert.deepEqual(yesql('./', {type: 'mysql', useNullForMissing: true}).updatePokemon(), { sql: '-- updatePokemon\nUPDATE pokemon SET price=?;', values: [null] }) }) it('pg with nulls for missing', () => { const query = 'SELECT * from pokemon WHERE id = :id and name=:name;' const options = {useNullForMissing: true} assert.deepEqual(yesql.pg(query, options)({id: 5}), { text: 'SELECT * from pokemon WHERE id = $1 and name=$2;', values: [5, null] }) assert.deepEqual(yesql('./', {type: 'pg', useNullForMissing: true}).updatePokemon({}), { text: 'UPDATE pokemon SET price=$1;', values: [null] }) assert.deepEqual(yesql('./', {type: 'pg', useNullForMissing: true}).updatePokemon(), { text: 'UPDATE pokemon SET price=$1;', values: [null] }) }) it('pg with insert and close by placeholders', () => { const query = 'INSERT INTO pokemon (name, price) VALUES(:name,:price) RETURNING *'; const res = yesql.pg(query)({name: 'pikachu', price: 1337}) assert.deepEqual(res, { text: 'INSERT INTO pokemon (name, price) VALUES($1,$2) RETURNING *', values: ['pikachu', 1337] }) }) it('mysql with insert and close by placeholders', () => { const query = 'INSERT INTO pokemon (name, price) VALUES(:name,:price)'; const res = yesql.mysql(query)({name: 'pikachu', price: 1337}) assert.deepEqual(res, { sql: 'INSERT INTO pokemon (name, price) VALUES(?,?)', values: ['pikachu', 1337] }) }) it('PG type cast with spaces', () => { const query = "SELECT TO_CHAR(NOW() :: DATE, 'dd/mm/yyyy');"; const res = yesql.pg(query)() assert.deepEqual(res, { text: "SELECT TO_CHAR(NOW() :: DATE, 'dd/mm/yyyy');", values: [] }) }) it('PG to char date format', () => { const query = "select to_char(current_timestamp, 'Day, DD HH12:MI:SS')"; const res = yesql.pg(query)() assert.deepEqual(res, { text: "select to_char(current_timestamp, 'Day, DD HH12:MI:SS')", values: [] }) }) it('PG to char number format', () => { const query = `select to_char(:num, '"Pre:"999" Post:" .999');`; const res = yesql.pg(query)({num: 485.8}) assert.deepEqual(res, { text: `select to_char($1, '"Pre:"999" Post:" .999');`, values: [485.8] }) }) it('PG multiple quoted strings', () => { const query = `select to_char(:num, '"Pre:"999" :skipthis Post:" .999'), TO_CHAR(NOW() :: DATE, 'dd/mm/yyyy') from boom WHERE pow = :pow;`; const res = yesql.pg(query)({num: 485.8, pow: 'kaboom'}) assert.deepEqual(res, { text: `select to_char($1, '"Pre:"999" :skipthis Post:" .999'), TO_CHAR(NOW() :: DATE, 'dd/mm/yyyy') from boom WHERE pow = $2;`, values: [485.8, 'kaboom'] }) }) it('PG double quoted strings with colon', () => { const query = 'SELECT :userid::integer as "User:Id"'; const res = yesql.pg(query)({userid: 5}) assert.deepEqual(res, { text: `SELECT $1::integer as "User:Id"`, values: [5] }) }) it('PG comments with empty lines', () => { const query = ` select :foo ::INT[], /* now we are really asking for *it */ /** * Really asking **/ :foo ::INT[], -- TODO I suppose we are ok now :foo ::INT[]` const res = yesql.pg(query)({foo: 5}) const text = ` select $1 ::INT[], $2 ::INT[], $3 ::INT[]`.trim() assert.deepEqual(res, {text, values: [5, 5, 5]}) }) it('PG comments with tokens and quotes', () => { const query = ` select :foo ::INT[], :foo ::INT[], :foo ::INT[]` const res = yesql.pg(query)({foo: 5}) const text = ` select $1 ::INT[], $2 ::INT[], $3 ::INT[]`.trim() assert.deepEqual(res, {text, values: [5, 5, 5]}) }) it('PG statement returning string with escaped backslash', () => { const query = `select 'C:\\work' as "path\\to\\folder"` const res = yesql.pg(query)() const text = `select 'C:\\work' as "path\\to\\folder"` assert.deepEqual(res, {text, values: []}) }) it('MySQL quoted date string with time with colons', () => { const q = "SELECT * FROM tablename3 WHERE dt < '2023-06-27 03:06:53'" const { sql, values } = yesql.mysql(q)({}); })