feat: try to write orm
This commit is contained in:
commit
45bc30b2f1
156
.gitignore
vendored
Normal file
156
.gitignore
vendored
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### Linux template
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
### Example user template template
|
||||||
|
### Example user template
|
||||||
|
|
||||||
|
# IntelliJ project files
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
|
out
|
||||||
|
gen
|
||||||
|
### Windows template
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
### macOS template
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
10
d3/main.go
Normal file
10
d3/main.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "flag"
|
||||||
|
|
||||||
|
var debug = flag.Bool("debug", false, "dont delete temporary files")
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
}
|
||||||
46
d3/parser/mod.go
Normal file
46
d3/parser/mod.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
doubleSlash = []byte("//")
|
||||||
|
moduleStr = []byte("module")
|
||||||
|
)
|
||||||
|
|
||||||
|
func ModulePath(mod []byte) string {
|
||||||
|
for len(mod) > 0 {
|
||||||
|
line := mod
|
||||||
|
mod = nil
|
||||||
|
if i := bytes.IndexByte(line, '\n'); i >= 0 {
|
||||||
|
line, mod = line[:i], line[i+1:]
|
||||||
|
}
|
||||||
|
if i := bytes.Index(line, doubleSlash); i >= 0 {
|
||||||
|
line = line[:i]
|
||||||
|
}
|
||||||
|
line = bytes.TrimSpace(line)
|
||||||
|
if !bytes.HasPrefix(line, moduleStr) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
line = line[len(moduleStr):]
|
||||||
|
n := len(line)
|
||||||
|
line = bytes.TrimSpace(line)
|
||||||
|
if len(line) == n || len(line) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if line[0] == '"' || line[0] == '`' {
|
||||||
|
p, err := strconv.Unquote(string(line))
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
11
go.mod
Normal file
11
go.mod
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module git.influ.su/artmares/d3orm
|
||||||
|
|
||||||
|
go 1.20
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/stretchr/objx v0.5.0 // indirect
|
||||||
|
github.com/stretchr/testify v1.8.4 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
17
go.sum
Normal file
17
go.sum
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
58
orm/entity/meta.go
Normal file
58
orm/entity/meta.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
type PkStrategy int
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ PkStrategy = iota
|
||||||
|
Auto
|
||||||
|
Manual
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Index struct {
|
||||||
|
Name string
|
||||||
|
Columns []string
|
||||||
|
Unique bool
|
||||||
|
}
|
||||||
|
InternalTools struct {
|
||||||
|
ExtractField FieldExtractor
|
||||||
|
SetFieldValue FieldSetter
|
||||||
|
NewInstance Instantiator
|
||||||
|
Copy Copier
|
||||||
|
CompareField FieldComparator
|
||||||
|
}
|
||||||
|
FieldExtractor func(e any, name string) (any, error)
|
||||||
|
FieldSetter func(e any, name string, value any) error
|
||||||
|
Instantiator func() any
|
||||||
|
Copier func(src any, dst any)
|
||||||
|
FieldComparator func(e1, e2 any, name string) bool
|
||||||
|
)
|
||||||
|
|
||||||
|
type D3Entity interface {
|
||||||
|
D3Token() MetaToken
|
||||||
|
}
|
||||||
|
|
||||||
|
type MetaToken struct {
|
||||||
|
Tools InternalTools
|
||||||
|
Tpl any
|
||||||
|
TableName string
|
||||||
|
Indexes []Index
|
||||||
|
}
|
||||||
|
|
||||||
|
type MetaInfo struct {
|
||||||
|
Tpl any
|
||||||
|
EntityName Name
|
||||||
|
TableName string
|
||||||
|
Indexes []Index
|
||||||
|
|
||||||
|
Relations map[string]Relation
|
||||||
|
}
|
||||||
|
|
||||||
|
type FieldInfo struct {
|
||||||
|
Name string
|
||||||
|
DBAlias string
|
||||||
|
FullDBAlias string
|
||||||
|
AssociatedType reflect.Type
|
||||||
|
}
|
||||||
48
orm/entity/name.go
Normal file
48
orm/entity/name.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Name string
|
||||||
|
|
||||||
|
func NameFromEntity(e any) Name {
|
||||||
|
t := reflect.TypeOf(e)
|
||||||
|
switch t.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
return Name(fmt.Sprintf("%s/%s", t.Elem().PkgPath(), t.Elem().Name()))
|
||||||
|
default:
|
||||||
|
return Name(fmt.Sprintf("%s/%s", t.PkgPath(), t.Name()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func nameFromTag(tag string, parentName Name) Name {
|
||||||
|
defined := Name(tag)
|
||||||
|
if defined.IsShort() {
|
||||||
|
return parentName.Combine(defined)
|
||||||
|
}
|
||||||
|
|
||||||
|
return defined
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n Name) Short() string {
|
||||||
|
path := strings.Split(string(n), "/")
|
||||||
|
|
||||||
|
return path[len(path)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n Name) IsShort() bool {
|
||||||
|
return !strings.Contains(string(n), "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n Name) Equal(name Name) bool {
|
||||||
|
return n == name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n Name) Combine(entity Name) Name {
|
||||||
|
path := strings.Split(string(n), "/")
|
||||||
|
|
||||||
|
return Name(strings.Join(append(path[:len(path)-1], entity.Short()), "/"))
|
||||||
|
}
|
||||||
52
orm/entity/relation.go
Normal file
52
orm/entity/relation.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
type DeleteStrategy int
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ DeleteStrategy = iota
|
||||||
|
None
|
||||||
|
Cascade
|
||||||
|
Nullable
|
||||||
|
)
|
||||||
|
|
||||||
|
func deleteStrategyFromAlias(alias string) DeleteStrategy {
|
||||||
|
switch alias {
|
||||||
|
case "cascade":
|
||||||
|
return Cascade
|
||||||
|
case "nullable":
|
||||||
|
return Nullable
|
||||||
|
default:
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type RelationType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ RelationType = iota
|
||||||
|
Lazy
|
||||||
|
Eager
|
||||||
|
SmartLazy
|
||||||
|
)
|
||||||
|
|
||||||
|
func relationTypeFromAlias(alias string) RelationType {
|
||||||
|
switch alias {
|
||||||
|
case "lazy":
|
||||||
|
return Lazy
|
||||||
|
case "eager":
|
||||||
|
return Eager
|
||||||
|
default:
|
||||||
|
return Lazy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Relation interface {
|
||||||
|
Type() RelationType
|
||||||
|
DeleteStrategy() DeleteStrategy
|
||||||
|
RelationWith() Name
|
||||||
|
|
||||||
|
Field() *FieldInfo
|
||||||
|
|
||||||
|
setField(f *FieldInfo)
|
||||||
|
fillFromTag(tag *parsedTag, parent *MetaInfo)
|
||||||
|
}
|
||||||
138
orm/entity/tag.go
Normal file
138
orm/entity/tag.go
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type property struct {
|
||||||
|
name string
|
||||||
|
value string
|
||||||
|
subProperty map[string]property
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *property) getSubPropVal(name string) string {
|
||||||
|
prop, ok := p.subProperty[name]
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop.value
|
||||||
|
}
|
||||||
|
|
||||||
|
type parsedTag struct {
|
||||||
|
properties map[string]property
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parsedTag) hasProperty(name string) bool {
|
||||||
|
_, ok := p.properties[name]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parsedTag) getProperty(name string) (property, bool) {
|
||||||
|
prop, ok := p.properties[name]
|
||||||
|
return prop, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// one_to_one:"target_entity:Address, join_column:address_id, reference:id"
|
||||||
|
func parseTag(tag reflect.StructTag) *parsedTag {
|
||||||
|
result := &parsedTag{
|
||||||
|
properties: make(map[string]property),
|
||||||
|
}
|
||||||
|
|
||||||
|
tagVal, ok := tag.Lookup("d3")
|
||||||
|
if !ok {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, value := range extractKVFromTag(tagVal) {
|
||||||
|
d3Property := property{
|
||||||
|
name: name,
|
||||||
|
value: value,
|
||||||
|
subProperty: make(map[string]property),
|
||||||
|
}
|
||||||
|
|
||||||
|
for subName, subValue := range extractKVFromValue(value) {
|
||||||
|
d3Property.subProperty[subName] = property{
|
||||||
|
name: subName,
|
||||||
|
value: subValue,
|
||||||
|
subProperty: make(map[string]property),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.properties[name] = d3Property
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractKVFromTag(tag string) map[string]string {
|
||||||
|
result := make(map[string]string)
|
||||||
|
|
||||||
|
var i int
|
||||||
|
for tag != "" {
|
||||||
|
for i < len(tag) && tag[i] != ':' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i >= len(tag) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
name := strings.Trim(tag[:i], " :,")
|
||||||
|
tag = tag[i+1:]
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
for i < len(tag) && tag[i] != '<' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i >= len(tag) {
|
||||||
|
result[name] = strings.Trim(tag[:i], "\" ,")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = tag[i+1:]
|
||||||
|
i = 0
|
||||||
|
for i < len(tag) && tag[i] != '>' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
result[name] = strings.Trim(tag[:i], "\" ,")
|
||||||
|
if i >= len(tag) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
tag = tag[i+1:]
|
||||||
|
i = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractKVFromValue(tag string) map[string]string {
|
||||||
|
result := make(map[string]string)
|
||||||
|
|
||||||
|
var i int
|
||||||
|
for tag != "" {
|
||||||
|
for i < len(tag) && tag[i] != ':' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i >= len(tag) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
name := strings.Trim(tag[:i], " :")
|
||||||
|
tag = tag[i+1:]
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
for i < len(tag) && tag[i] != ',' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
result[name] = strings.Trim(tag[:i], " ")
|
||||||
|
|
||||||
|
if i >= len(tag) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
tag = tag[i+1:]
|
||||||
|
i = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
127
orm/entity/tag_test.go
Normal file
127
orm/entity/tag_test.go
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTagParsing(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
arg string
|
||||||
|
expect *parsedTag
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"One Tag",
|
||||||
|
`d3:"one_to_one:<target_entity:Address, join_column:address_id, reference:id>"`,
|
||||||
|
&parsedTag{
|
||||||
|
properties: map[string]property{
|
||||||
|
"one_to_one": {
|
||||||
|
name: "one_to_one",
|
||||||
|
value: "target_entity:Address, join_column:address_id, reference:id",
|
||||||
|
subProperty: map[string]property{
|
||||||
|
"target_entity": {
|
||||||
|
name: "target_entity",
|
||||||
|
value: "Address",
|
||||||
|
subProperty: map[string]property{},
|
||||||
|
},
|
||||||
|
"join_column": {
|
||||||
|
name: "join_column",
|
||||||
|
value: "address_id",
|
||||||
|
subProperty: map[string]property{},
|
||||||
|
},
|
||||||
|
"reference": {
|
||||||
|
name: "reference",
|
||||||
|
value: "id",
|
||||||
|
subProperty: map[string]property{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Two Tags With Unknown",
|
||||||
|
`d3:"one_to_one: <target_entity:Address , join_column: address_id , reference: id> ",unknown_tag:"key1:val1,key2:val2"`,
|
||||||
|
&parsedTag{
|
||||||
|
properties: map[string]property{
|
||||||
|
"one_to_one": {
|
||||||
|
name: "one_to_one",
|
||||||
|
value: "target_entity:Address , join_column: address_id , reference: id",
|
||||||
|
subProperty: map[string]property{
|
||||||
|
"target_entity": {
|
||||||
|
name: "target_entity",
|
||||||
|
value: "Address",
|
||||||
|
subProperty: map[string]property{},
|
||||||
|
},
|
||||||
|
"join_column": {
|
||||||
|
name: "join_column",
|
||||||
|
value: "address_id",
|
||||||
|
subProperty: map[string]property{},
|
||||||
|
},
|
||||||
|
"reference": {
|
||||||
|
name: "reference",
|
||||||
|
value: "id",
|
||||||
|
subProperty: map[string]property{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Tree Tags",
|
||||||
|
`d3:"one_to_one:<target_entity:Address,join_column:address_id,reference:id>,many_to_one:<target_entity:User>,type:lazy"`,
|
||||||
|
&parsedTag{
|
||||||
|
properties: map[string]property{
|
||||||
|
"one_to_one": {
|
||||||
|
name: "one_to_one",
|
||||||
|
value: "target_entity:Address,join_column:address_id,reference:id",
|
||||||
|
subProperty: map[string]property{
|
||||||
|
"target_entity": {
|
||||||
|
name: "target_entity",
|
||||||
|
value: "Address",
|
||||||
|
subProperty: map[string]property{},
|
||||||
|
},
|
||||||
|
"join_column": {
|
||||||
|
name: "join_column",
|
||||||
|
value: "address_id",
|
||||||
|
subProperty: map[string]property{},
|
||||||
|
},
|
||||||
|
"reference": {
|
||||||
|
name: "reference",
|
||||||
|
value: "id",
|
||||||
|
subProperty: map[string]property{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"many_to_one": {
|
||||||
|
name: "many_to_one",
|
||||||
|
value: "target_entity:User",
|
||||||
|
subProperty: map[string]property{
|
||||||
|
"target_entity": {
|
||||||
|
name: "target_entity",
|
||||||
|
value: "User",
|
||||||
|
subProperty: map[string]property{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
name: "type",
|
||||||
|
value: "lazy",
|
||||||
|
subProperty: map[string]property{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range tests {
|
||||||
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
|
result := parseTag(reflect.StructTag(testCase.arg))
|
||||||
|
require.Equal(t, testCase.expect, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user