-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(cmfx/relationship): 添加 relationship 包
- Loading branch information
Showing
4 changed files
with
199 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// SPDX-FileCopyrightText: 2025 caixw | ||
// | ||
// SPDX-License-Identifier: MIT | ||
|
||
package relationship | ||
|
||
type relationshipPO[T1, T2 T] struct { | ||
V1 T1 `orm:"name(v1);unique(v12)"` | ||
V2 T2 `orm:"name(v2);unique(v12)"` | ||
} | ||
|
||
func (*relationshipPO[T1, T2]) TableName() string { return "_relationships" } |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// SPDX-FileCopyrightText: 2025 caixw | ||
// | ||
// SPDX-License-Identifier: MIT | ||
|
||
package relationship | ||
|
||
import ( | ||
"github.com/issue9/orm/v6" | ||
"github.com/issue9/orm/v6/fetch" | ||
"github.com/issue9/web" | ||
|
||
"github.com/issue9/cmfx/cmfx" | ||
) | ||
|
||
type Module[T1, T2 T] struct { | ||
db *orm.DB | ||
mod *cmfx.Module | ||
} | ||
|
||
func Load[T1, T2 T](mod *cmfx.Module, prefix string) *Module[T1, T2] { | ||
return &Module[T1, T2]{ | ||
db: buildDB(mod, prefix), | ||
mod: mod, | ||
} | ||
} | ||
|
||
func Install[T1, T2 T](mod *cmfx.Module, prefix string) *Module[T1, T2] { | ||
db := buildDB(mod, prefix) | ||
if err := db.Create(&relationshipPO[T1, T2]{}); err != nil { | ||
panic(web.SprintError(mod.Server().Locale().Printer(), true, err)) | ||
} | ||
|
||
return Load[T1, T2](mod, prefix) | ||
} | ||
|
||
func (m *Module[T1, T2]) engine(tx *orm.Tx) orm.Engine { | ||
if tx == nil { | ||
return m.db | ||
} | ||
return tx.NewEngine(m.db.TablePrefix()) | ||
} | ||
|
||
func (m *Module[T1, T2]) Add(tx *orm.Tx, v1 T1, v2 T2) error { | ||
_, err := m.engine(tx).Insert(&relationshipPO[T1, T2]{V1: v1, V2: v2}) | ||
return err | ||
} | ||
|
||
func (m *Module[T1, T2]) Delete(tx *orm.Tx, v1 T1, v2 T2) error { | ||
_, err := m.engine(tx).Delete(&relationshipPO[T1, T2]{V1: v1, V2: v2}) | ||
return err | ||
} | ||
|
||
func (m *Module[T1, T2]) DeleteByV1(tx *orm.Tx, v1 T1) error { | ||
_, err := m.engine(tx).Where("v1=?", v1).Delete(&relationshipPO[T1, T2]{}) | ||
return err | ||
} | ||
|
||
func (m *Module[T1, T2]) DeleteByV2(tx *orm.Tx, v2 T2) error { | ||
_, err := m.engine(tx).Where("v2=?", v2).Delete(&relationshipPO[T1, T2]{}) | ||
return err | ||
} | ||
|
||
func (m *Module[T1, T2]) CountByV1(v1 T1) (int64, error) { | ||
return m.db.Where("v1=?", v1).Count(&relationshipPO[T1, T2]{}) | ||
} | ||
|
||
func (m *Module[T1, T2]) CountByV2(v2 T2) (int64, error) { | ||
return m.db.Where("v2=?", v2).Count(&relationshipPO[T1, T2]{}) | ||
} | ||
|
||
// ListV1 列出所有与 v2 关联的 v1 列表 | ||
func (m *Module[T1, T2]) ListV1(v2 T2) ([]T1, error) { | ||
rows, err := m.db.SQLBuilder().Select().From(orm.TableName(&relationshipPO[T1, T2]{})).Where("v2=?", v2).Query() | ||
if err != nil { | ||
return nil, err | ||
} | ||
return fetch.Column[T1](false, "v1", rows) | ||
} | ||
|
||
// ListV2 列出所有与 v1 关联的 v2 列表 | ||
func (m *Module[T1, T2]) ListV2(v1 T1) ([]T2, error) { | ||
rows, err := m.db.SQLBuilder().Select().From(orm.TableName(&relationshipPO[T1, T2]{})).Where("v1=?", v1).Query() | ||
if err != nil { | ||
return nil, err | ||
} | ||
return fetch.Column[T2](false, "v2", rows) | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// SPDX-FileCopyrightText: 2025 caixw | ||
// | ||
// SPDX-License-Identifier: MIT | ||
|
||
package relationship | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/issue9/assert/v4" | ||
|
||
"github.com/issue9/cmfx/cmfx/initial/test" | ||
) | ||
|
||
func TestInstall(t *testing.T) { | ||
a := assert.New(t, false) | ||
suite := test.NewSuite(a) | ||
defer suite.Close() | ||
|
||
mod := suite.NewModule("rbac") | ||
Install[string, int](mod, "t1_t2") | ||
|
||
suite.TableExists(mod.ID() + "_t1_t2_relationships") | ||
} | ||
|
||
func TestModule(t *testing.T) { | ||
a := assert.New(t, false) | ||
s := test.NewSuite(a) | ||
defer s.Close() | ||
|
||
mod := s.NewModule("rbac") | ||
m := Install[string, int](mod, "t1_t2") | ||
|
||
// Add | ||
|
||
a.NotError(m.Add(nil, "v", 1)) | ||
a.NotError(m.Add(nil, "v", 2)) | ||
a.NotError(m.Add(nil, "v", 3)) | ||
|
||
// Count | ||
|
||
cnt, err := m.CountByV1("v") | ||
a.NotError(err).Equal(cnt, 3) | ||
|
||
cnt, err = m.CountByV2(3) | ||
a.NotError(err).Equal(cnt, 1) | ||
|
||
cnt, err = m.CountByV2(100) | ||
a.NotError(err).Equal(cnt, 0) | ||
|
||
// List | ||
|
||
list1, err := m.ListV1(2) | ||
a.NotError(err).Equal(list1, []string{"v"}) | ||
|
||
list2, err := m.ListV2("v") | ||
a.NotError(err).Equal(list2, []int{1, 2, 3}) | ||
|
||
list2, err = m.ListV2("vv") // 不存在的数据 | ||
a.NotError(err).Equal(list2, []int{}) | ||
|
||
// Delete | ||
|
||
a.NotError(m.Delete(nil, "v", 1)) | ||
cnt, err = m.CountByV1("v") | ||
a.NotError(err).Equal(cnt, 2) // 删除了一条 | ||
|
||
a.NotError(m.Delete(nil, "vv", 2)) // 不存在 | ||
cnt, err = m.CountByV1("v") | ||
a.NotError(err).Equal(cnt, 2) | ||
|
||
a.NotError(m.DeleteByV2(nil, 2)) | ||
cnt, err = m.CountByV1("v") | ||
a.NotError(err).Equal(cnt, 1) | ||
|
||
a.NotError(m.DeleteByV1(nil, "v")) | ||
cnt, err = m.CountByV1("v") | ||
a.NotError(err).Equal(cnt, 0) | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// SPDX-FileCopyrightText: 2025 caixw | ||
// | ||
// SPDX-License-Identifier: MIT | ||
|
||
// Package relationship 用于处理多对多的数据表关系 | ||
package relationship | ||
|
||
import ( | ||
"github.com/issue9/orm/v6" | ||
|
||
"github.com/issue9/cmfx/cmfx" | ||
) | ||
|
||
// T 限制了可用的字段类型 | ||
type T interface { | ||
~string | ~int | ~int64 | ||
} | ||
|
||
func buildDB(mod *cmfx.Module, tableName string) *orm.DB { | ||
return mod.DB().New(mod.DB().TablePrefix() + "_" + tableName) | ||
} |