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

chore: Merge v1.13 #424

Merged
merged 22 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ DB_PORT=3306
`))
temp, err := os.CreateTemp("", "goravel.env")
assert.Nil(t, err)
defer os.Remove(temp.Name())
defer temp.Close()
defer os.Remove(temp.Name())

_, err = temp.Write([]byte(`
APP_KEY=12345678901234567890123456789012
Expand Down
57 changes: 57 additions & 0 deletions database/gorm/conditions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package gorm

import (
ormcontract "github.com/goravel/framework/contracts/database/orm"
)

type Conditions struct {
distinct []any
group string
having *Having
join []Join
limit *int
lockForUpdate bool
model any
offset *int
omit []string
order []any
scopes []func(ormcontract.Query) ormcontract.Query
selectColumns *Select
sharedLock bool
table *Table
where []Where
with []With
withoutEvents bool
withTrashed bool
}

type Having struct {
query any
args []any
}

type Join struct {
query string
args []any
}

type Select struct {
query any
args []any
}

type Table struct {
name string
args []any
}

type Where struct {
query any
args []any
or bool
}

type With struct {
query string
args []any
}
8 changes: 6 additions & 2 deletions database/gorm/cursor.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@ func (c *CursorImpl) Scan(value any) error {
return err
}

for relation, args := range c.query.with {
if err := c.query.origin.Load(value, relation, args...); err != nil {
for _, item := range c.query.conditions.with {
// Need to new a query, avoid to clear the conditions
query := c.query.new(c.query.instance)
// The new query must be cleared
query.clearConditions()
if err := query.Load(value, item.query, item.args...); err != nil {
return err
}
}
Expand Down
265 changes: 131 additions & 134 deletions database/gorm/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,102 @@
}
}

func (e *Event) ColumnNamesWithDbColumnNames() map[string]string {
if e.columnNamesWithDbColumnNames != nil {
return e.columnNamesWithDbColumnNames

Check warning on line 33 in database/gorm/event.go

View check run for this annotation

Codecov / codecov/patch

database/gorm/event.go#L33

Added line #L33 was not covered by tests
}

res := make(map[string]string)
var modelType reflect.Type
var modelValue reflect.Value

if e.model != nil {
modelType = reflect.TypeOf(e.model)
modelValue = reflect.ValueOf(e.model)
} else {
modelType = reflect.TypeOf(e.dest)
modelValue = reflect.ValueOf(e.dest)
}
if modelType.Kind() == reflect.Pointer {
modelType = modelType.Elem()
modelValue = modelValue.Elem()
}

for i := 0; i < modelType.NumField(); i++ {
if !modelType.Field(i).IsExported() {
continue
}
if modelType.Field(i).Name == "Model" && modelValue.Field(i).Type().Kind() == reflect.Struct {
structField := modelValue.Field(i).Type()
for j := 0; j < structField.NumField(); j++ {
if !structField.Field(i).IsExported() {
continue

Check warning on line 60 in database/gorm/event.go

View check run for this annotation

Codecov / codecov/patch

database/gorm/event.go#L60

Added line #L60 was not covered by tests
}
dbColumn := structNameToDbColumnName(structField.Field(j).Name, structField.Field(j).Tag.Get("gorm"))
res[structField.Field(j).Name] = dbColumn
res[dbColumn] = dbColumn
}
}

dbColumn := structNameToDbColumnName(modelType.Field(i).Name, modelType.Field(i).Tag.Get("gorm"))
res[modelType.Field(i).Name] = dbColumn
res[dbColumn] = dbColumn
}

return res
}

func (e *Event) Context() context.Context {
return e.query.instance.Statement.Context
}

func (e *Event) DestOfMap() map[string]any {
if e.destOfMap != nil {
return e.destOfMap
}

var destOfMap map[string]any
if destMap, ok := e.dest.(map[string]any); ok {
destOfMap = destMap
} else {
destType := reflect.TypeOf(e.dest)
if destType.Kind() == reflect.Pointer {
destType = destType.Elem()
}
if destType.Kind() == reflect.Struct {
destOfMap = structToMap(e.dest)
}
}

e.destOfMap = destOfMap

return e.destOfMap
}

func (e *Event) GetAttribute(key string) any {
destOfMap := e.DestOfMap()
value, exist := destOfMap[e.toDBColumnName(key)]
if exist && e.validColumn(key) && e.validValue(key, value) {
return value
}

return e.GetOriginal(key)
}

func (e *Event) GetOriginal(key string, def ...any) any {
modelOfMap := e.ModelOfMap()
value, exist := modelOfMap[e.toDBColumnName(key)]
if exist {
return value
}

if len(def) > 0 {
return def[0]

Check warning on line 121 in database/gorm/event.go

View check run for this annotation

Codecov / codecov/patch

database/gorm/event.go#L121

Added line #L121 was not covered by tests
}

return nil
}

func (e *Event) IsDirty(columns ...string) bool {
destOfMap := e.DestOfMap()

Expand Down Expand Up @@ -63,15 +159,22 @@
return !e.IsDirty(fields...)
}

func (e *Event) Query() orm.Query {
return NewQueryImplByInstance(e.query.instance.Session(&gorm.Session{NewDB: true}), &QueryImpl{
config: e.query.config,
withoutEvents: false,
})
func (e *Event) ModelOfMap() map[string]any {
if e.modelOfMap != nil {
return e.modelOfMap
}

if e.model == nil {
return map[string]any{}
}

e.modelOfMap = structToMap(e.model)

return e.modelOfMap
}

func (e *Event) Context() context.Context {
return e.query.instance.Statement.Context
func (e *Event) Query() orm.Query {
return NewQueryImpl(e.query.ctx, e.query.config, e.query.connection, e.query.instance.Session(&gorm.Session{NewDB: true}), nil)
}

func (e *Event) SetAttribute(key string, value any) {
Expand Down Expand Up @@ -113,28 +216,35 @@
}
}

func (e *Event) GetAttribute(key string) any {
destOfMap := e.DestOfMap()
value, exist := destOfMap[e.toDBColumnName(key)]
if exist && e.validColumn(key) && e.validValue(key, value) {
return value
func (e *Event) dirty(destColumn string, destValue any) bool {
modelOfMap := e.ModelOfMap()
dbDestColumn := e.toDBColumnName(destColumn)

if modelValue, exist := modelOfMap[dbDestColumn]; exist {
return !reflect.DeepEqual(modelValue, destValue)
}

return e.GetOriginal(key)
return true
}

func (e *Event) GetOriginal(key string, def ...any) any {
modelOfMap := e.ModelOfMap()
value, exist := modelOfMap[e.toDBColumnName(key)]
if exist {
return value
func (e *Event) equalColumnName(origin, source string) bool {
originDbColumnName := e.toDBColumnName(origin)
sourceDbColumnName := e.toDBColumnName(source)

if originDbColumnName == "" || sourceDbColumnName == "" {
return false
}

if len(def) > 0 {
return def[0]
return originDbColumnName == sourceDbColumnName
}

func (e *Event) toDBColumnName(name string) string {
dbColumnName, exist := e.ColumnNamesWithDbColumnNames()[name]
if exist {
return dbColumnName
}

return nil
return ""
}

func (e *Event) validColumn(name string) bool {
Expand Down Expand Up @@ -197,119 +307,6 @@
return !valueValue.IsZero()
}

func (e *Event) dirty(destColumn string, destValue any) bool {
modelOfMap := e.ModelOfMap()
dbDestColumn := e.toDBColumnName(destColumn)

if modelValue, exist := modelOfMap[dbDestColumn]; exist {
return !reflect.DeepEqual(modelValue, destValue)
}

return true
}

func (e *Event) equalColumnName(origin, source string) bool {
originDbColumnName := e.toDBColumnName(origin)
sourceDbColumnName := e.toDBColumnName(source)

if originDbColumnName == "" || sourceDbColumnName == "" {
return false
}

return originDbColumnName == sourceDbColumnName
}

func (e *Event) toDBColumnName(name string) string {
dbColumnName, exist := e.ColumnNamesWithDbColumnNames()[name]
if exist {
return dbColumnName
}

return ""
}

func (e *Event) ModelOfMap() map[string]any {
if e.modelOfMap != nil {
return e.modelOfMap
}

if e.model == nil {
return map[string]any{}
}

e.modelOfMap = structToMap(e.model)

return e.modelOfMap
}

func (e *Event) DestOfMap() map[string]any {
if e.destOfMap != nil {
return e.destOfMap
}

var destOfMap map[string]any
if destMap, ok := e.dest.(map[string]any); ok {
destOfMap = destMap
} else {
destType := reflect.TypeOf(e.dest)
if destType.Kind() == reflect.Pointer {
destType = destType.Elem()
}
if destType.Kind() == reflect.Struct {
destOfMap = structToMap(e.dest)
}
}

e.destOfMap = destOfMap

return e.destOfMap
}

func (e *Event) ColumnNamesWithDbColumnNames() map[string]string {
if e.columnNamesWithDbColumnNames != nil {
return e.columnNamesWithDbColumnNames
}

res := make(map[string]string)
var modelType reflect.Type
var modelValue reflect.Value

if e.model != nil {
modelType = reflect.TypeOf(e.model)
modelValue = reflect.ValueOf(e.model)
} else {
modelType = reflect.TypeOf(e.dest)
modelValue = reflect.ValueOf(e.dest)
}
if modelType.Kind() == reflect.Pointer {
modelType = modelType.Elem()
modelValue = modelValue.Elem()
}

for i := 0; i < modelType.NumField(); i++ {
if !modelType.Field(i).IsExported() {
continue
}
if modelType.Field(i).Name == "Model" && modelValue.Field(i).Type().Kind() == reflect.Struct {
structField := modelValue.Field(i).Type()
for j := 0; j < structField.NumField(); j++ {
if !structField.Field(i).IsExported() {
continue
}
dbColumn := structNameToDbColumnName(structField.Field(j).Name, structField.Field(j).Tag.Get("gorm"))
res[structField.Field(j).Name] = dbColumn
res[dbColumn] = dbColumn
}
}

dbColumn := structNameToDbColumnName(modelType.Field(i).Name, modelType.Field(i).Tag.Get("gorm"))
res[modelType.Field(i).Name] = dbColumn
res[dbColumn] = dbColumn
}

return res
}

func structToMap(data any) map[string]any {
res := make(map[string]any)
modelType := reflect.TypeOf(data)
Expand Down
Loading
Loading