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

コメントを付与したSQLが実行されない問題の修正 #33

Merged
merged 10 commits into from
Dec 18, 2024

Conversation

KazuyaUchida
Copy link
Contributor

@KazuyaUchida KazuyaUchida commented Dec 17, 2024

#25 で追加されたオプションでSQL名を付与した場合と以下の様にSQLの先頭にコメントを挿入した場合に
RowListInterfaceではSQLが実行されない問題を修正

sample sql

/* todo_item_by_id_with_comment.sql */
SELECT
    *
FROM
    todo
WHERE
    id = :id 

Summary by CodeRabbit

  • New Features

    • Enhanced SQL query processing by removing comments and improving query validation.
    • Introduced new SQL files for selecting todo items by ID, including comments for clarity.
  • Tests

    • Added multiple new test methods to validate the functionality of SQL queries with comments, ensuring expected results.
    • Refactored existing test methods for improved clarity and organization.

Copy link
Contributor

coderabbitai bot commented Dec 17, 2024

Warning

Rate limit exceeded

@koriym has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 2 minutes and 33 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between bfe5106 and 20a90ae.

📒 Files selected for processing (2)
  • src/QueryInterceptor.php (2 hunks)
  • src/SqlQueryRowList.php (3 hunks)

Walkthrough

The pull request modifies the SqlQueryRowList class to enhance SQL query string processing by introducing the preg_replace function for comment removal and refining the method for detecting 'select' statements. Additionally, new SQL files are created to test query execution with various comment styles. The SqlQueryTest class is updated with new test methods to validate the handling of these comments in SQL queries, ensuring the logic processes them correctly. Furthermore, the QueryInterceptor class improves type safety and documentation for its methods.

Changes

File Change Summary
src/SqlQueryRowList.php Updated query processing logic to use preg_replace for comment removal and changed condition for 'select' statement detection to a strict comparison.
tests/Fake/sql/todo_item_by_id_with_comment.sql New SQL file added with a commented query to select todo item by ID.
tests/Fake/sql/todo_item_by_id_with_line_comment.sql New SQL file added with a line-commented query to select todo item by ID.
tests/Fake/sql/todo_item_by_id_with_multiple_comment.sql New SQL file added with a commented query to select todo item by ID.
tests/SqlQueryTest.php Added testWithComment(), testWithLineComment(), and testWithMultipleComment() methods to test SQL query execution with comments; refactored testInvoke to call testSql().
src/QueryInterceptor.php Enhanced type safety and documentation for getQueryResult and returnRo methods.

Poem

🐰 A Rabbit's Ode to SQL Refinement 🐰

Comments dance, then swiftly fade away,
Queries trimmed with precision's gentle sway,
str_starts_with leaps where strpos once did crawl,
Clean code emerges, standing proud and tall!

Hop, hop, hooray! 🥕


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in 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 generate unit testing code.
    • @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.

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 pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file 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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/SqlQueryRowList.php (1)

61-61: Consider whitespace handling in SELECT detection.

While using str_starts_with is cleaner than strpos, be aware that SQL statements might have leading whitespace even after trim. Consider using a more robust pattern matching.

-        if ($result instanceof PDOStatement && str_starts_with($lastQuery, 'select')) {
+        if ($result instanceof PDOStatement && preg_match('/^\s*select\b/i', $lastQuery)) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 103efbc and 4c856c9.

📒 Files selected for processing (3)
  • src/SqlQueryRowList.php (2 hunks)
  • tests/Fake/sql/todo_item_by_id_with_comment.sql (1 hunks)
  • tests/SqlQueryTest.php (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tests/Fake/sql/todo_item_by_id_with_comment.sql
🔇 Additional comments (1)
src/SqlQueryRowList.php (1)

15-18: Review PHP version compatibility and clean up imports.

The addition of str_starts_with requires PHP 8.0+. Also, strpos import appears to be unused after the change to str_starts_with.

src/SqlQueryRowList.php Outdated Show resolved Hide resolved
tests/SqlQueryTest.php Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c856c9 and f818228.

📒 Files selected for processing (4)
  • src/SqlQueryRowList.php (2 hunks)
  • tests/Fake/sql/todo_item_by_id_with_line_comment.sql (1 hunks)
  • tests/Fake/sql/todo_item_by_id_with_multiple_comment.sql (1 hunks)
  • tests/SqlQueryTest.php (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • tests/Fake/sql/todo_item_by_id_with_line_comment.sql
  • tests/Fake/sql/todo_item_by_id_with_multiple_comment.sql
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/SqlQueryRowList.php
🔇 Additional comments (3)
tests/SqlQueryTest.php (3)

35-35: LGTM! Good refactoring.

The extraction of common assertion logic into testSql improves code maintainability and follows DRY principles.


64-80: Consider adding more comprehensive test cases.

While the current test methods cover basic comment scenarios, consider adding test cases for:

  • Single-line comments (--)
  • Multiple comments in different positions
  • Malformed or nested comments
  • Comments between SQL keywords

66-66: Verify the SQL files exist and contain properly formatted queries.

Let's ensure the SQL files exist and contain valid queries with the expected comment styles.

Also applies to: 72-72, 78-78

✅ Verification successful

SQL files exist and contain valid queries with proper comments

All three SQL files are present in the expected location (tests/Fake/sql/) and contain properly formatted SQL queries with different comment styles:

  • todo_item_by_id_with_comment.sql: Uses /* */ block comments
  • todo_item_by_id_with_line_comment.sql: Uses -- line comments
  • todo_item_by_id_with_multiple_comment.sql: Uses both comment styles
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the SQL files exist and verify their content

# Check if files exist and show their content
for file in "todo_item_by_id_with_comment.sql" "todo_item_by_id_with_line_comment.sql" "todo_item_by_id_with_multiple_comment.sql"; do
  echo "=== Checking $file ==="
  cat "tests/Fake/sql/$file" 2>/dev/null || echo "File not found: $file"
done

Length of output: 1225

tests/SqlQueryTest.php Outdated Show resolved Hide resolved
@koriym
Copy link
Member

koriym commented Dec 17, 2024

PHP7.4からのサポートなので一部関数がアウトだと思います。

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/SqlQueryRowList.php (1)

57-57: Consider additional SQL comment handling improvements

The current implementation could be enhanced to:

  1. Handle MySQL's # style comments
  2. Better handle nested comments
  3. Validate comment syntax correctness

Consider updating the regex pattern:

-(string) preg_replace('/\/\*.*?\*\/|--.*$/m', '', (string) $result->queryString),
+(string) preg_replace('/\/\*(?:[^*]|\*(?!\/))*\*\/|(?:--|#).*$/m', '', (string) $result->queryString),
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c34dc4a and b310e55.

📒 Files selected for processing (1)
  • src/SqlQueryRowList.php (2 hunks)
🔇 Additional comments (3)
src/SqlQueryRowList.php (3)

15-15: LGTM: Import addition is compatible with PHP 7.4

The added preg_replace import is correctly placed and compatible with PHP 7.4.


56-59: Enhancement implemented as suggested

The code now handles both /* */ and -- style comments as previously recommended.


56-59: Verify SQL injection protection with comment stripping

Let's verify that the comment stripping logic doesn't affect the SQL injection protection mechanisms.

✅ Verification successful

SQL comment stripping is safely implemented

The code analysis reveals that the comment stripping is only used for query comparison after the query has already been executed through PDO's perform method, which uses parameterized queries. The preg_replace is not involved in query construction or execution, but only in post-execution analysis of the query string.

  • The SQL queries are executed using $pdo->perform() with proper parameter binding as seen in SqlQueryRowList.php and test files
  • Comment stripping via preg_replace is only applied to $result->queryString after query execution
  • The stripped query is only used for checking if it's a SELECT statement (strpos($lastQuery, 'select'))
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for SQL injection protection mechanisms in the codebase
# Expected: Find evidence of parameterized queries or escaping

# Check for PDO prepare/execute usage
echo "Checking for PDO prepare/execute usage:"
rg -A 2 'prepare|execute|perform' --type php

# Check for SQL injection related tests
echo "Checking for SQL injection tests:"
rg -l 'sql.*injection|injection.*test' --type php tests/

Length of output: 1601


Script:

#!/bin/bash
# Let's analyze the SQL query handling more thoroughly

# Check the implementation of perform method and related SQL handling
echo "Checking SQL query handling implementation:"
rg -A 10 "class.*Pdo|function perform" --type php

# Look for SQL parameter binding and preparation
echo "Checking parameter binding:"
rg -A 5 "->prepare|->bindParam|->bindValue" --type php

# Check the actual usage context of the comment stripping
echo "Checking comment stripping context:"
ast-grep --pattern 'preg_replace("/\*.*?\*/|--.*$/m"'

Length of output: 1059


Script:

#!/bin/bash
# Let's try a different approach to check SQL handling

# Check the SqlQueryRowList class implementation
echo "Checking SqlQueryRowList implementation:"
rg -A 15 "class SqlQueryRowList" --type php

# Look for SQL query execution with proper escaping
echo "Checking query execution:"
rg -A 10 '\$pdo.*->perform|\$this->pdo.*->perform' --type php

# Check if the comment stripping is only used for query comparison
echo "Checking preg_replace usage context:"
rg -A 5 -B 5 'preg_replace.*\*/.*\$result' --type php

Length of output: 4779

@koriym
Copy link
Member

koriym commented Dec 18, 2024

@coderabbitai これまでのコメントを日本語でもお願いします。

Copy link
Contributor

coderabbitai bot commented Dec 18, 2024

Tip

For best results, initiate chat on the files or code changes.

@koriym

以下に、Pull Request #33 に関連してこれまで出されているコメントや内容を日本語でまとめます。

  1. 「コメント付きSQLが実行されない問題を修正する」Pull Requestが作成されました。具体的には、下記の内容が含まれています。

    • SQL文の先頭にコメントが書かれている場合に実行されない問題を修正。
    • PHPの組み込み関数の使用(たとえば strpos → str_starts_with)によって、コメント付きSQLの動作をより確実にする変更が加えられています。
  2. あなた(@koriym)からの主なコメント:

    • 「PHP7.4からのサポートなので一部関数がアウトだと思います。」
      → PHP 7.4 以前だと一部の関数がサポートされていない可能性があるため、Pull Requestの変更内容がPHP 7.4の環境で問題を起こさないかが懸念点になっています。

もし他にご不明な点や追加でご説明が必要なことがありましたら、お知らせください。

@koriym
Copy link
Member

koriym commented Dec 18, 2024

@coderabbitai いえ、あなたのコメントです。以下の2つを訳してください。

#33 (review)

57-57: Consider additional SQL comment handling improvements

The current implementation could be enhanced to:

Handle MySQL's # style comments
Better handle nested comments
Validate comment syntax correctness

64-80: Consider adding more comprehensive test cases.

While the current test methods cover basic comment scenarios, consider adding test cases for:

Single-line comments (--)
Multiple comments in different positions
Malformed or nested comments
Comments between SQL keywords

Copy link
Contributor

coderabbitai bot commented Dec 18, 2024

Tip

For best results, initiate chat on the files or code changes.

@koriym

以下がご指定いただいた2箇所のコメントの和訳です。

■ 57-57: Consider additional SQL comment handling improvements
「追加のSQLコメント処理の改善を検討してください。

現在の実装は以下の点で強化できる可能性があります:
・MySQLの # スタイルコメントへの対応
・ネストされたコメントのより適切なハンドリング
・コメント構文の正当性を検証する機能」

■ 64-80: Consider adding more comprehensive test cases.
「より包括的なテストケースの追加を検討してください。

現在のテストメソッドは基本的なコメントシナリオをカバーしていますが、以下のようなテストケースを追加することを検討してください:
・1行コメント(--)
・異なる場所に複数のコメントが含まれる場合
・不正な形式のコメントやネストされたコメント
・SQLキーワードの間にコメントが入るケース」

@koriym
Copy link
Member

koriym commented Dec 18, 2024

@KazuyaUchida どうでしょうか?

@KazuyaUchida
Copy link
Contributor Author

KazuyaUchida commented Dec 18, 2024

@koriym
coderabbitai の提案を試してみましたが、

MySQLの # スタイルコメントへの対応

#スタイルコメントを挿入した場合は、そもそもSQLが実行できないです

PDOException : SQLSTATE[HY000]: General error: 1 unrecognized token: "#"
Ray.QueryModule/vendor/aura/sql/src/AbstractExtendedPdo.php:620
Ray.QueryModule/vendor/aura/sql/src/AbstractExtendedPdo.php:554
Ray.QueryModule/src/SqlQueryRowList.php:52

64-80: Consider adding more comprehensive test cases.

いくつか提案はされていますが、作成したテストで用意したSQLでカバーできています
今回の対応は先頭にコメントが挿入された場合に実行されてないケースの対応のため、SQL内のコメントがあった場合はスコープ外の認識です

1行コメント(--)

testWithLineCommentでチェック済み
SQLとして以下の様な書き方をしている場合はコメントアウトされていると思われるので、SQLが実行される方が問題かと思われます

-- todo_item_by_id_with_line_comment.sql SELECT * FROM todo WHERE id = :id

異なる場所に複数のコメントが含まれる場合

一応todo_item_by_id_with_comment.sqlで先頭以外のブロックコメントが含まれている場合のSQLでチェックしています

PHPStanでエラーになっているところも、今回の修正とは関係のないところでエラーになっているので、対応するか悩みどころです💦

Copy link
Member

@koriym koriym left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EOLの追加をsuggestしました。

tests/Fake/sql/todo_item_by_id_with_comment.sql Outdated Show resolved Hide resolved
tests/Fake/sql/todo_item_by_id_with_line_comment.sql Outdated Show resolved Hide resolved
tests/Fake/sql/todo_item_by_id_with_multiple_comment.sql Outdated Show resolved Hide resolved
Co-authored-by: Akihito Koriyama <[email protected]>
@KazuyaUchida
Copy link
Contributor Author

@koriym
eaf52fa で反映しました!

@KazuyaUchida KazuyaUchida requested a review from koriym December 18, 2024 03:58
Added precise type annotations for MethodInvocation and other parameters in QueryInterceptor. This improves code readability and aids in static analysis. No functional changes were made.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/QueryInterceptor.php (1)

Line range hint 49-64: Consider adding SQL comment validation

Since this PR aims to fix SQL comment handling, consider adding validation in getQueryResult to ensure proper comment handling before execution:

     private function getQueryResult(MethodInvocation $invocation, QueryInterface $query, array $param)
     {
+        // Validate SQL comments if query contains raw SQL
+        if ($query instanceof SqlQueryInterface) {
+            $this->validateSqlComments($query);
+        }
         /** @psalm-suppress MixedAssignment */
         $result = $query($param);

This would help catch malformed comments early and provide better error messages.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eaf52fa and 0354483.

📒 Files selected for processing (1)
  • src/QueryInterceptor.php (2 hunks)
🔇 Additional comments (1)
src/QueryInterceptor.php (1)

49-52: Verify PHP 7.4 compatibility for generic type hints

The type safety improvements with MethodInvocation<object> are good, but they might cause issues with PHP 7.4 as mentioned in the PR comments. Consider using PHPDoc-only type hints for backward compatibility.

Run this script to check PHP compatibility:

src/QueryInterceptor.php Outdated Show resolved Hide resolved
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/QueryInterceptor.php (1)

Line range hint 54-64: Consider enhancing error handling for query execution

The query execution could benefit from additional error handling:

  1. Add try-catch block to handle potential query execution errors
  2. Validate the result type matches the expected interface type

Example implementation:

     private function getQueryResult(MethodInvocation $invocation, QueryInterface $query, array $param)
     {
+        try {
             /** @psalm-suppress MixedAssignment */
             $result = $query($param);
+            
+            // Validate result type based on query interface
+            if ($query instanceof RowInterface && !is_array($result)) {
+                throw new UnexpectedValueException('Row query must return array');
+            }
+            if ($query instanceof RowListInterface && !is_array($result)) {
+                throw new UnexpectedValueException('Row list query must return array');
+            }
+            
             $object = $invocation->getThis();
             if ($object instanceof ResourceObject) {
                 return $this->returnRo($object, $invocation, $result);
             }

             return $result;
+        } catch (Exception $e) {
+            throw new QueryExecutionException('Query execution failed: ' . $e->getMessage(), 0, $e);
+        }
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0354483 and bfe5106.

📒 Files selected for processing (1)
  • src/QueryInterceptor.php (2 hunks)
🔇 Additional comments (2)
src/QueryInterceptor.php (2)

Line range hint 49-53: Enhance docblock completeness and PHP 7.4 compatibility

The docblock needs improvement for better type safety and compatibility:

  1. The generic type MethodInvocation<object> may cause PHP 7.4 compatibility issues
  2. Missing parameter documentation for $query

Apply this diff:

     /**
-     * @param MethodInvocation<object> $invocation
+     * @param MethodInvocation $invocation
      * @param array<string, mixed> $param
+     * @param QueryInterface $query
      *
-     * @return mixed
+     * @return array|object|scalar|null
      */

66-70: LGTM! Well-documented method signature

The docblock provides clear type information for parameters and return type.

Introduce `QUERY_CLEANUP_REGEX` and `TRIM_CHARACTERS_REGEX` constants to improve code readability and reduce redundancy. Replace hardcoded regex strings with these constants in SQL trimming and cleanup operations. This makes future maintenance and updates to these patterns simpler and more centralized.
Updated type annotations to ensure compatibility with diverse data structures and improve clarity. This change enhances maintainability and conforms to best practices for type declarations.
@koriym
Copy link
Member

koriym commented Dec 18, 2024

PHPStanでエラーになっているところも、今回の修正とは関係のないところでエラーになっているので、対応するか悩みどころです💦

修正しました。

@koriym koriym merged commit 45b0308 into ray-di:1.x Dec 18, 2024
20 checks passed
@KazuyaUchida KazuyaUchida deleted the fix-sql-with-comments-can-be-executed branch December 18, 2024 05:02
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