refactor: implement native database/sql repositories#8
Merged
Conversation
Remove github.com/allisson/sqlutil library and replace with native Go
database/sql implementations. This change creates separate repository
implementations for MySQL and PostgreSQL, providing better control,
clarity, and eliminating external dependencies.
Breaking Changes:
- UserRepository split into MySQLUserRepository and PostgreSQLUserRepository
- OutboxEventRepository split into MySQLOutboxEventRepository and PostgreSQLOutboxEventRepository
- Repositories now return interfaces from usecase package instead of concrete types
- DI container updated to instantiate correct repository based on DB_DRIVER config
Changes:
- internal/database/txmanager.go:
* Remove sqlutil.Querier import
* Define custom Querier interface matching database/sql
* Update GetTx() to return new Querier interface
- internal/user/repository/:
* Delete user_repository.go (unified implementation)
* Add mysql_user_repository.go with MySQL-specific implementation
- Uses BINARY(16) for UUID storage with marshal/unmarshal
- Uses ? placeholders for parameters
- MySQL-specific unique constraint error detection
* Add postgresql_user_repository.go with PostgreSQL-specific implementation
- Uses native UUID type
- Uses $1, $2, $3... numbered placeholders
- PostgreSQL-specific unique constraint error detection
* Add mysql_user_repository_test.go with comprehensive tests
* Add postgresql_user_repository_test.go with comprehensive tests
* Delete user_repository_test.go (old tests)
- internal/outbox/repository/:
* Delete outbox_repository.go (unified implementation)
* Add mysql_outbox_repository.go with MySQL-specific implementation
* Add postgresql_outbox_repository.go with PostgreSQL-specific implementation
* Add mysql_outbox_repository_test.go with comprehensive tests
* Add postgresql_outbox_repository_test.go with comprehensive tests
* Delete outbox_repository_test.go (old tests)
- internal/app/di.go:
* Update Container struct to use interface types for repositories
* Update UserRepository() to return userUsecase.UserRepository interface
* Update OutboxRepository() to return userUsecase.OutboxEventRepository interface
* Update initUserRepository() to switch on DBDriver and instantiate correct implementation
* Update initOutboxRepository() to switch on DBDriver and instantiate correct implementation
- go.mod:
* Remove github.com/allisson/sqlutil v1.10.0
* Remove indirect dependencies: sqlquery, scany, sqlbuilder, xstrings
- Documentation:
* README.md: Add "Database Repository Pattern" section explaining the architecture
* README.md: Update all code examples to show database/sql usage
* README.md: Update project structure to show separate repository files
* README.md: Update dependencies list removing sqlutil
* internal/app/README.md: Update dependency graph showing interface pattern
* internal/app/README.md: Update initialization examples with driver switch logic
Implementation Details:
MySQL Repositories:
- Use BINARY(16) for UUID storage requiring ID.MarshalBinary() for writes
and ID.UnmarshalBinary() for reads
- Use ? placeholders for all query parameters
- Detect unique violations by checking for "1062" or "duplicate entry" in error messages
- Use FOR UPDATE SKIP LOCKED syntax for outbox event locking
PostgreSQL Repositories:
- Use native UUID type, passing uuid.UUID directly without conversion
- Use numbered placeholders ($1, $2, $3...)
- Detect unique violations by checking for "duplicate key" or "unique constraint"
- Use FOR UPDATE SKIP LOCKED syntax for outbox event locking
Benefits:
- Zero external dependencies for database operations (standard library only)
- Database-specific optimizations (native UUID support in PostgreSQL)
- Explicit SQL queries improve code clarity and maintainability
- Easier to debug and optimize database-specific issues
- Better type safety without abstraction layers
- Reduced dependency tree and faster builds
Testing:
- All existing tests updated and passing
- New tests cover MySQL and PostgreSQL implementations separately
- Tests use sqlmock for database mocking
- Coverage maintained at same level as before
Lint:
- Fixed errcheck warnings by adding //nolint:errcheck to defer rows.Close()
- All golangci-lint checks passing (0 issues)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Remove github.com/allisson/sqlutil library and replace with native Go database/sql implementations. This change creates separate repository implementations for MySQL and PostgreSQL, providing better control, clarity, and eliminating external dependencies.
Breaking Changes:
Changes:
Implementation Details:
MySQL Repositories:
Benefits:
Testing:
Lint: