Add insert operation
This commit is contained in:
parent
7f07de08af
commit
25e1b2aa85
13 changed files with 509 additions and 38 deletions
internal/spec
|
@ -9,14 +9,14 @@ func (err ParsingError) Error() string {
|
|||
return "unknown operation"
|
||||
case UnsupportedNameError:
|
||||
return "method name is not supported"
|
||||
case UnsupportedReturnError:
|
||||
return "this type of return is not supported"
|
||||
case InvalidQueryError:
|
||||
return "invalid query"
|
||||
case InvalidParamError:
|
||||
return "parameters do not match the query"
|
||||
case InvalidUpdateFieldsError:
|
||||
return "update fields is invalid"
|
||||
case UnsupportedReturnError:
|
||||
return "this type of return is not supported"
|
||||
case ContextParamRequiredError:
|
||||
return "context parameter is required"
|
||||
case StructFieldNotFoundError:
|
||||
|
@ -29,10 +29,10 @@ func (err ParsingError) Error() string {
|
|||
const (
|
||||
UnknownOperationError ParsingError = "ERROR_UNKNOWN_OPERATION"
|
||||
UnsupportedNameError ParsingError = "ERROR_UNSUPPORTED"
|
||||
UnsupportedReturnError ParsingError = "ERROR_UNSUPPORTED_RETURN"
|
||||
InvalidQueryError ParsingError = "ERROR_INVALID_QUERY"
|
||||
InvalidParamError ParsingError = "ERROR_INVALID_PARAM"
|
||||
InvalidUpdateFieldsError ParsingError = "ERROR_INVALID_UPDATE_FIELDS"
|
||||
UnsupportedReturnError ParsingError = "ERROR_INVALID_RETURN"
|
||||
ContextParamRequiredError ParsingError = "ERROR_CONTEXT_PARAM_REQUIRED"
|
||||
StructFieldNotFoundError ParsingError = "ERROR_STRUCT_FIELD_NOT_FOUND"
|
||||
)
|
||||
|
|
|
@ -27,6 +27,11 @@ type MethodSpec struct {
|
|||
type Operation interface {
|
||||
}
|
||||
|
||||
// InsertOperation is a method specification for insert operations
|
||||
type InsertOperation struct {
|
||||
Mode QueryMode
|
||||
}
|
||||
|
||||
// FindOperation is a method specification for find operations
|
||||
type FindOperation struct {
|
||||
Mode QueryMode
|
||||
|
|
|
@ -23,6 +23,8 @@ type interfaceMethodParser struct {
|
|||
func (p interfaceMethodParser) Parse() (MethodSpec, error) {
|
||||
methodNameTokens := camelcase.Split(p.Method.Name)
|
||||
switch methodNameTokens[0] {
|
||||
case "Insert":
|
||||
return p.parseInsertMethod(methodNameTokens[1:])
|
||||
case "Find":
|
||||
return p.parseFindMethod(methodNameTokens[1:])
|
||||
case "Update":
|
||||
|
@ -33,6 +35,65 @@ func (p interfaceMethodParser) Parse() (MethodSpec, error) {
|
|||
return MethodSpec{}, UnknownOperationError
|
||||
}
|
||||
|
||||
func (p interfaceMethodParser) parseInsertMethod(tokens []string) (MethodSpec, error) {
|
||||
mode, err := p.extractInsertReturns(p.Method.Returns)
|
||||
if err != nil {
|
||||
return MethodSpec{}, err
|
||||
}
|
||||
|
||||
if err := p.validateContextParam(); err != nil {
|
||||
return MethodSpec{}, err
|
||||
}
|
||||
|
||||
pointerType := code.PointerType{ContainedType: p.StructModel.ReferencedType()}
|
||||
if mode == QueryModeOne && p.Method.Params[1].Type != pointerType {
|
||||
return MethodSpec{}, InvalidParamError
|
||||
}
|
||||
|
||||
arrayType := code.ArrayType{ContainedType: pointerType}
|
||||
if mode == QueryModeMany && p.Method.Params[1].Type != arrayType {
|
||||
return MethodSpec{}, InvalidParamError
|
||||
}
|
||||
|
||||
return MethodSpec{
|
||||
Name: p.Method.Name,
|
||||
Params: p.Method.Params,
|
||||
Returns: p.Method.Returns,
|
||||
Operation: InsertOperation{
|
||||
Mode: mode,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p interfaceMethodParser) extractInsertReturns(returns []code.Type) (QueryMode, error) {
|
||||
if len(returns) != 2 {
|
||||
return "", UnsupportedReturnError
|
||||
}
|
||||
|
||||
if returns[1] != code.SimpleType("error") {
|
||||
return "", UnsupportedReturnError
|
||||
}
|
||||
|
||||
interfaceType, ok := returns[0].(code.InterfaceType)
|
||||
if ok {
|
||||
if len(interfaceType.Methods) != 0 {
|
||||
return "", UnsupportedReturnError
|
||||
}
|
||||
return QueryModeOne, nil
|
||||
}
|
||||
|
||||
arrayType, ok := returns[0].(code.ArrayType)
|
||||
if ok {
|
||||
interfaceType, ok := arrayType.ContainedType.(code.InterfaceType)
|
||||
if !ok || len(interfaceType.Methods) != 0 {
|
||||
return "", UnsupportedReturnError
|
||||
}
|
||||
return QueryModeMany, nil
|
||||
}
|
||||
|
||||
return "", UnsupportedReturnError
|
||||
}
|
||||
|
||||
func (p interfaceMethodParser) parseFindMethod(tokens []string) (MethodSpec, error) {
|
||||
if len(tokens) == 0 {
|
||||
return MethodSpec{}, UnsupportedNameError
|
||||
|
|
|
@ -40,6 +40,64 @@ type ParseInterfaceMethodTestCase struct {
|
|||
ExpectedOperation spec.Operation
|
||||
}
|
||||
|
||||
func TestParseInterfaceMethod_Insert(t *testing.T) {
|
||||
testTable := []ParseInterfaceMethodTestCase{
|
||||
{
|
||||
Name: "InsertOne method",
|
||||
Method: code.Method{
|
||||
Name: "InsertOne",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.InterfaceType{},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOperation: spec.InsertOperation{
|
||||
Mode: spec.QueryModeOne,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "InsertMany method",
|
||||
Method: code.Method{
|
||||
Name: "InsertMany",
|
||||
Params: []code.Param{
|
||||
{Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Type: code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.InterfaceType{}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedOperation: spec.InsertOperation{
|
||||
Mode: spec.QueryModeMany,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testTable {
|
||||
t.Run(testCase.Name, func(t *testing.T) {
|
||||
actualSpec, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error = %s", err)
|
||||
}
|
||||
expectedOutput := spec.MethodSpec{
|
||||
Name: testCase.Method.Name,
|
||||
Params: testCase.Method.Params,
|
||||
Returns: testCase.Method.Returns,
|
||||
Operation: testCase.ExpectedOperation,
|
||||
}
|
||||
if !reflect.DeepEqual(actualSpec, expectedOutput) {
|
||||
t.Errorf("Expected = %v\nReceived = %v", expectedOutput, actualSpec)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseInterfaceMethod_Find(t *testing.T) {
|
||||
testTable := []ParseInterfaceMethodTestCase{
|
||||
{
|
||||
|
@ -736,6 +794,114 @@ func TestParseInterfaceMethod_Invalid(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestParseInterfaceMethod_Insert_Invalid(t *testing.T) {
|
||||
testTable := []ParseInterfaceMethodInvalidTestCase{
|
||||
{
|
||||
Name: "invalid number of returns",
|
||||
Method: code.Method{
|
||||
Name: "Insert",
|
||||
Returns: []code.Type{
|
||||
code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||
code.InterfaceType{},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.UnsupportedReturnError,
|
||||
},
|
||||
{
|
||||
Name: "unsupported return types from insert method",
|
||||
Method: code.Method{
|
||||
Name: "Insert",
|
||||
Returns: []code.Type{
|
||||
code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.UnsupportedReturnError,
|
||||
},
|
||||
{
|
||||
Name: "unempty interface return from insert method",
|
||||
Method: code.Method{
|
||||
Name: "Insert",
|
||||
Returns: []code.Type{
|
||||
code.InterfaceType{
|
||||
Methods: []code.Method{
|
||||
{Name: "DoSomething"},
|
||||
},
|
||||
},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.UnsupportedReturnError,
|
||||
},
|
||||
{
|
||||
Name: "error return not provided",
|
||||
Method: code.Method{
|
||||
Name: "Insert",
|
||||
Returns: []code.Type{
|
||||
code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||
code.InterfaceType{},
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.UnsupportedReturnError,
|
||||
},
|
||||
{
|
||||
Name: "no context parameter",
|
||||
Method: code.Method{
|
||||
Name: "Insert",
|
||||
Params: []code.Param{
|
||||
{Name: "userModel", Type: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.InterfaceType{},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.ContextParamRequiredError,
|
||||
},
|
||||
{
|
||||
Name: "mismatched model parameter for one mode",
|
||||
Method: code.Method{
|
||||
Name: "Insert",
|
||||
Params: []code.Param{
|
||||
{Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Name: "userModel", Type: code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.InterfaceType{},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.InvalidParamError,
|
||||
},
|
||||
{
|
||||
Name: "mismatched model parameter for many mode",
|
||||
Method: code.Method{
|
||||
Name: "Insert",
|
||||
Params: []code.Param{
|
||||
{Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}},
|
||||
{Name: "userModel", Type: code.PointerType{ContainedType: code.SimpleType("UserModel")}},
|
||||
},
|
||||
Returns: []code.Type{
|
||||
code.ArrayType{ContainedType: code.InterfaceType{}},
|
||||
code.SimpleType("error"),
|
||||
},
|
||||
},
|
||||
ExpectedError: spec.InvalidParamError,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testTable {
|
||||
t.Run(testCase.Name, func(t *testing.T) {
|
||||
_, err := spec.ParseInterfaceMethod(structModel, testCase.Method)
|
||||
|
||||
if err != testCase.ExpectedError {
|
||||
t.Errorf("\nExpected = %v\nReceived = %v", testCase.ExpectedError, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseInterfaceMethod_Find_Invalid(t *testing.T) {
|
||||
testTable := []ParseInterfaceMethodInvalidTestCase{
|
||||
{
|
||||
|
@ -758,7 +924,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) {
|
|||
ExpectedError: spec.UnsupportedReturnError,
|
||||
},
|
||||
{
|
||||
Name: "unsupported return values from find method",
|
||||
Name: "unsupported return types from find method",
|
||||
Method: code.Method{
|
||||
Name: "FindOneByID",
|
||||
Returns: []code.Type{
|
||||
|
@ -933,7 +1099,7 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) {
|
|||
ExpectedError: spec.UnsupportedReturnError,
|
||||
},
|
||||
{
|
||||
Name: "unsupported return values from find method",
|
||||
Name: "unsupported return types from update method",
|
||||
Method: code.Method{
|
||||
Name: "UpdateAgeByID",
|
||||
Returns: []code.Type{
|
||||
|
@ -1085,7 +1251,7 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) {
|
|||
ExpectedError: spec.UnsupportedReturnError,
|
||||
},
|
||||
{
|
||||
Name: "unsupported return values from find method",
|
||||
Name: "unsupported return types from delete method",
|
||||
Method: code.Method{
|
||||
Name: "DeleteOneByID",
|
||||
Returns: []code.Type{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue