Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for placeholder objects with toSqlValue functions. #44

Closed

Conversation

kfitzgerald
Copy link

Adds support for placeholder objects with toSqlValue functions.

Similar to how objects with toSqlString functions work, this function does not wrap the value with quotes. This is useful for parameterizing ridiculous numeric values or custom functions.

For example:

const MaxValue = {
  toSqlValue: () => '18446744073709551615'
}

const res = await db.query('SELECT * FROM `table` LIMIT ?, ?', [10, MaxValue]);

If there's a better way to implement this, please let me know!

Thanks,
-Kevin

 * Implemented `toSqlValue` function handler, similar to `toSqlString`, except the output is not wrapped in quotes. Useful for large integers or direct query control.
 * Updated docs
 * Updated tests
@rusher
Copy link
Collaborator

rusher commented Apr 16, 2019

Since there is already a method toSqlString that permit to returned value to be used as raw SQL, I don't see the point of having another method toSqlValue that will do exactly the same... or did I miss something?

@kfitzgerald
Copy link
Author

Hi @rusher !

Good question. The issue is that toSqlString implicitly wraps quotes around the string value. toSqlValue does not.

In lib/cmd/common-text-cmd.js:

        } else if (typeof value.toSqlString === "function") {
          out.writeStringEscapeQuote(String(value.toSqlString()));
        } else {

So attempting to do something like this:

const MaxValue = {
  toSqlString: () => '18446744073709551615'
}

const res = await db.query('SELECT * FROM `table` LIMIT ?, ?', [10, MaxValue]);

Fails with error:

UnhandledPromiseRejectionWarning: Error: (conn=71, no: 1064, SQLState: 42000) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''18446744073709551615'' at line 1
sql: SELECT * FROM `table` LIMIT ?, ? - parameters:[10,{}]

Presumably, because the translated statement would be:

SELECT * FROM `table` LIMIT 10, '18446744073709551615';

Which is an error.

So, purpose of toSqlValue is to avoid the implicitly-added quotes, making it useful for stupidly sized numbers or custom functions.

I could see a use case such as conditional value or function calls, like:

const Now = { toSqlValue: () => 'NOW()' };
db.query(`INSERT INTO table (id, created) VALUES (NULL, ?);`, [ givenDate || Now ]); 

Hope that helps!

Thanks,
-Kevin

@kfitzgerald
Copy link
Author

I suppose it's possible that toSqlString should not implicitly add quotes to the value... but that might break existing implementations of toSqlString.

Looking at lib/cmd/common-binary-cmd.js, I can't quite tell if that one adds implicit quotes like lib/cmd/common-text-cmd.js does. It looks like no, but that lovely UTF8 shenanigans could be misleading.

Thoughts?

@rusher
Copy link
Collaborator

rusher commented Apr 23, 2019

About handling very big number :
Using Long is now permitted as a parameter to handle very big number (more than 2^53-1 limitation). This will be in next release with this commit

But closing PR, since that kind of solution might lead to SQL injection.

@rusher rusher closed this Apr 23, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants