11package query
22
33import (
4+ "database/sql"
45 "fmt"
56 "reflect"
67 "strings"
@@ -15,31 +16,27 @@ const (
1516)
1617
1718type Builder [T any , F any ] struct {
18- TableName string
19- ModelType reflect.Type
20- BuildParam func (int ) string
19+ TableName string
20+ ModelType reflect.Type
2121}
2222
23- func UseQuery [T any , F any ](tableName string , options ... func ( int ) string ) func (F ) (string , []interface {}) {
24- b := NewBuilder [T , F ](tableName , options ... )
23+ func UseQuery [T any , F any ](db * sql. DB , tableName string ) func (F ) (string , []interface {}) {
24+ b := NewBuilder [T , F ](db , tableName )
2525 return b .BuildQuery
2626}
27- func NewBuilder [T any , F any ](tableName string , options ... func (int ) string ) * Builder [T , F ] {
28- var build func (int ) string
29- if len (options ) > 0 {
30- build = options [0 ]
31- } else {
32- build = BuildParam
33- }
27+ func NewBuilder [T any , F any ](db * sql.DB , tableName string ) * Builder [T , F ] {
28+ return NewBuilderWithDriver [T , F ](tableName )
29+ }
30+ func NewBuilderWithDriver [T any , F any ](tableName string ) * Builder [T , F ] {
3431 var t T
3532 resultModelType := reflect .TypeOf (t )
3633 if resultModelType .Kind () == reflect .Ptr {
3734 resultModelType = resultModelType .Elem ()
3835 }
39- return & Builder [T , F ]{TableName : tableName , ModelType : resultModelType , BuildParam : build }
36+ return & Builder [T , F ]{TableName : tableName , ModelType : resultModelType }
4037}
4138func (b * Builder [T , F ]) BuildQuery (filter F ) (string , []interface {}) {
42- return Build (filter , b .TableName , b .ModelType , b . BuildParam )
39+ return Build (filter , b .TableName , b .ModelType )
4340}
4441
4542const (
@@ -69,12 +66,17 @@ func getJoinFromSqlBuilderTag(typeOfField reflect.StructField) *string {
6966
7067func getColumnNameFromSqlBuilderTag (typeOfField reflect.StructField ) * string {
7168 return getStringFromTag (typeOfField , "sql_builder" , "column:" )
72- }
73-
74- func Build (fm interface {}, tableName string , modelType reflect.Type , buildParam func (int ) string ) (string , []interface {}) {
75- if buildParam == nil {
76- buildParam = BuildParam
69+ /*tag := typeOfField.Tag
70+ properties := strings.Split(tag.Get("sql_builder"), ";")
71+ for _, property := range properties {
72+ if strings.HasPrefix(property, "column:") {
73+ column := property[7:]
74+ return &column
75+ }
7776 }
77+ return nil*/
78+ }
79+ func Build (filter interface {}, tableName string , modelType reflect.Type ) (string , []interface {}) {
7880 s1 := ""
7981 rawConditions := make ([]string , 0 )
8082 queryValues := make ([]interface {}, 0 )
@@ -85,93 +87,65 @@ func Build(fm interface{}, tableName string, modelType reflect.Type, buildParam
8587 fields := make ([]string , 0 )
8688 var excluding []string
8789 var keyword string
88- value := reflect .Indirect (reflect .ValueOf (fm ))
89- typeOfValue := value .Type ()
90+ value := reflect .Indirect (reflect .ValueOf (filter ))
91+ filterType := value .Type ()
9092 numField := value .NumField ()
9193 var idCol string
9294 marker := 0
93- fCount := 0
9495 for i := 0 ; i < numField ; i ++ {
96+ columnName := getColumn (filterType , i )
97+ if columnName == "-" {
98+ continue
99+ }
95100 field := value .Field (i )
96101 kind := field .Kind ()
97102 x := field .Interface ()
98- typeOfField := value .Type ().Field (i )
99- param := buildParam (marker + 1 )
100-
101- if v , ok := x .(* s.Filter ); ok {
102- if len (v .Fields ) > 0 {
103- for _ , key := range v .Fields {
104- i , _ , columnName := getFieldByJson (modelType , key )
105- if len (columnName ) < 0 {
106- fields = fields [len (fields ):]
107- break
108- } else if i > - 1 {
109- fields = append (fields , columnName )
110- }
111- }
112- }
113- if len (fields ) > 0 {
114- s1 = `select ` + strings .Join (fields , "," ) + ` from ` + tableName
115- }
116- if len (v .Sort ) > 0 {
117- sortString = buildSort (v .Sort , modelType )
118- }
119- }
120-
121- columnName , existCol := getColumnName (value .Type (), typeOfField .Name )
122- if ! existCol {
123- columnName , _ = getColumnName (modelType , typeOfField .Name )
124- }
125-
126- columnNameFromSqlBuilderTag := getColumnNameFromSqlBuilderTag (typeOfField )
127- if columnNameFromSqlBuilderTag != nil {
128- columnName = * columnNameFromSqlBuilderTag
129- }
130-
131- joinFromSqlBuilderTag := getJoinFromSqlBuilderTag (typeOfField )
132- if joinFromSqlBuilderTag != nil {
133- rawJoin = append (rawJoin , * joinFromSqlBuilderTag )
134- }
135- ps := false
136- var value2 string
137- tag := typeOfValue .Field (i ).Tag
103+ tf := value .Type ().Field (i )
104+ fieldTypeName := tf .Type .String ()
105+ typeOfField := value .Type ().Field (i ) // ???
106+ var psv string
138107 isContinue := false
139- isStrPointer := false
108+ param := buildParam ( marker + 1 )
140109 if kind == reflect .Ptr {
141110 if field .IsNil () {
142- isContinue = true
143- isStrPointer = true
144- } else {
145- s0 , ok0 := x .(* string )
146- if ok0 {
147- if s0 == nil || len (* s0 ) == 0 {
148- isContinue = true
149- isStrPointer = true
150- }
151- ps = true
152- value2 = * s0
111+ if fieldTypeName != "*string" {
112+ continue
113+ } else {
114+ isContinue = true
153115 }
116+ } else {
154117 field = field .Elem ()
155- x = field .Interface ()
156118 kind = field .Kind ()
119+ x = field .Interface ()
157120 }
158121 }
159- if ! isStrPointer {
122+ if ! isContinue {
160123 s0 , ok0 := x .(string )
161124 if ok0 {
162125 if len (s0 ) == 0 {
163126 isContinue = true
164127 }
165- value2 = s0
128+ psv = s0
166129 }
167130 }
131+ if len (columnName ) == 0 {
132+ _ , _ , columnName = getFieldByJson (modelType , tf .Name )
133+ }
134+ columnNameFromSqlBuilderTag := getColumnNameFromSqlBuilderTag (typeOfField )
135+ if columnNameFromSqlBuilderTag != nil {
136+ columnName = * columnNameFromSqlBuilderTag
137+ }
138+
139+ joinFromSqlBuilderTag := getJoinFromSqlBuilderTag (typeOfField )
140+ if joinFromSqlBuilderTag != nil {
141+ rawJoin = append (rawJoin , * joinFromSqlBuilderTag )
142+ }
168143 if isContinue {
169144 if len (keyword ) > 0 {
170- qMatch , isQ := tag .Lookup ("q" )
145+ qMatch , isQ := tf . Tag .Lookup ("q" )
171146 if isQ {
172147 if qMatch == "=" {
173148 qQueryValues = append (qQueryValues , keyword )
174-
175149 } else if qMatch == "like" {
176150 qQueryValues = append (qQueryValues , buildQ (keyword ))
177151 } else {
@@ -183,6 +157,23 @@ func Build(fm interface{}, tableName string, modelType reflect.Type, buildParam
183157 continue
184158 }
185159 if v , ok := x .(s.Filter ); ok {
160+ if len (v .Fields ) > 0 {
161+ for _ , key := range v .Fields {
162+ i , _ , columnName := getFieldByJson (modelType , key )
163+ if len (columnName ) < 0 {
164+ fields = fields [len (fields ):]
165+ break
166+ } else if i > - 1 {
167+ fields = append (fields , columnName )
168+ }
169+ }
170+ }
171+ if len (fields ) > 0 {
172+ s1 = `select ` + strings .Join (fields , "," ) + ` from ` + tableName
173+ }
174+ if len (v .Sort ) > 0 {
175+ sortString = buildSort (v .Sort , modelType )
176+ }
186177 if v .Excluding != nil && len (v .Excluding ) > 0 {
187178 index , _ , columnName := getFieldByBson (value .Type (), "_id" )
188179 if ! (index == - 1 || columnName == "" ) {
@@ -194,25 +185,22 @@ func Build(fm interface{}, tableName string, modelType reflect.Type, buildParam
194185 keyword = strings .TrimSpace (v .Q )
195186 }
196187 continue
197- } else if ps || kind == reflect .String {
198- if len (value2 ) > 0 {
199- key , ok := tag .Lookup ("operator" )
200- if ! ok {
201- key , _ = tag .Lookup ("q" )
202- }
203- if key == "=" {
204- rawConditions = append (rawConditions , fmt .Sprintf ("%s %s %s" , columnName , "=" , param ))
188+ } else if len (psv ) > 0 {
189+ key , ok := tf .Tag .Lookup ("operator" )
190+ if ! ok {
191+ key , _ = tf .Tag .Lookup ("q" )
192+ }
193+ if key == "=" {
194+ rawConditions = append (rawConditions , fmt .Sprintf ("%s %s %s" , columnName , "=" , param ))
195+ } else {
196+ rawConditions = append (rawConditions , fmt .Sprintf ("%s %s %s" , columnName , like , param ))
197+ if key == "like" {
198+ queryValues = append (queryValues , buildQ (psv ))
205199 } else {
206- rawConditions = append (rawConditions , fmt .Sprintf ("%s %s %s" , columnName , like , param ))
207- fCount = fCount + 1
208- if key == "like" {
209- queryValues = append (queryValues , buildQ (value2 ))
210- } else {
211- queryValues = append (queryValues , prefix (value2 ))
212- }
200+ queryValues = append (queryValues , prefix (psv ))
213201 }
214- marker ++
215202 }
203+ marker ++
216204 } else if dateTime , ok := x .(s.TimeRange ); ok {
217205 if dateTime .Min != nil {
218206 rawConditions = append (rawConditions , fmt .Sprintf ("%s %s %s" , columnName , greaterEqualThan , param ))
@@ -306,7 +294,7 @@ func Build(fm interface{}, tableName string, modelType reflect.Type, buildParam
306294 marker += field .Len ()
307295 }
308296 } else {
309- key , ok := tag .Lookup ("operator" )
297+ key , ok := tf . Tag .Lookup ("operator" )
310298 if ! ok {
311299 key = "="
312300 }
@@ -338,23 +326,18 @@ func Build(fm interface{}, tableName string, modelType reflect.Type, buildParam
338326 for i , s := range qCols {
339327 param := buildParam (marker + 1 )
340328 qConditions = append (qConditions , fmt .Sprintf ("%s %s %s" , s , like , param ))
341- fCount = fCount + 1
342329 queryValues = append (queryValues , qQueryValues [i ])
343330 marker ++
344331 }
345332 if len (qConditions ) > 0 {
346333 rawConditions = append (rawConditions , " (" + strings .Join (qConditions , " or " )+ ") " )
347334 }
348335 }
349- allowFiltering := ""
350- if fCount >= 1 {
351- allowFiltering = " allow filtering"
352- }
353336 if len (rawConditions ) > 0 {
354- s2 := s1 + ` where ` + strings .Join (rawConditions , " AND " ) + sortString + allowFiltering
337+ s2 := s1 + ` where ` + strings .Join (rawConditions , " and " ) + sortString
355338 return s2 , queryValues
356339 }
357- s3 := s1 + sortString + allowFiltering
340+ s3 := s1 + sortString
358341 return s3 , queryValues
359342}
360343func extractArray (values []interface {}, field interface {}) []interface {} {
@@ -389,6 +372,27 @@ func getFieldByJson(modelType reflect.Type, jsonName string) (int, string, strin
389372 }
390373 return - 1 , jsonName , jsonName
391374}
375+ func getColumn (filterType reflect.Type , i int ) string {
376+ field := filterType .Field (i )
377+ if tag2 , ok := field .Tag .Lookup ("gorm" ); ok {
378+ if tag2 == "-" {
379+ return tag2
380+ }
381+ if has := strings .Contains (tag2 , "column" ); has {
382+ str1 := strings .Split (tag2 , ";" )
383+ num := len (str1 )
384+ for k := 0 ; k < num ; k ++ {
385+ str2 := strings .Split (str1 [k ], ":" )
386+ for j := 0 ; j < len (str2 ); j ++ {
387+ if str2 [j ] == "column" {
388+ return str2 [j + 1 ]
389+ }
390+ }
391+ }
392+ }
393+ }
394+ return ""
395+ }
392396func getFieldByBson (modelType reflect.Type , bsonName string ) (int , string , string ) {
393397 numField := modelType .NumField ()
394398 for i := 0 ; i < numField ; i ++ {
@@ -503,7 +507,7 @@ func getSortType(sortType string) string {
503507 }
504508}
505509
506- func BuildParam (i int ) string {
510+ func buildParam (i int ) string {
507511 return "?"
508512}
509513func buildParametersFrom (i int , numCol int , buildParam func (i int ) string ) string {
0 commit comments