Skip to content

Conversation

@jimezesinachi
Copy link
Contributor

@jimezesinachi jimezesinachi commented Sep 10, 2024

SynthQL pull request template

Why

We're adding a new data structure that allows us to parameterize and detect parameterized queries

What changed

Updated the WhereClause pipe include the new QueryParameter type

Important

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Enhanced QueryEngine with a method for registering multiple queries and a flag for allowing unregistered queries.
    • Introduced QueryStore class for managing parameterized queries, including methods to add, retrieve, and check queries.
    • Added new static methods in SynthqlError for improved error handling across various scenarios.
    • Introduced parameterization options in query generation functions for improved flexibility.
    • Updated search and navigation data in the documentation assets for improved functionality.
  • Bug Fixes

    • Adjusted QueryParameter type to accept only strings for the id property, improving data consistency.
  • Documentation

    • Improved documentation for query registration methods and options.
    • Updated import statements for clarity and consistency across the codebase.
    • Introduced documentation for new query request structures.

Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 10, 2024

Walkthrough

This pull request introduces enhancements to the QueryEngine class by adding a property for allowing unregistered queries and a method for registering queries. It also introduces a QueryStore class for managing parameterized queries, alongside updates to testing utilities to incorporate a new parameterize feature. Additionally, modifications are made to various error handling mechanisms and the structure of query requests to improve overall functionality.

Changes

Files Change Summary
packages/backend/src/QueryEngine.ts Added dangerouslyAllowUnregisteredQueries property and registerQueries method; modified execute methods for unregistered queries.
packages/backend/src/QueryStore.ts Introduced QueryStore class for managing parameterized queries with methods for adding, retrieving, and checking queries.
packages/backend/src/SynthqlError.ts Enhanced SynthqlError class with new static methods for improved error handling.
packages/backend/src/tests/propertyBased/arbitraries/arbitraryQuery.ts Updated ArbitraryQuery interface to include parameterize property; modified function signature.
packages/backend/src/tests/propertyBased/arbitraries/arbitraryWhere.ts Added parameterize parameter to arbitraryWhere function; removed date-time column filtering logic.
packages/backend/src/tests/propertyBased/arbitraries/arbitraryWhereValue.ts Added parameterize parameter to arbitraryWhereValue function; modified value generation logic.
packages/backend/src/tests/propertyBased/properties/cardinalityMany.test.ts Expanded tests to include parameterized query scenarios.
packages/backend/src/tests/propertyBased/properties/cardinalityMaybe.test.ts Added tests for parameterized queries in cardinality maybe context.
packages/backend/src/tests/propertyBased/properties/cardinalityOne.test.ts Introduced tests for parameterized queries in cardinality one context.
packages/docs/static/reference/assets/search.js Updated window.searchData with a new base64-encoded string.
packages/docs/static/reference/assets/navigation.js Updated window.navigationData with a new base64-encoded string.
packages/docs/docs/200-security.md Updated registerQueries method usage and renamed option from allowUnknownQueries to dangerouslyAllowUnregisteredQueries.
packages/handler-express/src/createExpressSynthqlHandler.ts Enhanced request handling with type checks and refactored query execution logic.
packages/handler-next/src/createNextSynthqlHandler.ts Improved request parsing and execution logic for SynthQL requests.
packages/queries/src/index.ts Added new exports for ColumnReference and QueryRequest, and renamed isQueryParam to isQueryParameter.
packages/queries/src/types/QueryRequest.ts Introduced interfaces for RegularQueryRequest and RegisteredQueryRequest.
packages/queries/src/util/iterateRecursively.ts Added utility function for recursive data structure traversal.
packages/queries/src/validators/isRegisteredQueryRequest.ts Added type guard function for validating RegisteredQueryRequest.
packages/queries/src/validators/isRegularQueryRequest.ts Added type guard function for validating RegularQueryRequest.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant QueryEngine
    participant QueryStore

    User->>QueryEngine: Execute query
    QueryEngine->>QueryStore: Check if query is registered
    alt Query is registered
        QueryStore-->>QueryEngine: Return query
        QueryEngine-->>User: Execute and return results
    else Query is not registered
        alt Allow unregistered queries
            QueryEngine-->>User: Execute and return results
        else Do not allow
            QueryEngine-->>User: Throw error
        end
    end
Loading

🐰 In the land of code, where rabbits play,
New features hop in, brightening the day!
Unregistered queries, a leap of delight,
With QueryStore to keep things just right.
Parameterized tests, oh what a thrill,
In this coding garden, we jump with skill! 🌼

Possibly related PRs

  • feat: added hashQuery() and used it in useSynthql() #41: The changes in this PR involve the introduction of a hash property in query structures, which relates to the new dangerouslyAllowUnregisteredQueries property in the main PR as both enhance query handling and management in the QueryEngine.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between a41c1e0 and 1c6db94.

📒 Files selected for processing (1)
  • packages/queries/src/util/iterateRecursively.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/queries/src/util/iterateRecursively.ts

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 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.

@vercel
Copy link

vercel bot commented Sep 10, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Sep 27, 2024 8:52am

@jimezesinachi jimezesinachi marked this pull request as ready for review September 10, 2024 08:30
@jimezesinachi jimezesinachi requested a review from fhur September 10, 2024 08:31
Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.com>
Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.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: 5

Outside diff range and nitpick comments (7)
packages/queries/src/util/iterateRecursively.ts (1)

21-22: Consider more descriptive names or specific wrappers.

The TODO comment raises a valid point about the clarity of the function name iterateRecursively. Here are some suggestions:

  1. More descriptive names:

    • traverseNestedStructure
    • deepTraversal
    • recursiveVisitor
  2. Specific named wrappers:

    • findNestedValue(traversable, predicate)
    • transformNestedStructure(traversable, transformer)
    • flattenNestedStructure(traversable)

These wrappers can provide a more intuitive API for common use cases while using iterateRecursively internally.

packages/backend/src/QueryEngine.test.ts (1)

1-9: LGTM!

The imports and test case setup look good. The test case is properly defined using the Vitest functions.

Please address the TODO comment in the future to complete the tests and consider moving them to an appropriate location if necessary.

packages/backend/src/QueryEngine.ts (4)

90-93: LGTM!

The new property dangerouslyAllowUnregisteredQueries is used to allow the execution of unregistered queries and the TODO comment indicates that the callback return type of the queries property needs to be fixed.

Do you want me to open a GitHub issue to track the TODO comment?


151-159: LGTM!

The conditional check ensures that only registered queries are executed if dangerouslyAllowUnregisteredQueries is false, which is a reasonable safety measure. The queries map is used to check if the query has been registered, which is a reasonable approach.

Do you want me to open a GitHub issue to track the TODO comment?


188-196: LGTM!

The conditional check ensures that only registered queries are executed if dangerouslyAllowUnregisteredQueries is false, which is a reasonable safety measure. The queries map is used to check if the query has been registered, which is a reasonable approach.

Do you want me to open a GitHub issue to track the TODO comment?


Line range hint 208-301: LGTM!

The new registerQueries method provides a way to register query functions, which is a useful feature. The logic of iterating over the provided query functions, executing each function to get the query, checking if the query has a hash, and adding the query function to the queries map using the query hash as the key is a reasonable approach to register query functions.

Do you want me to open GitHub issues to track the TODO comments?

packages/queries/src/query.ts (1)

Line range hint 66-100: Excellent addition for handling parameterized queries!

The new code block introduces a robust mechanism to identify and assign identifiers to query parameters within the constructed query object. The use of iterateRecursively ensures that all nested parameters are properly handled, and the isQueryParameter function provides a clear validation step.

Assigning identifiers based on the parameter's path is a good approach for uniquely identifying each parameter within the query structure.

Regarding the TODO comment:

Consider extracting the parameter identification logic into a separate function with a descriptive name and clear documentation. This will improve the readability and maintainability of the code.

For example:

function assignParameterIdentifiers(query: QueryObject) {
  // Documentation: Recursively iterates over the query object and assigns identifiers to query parameters based on their path.
  iterateRecursively(query, (value, path) => {
    if (isQueryParameter(value)) {
      value.id = path.join('.');
    }
  });
}

Then, you can call this function within the build method:

const query = {
  // ...
};

assignParameterIdentifiers(query);

return query;
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between c96c81e and 2ca9f27.

Files selected for processing (14)
  • packages/backend/src/QueryEngine.test.ts (1 hunks)
  • packages/backend/src/QueryEngine.ts (10 hunks)
  • packages/backend/src/SynthqlError.ts (5 hunks)
  • packages/backend/src/execution/executors/PgExecutor/PgExecutor.test.ts (5 hunks)
  • packages/docs/static/reference/assets/navigation.js (1 hunks)
  • packages/docs/static/reference/assets/search.js (1 hunks)
  • packages/queries/src/index.ts (1 hunks)
  • packages/queries/src/param.ts (1 hunks)
  • packages/queries/src/query.test.ts (2 hunks)
  • packages/queries/src/query.ts (3 hunks)
  • packages/queries/src/types/QueryParameter.ts (1 hunks)
  • packages/queries/src/types/QueryRequest.ts (1 hunks)
  • packages/queries/src/util/iterateRecursively.test.ts (1 hunks)
  • packages/queries/src/util/iterateRecursively.ts (1 hunks)
Files skipped from review as they are similar to previous changes (5)
  • packages/backend/src/execution/executors/PgExecutor/PgExecutor.test.ts
  • packages/docs/static/reference/assets/navigation.js
  • packages/docs/static/reference/assets/search.js
  • packages/queries/src/index.ts
  • packages/queries/src/query.test.ts
Additional comments not posted (23)
packages/queries/src/types/QueryParameter.ts (1)

3-3: Verify the impact of restricting id to string type.

The change to restrict the id property to only accept string values is a good move for type safety and consistency.

However, please ensure that this change does not break any existing code that may be using numeric id values. Run the following script to verify:

Verification successful

Approve the change: id restriction to string type is safe

The change to restrict the id property to only accept string values in packages/queries/src/types/QueryParameter.ts appears to be safe and localized. Our verification process didn't find any direct usage of numeric id values that would be affected by this change. The numeric IDs found in the codebase are mostly entity-specific (e.g., actor_id, film_id) and not related to the generic id property we're modifying.

This change will improve type safety and consistency in the QueryParameter interface without breaking existing code.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if numeric `id` values are used in the codebase.

# Test: Search for numeric `id` usage. Expect: No occurrences of numeric `id`.
rg --type typescript $'id:(\s+\d+|\s+\d+\.\d+)' 

Length of output: 83


Script:

#!/bin/bash
# Description: Verify if numeric `id` values are used in the codebase.

# Find TypeScript files and search for numeric `id` usage
fd -e ts -e tsx | xargs rg 'id:\s*(\d+|\d+\.\d+)' -n

# Also search for potential type definitions that allow number type for id
fd -e ts -e tsx | xargs rg 'id:\s*(number|string\s*\|\s*number|number\s*\|\s*string)' -n

Length of output: 13188

packages/queries/src/param.ts (1)

3-5: Verify the impact of the function signature change on the codebase.

The function signature has been updated to make the value parameter optional and remove the id parameter. This change might have affected other parts of the codebase where the function is called with an explicit id argument.

Run the following script to verify the function usage:

Verification successful

Function signature change appears compatible with existing usage

Based on the search results, the updated param() function signature seems to be compatible with its current usage across the codebase. Key observations:

  • No instances of param() being called with two arguments were found, which would have been incompatible with the new signature.
  • Both param() and param(value) usages are present, which are supported by the new optional parameter.
  • Most occurrences are in test files, reducing the risk of breaking changes in production code.

However, to ensure no edge cases were missed:

  • Manually review the changes in non-test files, particularly in packages/queries/src/types/Where.ts.
  • Verify that removing the id parameter doesn't cause any unexpected behavior in existing queries.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all function calls to `param` match the new signature.

# Test: Search for the function usage. Expect: Only occurrences of the new signature.
rg --type typescript -A 5 $'param\('

Length of output: 72


Script:

#!/bin/bash
# Description: Verify all function calls to `param` match the new signature using multiple search methods.

# Method 1: Use ripgrep without file type specification
echo "Method 1: Ripgrep search"
rg -n 'param\(' --type-add 'ts:*.ts' --type-add 'tsx:*.tsx' -g '*.{ts,tsx}'

# Method 2: Use find and grep
echo "Method 2: Find and grep search"
find . -name '*.ts' -o -name '*.tsx' | xargs grep -n 'param('

# Method 3: Use fd and grep
echo "Method 3: fd and grep search"
fd -e ts -e tsx | xargs grep -n 'param('

Length of output: 5504

packages/queries/src/types/QueryRequest.ts (3)

3-6: LGTM!

The RegularQueryRequest interface is well-defined and follows TypeScript best practices. The type property helps identify the type of query request, and the query property allows for flexibility in the query structure.


8-12: LGTM!

The RegisteredQueryRequest interface is well-defined and follows TypeScript best practices. The type property helps identify the type of query request, the queryId property allows for unique identification of the query, and the params property allows for flexibility in the parameter structure. The generic type parameter TValue with a default value of unknown provides type safety and flexibility for the parameter values.


14-14: LGTM!

The QueryRequest type is a well-defined union of the RegularQueryRequest and RegisteredQueryRequest interfaces. This allows for the application to handle both types of query requests interchangeably and follows TypeScript best practices.

packages/queries/src/util/iterateRecursively.ts (2)

6-19: LGTM!

The Primitive and Traversable type definitions are clear and comprehensive. The Traversable type correctly allows for recursive nesting of objects and arrays.


23-55: LGTM!

The implementation of the iterateRecursively function is well-structured and handles the traversal of complex data structures effectively. The recursive approach enables deep traversal of nested structures, and the visitor function allows for custom processing of each element.

The function correctly handles both arrays and objects, and it uses appropriate type checks to ensure the traversable is an object or an array. It also handles the case when the traversable is null or an instance of Date.

Overall, the implementation is solid and should work as intended.

packages/backend/src/QueryEngine.test.ts (2)

10-16: LGTM!

The query parameters are properly defined in the params object, following a consistent naming convention. The hardcoded values are acceptable for the purpose of the test case.


18-41: LGTM!

The findFilmActor query function is well-structured and correctly uses the @synthql/queries library to construct a complex query with nested relationships. The use of param, col, and maybe functions ensures that the query references the correct parameters, columns, and optional relationships.

packages/backend/src/SynthqlError.ts (5)

26-39: LGTM!

The createCardinalityError method is well-structured and provides a clear error message with a helpful hint. The error type and status code are appropriate for the described scenarios.


64-85: Looks good!

The updated createJsonParsingError method now provides more context by including the erroneous JSON string in the error message. This will help with troubleshooting JSON parsing issues. The additional guidance in the error message is also helpful.


87-92: Looks good to me!

The createMissingHashError method is straightforward and provides a clear error message for the case when a query is missing its hash during registration.


132-135: Nice update!

The additional guidance in the error message is valuable for troubleshooting response streaming errors. It covers important points like checking read access and ensuring all queries are registered.


141-152: Great refactoring!

Renaming the method to createSqlExecutionError better reflects its purpose. The use of the composeMessage function to generate a detailed error message is a good improvement. Including the error details, SQL query, parameters, and the original SynthQL query will greatly aid in debugging SQL execution errors.

packages/backend/src/QueryEngine.ts (7)

2-9: LGTM!

The imported types are used in the file and the imports look good.


22-26: LGTM!

The JSDoc comment provides a clear description of the url property.


37-40: LGTM!

The new property dangerouslyAllowUnregisteredQueries is well-documented and the default value of false ensures that only registered queries are executed by default. The property name and JSDoc comment clearly indicate the potential risks of using this feature.


Line range hint 49-72: LGTM!

The JSDoc comment provides a clear description of the providers property and the example demonstrates how to use it.


73-77: LGTM!

The JSDoc comment provides a clear description of the pool property and indicates that it can be used as an alternative to the url property.


103-107: LGTM!

The schema, dangerouslyAllowUnregisteredQueries, and prependSql properties are set to reasonable default values if the corresponding config properties are not provided.


122-132: LGTM!

The updated compile method returns an object with sql and params properties, which is a clearer and more explicit return type. The composeQuery function is used to generate the SQL query, which is a reasonable approach.

packages/queries/src/query.ts (2)

12-13: LGTM!

The new imports are relevant and properly defined.


Line range hint 1-11: Reviewed the rest of the file.

No further comments.

Also applies to: 14-65, 101-587

Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.com>
@synthql synthql deleted a comment from coderabbitai bot Sep 16, 2024
Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.com>
Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.com>
Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.com>
@jimezesinachi jimezesinachi changed the title feat: updated WhereClause type to include QueryParameter feat: complete adding support for parameterized and registered queries Sep 19, 2024
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: 7

Outside diff range and nitpick comments (3)
packages/handler-next/src/createNextSynthqlHandler.ts (1)

Line range hint 176-185: Address the TODO regarding error handling in streaming responses

There is a TODO comment indicating that the error handling logic within the writeResponseBody function for streaming responses is not effective, as errors thrown inside the NextResponse stream are propagated differently. Consider revising the streaming logic to appropriately handle errors during streaming, ensuring that clients receive meaningful error information.

Do you need assistance in refactoring the streaming error handling? If you'd like, I can help propose a solution or open a GitHub issue to track this task.

packages/react/src/createBody.ts (2)

13-24: Simplify error message construction using template literals

For improved readability, consider using template literals instead of joining array elements with '\n'.

Apply this refactor to streamline the code:

-                throw new Error(
-                    [
-                        'Missing value error!',
-                        '',
-                        'No value passed for the parameter:',
-                        '',
-                        JSON.stringify(x.id, null, 2),
-                        '',
-                    ].join('\n'),
-                );
+                throw new Error(`Missing value error!

No value passed for the parameter:

${JSON.stringify(x.id, null, 2)}
`);

32-43: Use template literals for cleaner error messages

Consistent with the previous suggestion, using template literals here enhances code clarity.

Here's how you can refactor the code:

-            throw new Error(
-                [
-                    'Missing hash error!',
-                    '',
-                    'The query:',
-                    '',
-                    JSON.stringify(query, null, 2),
-                    '',
-                    'is missing its `hash` property',
-                    '',
-                ].join('\n'),
-            );
+            throw new Error(`Missing hash error!

The query:

${JSON.stringify(query, null, 2)}

is missing its \`hash\` property
`);
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between c4fd1e3 and 772b166.

Files selected for processing (14)
  • packages/docs/static/reference/assets/navigation.js (1 hunks)
  • packages/docs/static/reference/assets/search.js (1 hunks)
  • packages/handler-express/src/createExpressSynthqlHandler.ts (5 hunks)
  • packages/handler-next/src/createNextSynthqlHandler.test.ts (1 hunks)
  • packages/handler-next/src/createNextSynthqlHandler.ts (5 hunks)
  • packages/queries/src/index.ts (1 hunks)
  • packages/queries/src/types/QueryParameter.ts (1 hunks)
  • packages/queries/src/types/QueryRequest.ts (1 hunks)
  • packages/queries/src/validators/isQueryParameter.ts (1 hunks)
  • packages/queries/src/validators/isRegisteredQuery.ts (1 hunks)
  • packages/queries/src/validators/isRegularQuery.ts (1 hunks)
  • packages/react/src/createBody.ts (1 hunks)
  • packages/react/src/useSynthql.ts (2 hunks)
  • packages/react/src/useSynthqlExamples.test.tsx (1 hunks)
Files skipped from review due to trivial changes (1)
  • packages/handler-next/src/createNextSynthqlHandler.test.ts
Files skipped from review as they are similar to previous changes (5)
  • packages/docs/static/reference/assets/navigation.js
  • packages/docs/static/reference/assets/search.js
  • packages/queries/src/index.ts
  • packages/queries/src/types/QueryParameter.ts
  • packages/queries/src/types/QueryRequest.ts
Additional comments not posted (12)
packages/queries/src/validators/isQueryParameter.ts (1)

3-5: LGTM!

The isQueryParameter function is a well-implemented type guard that enhances type safety and helps prevent runtime errors. The logic is correct, and the use of optional chaining is a good practice to safely access the type property.

The function signature correctly uses the x is QueryParameter return type to enable type narrowing when the function returns true, which can improve the overall reliability of the application by ensuring that only valid query parameters are processed.

packages/queries/src/validators/isRegularQuery.ts (1)

3-5: LGTM!

The isRegularQueryRequest function is a well-implemented type guard that enhances type safety and provides a reusable way to validate if an input is a RegularQueryRequest. The function correctly combines multiple conditions using the && operator and safely accesses the type property of x using the optional chaining operator. The function signature correctly uses the x is RegularQueryRequest return type to indicate that it is a type guard.

packages/queries/src/validators/isRegisteredQuery.ts (1)

3-5: Great use of a type guard function to enhance type safety!

The isRegisteredQueryRequest function is a well-implemented type guard that validates if the input x conforms to the RegisteredQueryRequest type. It correctly checks for null and undefined values before accessing the type property of x using the optional chaining operator ?., which is a good practice to avoid potential runtime errors.

By comparing the type property of x with the RegisteredQuery constant, the function ensures that only valid query requests are processed further in the application. This is crucial for maintaining type safety and preventing errors associated with invalid data structures.

The use of a type guard function allows TypeScript to infer the type of x as RegisteredQueryRequest when the function returns true, providing better type information and enabling more accurate type checking in the code that uses this function.

Overall, this is a great addition to the codebase that enhances type safety and improves the reliability of the application.

packages/react/src/useSynthql.ts (1)

6-6: Excellent encapsulation of body creation logic!

The introduction of the createBody function and its usage to construct the request body is a great improvement. It enhances maintainability and readability by centralizing the logic for body creation. This change also allows for more flexibility in case complex body structures or additional processing is required in the future.

Also applies to: 38-38

packages/react/src/useSynthqlExamples.test.tsx (1)

14-14: Verify the intentional change in the request object structure.

The change in accessing the where clause from req.where?.id.in to req.query.where?.id.in suggests a shift in the expected structure of the request object.

Please confirm if this change is intentional and aligns with the expected behavior of the createEchoServer function. Also, consider the potential impact on the filtering logic applied to the incoming data.

To verify the usage of the req.query.where property across the codebase, run the following script:

Verification successful

Verified: Change in request object structure is intentional and localized

The modification from req.where?.id.in to req.query.where?.id.in appears to be an intentional and isolated change. This alteration is consistent throughout the codebase, with no other occurrences of the old req.where structure found.

Key observations:

  • The change is localized to the test file packages/react/src/useSynthqlExamples.test.tsx.
  • No other instances of req.where were found in the codebase.

Given that this change is in a test file, it likely reflects an update in the API or request structure being tested. The localized nature of the change suggests it doesn't impact the broader codebase.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of `req.query.where` property.

# Test: Search for the usage of `req.query.where`. 
# Expect: Consistent usage across the codebase.
rg --type typescript $'req\.query\.where'

Length of output: 77


Script:

#!/bin/bash
# Description: Verify the usage of `req.query.where` property in TypeScript and TSX files.

# Find all .ts and .tsx files and search for 'req.query.where'
fd -e ts -e tsx | xargs rg -n -C 2 'req\.query\.where'

# Additionally, search for 'req.where' to compare usage
echo "Searching for 'req.where':"
fd -e ts -e tsx | xargs rg -n -C 2 'req\.where'

Length of output: 661

packages/handler-express/src/createExpressSynthqlHandler.ts (1)

118-127: Implementation of tryExecuteRegisteredQuery looks good

The new tryExecuteRegisteredQuery function correctly calls queryEngine.executeRegisteredQuery with the appropriate parameters. This addition enhances the handling of registered queries.

packages/handler-next/src/createNextSynthqlHandler.ts (5)

3-6: Import statements are correct and necessary

The new imports of isRegisteredQueryRequest and isRegularQueryRequest are necessary for handling the differentiation between registered and regular query requests.


70-70: Refactored request parsing for clarity

The usage of tryParseRequest to destructure { body, headers } improves code readability and isolates request parsing logic.


76-92: Appropriate differentiation between registered and regular queries

The updated logic correctly distinguishes between registered queries and regular queries using isRegisteredQueryRequest(body) and isRegularQueryRequest(body). This enhances the flexibility of request handling.


97-101: Function call updated to use writeResponseBody

The function writeBody has been renamed to writeResponseBody, and the call has been updated accordingly. This improves clarity regarding the function's purpose.


132-141: New function tryExecuteRegisteredQuery added correctly

The tryExecuteRegisteredQuery function is appropriately defined to handle registered queries, delegating execution to queryEngine.executeRegisteredQuery.

packages/react/src/createBody.ts (1)

11-28: Function implementation is robust and well-structured

The createBody function effectively constructs a QueryRequest based on the provided AnyQuery. It correctly handles parameter extraction and necessary error checks.

Also applies to: 30-56

…rty tests

Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.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: 4

Outside diff range and nitpick comments (11)
packages/backend/src/tests/propertyBased/arbitraries/arbitraryWhere.ts (2)

12-12: LGTM! Consider updating documentation.

The addition of the parameterize parameter aligns well with the PR objectives of adding support for parameterized queries. This boolean parameter provides a clear way to toggle query parameterization.

Consider updating the function's JSDoc comments (if they exist) to include information about this new parameter and its purpose.

Also applies to: 18-18


checkIfDateTimeColumn function still exists in the codebase

The checkIfDateTimeColumn function was not fully removed and is still defined in packages/backend/src/tests/propertyBased/checkIfDateTimeColumn.ts. Please ensure that the removal of date-time column filtering logic is complete and that the function is no longer necessary.

Analysis chain

Line range hint 20-38: Verify removal of date-time column filtering logic.

The AI-generated summary mentions the removal of date-time column filtering logic using the checkIfDateTimeColumn function. However, this change is not visible in the provided code snippet. We need to verify if this change was actually made and if it's intentional.

Let's check for any remaining usage of checkIfDateTimeColumn in this file:

If the function is indeed removed, we should also verify that this removal doesn't negatively impact the handling of date-time columns in where clauses.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining usage of checkIfDateTimeColumn in the file

rg --type typescript 'checkIfDateTimeColumn' packages/backend/src/tests/propertyBased/arbitraries/arbitraryWhere.ts

Length of output: 150


Script:

#!/bin/bash
# Description: Check for any remaining usage of checkIfDateTimeColumn in the specified file

rg 'checkIfDateTimeColumn' packages/backend/src/tests/propertyBased/arbitraries/arbitraryWhere.ts

Length of output: 97


Script:

#!/bin/bash
# Description: Check for any remaining usage of checkIfDateTimeColumn across the entire codebase

rg 'checkIfDateTimeColumn'

Length of output: 136

packages/backend/src/tests/propertyBased/properties/cardinalityMaybe.test.ts (3)

18-23: Good addition of parameterized query test.

The introduction of validAndParameterizedWhereArbitraryQuery is a valuable addition to the test suite. It allows for testing of valid parameterized queries, which increases the coverage and robustness of the tests.

Consider extracting the common configuration options into a separate object to reduce duplication:

const baseQueryConfig = {
  schema,
  allTablesRowsMap: await getTableRowsByTableName<DB>(pool, schema),
  cardinality: 'maybe',
  validWhere: true,
};

const validWhereArbitraryQuery = arbitraryQuery<DB>({
  ...baseQueryConfig,
  parameterize: false,
});

const validAndParameterizedWhereArbitraryQuery = arbitraryQuery<DB>({
  ...baseQueryConfig,
  parameterize: true,
});

This approach would make it easier to maintain and update the configurations in the future.


34-40: Good addition of invalid parameterized query test.

The introduction of invalidAndParameterizedWhereArbitraryQuery is a valuable addition to the test suite. It allows for testing of invalid parameterized queries, which increases the coverage and robustness of the tests.

Similar to the suggestion for the valid queries, consider extracting the common configuration options into a separate object to reduce duplication:

const baseInvalidQueryConfig = {
  schema,
  allTablesRowsMap: await getTableRowsByTableName<DB>(pool, schema),
  cardinality: 'maybe',
  validWhere: false,
};

const invalidWhereArbitraryQuery = arbitraryQuery<DB>({
  ...baseInvalidQueryConfig,
  parameterize: false,
});

const invalidAndParameterizedWhereArbitraryQuery = arbitraryQuery<DB>({
  ...baseInvalidQueryConfig,
  parameterize: true,
});

This approach would make it easier to maintain and update the configurations in the future.


Clarification Needed on Skipped Test in cardinalityMaybe.test.ts

The skipped test it.skip.prop in cardinalityMaybe.test.ts does not have a TODO comment explaining the reason for skipping. It's important to document why this test is skipped to maintain clarity and ensure it is addressed in the future.

  • Action Required: Please add a TODO comment or reference an existing issue that explains why the test is skipped and what needs to be done to re-enable it.
Analysis chain

Line range hint 42-84: Good update to include parameterized queries in tests, but clarification needed on skipped test.

The changes to incorporate both parameterized and non-parameterized queries in the test cases are well-implemented. This update provides more comprehensive coverage of the cardinalityMaybe functionality.

The structure and assertions of the tests remain consistent, which is good for maintaining the integrity of the test suite.

However, the invalid query test has been skipped using it.skip.prop. Could you please clarify why this test is being skipped? Is it temporary, or are there known issues with invalid parameterized queries that need to be addressed?

To investigate this further, let's check for any related TODO comments or issues:

If this is a temporary measure, consider adding a TODO comment explaining why the test is skipped and when it should be re-enabled.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for TODO comments related to skipped tests or invalid queries
rg --type typescript "TODO.*skip.*test|TODO.*invalid.*quer" packages/backend/src/tests

Length of output: 123


Script:

#!/bin/bash
# Search for TODO comments related to skipped tests or invalid queries in TypeScript files
rg --glob '*.ts' 'TODO.*skip.*test|TODO.*invalid.*quer' packages/backend/src/tests

Length of output: 193


Script:

#!/bin/bash
# Search for TODO comments near the skipped test in cardinalityMaybe.test.ts
rg 'it\.skip\.prop' packages/backend/src/tests/propertyBased/properties/cardinalityMaybe.test.ts -A 2

Length of output: 171

packages/backend/src/tests/propertyBased/properties/cardinalityMany.test.ts (2)

18-23: LGTM: Good addition of parameterized query generator.

The introduction of validAndParameterizedWhereArbitraryQuery is a valuable addition to the test suite. It allows testing of parameterized queries with valid where clauses, which is crucial for ensuring the system handles both parameterized and non-parameterized queries correctly.

Consider extracting the common configuration options into a separate object to reduce duplication and improve maintainability. For example:

const baseQueryConfig = {
  schema,
  allTablesRowsMap: await getTableRowsByTableName<DB>(pool, schema),
  cardinality: 'many',
  validWhere: true,
};

const validWhereArbitraryQuery = arbitraryQuery<DB>({
  ...baseQueryConfig,
  parameterize: false,
});

const validAndParameterizedWhereArbitraryQuery = arbitraryQuery<DB>({
  ...baseQueryConfig,
  parameterize: true,
});

This approach would make it easier to maintain consistent configurations across different query generators.


34-39: LGTM: Comprehensive coverage with parameterized invalid query generator.

The introduction of invalidAndParameterizedWhereArbitraryQuery completes the set of query generators, providing full coverage for both valid and invalid queries in parameterized and non-parameterized forms. This is excellent for ensuring robust testing of the query engine.

As suggested earlier, consider extracting common configuration options to reduce duplication. This applies to both valid and invalid query generators:

const baseQueryConfig = {
  schema,
  allTablesRowsMap: await getTableRowsByTableName<DB>(pool, schema),
  cardinality: 'many',
};

const invalidWhereArbitraryQuery = arbitraryQuery<DB>({
  ...baseQueryConfig,
  validWhere: false,
  parameterize: false,
});

const invalidAndParameterizedWhereArbitraryQuery = arbitraryQuery<DB>({
  ...baseQueryConfig,
  validWhere: false,
  parameterize: true,
});

This approach would make the configurations more maintainable and reduce the risk of inconsistencies.

packages/backend/src/tests/propertyBased/properties/cardinalityOne.test.ts (1)

43-46: Efficient test case update for both query types.

Great job on updating the it.prop test case to include both validWhereArbitraryQuery and validAndParameterizedWhereArbitraryQuery. This efficiently tests both parameterized and non-parameterized valid queries in a single test case, reducing code duplication.

For improved readability, consider using an array variable to store the query types:

const validQueries = [validWhereArbitraryQuery, validAndParameterizedWhereArbitraryQuery];
it.prop(validQueries, { verbose: 2 })(
  // ... rest of the test case
);

This makes the test structure clearer and easier to maintain if more query types are added in the future.

packages/backend/src/tests/propertyBased/arbitraries/arbitraryWhereValue.ts (3)

14-21: Consider adding documentation for the 'parameterize' parameter

The addition of the parameterize boolean parameter affects the behavior of the arbitraryWhereValue function by wrapping generated values with param() when true. Adding documentation or comments to explain this parameter can improve code readability and maintainability.


Line range hint 51-54: Address incomplete matching arms and correct typographical error

The comments indicate that the matching arms are presently incomplete, and more information is needed in the schema to enhance them. Additionally, there is a typographical error: "infomration" should be "information".

Would you like assistance in updating the schema to include the necessary information for completing the matching arms? This could improve the functionality and robustness of the code.


Line range hint 13-118: Add unit tests for the new 'parameterize' functionality

The new parameterize parameter modifies the behavior of the arbitraryWhereValue function. It's important to add unit tests to cover scenarios where parameterize is both true and false, ensuring that values are correctly wrapped with param() when required.

Do you need assistance in writing these unit tests, or would you like me to open a new GitHub issue to track this task?

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between d3030dd and 2cc7f6a.

Files selected for processing (9)
  • packages/backend/src/QueryEngine.ts (8 hunks)
  • packages/backend/src/QueryStore.ts (1 hunks)
  • packages/backend/src/tests/propertyBased/arbitraries/arbitraryQuery.ts (2 hunks)
  • packages/backend/src/tests/propertyBased/arbitraries/arbitraryWhere.ts (2 hunks)
  • packages/backend/src/tests/propertyBased/arbitraries/arbitraryWhereValue.ts (4 hunks)
  • packages/backend/src/tests/propertyBased/properties/cardinalityMany.test.ts (1 hunks)
  • packages/backend/src/tests/propertyBased/properties/cardinalityMaybe.test.ts (2 hunks)
  • packages/backend/src/tests/propertyBased/properties/cardinalityOne.test.ts (2 hunks)
  • packages/docs/static/reference/assets/search.js (1 hunks)
Files skipped from review as they are similar to previous changes (2)
  • packages/backend/src/QueryEngine.ts
  • packages/docs/static/reference/assets/search.js
Additional comments not posted (19)
packages/backend/src/tests/propertyBased/arbitraries/arbitraryWhere.ts (1)

31-31: LGTM! Parameterization properly propagated.

The parameterize argument is correctly passed to the arbitraryWhereValue function, ensuring that the parameterization option is propagated through the arbitrary generation process.

packages/backend/src/tests/propertyBased/arbitraries/arbitraryQuery.ts (3)

16-16: LGTM: New property aligns with PR objectives.

The addition of the parameterize: boolean property to the ArbitraryQuery interface is a good enhancement. It aligns well with the PR's objective of introducing support for parameterized queries. This boolean flag will allow for flexible control over query parameterization during arbitrary query generation.


24-24: LGTM: Function signature updated consistently.

The addition of the parameterize parameter to the arbitraryQuery function's destructured parameter list is correct and consistent with the interface update. This change ensures that the function can now accept and utilize the new parameterization option.


16-16: Summary: Consistent implementation of parameterize option

The changes in this file consistently implement the new parameterize option across the ArbitraryQuery interface, arbitraryQuery function signature, and the arbitraryWhere function call. These modifications align well with the PR objectives of supporting parameterized queries and enhance the flexibility of the arbitrary query generation process.

The implementation appears to be well-structured and consistent. However, to ensure completeness, it would be beneficial to review the implementation of the arbitraryWhere function to verify how it utilizes the new parameterize option.

Also applies to: 24-24, 41-41

packages/backend/src/QueryStore.ts (5)

1-7: LGTM: Imports are appropriate and concise.

The imports are well-organized and relevant to the functionality of the QueryStore class. All imported items are used within the file, and there are no unnecessary imports.


8-8: LGTM: QueryFunction type is well-defined.

The QueryFunction type is concisely defined and appropriate for its use in the QueryStore class. The use of unknown for parameters allows for flexibility in query function definitions while maintaining type safety.


13-15: LGTM: Constructor is concise and correct.

The constructor properly initializes the private queries Map, which is essential for the class's functionality.


63-65: LGTM: has method is simple and effective.

The has method provides a clear and concise way to check for the existence of a query in the store. It correctly utilizes the Map's built-in has method, making it efficient and easy to understand.


1-89: Overall, the QueryStore implementation is well-structured and functional.

The QueryStore class provides a solid foundation for managing parameterized queries. It effectively handles query storage, retrieval, and parameterization. The code is well-organized and follows good practices.

However, there are opportunities for improvement:

  1. Enhance error handling with more specific error types and detailed messages.
  2. Implement stricter type checking and validation, especially in the get and set methods.
  3. Consider adding more comprehensive documentation, including examples of usage.

These enhancements will further improve the robustness and maintainability of the QueryStore class.

packages/backend/src/tests/propertyBased/properties/cardinalityMaybe.test.ts (2)

15-16: LGTM: Explicit parameterization setting for existing query.

The addition of parameterize: false to the validWhereArbitraryQuery configuration is a good practice. It explicitly states the intended behavior for this test case, making the code more self-documenting and preparing for the introduction of parameterized queries.


31-31: LGTM: Consistent parameterization setting for invalid query.

The addition of parameterize: false to the invalidWhereArbitraryQuery configuration is consistent with the changes made to the valid query configuration. This explicit setting enhances code clarity and maintains consistency across the test cases.

packages/backend/src/tests/propertyBased/properties/cardinalityMany.test.ts (3)

15-16: LGTM: Explicit parameterization setting for clarity.

The addition of parameterize: false to the validWhereArbitraryQuery configuration is a good practice. It explicitly states that this query is not parameterized, which enhances code clarity and maintains consistency with the newly introduced parameterized query.


31-32: LGTM: Consistent parameterization setting for invalid queries.

The addition of parameterize: false to the invalidWhereArbitraryQuery configuration is consistent with the earlier change to validWhereArbitraryQuery. This explicit setting enhances code clarity and maintains consistency across the test suite.


42-85: LGTM for valid query test, but concern about skipped invalid query test.

The updates to the test cases to include both parameterized and non-parameterized queries are excellent. This provides comprehensive coverage and ensures that both query types behave as expected.

The changes to the valid query test (lines 42-67) look good. The test now checks both validWhereArbitraryQuery and validAndParameterizedWhereArbitraryQuery, which is crucial for ensuring consistent behavior across query types.

However, the invalid query test (lines 69-85) is currently skipped. This could potentially leave issues with invalid parameterized queries undetected. Can you provide more context on why this test is skipped? If it's due to a known issue or ongoing work, consider adding a TODO comment explaining the reason and tracking the issue.

To investigate further, let's check if there are any related issues or comments:

This will help us understand if there's an ongoing discussion or known issues related to the skipped test.

packages/backend/src/tests/propertyBased/properties/cardinalityOne.test.ts (5)

16-17: LGTM: Explicit non-parameterized query configuration.

The addition of parameterize: false clearly specifies that this query should not be parameterized. This explicit configuration enhances code readability and prevents potential misunderstandings.


19-24: Excellent addition: Parameterized query for comprehensive testing.

The introduction of validAndParameterizedWhereArbitraryQuery with parameterize: true is a valuable addition. This allows for testing both parameterized and non-parameterized queries, significantly improving the test coverage and ensuring the system handles both types correctly.


32-33: LGTM: Consistent non-parameterized configuration for invalid queries.

The addition of parameterize: false to invalidWhereArbitraryQuery maintains consistency with the valid query configuration. This explicit setting ensures clarity in test scenarios and prevents potential confusion.


35-40: Great addition: Complete test coverage with parameterized invalid queries.

The introduction of invalidAndParameterizedWhereArbitraryQuery with parameterize: true completes the set of test scenarios. This ensures comprehensive coverage of all combinations: valid/invalid and parameterized/non-parameterized queries. This thorough approach significantly enhances the robustness of the test suite.


73-79: Comprehensive test case update for invalid queries, but why skipped?

Excellent update to the it.skip.prop test case to include both invalidWhereArbitraryQuery and invalidAndParameterizedWhereArbitraryQuery. This efficiently tests both parameterized and non-parameterized invalid queries in a single test case, reducing code duplication.

For improved readability, consider using an array variable to store the query types:

const invalidQueries = [invalidWhereArbitraryQuery, invalidAndParameterizedWhereArbitraryQuery];
it.skip.prop(invalidQueries, { verbose: 2 })(
  // ... rest of the test case
);

This makes the test structure clearer and easier to maintain if more query types are added in the future.

The test is currently skipped (it.skip.prop). Is this intentional? If so, it might be helpful to add a comment explaining why it's skipped and when it should be unskipped. If not, consider removing the .skip to ensure these tests are being run.

Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.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

Outside diff range and nitpick comments (1)
packages/backend/src/SynthqlError.ts (1)

209-220: LGTM: Improved SQL execution error handling

The changes to the createSqlExecutionError method are well-implemented. The use of SqlExecutionErrorProps and the separate composeMessage function improves flexibility and maintainability.

Consider adding a brief comment explaining the purpose of the SqlExecutionErrorProps interface for better documentation.

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 2cc7f6a and d6eada0.

Files selected for processing (5)
  • packages/backend/src/QueryEngine.ts (8 hunks)
  • packages/backend/src/QueryStore.ts (1 hunks)
  • packages/backend/src/SynthqlError.ts (6 hunks)
  • packages/backend/src/tests/propertyBased/arbitraries/arbitraryWhereValue.ts (5 hunks)
  • packages/docs/static/reference/assets/search.js (1 hunks)
Files skipped from review as they are similar to previous changes (4)
  • packages/backend/src/QueryEngine.ts
  • packages/backend/src/QueryStore.ts
  • packages/backend/src/tests/propertyBased/arbitraries/arbitraryWhereValue.ts
  • packages/docs/static/reference/assets/search.js
Additional comments not posted (6)
packages/backend/src/SynthqlError.ts (6)

22-35: LGTM: Well-structured cardinality error handling

The createCardinalityError method is a valuable addition. It provides clear error messages and a helpful hint for developers, which can significantly improve debugging experience.


47-50: LGTM: Improved error message clarity

The changes to the createDatabaseConnectionError method enhance the clarity of the error message. The new wording provides more specific guidance to users encountering database connection issues.


104-117: LGTM: Helpful error handling for duplicate query registration

The createQueryAlreadyRegisteredError method is a valuable addition. It provides a clear error message when attempting to register a query with an ID that already exists in the query store.


119-136: LGTM: Comprehensive error handling for queries missing hash

The createQueryMissingHashError method is well-implemented. It provides a detailed error message that includes the query object and explains the importance of the hash property for query registration.


138-154: LGTM: Clear error handling for unregistered queries

The createQueryNotRegisteredError method is a valuable addition. It provides a clear error message when a query is not found in the query store and offers guidance on checking the correct queryId.


156-182: LGTM: Detailed error handling for missing query parameters

The createQueryParameterMissingValueError method is well-implemented. It provides a comprehensive error message that includes both the missing parameter IDs and the provided params object, which is extremely helpful for debugging parameter-related issues.

Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.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

🧹 Outside diff range and nitpick comments (5)
packages/queries/src/validators/isRegularQueryRequest.ts (1)

3-5: LGTM: Well-implemented type guard function with a minor suggestion.

The isRegularQueryRequest function is a well-implemented type guard. It correctly checks for null and undefined, uses optional chaining, and compares the type property with the RegularQuery constant.

Consider adding an additional check to ensure x is an object before accessing its properties. This would make the function more robust:

export function isRegularQueryRequest(x: any): x is RegularQueryRequest {
    return x !== null && x !== undefined && typeof x === 'object' && x.type === RegularQuery;
}

This change ensures that x is an object before attempting to access its type property, providing an extra layer of type safety.

packages/queries/src/validators/isRegisteredQueryRequest.ts (1)

3-5: LGTM: Well-implemented type guard with room for potential enhancement.

The isRegisteredQueryRequest function is correctly implemented as a type guard. It properly checks for null and undefined values, and uses optional chaining for safe property access. The check against the RegisteredQuery type is correct.

Consider enhancing the type guard to check for other required properties of RegisteredQueryRequest, if any exist. This would make the type guard more robust. For example:

export function isRegisteredQueryRequest(x: any): x is RegisteredQueryRequest {
    return (
        x !== null &&
        x !== undefined &&
        x?.type === RegisteredQuery &&
        typeof x.queryId === 'string' &&
        // Add other necessary property checks here
    );
}

This suggestion assumes that queryId is a required property of RegisteredQueryRequest. Adjust the properties checked based on the actual definition of RegisteredQueryRequest.

packages/backend/src/execution/executors/PgExecutor/queryBuilder/exp.ts (3)

Line range hint 104-121: LGTM: Enhanced compileExp function with new operators and string handling.

The additions improve the function's flexibility and query capabilities, aligning with the PR objectives.

Consider adding a comment explaining the purpose of the new '= any' and 'not = any' operators for better code documentation.


264-266: TODO noted for alias validation in addAs method.

The TODO comment for alias validation indicates awareness of potential issues.

Would you like me to create a GitHub issue to track the implementation of alias validation in the addAs method?


460-495: LGTM: Added handling for query parameters in expressionFromWhere method.

The addition of query parameter handling directly addresses the PR objectives. The implementation includes proper type checking and error handling, and the code is well-structured, following existing patterns in the class.

For consistency, consider extracting the repeated code for creating the exp object into a separate function, as it's used in both the isQueryParameter(op) and isQueryParameter(value) blocks.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between d6eada0 and a41c1e0.

📒 Files selected for processing (14)
  • packages/backend/src/QueryEngine.test.ts (1 hunks)
  • packages/backend/src/QueryEngine.ts (9 hunks)
  • packages/backend/src/QueryStore.ts (1 hunks)
  • packages/backend/src/execution/executors/PgExecutor/queryBuilder/exp.ts (14 hunks)
  • packages/docs/docs/200-security.md (2 hunks)
  • packages/docs/static/reference/assets/navigation.js (1 hunks)
  • packages/docs/static/reference/assets/search.js (1 hunks)
  • packages/handler-express/src/createExpressSynthqlHandler.ts (5 hunks)
  • packages/handler-next/src/createNextSynthqlHandler.ts (5 hunks)
  • packages/queries/src/index.ts (1 hunks)
  • packages/queries/src/types/QueryRequest.ts (1 hunks)
  • packages/queries/src/util/iterateRecursively.ts (1 hunks)
  • packages/queries/src/validators/isRegisteredQueryRequest.ts (1 hunks)
  • packages/queries/src/validators/isRegularQueryRequest.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (11)
  • packages/backend/src/QueryEngine.test.ts
  • packages/backend/src/QueryEngine.ts
  • packages/backend/src/QueryStore.ts
  • packages/docs/docs/200-security.md
  • packages/docs/static/reference/assets/navigation.js
  • packages/docs/static/reference/assets/search.js
  • packages/handler-express/src/createExpressSynthqlHandler.ts
  • packages/handler-next/src/createNextSynthqlHandler.ts
  • packages/queries/src/index.ts
  • packages/queries/src/types/QueryRequest.ts
  • packages/queries/src/util/iterateRecursively.ts
🔇 Additional comments (8)
packages/queries/src/validators/isRegularQueryRequest.ts (2)

1-1: LGTM: Import statement is correct and follows best practices.

The import statement correctly imports the necessary types from a separate file, which is good for code organization and maintainability.


1-5: Overall, the implementation is solid and follows TypeScript best practices.

This new file introduces a well-implemented type guard function for RegularQueryRequest. It's concise, focused, and achieves its purpose effectively. The suggested minor improvement to check if x is an object would further enhance its robustness, but the current implementation is already good.

packages/queries/src/validators/isRegisteredQueryRequest.ts (1)

1-1: LGTM: Import statement is correct and follows good practices.

The import statement correctly imports the necessary types RegisteredQuery and RegisteredQueryRequest from a separate file. This follows good practices for code organization and type management.

packages/backend/src/execution/executors/PgExecutor/queryBuilder/exp.ts (5)

1-1: LGTM: Import of isQueryParameter added.

The addition of isQueryParameter import aligns with the PR objectives to support parameterized queries.


Line range hint 183-192: LGTM: Enhanced addConst method with array handling.

The addition of array handling in the addConst method improves its capability to handle complex constant values, aligning with the PR objectives for more dynamic query construction.


226-236: LGTM: Refactored addInterleaved method for better readability.

The use of flatMap in the addInterleaved method improves code readability and potentially performance. While not directly related to the PR objectives, this change enhances the overall quality of the codebase.


242-246: LGTM: Added error handling for invalid operators in addOperator method.

The addition of error handling for invalid operators improves the robustness of the addOperator method, aligning with the PR objectives to enhance error handling.


311-323: LGTM: Refactored space method for better handling of different scenarios.

The refactoring of the space method improves its ability to handle different cases. While not directly related to the PR objectives, this change enhances the overall quality and robustness of the codebase.

async function tryExecuteRegisteredQuery<DB>(
queryEngine: QueryEngine<DB>,
{ queryId, params }: { queryId: string; params: Record<string, unknown> },
queryOrBody: any,
Copy link
Collaborator

Choose a reason for hiding this comment

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

unknown!!!!!!!

},
);
} else if (isRegularQueryRequest(queryOrBody)) {
return queryEngine.execute(queryOrBody.query as Query<DB>, {
Copy link
Collaborator

Choose a reason for hiding this comment

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

this cast shouldn't be needed: you should move the cast into isRegularQueryRequest

params: Record<string, unknown>;
}

export interface RegisteredQueryRequest {
Copy link
Collaborator

Choose a reason for hiding this comment

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

why do you need RegisteredQueryRequest and RegisteredQueryRequestBody?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

RegisteredQueryRequestBody is used to type executeRegisteredQuery()

returnLastOnly,
},
);
} else if (isRegularQueryRequest(queryOrBody)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

These last two branches are doing the same... something seems weird here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not exactly... the else if branch is matching RegisteredQueryRequests with the shape:

{
    type: typeof RegisteredQuery;
    queryId: string;
    params: Record<string, unknown>;
}

, while the else branch is just matching AnyQuery

Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.com>
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