Skip to content

Commit 4782374

Browse files
authored
feat(patch): defaulting to snake case naming of the resource object provided if no table name option has been provided (#131)
* defaulting to snake case naming of the resource object provided if no table name option has been provided * parallel tests * reording linter flow
1 parent c9e5f97 commit 4782374

File tree

5 files changed

+336
-8
lines changed

5 files changed

+336
-8
lines changed

.github/workflows/ci-code-approval.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ jobs:
2929
name: Golangci-lint
3030
runs-on: ubuntu-latest
3131
steps:
32+
- name: Checkout repository
33+
uses: actions/checkout@v4
34+
3235
# Sets up golang
3336
- uses: actions/setup-go@v5
3437
with:
35-
go-version: ${{ vars.GO_VERSION }}
38+
go-version-file: 'go.mod'
3639
cache-dependency-path: "**/*.sum"
3740

38-
- name: Checkout repository
39-
uses: actions/checkout@v4
40-
4141
- name: golangci-lint
4242
uses: golangci/golangci-lint-action@v6
4343
with:
@@ -54,7 +54,7 @@ jobs:
5454
- name: Set up Go
5555
uses: actions/setup-go@v5
5656
with:
57-
go-version: ${{ vars.GO_VERSION }}
57+
go-version-file: 'go.mod'
5858
cache-dependency-path: "**/*.sum"
5959

6060
- name: Make
@@ -83,7 +83,7 @@ jobs:
8383
- name: Set up Go
8484
uses: actions/setup-go@v5
8585
with:
86-
go-version: ${{ vars.GO_VERSION }}
86+
go-version-file: 'go.mod'
8787
cache-dependency-path: "**/*.sum"
8888

8989
- name: "Run Code Generation"

sql.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ func NewSQLPatch(resource any, opts ...PatchOpt) *SQLPatch {
3131
// It processes the fields of the struct, applying the necessary tags and options,
3232
// and prepares the SQL update statement components (fields and arguments).
3333
func (s *SQLPatch) patchGen(resource any) {
34+
if s.table == "" {
35+
s.table = getTableName(resource)
36+
}
37+
3438
resource = dereferenceIfPointer(resource)
3539
ensureStruct(resource)
3640

sql_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,24 @@ func (s *newSQLPatchSuite) TestNewSQLPatch_Success() {
3535
s.Equal([]any{1, "test"}, patch.args)
3636
}
3737

38+
func (s *newSQLPatchSuite) TestNewSQLPatch_Success_NoTableProvided() {
39+
type testObj struct {
40+
Id *int `db:"id_tag"`
41+
Name *string `db:"name_tag"`
42+
}
43+
44+
obj := testObj{
45+
Id: ptr(1),
46+
Name: ptr("test"),
47+
}
48+
49+
patch := NewSQLPatch(obj)
50+
51+
s.Equal([]string{"id_tag = ?", "name_tag = ?"}, patch.fields)
52+
s.Equal([]any{1, "test"}, patch.args)
53+
s.Equal("test_obj", patch.table)
54+
}
55+
3856
func (s *newSQLPatchSuite) TestNewSQLPatch_Success_Filter_Where() {
3957
type testObj struct {
4058
Id *int `db:"id_tag"`
@@ -759,6 +777,30 @@ func (s *generateSQLSuite) TestGenerateSQL_Success() {
759777
mw.AssertExpectations(s.T())
760778
}
761779

780+
func (s *generateSQLSuite) TestGenerateSQL_Success_NoTableProvided() {
781+
type testTable struct {
782+
Id *int `db:"id"`
783+
Name *string `db:"name"`
784+
}
785+
786+
obj := testTable{
787+
Id: ptr(1),
788+
Name: ptr("test"),
789+
}
790+
791+
mw := NewMockWherer(s.T())
792+
mw.On("Where").Return("age = ?", []any{18})
793+
794+
sqlStr, args, err := GenerateSQL(obj,
795+
WithWhere(mw),
796+
)
797+
s.Require().NoError(err)
798+
s.Equal("UPDATE test_table\nSET id = ?, name = ?\nWHERE (1=1)\nAND (\nage = ?\n)", sqlStr)
799+
s.Equal([]any{1, "test", 18}, args)
800+
801+
mw.AssertExpectations(s.T())
802+
}
803+
762804
type testFilter struct{}
763805

764806
func (f *testFilter) Where() (sqlStr string, args []any) {
@@ -1612,6 +1654,35 @@ func (s *NewDiffSQLPatchSuite) TestNewDiffSQLPatch_Success_SqlGen() {
16121654
s.Equal([]any{"test2", 18}, args)
16131655
}
16141656

1657+
func (s *NewDiffSQLPatchSuite) TestNewDiffSQLPatch_Success_SqlGen_NoTableProvided() {
1658+
type testTable struct {
1659+
Id *int `db:"id"`
1660+
Name *string `db:"name"`
1661+
}
1662+
1663+
obj := testTable{
1664+
Id: ptr(1),
1665+
Name: ptr("test"),
1666+
}
1667+
1668+
obj2 := testTable{
1669+
Id: ptr(1),
1670+
Name: ptr("test2"),
1671+
}
1672+
1673+
mw := NewMockWherer(s.T())
1674+
mw.On("Where").Return("age = ?", []any{18})
1675+
1676+
patch, err := NewDiffSQLPatch(&obj, &obj2, WithWhere(mw))
1677+
s.Require().NoError(err)
1678+
1679+
sqlStr, args, err := patch.GenerateSQL()
1680+
s.Require().NoError(err)
1681+
1682+
s.Equal("UPDATE test_table\nSET name = ?\nWHERE (1=1)\nAND (\nage = ?\n)", sqlStr)
1683+
s.Equal([]any{"test2", 18}, args)
1684+
}
1685+
16151686
func (s *NewDiffSQLPatchSuite) TestNewDiffSQLPatch_Success_SqlGen_ValueField() {
16161687
type testObj struct {
16171688
Id *int `db:"id"`

utils.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func isPointerToStruct[T any](t T) bool {
2020
}
2121

2222
func dereferenceIfPointer(resource any) any {
23-
if reflect.TypeOf(resource).Kind() == reflect.Ptr {
23+
if reflect.TypeOf(resource).Kind() == reflect.Ptr && !reflect.ValueOf(resource).IsNil() {
2424
return reflect.ValueOf(resource).Elem().Interface()
2525
}
2626
return resource
@@ -47,7 +47,9 @@ func getTag(fType *reflect.StructField, tagName string) string {
4747
}
4848

4949
func getValue(fVal reflect.Value) any {
50-
if fVal.Kind() == reflect.Ptr {
50+
if fVal.Kind() == reflect.Ptr && fVal.IsNil() {
51+
return nil
52+
} else if fVal.Kind() == reflect.Ptr {
5153
return fVal.Elem().Interface()
5254
}
5355
return fVal.Interface()
@@ -64,3 +66,22 @@ func IsValidType(val reflect.Value) bool {
6466
return false
6567
}
6668
}
69+
70+
func getTableName(resource any) string {
71+
typeOf := reflect.TypeOf(resource)
72+
if typeOf.Kind() == reflect.Ptr {
73+
typeOf = typeOf.Elem()
74+
}
75+
return toSnakeCase(typeOf.Name())
76+
}
77+
78+
func toSnakeCase(s string) string {
79+
result := make([]rune, 0, len(s)*2)
80+
for i, r := range s {
81+
if i > 0 && 'A' <= r && r <= 'Z' {
82+
result = append(result, '_')
83+
}
84+
result = append(result, r)
85+
}
86+
return strings.ToLower(string(result))
87+
}

0 commit comments

Comments
 (0)