node-mysql2 icon indicating copy to clipboard operation
node-mysql2 copied to clipboard

Add taggedExecute helper

Open sidorares opened this issue 3 years ago • 6 comments

RFC at this stage, but I think the feature was mentioned / requested few times in the past and looks like a safe and useful addition

At this stage I intentionally adding this to "real" prepared statements only ( AKA .execute() ) and also to promise wrapper only. Also intentional is that fields part is not returned, no more const [rows] = await ... destructuring. If fields are needed always possible to use slightly lower level .execute()

partially inspired by https://github.com/google/zx

examples:

import mysql from 'mysql2/promise';
const pool = mysql.createPool({ user: 'root', password: 'test' });
const $ = pool.taggedExecute();
const input = 'test\" --';
const rows = await $`select ${input} as solution`;
import mysql from 'mysql2/promise';
const connection = await mysql.createConnection({ user: 'root', password: 'test' });
const $ = connection.taggedExecute();
const input = 'test\" --';
const rows = await $`select ${input} as solution`;
  • [x] base functionality
  • [ ] unit tests
  • [ ] documentation update
  • [x] collect feedback on API design

sidorares avatar Mar 22 '22 05:03 sidorares

Coverage report

The coverage rate is 89.13920056100982%

The branch rate is 84.98563218390804%

100% of new lines are covered.

github-actions[bot] avatar Mar 22 '22 05:03 github-actions[bot]

Something that I don't like but not sure how to handle well in a backwards compatible way.

With addition of tagged templates based PS there will be 4 ways of sending parametrised sql, which potentially makes everything very confusing:

// 1 - client side interpolation, PS-like but not "real" prepared statements:
const [rows1, columns1] = await connection.query('select ? as solution', ["parameter"]);

// 2 - real PS, prepare(sql) + execute(param) command the first time its called, execute(param) after
//  api aims to mimic (1) but due to limitations of prepared statements there are differences
const [rows2, columns2] = await connection.execute('select ? as solution', ["parameter"]);

// 3 - named placeholders. Same as (2) but a bit easier to read
const [rows3, columns3] = await connection.execute('select :parameter as solution', { parameter: "parameter"});

// 4 - tagged template
const rows = await sql`select ${"parameter"} as solution`;

Is having (3) and (4) too much? Given that (3) is relatively unknown, maybe we should deprecate it in favour of (4) ?

sidorares avatar Mar 24 '22 04:03 sidorares

might be a good idea to model api to match https://github.com/porsager/postgres#await-sql---result

not sure though if it belongs to base driver or independent wrapper library

sidorares avatar Mar 24 '22 21:03 sidorares

add to docs: this extension should provide syntax highlighting with no additional config - https://marketplace.visualstudio.com/items?itemName=frigus02.vscode-sql-tagged-template-literals

sidorares avatar Apr 14 '22 00:04 sidorares

I'm leaning towards not merging this and creating separate package instead

sidorares avatar Apr 14 '22 00:04 sidorares

Existing external modules as of Nov 2023:

  • https://github.com/nearform/sql
  • https://github.com/blakeembrey/sql-template-tag

sidorares avatar Nov 02 '23 00:11 sidorares