Add count operation

This commit is contained in:
sunboyy 2021-02-06 18:05:47 +07:00
parent c752849518
commit 496f9541cb
12 changed files with 858 additions and 261 deletions

View file

@ -85,6 +85,8 @@ func (g RepositoryGenerator) generateMethodImplementation(methodSpec spec.Method
return g.generateUpdateImplementation(operation)
case spec.DeleteOperation:
return g.generateDeleteImplementation(operation)
case spec.CountOperation:
return g.generateCountImplementation(operation)
}
return "", OperationNotSupportedError
@ -98,8 +100,6 @@ func (g RepositoryGenerator) generateInsertImplementation(operation spec.InsertO
}
func (g RepositoryGenerator) generateFindImplementation(operation spec.FindOperation) (string, error) {
buffer := new(bytes.Buffer)
querySpec, err := g.mongoQuerySpec(operation.Query)
if err != nil {
return "", err
@ -111,31 +111,12 @@ func (g RepositoryGenerator) generateFindImplementation(operation spec.FindOpera
}
if operation.Mode == spec.QueryModeOne {
tmpl, err := template.New("mongo_repository_findone").Parse(findOneTemplate)
if err != nil {
return "", err
}
if err := tmpl.Execute(buffer, tmplData); err != nil {
return "", err
}
} else {
tmpl, err := template.New("mongo_repository_findmany").Parse(findManyTemplate)
if err != nil {
return "", err
}
if err := tmpl.Execute(buffer, tmplData); err != nil {
return "", err
}
return generateFromTemplate("mongo_repository_findone", findOneTemplate, tmplData)
}
return buffer.String(), nil
return generateFromTemplate("mongo_repository_findmany", findManyTemplate, tmplData)
}
func (g RepositoryGenerator) generateUpdateImplementation(operation spec.UpdateOperation) (string, error) {
buffer := new(bytes.Buffer)
var fields []updateField
for _, field := range operation.Fields {
bsonTag, err := g.bsonTagFromFieldName(field.Name)
@ -156,31 +137,12 @@ func (g RepositoryGenerator) generateUpdateImplementation(operation spec.UpdateO
}
if operation.Mode == spec.QueryModeOne {
tmpl, err := template.New("mongo_repository_updateone").Parse(updateOneTemplate)
if err != nil {
return "", err
}
if err := tmpl.Execute(buffer, tmplData); err != nil {
return "", err
}
} else {
tmpl, err := template.New("mongo_repository_updatemany").Parse(updateManyTemplate)
if err != nil {
return "", err
}
if err := tmpl.Execute(buffer, tmplData); err != nil {
return "", err
}
return generateFromTemplate("mongo_repository_updateone", updateOneTemplate, tmplData)
}
return buffer.String(), nil
return generateFromTemplate("mongo_repository_updatemany", updateManyTemplate, tmplData)
}
func (g RepositoryGenerator) generateDeleteImplementation(operation spec.DeleteOperation) (string, error) {
buffer := new(bytes.Buffer)
querySpec, err := g.mongoQuerySpec(operation.Query)
if err != nil {
return "", err
@ -191,26 +153,22 @@ func (g RepositoryGenerator) generateDeleteImplementation(operation spec.DeleteO
}
if operation.Mode == spec.QueryModeOne {
tmpl, err := template.New("mongo_repository_deleteone").Parse(deleteOneTemplate)
if err != nil {
return "", err
}
return generateFromTemplate("mongo_repository_deleteone", deleteOneTemplate, tmplData)
}
return generateFromTemplate("mongo_repository_deletemany", deleteManyTemplate, tmplData)
}
if err := tmpl.Execute(buffer, tmplData); err != nil {
return "", err
}
} else {
tmpl, err := template.New("mongo_repository_deletemany").Parse(deleteManyTemplate)
if err != nil {
return "", err
}
if err := tmpl.Execute(buffer, tmplData); err != nil {
return "", err
}
func (g RepositoryGenerator) generateCountImplementation(operation spec.CountOperation) (string, error) {
querySpec, err := g.mongoQuerySpec(operation.Query)
if err != nil {
return "", err
}
return buffer.String(), nil
tmplData := mongoCountTemplateData{
QuerySpec: querySpec,
}
return generateFromTemplate("mongo_repository_count", countTemplate, tmplData)
}
func (g RepositoryGenerator) mongoQuerySpec(query spec.QuerySpec) (querySpec, error) {
@ -252,3 +210,17 @@ func (g RepositoryGenerator) bsonTagFromFieldName(fieldName string) (string, err
func (g RepositoryGenerator) structName() string {
return g.InterfaceName + "Mongo"
}
func generateFromTemplate(name string, templateString string, tmplData interface{}) (string, error) {
tmpl, err := template.New(name).Parse(templateString)
if err != nil {
return "", err
}
buffer := new(bytes.Buffer)
if err := tmpl.Execute(buffer, tmplData); err != nil {
return "", err
}
return buffer.String(), nil
}

View file

@ -1089,6 +1089,358 @@ func (r *UserRepositoryMongo) DeleteByGenderIn(arg0 context.Context, arg1 []Gend
}
}
func TestGenerateMethod_Count(t *testing.T) {
testTable := []GenerateMethodTestCase{
{
Name: "simple count method",
MethodSpec: spec.MethodSpec{
Name: "CountByGender",
Params: []code.Param{
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
{Type: code.SimpleType("Gender")},
},
Returns: []code.Type{
code.SimpleType("int"),
code.SimpleType("error"),
},
Operation: spec.CountOperation{
Query: spec.QuerySpec{
Predicates: []spec.Predicate{
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 1},
},
},
},
},
ExpectedCode: `
func (r *UserRepositoryMongo) CountByGender(arg0 context.Context, arg1 Gender) (int, error) {
count, err := r.collection.CountDocuments(arg0, bson.M{
"gender": arg1,
})
if err != nil {
return 0, err
}
return int(count), nil
}
`,
},
{
Name: "count with And operator",
MethodSpec: spec.MethodSpec{
Name: "CountByGenderAndCity",
Params: []code.Param{
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
{Type: code.SimpleType("Gender")},
{Type: code.SimpleType("int")},
},
Returns: []code.Type{
code.SimpleType("int"),
code.SimpleType("error"),
},
Operation: spec.CountOperation{
Query: spec.QuerySpec{
Operator: spec.OperatorAnd,
Predicates: []spec.Predicate{
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 1},
{Field: "Age", Comparator: spec.ComparatorEqual, ParamIndex: 2},
},
},
},
},
ExpectedCode: `
func (r *UserRepositoryMongo) CountByGenderAndCity(arg0 context.Context, arg1 Gender, arg2 int) (int, error) {
count, err := r.collection.CountDocuments(arg0, bson.M{
"gender": arg1,
"age": arg2,
})
if err != nil {
return 0, err
}
return int(count), nil
}
`,
},
{
Name: "count with Or operator",
MethodSpec: spec.MethodSpec{
Name: "CountByGenderOrCity",
Params: []code.Param{
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
{Type: code.SimpleType("Gender")},
{Type: code.SimpleType("int")},
},
Returns: []code.Type{
code.SimpleType("int"),
code.SimpleType("error"),
},
Operation: spec.CountOperation{
Query: spec.QuerySpec{
Operator: spec.OperatorOr,
Predicates: []spec.Predicate{
{Field: "Gender", Comparator: spec.ComparatorEqual, ParamIndex: 1},
{Field: "Age", Comparator: spec.ComparatorEqual, ParamIndex: 2},
},
},
},
},
ExpectedCode: `
func (r *UserRepositoryMongo) CountByGenderOrCity(arg0 context.Context, arg1 Gender, arg2 int) (int, error) {
count, err := r.collection.CountDocuments(arg0, bson.M{
"$or": []bson.M{
{"gender": arg1},
{"age": arg2},
},
})
if err != nil {
return 0, err
}
return int(count), nil
}
`,
},
{
Name: "count with Not comparator",
MethodSpec: spec.MethodSpec{
Name: "CountByGenderNot",
Params: []code.Param{
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
{Type: code.SimpleType("Gender")},
},
Returns: []code.Type{
code.SimpleType("int"),
code.SimpleType("error"),
},
Operation: spec.CountOperation{
Query: spec.QuerySpec{
Predicates: []spec.Predicate{
{Field: "Gender", Comparator: spec.ComparatorNot, ParamIndex: 1},
},
},
},
},
ExpectedCode: `
func (r *UserRepositoryMongo) CountByGenderNot(arg0 context.Context, arg1 Gender) (int, error) {
count, err := r.collection.CountDocuments(arg0, bson.M{
"gender": bson.M{"$ne": arg1},
})
if err != nil {
return 0, err
}
return int(count), nil
}
`,
},
{
Name: "count with LessThan comparator",
MethodSpec: spec.MethodSpec{
Name: "CountByAgeLessThan",
Params: []code.Param{
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
{Type: code.SimpleType("int")},
},
Returns: []code.Type{
code.SimpleType("int"),
code.SimpleType("error"),
},
Operation: spec.CountOperation{
Query: spec.QuerySpec{
Predicates: []spec.Predicate{
{Field: "Age", Comparator: spec.ComparatorLessThan, ParamIndex: 1},
},
},
},
},
ExpectedCode: `
func (r *UserRepositoryMongo) CountByAgeLessThan(arg0 context.Context, arg1 int) (int, error) {
count, err := r.collection.CountDocuments(arg0, bson.M{
"age": bson.M{"$lt": arg1},
})
if err != nil {
return 0, err
}
return int(count), nil
}
`,
},
{
Name: "count with LessThanEqual comparator",
MethodSpec: spec.MethodSpec{
Name: "CountByAgeLessThanEqual",
Params: []code.Param{
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
{Type: code.SimpleType("int")},
},
Returns: []code.Type{
code.SimpleType("int"),
code.SimpleType("error"),
},
Operation: spec.CountOperation{
Query: spec.QuerySpec{
Predicates: []spec.Predicate{
{Field: "Age", Comparator: spec.ComparatorLessThanEqual, ParamIndex: 1},
},
},
},
},
ExpectedCode: `
func (r *UserRepositoryMongo) CountByAgeLessThanEqual(arg0 context.Context, arg1 int) (int, error) {
count, err := r.collection.CountDocuments(arg0, bson.M{
"age": bson.M{"$lte": arg1},
})
if err != nil {
return 0, err
}
return int(count), nil
}
`,
},
{
Name: "count with GreaterThan comparator",
MethodSpec: spec.MethodSpec{
Name: "CountByAgeGreaterThan",
Params: []code.Param{
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
{Type: code.SimpleType("int")},
},
Returns: []code.Type{
code.SimpleType("int"),
code.SimpleType("error"),
},
Operation: spec.CountOperation{
Query: spec.QuerySpec{
Predicates: []spec.Predicate{
{Field: "Age", Comparator: spec.ComparatorGreaterThan, ParamIndex: 1},
},
},
},
},
ExpectedCode: `
func (r *UserRepositoryMongo) CountByAgeGreaterThan(arg0 context.Context, arg1 int) (int, error) {
count, err := r.collection.CountDocuments(arg0, bson.M{
"age": bson.M{"$gt": arg1},
})
if err != nil {
return 0, err
}
return int(count), nil
}
`,
},
{
Name: "count with GreaterThanEqual comparator",
MethodSpec: spec.MethodSpec{
Name: "CountByAgeGreaterThanEqual",
Params: []code.Param{
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
{Type: code.SimpleType("int")},
},
Returns: []code.Type{
code.SimpleType("int"),
code.SimpleType("error"),
},
Operation: spec.CountOperation{
Query: spec.QuerySpec{
Predicates: []spec.Predicate{
{Field: "Age", Comparator: spec.ComparatorGreaterThanEqual, ParamIndex: 1},
},
},
},
},
ExpectedCode: `
func (r *UserRepositoryMongo) CountByAgeGreaterThanEqual(arg0 context.Context, arg1 int) (int, error) {
count, err := r.collection.CountDocuments(arg0, bson.M{
"age": bson.M{"$gte": arg1},
})
if err != nil {
return 0, err
}
return int(count), nil
}
`,
},
{
Name: "count with Between comparator",
MethodSpec: spec.MethodSpec{
Name: "CountByAgeBetween",
Params: []code.Param{
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
{Type: code.SimpleType("int")},
{Type: code.SimpleType("int")},
},
Returns: []code.Type{
code.SimpleType("int"),
code.SimpleType("error"),
},
Operation: spec.CountOperation{
Query: spec.QuerySpec{
Predicates: []spec.Predicate{
{Field: "Age", Comparator: spec.ComparatorBetween, ParamIndex: 1},
},
},
},
},
ExpectedCode: `
func (r *UserRepositoryMongo) CountByAgeBetween(arg0 context.Context, arg1 int, arg2 int) (int, error) {
count, err := r.collection.CountDocuments(arg0, bson.M{
"age": bson.M{"$gte": arg1, "$lte": arg2},
})
if err != nil {
return 0, err
}
return int(count), nil
}
`,
},
{
Name: "count with In comparator",
MethodSpec: spec.MethodSpec{
Name: "CountByAgeIn",
Params: []code.Param{
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
{Type: code.ArrayType{ContainedType: code.SimpleType("int")}},
},
Returns: []code.Type{
code.SimpleType("int"),
code.SimpleType("error"),
},
Operation: spec.CountOperation{
Query: spec.QuerySpec{
Predicates: []spec.Predicate{
{Field: "Age", Comparator: spec.ComparatorIn, ParamIndex: 1},
},
},
},
},
ExpectedCode: `
func (r *UserRepositoryMongo) CountByAgeIn(arg0 context.Context, arg1 []int) (int, error) {
count, err := r.collection.CountDocuments(arg0, bson.M{
"age": bson.M{"$in": arg1},
})
if err != nil {
return 0, err
}
return int(count), nil
}
`,
},
}
for _, testCase := range testTable {
t.Run(testCase.Name, func(t *testing.T) {
generator := mongo.NewGenerator(userModel, "UserRepository")
buffer := new(bytes.Buffer)
err := generator.GenerateMethod(testCase.MethodSpec, buffer)
if err != nil {
t.Error(err)
}
if err := testutils.ExpectMultiLineString(testCase.ExpectedCode, buffer.String()); err != nil {
t.Error(err)
}
})
}
}
type GenerateMethodInvalidTestCase struct {
Name string
Method spec.MethodSpec

View file

@ -159,3 +159,15 @@ const deleteManyTemplate = ` result, err := r.collection.DeleteMany(arg0, bson.M
return 0, err
}
return int(result.DeletedCount), nil`
type mongoCountTemplateData struct {
QuerySpec querySpec
}
const countTemplate = ` count, err := r.collection.CountDocuments(arg0, bson.M{
{{.QuerySpec.Code}}
})
if err != nil {
return 0, err
}
return int(count), nil`