Enhance interpolateParams to correctly handle placeholders
Enhance client side statement to correctly handle placeholders in queries with comments, strings, and backticks.
Add findParamPositions to identify real parameter positions Update and expand related tests.
"""
Walkthrough
A new state-machine-based function was introduced to accurately find parameter placeholders in SQL queries, ignoring those inside comments, strings, and backticks. The parameter interpolation logic was updated to use this function and refactored to handle argument escaping with a simplified flag. Corresponding tests were updated to verify correct handling of placeholders in various SQL contexts including comments and backticks.
Changes
| File(s) | Change Summary |
|---|---|
| connection.go | Rewrote interpolateParams with a state-machine parser to detect real parameter placeholders outside strings/comments/backticks; refactored argument escaping using a noBackslashEscapes flag. |
| connection_test.go | Removed test for placeholders inside string literals; added comprehensive test covering placeholders inside comments, strings, backticks, and complex cases with expected substitution or skip errors. |
| utils.go | Introduced backslashEscapeTable for escaping; split and updated escape functions to add surrounding quotes and support _binary prefix for binary literals; refactored escapeBytes functions to accept a binary flag. |
| utils_test.go | Extended tests for escape functions to cover new binary mode flag, verifying correct escaping with and without _binary prefix; updated calls to pass explicit binary flags. |
Sequence Diagram(s)
sequenceDiagram
participant Client
participant mysqlConn
Client->>mysqlConn: interpolateParams(query, args)
mysqlConn->>mysqlConn: parse query with state machine to find real placeholders
mysqlConn->>mysqlConn: interpolate arguments only at valid placeholders
mysqlConn-->>Client: return interpolated query or error
Possibly related PRs
- go-sql-driver/mysql#1595: Related to
interpolateParamsmethod; this PR rewrites the parsing logic while #1595 modifies error handling and cleanup calls within the same method.
Suggested reviewers
- methane """
[!WARNING]
Review ran into problems
🔥 Problems
Check-run timed out after 90 seconds. Some checks/pipelines were still in progress when the timeout was reached. Consider increasing the reviews.tools.github-checks.timeout_ms value in your CodeRabbit configuration to allow more time for checks to complete.
📜 Recent review details
Configuration used: CodeRabbit UI Review profile: CHILL Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between 919e7cac32be442ccd3223de93395abcecf842f4 and 66edfad9d2c331e4a463251262604d2b5642bb53.
📒 Files selected for processing (4)
-
connection.go(2 hunks) -
connection_test.go(1 hunks) -
utils.go(1 hunks) -
utils_test.go(3 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: shogo82148
PR: go-sql-driver/mysql#1576
File: CHANGELOG.md:1-6
Timestamp: 2024-07-26T20:55:56.049Z
Learning: PRs #1562 and #1570 in the go-sql-driver/mysql repository collectively address the same underlying issue related to fixing a race condition when a context is canceled, as documented in the CHANGELOG.md for version 1.8.1.
utils_test.go (2)
Learnt from: Gusted
PR: go-sql-driver/mysql#1518
File: auth_test.go:1356-1361
Timestamp: 2024-10-13T01:00:38.299Z
Learning: The user has indicated that hardcoding expected responses in tests is a consistent pattern in the `auth_test.go` file and is the preferred approach for this particular codebase.
Learnt from: Gusted
PR: go-sql-driver/mysql#1518
File: auth_test.go:1356-1361
Timestamp: 2024-07-26T20:55:56.049Z
Learning: The user has indicated that hardcoding expected responses in tests is a consistent pattern in the `auth_test.go` file and is the preferred approach for this particular codebase.
connection.go (3)
Learnt from: shogo82148
PR: go-sql-driver/mysql#1576
File: CHANGELOG.md:1-6
Timestamp: 2024-07-26T20:55:56.049Z
Learning: PRs #1562 and #1570 in the go-sql-driver/mysql repository collectively address the same underlying issue related to fixing a race condition when a context is canceled, as documented in the CHANGELOG.md for version 1.8.1.
Learnt from: Gusted
PR: go-sql-driver/mysql#1518
File: auth_test.go:1356-1361
Timestamp: 2024-07-26T20:55:56.049Z
Learning: The user has indicated that hardcoding expected responses in tests is a consistent pattern in the `auth_test.go` file and is the preferred approach for this particular codebase.
Learnt from: Gusted
PR: go-sql-driver/mysql#1518
File: auth_test.go:1356-1361
Timestamp: 2024-10-13T01:00:38.299Z
Learning: The user has indicated that hardcoding expected responses in tests is a consistent pattern in the `auth_test.go` file and is the preferred approach for this particular codebase.
utils.go (1)
Learnt from: shogo82148
PR: go-sql-driver/mysql#1576
File: CHANGELOG.md:1-6
Timestamp: 2024-07-26T20:55:56.049Z
Learning: PRs #1562 and #1570 in the go-sql-driver/mysql repository collectively address the same underlying issue related to fixing a race condition when a context is canceled, as documented in the CHANGELOG.md for version 1.8.1.
🧬 Code Graph Analysis (1)
connection_test.go (1)
dsn.go (1)
Config(37-84)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
- GitHub Check: test (ubuntu-latest, 1.22, 9.0)
- GitHub Check: test (windows-latest, 1.24, mariadb-10.6)
- GitHub Check: test (windows-latest, 1.24, mariadb-11.4)
- GitHub Check: test (macos-latest, 1.24, mariadb-11.1)
- GitHub Check: test (windows-latest, 1.24, 9.0)
- GitHub Check: test (macos-latest, 1.24, 8.0)
- GitHub Check: test (macos-latest, 1.24, mariadb-10.11)
- GitHub Check: test (macos-latest, 1.24, 5.7)
- GitHub Check: test (macos-latest, 1.24, 8.4)
- GitHub Check: test (ubuntu-latest, 1.24, mariadb-10.5)
- GitHub Check: test (ubuntu-latest, 1.24, mariadb-10.6)
- GitHub Check: test (ubuntu-latest, 1.24, mariadb-11.4)
- GitHub Check: test (ubuntu-latest, 1.24, mariadb-11.1)
- GitHub Check: test (ubuntu-latest, 1.24, mariadb-10.11)
- GitHub Check: test (ubuntu-latest, 1.24, 5.7)
- GitHub Check: test (ubuntu-latest, 1.24, mariadb-11.2)
- GitHub Check: test (ubuntu-latest, 1.24, 9.0)
- GitHub Check: test (ubuntu-latest, 1.24, 8.0)
- GitHub Check: test (ubuntu-latest, 1.24, 8.4)
- GitHub Check: Analyze (go)
🔇 Additional comments (14)
utils.go (5)
628-639: Excellent optimization using lookup table approach.The introduction of a global lookup table for backslash escapes is a smart performance optimization that replaces repetitive switch-case logic. The initialization in
init()ensures the table is populated once at startup.
641-661: Good separation of string vs byte slice handling.The new
escapeStringBackslashfunction provides a clean separation between string and byte slice escaping while maintaining consistent behavior. The addition of surrounding single quotes ensures proper SQL literal formatting.
664-688: Well-implemented binary flag support.The
binaryflag implementation correctly handles MySQL's_binaryprefix for binary literals. The buffer reservation calculation properly accounts for the additional_binaryprefix (7 chars + single quote = 8 total chars) when the flag is enabled.
691-715: Consistent implementation across quote escaping functions.The
escapeBytesQuotesfunction maintains consistency with the backslash variant in terms of binary flag handling and buffer management. The logic correctly doubles single quotes for SQL quote escaping.
717-737: Consistent string quote escaping with proper formatting.The
escapeStringQuotesfunction now consistently adds surrounding single quotes and uses the same quote-doubling logic as the byte slice variant, ensuring uniform behavior across all escaping functions.utils_test.go (2)
123-165: Comprehensive test coverage for binary flag functionality.The test updates properly maintain backward compatibility by explicitly passing
falsefor the binary flag in existing tests, while adding dedicated binary test cases with thebinExpecthelper. The expected outputs correctly show_binary'...'format for binary mode and regular'...'format for normal mode.
169-209: Well-structured binary mode testing for quote escaping.The quote escaping tests follow the same pattern as backslash tests, ensuring consistent test coverage. The binary mode tests correctly verify that only quote characters are affected (doubled) while other characters remain unchanged, with proper
_binaryprefixing.connection_test.go (1)
190-240: Excellent comprehensive test coverage for complex SQL parsing scenarios.The new test suite thoroughly validates the state machine parser's ability to correctly identify parameter placeholders in various contexts:
- Single-line comments (
--and#)- Multi-line comments (
/* */)- String literals with single quotes
- Backtick identifiers
- Escaped string literals with backslashes
The test cases also include edge cases where insufficient parameters should trigger
driver.ErrSkip, ensuring proper error handling. This comprehensive coverage is essential for validating the complex parsing logic introduced ininterpolateParams.connection.go (6)
175-175: Minor grammar correction.The comment has been improved from "successful authentication" to "successful authentication" for better clarity.
248-270: Well-designed state machine setup for SQL parsing.The state machine design with clearly defined states (
stateNormal,stateString,stateEscape, etc.) and named byte constants provides excellent readability and maintainability. The approach properly handles the complexity of SQL syntax parsing.
278-291: Correct escape sequence handling logic.The escape state logic correctly handles the case where an escaped character is not the matching quote character, properly transitioning back to string state. This ensures that escape sequences like
\n,\t, etc., don't incorrectly terminate string parsing.
292-411: Comprehensive state machine implementation for SQL parsing.The state machine correctly handles all major SQL syntax elements:
- Multi-line comments (
/* */)- Single-line comments (
--and#)- String literals with both single and double quotes
- Escape sequences within strings
- Backtick identifiers
- Parameter placeholders only in normal state
The logic properly tracks quote types and handles state transitions accurately. This ensures that placeholders inside comments, strings, or identifiers are not mistakenly replaced.
336-403: Robust parameter substitution with proper escaping.The parameter substitution logic correctly:
- Validates argument count before processing
- Handles
NULLvalues appropriately- Supports all expected data types (integers, floats, booleans, time, JSON, bytes, strings)
- Uses the appropriate escaping function based on
noBackslashEscapesflag- Applies binary flag correctly for byte slices
- Enforces packet size limits
The integration with the refactored escaping functions ensures consistent and secure parameter handling.
414-418: Proper completion and validation logic.The final steps correctly append the remaining query portion and validate that all arguments have been consumed, returning
driver.ErrSkipfor parameter count mismatches. This ensures robust error handling.
✨ Finishing Touches
- [ ] 📝 Generate Docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
🪧 Tips
Chat
There are 3 ways to chat with CodeRabbit:
- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
-
I pushed a fix in commit <commit_id>, please review it. -
Explain this complex logic. -
Open a follow-up GitHub issue for this discussion.
-
- Files and specific lines of code (under the "Files changed" tab): Tag
@coderabbitaiin a new review comment at the desired location with your query. Examples:-
@coderabbitai explain this code block. -
@coderabbitai modularize this function.
-
- PR comments: Tag
@coderabbitaiin a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:-
@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase. -
@coderabbitai read src/utils.ts and explain its main purpose. -
@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format. -
@coderabbitai help me debug CodeRabbit configuration file.
-
Support
Need help? Create a ticket on our support page for assistance with any issues or questions.
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.
CodeRabbit Commands (Invoked using PR comments)
-
@coderabbitai pauseto pause the reviews on a PR. -
@coderabbitai resumeto resume the paused reviews. -
@coderabbitai reviewto trigger an incremental review. This is useful when automatic reviews are disabled for the repository. -
@coderabbitai full reviewto do a full review from scratch and review all the files again. -
@coderabbitai summaryto regenerate the summary of the PR. -
@coderabbitai generate docstringsto generate docstrings for this PR. -
@coderabbitai generate sequence diagramto generate a sequence diagram of the changes in this PR. -
@coderabbitai resolveresolve all the CodeRabbit review comments. -
@coderabbitai configurationto show the current CodeRabbit configuration for the repository. -
@coderabbitai helpto get help.
Other keywords and placeholders
- Add
@coderabbitai ignoreanywhere in the PR description to prevent this PR from being reviewed. - Add
@coderabbitai summaryto generate the high-level summary at a specific location in the PR description. - Add
@coderabbitaianywhere in the PR title to generate the title automatically.
CodeRabbit Configuration File (.coderabbit.yaml)
- You can programmatically configure CodeRabbit by adding a
.coderabbit.yamlfile to the root of your repository. - Please see the configuration documentation for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation:
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
Documentation and Community
- Visit our Documentation for detailed information on how to use CodeRabbit.
- Join our Discord Community to get help, request features, and share feedback.
- Follow us on X/Twitter for updates and announcements.
coverage: 82.65% (+0.1%) from 82.508% when pulling 66edfad9d2c331e4a463251262604d2b5642bb53 on rusher:InterpolateParams into 76c00e35a8d48f8f70f0e7dffe584692bd3fa612 on go-sql-driver:master.
Please run BenchmarkInterpolation and write the results.
Is this algorithm identical to the MySQL or MariaDB? And are there examples of this algorithm implemented in other database drivers?
force push implementation with performance improvement.
current implementation :
Running tool: /usr/bin/go test -benchmem -run=^$ -bench ^BenchmarkInterpolation$ github.com/go-sql-driver/mysql
goos: linux
goarch: amd64
pkg: github.com/go-sql-driver/mysql
cpu: 11th Gen Intel(R) Core(TM) i9-11900K @ 3.50GHz
BenchmarkInterpolation-16 4036990 297.6 ns/op 176 B/op 1 allocs/op
initial proposal:
BenchmarkInterpolation-16 2726235 442.5 ns/op 296 B/op 5 allocs/op
new proposal:
BenchmarkInterpolation-16 4092514 295.5 ns/op 176 B/op 1 allocs/op
There is only one loop now, and escaping methods for parameters have been improved.
about other driver using that :
- MariaDB java driver
- MariaDB node.js driver
- MySQL Java driver
- ... (all driver does that one way or another, or it might result of a Poor Little Bobby Tables)
I hope this is included fast, since it's a security risk. proper client side statement must be handled well.
This is particulary dangerous when InterpolateParams and MultiStatements are enable :
for example, a query like select * /* ? */ from mytable where id = ? with parameter like ['*/ from mytable; delete * from mysql.user --/*', 1 ]
will result in deleting mysql.user table. SQL injection issue must be handle quickly
is there anything to do still to be merged ?
time. I don't intend to merge this in current series (v1.9) because it brings major behavior change.
I plan to release v1.9.4 next month, followed by creating a branch for v1.9 and beginning to incorporate changes for v1.10 into the master branch.