Skip to content

Conversation

@feeblefakie
Copy link
Contributor

This is an automated backport of the following:

Please merge this PR after all checks have passed.

Co-authored-by: Josh Wong <joshua.wong@scalar-labs.com>
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @feeblefakie, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request is an automated backport that introduces a PartiQL parser to the system, enabling it to understand and process CREATE TABLE and INSERT statements. It establishes a new dedicated module for this parsing capability, integrates the PartiQL library, and defines the necessary structures to convert parsed SQL into executable contract statements, complete with robust error handling and comprehensive unit tests.

Highlights

  • New table-store Module: A new table-store module has been introduced to encapsulate the PartiQL parsing logic and related functionalities, including its own build configuration and dependencies.
  • PartiQL Parser Integration: The pull request integrates the PartiQL library and implements a custom parser (ScalarPartiqlParser and PartiqlParserVisitor) specifically designed to interpret and process CREATE TABLE and INSERT statements.
  • Statement Conversion to Contracts: The newly implemented parser converts parsed PartiQL CREATE TABLE and INSERT statements into internal ContractStatement objects. These objects are then used to generate the necessary arguments for the respective table.v1_0_0.Create and table.v1_0_0.Insert contracts, facilitating interaction with the underlying ledger.
  • Enhanced Error Handling for Parsing: New error types have been defined within TableStoreClientError to provide more specific and detailed feedback for various PartiQL syntax and semantic parsing issues, improving diagnostic capabilities.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request introduces PartiQL parser functionality for creating tables and inserting data. The changes include adding dependencies, defining data types, implementing parser logic, and creating statement classes. The code also includes error handling and tests to ensure the functionality works as expected.

Comment on lines +10 to +11
public static final String CONTRACT_CREATE = PACKAGE + "." + VERSION + ".Create";
public static final String CONTRACT_INSERT = PACKAGE + "." + VERSION + ".Insert";

Choose a reason for hiding this comment

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

medium

It is recommended to maintain consistency in the order of declarations. Consider placing CONTRACT_CREATE and CONTRACT_INSERT after CONTRACT_GET_ASSET_ID and CONTRACT_SCAN to maintain alphabetical order.

Suggested change
public static final String CONTRACT_CREATE = PACKAGE + "." + VERSION + ".Create";
public static final String CONTRACT_INSERT = PACKAGE + "." + VERSION + ".Insert";
public static final String CONTRACT_GET_ASSET_ID = PACKAGE + "." + VERSION + ".GetAssetId";
public static final String CONTRACT_SCAN = PACKAGE + "." + VERSION + ".Scan";
public static final String CONTRACT_CREATE = PACKAGE + "." + VERSION + ".Create";
public static final String CONTRACT_INSERT = PACKAGE + "." + VERSION + ".Insert";

Comment on lines +64 to +66
if (primaryKey != null) {
throw new IllegalArgumentException(
TableStoreClientError.SYNTAX_ERROR_INVALID_PRIMARY_KEY_SPECIFICATION.buildMessage());

Choose a reason for hiding this comment

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

medium

The exception message is built but not logged. Consider logging the exception message for debugging purposes.

Suggested change
if (primaryKey != null) {
throw new IllegalArgumentException(
TableStoreClientError.SYNTAX_ERROR_INVALID_PRIMARY_KEY_SPECIFICATION.buildMessage());
if (primaryKey != null) {
String message = TableStoreClientError.SYNTAX_ERROR_INVALID_PRIMARY_KEY_SPECIFICATION.buildMessage();
// Log the message here
throw new IllegalArgumentException(message);
}

Comment on lines +70 to +72
} else {
throw new IllegalArgumentException(
TableStoreClientError.SYNTAX_ERROR_INVALID_COLUMN_CONSTRAINTS.buildMessage());

Choose a reason for hiding this comment

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

medium

The exception message is built but not logged. Consider logging the exception message for debugging purposes.

      } else {
        String message = TableStoreClientError.SYNTAX_ERROR_INVALID_COLUMN_CONSTRAINTS.buildMessage();
        // Log the message here
        throw new IllegalArgumentException(message);
      }

Comment on lines +76 to +78
if (primaryKey == null) {
throw new IllegalArgumentException(
TableStoreClientError.SYNTAX_ERROR_INVALID_PRIMARY_KEY_SPECIFICATION.buildMessage());

Choose a reason for hiding this comment

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

medium

The exception message is built but not logged. Consider logging the exception message for debugging purposes.

    if (primaryKey == null) {
      String message = TableStoreClientError.SYNTAX_ERROR_INVALID_PRIMARY_KEY_SPECIFICATION.buildMessage();
      // Log the message here
      throw new IllegalArgumentException(message);
    }

Comment on lines +90 to +91
throw new IllegalArgumentException(
TableStoreClientError.SYNTAX_ERROR_INVALID_INSERT_STATEMENT.buildMessage());

Choose a reason for hiding this comment

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

medium

The exception message is built but not logged. Consider logging the exception message for debugging purposes.

    if (astNode.getAsAlias() != null || astNode.getOnConflict() != null) {
      String message = TableStoreClientError.SYNTAX_ERROR_INVALID_INSERT_STATEMENT.buildMessage();
      // Log the message here
      throw new IllegalArgumentException(message);
    }

Comment on lines +178 to +179
throw new IllegalArgumentException(
TableStoreClientError.SYNTAX_ERROR_INVALID_LITERAL.buildMessage(toSql(literal)));

Choose a reason for hiding this comment

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

medium

The exception message is built but not logged. Consider logging the exception message for debugging purposes.

      String message = TableStoreClientError.SYNTAX_ERROR_INVALID_LITERAL.buildMessage(toSql(literal));
      // Log the message here
      throw new IllegalArgumentException(message);

Comment on lines +193 to +194
throw new IllegalArgumentException(
TableStoreClientError.SYNTAX_ERROR_INVALID_EXPRESSION.buildMessage(toSql(expr)));

Choose a reason for hiding this comment

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

medium

The exception message is built but not logged. Consider logging the exception message for debugging purposes.

        String message = TableStoreClientError.SYNTAX_ERROR_INVALID_EXPRESSION.buildMessage(toSql(expr));
        // Log the message here
        throw new IllegalArgumentException(message);

Comment on lines +216 to +217
throw new IllegalArgumentException(
TableStoreClientError.SYNTAX_ERROR_INVALID_EXPRESSION.buildMessage(toSql(expr)));

Choose a reason for hiding this comment

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

medium

The exception message is built but not logged. Consider logging the exception message for debugging purposes.

        String message = TableStoreClientError.SYNTAX_ERROR_INVALID_EXPRESSION.buildMessage(toSql(expr));
        // Log the message here
        throw new IllegalArgumentException(message);

Comment on lines +21 to +23
Throwable cause = error.get("CAUSE", Throwable.class);
if (cause instanceof IllegalArgumentException) {
throw (IllegalArgumentException) cause;

Choose a reason for hiding this comment

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

medium

Catching Throwable and re-throwing IllegalArgumentException might hide other potential exceptions. Consider catching IllegalArgumentException directly.

      error -> {
        if (error.get("CAUSE", Throwable.class) instanceof IllegalArgumentException) {
          throw (IllegalArgumentException) error.get("CAUSE", Throwable.class);
        } else if (error.severity.code() == Severity.ERROR

Comment on lines +21 to +24
Throwable cause = error.get("CAUSE", Throwable.class);
if (cause instanceof IllegalArgumentException) {
throw (IllegalArgumentException) cause;
} else if (error.severity.code() == Severity.ERROR

Choose a reason for hiding this comment

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

medium

It's generally not recommended to catch a Throwable because it also catches Error types, which are typically unrecoverable. Consider catching only Exception or, more specifically, IllegalArgumentException.

      error -> {
        Throwable cause = error.get("CAUSE", Throwable.class);
        if (cause instanceof IllegalArgumentException) {
          throw (IllegalArgumentException) cause;
        } else if (error.severity.code() == Severity.ERROR

@jnmt jnmt merged commit 4941f78 into 3 Jul 11, 2025
8 checks passed
@jnmt jnmt deleted the 3-pull-180 branch July 11, 2025 00:56
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