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: [#358] Add Insert First methods for DB #888

Merged
merged 15 commits into from
Feb 19, 2025
Merged

feat: [#358] Add Insert First methods for DB #888

merged 15 commits into from
Feb 19, 2025

Conversation

hwbrzzl
Copy link
Contributor

@hwbrzzl hwbrzzl commented Feb 14, 2025

📑 Description

goravel/goravel#358

Summary by CodeRabbit

  • New Features

    • Enhanced database interactions with improved methods for data insertion and retrieval.
    • Added clear error messaging for unsupported data types.
  • Refactor

    • Transitioned to a builder pattern for database queries, improving reliability.
    • Updated product data mapping and timestamp handling for better data consistency.
  • Tests

    • Expanded test coverage to validate new query behaviors and overall database operations, including comprehensive tests for product data insertion and retrieval.
  • Chores

    • Upgraded external dependencies to the latest versions for improved performance and security.

✅ Checks

  • Added test cases for my code

Copy link
Contributor

coderabbitai bot commented Feb 14, 2025

Walkthrough

The changes enhance the database interaction layer by modifying the Query interface and its implementations. New methods such as First and Insert have been added to the Query interface, along with a new Result struct and a Builder interface to handle SQL execution. The DB struct now uses a Builder instead of a direct SQL instance. Additional utility functions for data conversion have been introduced, accompanied by new tests and updated mocks. Module dependency versions have been bumped, and an error variable for unsupported types has been added.

Changes

File(s) Change Summary
contracts/database/db/db.go, database/db/db.go, database/db/query.go Enhanced Query interface with new methods (First, Insert), added a new Result struct and Builder interface, and updated the DB struct to use a builder pattern for query execution.
database/db/db_test.go, database/db/query_test.go, database/db/utils_test.go Introduced new tests for BuildDB, Query functionalities, and utility functions with table-driven and mock-based approaches.
database/db/utils.go Added utility functions convertToSliceMap and convertToMap for converting various input types into map representations.
errors/list.go Added a new error variable DatabaseUnsupportedType for handling unsupported types in database operations.
go.mod, tests/go.mod Updated the dependency golang.org/x/net from v0.34.0 to v0.35.0.
mocks/database/db/Builder.go, mocks/database/db/Query.go Added comprehensive mock implementations for the Builder and Query interfaces, including helper methods for setting expectations.
tests/db_test.go, tests/models.go Added and updated tests to validate product insertion and querying; modified model definitions (e.g., adding db:"name" tags and converting certain fields to pointers).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Query
    participant Builder

    Client->>Query: Insert(data)
    Query->>Query: buildInsert(data)
    Query->>Builder: Exec(SQL, args)
    Builder-->>Query: (sql.Result, error)
    Query-->>Client: Return (*Result, error)
Loading
sequenceDiagram
    participant Client
    participant Query
    participant Builder

    Client->>Query: First(dest)
    Query->>Builder: Get(dest, SQL, args)
    Builder-->>Query: error (if any)
    Query-->>Client: Return error
Loading

Possibly related PRs

  • feat: [#280] Add Time methods #733: The changes in the main PR, which enhance the Query interface and introduce new methods for database interactions, are related to the modifications in the retrieved PR that also involve adding new methods to the database schema, specifically for handling time-related column types.
  • chore: orm test #658: The changes in the main PR, which enhance the Query interface and introduce new methods and types, are directly related to the modifications in the retrieved PR that involve refactoring tests for database operations, particularly those that utilize the Query struct and its methods.
  • feat: [#358] Add facades.DB, to provider an original sql flow #869: The changes in the main PR, which enhance the Query interface and introduce new methods and types in the db package, are related to the modifications in the retrieved PR that also involve the db package, specifically the introduction of a new DB interface and its methods for database interactions.

Suggested reviewers

  • almas1992
  • devhaozi

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 golangci-lint (1.62.2)

Error: can't load config: the Go language version (go1.23) used to build golangci-lint is lower than the targeted Go version (1.24.0)
Failed executing command with error: can't load config: the Go language version (go1.23) used to build golangci-lint is lower than the targeted Go version (1.24.0)

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

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 generate docstrings to generate docstrings for this PR. (Beta)
  • @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.

Copy link

codecov bot commented Feb 15, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 67.65%. Comparing base (0839829) to head (19a2824).
Report is 3 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #888   +/-   ##
=======================================
  Coverage   67.65%   67.65%           
=======================================
  Files         152      152           
  Lines       10050    10050           
=======================================
  Hits         6799     6799           
  Misses       2925     2925           
  Partials      326      326           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@hwbrzzl hwbrzzl changed the title feat: [#358] Add Insert Update Delete methods for DB feat: [#358] Add Insert First methods for DB Feb 18, 2025
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.50.

Benchmark suite Current: 19a2824 Previous: 2cdb138 Ratio
Benchmark_EncryptString 6259 ns/op 2160 B/op 15 allocs/op 2225 ns/op 2160 B/op 15 allocs/op 2.81
Benchmark_EncryptString - ns/op 6259 ns/op 2225 ns/op 2.81

This comment was automatically generated by workflow using github-action-benchmark.

@hwbrzzl hwbrzzl marked this pull request as ready for review February 18, 2025 09:40
@hwbrzzl hwbrzzl requested a review from a team as a code owner February 18, 2025 09:40
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 comments (1)
database/factory/factory_test.go (1)

43-52: ⚠️ Potential issue

Fix inconsistency in factory definition.

The factory definition creates value types for timestamp fields, but the struct fields are now pointer types.

Update the factory definition to use pointer types:

 func (u *UserFactory) Definition() map[string]any {
 	faker := gofakeit.New(0)
+	now := carbon.Now()
+	deletedAt := time.Now()
 	return map[string]any{
 		"Name":      faker.Name(),
 		"Avatar":    faker.Email(),
-		"CreatedAt": carbon.NewDateTime(carbon.Now()),
-		"UpdatedAt": carbon.NewDateTime(carbon.Now()),
-		"DeletedAt": gormio.DeletedAt{Time: time.Now(), Valid: true},
+		"CreatedAt": carbon.NewDateTime(now),
+		"UpdatedAt": carbon.NewDateTime(now),
+		"DeletedAt": &gormio.DeletedAt{Time: deletedAt, Valid: true},
 	}
 }
🧹 Nitpick comments (7)
database/db/query.go (3)

31-40: Use structured logging instead of fmt.Println.

Within First, you use fmt.Println(sql, args, err) for debug logging (lines 35-36). Replacing it with a structured logger or code-level debugging tools would align better with production standards.

 func (r *Query) First(dest any) error {
     sql, args, err := r.buildSelect()
-    fmt.Println(sql, args, err)
+    // logger.Debug("Executing SELECT: ", sql, args, "Error: ", err)
     if err != nil {
         return err
     }
     return r.builder.Get(dest, sql, args...)
 }

42-51: Consistency between Get and First.

Get also uses fmt.Println for logging but otherwise follows a similar pattern to First. Consistency in logging and error handling across these methods is encouraged. Consider extracting shared logic (e.g. building the SELECT query, printing a debug message) into a helper to reduce duplication.


53-78: Excellent insertion pattern; consider returning last insert ID.

Your new Insert method correctly leverages buildInsert and returns a Result containing RowsAffected. For completeness—if the database supports it—consider also retrieving a last inserted ID (e.g. using result.LastInsertId()) in the future.

contracts/database/db/db.go (1)

16-18: Result struct usage.

RowsAffected int64 is helpful, but consider a future enhancement to store LastInsertId if your DB engine supports it.

database/db/utils.go (1)

89-131: Consider optimizing map allocation size.

The map is initialized without a size hint, which could lead to reallocations as fields are added. Consider pre-allocating with the expected size.

-result := make(map[string]any)
+result := make(map[string]any, typ.NumField())
tests/db_test.go (1)

38-134: Add error case tests for Insert operations.

While the happy path cases are well covered, consider adding tests for:

  • Invalid field types
  • Database connection errors
  • Constraint violations
database/db/query_test.go (1)

16-20: Consider adding validation tags to the test model.

The TestUser model could benefit from validation tags to test validation behavior during operations.

 type TestUser struct {
-	ID   uint   `db:"id"`
-	Name string `db:"-"`
-	Age  int
+	ID   uint   `db:"id" validate:"required"`
+	Name string `db:"-" validate:"required"`
+	Age  int    `validate:"gte=0"`
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0839829 and b666073.

⛔ Files ignored due to path filters (2)
  • go.sum is excluded by !**/*.sum
  • tests/go.sum is excluded by !**/*.sum
📒 Files selected for processing (19)
  • auth/auth_test.go (1 hunks)
  • contracts/database/db/db.go (1 hunks)
  • database/db/db.go (2 hunks)
  • database/db/db_test.go (1 hunks)
  • database/db/query.go (3 hunks)
  • database/db/query_test.go (1 hunks)
  • database/db/utils.go (1 hunks)
  • database/db/utils_test.go (1 hunks)
  • database/factory/factory_test.go (1 hunks)
  • database/gorm/event_test.go (7 hunks)
  • database/orm/model.go (1 hunks)
  • errors/list.go (1 hunks)
  • go.mod (1 hunks)
  • mocks/database/db/Builder.go (1 hunks)
  • mocks/database/db/Query.go (2 hunks)
  • support/database/database_test.go (1 hunks)
  • tests/db_test.go (3 hunks)
  • tests/go.mod (1 hunks)
  • tests/models.go (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tests/go.mod
⏰ Context from checks skipped due to timeout of 300000ms (2)
  • GitHub Check: ubuntu (1.24)
  • GitHub Check: ubuntu (1.23)
🔇 Additional comments (25)
go.mod (1)

95-95: Dependency Version Upgrade: golang.org/x/net

The dependency version for golang.org/x/net has been updated from v0.34.0 to v0.35.0. This change aligns with the updated version in the test module and ensures consistency within the dependency tree. Please verify that the new version maintains compatibility with all modules relying on this package across the codebase.

database/db/query.go (4)

5-19: Confirm the necessity of new imports and fields.

You introduced "sort" (line 5), "github.com/goravel/framework/support/str" (line 12), and the builder db.Builder field (line 16). Ensure these dependencies are strictly needed and do not create circular references. Also confirm that the builder field is always initialized with a valid object to avoid runtime errors.


21-29: Constructor logic validation.

NewQuery sets up a fresh Query configured with a db.Builder. This design appears consistent with the shift to a builder pattern. Make sure to handle potential edge cases, such as empty table names (though you check table presence in other methods, it’s good to consistently protect constructors with validations if needed).


80-89: Immutability approach in Where.

Where returns a new Query instance rather than mutating the original, promoting an immutable/fluent API. This is generally safer in concurrent contexts. Confirm that client code expects a newly created Query each time and is not relying on any side effects to the old instance.


91-119: Insertion logic is clear and well-structured.

You’ve used sort.Strings(cols) to ensure consistent column ordering for multi-row inserts, which is a good approach. The method is concise and easy to read.

contracts/database/db/db.go (3)

3-4: Validate the standard library import usage.

The new import "database/sql" looks appropriate for sql.Result usage. Confirm that no advanced features from other packages are required.


10-14: New methods in the Query interface are well-defined.

Adding First(dest any) error and Insert(data any) (*Result, error) extends the interface logically. Ensure that your mocking strategy covers these new methods thoroughly for testing.


20-23: Builder interface alignment.

The Builder interface’s Exec, Get, and Select methods make sense for your builder pattern. Confirm that any advanced query building or relation handling is accounted for.

database/orm/model.go (1)

18-23: Check nil pointer usage compatibility.

Changing DeletedAt, CreatedAt, and UpdatedAt to pointers allows nil values. Ensure that migrations, queries, and JSON marshaling handle nil values as expected. Also confirm that gorm:"autoCreateTime" and gorm:"autoUpdateTime" operate correctly with these pointer types in your environment.

database/db/db.go (2)

15-18: LGTM! Good architectural improvement.

The shift from direct DB instance to builder pattern improves separation of concerns and testability. This change provides better abstraction for the database layer.


20-22:

✅ Verification successful

Verify impact of builder pattern transition.

While the implementation looks correct, this is a significant architectural change that affects how database operations are performed.

Let's verify the usage of this new pattern across the codebase:

Also applies to: 43-45


🏁 Script executed:

#!/bin/bash
# Search for any remaining direct usage of sqlx.DB that should be using the builder
rg -g '!vendor/*' -g '!mocks/*' "sqlx\.DB"

# Search for existing builder pattern implementations to ensure consistency
ast-grep --pattern 'type $_ struct {
  $$$
  builder db.Builder
  $$$
}'

Length of output: 483


Builder Pattern Transition Verified

Our scan confirms that the transition to using db.Builder is consistently applied:

  • In database/db/db.go, the NewDB function correctly instantiates the DB struct with both config and builder as intended.
  • In database/db/query.go, the Query struct similarly embeds builder db.Builder, following the new architectural pattern.
  • No direct usage of sqlx.DB was detected across the codebase.

Everything appears aligned with the intended refactor. Please continue to monitor any future changes to ensure consistent use of the builder pattern.

database/db/db_test.go (1)

16-67: LGTM! Well-structured test implementation.

The test suite demonstrates good practices:

  • Table-driven tests for better maintainability
  • Proper mocking of dependencies
  • Coverage of both success and error scenarios
database/factory/factory_test.go (1)

20-27: LGTM! Good change to support nullable timestamps.

The change to pointer types for timestamp fields allows proper handling of null values.

database/db/utils_test.go (1)

22-95: LGTM! Comprehensive test coverage for utility function.

The test suite demonstrates excellent practices:

  • Table-driven tests with diverse scenarios
  • Edge case handling (nil, pointers, maps)
  • Validation of struct tag behavior
database/db/utils.go (1)

10-61: LGTM! Well-structured conversion function with comprehensive type handling.

The function handles various input types robustly, including nil values, pointers, slices, and single values. Good error propagation and type checking.

support/database/database_test.go (1)

19-20: LGTM! Good change to pointer types for timestamp fields.

Using pointer types for timestamp fields allows for proper nil value handling, which is essential for optional timestamps.

tests/db_test.go (1)

136-173: LGTM! Comprehensive test cases for Where conditions.

Good coverage of different query scenarios including simple conditions, multiple arguments, and raw queries.

database/db/query_test.go (1)

54-145: LGTM! Excellent test coverage for Insert operations.

The test cases cover all important scenarios:

  • Single and multiple structs
  • Single and multiple maps
  • Error cases
  • Mock result verification
mocks/database/db/Query.go (2)

23-39: LGTM! The First method implementation follows mock best practices.

The implementation correctly handles:

  • Return value validation with appropriate panic
  • Type assertions for function returns
  • Error propagation

115-143: LGTM! The Insert method implementation follows mock best practices.

The implementation correctly handles:

  • Multiple return values (Result and error)
  • Type assertions for function returns
  • Proper nil checks for Result
mocks/database/db/Builder.go (1)

1-222: LGTM! The Builder mock implementation follows best practices.

The implementation correctly handles:

  • Consistent error handling across methods
  • Proper type assertions
  • Flexible return value handling
  • Clean separation of concerns with helper methods
errors/list.go (1)

53-53: LGTM! The error message is well-formed.

The error message follows the established pattern and provides clear context with placeholders for the unsupported and expected types.

tests/models.go (2)

446-450: LGTM! Added database column mapping.

The addition of the db tag for the Name field improves clarity in database mapping and follows ORM best practices.


28-31:

❓ Verification inconclusive

Verify the impact of nullable timestamp fields.

Converting CreatedAt and UpdatedAt from value types to pointer types is a breaking change. While it allows for nil values, it requires careful handling in code that accesses these fields.

Run the following script to check for potential impacts:


🏁 Script executed:

#!/bin/bash
# Description: Check for direct field access and potential nil pointer dereferences.

# Search for direct field access
rg -A 2 'CreatedAt\.|UpdatedAt\.'

# Search for potential nil checks
rg -A 2 'if .*CreatedAt|if .*UpdatedAt'

Length of output: 2145


Action Required: Revisit Nullable Field Handling

The tests in tests/query_test.go and tests/factory_test.go directly call .String() on both CreatedAt and UpdatedAt without checking for nil, which may lead to runtime nil dereference errors when these fields are nil. Please ensure that one of the following approaches is taken:

  • Add explicit nil checks before accessing these pointer fields.
  • Guarantee that these fields are always populated, even when set as nullable, to avoid breaking existing call sites.
auth/auth_test.go (1)

29-30:

❓ Verification inconclusive

Verify test coverage for nil timestamp values.

The change to pointer types for CreatedAt and UpdatedAt fields is consistent with the model changes. However, ensure that test cases cover scenarios with nil values.

Run the following script to check test coverage:


🏁 Script executed:

#!/bin/bash
# Description: Check for test cases handling nil timestamp values.

# Search for test cases setting nil timestamps
rg -A 5 'CreatedAt = nil|UpdatedAt = nil'

# Search for test assertions on timestamps
rg -A 5 'assert.*CreatedAt|assert.*UpdatedAt'

Length of output: 354


Attention: Verify handling of potential nil timestamps in auth tests.

The conversion of CreatedAt and UpdatedAt to pointer types is consistent with the overall model changes. Our checks show that tests—such as those in database/factory/factory_test.go—already confirm these fields are automatically set (asserting they’re not nil). However, please ensure that the tests in auth/auth_test.go also cover scenarios where, due to any edge case or misconfiguration, these fields might unexpectedly be nil. If such a scenario is plausible, consider adding explicit tests to simulate and handle nil timestamp values.

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: 2

♻️ Duplicate comments (1)
database/db/query.go (1)

134-148: ⚠️ Potential issue

Potential panic in Where clause handling.

The code could panic if where.args is empty but the query doesn't contain placeholders.

🧹 Nitpick comments (3)
database/db/query.go (1)

31-40: Replace println with proper logging.

The TODO comment indicates a need for proper logging. This should be addressed before merging.

-	// TODO: use logger instead of println
-	fmt.Println(sql, args, err)
+	if r.config.Debug {
+		r.config.Logger.Info("SQL Query", map[string]any{
+			"query": sql,
+			"args":  args,
+		})
+	}
tests/db_test.go (2)

38-134: Add test cases for error scenarios.

The test suite thoroughly covers successful scenarios but lacks tests for error cases. Consider adding tests for:

  • Inserting nil/empty data
  • Invalid data types
  • Concurrent inserts

Example test case:

s.Run("error cases", func() {
    // Test nil data
    result, err := query.DB().Table("products").Insert(nil)
    s.Error(err)
    s.Nil(result)

    // Test empty slice
    result, err = query.DB().Table("products").Insert([]Product{})
    s.Error(err)
    s.Nil(result)

    // Test invalid type
    result, err = query.DB().Table("products").Insert(42)
    s.Error(err)
    s.Nil(result)
})

136-173: Add test cases for complex Where conditions.

The Where test cases could be expanded to include:

  • Multiple WHERE clauses with AND/OR conditions
  • WHERE IN with empty arrays
  • WHERE with NULL/NOT NULL conditions

Example test cases:

s.Run("complex where conditions", func() {
    var products []Product
    err := query.DB().Table("products").
        Where("name = ?", "where model").
        Where("created_at > ?", now).
        Get(&products)
    s.NoError(err)
    
    err = query.DB().Table("products").
        Where("name", []string{}).
        Get(&products)
    s.NoError(err)
    s.Empty(products)
})
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b666073 and ed2f9cb.

📒 Files selected for processing (3)
  • database/db/query.go (3 hunks)
  • tests/db_test.go (3 hunks)
  • tests/models.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/models.go
🔇 Additional comments (1)
database/db/query.go (1)

15-29: LGTM! Good refactoring to use the builder pattern.

The Query struct and constructor have been updated to use a builder pattern, which improves modularity and testability.

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

♻️ Duplicate comments (1)
database/db/query.go (1)

96-125: ⚠️ Potential issue

Add validation for empty data array.

The function assumes data[0] exists without checking array bounds, which could lead to a panic.

Apply this diff to add validation:

 func (r *Query) buildInsert(data []map[string]any) (sql string, args []any, err error) {
 	if r.conditions.table == "" {
 		return "", nil, errors.DatabaseTableIsRequired
 	}
+	if len(data) == 0 {
+		return "", nil, fmt.Errorf("no data to insert")
+	}
🧹 Nitpick comments (2)
database/db/query.go (1)

31-40: Replace TODO with proper logging.

The function uses a TODO comment for logging. Consider using a proper logging mechanism for SQL queries and their arguments.

Would you like me to help implement a proper logging mechanism for SQL queries?

database/db/query_test.go (1)

37-43: Add more test cases for error scenarios.

Consider adding test cases for:

  • Empty result
  • Database error
  • Invalid query conditions
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed2f9cb and 19a2824.

📒 Files selected for processing (2)
  • database/db/query.go (3 hunks)
  • database/db/query_test.go (1 hunks)
🔇 Additional comments (9)
database/db/query.go (5)

21-29: LGTM! Good use of the builder pattern.

The constructor function has been updated to use a builder pattern, which is a good design choice for SQL operations.


42-51: Replace TODO with proper logging.

The function uses a TODO comment for logging. Consider using a proper logging mechanism for SQL queries and their arguments.


53-83: LGTM! Good error handling and empty data validation.

The function correctly handles empty data and error cases. However, the TODO comment for logging should be addressed.


85-94: LGTM! Good use of immutability.

The function creates a new Query instance instead of modifying the existing one, which is a good practice for maintaining immutability.


127-156: LGTM! Good handling of different where conditions.

The function correctly handles different types of where conditions and placeholders in raw queries.

database/db/query_test.go (4)

15-35: LGTM! Good test setup with proper mocking.

The test setup correctly defines the test model with db tags and initializes the mock builder.


45-52: Add more test cases for error scenarios.

Consider adding test cases for:

  • Empty result
  • Database error
  • Invalid query conditions

54-151: LGTM! Excellent test coverage.

The test suite comprehensively covers various scenarios:

  • Empty data
  • Single and multiple structs
  • Single and multiple maps
  • Error cases (unknown type, exec failure)

153-177: LGTM! Good coverage of where conditions.

The test suite effectively covers various where conditions:

  • Simple where condition
  • Multiple arguments
  • Raw query

@hwbrzzl hwbrzzl merged commit abaac7b into master Feb 19, 2025
13 of 14 checks passed
@hwbrzzl hwbrzzl deleted the bowen/#358-1 branch February 19, 2025 15:12
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.

1 participant