Support referencing field of another struct
This commit is contained in:
parent
706706e91e
commit
d4f3591912
14 changed files with 826 additions and 354 deletions
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -29,7 +29,7 @@ jobs:
|
||||||
- name: Vet & Lint
|
- name: Vet & Lint
|
||||||
run: |
|
run: |
|
||||||
go vet ./...
|
go vet ./...
|
||||||
golint ./...
|
golint -set_exit_status ./...
|
||||||
|
|
||||||
- uses: codecov/codecov-action@v1
|
- uses: codecov/codecov-action@v1
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -2,8 +2,8 @@ coverage:
|
||||||
status:
|
status:
|
||||||
project:
|
project:
|
||||||
default:
|
default:
|
||||||
target: 85%
|
target: 90%
|
||||||
threshold: 3%
|
threshold: 3%
|
||||||
patch:
|
patch:
|
||||||
default:
|
default:
|
||||||
target: 75%
|
target: 80%
|
||||||
|
|
|
@ -165,7 +165,7 @@ func getType(expr ast.Expr) Type {
|
||||||
|
|
||||||
case *ast.ArrayType:
|
case *ast.ArrayType:
|
||||||
containedType := getType(expr.Elt)
|
containedType := getType(expr.Elt)
|
||||||
return ArrayType{containedType}
|
return ArrayType{ContainedType: containedType}
|
||||||
|
|
||||||
case *ast.InterfaceType:
|
case *ast.InterfaceType:
|
||||||
var methods []Method
|
var methods []Method
|
||||||
|
|
|
@ -9,30 +9,36 @@ import (
|
||||||
"github.com/sunboyy/repogen/internal/spec"
|
"github.com/sunboyy/repogen/internal/spec"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
idField = code.StructField{
|
||||||
|
Name: "ID",
|
||||||
|
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
||||||
|
Tags: map[string][]string{"bson": {"_id", "omitempty"}},
|
||||||
|
}
|
||||||
|
genderField = code.StructField{
|
||||||
|
Name: "Gender",
|
||||||
|
Type: code.SimpleType("Gender"),
|
||||||
|
Tags: map[string][]string{"bson": {"gender"}},
|
||||||
|
}
|
||||||
|
ageField = code.StructField{
|
||||||
|
Name: "Age",
|
||||||
|
Type: code.SimpleType("int"),
|
||||||
|
Tags: map[string][]string{"bson": {"age"}},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func TestGenerateMongoRepository(t *testing.T) {
|
func TestGenerateMongoRepository(t *testing.T) {
|
||||||
userModel := code.Struct{
|
userModel := code.Struct{
|
||||||
Name: "UserModel",
|
Name: "UserModel",
|
||||||
Fields: code.StructFields{
|
Fields: code.StructFields{
|
||||||
{
|
idField,
|
||||||
Name: "ID",
|
|
||||||
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
|
||||||
Tags: map[string][]string{"bson": {"_id", "omitempty"}},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: "Username",
|
Name: "Username",
|
||||||
Type: code.SimpleType("string"),
|
Type: code.SimpleType("string"),
|
||||||
Tags: map[string][]string{"bson": {"username"}},
|
Tags: map[string][]string{"bson": {"username"}},
|
||||||
},
|
},
|
||||||
{
|
genderField,
|
||||||
Name: "Gender",
|
ageField,
|
||||||
Type: code.SimpleType("Gender"),
|
|
||||||
Tags: map[string][]string{"bson": {"gender"}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Age",
|
|
||||||
Type: code.SimpleType("int"),
|
|
||||||
Tags: map[string][]string{"bson": {"age"}},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
methods := []spec.MethodSpec{
|
methods := []spec.MethodSpec{
|
||||||
|
@ -48,7 +54,7 @@ func TestGenerateMongoRepository(t *testing.T) {
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "ID", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -70,8 +76,8 @@ func TestGenerateMongoRepository(t *testing.T) {
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Operator: spec.OperatorAnd,
|
Operator: spec.OperatorAnd,
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Gender", Comparator: spec.ComparatorNot, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, Comparator: spec.ComparatorNot, ParamIndex: 1},
|
||||||
{Field: "Age", Comparator: spec.ComparatorLessThan, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorLessThan, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -90,11 +96,11 @@ func TestGenerateMongoRepository(t *testing.T) {
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorLessThanEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorLessThanEqual, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Sorts: []spec.Sort{
|
Sorts: []spec.Sort{
|
||||||
{FieldName: "Age", Ordering: spec.OrderingAscending},
|
{FieldReference: spec.FieldReference{ageField}, Ordering: spec.OrderingAscending},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -112,11 +118,11 @@ func TestGenerateMongoRepository(t *testing.T) {
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorGreaterThan, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorGreaterThan, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Sorts: []spec.Sort{
|
Sorts: []spec.Sort{
|
||||||
{FieldName: "Age", Ordering: spec.OrderingAscending},
|
{FieldReference: spec.FieldReference{ageField}, Ordering: spec.OrderingAscending},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -134,11 +140,11 @@ func TestGenerateMongoRepository(t *testing.T) {
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorGreaterThanEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorGreaterThanEqual, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Sorts: []spec.Sort{
|
Sorts: []spec.Sort{
|
||||||
{FieldName: "Age", Ordering: spec.OrderingDescending},
|
{FieldReference: spec.FieldReference{ageField}, Ordering: spec.OrderingDescending},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -157,7 +163,7 @@ func TestGenerateMongoRepository(t *testing.T) {
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorBetween, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorBetween, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -178,8 +184,8 @@ func TestGenerateMongoRepository(t *testing.T) {
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Operator: spec.OperatorOr,
|
Operator: spec.OperatorOr,
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
{Field: "Age", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,8 +2,8 @@ package mongo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/sunboyy/repogen/internal/code"
|
"github.com/sunboyy/repogen/internal/code"
|
||||||
|
@ -126,13 +126,13 @@ func (g RepositoryGenerator) mongoSorts(sortSpec []spec.Sort) ([]sort, error) {
|
||||||
var sorts []sort
|
var sorts []sort
|
||||||
|
|
||||||
for _, s := range sortSpec {
|
for _, s := range sortSpec {
|
||||||
bsonTag, err := g.bsonTagFromFieldName(s.FieldName)
|
bsonFieldReference, err := g.bsonFieldReference(s.FieldReference)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sorts = append(sorts, sort{
|
sorts = append(sorts, sort{
|
||||||
BsonTag: bsonTag,
|
BsonTag: bsonFieldReference,
|
||||||
Ordering: s.Ordering,
|
Ordering: s.Ordering,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -169,11 +169,11 @@ func (g RepositoryGenerator) getMongoUpdate(updateSpec spec.Update) (update, err
|
||||||
case spec.UpdateFields:
|
case spec.UpdateFields:
|
||||||
var update updateFields
|
var update updateFields
|
||||||
for _, field := range updateSpec {
|
for _, field := range updateSpec {
|
||||||
bsonTag, err := g.bsonTagFromFieldName(field.Name)
|
bsonFieldReference, err := g.bsonFieldReference(field.FieldReference)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return querySpec{}, err
|
||||||
}
|
}
|
||||||
update.Fields = append(update.Fields, updateField{BsonTag: bsonTag, ParamIndex: field.ParamIndex})
|
update.Fields = append(update.Fields, updateField{BsonTag: bsonFieldReference, ParamIndex: field.ParamIndex})
|
||||||
}
|
}
|
||||||
return update, nil
|
return update, nil
|
||||||
default:
|
default:
|
||||||
|
@ -214,13 +214,13 @@ func (g RepositoryGenerator) mongoQuerySpec(query spec.QuerySpec) (querySpec, er
|
||||||
var predicates []predicate
|
var predicates []predicate
|
||||||
|
|
||||||
for _, predicateSpec := range query.Predicates {
|
for _, predicateSpec := range query.Predicates {
|
||||||
bsonTag, err := g.bsonTagFromFieldName(predicateSpec.Field)
|
bsonFieldReference, err := g.bsonFieldReference(predicateSpec.FieldReference)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return querySpec{}, err
|
return querySpec{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
predicates = append(predicates, predicate{
|
predicates = append(predicates, predicate{
|
||||||
Field: bsonTag,
|
Field: bsonFieldReference,
|
||||||
Comparator: predicateSpec.Comparator,
|
Comparator: predicateSpec.Comparator,
|
||||||
ParamIndex: predicateSpec.ParamIndex,
|
ParamIndex: predicateSpec.ParamIndex,
|
||||||
})
|
})
|
||||||
|
@ -232,15 +232,22 @@ func (g RepositoryGenerator) mongoQuerySpec(query spec.QuerySpec) (querySpec, er
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g RepositoryGenerator) bsonTagFromFieldName(fieldName string) (string, error) {
|
func (g RepositoryGenerator) bsonFieldReference(fieldReference spec.FieldReference) (string, error) {
|
||||||
structField, ok := g.StructModel.Fields.ByName(fieldName)
|
var bsonTags []string
|
||||||
if !ok {
|
for _, field := range fieldReference {
|
||||||
return "", fmt.Errorf("struct field %s not found", fieldName)
|
tag, err := g.bsonTagFromField(field)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
|
bsonTags = append(bsonTags, tag)
|
||||||
|
}
|
||||||
|
return strings.Join(bsonTags, "."), nil
|
||||||
|
}
|
||||||
|
|
||||||
bsonTag, ok := structField.Tags["bson"]
|
func (g RepositoryGenerator) bsonTagFromField(field code.StructField) (string, error) {
|
||||||
|
bsonTag, ok := field.Tags["bson"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", NewBsonTagNotFoundError(fieldName)
|
return "", NewBsonTagNotFoundError(field.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return bsonTag[0], nil
|
return bsonTag[0], nil
|
||||||
|
|
|
@ -10,38 +10,58 @@ import (
|
||||||
"github.com/sunboyy/repogen/internal/testutils"
|
"github.com/sunboyy/repogen/internal/testutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var userModel = code.Struct{
|
var (
|
||||||
Name: "UserModel",
|
idField = code.StructField{
|
||||||
Fields: code.StructFields{
|
|
||||||
{
|
|
||||||
Name: "ID",
|
Name: "ID",
|
||||||
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
||||||
Tags: map[string][]string{"bson": {"_id", "omitempty"}},
|
Tags: map[string][]string{"bson": {"_id", "omitempty"}},
|
||||||
},
|
}
|
||||||
|
genderField = code.StructField{
|
||||||
|
Name: "Gender",
|
||||||
|
Type: code.SimpleType("Gender"),
|
||||||
|
Tags: map[string][]string{"bson": {"gender"}},
|
||||||
|
}
|
||||||
|
ageField = code.StructField{
|
||||||
|
Name: "Age",
|
||||||
|
Type: code.SimpleType("int"),
|
||||||
|
Tags: map[string][]string{"bson": {"age"}},
|
||||||
|
}
|
||||||
|
nameField = code.StructField{
|
||||||
|
Name: "Name",
|
||||||
|
Type: code.SimpleType("NameModel"),
|
||||||
|
Tags: map[string][]string{"bson": {"name"}},
|
||||||
|
}
|
||||||
|
enabledField = code.StructField{
|
||||||
|
Name: "Enabled",
|
||||||
|
Type: code.SimpleType("bool"),
|
||||||
|
Tags: map[string][]string{"bson": {"enabled"}},
|
||||||
|
}
|
||||||
|
accessTokenField = code.StructField{
|
||||||
|
Name: "AccessToken",
|
||||||
|
Type: code.SimpleType("string"),
|
||||||
|
}
|
||||||
|
|
||||||
|
firstNameField = code.StructField{
|
||||||
|
Name: "First",
|
||||||
|
Type: code.SimpleType("string"),
|
||||||
|
Tags: map[string][]string{"bson": {"first"}},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var userModel = code.Struct{
|
||||||
|
Name: "UserModel",
|
||||||
|
Fields: code.StructFields{
|
||||||
|
idField,
|
||||||
{
|
{
|
||||||
Name: "Username",
|
Name: "Username",
|
||||||
Type: code.SimpleType("string"),
|
Type: code.SimpleType("string"),
|
||||||
Tags: map[string][]string{"bson": {"username"}},
|
Tags: map[string][]string{"bson": {"username"}},
|
||||||
},
|
},
|
||||||
{
|
genderField,
|
||||||
Name: "Gender",
|
ageField,
|
||||||
Type: code.SimpleType("Gender"),
|
nameField,
|
||||||
Tags: map[string][]string{"bson": {"gender"}},
|
enabledField,
|
||||||
},
|
accessTokenField,
|
||||||
{
|
|
||||||
Name: "Age",
|
|
||||||
Type: code.SimpleType("int"),
|
|
||||||
Tags: map[string][]string{"bson": {"age"}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Enabled",
|
|
||||||
Type: code.SimpleType("bool"),
|
|
||||||
Tags: map[string][]string{"bson": {"enabled"}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "AccessToken",
|
|
||||||
Type: code.SimpleType("string"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +203,7 @@ func TestGenerateMethod_Find(t *testing.T) {
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorEqual, Field: "ID", ParamIndex: 1},
|
{Comparator: spec.ComparatorEqual, FieldReference: spec.FieldReference{idField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -217,7 +237,7 @@ func (r *UserRepositoryMongo) FindByID(arg0 context.Context, arg1 primitive.Obje
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorEqual, Field: "Gender", ParamIndex: 1},
|
{Comparator: spec.ComparatorEqual, FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -237,6 +257,44 @@ func (r *UserRepositoryMongo) FindByGender(arg0 context.Context, arg1 Gender) ([
|
||||||
}
|
}
|
||||||
return entities, nil
|
return entities, nil
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "find with deep field reference",
|
||||||
|
MethodSpec: spec.MethodSpec{
|
||||||
|
Name: "FindByNameFirst",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Name: "firstName", Type: code.SimpleType("string")},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
Operation: spec.FindOperation{
|
||||||
|
Mode: spec.QueryModeOne,
|
||||||
|
Query: spec.QuerySpec{
|
||||||
|
Predicates: []spec.Predicate{
|
||||||
|
{
|
||||||
|
Comparator: spec.ComparatorEqual,
|
||||||
|
FieldReference: spec.FieldReference{nameField, firstNameField},
|
||||||
|
ParamIndex: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedCode: `
|
||||||
|
func (r *UserRepositoryMongo) FindByNameFirst(arg0 context.Context, arg1 string) (*UserModel, error) {
|
||||||
|
var entity UserModel
|
||||||
|
if err := r.collection.FindOne(arg0, bson.M{
|
||||||
|
"name.first": arg1,
|
||||||
|
}, options.FindOne().SetSort(bson.M{
|
||||||
|
})).Decode(&entity); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &entity, nil
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -257,8 +315,8 @@ func (r *UserRepositoryMongo) FindByGender(arg0 context.Context, arg1 Gender) ([
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Operator: spec.OperatorAnd,
|
Operator: spec.OperatorAnd,
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorEqual, Field: "Gender", ParamIndex: 1},
|
{Comparator: spec.ComparatorEqual, FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
{Comparator: spec.ComparatorEqual, Field: "Age", ParamIndex: 2},
|
{Comparator: spec.ComparatorEqual, FieldReference: spec.FieldReference{ageField}, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -301,8 +359,8 @@ func (r *UserRepositoryMongo) FindByGenderAndAge(arg0 context.Context, arg1 Gend
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Operator: spec.OperatorOr,
|
Operator: spec.OperatorOr,
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorEqual, Field: "Gender", ParamIndex: 1},
|
{Comparator: spec.ComparatorEqual, FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
{Comparator: spec.ComparatorEqual, Field: "Age", ParamIndex: 2},
|
{Comparator: spec.ComparatorEqual, FieldReference: spec.FieldReference{ageField}, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -343,7 +401,7 @@ func (r *UserRepositoryMongo) FindByGenderOrAge(arg0 context.Context, arg1 Gende
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorNot, Field: "Gender", ParamIndex: 1},
|
{Comparator: spec.ComparatorNot, FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -381,7 +439,7 @@ func (r *UserRepositoryMongo) FindByGenderNot(arg0 context.Context, arg1 Gender)
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorLessThan, Field: "Age", ParamIndex: 1},
|
{Comparator: spec.ComparatorLessThan, FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -419,7 +477,7 @@ func (r *UserRepositoryMongo) FindByAgeLessThan(arg0 context.Context, arg1 int)
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorLessThanEqual, Field: "Age", ParamIndex: 1},
|
{Comparator: spec.ComparatorLessThanEqual, FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -457,7 +515,7 @@ func (r *UserRepositoryMongo) FindByAgeLessThanEqual(arg0 context.Context, arg1
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorGreaterThan, Field: "Age", ParamIndex: 1},
|
{Comparator: spec.ComparatorGreaterThan, FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -495,7 +553,7 @@ func (r *UserRepositoryMongo) FindByAgeGreaterThan(arg0 context.Context, arg1 in
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorGreaterThanEqual, Field: "Age", ParamIndex: 1},
|
{Comparator: spec.ComparatorGreaterThanEqual, FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -534,7 +592,7 @@ func (r *UserRepositoryMongo) FindByAgeGreaterThanEqual(arg0 context.Context, ar
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorBetween, Field: "Age", ParamIndex: 1},
|
{Comparator: spec.ComparatorBetween, FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -572,7 +630,7 @@ func (r *UserRepositoryMongo) FindByAgeBetween(arg0 context.Context, arg1 int, a
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorIn, Field: "Gender", ParamIndex: 1},
|
{Comparator: spec.ComparatorIn, FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -610,7 +668,7 @@ func (r *UserRepositoryMongo) FindByGenderIn(arg0 context.Context, arg1 []Gender
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorNotIn, Field: "Gender", ParamIndex: 1},
|
{Comparator: spec.ComparatorNotIn, FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -647,7 +705,7 @@ func (r *UserRepositoryMongo) FindByGenderNotIn(arg0 context.Context, arg1 []Gen
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorTrue, Field: "Enabled", ParamIndex: 1},
|
{Comparator: spec.ComparatorTrue, FieldReference: spec.FieldReference{enabledField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -684,7 +742,7 @@ func (r *UserRepositoryMongo) FindByEnabledTrue(arg0 context.Context) ([]*UserMo
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorFalse, Field: "Enabled", ParamIndex: 1},
|
{Comparator: spec.ComparatorFalse, FieldReference: spec.FieldReference{enabledField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -720,7 +778,7 @@ func (r *UserRepositoryMongo) FindByEnabledFalse(arg0 context.Context) ([]*UserM
|
||||||
Operation: spec.FindOperation{
|
Operation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Sorts: []spec.Sort{
|
Sorts: []spec.Sort{
|
||||||
{FieldName: "Age", Ordering: spec.OrderingAscending},
|
{FieldReference: spec.FieldReference{ageField}, Ordering: spec.OrderingAscending},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -745,7 +803,7 @@ func (r *UserRepositoryMongo) FindAllOrderByAge(arg0 context.Context) ([]*UserMo
|
||||||
{
|
{
|
||||||
Name: "find with sort descending",
|
Name: "find with sort descending",
|
||||||
MethodSpec: spec.MethodSpec{
|
MethodSpec: spec.MethodSpec{
|
||||||
Name: "FindAllOrderByAge",
|
Name: "FindAllOrderByAgeDesc",
|
||||||
Params: []code.Param{
|
Params: []code.Param{
|
||||||
{Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
{Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
},
|
},
|
||||||
|
@ -756,12 +814,12 @@ func (r *UserRepositoryMongo) FindAllOrderByAge(arg0 context.Context) ([]*UserMo
|
||||||
Operation: spec.FindOperation{
|
Operation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Sorts: []spec.Sort{
|
Sorts: []spec.Sort{
|
||||||
{FieldName: "Age", Ordering: spec.OrderingDescending},
|
{FieldReference: spec.FieldReference{ageField}, Ordering: spec.OrderingDescending},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedCode: `
|
ExpectedCode: `
|
||||||
func (r *UserRepositoryMongo) FindAllOrderByAge(arg0 context.Context) ([]*UserModel, error) {
|
func (r *UserRepositoryMongo) FindAllOrderByAgeDesc(arg0 context.Context) ([]*UserModel, error) {
|
||||||
cursor, err := r.collection.Find(arg0, bson.M{
|
cursor, err := r.collection.Find(arg0, bson.M{
|
||||||
|
|
||||||
}, options.Find().SetSort(bson.M{
|
}, options.Find().SetSort(bson.M{
|
||||||
|
@ -776,6 +834,42 @@ func (r *UserRepositoryMongo) FindAllOrderByAge(arg0 context.Context) ([]*UserMo
|
||||||
}
|
}
|
||||||
return entities, nil
|
return entities, nil
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "find with deep sort ascending",
|
||||||
|
MethodSpec: spec.MethodSpec{
|
||||||
|
Name: "FindAllOrderByNameFirst",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
Operation: spec.FindOperation{
|
||||||
|
Mode: spec.QueryModeMany,
|
||||||
|
Sorts: []spec.Sort{
|
||||||
|
{FieldReference: spec.FieldReference{nameField, firstNameField}, Ordering: spec.OrderingAscending},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedCode: `
|
||||||
|
func (r *UserRepositoryMongo) FindAllOrderByNameFirst(arg0 context.Context) ([]*UserModel, error) {
|
||||||
|
cursor, err := r.collection.Find(arg0, bson.M{
|
||||||
|
|
||||||
|
}, options.Find().SetSort(bson.M{
|
||||||
|
"name.first": 1,
|
||||||
|
}))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var entities []*UserModel
|
||||||
|
if err := cursor.All(arg0, &entities); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return entities, nil
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -792,8 +886,8 @@ func (r *UserRepositoryMongo) FindAllOrderByAge(arg0 context.Context) ([]*UserMo
|
||||||
Operation: spec.FindOperation{
|
Operation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Sorts: []spec.Sort{
|
Sorts: []spec.Sort{
|
||||||
{FieldName: "Gender", Ordering: spec.OrderingAscending},
|
{FieldReference: spec.FieldReference{genderField}, Ordering: spec.OrderingAscending},
|
||||||
{FieldName: "Age", Ordering: spec.OrderingDescending},
|
{FieldReference: spec.FieldReference{ageField}, Ordering: spec.OrderingDescending},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -855,7 +949,7 @@ func TestGenerateMethod_Update(t *testing.T) {
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "ID", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -889,12 +983,12 @@ func (r *UserRepositoryMongo) UpdateByID(arg0 context.Context, arg1 *UserModel,
|
||||||
},
|
},
|
||||||
Operation: spec.UpdateOperation{
|
Operation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{Name: "Age", ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "ID", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -930,12 +1024,12 @@ func (r *UserRepositoryMongo) UpdateAgeByID(arg0 context.Context, arg1 int, arg2
|
||||||
},
|
},
|
||||||
Operation: spec.UpdateOperation{
|
Operation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{Name: "Age", ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{genderField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -954,6 +1048,47 @@ func (r *UserRepositoryMongo) UpdateAgeByGender(arg0 context.Context, arg1 int,
|
||||||
}
|
}
|
||||||
return int(result.MatchedCount), err
|
return int(result.MatchedCount), err
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "update with deeply referenced field",
|
||||||
|
MethodSpec: spec.MethodSpec{
|
||||||
|
Name: "UpdateNameFirstByID",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Name: "firstName", Type: code.SimpleType("string")},
|
||||||
|
{Name: "id", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.SimpleType("bool"),
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
Operation: spec.UpdateOperation{
|
||||||
|
Update: spec.UpdateFields{
|
||||||
|
{FieldReference: spec.FieldReference{nameField, firstNameField}, ParamIndex: 1},
|
||||||
|
},
|
||||||
|
Mode: spec.QueryModeOne,
|
||||||
|
Query: spec.QuerySpec{
|
||||||
|
Predicates: []spec.Predicate{
|
||||||
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedCode: `
|
||||||
|
func (r *UserRepositoryMongo) UpdateNameFirstByID(arg0 context.Context, arg1 string, arg2 primitive.ObjectID) (bool, error) {
|
||||||
|
result, err := r.collection.UpdateOne(arg0, bson.M{
|
||||||
|
"_id": arg2,
|
||||||
|
}, bson.M{
|
||||||
|
"$set": bson.M{
|
||||||
|
"name.first": arg1,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return result.MatchedCount > 0, err
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -990,7 +1125,7 @@ func TestGenerateMethod_Delete(t *testing.T) {
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorEqual, Field: "ID", ParamIndex: 1},
|
{Comparator: spec.ComparatorEqual, FieldReference: spec.FieldReference{idField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1023,7 +1158,7 @@ func (r *UserRepositoryMongo) DeleteByID(arg0 context.Context, arg1 primitive.Ob
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorEqual, Field: "Gender", ParamIndex: 1},
|
{Comparator: spec.ComparatorEqual, FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1058,8 +1193,8 @@ func (r *UserRepositoryMongo) DeleteByGender(arg0 context.Context, arg1 Gender)
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Operator: spec.OperatorAnd,
|
Operator: spec.OperatorAnd,
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorEqual, Field: "Gender", ParamIndex: 1},
|
{Comparator: spec.ComparatorEqual, FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
{Comparator: spec.ComparatorEqual, Field: "Age", ParamIndex: 2},
|
{Comparator: spec.ComparatorEqual, FieldReference: spec.FieldReference{ageField}, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1097,8 +1232,8 @@ func (r *UserRepositoryMongo) DeleteByGenderAndAge(arg0 context.Context, arg1 Ge
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Operator: spec.OperatorOr,
|
Operator: spec.OperatorOr,
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorEqual, Field: "Gender", ParamIndex: 1},
|
{Comparator: spec.ComparatorEqual, FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
{Comparator: spec.ComparatorEqual, Field: "Age", ParamIndex: 2},
|
{Comparator: spec.ComparatorEqual, FieldReference: spec.FieldReference{ageField}, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1134,7 +1269,7 @@ func (r *UserRepositoryMongo) DeleteByGenderOrAge(arg0 context.Context, arg1 Gen
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorNot, Field: "Gender", ParamIndex: 1},
|
{Comparator: spec.ComparatorNot, FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1167,7 +1302,7 @@ func (r *UserRepositoryMongo) DeleteByGenderNot(arg0 context.Context, arg1 Gende
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorLessThan, Field: "Age", ParamIndex: 1},
|
{Comparator: spec.ComparatorLessThan, FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1200,7 +1335,7 @@ func (r *UserRepositoryMongo) DeleteByAgeLessThan(arg0 context.Context, arg1 int
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorLessThanEqual, Field: "Age", ParamIndex: 1},
|
{Comparator: spec.ComparatorLessThanEqual, FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1233,7 +1368,7 @@ func (r *UserRepositoryMongo) DeleteByAgeLessThanEqual(arg0 context.Context, arg
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorGreaterThan, Field: "Age", ParamIndex: 1},
|
{Comparator: spec.ComparatorGreaterThan, FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1266,7 +1401,7 @@ func (r *UserRepositoryMongo) DeleteByAgeGreaterThan(arg0 context.Context, arg1
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorGreaterThanEqual, Field: "Age", ParamIndex: 1},
|
{Comparator: spec.ComparatorGreaterThanEqual, FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1300,7 +1435,7 @@ func (r *UserRepositoryMongo) DeleteByAgeGreaterThanEqual(arg0 context.Context,
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorBetween, Field: "Age", ParamIndex: 1},
|
{Comparator: spec.ComparatorBetween, FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1333,7 +1468,7 @@ func (r *UserRepositoryMongo) DeleteByAgeBetween(arg0 context.Context, arg1 int,
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Comparator: spec.ComparatorIn, Field: "Gender", ParamIndex: 1},
|
{Comparator: spec.ComparatorIn, FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1386,7 +1521,7 @@ func TestGenerateMethod_Count(t *testing.T) {
|
||||||
Operation: spec.CountOperation{
|
Operation: spec.CountOperation{
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1420,8 +1555,8 @@ func (r *UserRepositoryMongo) CountByGender(arg0 context.Context, arg1 Gender) (
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Operator: spec.OperatorAnd,
|
Operator: spec.OperatorAnd,
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
{Field: "Age", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1458,8 +1593,8 @@ func (r *UserRepositoryMongo) CountByGenderAndCity(arg0 context.Context, arg1 Ge
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Operator: spec.OperatorOr,
|
Operator: spec.OperatorOr,
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
{Field: "Age", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1494,7 +1629,7 @@ func (r *UserRepositoryMongo) CountByGenderOrCity(arg0 context.Context, arg1 Gen
|
||||||
Operation: spec.CountOperation{
|
Operation: spec.CountOperation{
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Gender", Comparator: spec.ComparatorNot, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, Comparator: spec.ComparatorNot, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1526,7 +1661,7 @@ func (r *UserRepositoryMongo) CountByGenderNot(arg0 context.Context, arg1 Gender
|
||||||
Operation: spec.CountOperation{
|
Operation: spec.CountOperation{
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorLessThan, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorLessThan, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1558,7 +1693,7 @@ func (r *UserRepositoryMongo) CountByAgeLessThan(arg0 context.Context, arg1 int)
|
||||||
Operation: spec.CountOperation{
|
Operation: spec.CountOperation{
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorLessThanEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorLessThanEqual, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1590,7 +1725,7 @@ func (r *UserRepositoryMongo) CountByAgeLessThanEqual(arg0 context.Context, arg1
|
||||||
Operation: spec.CountOperation{
|
Operation: spec.CountOperation{
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorGreaterThan, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorGreaterThan, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1622,7 +1757,7 @@ func (r *UserRepositoryMongo) CountByAgeGreaterThan(arg0 context.Context, arg1 i
|
||||||
Operation: spec.CountOperation{
|
Operation: spec.CountOperation{
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorGreaterThanEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorGreaterThanEqual, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1655,7 +1790,7 @@ func (r *UserRepositoryMongo) CountByAgeGreaterThanEqual(arg0 context.Context, a
|
||||||
Operation: spec.CountOperation{
|
Operation: spec.CountOperation{
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorBetween, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorBetween, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1687,7 +1822,7 @@ func (r *UserRepositoryMongo) CountByAgeBetween(arg0 context.Context, arg1 int,
|
||||||
Operation: spec.CountOperation{
|
Operation: spec.CountOperation{
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorIn, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorIn, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1770,7 +1905,7 @@ func TestGenerateMethod_Invalid(t *testing.T) {
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "AccessToken", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{accessTokenField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1791,7 +1926,7 @@ func TestGenerateMethod_Invalid(t *testing.T) {
|
||||||
Operation: spec.FindOperation{
|
Operation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Sorts: []spec.Sort{
|
Sorts: []spec.Sort{
|
||||||
{FieldName: "AccessToken", Ordering: spec.OrderingAscending},
|
{FieldReference: spec.FieldReference{accessTokenField}, Ordering: spec.OrderingAscending},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1812,12 +1947,12 @@ func TestGenerateMethod_Invalid(t *testing.T) {
|
||||||
},
|
},
|
||||||
Operation: spec.UpdateOperation{
|
Operation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{Name: "AccessToken", ParamIndex: 1},
|
{FieldReference: spec.FieldReference{accessTokenField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "ID", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1842,7 +1977,7 @@ func TestGenerateMethod_Invalid(t *testing.T) {
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "ID", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -75,8 +75,8 @@ func (err unknownOperationError) Error() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStructFieldNotFoundError creates structFieldNotFoundError
|
// NewStructFieldNotFoundError creates structFieldNotFoundError
|
||||||
func NewStructFieldNotFoundError(fieldName string) error {
|
func NewStructFieldNotFoundError(tokens []string) error {
|
||||||
return structFieldNotFoundError{FieldName: fieldName}
|
return structFieldNotFoundError{FieldName: strings.Join(tokens, "")}
|
||||||
}
|
}
|
||||||
|
|
||||||
type structFieldNotFoundError struct {
|
type structFieldNotFoundError struct {
|
||||||
|
|
|
@ -22,13 +22,13 @@ func TestError(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "StructFieldNotFoundError",
|
Name: "StructFieldNotFoundError",
|
||||||
Error: spec.NewStructFieldNotFoundError("Country"),
|
Error: spec.NewStructFieldNotFoundError([]string{"Phone", "Number"}),
|
||||||
ExpectedString: "struct field 'Country' not found",
|
ExpectedString: "struct field 'PhoneNumber' not found",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "InvalidQueryError",
|
Name: "InvalidQueryError",
|
||||||
Error: spec.NewInvalidQueryError([]string{"By", "And"}),
|
Error: spec.NewInvalidQueryError([]string{"And"}),
|
||||||
ExpectedString: "invalid query 'ByAnd'",
|
ExpectedString: "invalid query 'And'",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "IncompatibleComparatorError",
|
Name: "IncompatibleComparatorError",
|
||||||
|
|
64
internal/spec/field.go
Normal file
64
internal/spec/field.go
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
package spec
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sunboyy/repogen/internal/code"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FieldReference is a reference path to access to the field
|
||||||
|
type FieldReference []code.StructField
|
||||||
|
|
||||||
|
// ReferencedField returns the last struct field
|
||||||
|
func (r FieldReference) ReferencedField() code.StructField {
|
||||||
|
return r[len(r)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
type fieldResolver struct {
|
||||||
|
Structs code.Structs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r fieldResolver) ResolveStructField(structModel code.Struct, tokens []string) (FieldReference, bool) {
|
||||||
|
fieldName := strings.Join(tokens, "")
|
||||||
|
field, ok := structModel.Fields.ByName(fieldName)
|
||||||
|
if ok {
|
||||||
|
return FieldReference{field}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := len(tokens) - 1; i > 0; i-- {
|
||||||
|
fieldName := strings.Join(tokens[:i], "")
|
||||||
|
field, ok := structModel.Fields.ByName(fieldName)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldSimpleType, ok := getSimpleType(field.Type)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
childStruct, ok := r.Structs.ByName(fieldSimpleType.Code())
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fields, ok := r.ResolveStructField(childStruct, tokens[i:])
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return append(FieldReference{field}, fields...), true
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSimpleType(t code.Type) (code.SimpleType, bool) {
|
||||||
|
switch t := t.(type) {
|
||||||
|
case code.SimpleType:
|
||||||
|
return t, true
|
||||||
|
case code.PointerType:
|
||||||
|
return getSimpleType(t.ContainedType)
|
||||||
|
default:
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,7 +50,7 @@ func (o FindOperation) Name() string {
|
||||||
|
|
||||||
// Sort is a detail of sorting find result
|
// Sort is a detail of sorting find result
|
||||||
type Sort struct {
|
type Sort struct {
|
||||||
FieldName string
|
FieldReference FieldReference
|
||||||
Ordering Ordering
|
Ordering Ordering
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ func (o UpdateOperation) Name() string {
|
||||||
|
|
||||||
// UpdateField stores mapping between field name in the model and the parameter index
|
// UpdateField stores mapping between field name in the model and the parameter index
|
||||||
type UpdateField struct {
|
type UpdateField struct {
|
||||||
Name string
|
FieldReference FieldReference
|
||||||
ParamIndex int
|
ParamIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
package spec
|
package spec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/fatih/camelcase"
|
"github.com/fatih/camelcase"
|
||||||
"github.com/sunboyy/repogen/internal/code"
|
"github.com/sunboyy/repogen/internal/code"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseInterfaceMethod returns repository method spec from declared interface method
|
// ParseInterfaceMethod returns repository method spec from declared interface method
|
||||||
func ParseInterfaceMethod(structModel code.Struct, method code.Method) (MethodSpec, error) {
|
func ParseInterfaceMethod(structs code.Structs, structModel code.Struct, method code.Method) (MethodSpec, error) {
|
||||||
parser := interfaceMethodParser{
|
parser := interfaceMethodParser{
|
||||||
|
fieldResolver: fieldResolver{
|
||||||
|
Structs: structs,
|
||||||
|
},
|
||||||
StructModel: structModel,
|
StructModel: structModel,
|
||||||
Method: method,
|
Method: method,
|
||||||
}
|
}
|
||||||
|
@ -18,6 +19,7 @@ func ParseInterfaceMethod(structModel code.Struct, method code.Method) (MethodSp
|
||||||
}
|
}
|
||||||
|
|
||||||
type interfaceMethodParser struct {
|
type interfaceMethodParser struct {
|
||||||
|
fieldResolver fieldResolver
|
||||||
StructModel code.Struct
|
StructModel code.Struct
|
||||||
Method code.Method
|
Method code.Method
|
||||||
}
|
}
|
||||||
|
@ -115,7 +117,7 @@ func (p interfaceMethodParser) parseFindOperation(tokens []string) (Operation, e
|
||||||
|
|
||||||
queryTokens, sortTokens := p.splitQueryAndSortTokens(tokens)
|
queryTokens, sortTokens := p.splitQueryAndSortTokens(tokens)
|
||||||
|
|
||||||
querySpec, err := parseQuery(queryTokens, 1)
|
querySpec, err := p.parseQuery(queryTokens, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -145,38 +147,43 @@ func (p interfaceMethodParser) parseSort(rawTokens []string) ([]Sort, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sortTokens := rawTokens[2:]
|
sortTokens, ok := splitByAnd(rawTokens[2:])
|
||||||
|
if !ok {
|
||||||
|
return nil, NewInvalidSortError(rawTokens)
|
||||||
|
}
|
||||||
|
|
||||||
var sorts []Sort
|
var sorts []Sort
|
||||||
var aggregatedToken sortToken
|
|
||||||
for _, token := range sortTokens {
|
for _, token := range sortTokens {
|
||||||
if token != "And" {
|
sort, err := p.parseSortToken(token)
|
||||||
aggregatedToken = append(aggregatedToken, token)
|
if err != nil {
|
||||||
} else if len(aggregatedToken) == 0 {
|
return nil, err
|
||||||
return nil, NewInvalidSortError(rawTokens)
|
|
||||||
} else {
|
|
||||||
sorts = append(sorts, aggregatedToken.ToSort())
|
|
||||||
aggregatedToken = sortToken{}
|
|
||||||
}
|
}
|
||||||
|
sorts = append(sorts, sort)
|
||||||
}
|
}
|
||||||
if len(aggregatedToken) == 0 {
|
|
||||||
return nil, NewInvalidSortError(rawTokens)
|
|
||||||
}
|
|
||||||
sorts = append(sorts, aggregatedToken.ToSort())
|
|
||||||
|
|
||||||
return sorts, nil
|
return sorts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type sortToken []string
|
func (p interfaceMethodParser) parseSortToken(t []string) (Sort, error) {
|
||||||
|
|
||||||
func (t sortToken) ToSort() Sort {
|
|
||||||
if len(t) > 1 && t[len(t)-1] == "Asc" {
|
if len(t) > 1 && t[len(t)-1] == "Asc" {
|
||||||
return Sort{FieldName: strings.Join(t[:len(t)-1], ""), Ordering: OrderingAscending}
|
return p.createSort(t[:len(t)-1], OrderingAscending)
|
||||||
}
|
}
|
||||||
if len(t) > 1 && t[len(t)-1] == "Desc" {
|
if len(t) > 1 && t[len(t)-1] == "Desc" {
|
||||||
return Sort{FieldName: strings.Join(t[:len(t)-1], ""), Ordering: OrderingDescending}
|
return p.createSort(t[:len(t)-1], OrderingDescending)
|
||||||
}
|
}
|
||||||
return Sort{FieldName: strings.Join(t, ""), Ordering: OrderingAscending}
|
return p.createSort(t, OrderingAscending)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p interfaceMethodParser) createSort(t []string, ordering Ordering) (Sort, error) {
|
||||||
|
fields, ok := p.fieldResolver.ResolveStructField(p.StructModel, t)
|
||||||
|
if !ok {
|
||||||
|
return Sort{}, NewStructFieldNotFoundError(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Sort{
|
||||||
|
FieldReference: fields,
|
||||||
|
Ordering: ordering,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p interfaceMethodParser) splitQueryAndSortTokens(tokens []string) ([]string, []string) {
|
func (p interfaceMethodParser) splitQueryAndSortTokens(tokens []string) ([]string, []string) {
|
||||||
|
@ -245,7 +252,7 @@ func (p interfaceMethodParser) parseUpdateOperation(tokens []string) (Operation,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
querySpec, err := parseQuery(queryTokens, 1+update.NumberOfArguments())
|
querySpec, err := p.parseQuery(queryTokens, 1+update.NumberOfArguments())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -270,37 +277,57 @@ func (p interfaceMethodParser) parseUpdate(tokens []string) (Update, error) {
|
||||||
return UpdateModel{}, nil
|
return UpdateModel{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateFieldTokens, ok := splitByAnd(tokens)
|
||||||
|
if !ok {
|
||||||
|
return nil, InvalidUpdateFieldsError
|
||||||
|
}
|
||||||
|
|
||||||
|
var updateFields UpdateFields
|
||||||
|
|
||||||
paramIndex := 1
|
paramIndex := 1
|
||||||
var update UpdateFields
|
for _, updateFieldToken := range updateFieldTokens {
|
||||||
var aggregatedToken string
|
updateFieldReference, ok := p.fieldResolver.ResolveStructField(p.StructModel, updateFieldToken)
|
||||||
|
if !ok {
|
||||||
|
return nil, NewStructFieldNotFoundError(updateFieldToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFields = append(updateFields, UpdateField{
|
||||||
|
FieldReference: updateFieldReference,
|
||||||
|
ParamIndex: paramIndex,
|
||||||
|
})
|
||||||
|
paramIndex++
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, field := range updateFields {
|
||||||
|
if len(p.Method.Params) <= field.ParamIndex ||
|
||||||
|
field.FieldReference.ReferencedField().Type != p.Method.Params[field.ParamIndex].Type {
|
||||||
|
return nil, InvalidUpdateFieldsError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateFields, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitByAnd(tokens []string) ([][]string, bool) {
|
||||||
|
var updateFieldTokens [][]string
|
||||||
|
var aggregatedToken []string
|
||||||
|
|
||||||
for _, token := range tokens {
|
for _, token := range tokens {
|
||||||
if token != "And" {
|
if token != "And" {
|
||||||
aggregatedToken += token
|
aggregatedToken = append(aggregatedToken, token)
|
||||||
} else if len(aggregatedToken) == 0 {
|
} else if len(aggregatedToken) == 0 {
|
||||||
return nil, InvalidUpdateFieldsError
|
return nil, false
|
||||||
} else {
|
} else {
|
||||||
update = append(update, UpdateField{Name: aggregatedToken, ParamIndex: paramIndex})
|
updateFieldTokens = append(updateFieldTokens, aggregatedToken)
|
||||||
paramIndex++
|
aggregatedToken = nil
|
||||||
aggregatedToken = ""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(aggregatedToken) == 0 {
|
if len(aggregatedToken) == 0 {
|
||||||
return nil, InvalidUpdateFieldsError
|
return nil, false
|
||||||
}
|
}
|
||||||
update = append(update, UpdateField{Name: aggregatedToken, ParamIndex: paramIndex})
|
updateFieldTokens = append(updateFieldTokens, aggregatedToken)
|
||||||
|
|
||||||
for _, field := range update {
|
return updateFieldTokens, true
|
||||||
structField, ok := p.StructModel.Fields.ByName(field.Name)
|
|
||||||
if !ok {
|
|
||||||
return nil, NewStructFieldNotFoundError(field.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p.Method.Params) <= field.ParamIndex || structField.Type != p.Method.Params[field.ParamIndex].Type {
|
|
||||||
return nil, InvalidUpdateFieldsError
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return update, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p interfaceMethodParser) splitUpdateAndQueryTokens(tokens []string) ([]string, []string) {
|
func (p interfaceMethodParser) splitUpdateAndQueryTokens(tokens []string) ([]string, []string) {
|
||||||
|
@ -325,7 +352,7 @@ func (p interfaceMethodParser) parseDeleteOperation(tokens []string) (Operation,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
querySpec, err := parseQuery(tokens, 1)
|
querySpec, err := p.parseQuery(tokens, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -349,7 +376,7 @@ func (p interfaceMethodParser) parseCountOperation(tokens []string) (Operation,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
querySpec, err := parseQuery(tokens, 1)
|
querySpec, err := p.parseQuery(tokens, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -420,19 +447,15 @@ func (p interfaceMethodParser) validateQueryFromParams(params []code.Param, quer
|
||||||
|
|
||||||
var currentParamIndex int
|
var currentParamIndex int
|
||||||
for _, predicate := range querySpec.Predicates {
|
for _, predicate := range querySpec.Predicates {
|
||||||
structField, ok := p.StructModel.Fields.ByName(predicate.Field)
|
|
||||||
if !ok {
|
|
||||||
return NewStructFieldNotFoundError(predicate.Field)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (predicate.Comparator == ComparatorTrue || predicate.Comparator == ComparatorFalse) &&
|
if (predicate.Comparator == ComparatorTrue || predicate.Comparator == ComparatorFalse) &&
|
||||||
structField.Type != code.SimpleType("bool") {
|
predicate.FieldReference.ReferencedField().Type != code.SimpleType("bool") {
|
||||||
return NewIncompatibleComparatorError(predicate.Comparator, structField)
|
return NewIncompatibleComparatorError(predicate.Comparator,
|
||||||
|
predicate.FieldReference.ReferencedField())
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < predicate.Comparator.NumberOfArguments(); i++ {
|
for i := 0; i < predicate.Comparator.NumberOfArguments(); i++ {
|
||||||
if params[currentParamIndex].Type != predicate.Comparator.ArgumentTypeFromFieldType(
|
if params[currentParamIndex].Type != predicate.Comparator.ArgumentTypeFromFieldType(
|
||||||
structField.Type) {
|
predicate.FieldReference.ReferencedField().Type) {
|
||||||
return InvalidParamError
|
return InvalidParamError
|
||||||
}
|
}
|
||||||
currentParamIndex++
|
currentParamIndex++
|
||||||
|
@ -441,3 +464,11 @@ func (p interfaceMethodParser) validateQueryFromParams(params []code.Param, quer
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p interfaceMethodParser) parseQuery(queryTokens []string, paramIndex int) (QuerySpec, error) {
|
||||||
|
queryParser := queryParser{
|
||||||
|
fieldResolver: p.fieldResolver,
|
||||||
|
StructModel: p.StructModel,
|
||||||
|
}
|
||||||
|
return queryParser.parseQuery(queryTokens, paramIndex)
|
||||||
|
}
|
||||||
|
|
|
@ -8,34 +8,87 @@ import (
|
||||||
"github.com/sunboyy/repogen/internal/spec"
|
"github.com/sunboyy/repogen/internal/spec"
|
||||||
)
|
)
|
||||||
|
|
||||||
var structModel = code.Struct{
|
var (
|
||||||
Name: "UserModel",
|
idField = code.StructField{
|
||||||
Fields: code.StructFields{
|
|
||||||
{
|
|
||||||
Name: "ID",
|
Name: "ID",
|
||||||
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
||||||
},
|
}
|
||||||
{
|
phoneNumberField = code.StructField{
|
||||||
Name: "PhoneNumber",
|
Name: "PhoneNumber",
|
||||||
Type: code.SimpleType("string"),
|
Type: code.SimpleType("string"),
|
||||||
},
|
}
|
||||||
{
|
genderField = code.StructField{
|
||||||
Name: "Gender",
|
Name: "Gender",
|
||||||
Type: code.SimpleType("Gender"),
|
Type: code.SimpleType("Gender"),
|
||||||
},
|
}
|
||||||
{
|
cityField = code.StructField{
|
||||||
Name: "City",
|
Name: "City",
|
||||||
Type: code.SimpleType("string"),
|
Type: code.SimpleType("string"),
|
||||||
},
|
}
|
||||||
{
|
ageField = code.StructField{
|
||||||
Name: "Age",
|
Name: "Age",
|
||||||
Type: code.SimpleType("int"),
|
Type: code.SimpleType("int"),
|
||||||
},
|
}
|
||||||
{
|
nameField = code.StructField{
|
||||||
|
Name: "Name",
|
||||||
|
Type: code.SimpleType("NameModel"),
|
||||||
|
}
|
||||||
|
contactField = code.StructField{
|
||||||
|
Name: "Contact",
|
||||||
|
Type: code.SimpleType("ContactModel"),
|
||||||
|
}
|
||||||
|
referrerField = code.StructField{
|
||||||
|
Name: "Referrer",
|
||||||
|
Type: code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||||
|
}
|
||||||
|
defaultPaymentField = code.StructField{
|
||||||
|
Name: "DefaultPayment",
|
||||||
|
Type: code.ExternalType{PackageAlias: "payment", Name: "Payment"},
|
||||||
|
}
|
||||||
|
enabledField = code.StructField{
|
||||||
Name: "Enabled",
|
Name: "Enabled",
|
||||||
Type: code.SimpleType("bool"),
|
Type: code.SimpleType("bool"),
|
||||||
|
}
|
||||||
|
|
||||||
|
firstNameField = code.StructField{
|
||||||
|
Name: "First",
|
||||||
|
Type: code.SimpleType("string"),
|
||||||
|
}
|
||||||
|
lastNameField = code.StructField{
|
||||||
|
Name: "Last",
|
||||||
|
Type: code.SimpleType("string"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
nameStruct = code.Struct{
|
||||||
|
Name: "NameModel",
|
||||||
|
Fields: code.StructFields{
|
||||||
|
firstNameField,
|
||||||
|
lastNameField,
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
structModel = code.Struct{
|
||||||
|
Name: "UserModel",
|
||||||
|
Fields: code.StructFields{
|
||||||
|
idField,
|
||||||
|
phoneNumberField,
|
||||||
|
genderField,
|
||||||
|
cityField,
|
||||||
|
ageField,
|
||||||
|
nameField,
|
||||||
|
contactField,
|
||||||
|
referrerField,
|
||||||
|
defaultPaymentField,
|
||||||
|
enabledField,
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var structs = code.Structs{
|
||||||
|
nameStruct,
|
||||||
|
structModel,
|
||||||
}
|
}
|
||||||
|
|
||||||
type ParseInterfaceMethodTestCase struct {
|
type ParseInterfaceMethodTestCase struct {
|
||||||
|
@ -84,7 +137,7 @@ func TestParseInterfaceMethod_Insert(t *testing.T) {
|
||||||
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.Name, func(t *testing.T) {
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
actualSpec, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
actualSpec, err := spec.ParseInterfaceMethod(structs, structModel, testCase.Method)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error = %s", err)
|
t.Errorf("Error = %s", err)
|
||||||
|
@ -120,7 +173,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "ID", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -140,7 +193,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "PhoneNumber", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{phoneNumberField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -160,7 +213,47 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "FindByDeepArg method",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "FindByNameFirst",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Type: code.SimpleType("string")},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedOperation: spec.FindOperation{
|
||||||
|
Mode: spec.QueryModeMany,
|
||||||
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
|
{FieldReference: spec.FieldReference{nameField, firstNameField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "FindByDeepPointerArg method",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "FindByReferrerID",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedOperation: spec.FindOperation{
|
||||||
|
Mode: spec.QueryModeMany,
|
||||||
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
|
{FieldReference: spec.FieldReference{referrerField, idField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -199,8 +292,8 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Operator: spec.OperatorAnd,
|
Operator: spec.OperatorAnd,
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{genderField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -224,8 +317,8 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Operator: spec.OperatorOr,
|
Operator: spec.OperatorOr,
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{genderField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -246,7 +339,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorNot, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorNot, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -266,7 +359,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorLessThan, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorLessThan, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -286,7 +379,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorLessThanEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorLessThanEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -306,7 +399,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorGreaterThan, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorGreaterThan, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -326,7 +419,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorGreaterThanEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorGreaterThanEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -347,7 +440,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorBetween, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorBetween, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -367,7 +460,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorIn, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorIn, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -387,7 +480,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorNotIn, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorNotIn, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -406,7 +499,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "Enabled", Comparator: spec.ComparatorTrue, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{enabledField}, Comparator: spec.ComparatorTrue, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -425,7 +518,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "Enabled", Comparator: spec.ComparatorFalse, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{enabledField}, Comparator: spec.ComparatorFalse, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -445,10 +538,10 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
Sorts: []spec.Sort{
|
Sorts: []spec.Sort{
|
||||||
{FieldName: "Age", Ordering: spec.OrderingAscending},
|
{FieldReference: spec.FieldReference{ageField}, Ordering: spec.OrderingAscending},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -468,10 +561,10 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
Sorts: []spec.Sort{
|
Sorts: []spec.Sort{
|
||||||
{FieldName: "Age", Ordering: spec.OrderingAscending},
|
{FieldReference: spec.FieldReference{ageField}, Ordering: spec.OrderingAscending},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -491,10 +584,33 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
Sorts: []spec.Sort{
|
Sorts: []spec.Sort{
|
||||||
{FieldName: "Age", Ordering: spec.OrderingDescending},
|
{FieldReference: spec.FieldReference{ageField}, Ordering: spec.OrderingDescending},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "FindByArgOrderByDeepArg method",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "FindByCityOrderByNameFirst",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Type: code.SimpleType("string")},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedOperation: spec.FindOperation{
|
||||||
|
Mode: spec.QueryModeMany,
|
||||||
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
|
}},
|
||||||
|
Sorts: []spec.Sort{
|
||||||
|
{FieldReference: spec.FieldReference{nameField, firstNameField}, Ordering: spec.OrderingAscending},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -514,11 +630,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
ExpectedOperation: spec.FindOperation{
|
ExpectedOperation: spec.FindOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
Sorts: []spec.Sort{
|
Sorts: []spec.Sort{
|
||||||
{FieldName: "City", Ordering: spec.OrderingAscending},
|
{FieldReference: spec.FieldReference{cityField}, Ordering: spec.OrderingAscending},
|
||||||
{FieldName: "Age", Ordering: spec.OrderingDescending},
|
{FieldReference: spec.FieldReference{ageField}, Ordering: spec.OrderingDescending},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -526,7 +642,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.Name, func(t *testing.T) {
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
actualSpec, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
actualSpec, err := spec.ParseInterfaceMethod(structs, structModel, testCase.Method)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error = %s", err)
|
t.Errorf("Error = %s", err)
|
||||||
|
@ -564,7 +680,7 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
|
||||||
Update: spec.UpdateModel{},
|
Update: spec.UpdateModel{},
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "ID", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -584,11 +700,11 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedOperation: spec.UpdateOperation{
|
ExpectedOperation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{Name: "Gender", ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "ID", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -608,11 +724,35 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedOperation: spec.UpdateOperation{
|
ExpectedOperation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{Name: "Gender", ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "ID", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "UpdateArgByArg one with deeply referenced update field method",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "UpdateNameFirstByID",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Type: code.SimpleType("string")},
|
||||||
|
{Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.SimpleType("bool"),
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedOperation: spec.UpdateOperation{
|
||||||
|
Update: spec.UpdateFields{
|
||||||
|
{FieldReference: spec.FieldReference{nameField, firstNameField}, ParamIndex: 1},
|
||||||
|
},
|
||||||
|
Mode: spec.QueryModeOne,
|
||||||
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -633,12 +773,12 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedOperation: spec.UpdateOperation{
|
ExpectedOperation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{Name: "Gender", ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
||||||
{Name: "City", ParamIndex: 2},
|
{FieldReference: spec.FieldReference{cityField}, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "ID", Comparator: spec.ComparatorEqual, ParamIndex: 3},
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 3},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -646,7 +786,7 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
|
||||||
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.Name, func(t *testing.T) {
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
actualSpec, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
actualSpec, err := spec.ParseInterfaceMethod(structs, structModel, testCase.Method)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error = %s", err)
|
t.Errorf("Error = %s", err)
|
||||||
|
@ -682,7 +822,7 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
ExpectedOperation: spec.DeleteOperation{
|
ExpectedOperation: spec.DeleteOperation{
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "ID", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -702,7 +842,7 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
ExpectedOperation: spec.DeleteOperation{
|
ExpectedOperation: spec.DeleteOperation{
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "PhoneNumber", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{phoneNumberField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -722,7 +862,7 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
ExpectedOperation: spec.DeleteOperation{
|
ExpectedOperation: spec.DeleteOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -761,8 +901,8 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Operator: spec.OperatorAnd,
|
Operator: spec.OperatorAnd,
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{genderField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -786,8 +926,8 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Operator: spec.OperatorOr,
|
Operator: spec.OperatorOr,
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{genderField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -808,7 +948,7 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
ExpectedOperation: spec.DeleteOperation{
|
ExpectedOperation: spec.DeleteOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorNot, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorNot, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -828,7 +968,7 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
ExpectedOperation: spec.DeleteOperation{
|
ExpectedOperation: spec.DeleteOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorLessThan, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorLessThan, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -848,7 +988,7 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
ExpectedOperation: spec.DeleteOperation{
|
ExpectedOperation: spec.DeleteOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorLessThanEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorLessThanEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -868,7 +1008,7 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
ExpectedOperation: spec.DeleteOperation{
|
ExpectedOperation: spec.DeleteOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorGreaterThan, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorGreaterThan, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -888,7 +1028,7 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
ExpectedOperation: spec.DeleteOperation{
|
ExpectedOperation: spec.DeleteOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorGreaterThanEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorGreaterThanEqual, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -909,7 +1049,7 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
ExpectedOperation: spec.DeleteOperation{
|
ExpectedOperation: spec.DeleteOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "Age", Comparator: spec.ComparatorBetween, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, Comparator: spec.ComparatorBetween, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -929,7 +1069,7 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
ExpectedOperation: spec.DeleteOperation{
|
ExpectedOperation: spec.DeleteOperation{
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
{Field: "City", Comparator: spec.ComparatorIn, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{cityField}, Comparator: spec.ComparatorIn, ParamIndex: 1},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -937,7 +1077,7 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.Name, func(t *testing.T) {
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
actualSpec, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
actualSpec, err := spec.ParseInterfaceMethod(structs, structModel, testCase.Method)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error = %s", err)
|
t.Errorf("Error = %s", err)
|
||||||
|
@ -989,7 +1129,7 @@ func TestParseInterfaceMethod_Count(t *testing.T) {
|
||||||
ExpectedOperation: spec.CountOperation{
|
ExpectedOperation: spec.CountOperation{
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
Predicates: []spec.Predicate{
|
Predicates: []spec.Predicate{
|
||||||
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, Comparator: spec.ComparatorEqual, ParamIndex: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -998,7 +1138,7 @@ func TestParseInterfaceMethod_Count(t *testing.T) {
|
||||||
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.Name, func(t *testing.T) {
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
actualSpec, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
actualSpec, err := spec.ParseInterfaceMethod(structs, structModel, testCase.Method)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error = %s", err)
|
t.Errorf("Error = %s", err)
|
||||||
|
@ -1023,7 +1163,7 @@ type ParseInterfaceMethodInvalidTestCase struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseInterfaceMethod_Invalid(t *testing.T) {
|
func TestParseInterfaceMethod_Invalid(t *testing.T) {
|
||||||
_, err := spec.ParseInterfaceMethod(structModel, code.Method{
|
_, err := spec.ParseInterfaceMethod(structs, structModel, code.Method{
|
||||||
Name: "SearchByID",
|
Name: "SearchByID",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1132,7 +1272,7 @@ func TestParseInterfaceMethod_Insert_Invalid(t *testing.T) {
|
||||||
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.Name, func(t *testing.T) {
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
_, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
_, err := spec.ParseInterfaceMethod(structs, structModel, testCase.Method)
|
||||||
|
|
||||||
if err != testCase.ExpectedError {
|
if err != testCase.ExpectedError {
|
||||||
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError, err)
|
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError, err)
|
||||||
|
@ -1197,7 +1337,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewInvalidQueryError([]string{"By", "And", "Gender"}),
|
ExpectedError: spec.NewInvalidQueryError([]string{"And", "Gender"}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "misplaced operator token (rightmost)",
|
Name: "misplaced operator token (rightmost)",
|
||||||
|
@ -1208,7 +1348,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewInvalidQueryError([]string{"By", "Gender", "And"}),
|
ExpectedError: spec.NewInvalidQueryError([]string{"Gender", "And"}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "misplaced operator token (double operator)",
|
Name: "misplaced operator token (double operator)",
|
||||||
|
@ -1219,7 +1359,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewInvalidQueryError([]string{"By", "Gender", "And", "And", "City"}),
|
ExpectedError: spec.NewInvalidQueryError([]string{"Gender", "And", "And", "City"}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "ambiguous query",
|
Name: "ambiguous query",
|
||||||
|
@ -1230,7 +1370,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewInvalidQueryError([]string{"By", "Gender", "And", "City", "Or", "Age"}),
|
ExpectedError: spec.NewInvalidQueryError([]string{"Gender", "And", "City", "Or", "Age"}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "no context parameter",
|
Name: "no context parameter",
|
||||||
|
@ -1249,7 +1389,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "mismatched number of parameters",
|
Name: "mismatched number of parameters",
|
||||||
Method: code.Method{
|
Method: code.Method{
|
||||||
Name: "FindByCountry",
|
Name: "FindByCity",
|
||||||
Params: []code.Param{
|
Params: []code.Param{
|
||||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
{Type: code.SimpleType("string")},
|
{Type: code.SimpleType("string")},
|
||||||
|
@ -1275,7 +1415,52 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewStructFieldNotFoundError("Country"),
|
ExpectedError: spec.NewStructFieldNotFoundError([]string{"Country"}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "deeply referenced struct field not found",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "FindByNameMiddle",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Type: code.SimpleType("string")},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedError: spec.NewStructFieldNotFoundError([]string{"Name", "Middle"}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "deeply referenced struct not found",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "FindByContactPhone",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Type: code.SimpleType("string")},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedError: spec.NewStructFieldNotFoundError([]string{"Contact", "Phone"}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "deeply referenced external struct field",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "FindByDefaultPaymentMethod",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Type: code.SimpleType("string")},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedError: spec.NewStructFieldNotFoundError([]string{"Default", "Payment", "Method"}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "incompatible struct field for True comparator",
|
Name: "incompatible struct field for True comparator",
|
||||||
|
@ -1374,11 +1559,22 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewInvalidSortError([]string{"Order", "By", "Age", "And", "And", "Gender"}),
|
ExpectedError: spec.NewInvalidSortError([]string{"Order", "By", "Age", "And", "And", "Gender"}),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "sort field not found",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "FindAllOrderByCountry",
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedError: spec.NewStructFieldNotFoundError([]string{"Country"}),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.Name, func(t *testing.T) {
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
_, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
_, err := spec.ParseInterfaceMethod(structs, structModel, testCase.Method)
|
||||||
|
|
||||||
if err.Error() != testCase.ExpectedError.Error() {
|
if err.Error() != testCase.ExpectedError.Error() {
|
||||||
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError.Error(), err.Error())
|
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError.Error(), err.Error())
|
||||||
|
@ -1479,7 +1675,7 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewInvalidQueryError([]string{"By", "ID", "And", "Username", "Or", "Gender"}),
|
ExpectedError: spec.NewInvalidQueryError([]string{"ID", "And", "Username", "Or", "Gender"}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "update model with invalid parameter",
|
Name: "update model with invalid parameter",
|
||||||
|
@ -1525,7 +1721,7 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewStructFieldNotFoundError("Country"),
|
ExpectedError: spec.NewStructFieldNotFoundError([]string{"Country"}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "struct field does not match parameter in update fields",
|
Name: "struct field does not match parameter in update fields",
|
||||||
|
@ -1563,7 +1759,7 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) {
|
||||||
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.Name, func(t *testing.T) {
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
_, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
_, err := spec.ParseInterfaceMethod(structs, structModel, testCase.Method)
|
||||||
|
|
||||||
if err != testCase.ExpectedError {
|
if err != testCase.ExpectedError {
|
||||||
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError, err)
|
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError, err)
|
||||||
|
@ -1628,7 +1824,7 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewInvalidQueryError([]string{"By", "And", "Gender"}),
|
ExpectedError: spec.NewInvalidQueryError([]string{"And", "Gender"}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "misplaced operator token (rightmost)",
|
Name: "misplaced operator token (rightmost)",
|
||||||
|
@ -1639,7 +1835,7 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewInvalidQueryError([]string{"By", "Gender", "And"}),
|
ExpectedError: spec.NewInvalidQueryError([]string{"Gender", "And"}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "misplaced operator token (double operator)",
|
Name: "misplaced operator token (double operator)",
|
||||||
|
@ -1650,7 +1846,7 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewInvalidQueryError([]string{"By", "Gender", "And", "And", "City"}),
|
ExpectedError: spec.NewInvalidQueryError([]string{"Gender", "And", "And", "City"}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "ambiguous query",
|
Name: "ambiguous query",
|
||||||
|
@ -1661,7 +1857,7 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewInvalidQueryError([]string{"By", "Gender", "And", "City", "Or", "Age"}),
|
ExpectedError: spec.NewInvalidQueryError([]string{"Gender", "And", "City", "Or", "Age"}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "no context parameter",
|
Name: "no context parameter",
|
||||||
|
@ -1680,7 +1876,7 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "mismatched number of parameters",
|
Name: "mismatched number of parameters",
|
||||||
Method: code.Method{
|
Method: code.Method{
|
||||||
Name: "DeleteByCountry",
|
Name: "DeleteByCity",
|
||||||
Params: []code.Param{
|
Params: []code.Param{
|
||||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
{Type: code.SimpleType("string")},
|
{Type: code.SimpleType("string")},
|
||||||
|
@ -1706,7 +1902,7 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewStructFieldNotFoundError("Country"),
|
ExpectedError: spec.NewStructFieldNotFoundError([]string{"Country"}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "mismatched method parameter type",
|
Name: "mismatched method parameter type",
|
||||||
|
@ -1742,7 +1938,7 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) {
|
||||||
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.Name, func(t *testing.T) {
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
_, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
_, err := spec.ParseInterfaceMethod(structs, structModel, testCase.Method)
|
||||||
|
|
||||||
if err != testCase.ExpectedError {
|
if err != testCase.ExpectedError {
|
||||||
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError, err)
|
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError, err)
|
||||||
|
@ -1867,13 +2063,13 @@ func TestParseInterfaceMethod_Count_Invalid(t *testing.T) {
|
||||||
code.SimpleType("error"),
|
code.SimpleType("error"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewStructFieldNotFoundError("Country"),
|
ExpectedError: spec.NewStructFieldNotFoundError([]string{"Country"}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.Name, func(t *testing.T) {
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
_, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
_, err := spec.ParseInterfaceMethod(structs, structModel, testCase.Method)
|
||||||
|
|
||||||
if err != testCase.ExpectedError {
|
if err != testCase.ExpectedError {
|
||||||
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError, err)
|
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError, err)
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package spec
|
package spec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/sunboyy/repogen/internal/code"
|
"github.com/sunboyy/repogen/internal/code"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -72,48 +70,17 @@ func (c Comparator) NumberOfArguments() int {
|
||||||
|
|
||||||
// Predicate is a criteria for querying a field
|
// Predicate is a criteria for querying a field
|
||||||
type Predicate struct {
|
type Predicate struct {
|
||||||
Field string
|
FieldReference FieldReference
|
||||||
Comparator Comparator
|
Comparator Comparator
|
||||||
ParamIndex int
|
ParamIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
type predicateToken []string
|
type queryParser struct {
|
||||||
|
fieldResolver fieldResolver
|
||||||
func (t predicateToken) ToPredicate(paramIndex int) Predicate {
|
StructModel code.Struct
|
||||||
if len(t) > 1 && t[len(t)-1] == "Not" {
|
|
||||||
return Predicate{Field: strings.Join(t[:len(t)-1], ""), Comparator: ComparatorNot, ParamIndex: paramIndex}
|
|
||||||
}
|
|
||||||
if len(t) > 2 && t[len(t)-2] == "Less" && t[len(t)-1] == "Than" {
|
|
||||||
return Predicate{Field: strings.Join(t[:len(t)-2], ""), Comparator: ComparatorLessThan, ParamIndex: paramIndex}
|
|
||||||
}
|
|
||||||
if len(t) > 3 && t[len(t)-3] == "Less" && t[len(t)-2] == "Than" && t[len(t)-1] == "Equal" {
|
|
||||||
return Predicate{Field: strings.Join(t[:len(t)-3], ""), Comparator: ComparatorLessThanEqual, ParamIndex: paramIndex}
|
|
||||||
}
|
|
||||||
if len(t) > 2 && t[len(t)-2] == "Greater" && t[len(t)-1] == "Than" {
|
|
||||||
return Predicate{Field: strings.Join(t[:len(t)-2], ""), Comparator: ComparatorGreaterThan, ParamIndex: paramIndex}
|
|
||||||
}
|
|
||||||
if len(t) > 3 && t[len(t)-3] == "Greater" && t[len(t)-2] == "Than" && t[len(t)-1] == "Equal" {
|
|
||||||
return Predicate{Field: strings.Join(t[:len(t)-3], ""), Comparator: ComparatorGreaterThanEqual, ParamIndex: paramIndex}
|
|
||||||
}
|
|
||||||
if len(t) > 2 && t[len(t)-2] == "Not" && t[len(t)-1] == "In" {
|
|
||||||
return Predicate{Field: strings.Join(t[:len(t)-2], ""), Comparator: ComparatorNotIn, ParamIndex: paramIndex}
|
|
||||||
}
|
|
||||||
if len(t) > 1 && t[len(t)-1] == "In" {
|
|
||||||
return Predicate{Field: strings.Join(t[:len(t)-1], ""), Comparator: ComparatorIn, ParamIndex: paramIndex}
|
|
||||||
}
|
|
||||||
if len(t) > 1 && t[len(t)-1] == "Between" {
|
|
||||||
return Predicate{Field: strings.Join(t[:len(t)-1], ""), Comparator: ComparatorBetween, ParamIndex: paramIndex}
|
|
||||||
}
|
|
||||||
if len(t) > 1 && t[len(t)-1] == "True" {
|
|
||||||
return Predicate{Field: strings.Join(t[:len(t)-1], ""), Comparator: ComparatorTrue, ParamIndex: paramIndex}
|
|
||||||
}
|
|
||||||
if len(t) > 1 && t[len(t)-1] == "False" {
|
|
||||||
return Predicate{Field: strings.Join(t[:len(t)-1], ""), Comparator: ComparatorFalse, ParamIndex: paramIndex}
|
|
||||||
}
|
|
||||||
return Predicate{Field: strings.Join(t, ""), Comparator: ComparatorEqual, ParamIndex: paramIndex}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseQuery(rawTokens []string, paramIndex int) (QuerySpec, error) {
|
func (p queryParser) parseQuery(rawTokens []string, paramIndex int) (QuerySpec, error) {
|
||||||
if len(rawTokens) == 0 {
|
if len(rawTokens) == 0 {
|
||||||
return QuerySpec{}, QueryRequiredError
|
return QuerySpec{}, QueryRequiredError
|
||||||
}
|
}
|
||||||
|
@ -130,38 +97,104 @@ func parseQuery(rawTokens []string, paramIndex int) (QuerySpec, error) {
|
||||||
tokens = tokens[1:]
|
tokens = tokens[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(tokens) == 0 || tokens[0] == "And" || tokens[0] == "Or" {
|
if len(tokens) == 0 {
|
||||||
return QuerySpec{}, NewInvalidQueryError(rawTokens)
|
return QuerySpec{}, NewInvalidQueryError(rawTokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator, predicateTokens, err := p.splitPredicateTokens(tokens)
|
||||||
|
if err != nil {
|
||||||
|
return QuerySpec{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
querySpec := QuerySpec{
|
||||||
|
Operator: operator,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, predicateToken := range predicateTokens {
|
||||||
|
predicate, err := p.parsePredicate(predicateToken, paramIndex)
|
||||||
|
if err != nil {
|
||||||
|
return QuerySpec{}, err
|
||||||
|
}
|
||||||
|
querySpec.Predicates = append(querySpec.Predicates, predicate)
|
||||||
|
paramIndex += predicate.Comparator.NumberOfArguments()
|
||||||
|
}
|
||||||
|
|
||||||
|
return querySpec, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p queryParser) splitPredicateTokens(tokens []string) (Operator, [][]string, error) {
|
||||||
var operator Operator
|
var operator Operator
|
||||||
var predicates []Predicate
|
var predicateTokens [][]string
|
||||||
var aggregatedToken predicateToken
|
var aggregatedToken []string
|
||||||
|
|
||||||
for _, token := range tokens {
|
for _, token := range tokens {
|
||||||
if token != "And" && token != "Or" {
|
if token != "And" && token != "Or" {
|
||||||
aggregatedToken = append(aggregatedToken, token)
|
aggregatedToken = append(aggregatedToken, token)
|
||||||
} else if len(aggregatedToken) == 0 {
|
} else if len(aggregatedToken) == 0 {
|
||||||
return QuerySpec{}, NewInvalidQueryError(rawTokens)
|
return "", nil, NewInvalidQueryError(tokens)
|
||||||
} else if token == "And" && operator != OperatorOr {
|
} else if token == "And" && operator != OperatorOr {
|
||||||
operator = OperatorAnd
|
operator = OperatorAnd
|
||||||
predicate := aggregatedToken.ToPredicate(paramIndex)
|
predicateTokens = append(predicateTokens, aggregatedToken)
|
||||||
predicates = append(predicates, predicate)
|
aggregatedToken = nil
|
||||||
paramIndex += predicate.Comparator.NumberOfArguments()
|
|
||||||
aggregatedToken = predicateToken{}
|
|
||||||
} else if token == "Or" && operator != OperatorAnd {
|
} else if token == "Or" && operator != OperatorAnd {
|
||||||
operator = OperatorOr
|
operator = OperatorOr
|
||||||
predicate := aggregatedToken.ToPredicate(paramIndex)
|
predicateTokens = append(predicateTokens, aggregatedToken)
|
||||||
predicates = append(predicates, predicate)
|
aggregatedToken = nil
|
||||||
paramIndex += predicate.Comparator.NumberOfArguments()
|
|
||||||
aggregatedToken = predicateToken{}
|
|
||||||
} else {
|
} else {
|
||||||
return QuerySpec{}, NewInvalidQueryError(rawTokens)
|
return "", nil, NewInvalidQueryError(tokens)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(aggregatedToken) == 0 {
|
if len(aggregatedToken) == 0 {
|
||||||
return QuerySpec{}, NewInvalidQueryError(rawTokens)
|
return "", nil, NewInvalidQueryError(tokens)
|
||||||
}
|
}
|
||||||
predicates = append(predicates, aggregatedToken.ToPredicate(paramIndex))
|
predicateTokens = append(predicateTokens, aggregatedToken)
|
||||||
|
|
||||||
return QuerySpec{Operator: operator, Predicates: predicates}, nil
|
return operator, predicateTokens, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p queryParser) parsePredicate(t []string, paramIndex int) (Predicate, error) {
|
||||||
|
if len(t) > 1 && t[len(t)-1] == "Not" {
|
||||||
|
return p.createPredicate(t[:len(t)-1], ComparatorNot, paramIndex)
|
||||||
|
}
|
||||||
|
if len(t) > 2 && t[len(t)-2] == "Less" && t[len(t)-1] == "Than" {
|
||||||
|
return p.createPredicate(t[:len(t)-2], ComparatorLessThan, paramIndex)
|
||||||
|
}
|
||||||
|
if len(t) > 3 && t[len(t)-3] == "Less" && t[len(t)-2] == "Than" && t[len(t)-1] == "Equal" {
|
||||||
|
return p.createPredicate(t[:len(t)-3], ComparatorLessThanEqual, paramIndex)
|
||||||
|
}
|
||||||
|
if len(t) > 2 && t[len(t)-2] == "Greater" && t[len(t)-1] == "Than" {
|
||||||
|
return p.createPredicate(t[:len(t)-2], ComparatorGreaterThan, paramIndex)
|
||||||
|
}
|
||||||
|
if len(t) > 3 && t[len(t)-3] == "Greater" && t[len(t)-2] == "Than" && t[len(t)-1] == "Equal" {
|
||||||
|
return p.createPredicate(t[:len(t)-3], ComparatorGreaterThanEqual, paramIndex)
|
||||||
|
}
|
||||||
|
if len(t) > 2 && t[len(t)-2] == "Not" && t[len(t)-1] == "In" {
|
||||||
|
return p.createPredicate(t[:len(t)-2], ComparatorNotIn, paramIndex)
|
||||||
|
}
|
||||||
|
if len(t) > 1 && t[len(t)-1] == "In" {
|
||||||
|
return p.createPredicate(t[:len(t)-1], ComparatorIn, paramIndex)
|
||||||
|
}
|
||||||
|
if len(t) > 1 && t[len(t)-1] == "Between" {
|
||||||
|
return p.createPredicate(t[:len(t)-1], ComparatorBetween, paramIndex)
|
||||||
|
}
|
||||||
|
if len(t) > 1 && t[len(t)-1] == "True" {
|
||||||
|
return p.createPredicate(t[:len(t)-1], ComparatorTrue, paramIndex)
|
||||||
|
}
|
||||||
|
if len(t) > 1 && t[len(t)-1] == "False" {
|
||||||
|
return p.createPredicate(t[:len(t)-1], ComparatorFalse, paramIndex)
|
||||||
|
}
|
||||||
|
return p.createPredicate(t, ComparatorEqual, paramIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p queryParser) createPredicate(t []string, comparator Comparator, paramIndex int) (Predicate, error) {
|
||||||
|
fields, ok := p.fieldResolver.ResolveStructField(p.StructModel, t)
|
||||||
|
if !ok {
|
||||||
|
return Predicate{}, NewStructFieldNotFoundError(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Predicate{
|
||||||
|
FieldReference: fields,
|
||||||
|
Comparator: comparator,
|
||||||
|
ParamIndex: paramIndex,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
2
main.go
2
main.go
|
@ -75,7 +75,7 @@ func generateFromRequest(fileName, structModelName, repositoryInterfaceName stri
|
||||||
|
|
||||||
var methodSpecs []spec.MethodSpec
|
var methodSpecs []spec.MethodSpec
|
||||||
for _, method := range intf.Methods {
|
for _, method := range intf.Methods {
|
||||||
methodSpec, err := spec.ParseInterfaceMethod(structModel, method)
|
methodSpec, err := spec.ParseInterfaceMethod(file.Structs, structModel, method)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue