Enhancement: Support node-oracledb bind parameters
PhilippSalvisberg opened this issue · comments
Thanks for providing sql-template-tag. I very much like the idea of this module.
I tried to use it against an Oracle Database with node-oracledb bind parameters. It did not work since Oracle is using a colon to prefix its bind parameters. They also do not like the idea of supporting ?
for bind variables. (see oracle/node-oracledb#109).
Here's a small example:
import sql from "sql-template-tag";
const v1 = 'Value 1';
const v2 = 'Value 2';
const query = sql`select * from t1 where c1 = ${v1} and c2 = ${v2}`;
// query.sql = "select * from t1 where c1 = ? and c2 = ?"
// query.text = "select * from t1 where c1 = $1 and c2 = $2"
For oracledb we would need a result similar to this:
// query.oratext = "select * from t1 where c1 = :1 and c2 = :2"
Is targeting the Oracle Database an option for you? I can also provide a PR if you like.
Do you have any documentation on oratext
I should refer to? Otherwise I'd propose it being a "recipe" in the README like MSSQL, especially if it only accept (query, args)
style like I'm seeing here: https://node-oracledb.readthedocs.io/en/latest/user_guide/bind.html#bind-parameters-for-prepared-statements
Do you have any documentation on
oratext
I should refer to?
No. oratext
was just an idea of how to deal with the fact that oracledb does not support bind parameters ?
nor $<pos>
. It's similar to PostgreSQL but they use a :
instead of a $
. As a result you cannot use query.sql
nor query.text
.
Maybe I misunderstood something, but I currently do not see how you can deal with that by providing a "recipe" without replacing the $
by a :
before passing the statement to oracledb.
Postgres and MySQL are supported automatically due to the fact that they accept an object that has { text: '' }
or { sql: '' }
respectively. We could add oratext
but if there's no actual support for this in the oracledb library it might just be simpler to document how people can do this themselves. E.g.
function toQuery(sql) {
let i = 1,
value = sql.strings[0];
while (i < sql.strings.length) value += `:${i}${sql.strings[i++]}`;
return value;
}
.execute(toQuery(sql), sql.values)
It's not the most elegant, but it would work as a wrapper around the library.
Ok, I understand. The "recipe" is just a bit more extensive.
To simplify the usage the toQuery
function could be provided by the module. I can imagine that it could be reused for PostgreSQL with a second, optional parameter defaulting to :
to simplify the use for oracledb but allow the reuse for PostgreSQL internally by passing a $
.
This would make the "recipe" an oneliner, similar to MSSQL.
That sounds reasonable. Alternatively (after giving it some thought, sorry), if we can come up with a better name for oratext
, I think it's fine to add and then update the "recipes" with the one-liner. Some ideas for the name are: query
, rawText
, bindText
, rawSql
, rawText
, etc.
By better, I'm mostly just thinking that it'd be re-usable for anyone using the :
style binding.
Yes, naming is one of the difficult things in IT... Good thinking regarding :
being used in other DBs than Oracle.
I think raw...
is a bit misleading, it contains bind variables. query
sounds good, but using query.query
is strange. So based on the options you provided, I'd go with bindText
or bindSql
or just bind
or stmt
. I like the last one best (at the moment). Similar to sql
it covers all kinds of SQL statements. The resulting recipe would look like this:
session.execute(query.stmt, query.values);
I love statement
, I added a commit here using it: af8b4be. WDYT? Can you confirm it works with OracleDB before I release it? The docs imply it should work as-is.
Perfect. I've tested it successfully against an Oracle Database 23c Free instance. Thank you!
Awesome. Thank you for the confirmation. Just released as 5.2.