-
-
Notifications
You must be signed in to change notification settings - Fork 12
feat: implement raw queries #69
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
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughRaw 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
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
Poem
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this 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$queryRawUnsafemethods 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
providersasstring[]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
createDeferredPromiseis 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
compiledQueryis not defined in this scope, socompiledQuery.parameterswill 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}`);
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this 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
📒 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
$executeRawmethod 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
$queryRawmethod with generic return typeTallows for flexible result typing while maintaining type safety through prepared statements.
43-79: Verify raw query placeholder handling across providersFile: packages/runtime/src/client/contract.ts
Lines: 43–79Snippet 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$queryRawUnsafemap 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.parametersensures 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
parametersparameter and its propagation toproceedQuerymaintains 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
CompiledQueryandsqlimports 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
sqltagged 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
$executeRawUnsafemethod properly usesCompiledQuery.rawfor 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
$executeRawbut returns the result rows instead of affected row count.
237-243: Appropriate implementation of unsafe raw query method.The
$queryRawUnsafemethod maintains consistency with its execute counterpart while returning query results. The implementation correctly handles the unsafe SQL execution pattern.
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Chores