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

Problem using execute and array parameters #476

Closed
HugoMuller opened this issue Dec 1, 2016 · 3 comments
Closed

Problem using execute and array parameters #476

HugoMuller opened this issue Dec 1, 2016 · 3 comments
Labels

Comments

@HugoMuller
Copy link

HugoMuller commented Dec 1, 2016

Hi,

mysql2 is a good alternative to mysql, but there is a little bug I guess.

I try to prepare a statement with an array parameter, that should be turned into a list. It works with query but not with execute.

const ids = [1, 2, 3];
connection.query('SELECT id FROM mytable WHERE id IN (?)', [ids]);
// that's okay, I get 3 rows
[
  TextRow { id: 1 },
  TextRow { id: 2 },
  TextRow { id: 3 }
]

connection.execute('SELECT id FROM mytable WHERE id IN (?)', [ids]);
// I get only 1 row
[
  TextRow { id: 1 }
]

It seems that only the first element of the array is taken into account.

I'm using mysql2 v1.1.2.

@sidorares
Copy link
Owner

This is the way prepared statements work, I think we should document that better

.execute() under the hood is doing prepare + execute commands

query vs execute step by step:

query:

  • format sql on the client: 'SELECT id FROM mytable WHERE id IN (?)' + [ [1,2,3] ] becomes 'SELECT id FROM mytable WHERE id IN (1, 2, 3)'
  • send COM_QUERY command with 'SELECT id FROM mytable WHERE id IN (1, 2, 3)'
  • read fields + rows

execute:

  • send COM_PREPARE command with SELECT id FROM mytable WHERE id IN (?) as query parameter
  • read prepared statement result (id + parameters + result fields if known from query ). For this query there is one parameter ( one ? ). id is a number, usually starts with 1 for every connection ( not unique server-wise, you can't prepare statement in one connection and use in another )
  • send COM_EXECUTE command using statement id + parameters. Parameters must be simple mysql types, and currently all parameters coerced to strings and serialised as strings (with exception for Buffer parameters, they sent as is). In your example is "please execute stmt with id 1 and one parameter which is a string "1,2,3"

Result from prepare step above is cached, with next execute commands with same query only 'COM_EXECUTE' part is performed

I agree that this is confusing but this is how prepared statement work. We should improve this with better documentation and maybe some parameter validation warnings/errors like _"hey, are you sure you want to send your {foo: 'bar'} parameter to prepared statement? It'll be sent as [Object object]!''

I'll keep this issue open to track improvements in documentation - feel free to suggest your

@BorePlusPlus
Copy link

Late to the party as usual, but is the issue essentially that you'd have to prepare new statement every time someone used an array of a different size?

@sidorares
Copy link
Owner

@BorePlusPlus not exactly. Prepared statements api does not turn array parameters into list unlike non-prepared version. You can work around this by providing as much placeholders as you have elements in the array but this will result in new prepared statement created on the server

Leask added a commit to Leask/node-mysql2 that referenced this issue Jan 18, 2020
zappen999 added a commit to zappen999/mysql2-extended that referenced this issue Jun 8, 2022
mysql2 query() function will actually prepare the query before it's sent
to the DB server. That makes it possible to write queries like:

'select * from users where id in(?)' + [1, 2, 3]

More info:
sidorares/node-mysql2#476 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants