Skip to content

feat: add migration methods Morphs, Uuid and Ulid and morphs for each#1114

Merged
hwbrzzl merged 23 commits intogoravel:masterfrom
ahmed3mar:feature/support-uuid
Jul 9, 2025
Merged

feat: add migration methods Morphs, Uuid and Ulid and morphs for each#1114
hwbrzzl merged 23 commits intogoravel:masterfrom
ahmed3mar:feature/support-uuid

Conversation

@ahmed3mar
Copy link
Contributor

@ahmed3mar ahmed3mar commented Jul 2, 2025

📑 Description

This pull request introduces support for morph columns in polymorphic relationships, along with enhancements to UUID and ULID column handling in the database schema blueprint. It also includes the ability to configure the default morph key type and comprehensive test coverage for these new features.

Morph Column Enhancements:

  • Added methods to Blueprint for creating morph columns: Morphs, NullableMorphs, NumericMorphs, UuidMorphs, and UlidMorphs. These methods generate the necessary type and ID columns, along with optional indexing. (contracts/database/schema/blueprint.go, database/schema/blueprint.go - [1] [2]
  • Introduced morph_config.go to manage the default morph key type (int, uuid, or ulid) with utility functions like SetDefaultMorphKeyType, GetDefaultMorphKeyType, and convenience methods (MorphUsingUuids, MorphUsingUlids, MorphUsingInts). (database/schema/morph_config.go - database/schema/morph_config.goR1-R43)

UUID and ULID Column Support:

  • Added Uuid and Ulid methods to Blueprint for creating respective columns. (contracts/database/schema/blueprint.go, database/schema/blueprint.go - [1] [2]

Testing Enhancements:

  • Added extensive test cases in BlueprintTestSuite to validate the behavior of morph columns, UUID/ULID columns, and morph key type configuration. Tests cover scenarios for default, nullable, and custom key types. (database/schema/blueprint_test.go - database/schema/blueprint_test.goR736-R1081)

Mock Support for Morph Columns:

Related PRs

goravel/sqlserver#30
goravel/sqlite#22
goravel/postgres#56
goravel/mysql#45

✅ Checks

  • Added test cases for my code

Copilot AI review requested due to automatic review settings July 2, 2025 16:20
@ahmed3mar ahmed3mar requested a review from a team as a code owner July 2, 2025 16:20
@codecov
Copy link

codecov bot commented Jul 2, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 66.82%. Comparing base (01cc778) to head (e444efa).
Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1114   +/-   ##
=======================================
  Coverage   66.82%   66.82%           
=======================================
  Files         214      214           
  Lines       14104    14104           
=======================================
  Hits         9425     9425           
  Misses       4303     4303           
  Partials      376      376           

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds polymorphic morph column support and enhances UUID/ULID column handling in the schema blueprint, alongside configuration and test coverage updates.

  • Introduced Morphs, NullableMorphs, NumericMorphs, UuidMorphs, UlidMorphs methods in Blueprint
  • Added global morph key type configuration with convenience functions in morph_config.go
  • Expanded tests for new column types and morph behaviors

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
mocks/database/schema/Blueprint.go Added mock implementations for new morph and ID methods
database/schema/morph_config.go Introduced default morph key type config and utilities
database/schema/blueprint.go Implemented morph and UUID/ULID column builder methods
contracts/database/schema/blueprint.go Updated interface with new methods
database/schema/blueprint_test.go Added tests for Uuid, Ulid, morph methods and config
Comments suppressed due to low confidence (2)

database/schema/blueprint_test.go:807

  • TestUuidMorphs does not include a scenario for custom index names. Consider adding a test similar to TestNumericMorphs to verify custom index naming for UuidMorphs.
func (s *BlueprintTestSuite) TestUuidMorphs() {

database/schema/morph_config.go:19

  • [nitpick] The error message lists valid key types but doesn't include the invalid value passed. Including the actual keyType in the error could aid debugging.
		return fmt.Errorf("morph key type must be '%s', '%s', or '%s'", MorphKeyTypeInt, MorphKeyTypeUuid, MorphKeyTypeUlid)

@almas-x
Copy link
Contributor

almas-x commented Jul 3, 2025

If you modify any file under the contracts folder, please run the go run github.com/vektra/mockery/v2 command in the root directory to generate the mock file.

Copy link
Contributor

@hwbrzzl hwbrzzl left a comment

Choose a reason for hiding this comment

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

Thanks, great PR 👍

Comment on lines +18 to +20
if keyType != MorphKeyTypeInt && keyType != MorphKeyTypeUuid && keyType != MorphKeyTypeUlid {
return fmt.Errorf("morph key type must be '%s', '%s', or '%s'", MorphKeyTypeInt, MorphKeyTypeUuid, MorphKeyTypeUlid)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Given we define a new MorphKeyType type, this judgment is unnecessary.

})
}

func (s *BlueprintTestSuite) TestMorphKeyTypeConfiguration() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you move this test function to morph_config_test.go?

Copy link
Contributor

@hwbrzzl hwbrzzl left a comment

Choose a reason for hiding this comment

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

Left a few questions, and FYI, the merge process when adding new functions in schema will be:

  1. Define new interface functions and implement main logic in goravel/framework
  2. Implement new interface functions in every drivers
  3. Merge all drver PRs first
  4. Add test cases for the new functions in the goravel/framework::tests folder
  5. Merge goravel/framework's PR

Comment on lines +460 to +462
func (r *Blueprint) Uuid(column string) driver.ColumnDefinition {
return r.createAndAddColumn("uuid", column)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Please sort the function based on the first letter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Contributor

Choose a reason for hiding this comment

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

It seems not to be changed.

// TypeUuid Create the column definition for a uuid type.
TypeUuid(column ColumnDefinition) string
// TypeUlid Create the column definition for a ulid type.
TypeUlid(column ColumnDefinition) string
Copy link
Contributor

Choose a reason for hiding this comment

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

Is TypeUlid required? Can TypeChat be used instead? I noticed that TypeUlid is char(26) in each driver.

Copy link
Contributor

Choose a reason for hiding this comment

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

Please run go run github.com/vektra/mockery/v2 to regenerate this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Contributor

Choose a reason for hiding this comment

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

Great tests 👍

Copy link
Contributor

@hwbrzzl hwbrzzl left a comment

Choose a reason for hiding this comment

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

Great 👍 Please add test cases in tests/query_test.go for the new feature.

Comment on lines +385 to +388
columnImpl := r.createAndAddColumn("char", column)
columnImpl.length = &defaultLength

return columnImpl
Copy link
Contributor

Choose a reason for hiding this comment

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

Char can be called here directly.

Comment on lines +460 to +462
func (r *Blueprint) Uuid(column string) driver.ColumnDefinition {
return r.createAndAddColumn("uuid", column)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems not to be changed.

@hwbrzzl
Copy link
Contributor

hwbrzzl commented Jul 9, 2025

Hi @ahmed3mar Thanks for your great PR, and FYI, v1.16 is going to be released in about one/two weeks. I think this PR is almost finished, it only lacks test cases in the tests folder. It would be great if it could be merged before the release.

ahmed3mar added 3 commits July 9, 2025 12:36
…ionships

- Introduced UuidEntity and UlidEntity models for testing UUID and ULID columns.
- Added MorphableEntity, UuidMorphableEntity, and UlidMorphableEntity models for testing polymorphic relationships.
- Implemented comprehensive test cases for UUID and ULID column operations, including creation, retrieval, and format validation.
- Enhanced tests for morphable relationships, ensuring correct functionality across different entity types.
Copy link
Contributor

@hwbrzzl hwbrzzl left a comment

Choose a reason for hiding this comment

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

Great 👍 but CI failed, you can only test postgres driver locally, the speed will be faster: https://github.com/goravel/framework/blob/master/tests/query.go#L131-L143

}

s.Run(fmt.Sprintf("TestUuidColumn_%s", driver), func() {
query.CreateTable(TestTableUuidEntities)
Copy link
Contributor

Choose a reason for hiding this comment

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

It's unnecessary, the table will be created here https://github.com/goravel/framework/blob/master/tests/query_test.go#L44

Copy link
Contributor

Choose a reason for hiding this comment

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

The test cases only covered the create and Find flows, we'd better add some test cases for the Relationship query: facades.Orm().Query().With({morphable_table}).Fine(&user).

Copy link
Contributor

@hwbrzzl hwbrzzl left a comment

Choose a reason for hiding this comment

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

Amazing job 💯 Thanks!

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Race Condition in Global Morph Key Type

The global variable defaultMorphKeyType is subject to race conditions. Multiple functions (e.g., SetDefaultMorphKeyType, GetDefaultMorphKeyType, MorphUsingUuids) access and modify this variable without any synchronization. This lack of protection can lead to inconsistent reads and writes, causing data races when multiple goroutines interact with the morph key type configuration concurrently.

database/schema/morph_config.go#L11-L37

var defaultMorphKeyType MorphKeyType = MorphKeyTypeInt
// SetDefaultMorphKeyType sets the default morph key type
func SetDefaultMorphKeyType(keyType MorphKeyType) {
defaultMorphKeyType = keyType
}
// GetDefaultMorphKeyType returns the current default morph key type
func GetDefaultMorphKeyType() MorphKeyType {
return defaultMorphKeyType
}
// MorphUsingUuids sets the default morph key type to UUID
func MorphUsingUuids() {
defaultMorphKeyType = MorphKeyTypeUuid
}
// MorphUsingUlids sets the default morph key type to ULID
func MorphUsingUlids() {
defaultMorphKeyType = MorphKeyTypeUlid
}
// MorphUsingInts sets the default morph key type to int (default)
func MorphUsingInts() {
defaultMorphKeyType = MorphKeyTypeInt
}

Fix in CursorFix in Web


BugBot free trial expires on July 22, 2025
You have used $0.00 of your $1.00 spend limit so far. Manage your spend limit in the Cursor dashboard.

Was this report helpful? Give feedback by reacting with 👍 or 👎

@hwbrzzl hwbrzzl merged commit fe8bfb1 into goravel:master Jul 9, 2025
14 of 15 checks passed
@ahmed3mar ahmed3mar deleted the feature/support-uuid branch July 9, 2025 15:09
@hwbrzzl
Copy link
Contributor

hwbrzzl commented Jul 22, 2025

Hey @ahmed3mar, thanks for your amazing PRs. Congratulations on getting a v1.16 commemorative T-shirt. I sent a message on Discord, please contact me.

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.

4 participants