fix: substitute placeholders near non-comment -- and executable comments#31
fix: substitute placeholders near non-comment -- and executable comments#31spokodev wants to merge 2 commits into
-- and executable comments#31Conversation
…ments
`skipSqlContext` treated every `--` as a line comment and every `/* */` as a
regular comment, so placeholders were dropped or shifted in two cases MySQL
parses differently:
- `--` only starts a comment when followed by whitespace/control/EOF, so
`format("SELECT 1--2, ?", ["VAL"])` returned `"SELECT 1--2, ?"` (placeholder
dropped) instead of `"SELECT 1--2, 'VAL'"`.
- `/*! ... */` and `/*+ ... */` are executable comments / optimizer hints that
MySQL evaluates, so a `?` inside them is a live placeholder. `format("SELECT
/*!40101 ? */ , ?", ["A", "B"])` returned `"SELECT /*!40101 ? */ , 'A'"` (value
shifted to the wrong slot) instead of `"SELECT /*!40101 'A' */ , 'B'"`.
Require a whitespace/control/EOF suffix before skipping `--`, and exclude
`/*!`/`/*+` from the block-comment skip. Regular `--` and `/* */` comments are
still skipped, matching the comment-aware behavior added in mysqljs#22.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #31 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 1 1
Lines 401 410 +9
=========================================
+ Hits 401 410 +9 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| // MySQL starts a `--` comment only when the dashes are followed by a | ||
| // whitespace/control character (or end of input); `1--2` is an operator | ||
| // sequence, not a comment, so it must not swallow following placeholders. | ||
| const afterDash = sql.charCodeAt(position + 2); |
There was a problem hiding this comment.
Thanks, @spokodev! I believe we can remove 100% of the need for any comments in the entire implementation, since the logic and variable names are already clear for long-term maintenance 🙋🏻♂️
| }); | ||
|
|
||
| test('double dash without trailing whitespace is not a comment', () => { | ||
| // MySQL only treats `--` as a comment when followed by whitespace/control; |
There was a problem hiding this comment.
The same idea applies to tests, where instead of loose comments, we can use test, describe, it, and the assertions themselves to maintain clarity of what is being tested.
The variable names and test descriptions already convey intent, so the inline comments in the implementation and tests are redundant. Logic and assertions are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Done, dropped the comments in both the implementation and the tests. Logic and assertions are unchanged, suite stays green. |
Bug
format()drops or shifts?placeholders in two cases that MySQL parses differently from howskipSqlContexttreats them:sqlstringreturns the expected results for both. This is a correctness / data-integrity issue, not a quoting/injection one: the values stay quoted, but they land in the wrong slot or get silently dropped.Why MySQL parses these as live placeholders
Per the MySQL reference manual, §9.7 Comments:
--begins a comment only when the two dashes are followed by a whitespace (or control) character, or end of input. So1--2is not a comment — it is1minus-2./*! ... */is an executable comment: MySQL runs the code inside it (used for version-gated SQL)./*+ ... */is an optimizer hint, also evaluated. A?inside either is a real placeholder.Root cause
skipSqlContext(src/index.ts) detects:--with no whitespace-suffix check, so it skips from1--2to end of line and swallows the trailing placeholder./* */without excluding/*!and/*+, so it skips over placeholders inside executable comments / optimizer hints.This comes from the comment-aware skipping layer added in #22 (which correctly fixed
--and/* */sequences inside backtick identifiers). This PR narrows that skip to actual comments.Fix
--branch: only treat as a comment when the character after the two dashes is whitespace/control or end of input; otherwise it is an operator sequence and is not skipped./* */branch: return early (do not skip) when the marker is/*!or/*+, so the placeholder inside is substituted normally.Regular
--(with trailing whitespace) and regular/* */comments are still skipped, so the behavior from #22 is preserved.Tests
Added three cases to
test/delimiters.test.tsunderQuery comments for debugging. They fail onmainand pass with the fix; the full suite stays green across the 9 test files.SELECT 1--2, ?SELECT 1--2, ?SELECT 1--2, 'VAL'SELECT /*!40101 ? */ , ?SELECT /*!40101 ? */ , 'A'SELECT /*!40101 'A' */ , 'B'SELECT /*+ MAX_EXECUTION_TIME(?) */ id FROM tSELECT /*+ MAX_EXECUTION_TIME(1000) */ id FROM t