Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(indexer/postgres): add insert/update/delete functionality #21186

Merged
merged 101 commits into from
Sep 4, 2024

Conversation

aaronc
Copy link
Member

@aaronc aaronc commented Aug 6, 2024

Description

This PR adds the postgres insert/update/delete functionality to the postgres indexer. It is tested using generated data from cosmossdk.io/schema/testing. This is essentially the "core" postgres state indexer implementation.


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • included the correct type prefix in the PR title, you can find examples of the prefixes below:
  • confirmed ! in the type prefix if API or client breaking change
  • targeted the correct branch (see PR Targeting)
  • provided a link to the relevant issue or specification
  • reviewed "Files changed" and left comments if necessary
  • included the necessary unit and integration tests
  • added a changelog entry to CHANGELOG.md
  • updated the relevant documentation or specification, including comments for documenting Go code
  • confirmed all CI checks have passed

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.

Please see Pull Request Reviewer section in the contributing guide for more information on how to review a pull request.

I have...

  • confirmed the correct type prefix in the PR title
  • confirmed all author checklist items have been addressed
  • reviewed state machine logic, API design and naming, documentation is accurate, tests and test coverage

Summary by CodeRabbit

  • New Features

    • Introduced functionality for deleting, inserting, and updating rows in the PostgreSQL database.
    • Added dynamic SQL clause generation for enhanced database interactions.
    • Implemented comprehensive methods for counting, existence checks, and data retrieval.
    • Enhanced the indexer with an OnObjectUpdate callback for handling updates to objects.
  • Bug Fixes

    • Improved handling of database operations to ensure robustness and error management.
  • Tests

    • Added unit tests for the PostgreSQL indexer, ensuring comprehensive validation of functionality.

@aaronc aaronc requested a review from a team as a code owner August 21, 2024 15:13
Copy link
Contributor

@aaronc your pull request is missing a changelog!

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, codebase verification and nitpick comments (4)
indexer/postgres/listener.go (1)

28-55: Ensure comprehensive error handling and logging.

The OnObjectUpdate method effectively handles object updates, but consider enhancing error handling and logging for better traceability. Ensure that errors are logged with sufficient context to aid in debugging.

Additionally, consider wrapping the entire update process in a transaction to ensure atomicity, especially if partial updates could lead to inconsistent states.

 if err != nil {
-  return err
+  if i.logger != nil {
+    i.logger.Error("Failed to update object", "module", module, "type", update.TypeName, "key", update.Key, "error", err)
+  }
+  return fmt.Errorf("failed to update object in module %s: %w", module, err)
 }
indexer/postgres/delete.go (2)

11-28: Verify SQL injection protection and enhance logging.

The delete method constructs SQL statements dynamically. Ensure that all inputs are properly sanitized to prevent SQL injection. The use of parameterized queries helps mitigate this risk, but double-check the implementation.

Consider enhancing logging to include more context about the operation being performed, especially in error scenarios.

 if err != nil {
-  return err
+  tm.options.logger.Error("Failed to execute delete", "sql", sqlStr, "params", params, "error", err)
+  return fmt.Errorf("failed to execute delete: %w", err)
 }

46-61: Review retain deletion logic and parameter handling.

The retainDeleteSqlAndParams method generates an UPDATE statement for retaining deletions. Ensure that the logic aligns with the intended functionality and that parameters are safely handled to prevent SQL injection.

 if err != nil {
-  return nil, err
+  tm.options.logger.Error("Failed to generate retain delete SQL", "error", err)
+  return nil, fmt.Errorf("failed to generate retain delete SQL: %w", err)
 }
indexer/postgres/indexer.go (1)

Line range hint 75-89: Verify integration of addressCodec and ensure proper initialization.

The addition of the addressCodec field in the opts struct enhances configurability. Ensure that this field is correctly utilized in the indexer and that its integration does not introduce any unintended side effects.

Consider adding comments to document the purpose and usage of the addressCodec field for future maintainability.

 opts := options{
   disableRetainDeletions: config.DisableRetainDeletions,
   logger:                 params.Logger,
+  // addressCodec is used for encoding addresses in the indexer.
   addressCodec:           params.AddressCodec,
 }
Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between e88c138 and d144751.

Files ignored due to path filters (1)
  • indexer/postgres/tests/go.sum is excluded by !**/*.sum
Files selected for processing (11)
  • indexer/postgres/delete.go (1 hunks)
  • indexer/postgres/indexer.go (2 hunks)
  • indexer/postgres/insert_update.go (1 hunks)
  • indexer/postgres/listener.go (1 hunks)
  • indexer/postgres/options.go (2 hunks)
  • indexer/postgres/params.go (1 hunks)
  • indexer/postgres/select.go (1 hunks)
  • indexer/postgres/tests/go.mod (3 hunks)
  • indexer/postgres/tests/postgres_test.go (1 hunks)
  • indexer/postgres/view.go (1 hunks)
  • indexer/postgres/where.go (1 hunks)
Additional context used
Path-based instructions (10)
indexer/postgres/options.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

indexer/postgres/where.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

indexer/postgres/listener.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

indexer/postgres/delete.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

indexer/postgres/indexer.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

indexer/postgres/tests/postgres_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

indexer/postgres/insert_update.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

indexer/postgres/view.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

indexer/postgres/params.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

indexer/postgres/select.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

Additional comments not posted (32)
indexer/postgres/options.go (2)

3-5: Imports are well-organized.

The import statements are correctly updated to include the new addressutil package.


16-17: Ensure addressCodec is initialized properly.

The addressCodec field is expected to be non-nil. Ensure that it is properly initialized in all instances of the options struct.

indexer/postgres/tests/go.mod (3)

8-14: New dependencies added for testing.

The dependencies cosmossdk.io/schema/testing and pgregory.net/rapid are added, which enhance testing capabilities.


Line range hint 18-28: Indirect dependencies are correctly listed.

The indirect dependencies github.com/cockroachdb/apd/v3 and github.com/tidwall/btree are correctly listed, indicating they are used by other dependencies.


40-41: Replace directives point to local paths.

The replace directives are correctly set to local paths, which is typical for local development and testing.

indexer/postgres/where.go (2)

8-18: Function whereSqlAndParams is well-structured.

The function efficiently generates a WHERE clause and handles errors consistently. Ensure that bindKeyParams is correctly implemented to support this function.


20-59: Function whereSql efficiently constructs SQL clauses.

The function uses io.Writer to construct SQL strings, which is efficient. Error handling is consistent throughout the function.

indexer/postgres/delete.go (1)

30-44: Ensure SQL statement correctness and parameter safety.

The deleteSqlAndParams method generates a DELETE statement. Ensure that the table name and parameters are correctly handled to prevent SQL injection. The use of fmt.Fprintf should be carefully reviewed to avoid any formatting issues.

indexer/postgres/tests/postgres_test.go (2)

22-28: Good test structure with sub-tests.

The use of t.Run for organizing sub-tests is appropriate and enhances the readability and maintainability of the tests.


31-98: Comprehensive test function with setup and cleanup.

The test function is well-structured, covering setup, execution, and cleanup phases. The use of require.NoError ensures that errors are caught immediately.

indexer/postgres/insert_update.go (3)

11-39: Efficient insert/update logic.

The function efficiently handles insert/update logic and logs SQL statements if a logger is present.

However, address the existing issue with unused variables as highlighted in previous comments.


41-71: Correct SQL INSERT statement generation.

The function correctly constructs the SQL INSERT statement and handles parameter binding. Error handling is appropriate.


73-113: Correct SQL UPDATE statement generation.

The function correctly constructs the SQL UPDATE statement and handles parameter binding. Error handling is appropriate.

indexer/postgres/view.go (5)

14-16: Correct application state return.

The function correctly returns the application state.


18-25: Correct block number retrieval.

The function correctly queries the database for the maximum block number and handles errors appropriately.


33-43: Correct module retrieval.

The function correctly retrieves a module by name and returns its view.


45-54: Correct module iteration with callback.

The function correctly iterates over modules and applies the callback function.

However, address the existing issue with potential non-determinism due to map iteration as highlighted in previous comments.


81-90: Correct object collection iteration with callback.

The function correctly iterates over object collections and applies the callback function.

However, address the existing issue with potential non-determinism due to map iteration as highlighted in previous comments.

indexer/postgres/params.go (4)

10-26: LGTM!

The bindKeyParams function correctly handles key parameter binding with appropriate error handling for type mismatches.


28-63: LGTM!

The bindValueParams function effectively manages value parameter binding with comprehensive error handling for unknown columns and type mismatches.


65-87: LGTM!

The bindParams function efficiently binds parameters to fields with robust error handling for missing values.


89-116: LGTM!

The bindParam function handles individual parameter binding with comprehensive error handling for nullability and type mismatches.

indexer/postgres/select.go (10)

16-26: LGTM!

The count function correctly constructs and executes a SQL count query with optional logging.


28-37: LGTM!

The exists function effectively checks for row existence using helper methods for SQL generation.


39-54: LGTM!

The checkExists function includes robust error handling for different query outcomes.


56-70: LGTM!

The existsSqlAndParams function correctly generates a SQL SELECT statement with appropriate error handling.


72-86: LGTM!

The get function effectively retrieves a row using helper methods for SQL generation and result reading.


88-96: LGTM!

The selectAllSql function correctly generates a SQL SELECT statement, considering configuration options for deletion flags.


98-116: LGTM!

The getSqlAndParams function correctly generates a SQL SELECT statement and binds parameters with appropriate error handling.


118-147: LGTM!

The selectAllClause function correctly constructs a SQL SELECT clause, ensuring all relevant fields are included.


149-214: LGTM!

The readRow function includes comprehensive handling for different field types and optional deletion flags.


217-298: LGTM!

The colBindValue and readCol functions correctly handle different field types, ensuring proper data conversion and error handling.

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

Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between d144751 and f051ddf.

Files selected for processing (1)
  • indexer/postgres/insert_update.go (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • indexer/postgres/insert_update.go

@testinginprod testinginprod self-requested a review August 22, 2024 12:59
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

Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between f051ddf and e7ca1d7.

Files selected for processing (2)
  • indexer/postgres/select.go (1 hunks)
  • indexer/postgres/where.go (1 hunks)
Files skipped from review as they are similar to previous changes (2)
  • indexer/postgres/select.go
  • indexer/postgres/where.go

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

Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between e7ca1d7 and d502da1.

Files selected for processing (1)
  • indexer/postgres/tests/go.mod (3 hunks)
Files skipped from review due to trivial changes (1)
  • indexer/postgres/tests/go.mod

@aaronc aaronc marked this pull request as draft August 27, 2024 16:05
@aaronc aaronc marked this pull request as ready for review August 28, 2024 17:54
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

Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between d502da1 and 66db5c5.

Files ignored due to path filters (1)
  • indexer/postgres/tests/go.sum is excluded by !**/*.sum
Files selected for processing (1)
  • indexer/postgres/tests/go.mod (3 hunks)
Files skipped from review due to trivial changes (1)
  • indexer/postgres/tests/go.mod

@aaronc aaronc added this pull request to the merge queue Sep 4, 2024
Merged via the queue into main with commit 292d7b4 Sep 4, 2024
77 checks passed
@aaronc aaronc deleted the aaronc/indexer-postgres2 branch September 4, 2024 12:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants