Skip to content

Commit

Permalink
Merge pull request #81 from sev-2/feature/model-fk-index
Browse files Browse the repository at this point in the history
feature(model) support auto index fkey and setup relation on update a…
  • Loading branch information
toopay authored Oct 22, 2024
2 parents f957776 + b24117e commit c9f3591
Show file tree
Hide file tree
Showing 28 changed files with 992 additions and 56 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/raiden.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Setup golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.58.1
version: v1.60
args: --verbose
test:
needs: lint
Expand Down Expand Up @@ -79,4 +79,4 @@ jobs:

- name: Format
if: matrix.go-version == '1.22.x'
run: diff -u <(echo -n) <(gofmt -d .)
run: diff -u <(echo -n) <(gofmt -d .)
1 change: 1 addition & 0 deletions model.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type (
Nullable bool
Default any
Unique bool
Index bool
}

// definition of join tag, example:
Expand Down
25 changes: 23 additions & 2 deletions pkg/generator/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,14 +266,35 @@ func containsRelation(relations []state.Relation, r state.Relation) bool {
return false
}

func BuildJoinTag(r *state.Relation) string {
func BuildRelationTag(r *state.Relation) string {
var tags []string
var joinTags []string

// append json tag
jsonTag := fmt.Sprintf("json:%q", utils.ToSnakeCase(r.Table)+",omitempty")
tags = append(tags, jsonTag)

if r.Action != nil {

onUpdate, onDelete := objects.RelationActionDefaultLabel, objects.RelationActionDefaultLabel
if r.Action.UpdateAction != "" {
code := strings.ToLower(r.Action.UpdateAction)
if v, ok := objects.RelationActionMapLabel[objects.RelationAction(code)]; ok {
onUpdate = v
}
}

if r.Action.DeletionAction != "" {
code := strings.ToLower(r.Action.DeletionAction)
if v, ok := objects.RelationActionMapLabel[objects.RelationAction(code)]; ok {
onDelete = v
}
}

tags = append(tags, fmt.Sprintf("onUpdate:%q", onUpdate))
tags = append(tags, fmt.Sprintf("onDelete:%q", onDelete))
}

// append relation type tag
relTypeTag := fmt.Sprintf("joinType:%s", r.RelationType)
joinTags = append(joinTags, relTypeTag)
Expand Down Expand Up @@ -350,7 +371,7 @@ func BuildRelationFields(table objects.Table, relations []state.Relation) (mappe
r.Table = fmt.Sprintf("%sThrough%s", inflection.Plural(r.Table), utils.SnakeCaseToPascalCase(inflection.Singular(throughSuffix)))
}

r.Tag = BuildJoinTag(&r)
r.Tag = BuildRelationTag(&r)

if !containsRelation(mappedRelations, r) {
mappedRelations = append(mappedRelations, r)
Expand Down
6 changes: 6 additions & 0 deletions pkg/generator/model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ func TestGenerateModels(t *testing.T) {
err1 := utils.CreateFolder(modelPath)
assert.NoError(t, err1)

relationshipAction := objects.TablesRelationshipAction{
UpdateAction: "c",
DeletionAction: "c",
}

tables := []*generator.GenerateModelInput{
{
Table: objects.Table{
Expand All @@ -42,6 +47,7 @@ func TestGenerateModels(t *testing.T) {
Table: "related_table",
ForeignKey: "test_table_id",
PrimaryKey: "id",
Action: &relationshipAction,
},
},
Policies: objects.Policies{},
Expand Down
2 changes: 1 addition & 1 deletion pkg/generator/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func GenerateStorage(folderPath string, storage *GenerateStorageInput, generateF
}

var allowedMimeTypes = ""
if storage.Bucket.AllowedMimeTypes != nil && len(storage.Bucket.AllowedMimeTypes) > 0 {
if len(storage.Bucket.AllowedMimeTypes) > 0 {
allowedMimeTypes = GenerateArrayDeclaration(reflect.ValueOf(storage.Bucket.AllowedMimeTypes), false)
}

Expand Down
9 changes: 4 additions & 5 deletions pkg/resource/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type MigrateData struct {

// Migrate resource :
//
// [ ] migrate table
// [x] migrate table
//
// [x] create table name, schema and columns
// [x] create table rls enable
Expand Down Expand Up @@ -84,8 +84,8 @@ type MigrateData struct {
// [x] create new storage
// [x] update storage
// [x] delete storage
// [ ] add storage acl
// [ ] update storage acl
// [x] add storage acl
// [x] update storage acl
func Apply(flags *Flags, config *raiden.Config) error {
// declare default variable
var migrateData MigrateData
Expand Down Expand Up @@ -165,6 +165,7 @@ func Apply(flags *Flags, config *raiden.Config) error {
}

if flags.All() || flags.ModelsOnly {
resource.Tables = tables.AttachIndexAndAction(resource.Tables, resource.Indexes, resource.RelationActions)
if data, err := tables.BuildMigrateData(appTables, resource.Tables); err != nil {
return err
} else {
Expand Down Expand Up @@ -243,7 +244,6 @@ func Migrate(config *raiden.Config, importState *state.LocalState, projectPath s
ForceCreateRelation: true,
},
})
resource.Tables[i].MigrationItems.ChangeRelationItems = make([]objects.UpdateRelationItem, 0)
} else {
updateTableRelation = append(updateTableRelation, tables.MigrateItem{
Type: t.Type,
Expand All @@ -254,7 +254,6 @@ func Migrate(config *raiden.Config, importState *state.LocalState, projectPath s
ChangeRelationItems: t.MigrationItems.ChangeRelationItems,
},
})
resource.Tables[i].MigrationItems.ChangeRelationItems = make([]objects.UpdateRelationItem, 0)
}
}
}
Expand Down
1 change: 1 addition & 0 deletions pkg/resource/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func Import(flags *Flags, config *raiden.Config) error {
if err != nil {
return err
}
spResource.Tables = tables.AttachIndexAndAction(spResource.Tables, spResource.Indexes, spResource.RelationActions)

// create import state
ImportLogger.Debug("get native roles")
Expand Down
29 changes: 24 additions & 5 deletions pkg/resource/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ import (
var LoadLogger hclog.Logger = logger.HcLog().Named("import.load")

type Resource struct {
Tables []objects.Table
Policies objects.Policies
Roles []objects.Role
Functions []objects.Function
Storages []objects.Bucket
Tables []objects.Table
Policies objects.Policies
Roles []objects.Role
Functions []objects.Function
Storages []objects.Bucket
Indexes []objects.Index
RelationActions []objects.TablesRelationshipAction
}

// The Load function loads resources based on the provided flags and project ID, and returns a resource
Expand Down Expand Up @@ -47,6 +49,12 @@ func Load(flags *Flags, cfg *raiden.Config) (*Resource, error) {
case []objects.Bucket:
resource.Storages = rs
LoadLogger.Debug("Finish Get Bucket From Supabase")
case []objects.Index:
resource.Indexes = rs
LoadLogger.Debug("Finish Get Indexes From Supabase")
case []objects.TablesRelationshipAction:
resource.RelationActions = rs
LoadLogger.Debug("Finish Get Relation Action From Supabase")
case error:
return nil, rs
}
Expand Down Expand Up @@ -99,6 +107,17 @@ func loadResource(cfg *raiden.Config, flags *Flags) <-chan any {
return supabase.GetTables(cfg, supabase.DefaultIncludedSchema)
})

wg.Add(1)
LoadLogger.Debug("Get Index From Supabase")
go loadSupabaseResource(&wg, cfg, outChan, func(cfg *raiden.Config) ([]objects.Index, error) {
return supabase.GetIndexes(cfg, supabase.DefaultIncludedSchema[0])
})

wg.Add(1)
LoadLogger.Debug("Get Table Relation Actions From Supabase")
go loadSupabaseResource(&wg, cfg, outChan, func(cfg *raiden.Config) ([]objects.TablesRelationshipAction, error) {
return supabase.GetTableRelationshipActions(cfg, supabase.DefaultIncludedSchema[0])
})
}

if flags.All() || flags.RolesOnly {
Expand Down
37 changes: 37 additions & 0 deletions pkg/resource/tables/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,43 @@ func compareRelations(table *objects.Table, source, target []objects.TablesRelat
continue
}

if t.Index == nil && sc.Index == nil {
updateItems = append(updateItems, objects.UpdateRelationItem{
Data: sc,
Type: objects.UpdateRelationCreateIndex,
})
Logger.Debug("create new index", "constrain-name", sc.ConstraintName)
}

if t.Action != nil && sc.Action != nil {
if t.Action.UpdateAction != sc.Action.UpdateAction {
updateItems = append(updateItems, objects.UpdateRelationItem{
Data: sc,
Type: objects.UpdateRelationActionOnUpdate,
})
Logger.Debug("check on update", "t-on-update", t.Action.UpdateAction, "sc-on-delete", sc.Action.UpdateAction, "same", t.Action.UpdateAction == sc.Action.UpdateAction)
}

if t.Action.DeletionAction != sc.Action.DeletionAction {
updateItems = append(updateItems, objects.UpdateRelationItem{
Data: sc,
Type: objects.UpdateRelationActionOnDelete,
})
Logger.Debug("check on delete", "t-on-delete", t.Action.DeletionAction, "sc-on-delete", sc.Action.DeletionAction, "same", t.Action.DeletionAction == sc.Action.DeletionAction)
}
} else if t.Action != nil && sc.Action == nil {
updateItems = append(updateItems, objects.UpdateRelationItem{
Data: sc,
Type: objects.UpdateRelationActionOnUpdate,
})

updateItems = append(updateItems, objects.UpdateRelationItem{
Data: sc,
Type: objects.UpdateRelationActionOnDelete,
})
Logger.Debug("create relation new action", "on-update", t.Action.UpdateAction, "on-delete", t.Action.DeletionAction)
}

delete(mapTargetRelation, sc.ConstraintName)

if (sc.SourceSchema != t.SourceSchema) || (sc.SourceTableName != t.SourceTableName) || (sc.SourceColumnName != t.SourceColumnName) {
Expand Down
98 changes: 98 additions & 0 deletions pkg/resource/tables/compare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,102 @@ func TestCompareList(t *testing.T) {
}

func TestCompareItem(t *testing.T) {

sourceRelationshipAction := objects.TablesRelationshipAction{
UpdateAction: "c",
DeletionAction: "c",
}

targetRelationshipAction := objects.TablesRelationshipAction{
UpdateAction: "a",
DeletionAction: "a",
}

source := objects.Table{
ID: 1,
Name: "table1",
Schema: "public",
RLSEnabled: true,
RLSForced: true,
PrimaryKeys: []objects.PrimaryKey{{Name: "id", Schema: "public", TableName: "table1"}},
Columns: []objects.Column{
{Name: "id", DataType: "int", IsNullable: false},
{Name: "name", DataType: "varchar", IsNullable: true},
{Name: "nullable", DataType: "varchar", IsNullable: true},
{Name: "changeable", DataType: "varchar", IsNullable: true},
{Name: "uniqueness", DataType: "varchar", IsNullable: false, IsUnique: true},
{Name: "identity", DataType: "varchar", IsNullable: false, IsIdentity: true},
},
Relationships: []objects.TablesRelationship{
{
ConstraintName: "constraint1",
SourceSchema: "public",
SourceTableName: "table1",
SourceColumnName: "id",
TargetTableSchema: "public",
TargetTableName: "table2",
TargetColumnName: "id",
Index: &objects.Index{Schema: "public", Table: "table1", Name: "index1", Definition: "index1"},
Action: &sourceRelationshipAction,
},
},
}

target := objects.Table{
ID: 1,
Name: "table1_updated",
Schema: "private",
RLSEnabled: false,
RLSForced: false,
PrimaryKeys: []objects.PrimaryKey{{Name: "id", Schema: "public", TableName: "table1"}},
Columns: []objects.Column{
{Name: "id", DataType: "int", IsNullable: false},
{Name: "name", DataType: "varchar", IsNullable: false},
{Name: "description", DataType: "text", IsNullable: true},
{Name: "nullable", DataType: "varchar", IsNullable: false},
{Name: "changeable", DataType: "json", IsNullable: true},
{Name: "uniqueness", DataType: "varchar", IsNullable: false, IsUnique: false},
{Name: "identity", DataType: "varchar", IsNullable: false, IsIdentity: false},
},
Relationships: []objects.TablesRelationship{
{
ConstraintName: "constraint1",
SourceSchema: "public",
SourceTableName: "table1",
SourceColumnName: "id",
TargetTableSchema: "public",
TargetTableName: "table2",
TargetColumnName: "id",
Index: &objects.Index{Schema: "public", Table: "table1", Name: "index1", Definition: "index1"},
Action: &targetRelationshipAction,
},
{
ConstraintName: "constraint2",
SourceSchema: "public",
SourceTableName: "table1",
SourceColumnName: "name",
TargetTableSchema: "public",
TargetTableName: "table2",
TargetColumnName: "name",
Action: &targetRelationshipAction,
},
},
}

diffResult := tables.CompareItem(source, target)
assert.True(t, diffResult.IsConflict)
assert.Equal(t, "table1", diffResult.SourceResource.Name)
assert.Equal(t, "table1_updated", diffResult.TargetResource.Name)
assert.Equal(t, []objects.UpdateColumnType{objects.UpdateColumnNullable}, diffResult.DiffItems.ChangeColumnItems[0].UpdateItems)
assert.Equal(t, []objects.UpdateColumnType{objects.UpdateColumnNullable}, diffResult.DiffItems.ChangeColumnItems[1].UpdateItems)
}

func TestCompareItemWithoutIndex(t *testing.T) {
targetRelationshipAction := objects.TablesRelationshipAction{
UpdateAction: "c",
DeletionAction: "c",
}

source := objects.Table{
ID: 1,
Name: "table1",
Expand All @@ -84,6 +180,7 @@ func TestCompareItem(t *testing.T) {
TargetTableSchema: "public",
TargetTableName: "table2",
TargetColumnName: "id",
Action: nil,
},
},
}
Expand Down Expand Up @@ -113,6 +210,7 @@ func TestCompareItem(t *testing.T) {
TargetTableSchema: "public",
TargetTableName: "table2",
TargetColumnName: "id",
Action: &targetRelationshipAction,
},
{
ConstraintName: "constraint2",
Expand Down
Loading

0 comments on commit c9f3591

Please sign in to comment.