diff --git a/README.md b/README.md index 05430d2..0762c52 100644 --- a/README.md +++ b/README.md @@ -463,16 +463,16 @@ if err != nil { In the example above, since we are only interested in a couple of columns it is far simpler and more efficient for the database to only select the columns -that we actually care about, so it's better not to use composite structs. +that we actually care about, so it's better not to use composite kstructs. ### Testing Examples This library has a few helper functions for helping your tests: -- `structs.FillStructWith(struct interface{}, dbRow map[string]interface{}) error` -- `structs.FillSliceWith(structSlice interface{}, dbRows []map[string]interface{}) error` -- `structs.StructToMap(struct interface{}) (map[string]interface{}, error)` -- `structs.CallFunctionWithRows(fn interface{}, rows []map[string]interface{}) (map[string]interface{}, error)` +- `kstructs.FillStructWith(struct interface{}, dbRow map[string]interface{}) error` +- `kstructs.FillSliceWith(structSlice interface{}, dbRows []map[string]interface{}) error` +- `kstructs.StructToMap(struct interface{}) (map[string]interface{}, error)` +- `kstructs.CallFunctionWithRows(fn interface{}, rows []map[string]interface{}) (map[string]interface{}, error)` If you want to see examples (we have examples for all the public functions) just read the example tests available on our [example service](./examples/example_service) @@ -524,7 +524,7 @@ make test - Improve error messages - Add tests for tables using composite keys - Add support for serializing structs as other formats such as YAML -- Update `structs.FillStructWith` to work with `json` tagged attributes +- Update `kstructs.FillStructWith` to work with `json` tagged attributes - Make testing easier by exposing the connection strings in an .env file - Make testing easier by automatically creating the `ksql` database - Create a way for users to submit user defined dialects diff --git a/examples/example_service/example_service_test.go b/examples/example_service/example_service_test.go index 983ee88..007f1c0 100644 --- a/examples/example_service/example_service_test.go +++ b/examples/example_service/example_service_test.go @@ -8,7 +8,7 @@ import ( "github.com/tj/assert" "github.com/vingarcia/ksql" "github.com/vingarcia/ksql/nullable" - "github.com/vingarcia/ksql/structs" + "github.com/vingarcia/ksql/kstructs" ) func TestCreateUser(t *testing.T) { @@ -58,7 +58,7 @@ func TestCreateUser(t *testing.T) { // // If you are inserting an anonymous struct (not usual) this function // can make your tests shorter: - uMap, err := structs.StructToMap(record) + uMap, err := kstructs.StructToMap(record) if err != nil { return err } @@ -95,7 +95,7 @@ func TestUpdateUserScore(t *testing.T) { DoAndReturn(func(ctx context.Context, result interface{}, query string, params ...interface{}) error { // This function will use reflection to fill the // struct fields with the values from the map - return structs.FillStructWith(result, map[string]interface{}{ + return kstructs.FillStructWith(result, map[string]interface{}{ // Use int this map the keys you set on the ksql tags, e.g. `ksql:"score"` // Each of these fields represent the database rows returned // by the query. @@ -138,7 +138,7 @@ func TestListUsers(t *testing.T) { DoAndReturn(func(ctx context.Context, result interface{}, query string, params ...interface{}) error { // This function will use reflection to fill the // struct fields with the values from the map - return structs.FillStructWith(result, map[string]interface{}{ + return kstructs.FillStructWith(result, map[string]interface{}{ // Use int this map the keys you set on the ksql tags, e.g. `ksql:"score"` // Each of these fields represent the database rows returned // by the query. @@ -147,7 +147,7 @@ func TestListUsers(t *testing.T) { }), mockDB.EXPECT().Query(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). DoAndReturn(func(ctx context.Context, results interface{}, query string, params ...interface{}) error { - return structs.FillSliceWith(results, []map[string]interface{}{ + return kstructs.FillSliceWith(results, []map[string]interface{}{ { "id": 1, "name": "fake name", @@ -198,7 +198,7 @@ func TestStreamAllUsers(t *testing.T) { mockDB.EXPECT().QueryChunks(gomock.Any(), gomock.Any()). DoAndReturn(func(ctx context.Context, parser ksql.ChunkParser) error { // Chunk 1: - err := structs.CallFunctionWithRows(parser.ForEachChunk, []map[string]interface{}{ + err := kstructs.CallFunctionWithRows(parser.ForEachChunk, []map[string]interface{}{ { "id": 1, "name": "fake name", @@ -215,7 +215,7 @@ func TestStreamAllUsers(t *testing.T) { } // Chunk 2: - err = structs.CallFunctionWithRows(parser.ForEachChunk, []map[string]interface{}{ + err = kstructs.CallFunctionWithRows(parser.ForEachChunk, []map[string]interface{}{ { "id": 3, "name": "yet another fake name", diff --git a/ksql.go b/ksql.go index 0665449..1f9195f 100644 --- a/ksql.go +++ b/ksql.go @@ -9,7 +9,7 @@ import ( "unicode" "github.com/pkg/errors" - "github.com/vingarcia/ksql/structs" + "github.com/vingarcia/ksql/kstructs" ) var selectQueryCache = map[string]map[reflect.Type]string{} @@ -93,7 +93,7 @@ func (c DB) Query( } sliceType := slicePtrType.Elem() slice := slicePtr.Elem() - structType, isSliceOfPtrs, err := structs.DecodeAsSliceOfStructs(sliceType) + structType, isSliceOfPtrs, err := kstructs.DecodeAsSliceOfStructs(sliceType) if err != nil { return err } @@ -105,7 +105,7 @@ func (c DB) Query( slice = slice.Slice(0, 0) } - info := structs.GetTagInfo(structType) + info := kstructs.GetTagInfo(structType) firstToken := strings.ToUpper(getFirstToken(query)) if info.IsNestedStruct && firstToken == "SELECT" { @@ -186,7 +186,7 @@ func (c DB) QueryOne( return fmt.Errorf("ksql: expected to receive a pointer to struct, but got: %T", record) } - info := structs.GetTagInfo(t) + info := kstructs.GetTagInfo(t) firstToken := strings.ToUpper(getFirstToken(query)) if info.IsNestedStruct && firstToken == "SELECT" { @@ -244,19 +244,19 @@ func (c DB) QueryChunks( parser ChunkParser, ) error { fnValue := reflect.ValueOf(parser.ForEachChunk) - chunkType, err := structs.ParseInputFunc(parser.ForEachChunk) + chunkType, err := kstructs.ParseInputFunc(parser.ForEachChunk) if err != nil { return err } chunk := reflect.MakeSlice(chunkType, 0, parser.ChunkSize) - structType, isSliceOfPtrs, err := structs.DecodeAsSliceOfStructs(chunkType) + structType, isSliceOfPtrs, err := kstructs.DecodeAsSliceOfStructs(chunkType) if err != nil { return err } - info := structs.GetTagInfo(structType) + info := kstructs.GetTagInfo(structType) firstToken := strings.ToUpper(getFirstToken(parser.Query)) if info.IsNestedStruct && firstToken == "SELECT" { @@ -416,7 +416,7 @@ func (c DB) insertWithLastInsertID( return errors.Wrap(err, "can't write to `"+idName+"` field") } - info := structs.GetTagInfo(t.Elem()) + info := kstructs.GetTagInfo(t.Elem()) id, err := result.LastInsertId() if err != nil { @@ -499,7 +499,7 @@ func normalizeIDsAsMaps(idNames []string, ids []interface{}) ([]map[string]inter t := reflect.TypeOf(ids[i]) switch t.Kind() { case reflect.Struct: - m, err := structs.StructToMap(ids[i]) + m, err := kstructs.StructToMap(ids[i]) if err != nil { return nil, errors.Wrapf(err, "could not get ID(s) from record on idx %d", i) } @@ -561,9 +561,9 @@ func buildInsertQuery( ) } - info := structs.GetTagInfo(t.Elem()) + info := kstructs.GetTagInfo(t.Elem()) - recordMap, err := structs.StructToMap(record) + recordMap, err := kstructs.StructToMap(record) if err != nil { return "", nil, nil, err } @@ -651,7 +651,7 @@ func buildUpdateQuery( record interface{}, idFieldNames ...string, ) (query string, args []interface{}, err error) { - recordMap, err := structs.StructToMap(record) + recordMap, err := kstructs.StructToMap(record) if err != nil { return "", nil, err } @@ -681,7 +681,7 @@ func buildUpdateQuery( if t.Kind() == reflect.Ptr { t = t.Elem() } - info := structs.GetTagInfo(t) + info := kstructs.GetTagInfo(t) var setQuery []string for i, k := range keys { @@ -781,13 +781,13 @@ func scanRows(dialect dialect, rows *sql.Rows, record interface{}) error { return fmt.Errorf("ksql: expected record to be a pointer to struct, but got: %T", record) } - info := structs.GetTagInfo(t) + info := kstructs.GetTagInfo(t) var scanArgs []interface{} if info.IsNestedStruct { // This version is positional meaning that it expect the arguments // to follow an specific order. It's ok because we don't allow the - // user to type the "SELECT" part of the query for nested structs. + // user to type the "SELECT" part of the query for nested kstructs. scanArgs = getScanArgsForNestedStructs(dialect, rows, t, v, info) } else { names, err := rows.Columns() @@ -802,11 +802,11 @@ func scanRows(dialect dialect, rows *sql.Rows, record interface{}) error { return rows.Scan(scanArgs...) } -func getScanArgsForNestedStructs(dialect dialect, rows *sql.Rows, t reflect.Type, v reflect.Value, info structs.StructInfo) []interface{} { +func getScanArgsForNestedStructs(dialect dialect, rows *sql.Rows, t reflect.Type, v reflect.Value, info kstructs.StructInfo) []interface{} { scanArgs := []interface{}{} for i := 0; i < v.NumField(); i++ { // TODO(vingarcia00): Handle case where type is pointer - nestedStructInfo := structs.GetTagInfo(t.Field(i).Type) + nestedStructInfo := kstructs.GetTagInfo(t.Field(i).Type) nestedStructValue := v.Field(i) for j := 0; j < nestedStructValue.NumField(); j++ { fieldInfo := nestedStructInfo.ByIndex(j) @@ -829,7 +829,7 @@ func getScanArgsForNestedStructs(dialect dialect, rows *sql.Rows, t reflect.Type return scanArgs } -func getScanArgsFromNames(dialect dialect, names []string, v reflect.Value, info structs.StructInfo) []interface{} { +func getScanArgsFromNames(dialect dialect, names []string, v reflect.Value, info kstructs.StructInfo) []interface{} { scanArgs := []interface{}{} for _, name := range names { fieldInfo := info.ByName(name) @@ -919,7 +919,7 @@ func getFirstToken(s string) string { func buildSelectQuery( dialect dialect, structType reflect.Type, - info structs.StructInfo, + info kstructs.StructInfo, selectQueryCache map[reflect.Type]string, ) (query string, err error) { if selectQuery, found := selectQueryCache[structType]; found { @@ -942,7 +942,7 @@ func buildSelectQuery( func buildSelectQueryForPlainStructs( dialect dialect, structType reflect.Type, - info structs.StructInfo, + info kstructs.StructInfo, ) string { var fields []string for i := 0; i < structType.NumField(); i++ { @@ -955,7 +955,7 @@ func buildSelectQueryForPlainStructs( func buildSelectQueryForNestedStructs( dialect dialect, structType reflect.Type, - info structs.StructInfo, + info kstructs.StructInfo, ) (string, error) { var fields []string for i := 0; i < structType.NumField(); i++ { @@ -968,7 +968,7 @@ func buildSelectQueryForNestedStructs( ) } - nestedStructInfo := structs.GetTagInfo(nestedStructType) + nestedStructInfo := kstructs.GetTagInfo(nestedStructType) for j := 0; j < structType.Field(i).Type.NumField(); j++ { fields = append( fields, diff --git a/structs/func_parser.go b/kstructs/func_parser.go similarity index 98% rename from structs/func_parser.go rename to kstructs/func_parser.go index d68db69..56550f2 100644 --- a/structs/func_parser.go +++ b/kstructs/func_parser.go @@ -1,4 +1,4 @@ -package structs +package kstructs import ( "fmt" diff --git a/structs/structs.go b/kstructs/structs.go similarity index 99% rename from structs/structs.go rename to kstructs/structs.go index a77b3a0..0232862 100644 --- a/structs/structs.go +++ b/kstructs/structs.go @@ -1,4 +1,4 @@ -package structs +package kstructs import ( "fmt" diff --git a/structs/structs_test.go b/kstructs/structs_test.go similarity index 99% rename from structs/structs_test.go rename to kstructs/structs_test.go index c11c3c1..3887be2 100644 --- a/structs/structs_test.go +++ b/kstructs/structs_test.go @@ -1,4 +1,4 @@ -package structs +package kstructs import ( "testing" diff --git a/structs/testhelpers.go b/kstructs/testhelpers.go similarity index 99% rename from structs/testhelpers.go rename to kstructs/testhelpers.go index c02c40d..caa7bb7 100644 --- a/structs/testhelpers.go +++ b/kstructs/testhelpers.go @@ -1,4 +1,4 @@ -package structs +package kstructs import ( "fmt"