question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Indicate that a placeholder parameter is literal

See original GitHub issue
await dbPool.execute(
  `
    update notifications
    set seen_at = ?
    where id in(?)
  `,
  [
    Date.now(),
    notifications.reduce((accumulator, current) => {
      if (accumulator) accumulator += ',';
      accumulator += `"${current.id}"`;
      return accumulator;
    }, '')
  ]
);

The query does not seem to work and when I try to log the result of the query, it returned:

[
  ResultSetHeader {
    fieldCount: 0,
    affectedRows: 0,
    insertId: 0,
    info: 'Rows matched: 0  Changed: 0  Warnings: 0',
    serverStatus: 2,
    warningStatus: 0,
    changedRows: 0
  },
  undefined
]

BUT, this query works:

await dbPool.execute(
  `
    update notifications
    set seen_at = ?
    where id in(${notifications.reduce((accumulator, current) => {
      if (accumulator) accumulator += ',';
      accumulator += `"${current.id}"`;
      return accumulator;
    }, '')})
  `,
  [
    Date.now()
  ]
);

returning:

[
  ResultSetHeader {
    fieldCount: 0,
    affectedRows: 2,
    insertId: 0,
    info: 'Rows matched: 2  Changed: 2  Warnings: 0',
    serverStatus: 2,
    warningStatus: 0,
    changedRows: 2
  },
  undefined
]

Seems placeholder replacement does not work in this scenario.

Why it happens

I think the reason is because when the placeholder is being replaced, the result becomes:

update notifications
set seen_at = 1574563019209
where id in('"1", "2", "3", "4"')

Notice the single quotes in the IN function, which is not the outcome I am looking for. The correct approach is actually:

const placeholders = notifications.reduce((accumulator) => {
  if (accumulator) accumulator += ',';
  accumulator += '?';
  return accumulator;
}, '');

const result = await dbPool.execute(
  `
    update notifications
    set seen_at = ?
    where id in(${placeholders})
  `,
  [
    Date.now(),
    ...notifications.map(notification => notification.id)
  ]
);

which returns:

[
  ResultSetHeader {
    fieldCount: 0,
    affectedRows: 2,
    insertId: 0,
    info: 'Rows matched: 2  Changed: 2  Warnings: 0',
    serverStatus: 2,
    warningStatus: 0,
    changedRows: 2
  },
  undefined
]

But this is doing more work than it needs it, I just did 2 loops to get to the goal. Is there any way we can tell mysql2 that a parameter is literal where it will not do any parsing to the parameter?

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
sidorarescommented, Nov 25, 2019

Yes, this is top level api ( it basically calls sqlstring.format - https://github.com/mysqljs/sqlstring#escaping-query-values )

1reaction
sidorarescommented, Nov 24, 2019

in that case .query() is probably better. While .query() and .execute() look similar, the way they work is quite different. See some explanation in https://github.com/sidorares/node-mysql2/issues/196

We should probably be better in helping to notice this, I’ll need to check which type mysql prepare reports for “IN (?)”. Type conversion for execute parameters is based on “what PREPARE returned” vs “what you have in params array”. In your case you have single parameter on PREPARE side - IN (?) and array as parameter to pass, and it was sent as a string

Read more comments on GitHub >

github_iconTop Results From Across the Web

asp.net - How can the literal contents of a PlaceHolder be read?
I would have expected that the contents of the PlaceHolder would be be a single Literal control, but the Controls collection is empty....
Read more >
Template literals (Template strings) - JavaScript | MDN
Template literals are literals delimited with backtick ... The strings and placeholders get passed to a function — either a default function ...
Read more >
x/tools/gopls: no completion for function literal in parameter
If we change the placeholder option to only apply to function invocations, then this problem would go away.
Read more >
FactoryTalk View Literal string in Global Object [Text] - PLCS.net
parameter value that replaces the tag placeholder. The literal string you type (or specify in a parameter file) cannot contain spaces.
Read more >
Placeholder Syntax in Scala - GeeksforGeeks
However, each parameter must appear only one time within the function literal. Note: Internally, the underscore is expanded into a literal for a ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found