Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Jul 2, 2025

Summary by CodeRabbit

  • New Features

    • Introduced safe and unsafe methods for executing raw SQL queries and commands directly from the client, supporting both templated and raw string queries.
  • Bug Fixes

    • Improved parameter handling in query execution to ensure consistent propagation through the execution pipeline.
  • Tests

    • Added comprehensive tests covering both safe and unsafe raw SQL query methods.
  • Chores

    • Updated configuration files and logging messages for clarity and build process improvements.

Copilot AI review requested due to automatic review settings July 2, 2025 16:39
@coderabbitai
Copy link

coderabbitai bot commented Jul 2, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Raw SQL query capabilities were introduced to the client API, including both safe (prepared) and unsafe (raw string) methods for executing and querying data. Supporting changes were made to the client contract, query executor, and tests. Additional configuration and minor logging updates were applied to project files.

Changes

File(s) Change Summary
.coderabbit.yaml Added a new CodeRabbit configuration file specifying language, features, and schema.
packages/runtime/src/client/client-impl.ts Added four new async methods for raw SQL execution and querying: $executeRaw, $executeRawUnsafe, $queryRaw, $queryRawUnsafe.
packages/runtime/src/client/contract.ts Extended ClientContract with the same four raw SQL methods, including documentation and usage notes.
packages/runtime/src/client/executor/zenstack-query-executor.ts Updated query executor to explicitly propagate query parameters through execution methods.
packages/runtime/test/client-api/raw-query.test.ts Added a new test suite for raw query methods, covering both safe and unsafe variants for execution and querying.
packages/runtime/test/client-api/client-specs.ts Generalized the providers parameter type in createClientSpecs from a tuple to a string array.
packages/testtools/src/schema.ts Minor change in a console log message wording.
turbo.json Added "inputs": ["src/**"] to the build task configuration.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Client
    participant QueryExecutor
    participant Kysely

    User->>Client: $executeRaw / $queryRaw (template, values)
    Client->>Kysely: sql(template, values)
    Kysely-->>Client: CompiledQuery
    Client->>QueryExecutor: execute(compiledQuery)
    QueryExecutor->>Kysely: execute(compiledQuery)
    Kysely-->>QueryExecutor: Result
    QueryExecutor-->>Client: Result
    Client-->>User: Result

    User->>Client: $executeRawUnsafe / $queryRawUnsafe (query string, values)
    Client->>Kysely: CompiledQuery.raw(query string, values)
    Kysely-->>Client: CompiledQuery
    Client->>QueryExecutor: execute(compiledQuery)
    QueryExecutor->>Kysely: execute(compiledQuery)
    Kysely-->>QueryExecutor: Result
    QueryExecutor-->>Client: Result
    Client-->>User: Result
Loading

Poem

In the warren where queries hop and run,
New SQL tricks have just begun!
Safe or wild, raw or neat,
The client now can’t be beat.
With tests in tow and configs anew,
This bunny’s code is fresh as dew.
🐇✨


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.

❤️ 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.
    • 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 @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @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 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 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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @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.

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

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR introduces support for executing raw SQL queries through the client API. It:

  • Defines new $executeRaw, $executeRawUnsafe, $queryRaw, and $queryRawUnsafe methods in the client contract and implementation.
  • Updates the internal query executor to thread raw-query parameters through Kysely interceptors.
  • Adds end-to-end tests for raw query usage across SQLite and PostgreSQL providers.

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
turbo.json Added inputs pattern to the build task for caching accuracy
packages/testtools/src/schema.ts Tweaked console log message for the generated TS schema tool
packages/runtime/test/client-api/raw-query.test.ts New tests covering all four raw-query methods
packages/runtime/test/client-api/client-specs.ts Adjusted createClientSpecs signature and provider typing
packages/runtime/src/client/executor/zenstack-query-executor.ts Changed proceedQueryWithKyselyInterceptors to accept parameters
packages/runtime/src/client/contract.ts Added TypeScript declarations for the raw-query client API
packages/runtime/src/client/client-impl.ts Implemented the raw-query methods in the client implementation
Comments suppressed due to low confidence (4)

packages/runtime/test/client-api/client-specs.ts:6

  • Typing providers as string[] broadens allowed values and loses literal type safety. Consider using ('sqlite' | 'postgresql')[] or a readonly tuple to restrict providers to the expected values.
export function createClientSpecs(dbName: string, logQueries = false, providers: string[] = ['sqlite', 'postgresql']) {

packages/runtime/src/client/client-impl.ts:216

  • The function createDeferredPromise is used here but not imported; add the appropriate import statement at the top of this file.
        return createDeferredPromise(async () => {

packages/runtime/src/client/executor/zenstack-query-executor.ts:84

  • The variable compiledQuery is not defined in this scope, so compiledQuery.parameters will cause a ReferenceError. You should compute or pass the compiled query earlier, or adjust the call to use a defined variable.
            const result = await this.proceedQueryWithKyselyInterceptors(queryNode, compiledQuery.parameters, queryId);

packages/testtools/src/schema.ts:38

  • [nitpick] The log message reads 'Work directory', which is less common than 'Working directory'. For clarity and consistency, consider reverting to 'Working directory'.
    console.log(`Work directory: ${workDir}`);

@ymc9
Copy link
Member Author

ymc9 commented Jul 2, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jul 2, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@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 (4)
packages/testtools/src/schema.ts (1)

38-38: Consider keeping the original "Working directory" terminology.

"Working directory" is more standard terminology in development contexts compared to "Work directory". The original phrasing was more conventional and clear.

-    console.log(`Work directory: ${workDir}`);
+    console.log(`Working directory: ${workDir}`);
packages/runtime/src/client/contract.ts (2)

52-60: Security warning appropriately documented for unsafe method.

Good that the documentation clearly states "This method is susceptible to SQL injections" for $executeRawUnsafe. Consider adding a stronger warning or recommendation to prefer the safe variant when possible.

     * Executes a raw query and returns the number of affected rows.
-    * This method is susceptible to SQL injections.
+    * ⚠️  **WARNING**: This method is susceptible to SQL injections. Use `$executeRaw` instead whenever possible.

71-79: Consider strengthening the security warning.

Similar to $executeRawUnsafe, this method should have a more prominent security warning to discourage use when the safe variant is suitable.

     * Performs a raw query and returns the `SELECT` data.
-    * This method is susceptible to SQL injections.
+    * ⚠️  **WARNING**: This method is susceptible to SQL injections. Use `$queryRaw` instead whenever possible.
packages/runtime/src/client/client-impl.ts (1)

215-243: Consider enhancing error handling and type safety.

While the current implementation relies on underlying Kysely error handling, consider adding more specific error messages or validation for common scenarios like empty queries or invalid parameter counts.

Example enhancement for parameter validation:

 $executeRawUnsafe(query: string, ...values: any[]) {
     return createDeferredPromise(async () => {
+        if (!query.trim()) {
+            throw new QueryError('Query cannot be empty');
+        }
         const compiledQuery = CompiledQuery.raw(query, values);
         const result = await this.kysely.executeQuery(compiledQuery);
         return Number(result.numAffectedRows ?? 0);
     });
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c1f1b69 and 0db28f1.

📒 Files selected for processing (8)
  • .coderabbit.yaml (1 hunks)
  • packages/runtime/src/client/client-impl.ts (2 hunks)
  • packages/runtime/src/client/contract.ts (1 hunks)
  • packages/runtime/src/client/executor/zenstack-query-executor.ts (3 hunks)
  • packages/runtime/test/client-api/client-specs.ts (1 hunks)
  • packages/runtime/test/client-api/raw-query.test.ts (1 hunks)
  • packages/testtools/src/schema.ts (1 hunks)
  • turbo.json (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/runtime/test/client-api/raw-query.test.ts (2)
packages/runtime/test/client-api/client-specs.ts (1)
  • createClientSpecs (6-42)
packages/runtime/src/client/contract.ts (1)
  • ClientContract (35-133)
packages/runtime/src/client/client-impl.ts (2)
packages/runtime/src/client/promise.ts (1)
  • createDeferredPromise (5-28)
packages/runtime/src/client/executor/zenstack-driver.ts (1)
  • compiledQuery (166-173)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build-test (20.x)
🔇 Additional comments (16)
.coderabbit.yaml (1)

1-8: LGTM! Well-structured CodeRabbit configuration.

The configuration file follows the schema correctly and sets appropriate defaults for automated code review and chat functionality.

turbo.json (1)

6-6: Good improvement to build configuration.

Explicitly specifying "inputs": ["src/**"] makes build cache invalidation more reliable and aligns with Turbo best practices for dependency tracking.

packages/runtime/test/client-api/client-specs.ts (1)

6-6: Improved flexibility for database provider testing.

Changing from a const tuple to string[] with default values maintains backward compatibility while allowing more flexible provider specification for testing, which supports the new raw query functionality well.

packages/runtime/src/client/contract.ts (3)

43-50: Well-designed safe raw execution method.

The $executeRaw method provides a secure way to execute raw SQL using prepared statements. The JSDoc documentation is comprehensive with a practical example.


62-69: Generic typing provides good flexibility for query results.

The $queryRaw method with generic return type T allows for flexible result typing while maintaining type safety through prepared statements.


43-79: Verify raw query placeholder handling across providers

File: packages/runtime/src/client/contract.ts
Lines: 43–79

Snippet showing the final state of code at these lines

    /**
     * Executes a prepared raw query and returns the number of affected rows.
     * @example
     * ```
     * const result = await client.$executeRaw`UPDATE User SET cool = ${true} WHERE email = ${'user@email.com'};`
     * ```
     */
    $executeRaw(query: TemplateStringsArray, ...values: any[]): Promise<number>;

    /**
     * Executes a raw query and returns the number of affected rows.
     * This method is susceptible to SQL injections.
     * @example
     * ```
     * const result = await client.$executeRawUnsafe('UPDATE User SET cool = $1 WHERE email = $2 ;', true, '[email protected]')
     * ```
     */
    $executeRawUnsafe(query: string, ...values: any[]): Promise<number>;

    /**
     * Performs a prepared raw query and returns the `SELECT` data.
     * @example
     * ```
     * const result = await client.$queryRaw`SELECT * FROM User WHERE id = ${1} OR email = ${'user@email.com'};`
     * ```
     */
    $queryRaw<T = unknown>(query: TemplateStringsArray, ...values: any[]): Promise<T>;

    /**
     * Performs a raw query and returns the `SELECT` data.
     * This method is susceptible to SQL injections.
     * @example
     * ```
     * const result = await client.$queryRawUnsafe('SELECT * FROM User WHERE id = $1 OR email = $2;', 1, '[email protected]')
     * ```
     */
    $queryRawUnsafe<T = unknown>(query: string, ...values: any[]): Promise<T>;

I wasn’t able to locate the actual runtime implementations of these methods in the codebase. Please manually confirm that:

  • The PrismaClient methods $executeRaw, $executeRawUnsafe, $queryRaw, and $queryRawUnsafe map template values or argument arrays to the correct placeholder syntax for each provider (e.g. $1, $2… on PostgreSQL, ? on SQLite, etc.).
  • The underlying query engine or connector layer uniformly handles placeholder translation across all supported databases.
packages/runtime/test/client-api/raw-query.test.ts (2)

1-80: Comprehensive test coverage for raw query methods.

The test suite effectively covers all four new raw query methods with appropriate test scenarios. The implementation correctly handles provider-specific parameter syntax differences and verifies both execution results and data changes.


41-47: Good handling of provider-specific SQL parameter syntax.

The conditional parameter placeholder logic correctly handles the differences between PostgreSQL ($1, $2) and SQLite (?) parameter syntax.

packages/runtime/src/client/executor/zenstack-query-executor.ts (3)

84-84: Proper parameter propagation to interceptors.

The explicit passing of compiledQuery.parameters ensures that query parameters are available throughout the interceptor pipeline, which is essential for the new raw query functionality.


99-104: Updated method signature supports parameter handling.

The addition of the parameters parameter and its propagation to proceedQuery maintains the parameter flow through the execution chain.


132-135: Correct parameter merging into compiled query.

The merging of parameters into the compiled query object using the spread operator ensures that the original compilation result is preserved while adding the parameters.

packages/runtime/src/client/client-impl.ts (5)

4-10: Appropriate imports for raw query functionality.

The addition of CompiledQuery and sql imports provides the necessary tools for both safe and unsafe raw query execution.


215-220: Secure implementation of $executeRaw using tagged templates.

The use of Kysely's sql tagged template function ensures proper parameterization and prevents SQL injection. The return value handling correctly extracts the number of affected rows.


222-228: Correct implementation of unsafe raw execution method.

The $executeRawUnsafe method properly uses CompiledQuery.raw for direct SQL execution. The method name and implementation clearly indicate the SQL injection risk, which aligns with the contract documentation.


230-235: Secure implementation of $queryRaw using tagged templates.

The query method correctly uses the same secure parameterization approach as $executeRaw but returns the result rows instead of affected row count.


237-243: Appropriate implementation of unsafe raw query method.

The $queryRawUnsafe method maintains consistency with its execute counterpart while returning query results. The implementation correctly handles the unsafe SQL execution pattern.

@ymc9 ymc9 merged commit d259709 into dev Jul 2, 2025
3 checks passed
This was referenced Jul 2, 2025
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