Add push update operator
This commit is contained in:
parent
b3d9bf3f8f
commit
295f457e64
14 changed files with 382 additions and 57 deletions
16
README.md
16
README.md
|
@ -200,13 +200,15 @@ Assuming that the `City` field in the `UserModel` struct is of type `string` and
|
||||||
|
|
||||||
When you specify the query like `ByAge`, it finds documents that contains age value **equal to** the provided parameter value. However, there are other types of comparators provided for you to use as follows.
|
When you specify the query like `ByAge`, it finds documents that contains age value **equal to** the provided parameter value. However, there are other types of comparators provided for you to use as follows.
|
||||||
|
|
||||||
- `Not`: The value in the document is not equal to the provided parameter value.
|
| Keyword | Meaning | Sample |
|
||||||
- `LessThan`: The value in the document is less than the provided parameter value.
|
|--------------------|-----------------|--------------------------------------|
|
||||||
- `LessThanEqual`: The value in the document is less than or equal to the provided parameter value.
|
| - | == $1 | `FindByUsername(ctx, $1)` |
|
||||||
- `GreaterThan`: The value in the document is greater than the provided parameter value.
|
| `LessThan` | < $1 | `FindByAgeLessThan(ctx, $1)` |
|
||||||
- `GreaterThanEqual`: The value in the document is greater than of equal to the provided parameter value.
|
| `LessThanEqual` | <= $1 | `FindByAgeLessThanEqual(ctx, $1)` |
|
||||||
- `Between`: The value in the document is between two provided parameter values (inclusive).
|
| `GreaterThan` | > $1 | `FindByAgeGreaterThan(ctx, $1)` |
|
||||||
- `In`: The value in the document is in the provided parameter value (which is a slice).
|
| `GreaterThanEqual` | >= $1 | `FindByAgeGreaterThanEqual(ctx, $1)` |
|
||||||
|
| `Between` | >= $1 and <= $2 | `FindByAgeBetween(ctx, $1, $2)` |
|
||||||
|
| `In` | in slice $1 | `FindByCityIn(ctx, $1)` |
|
||||||
|
|
||||||
To apply these comparators to the query, place these words after the field name such as `ByAgeGreaterThan`. You can also use comparators along with `And` and `Or` operators. For example, `ByGenderNotOrAgeLessThan` will apply `Not` comparator to the `Gender` field and `LessThan` comparator to the `Age` field.
|
To apply these comparators to the query, place these words after the field name such as `ByAgeGreaterThan`. You can also use comparators along with `And` and `Or` operators. For example, `ByGenderNotOrAgeLessThan` will apply `Not` comparator to the `Gender` field and `LessThan` comparator to the `Age` field.
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,7 @@ type UserRepository interface {
|
||||||
file := code.ExtractComponents(f)
|
file := code.ExtractComponents(f)
|
||||||
|
|
||||||
if !reflect.DeepEqual(file, testCase.ExpectedOutput) {
|
if !reflect.DeepEqual(file, testCase.ExpectedOutput) {
|
||||||
t.Errorf("Expected = %v\nReceived = %v", testCase.ExpectedOutput, file)
|
t.Errorf("Expected = %+v\nReceived = %+v", testCase.ExpectedOutput, file)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ func TestStructsByName(t *testing.T) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(structModel, userStruct) {
|
if !reflect.DeepEqual(structModel, userStruct) {
|
||||||
t.Errorf("Expected = %v\nReceived = %v", userStruct, structModel)
|
t.Errorf("Expected = %+v\nReceived = %+v", userStruct, structModel)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ func TestStructFieldsByName(t *testing.T) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(field, usernameField) {
|
if !reflect.DeepEqual(field, usernameField) {
|
||||||
t.Errorf("Expected = %v\nReceived = %v", usernameField, field)
|
t.Errorf("Expected = %+v\nReceived = %+v", usernameField, field)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ func TestInterfacesByName(t *testing.T) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(intf, userRepoIntf) {
|
if !reflect.DeepEqual(intf, userRepoIntf) {
|
||||||
t.Errorf("Expected = %v\nReceived = %v", userRepoIntf, intf)
|
t.Errorf("Expected = %+v\nReceived = %+v", userRepoIntf, intf)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ func TestArrayTypeCode(t *testing.T) {
|
||||||
code := testCase.Type.Code()
|
code := testCase.Type.Code()
|
||||||
|
|
||||||
if code != testCase.ExpectedCode {
|
if code != testCase.ExpectedCode {
|
||||||
t.Errorf("Expected = %v\nReceived = %v", testCase.ExpectedCode, code)
|
t.Errorf("Expected = %+v\nReceived = %+v", testCase.ExpectedCode, code)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,3 +44,16 @@ type updateTypeNotSupportedError struct {
|
||||||
func (err updateTypeNotSupportedError) Error() string {
|
func (err updateTypeNotSupportedError) Error() string {
|
||||||
return fmt.Sprintf("update type %s not supported", err.Update.Name())
|
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"
|
"testing"
|
||||||
|
|
||||||
"github.com/sunboyy/repogen/internal/mongo"
|
"github.com/sunboyy/repogen/internal/mongo"
|
||||||
|
"github.com/sunboyy/repogen/internal/spec"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ErrorTestCase struct {
|
type ErrorTestCase struct {
|
||||||
|
@ -40,12 +41,17 @@ func TestError(t *testing.T) {
|
||||||
Error: mongo.NewUpdateTypeNotSupportedError(StubUpdate{}),
|
Error: mongo.NewUpdateTypeNotSupportedError(StubUpdate{}),
|
||||||
ExpectedString: "update type Stub not supported",
|
ExpectedString: "update type Stub not supported",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "UpdateOperatorNotSupportedError",
|
||||||
|
Error: mongo.NewUpdateOperatorNotSupportedError(spec.UpdateOperator("STUB")),
|
||||||
|
ExpectedString: "update operator STUB not supported",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.Name, func(t *testing.T) {
|
t.Run(testCase.Name, func(t *testing.T) {
|
||||||
if testCase.Error.Error() != testCase.ExpectedString {
|
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:
|
case spec.UpdateModel:
|
||||||
return updateModel{}, nil
|
return updateModel{}, nil
|
||||||
case spec.UpdateFields:
|
case spec.UpdateFields:
|
||||||
var update updateFields
|
update := make(updateFields)
|
||||||
for _, field := range updateSpec {
|
for _, field := range updateSpec {
|
||||||
bsonFieldReference, err := g.bsonFieldReference(field.FieldReference)
|
bsonFieldReference, err := g.bsonFieldReference(field.FieldReference)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return querySpec{}, err
|
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
|
return update, nil
|
||||||
default:
|
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) {
|
func (g RepositoryGenerator) generateDeleteImplementation(operation spec.DeleteOperation) (string, error) {
|
||||||
querySpec, err := g.mongoQuerySpec(operation.Query)
|
querySpec, err := g.mongoQuerySpec(operation.Query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -31,6 +31,11 @@ var (
|
||||||
Type: code.SimpleType("NameModel"),
|
Type: code.SimpleType("NameModel"),
|
||||||
Tags: map[string][]string{"bson": {"name"}},
|
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{
|
enabledField = code.StructField{
|
||||||
Name: "Enabled",
|
Name: "Enabled",
|
||||||
Type: code.SimpleType("bool"),
|
Type: code.SimpleType("bool"),
|
||||||
|
@ -60,6 +65,7 @@ var userModel = code.Struct{
|
||||||
genderField,
|
genderField,
|
||||||
ageField,
|
ageField,
|
||||||
nameField,
|
nameField,
|
||||||
|
consentHistoryField,
|
||||||
enabledField,
|
enabledField,
|
||||||
accessTokenField,
|
accessTokenField,
|
||||||
},
|
},
|
||||||
|
@ -983,7 +989,7 @@ func (r *UserRepositoryMongo) UpdateByID(arg0 context.Context, arg1 *UserModel,
|
||||||
},
|
},
|
||||||
Operation: spec.UpdateOperation{
|
Operation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
|
@ -1024,7 +1030,7 @@ func (r *UserRepositoryMongo) UpdateAgeByID(arg0 context.Context, arg1 int, arg2
|
||||||
},
|
},
|
||||||
Operation: spec.UpdateOperation{
|
Operation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{ageField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
|
@ -1048,6 +1054,93 @@ func (r *UserRepositoryMongo) UpdateAgeByGender(arg0 context.Context, arg1 int,
|
||||||
}
|
}
|
||||||
return int(result.MatchedCount), err
|
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{
|
Operation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{FieldReference: spec.FieldReference{nameField, firstNameField}, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{nameField, firstNameField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
|
@ -1947,7 +2040,7 @@ func TestGenerateMethod_Invalid(t *testing.T) {
|
||||||
},
|
},
|
||||||
Operation: spec.UpdateOperation{
|
Operation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{FieldReference: spec.FieldReference{accessTokenField}, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{accessTokenField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{
|
Query: spec.QuerySpec{
|
||||||
|
@ -1984,6 +2077,33 @@ func TestGenerateMethod_Invalid(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedError: mongo.NewUpdateTypeNotSupportedError(StubUpdate{}),
|
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 {
|
for _, testCase := range testTable {
|
||||||
|
@ -1994,7 +2114,7 @@ func TestGenerateMethod_Invalid(t *testing.T) {
|
||||||
err := generator.GenerateMethod(testCase.Method, buffer)
|
err := generator.GenerateMethod(testCase.Method, buffer)
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,16 +23,19 @@ func (u updateModel) Code() string {
|
||||||
return ` "$set": arg1,`
|
return ` "$set": arg1,`
|
||||||
}
|
}
|
||||||
|
|
||||||
type updateFields struct {
|
type updateFields map[string][]updateField
|
||||||
Fields []updateField
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u updateFields) Code() string {
|
func (u updateFields) Code() string {
|
||||||
lines := []string{` "$set": bson.M{`}
|
var lines []string
|
||||||
for _, field := range u.Fields {
|
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, fmt.Sprintf(` "%s": arg%d,`, field.BsonTag, field.ParamIndex))
|
||||||
}
|
}
|
||||||
|
|
||||||
lines = append(lines, ` },`)
|
lines = append(lines, ` },`)
|
||||||
|
}
|
||||||
return strings.Join(lines, "\n")
|
return strings.Join(lines, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,11 @@ func (err ParsingError) Error() string {
|
||||||
case InvalidParamError:
|
case InvalidParamError:
|
||||||
return "parameters do not match the query"
|
return "parameters do not match the query"
|
||||||
case InvalidUpdateFieldsError:
|
case InvalidUpdateFieldsError:
|
||||||
return "update fields is invalid"
|
return "update fields are invalid"
|
||||||
case ContextParamRequiredError:
|
case ContextParamRequiredError:
|
||||||
return "context parameter is required"
|
return "context parameter is required"
|
||||||
|
case PushNonArrayError:
|
||||||
|
return "cannot use push operation in a non-array type"
|
||||||
}
|
}
|
||||||
return string(err)
|
return string(err)
|
||||||
}
|
}
|
||||||
|
@ -33,6 +35,7 @@ const (
|
||||||
InvalidParamError ParsingError = "ERROR_INVALID_PARAM"
|
InvalidParamError ParsingError = "ERROR_INVALID_PARAM"
|
||||||
InvalidUpdateFieldsError ParsingError = "ERROR_INVALID_UPDATE_FIELDS"
|
InvalidUpdateFieldsError ParsingError = "ERROR_INVALID_UPDATE_FIELDS"
|
||||||
ContextParamRequiredError ParsingError = "ERROR_CONTEXT_PARAM_REQUIRED"
|
ContextParamRequiredError ParsingError = "ERROR_CONTEXT_PARAM_REQUIRED"
|
||||||
|
PushNonArrayError ParsingError = "ERROR_PUSH_NON_ARRAY"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewInvalidQueryError creates invalidQueryError
|
// NewInvalidQueryError creates invalidQueryError
|
||||||
|
|
|
@ -48,7 +48,7 @@ func TestError(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) {
|
||||||
if testCase.Error.Error() != testCase.ExpectedString {
|
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())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ func TestOperationName(t *testing.T) {
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.ExpectedName, func(t *testing.T) {
|
t.Run(testCase.ExpectedName, func(t *testing.T) {
|
||||||
if testCase.Operation.Name() != testCase.ExpectedName {
|
if testCase.Operation.Name() != testCase.ExpectedName {
|
||||||
t.Errorf("Expected = %v\nReceived = %v", testCase.ExpectedName, testCase.Operation.Name())
|
t.Errorf("Expected = %+v\nReceived = %+v", testCase.ExpectedName, testCase.Operation.Name())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,10 @@ var (
|
||||||
Name: "Enabled",
|
Name: "Enabled",
|
||||||
Type: code.SimpleType("bool"),
|
Type: code.SimpleType("bool"),
|
||||||
}
|
}
|
||||||
|
consentHistoryField = code.StructField{
|
||||||
|
Name: "ConsentHistory",
|
||||||
|
Type: code.ArrayType{ContainedType: code.SimpleType("ConsentHistoryItem")},
|
||||||
|
}
|
||||||
|
|
||||||
firstNameField = code.StructField{
|
firstNameField = code.StructField{
|
||||||
Name: "First",
|
Name: "First",
|
||||||
|
@ -81,6 +85,7 @@ var (
|
||||||
contactField,
|
contactField,
|
||||||
referrerField,
|
referrerField,
|
||||||
defaultPaymentField,
|
defaultPaymentField,
|
||||||
|
consentHistoryField,
|
||||||
enabledField,
|
enabledField,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -149,7 +154,7 @@ func TestParseInterfaceMethod_Insert(t *testing.T) {
|
||||||
Operation: testCase.ExpectedOperation,
|
Operation: testCase.ExpectedOperation,
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(actualSpec, expectedOutput) {
|
if !reflect.DeepEqual(actualSpec, expectedOutput) {
|
||||||
t.Errorf("Expected = %v\nReceived = %v", expectedOutput, actualSpec)
|
t.Errorf("Expected = %+v\nReceived = %+v", expectedOutput, actualSpec)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -654,7 +659,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||||
Operation: testCase.ExpectedOperation,
|
Operation: testCase.ExpectedOperation,
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(actualSpec, expectedOutput) {
|
if !reflect.DeepEqual(actualSpec, expectedOutput) {
|
||||||
t.Errorf("Expected = %v\nReceived = %v", expectedOutput, actualSpec)
|
t.Errorf("Expected = %+v\nReceived = %+v", expectedOutput, actualSpec)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -700,7 +705,7 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedOperation: spec.UpdateOperation{
|
ExpectedOperation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
|
@ -724,7 +729,7 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedOperation: spec.UpdateOperation{
|
ExpectedOperation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
|
@ -748,7 +753,7 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedOperation: spec.UpdateOperation{
|
ExpectedOperation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{FieldReference: spec.FieldReference{nameField, firstNameField}, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{nameField, firstNameField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||||
},
|
},
|
||||||
Mode: spec.QueryModeOne,
|
Mode: spec.QueryModeOne,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
|
@ -773,8 +778,58 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedOperation: spec.UpdateOperation{
|
ExpectedOperation: spec.UpdateOperation{
|
||||||
Update: spec.UpdateFields{
|
Update: spec.UpdateFields{
|
||||||
{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1},
|
{FieldReference: spec.FieldReference{genderField}, ParamIndex: 1, Operator: spec.UpdateOperatorSet},
|
||||||
{FieldReference: spec.FieldReference{cityField}, ParamIndex: 2},
|
{FieldReference: spec.FieldReference{cityField}, ParamIndex: 2, Operator: spec.UpdateOperatorSet},
|
||||||
|
},
|
||||||
|
Mode: spec.QueryModeMany,
|
||||||
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 3},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "UpdateArgPushByArg method",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "UpdateConsentHistoryPushByID",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Type: code.SimpleType("ConsentHistoryItem")},
|
||||||
|
{Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.SimpleType("int"),
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedOperation: spec.UpdateOperation{
|
||||||
|
Update: spec.UpdateFields{
|
||||||
|
{FieldReference: spec.FieldReference{consentHistoryField}, ParamIndex: 1, Operator: spec.UpdateOperatorPush},
|
||||||
|
},
|
||||||
|
Mode: spec.QueryModeMany,
|
||||||
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
|
{FieldReference: spec.FieldReference{idField}, Comparator: spec.ComparatorEqual, ParamIndex: 2},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "UpdateArgAndArgPushByArg method",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "UpdateEnabledAndConsentHistoryPushByID",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Type: code.SimpleType("bool")},
|
||||||
|
{Type: code.SimpleType("ConsentHistoryItem")},
|
||||||
|
{Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.SimpleType("int"),
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedOperation: 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.QueryModeMany,
|
Mode: spec.QueryModeMany,
|
||||||
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
Query: spec.QuerySpec{Predicates: []spec.Predicate{
|
||||||
|
@ -798,7 +853,7 @@ func TestParseInterfaceMethod_Update(t *testing.T) {
|
||||||
Operation: testCase.ExpectedOperation,
|
Operation: testCase.ExpectedOperation,
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(actualSpec, expectedOutput) {
|
if !reflect.DeepEqual(actualSpec, expectedOutput) {
|
||||||
t.Errorf("Expected = %v\nReceived = %v", expectedOutput, actualSpec)
|
t.Errorf("Expected = %+v\nReceived = %+v", expectedOutput, actualSpec)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1089,7 +1144,7 @@ func TestParseInterfaceMethod_Delete(t *testing.T) {
|
||||||
Operation: testCase.ExpectedOperation,
|
Operation: testCase.ExpectedOperation,
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(actualSpec, expectedOutput) {
|
if !reflect.DeepEqual(actualSpec, expectedOutput) {
|
||||||
t.Errorf("Expected = %v\nReceived = %v", expectedOutput, actualSpec)
|
t.Errorf("Expected = %+v\nReceived = %+v", expectedOutput, actualSpec)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1150,7 +1205,7 @@ func TestParseInterfaceMethod_Count(t *testing.T) {
|
||||||
Operation: testCase.ExpectedOperation,
|
Operation: testCase.ExpectedOperation,
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(actualSpec, expectedOutput) {
|
if !reflect.DeepEqual(actualSpec, expectedOutput) {
|
||||||
t.Errorf("Expected = %v\nReceived = %v", expectedOutput, actualSpec)
|
t.Errorf("Expected = %+v\nReceived = %+v", expectedOutput, actualSpec)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1169,7 +1224,7 @@ func TestParseInterfaceMethod_Invalid(t *testing.T) {
|
||||||
|
|
||||||
expectedError := spec.NewUnknownOperationError("Search")
|
expectedError := spec.NewUnknownOperationError("Search")
|
||||||
if err != expectedError {
|
if err != expectedError {
|
||||||
t.Errorf("\nExpected = %v\nReceived = %v", expectedError, err)
|
t.Errorf("\nExpected = %+v\nReceived = %+v", expectedError, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1275,7 +1330,7 @@ func TestParseInterfaceMethod_Insert_Invalid(t *testing.T) {
|
||||||
_, err := spec.ParseInterfaceMethod(structs, 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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1577,7 +1632,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) {
|
||||||
_, err := spec.ParseInterfaceMethod(structs, 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())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1647,6 +1702,22 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedError: spec.InvalidUpdateFieldsError,
|
ExpectedError: spec.InvalidUpdateFieldsError,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "push operator in non-array field",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "UpdateGenderPushByID",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Type: code.SimpleType("Gender")},
|
||||||
|
{Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.SimpleType("bool"),
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedError: spec.PushNonArrayError,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "update method without query",
|
Name: "update method without query",
|
||||||
Method: code.Method{
|
Method: code.Method{
|
||||||
|
@ -1677,6 +1748,37 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) {
|
||||||
},
|
},
|
||||||
ExpectedError: spec.NewInvalidQueryError([]string{"ID", "And", "Username", "Or", "Gender"}),
|
ExpectedError: spec.NewInvalidQueryError([]string{"ID", "And", "Username", "Or", "Gender"}),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "parameters for push operator is not array's contained type",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "UpdateConsentHistoryPushByID",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
{Type: code.ArrayType{ContainedType: code.SimpleType("ConsentHistoryItem")}},
|
||||||
|
{Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.SimpleType("int"),
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedError: spec.InvalidUpdateFieldsError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "insufficient function parameters",
|
||||||
|
Method: code.Method{
|
||||||
|
Name: "UpdateEnabledAll",
|
||||||
|
Params: []code.Param{
|
||||||
|
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||||
|
// {Type: code.SimpleType("Enabled")},
|
||||||
|
},
|
||||||
|
Returns: []code.Type{
|
||||||
|
code.SimpleType("int"),
|
||||||
|
code.SimpleType("error"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ExpectedError: spec.InvalidUpdateFieldsError,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "update model with invalid parameter",
|
Name: "update model with invalid parameter",
|
||||||
Method: code.Method{
|
Method: code.Method{
|
||||||
|
@ -1762,7 +1864,7 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) {
|
||||||
_, err := spec.ParseInterfaceMethod(structs, 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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1941,7 +2043,7 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) {
|
||||||
_, err := spec.ParseInterfaceMethod(structs, 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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2072,7 +2174,7 @@ func TestParseInterfaceMethod_Count_Invalid(t *testing.T) {
|
||||||
_, err := spec.ParseInterfaceMethod(structs, 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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,35 @@ func (u UpdateFields) NumberOfArguments() int {
|
||||||
type UpdateField struct {
|
type UpdateField struct {
|
||||||
FieldReference FieldReference
|
FieldReference FieldReference
|
||||||
ParamIndex int
|
ParamIndex int
|
||||||
|
Operator UpdateOperator
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOperator is a custom type that declares update operator to be used in an update operation
|
||||||
|
type UpdateOperator string
|
||||||
|
|
||||||
|
// UpdateOperator constants
|
||||||
|
const (
|
||||||
|
UpdateOperatorSet UpdateOperator = "SET"
|
||||||
|
UpdateOperatorPush UpdateOperator = "PUSH"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NumberOfArguments returns number of arguments required to perform an update operation
|
||||||
|
func (o UpdateOperator) NumberOfArguments() int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArgumentType returns type that is required for function parameter
|
||||||
|
func (o UpdateOperator) ArgumentType(fieldType code.Type) (code.Type, error) {
|
||||||
|
switch o {
|
||||||
|
case UpdateOperatorPush:
|
||||||
|
arrayType, ok := fieldType.(code.ArrayType)
|
||||||
|
if !ok {
|
||||||
|
return nil, PushNonArrayError
|
||||||
|
}
|
||||||
|
return arrayType.ContainedType, nil
|
||||||
|
default:
|
||||||
|
return fieldType, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p interfaceMethodParser) parseUpdateOperation(tokens []string) (Operation, error) {
|
func (p interfaceMethodParser) parseUpdateOperation(tokens []string) (Operation, error) {
|
||||||
|
@ -104,24 +133,51 @@ func (p interfaceMethodParser) parseUpdate(tokens []string) (Update, error) {
|
||||||
|
|
||||||
paramIndex := 1
|
paramIndex := 1
|
||||||
for _, updateFieldToken := range updateFieldTokens {
|
for _, updateFieldToken := range updateFieldTokens {
|
||||||
updateFieldReference, ok := p.fieldResolver.ResolveStructField(p.StructModel, updateFieldToken)
|
updateField, err := p.parseUpdateField(updateFieldToken, paramIndex)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return nil, NewStructFieldNotFoundError(updateFieldToken)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFields = append(updateFields, UpdateField{
|
updateFields = append(updateFields, updateField)
|
||||||
FieldReference: updateFieldReference,
|
paramIndex += updateField.Operator.NumberOfArguments()
|
||||||
ParamIndex: paramIndex,
|
|
||||||
})
|
|
||||||
paramIndex++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, field := range updateFields {
|
for _, field := range updateFields {
|
||||||
if len(p.Method.Params) <= field.ParamIndex ||
|
if len(p.Method.Params) < field.ParamIndex+field.Operator.NumberOfArguments() {
|
||||||
field.FieldReference.ReferencedField().Type != p.Method.Params[field.ParamIndex].Type {
|
|
||||||
return nil, InvalidUpdateFieldsError
|
return nil, InvalidUpdateFieldsError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requiredType, err := field.Operator.ArgumentType(field.FieldReference.ReferencedField().Type)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < field.Operator.NumberOfArguments(); i++ {
|
||||||
|
if requiredType != p.Method.Params[field.ParamIndex+i].Type {
|
||||||
|
return nil, InvalidUpdateFieldsError
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return updateFields, nil
|
return updateFields, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p interfaceMethodParser) parseUpdateField(t []string, paramIndex int) (UpdateField, error) {
|
||||||
|
if len(t) > 1 && t[len(t)-1] == "Push" {
|
||||||
|
return p.createUpdateField(t[:len(t)-1], UpdateOperatorPush, paramIndex)
|
||||||
|
}
|
||||||
|
return p.createUpdateField(t, UpdateOperatorSet, paramIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p interfaceMethodParser) createUpdateField(t []string, operator UpdateOperator, paramIndex int) (UpdateField, error) {
|
||||||
|
fieldReference, ok := p.fieldResolver.ResolveStructField(p.StructModel, t)
|
||||||
|
if !ok {
|
||||||
|
return UpdateField{}, NewStructFieldNotFoundError(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
return UpdateField{
|
||||||
|
FieldReference: fieldReference,
|
||||||
|
ParamIndex: paramIndex,
|
||||||
|
Operator: operator,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestUpdateTypeName(t *testing.T) {
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.ExpectedName, func(t *testing.T) {
|
t.Run(testCase.ExpectedName, func(t *testing.T) {
|
||||||
if testCase.Update.Name() != testCase.ExpectedName {
|
if testCase.Update.Name() != testCase.ExpectedName {
|
||||||
t.Errorf("Expected = %v\nReceived = %v", testCase.ExpectedName, testCase.Update.Name())
|
t.Errorf("Expected = %+v\nReceived = %+v", testCase.ExpectedName, testCase.Update.Name())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue