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 schema creation + CI config #20701

Open
wants to merge 95 commits into
base: main
Choose a base branch
from

Conversation

aaronc
Copy link
Member

@aaronc aaronc commented Jun 17, 2024

Description

This PR adds:

  • a new go module cosmossdk.io/indexer/postgres for the postgres indexer
  • a new go module cosmossdk.io/indexer/postgres/tests for postgres indexer integration tests (to keep the dependencies on pgx and embedded postgres out of indexer/postgres)
  • postgres schema creation for cosmossdk.io/schema module schemas with tests
  • CI config for the above

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 PostgreSQL Indexer with functionality to index and query current states of modules.
    • Added methods for creating and managing PostgreSQL tables, enums, and schema types.
    • Implemented logging capabilities with different levels (INFO, WARN, ERROR, DEBUG).
    • Added test cases for PostgreSQL Indexer in a separate module to maintain driver independence.
  • Documentation

    • Added README.md and CHANGELOG.md for PostgreSQL Indexer detailing setup, usage, and change guidelines.
    • Provided comprehensive test documentation for PostgreSQL Indexer tests.

@aaronc aaronc marked this pull request as ready for review July 8, 2024 13:04
@aaronc aaronc requested a review from a team as a code owner July 8, 2024 13:04
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: 6

Outside diff range and nitpick comments (10)
indexer/postgres/create_table.go (2)

11-24: Ensure proper logging and error handling.

The CreateTable function correctly logs and handles errors. However, consider adding more context to the error messages for better debugging.

if err != nil {
  return fmt.Errorf("failed to create table SQL: %w", err)
}

77-77: Improve primary key definition.

Ensure that the primary key definition is correct and consider adding more context to the error message.

_, err = fmt.Fprintf(writer, "PRIMARY KEY (%s)", strings.Join(pKeys, ", "))
if err != nil {
  return fmt.Errorf("failed to define primary key: %w", err)
}
indexer/postgres/tests/init_schema_test.go (1)

34-66: Improve error message context in tests.

The testInitSchema function logs SQL statements and parameters. Ensure that the error messages provide enough context for debugging.

require.NoError(t, err, fmt.Sprintf("failed to log message: %s", msg))
indexer/postgres/enum.go (3)

13-39: Ensure proper error handling and logging.

The CreateEnumType function checks if the enum type exists and creates it if it doesn't. Ensure that the error messages provide enough context for debugging.

return fmt.Errorf("failed to check if enum type %q exists: %w", typeName, err)

41-63: Ensure SQL statement generation is correct.

The CreateEnumTypeSql function generates a SQL statement for creating an enum type. Ensure that the generated SQL is correct and consider adding more context to the error messages.

return fmt.Errorf("failed to generate CREATE TYPE statement: %w", err)

70-91: Ensure proper handling of enum types.

The createEnumTypesForFields function creates enum types for fields with enum kind. Ensure that the function correctly handles all cases and consider adding more context to the error messages.

return fmt.Errorf("failed to create enum type for field %q: %w", field.Name, err)
indexer/postgres/column.go (4)

10-52: Ensure proper handling of column definitions.

The createColumnDefinition function writes a column definition within a CREATE TABLE statement. Ensure that the function correctly handles all cases and consider adding more context to the error messages.

return fmt.Errorf("failed to write column definition for field %q: %w", field.Name, err)

54-63: Ensure proper handling of nullability.

The writeNullability function writes column nullability. Ensure that the function correctly handles all cases and consider adding more context to the error messages.

return fmt.Errorf("failed to write nullability for column: %w", err)

65-108: Ensure proper handling of simple column types.

The simpleColumnType function returns the PostgreSQL column type for simple types. Ensure that the function correctly handles all cases and consider adding more context to the error messages.

return fmt.Errorf("unexpected kind: %v", kind)

110-119: Ensure proper handling of updatable column names.

The updatableColumnName function returns the name of the insertable/updatable column name for the field. Ensure that the function correctly handles all cases and consider adding more context to the error messages.

return fmt.Errorf("failed to get updatable column name for field %q: %w", field.Name, err)
Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 3ec041e and b48d768.

Files ignored due to path filters (2)
  • indexer/postgres/go.sum is excluded by !**/*.sum
  • indexer/postgres/tests/go.sum is excluded by !**/*.sum
Files selected for processing (26)
  • .github/dependabot.yml (1 hunks)
  • .github/pr_labeler.yml (1 hunks)
  • .github/workflows/test.yml (1 hunks)
  • go.work.example (1 hunks)
  • indexer/postgres/CHANGELOG.md (1 hunks)
  • indexer/postgres/README.md (1 hunks)
  • indexer/postgres/base_sql.go (1 hunks)
  • indexer/postgres/column.go (1 hunks)
  • indexer/postgres/conn.go (1 hunks)
  • indexer/postgres/create_table.go (1 hunks)
  • indexer/postgres/create_table_test.go (1 hunks)
  • indexer/postgres/enum.go (1 hunks)
  • indexer/postgres/enum_test.go (1 hunks)
  • indexer/postgres/go.mod (1 hunks)
  • indexer/postgres/indexer.go (1 hunks)
  • indexer/postgres/internal/testdata/example_schema.go (1 hunks)
  • indexer/postgres/module_mgr.go (1 hunks)
  • indexer/postgres/options.go (1 hunks)
  • indexer/postgres/sonar-project.properties (1 hunks)
  • indexer/postgres/table_mgr.go (1 hunks)
  • indexer/postgres/tests/README.md (1 hunks)
  • indexer/postgres/tests/go.mod (1 hunks)
  • indexer/postgres/tests/init_schema_test.go (1 hunks)
  • indexer/postgres/tests/testdata/init_schema.txt (1 hunks)
  • indexer/postgres/tests/testdata/init_schema_no_retain_delete.txt (1 hunks)
  • schema/logutil/logger.go (1 hunks)
Files skipped from review due to trivial changes (8)
  • .github/dependabot.yml
  • .github/pr_labeler.yml
  • go.work.example
  • indexer/postgres/CHANGELOG.md
  • indexer/postgres/base_sql.go
  • indexer/postgres/enum_test.go
  • indexer/postgres/go.mod
  • indexer/postgres/tests/README.md
Additional context used
Path-based instructions (13)
indexer/postgres/options.go (1)

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

indexer/postgres/conn.go (1)

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

indexer/postgres/table_mgr.go (1)

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

schema/logutil/logger.go (1)

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

indexer/postgres/internal/testdata/example_schema.go (1)

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

indexer/postgres/create_table_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/module_mgr.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/create_table.go (1)

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

indexer/postgres/tests/init_schema_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/enum.go (1)

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

indexer/postgres/column.go (1)

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

indexer/postgres/README.md (1)

Pattern **/*.md: "Assess the documentation for misspellings, grammatical errors, missing documentation and correctness"

LanguageTool
indexer/postgres/tests/testdata/init_schema_no_retain_delete.txt

[style] ~22-~22: The adverb ‘ALWAYS’ is usually put before the verb ‘GENERATED’.
Context: ..." BOOLEAN NOT NULL, "time" TIMESTAMPTZ GENERATED ALWAYS AS (nanos_to_timestamptz("time_nanos"))...

(ADVERB_WORD_ORDER)


[typographical] ~26-~26: Consider adding a comma here.
Context: ...oat32" REAL NOT NULL, "float64" DOUBLE PRECISION NOT NULL, "bech32address" TEXT NOT NUL...

(NN_NOT_NN_COMMA)

indexer/postgres/tests/testdata/init_schema.txt

[style] ~22-~22: The adverb ‘ALWAYS’ is usually put before the verb ‘GENERATED’.
Context: ..." BOOLEAN NOT NULL, "time" TIMESTAMPTZ GENERATED ALWAYS AS (nanos_to_timestamptz("time_nanos"))...

(ADVERB_WORD_ORDER)


[typographical] ~26-~26: Consider adding a comma here.
Context: ...oat32" REAL NOT NULL, "float64" DOUBLE PRECISION NOT NULL, "bech32address" TEXT NOT NUL...

(NN_NOT_NN_COMMA)

indexer/postgres/README.md

[uncategorized] ~3-~3: You might be missing the article “the” here.
Context: ... The PostgreSQL indexer can fully index current state for all modules that implement `c...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[misspelling] ~37-~37: This word is normally spelled as one.
Context: ... one with the _nanos suffix with full nano-seconds precision, and another as a `TIMESTAMPT...

(EN_COMPOUNDS_NANO_SECONDS)


[duplication] ~39-~39: Possible typo: you repeated a word
Context: ...ype is created for each module prefixed with with module name it pertains to ...

(ENGLISH_WORD_REPEAT_RULE)

Additional comments not posted (38)
indexer/postgres/options.go (1)

1-10: Ensure field names and documentation are clear.

The ManagerOptions struct is well-documented and the field names are descriptive. The changes align with the Uber Golang style guide.

indexer/postgres/conn.go (1)

1-14: Ensure interface methods are well-documented and named appropriately.

The DBConn interface is well-defined, and the method names are descriptive. The changes align with the Uber Golang style guide.

indexer/postgres/sonar-project.properties (1)

1-16: Ensure SonarCloud properties are correctly configured.

The SonarCloud properties are well-configured and align with best practices for CI integration.

indexer/postgres/table_mgr.go (1)

1-44: Ensure struct and methods are well-documented and named appropriately.

The TableManager struct and its methods are well-defined, and the method names are descriptive. The changes align with the Uber Golang style guide.

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

1-1: Module declaration looks good.

The module path is correctly specified.


3-11: Required dependencies look good.

The dependencies are correctly listed and necessary for testing.


13-29: Indirect dependencies look good.

The indirect dependencies are correctly listed and necessary.


31-33: Replace directives look good.

The replace directives are correctly specified for local development and testing.

schema/logutil/logger.go (3)

1-3: Package declaration looks good.

The package is correctly specified as logutil.


5-22: Logger interface looks good.

The interface methods are well-defined and follow best practices.


24-35: NoopLogger implementation looks good.

The NoopLogger correctly implements the Logger interface with no-op methods.

indexer/postgres/tests/testdata/init_schema_no_retain_delete.txt (3)

1-5: Enum type creation looks good.

The SQL statements for creating enum types test_my_enum and test_vote_type are correct.


34-40: Table creation for test_singleton looks good.

The SQL statements for creating the table test_singleton are correct.


42-48: Table creation for test_vote looks good.

The SQL statements for creating the table test_vote are correct.

indexer/postgres/tests/testdata/init_schema.txt (3)

1-5: Enum type creation looks good.

The SQL statements for creating enum types test_my_enum and test_vote_type are correct.


34-40: Table creation for test_singleton looks good.

The SQL statements for creating the table test_singleton are correct.


42-49: Table creation for test_vote looks good.

The SQL statements for creating the table test_vote are correct.

indexer/postgres/internal/testdata/example_schema.go (6)

7-18: Ensure correct initialization of AllKindsObject.

The AllKindsObject is correctly initialized with a name and key fields. The initialization logic appears correct.


20-35: Verify field initialization logic.

The loop correctly initializes fields for each valid kind, with special handling for EnumKind and Bech32AddressKind. Ensure that MyEnum and address prefix are correctly defined.


37-43: Ensure correct initialization of ExampleSchema.

The ExampleSchema is initialized with object types. The initialization logic appears correct.


46-57: Ensure correct definition of SingletonObject.

The SingletonObject is correctly defined with a name and value fields. The definition logic appears correct.


60-83: Ensure correct definition of RetainDeleteObject.

The RetainDeleteObject is correctly defined with a name, key fields, value fields, and the RetainDeletions flag. The definition logic appears correct.


85-88: Ensure correct definition of MyEnum.

The MyEnum is correctly defined with a name and values. The definition logic appears correct.

indexer/postgres/create_table_test.go (3)

10-38: Ensure correct table creation for AllKindsObject.

The example function correctly creates a table for AllKindsObject and verifies the output. The logic appears correct.


40-49: Ensure correct table creation for SingletonObject.

The example function correctly creates a table for SingletonObject and verifies the output. The logic appears correct.


51-57: Ensure correct helper function for table creation.

The helper function correctly initializes the TableManager and creates the table. The logic appears correct.

indexer/postgres/module_mgr.go (4)

10-17: Ensure correct definition of ModuleManager.

The ModuleManager is correctly defined with necessary fields. The definition logic appears correct.


19-27: Ensure correct initialization of ModuleManager.

The function correctly initializes the ModuleManager with the provided schema and options. The logic appears correct.


30-57: Ensure correct schema initialization.

The method correctly initializes the schema by creating enum types and tables. The logic appears correct.


59-62: Ensure correct table retrieval.

The method correctly returns the table managers for the module. The logic appears correct.

indexer/postgres/indexer.go (3)

11-20: Ensure correct definition of Config.

The Config struct is correctly defined with necessary fields. The definition logic appears correct.


22-22: Ensure correct definition of SqlLogger.

The SqlLogger type is correctly defined. The definition logic appears correct.


24-79: Ensure correct initialization of the indexer.

The StartIndexer function correctly initializes the PostgreSQL indexer with the provided configuration and logger. The logic appears correct.

indexer/postgres/create_table.go (2)

55-61: Optimize condition check for retaining deletions.

The condition check for retaining deletions is clear and concise. Ensure that tm.options.DisableRetainDeletions and tm.typ.RetainDeletions are correctly set.


87-93: Ensure proper permissions are set.

The code grants SELECT permissions to PUBLIC. Ensure this aligns with security requirements and does not expose sensitive data.

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

24-32: Ensure comprehensive test coverage.

The TestInitSchema function includes two test cases. Ensure that all edge cases are covered and consider adding more test cases if necessary.


68-87: Ensure proper cleanup in tests.

The createTestDB function creates a temporary directory and starts an embedded PostgreSQL instance. Ensure that the cleanup operations are correctly executed.

.github/workflows/test.yml (1)

490-525: LGTM! New job addition for PostgreSQL indexer tests.

The new job test-indexer-postgres correctly follows the pattern of other test jobs and integrates with SonarCloud. It runs the necessary tests for the PostgreSQL indexer.

indexer/postgres/README.md Outdated Show resolved Hide resolved
indexer/postgres/README.md Outdated Show resolved Hide resolved
indexer/postgres/create_table.go Outdated Show resolved Hide resolved
indexer/postgres/README.md Outdated Show resolved Hide resolved
indexer/postgres/tests/testdata/init_schema.txt Outdated Show resolved Hide resolved
aaronc and others added 4 commits July 8, 2024 15:33
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link

sonarcloud bot commented Jul 8, 2024

Quality Gate Passed Quality Gate passed for 'Cosmos SDK - Postgres Indexer'

Issues
2 New issues
0 Accepted issues

Measures
0 Security Hotspots
81.2% Coverage on New Code
0.0% Duplication on New Code

See analysis details on SonarCloud

Copy link

sonarcloud bot commented Jul 8, 2024

Quality Gate Failed Quality Gate failed for 'Cosmos SDK - Schema'

Failed conditions
B Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarCloud

Catch issues before they fail your Quality Gate with our IDE extension SonarLint

@github-actions github-actions bot removed the C:schema label Jul 9, 2024

// CreateTableSql generates a CREATE TABLE statement for the object type.
func (tm *TableManager) CreateTableSql(writer io.Writer) error {
_, err := fmt.Fprintf(writer, "CREATE TABLE IF NOT EXISTS %q (\n\t", tm.TableName())
Copy link
Member

Choose a reason for hiding this comment

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

Shall we use ? for avoiding requiring to sanitize table name and module names?

Copy link
Member Author

Choose a reason for hiding this comment

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

Can placeholders bind identifiers? I thought it was only parameters. The downside would be that it's hard to inspect the actual SQL in tests and logs

Copy link
Member

Choose a reason for hiding this comment

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

I see, everything goes to a writer, cannot be a prepared statement indeed. We should probably sanitize the inputs then.

Copy link
Member Author

Choose a reason for hiding this comment

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

Schema validation enforces use of the NameFormat regex first, then second %q quotes and escapes these

Copy link
Member

@julienrbrt julienrbrt left a comment

Choose a reason for hiding this comment

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

lgtm! sql generator seems to output valid sql.
I find only the module manager to have a confusing name given what is a module manager in the SDK, especially because it manages only one module.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants