Add push update operator
This commit is contained in:
parent
b3d9bf3f8f
commit
295f457e64
14 changed files with 382 additions and 57 deletions
|
@ -44,3 +44,16 @@ type updateTypeNotSupportedError struct {
|
|||
func (err updateTypeNotSupportedError) Error() string {
|
||||
return fmt.Sprintf("update type %s not supported", err.Update.Name())
|
||||
}
|
||||
|
||||
// NewUpdateOperatorNotSupportedError creates updateOperatorNotSupportedError
|
||||
func NewUpdateOperatorNotSupportedError(operator spec.UpdateOperator) error {
|
||||
return updateOperatorNotSupportedError{Operator: operator}
|
||||
}
|
||||
|
||||
type updateOperatorNotSupportedError struct {
|
||||
Operator spec.UpdateOperator
|
||||
}
|
||||
|
||||
func (err updateOperatorNotSupportedError) Error() string {
|
||||
return fmt.Sprintf("update operator %s not supported", err.Operator)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/sunboyy/repogen/internal/mongo"
|
||||
"github.com/sunboyy/repogen/internal/spec"
|
||||
)
|
||||
|
||||
type ErrorTestCase struct {
|
||||
|
@ -40,12 +41,17 @@ func TestError(t *testing.T) {
|
|||
Error: mongo.NewUpdateTypeNotSupportedError(StubUpdate{}),
|
||||
ExpectedString: "update type Stub not supported",
|
||||
},
|
||||
{
|
||||
Name: "UpdateOperatorNotSupportedError",
|
||||
Error: mongo.NewUpdateOperatorNotSupportedError(spec.UpdateOperator("STUB")),
|
||||
ExpectedString: "update operator STUB not supported",
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testTable {
|
||||
t.Run(testCase.Name, func(t *testing.T) {
|
||||
if testCase.Error.Error() != testCase.ExpectedString {
|
||||
t.Errorf("Expected = %v\nReceived = %v", testCase.ExpectedString, testCase.Error.Error())
|
||||
t.Errorf("Expected = %+v\nReceived = %+v", testCase.ExpectedString, testCase.Error.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -167,13 +167,22 @@ func (g RepositoryGenerator) getMongoUpdate(updateSpec spec.Update) (update, err
|
|||
case spec.UpdateModel:
|
||||
return updateModel{}, nil
|
||||
case spec.UpdateFields:
|
||||
var update updateFields
|
||||
update := make(updateFields)
|
||||
for _, field := range updateSpec {
|
||||
bsonFieldReference, err := g.bsonFieldReference(field.FieldReference)
|
||||
if err != nil {
|
||||
return querySpec{}, err
|
||||
}
|
||||
update.Fields = append(update.Fields, updateField{BsonTag: bsonFieldReference, ParamIndex: field.ParamIndex})
|
||||
|
||||
updateKey := getUpdateOperatorKey(field.Operator)
|
||||
if updateKey == "" {
|
||||
return querySpec{}, NewUpdateOperatorNotSupportedError(field.Operator)
|
||||
}
|
||||
updateField := updateField{
|
||||
BsonTag: bsonFieldReference,
|
||||
ParamIndex: field.ParamIndex,
|
||||
}
|
||||
update[updateKey] = append(update[updateKey], updateField)
|
||||
}
|
||||
return update, nil
|
||||
default:
|
||||
|
@ -181,6 +190,17 @@ func (g RepositoryGenerator) getMongoUpdate(updateSpec spec.Update) (update, err
|
|||
}
|
||||
}
|
||||
|
||||
func getUpdateOperatorKey(operator spec.UpdateOperator) string {
|
||||
switch operator {
|
||||
case spec.UpdateOperatorSet:
|
||||
return "$set"
|
||||
case spec.UpdateOperatorPush:
|
||||
return "$push"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (g RepositoryGenerator) generateDeleteImplementation(operation spec.DeleteOperation) (string, error) {
|
||||
querySpec, err := g.mongoQuerySpec(operation.Query)
|
||||
if err != nil {
|
||||
|
|
|
@ -31,6 +31,11 @@ var (
|
|||
Type: code.SimpleType("NameModel"),
|
||||
Tags: map[string][]string{"bson": {"name"}},
|
||||
}
|
||||
consentHistoryField = code.StructField{
|
||||
Name: "ConsentHistory",
|
||||
Type: code.ArrayType{ContainedType: code.SimpleType("ConsentHistory")},
|
||||
Tags: map[string][]string{"bson": {"consent_history"}},
|
||||
}
|
||||
enabledField = code.StructField{
|
||||
Name: "Enabled",
|
||||
Type: code.SimpleType("bool"),
|
||||
|
@ -60,6 +65,7 @@ var userModel = code.Struct{
|
|||
genderField,
|
||||
ageField,
|
||||
nameField,
|
||||
consentHistoryField,
|
||||
enabledField,
|
||||
accessTokenField,
|
||||
},
|
||||
|
@ -983,7 +989,7 @@ func (r *UserRepositoryMongo) UpdateByID(arg0 context.Context, arg1 *UserModel,
|
|||
},
|
||||
Operation: spec.UpdateOperation{
|
||||
Update: spec.UpdateFields{
|
||||
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||
},
|
||||
Mode: spec.QueryModeOne,
|
||||
Query: spec.QuerySpec{
|
||||
|
@ -1024,7 +1030,7 @@ func (r *UserRepositoryMongo) UpdateAgeByID(arg0 context.Context, arg1 int, arg2
|
|||
},
|
||||
Operation: spec.UpdateOperation{
|
||||
Update: spec.UpdateFields{
|
||||
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
||||
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||
},
|
||||
Mode: spec.QueryModeMany,
|
||||
Query: spec.QuerySpec{
|
||||
|
@ -1048,6 +1054,93 @@ func (r *UserRepositoryMongo) UpdateAgeByGender(arg0 context.Context, arg1 int,
|
|||
}
|
||||
return int(result.MatchedCount), err
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
Name: "simple update push method",
|
||||
MethodSpec: spec.MethodSpec{
|
||||
Name: "UpdateConsentHistoryPushByID",
|
||||
Params: []code.Param{
|
||||
{Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Name: "consentHistory", Type: code.SimpleType("ConsentHistory")},
|
||||
{Name: "gender", 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{consentHistoryField}, ParamIndex: 1, Operator: spec.UpdateOperatorPush},
|
||||
},
|
||||
Mode: spec.QueryModeOne,
|
||||
Query: spec.QuerySpec{
|
||||
Predicates: []spec.Predicate{
|
||||
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectedCode: `
|
||||
func (r *UserRepositoryMongo) UpdateConsentHistoryPushByID(arg0 context.Context, arg1 ConsentHistory, arg2 primitive.ObjectID) (bool, error) {
|
||||
result, err := r.collection.UpdateOne(arg0, bson.M{
|
||||
"_id": arg2,
|
||||
}, bson.M{
|
||||
"$push": bson.M{
|
||||
"consent_history": arg1,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return result.MatchedCount > 0, err
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
Name: "simple update set and push method",
|
||||
MethodSpec: spec.MethodSpec{
|
||||
Name: "UpdateEnabledAndConsentHistoryPushByID",
|
||||
Params: []code.Param{
|
||||
{Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Name: "enabled", Type: code.SimpleType("bool")},
|
||||
{Name: "consentHistory", Type: code.SimpleType("ConsentHistory")},
|
||||
{Name: "gender", 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{enabledField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||
{FieldReference: spec.FieldReference{consentHistoryField}, ParamIndex: 2, Operator: spec.UpdateOperatorPush},
|
||||
},
|
||||
Mode: spec.QueryModeOne,
|
||||
Query: spec.QuerySpec{
|
||||
Predicates: []spec.Predicate{
|
||||
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectedCode: `
|
||||
func (r *UserRepositoryMongo) UpdateEnabledAndConsentHistoryPushByID(arg0 context.Context, arg1 bool, arg2 ConsentHistory, arg3 primitive.ObjectID) (bool, error) {
|
||||
result, err := r.collection.UpdateOne(arg0, bson.M{
|
||||
"_id": arg3,
|
||||
}, bson.M{
|
||||
"$set": bson.M{
|
||||
"enabled": arg1,
|
||||
},
|
||||
"$push": bson.M{
|
||||
"consent_history": arg2,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return result.MatchedCount > 0, err
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
@ -1065,7 +1158,7 @@ func (r *UserRepositoryMongo) UpdateAgeByGender(arg0 context.Context, arg1 int,
|
|||
},
|
||||
Operation: spec.UpdateOperation{
|
||||
Update: spec.UpdateFields{
|
||||
{FieldReference: spec.FieldReference{nameField, firstNameField}, ParamIndex: 1},
|
||||
{FieldReference: spec.FieldReference{nameField, firstNameField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||
},
|
||||
Mode: spec.QueryModeOne,
|
||||
Query: spec.QuerySpec{
|
||||
|
@ -1947,7 +2040,7 @@ func TestGenerateMethod_Invalid(t *testing.T) {
|
|||
},
|
||||
Operation: spec.UpdateOperation{
|
||||
Update: spec.UpdateFields{
|
||||
{FieldReference: spec.FieldReference{accessTokenField}, ParamIndex: 1},
|
||||
{FieldReference: spec.FieldReference{accessTokenField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||
},
|
||||
Mode: spec.QueryModeOne,
|
||||
Query: spec.QuerySpec{
|
||||
|
@ -1984,6 +2077,33 @@ func TestGenerateMethod_Invalid(t *testing.T) {
|
|||
},
|
||||
ExpectedError: mongo.NewUpdateTypeNotSupportedError(StubUpdate{}),
|
||||
},
|
||||
{
|
||||
Name: "update operator not supported",
|
||||
Method: spec.MethodSpec{
|
||||
Name: "UpdateConsentHistoryAppendByID",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.SimpleType("int")},
|
||||
{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{consentHistoryField}, ParamIndex: 1, Operator: "APPEND"},
|
||||
},
|
||||
Mode: spec.QueryModeOne,
|
||||
Query: spec.QuerySpec{
|
||||
Predicates: []spec.Predicate{
|
||||
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectedError: mongo.NewUpdateOperatorNotSupportedError("APPEND"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testTable {
|
||||
|
@ -1994,7 +2114,7 @@ func TestGenerateMethod_Invalid(t *testing.T) {
|
|||
err := generator.GenerateMethod(testCase.Method, buffer)
|
||||
|
||||
if err != testCase.ExpectedError {
|
||||
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError, err)
|
||||
t.Errorf("\nExpected = %+v\nReceived = %+v", testCase.ExpectedError, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -23,16 +23,19 @@ func (u updateModel) Code() string {
|
|||
return ` "$set": arg1,`
|
||||
}
|
||||
|
||||
type updateFields struct {
|
||||
Fields []updateField
|
||||
}
|
||||
type updateFields map[string][]updateField
|
||||
|
||||
func (u updateFields) Code() string {
|
||||
lines := []string{` "$set": bson.M{`}
|
||||
for _, field := range u.Fields {
|
||||
lines = append(lines, fmt.Sprintf(` "%s": arg%d,`, field.BsonTag, field.ParamIndex))
|
||||
var lines []string
|
||||
for k, v := range u {
|
||||
lines = append(lines, fmt.Sprintf(` "%s": bson.M{`, k))
|
||||
|
||||
for _, field := range v {
|
||||
lines = append(lines, fmt.Sprintf(` "%s": arg%d,`, field.BsonTag, field.ParamIndex))
|
||||
}
|
||||
|
||||
lines = append(lines, ` },`)
|
||||
}
|
||||
lines = append(lines, ` },`)
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue