gdb_func.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package gdb
  7. import (
  8. "bytes"
  9. "database/sql"
  10. "fmt"
  11. "github.com/gogf/gf/errors/gcode"
  12. "reflect"
  13. "regexp"
  14. "strings"
  15. "time"
  16. "github.com/gogf/gf/errors/gerror"
  17. "github.com/gogf/gf/internal/empty"
  18. "github.com/gogf/gf/internal/json"
  19. "github.com/gogf/gf/internal/utils"
  20. "github.com/gogf/gf/os/gtime"
  21. "github.com/gogf/gf/util/gmeta"
  22. "github.com/gogf/gf/util/gutil"
  23. "github.com/gogf/gf/internal/structs"
  24. "github.com/gogf/gf/text/gregex"
  25. "github.com/gogf/gf/text/gstr"
  26. "github.com/gogf/gf/util/gconv"
  27. )
  28. // apiString is the type assert api for String.
  29. type apiString interface {
  30. String() string
  31. }
  32. // apiIterator is the type assert api for Iterator.
  33. type apiIterator interface {
  34. Iterator(f func(key, value interface{}) bool)
  35. }
  36. // apiInterfaces is the type assert api for Interfaces.
  37. type apiInterfaces interface {
  38. Interfaces() []interface{}
  39. }
  40. // apiMapStrAny is the interface support for converting struct parameter to map.
  41. type apiMapStrAny interface {
  42. MapStrAny() map[string]interface{}
  43. }
  44. // apiTableName is the interface for retrieving table name fro struct.
  45. type apiTableName interface {
  46. TableName() string
  47. }
  48. const (
  49. OrmTagForStruct = "orm"
  50. OrmTagForUnique = "unique"
  51. OrmTagForPrimary = "primary"
  52. OrmTagForTable = "table"
  53. OrmTagForWith = "with"
  54. OrmTagForWithWhere = "where"
  55. OrmTagForWithOrder = "order"
  56. )
  57. var (
  58. // quoteWordReg is the regular expression object for a word check.
  59. quoteWordReg = regexp.MustCompile(`^[a-zA-Z0-9\-_]+$`)
  60. // Priority tags for struct converting for orm field mapping.
  61. structTagPriority = append([]string{OrmTagForStruct}, gconv.StructTagPriority...)
  62. )
  63. // guessPrimaryTableName parses and returns the primary table name.
  64. func (m *Model) guessPrimaryTableName(tableStr string) string {
  65. if tableStr == "" {
  66. return ""
  67. }
  68. var (
  69. guessedTableName = ""
  70. array1 = gstr.SplitAndTrim(tableStr, ",")
  71. array2 = gstr.SplitAndTrim(array1[0], " ")
  72. array3 = gstr.SplitAndTrim(array2[0], ".")
  73. )
  74. if len(array3) >= 2 {
  75. guessedTableName = array3[1]
  76. } else {
  77. guessedTableName = array3[0]
  78. }
  79. charL, charR := m.db.GetChars()
  80. if charL != "" || charR != "" {
  81. guessedTableName = gstr.Trim(guessedTableName, charL+charR)
  82. }
  83. if !gregex.IsMatchString(regularFieldNameRegPattern, guessedTableName) {
  84. return ""
  85. }
  86. return guessedTableName
  87. }
  88. // getTableNameFromOrmTag retrieves and returns the table name from struct object.
  89. func getTableNameFromOrmTag(object interface{}) string {
  90. var tableName string
  91. // Use the interface value.
  92. if r, ok := object.(apiTableName); ok {
  93. tableName = r.TableName()
  94. }
  95. // User meta data tag "orm".
  96. if tableName == "" {
  97. if ormTag := gmeta.Get(object, OrmTagForStruct); !ormTag.IsEmpty() {
  98. match, _ := gregex.MatchString(
  99. fmt.Sprintf(`%s\s*:\s*([^,]+)`, OrmTagForTable),
  100. ormTag.String(),
  101. )
  102. if len(match) > 1 {
  103. tableName = match[1]
  104. }
  105. }
  106. }
  107. // Use the struct name of snake case.
  108. if tableName == "" {
  109. if t, err := structs.StructType(object); err != nil {
  110. panic(err)
  111. } else {
  112. tableName = gstr.CaseSnakeFirstUpper(
  113. gstr.StrEx(t.String(), "."),
  114. )
  115. }
  116. }
  117. return tableName
  118. }
  119. // ListItemValues retrieves and returns the elements of all item struct/map with key `key`.
  120. // Note that the parameter `list` should be type of slice which contains elements of map or struct,
  121. // or else it returns an empty slice.
  122. //
  123. // The parameter `list` supports types like:
  124. // []map[string]interface{}
  125. // []map[string]sub-map
  126. // []struct
  127. // []struct:sub-struct
  128. // Note that the sub-map/sub-struct makes sense only if the optional parameter `subKey` is given.
  129. // See gutil.ListItemValues.
  130. func ListItemValues(list interface{}, key interface{}, subKey ...interface{}) (values []interface{}) {
  131. return gutil.ListItemValues(list, key, subKey...)
  132. }
  133. // ListItemValuesUnique retrieves and returns the unique elements of all struct/map with key `key`.
  134. // Note that the parameter `list` should be type of slice which contains elements of map or struct,
  135. // or else it returns an empty slice.
  136. // See gutil.ListItemValuesUnique.
  137. func ListItemValuesUnique(list interface{}, key string, subKey ...interface{}) []interface{} {
  138. return gutil.ListItemValuesUnique(list, key, subKey...)
  139. }
  140. // GetInsertOperationByOption returns proper insert option with given parameter `option`.
  141. func GetInsertOperationByOption(option int) string {
  142. var operator string
  143. switch option {
  144. case insertOptionReplace:
  145. operator = "REPLACE"
  146. case insertOptionIgnore:
  147. operator = "INSERT IGNORE"
  148. default:
  149. operator = "INSERT"
  150. }
  151. return operator
  152. }
  153. // ConvertDataForTableRecord is a very important function, which does converting for any data that
  154. // will be inserted into table as a record.
  155. //
  156. // The parameter `value` should be type of *map/map/*struct/struct.
  157. // It supports embedded struct definition for struct.
  158. func ConvertDataForTableRecord(value interface{}) map[string]interface{} {
  159. var (
  160. rvValue reflect.Value
  161. rvKind reflect.Kind
  162. data = DataToMapDeep(value)
  163. )
  164. for k, v := range data {
  165. rvValue = reflect.ValueOf(v)
  166. rvKind = rvValue.Kind()
  167. for rvKind == reflect.Ptr {
  168. rvValue = rvValue.Elem()
  169. rvKind = rvValue.Kind()
  170. }
  171. switch rvKind {
  172. case reflect.Slice, reflect.Array, reflect.Map:
  173. // It should ignore the bytes type.
  174. if _, ok := v.([]byte); !ok {
  175. // Convert the value to JSON.
  176. data[k], _ = json.Marshal(v)
  177. }
  178. case reflect.Struct:
  179. switch r := v.(type) {
  180. // If the time is zero, it then updates it to nil,
  181. // which will insert/update the value to database as "null".
  182. case time.Time:
  183. if r.IsZero() {
  184. data[k] = nil
  185. }
  186. case gtime.Time:
  187. if r.IsZero() {
  188. data[k] = nil
  189. }
  190. case *gtime.Time:
  191. if r.IsZero() {
  192. data[k] = nil
  193. }
  194. case *time.Time:
  195. continue
  196. case Counter, *Counter:
  197. continue
  198. default:
  199. // Use string conversion in default.
  200. if s, ok := v.(apiString); ok {
  201. data[k] = s.String()
  202. } else {
  203. // Convert the value to JSON.
  204. data[k], _ = json.Marshal(v)
  205. }
  206. }
  207. }
  208. }
  209. return data
  210. }
  211. // DataToMapDeep converts `value` to map type recursively(if attribute struct is embedded).
  212. // The parameter `value` should be type of *map/map/*struct/struct.
  213. // It supports embedded struct definition for struct.
  214. func DataToMapDeep(value interface{}) map[string]interface{} {
  215. m := gconv.Map(value, structTagPriority...)
  216. for k, v := range m {
  217. switch v.(type) {
  218. case time.Time, *time.Time, gtime.Time, *gtime.Time:
  219. m[k] = v
  220. default:
  221. // Use string conversion in default.
  222. if s, ok := v.(apiString); ok {
  223. m[k] = s.String()
  224. } else {
  225. m[k] = v
  226. }
  227. }
  228. }
  229. return m
  230. }
  231. // doHandleTableName adds prefix string and quote chars for the table. It handles table string like:
  232. // "user", "user u", "user,user_detail", "user u, user_detail ut", "user as u, user_detail as ut",
  233. // "user.user u", "`user`.`user` u".
  234. //
  235. // Note that, this will automatically checks the table prefix whether already added, if true it does
  236. // nothing to the table name, or else adds the prefix to the table name.
  237. func doHandleTableName(table, prefix, charLeft, charRight string) string {
  238. var (
  239. index = 0
  240. chars = charLeft + charRight
  241. array1 = gstr.SplitAndTrim(table, ",")
  242. )
  243. for k1, v1 := range array1 {
  244. array2 := gstr.SplitAndTrim(v1, " ")
  245. // Trim the security chars.
  246. array2[0] = gstr.Trim(array2[0], chars)
  247. // Check whether it has database name.
  248. array3 := gstr.Split(gstr.Trim(array2[0]), ".")
  249. for k, v := range array3 {
  250. array3[k] = gstr.Trim(v, chars)
  251. }
  252. index = len(array3) - 1
  253. // If the table name already has the prefix, skips the prefix adding.
  254. if len(array3[index]) <= len(prefix) || array3[index][:len(prefix)] != prefix {
  255. array3[index] = prefix + array3[index]
  256. }
  257. array2[0] = gstr.Join(array3, ".")
  258. // Add the security chars.
  259. array2[0] = doQuoteString(array2[0], charLeft, charRight)
  260. array1[k1] = gstr.Join(array2, " ")
  261. }
  262. return gstr.Join(array1, ",")
  263. }
  264. // doQuoteWord checks given string `s` a word, if true quotes it with `charLeft` and `charRight`
  265. // and returns the quoted string; or else returns `s` without any change.
  266. func doQuoteWord(s, charLeft, charRight string) string {
  267. if quoteWordReg.MatchString(s) && !gstr.ContainsAny(s, charLeft+charRight) {
  268. return charLeft + s + charRight
  269. }
  270. return s
  271. }
  272. // doQuoteString quotes string with quote chars.
  273. // For example, if quote char is '`':
  274. // "user" => "`user`"
  275. // "user u" => "`user` u"
  276. // "user,user_detail" => "`user`,`user_detail`"
  277. // "user u, user_detail ut" => "`user` u,`user_detail` ut"
  278. // "user.user u, user.user_detail ut" => "`user`.`user` u,`user`.`user_detail` ut"
  279. // "u.id, u.name, u.age" => "`u`.`id`,`u`.`name`,`u`.`age`"
  280. // "u.id asc" => "`u`.`id` asc"
  281. func doQuoteString(s, charLeft, charRight string) string {
  282. array1 := gstr.SplitAndTrim(s, ",")
  283. for k1, v1 := range array1 {
  284. array2 := gstr.SplitAndTrim(v1, " ")
  285. array3 := gstr.Split(gstr.Trim(array2[0]), ".")
  286. if len(array3) == 1 {
  287. array3[0] = doQuoteWord(array3[0], charLeft, charRight)
  288. } else if len(array3) >= 2 {
  289. array3[0] = doQuoteWord(array3[0], charLeft, charRight)
  290. // Note:
  291. // mysql: u.uid
  292. // mssql double dots: Database..Table
  293. array3[len(array3)-1] = doQuoteWord(array3[len(array3)-1], charLeft, charRight)
  294. }
  295. array2[0] = gstr.Join(array3, ".")
  296. array1[k1] = gstr.Join(array2, " ")
  297. }
  298. return gstr.Join(array1, ",")
  299. }
  300. // GetWhereConditionOfStruct returns the where condition sql and arguments by given struct pointer.
  301. // This function automatically retrieves primary or unique field and its attribute value as condition.
  302. func GetWhereConditionOfStruct(pointer interface{}) (where string, args []interface{}, err error) {
  303. tagField, err := structs.TagFields(pointer, []string{OrmTagForStruct})
  304. if err != nil {
  305. return "", nil, err
  306. }
  307. array := ([]string)(nil)
  308. for _, field := range tagField {
  309. array = strings.Split(field.TagValue, ",")
  310. if len(array) > 1 && gstr.InArray([]string{OrmTagForUnique, OrmTagForPrimary}, array[1]) {
  311. return array[0], []interface{}{field.Value.Interface()}, nil
  312. }
  313. if len(where) > 0 {
  314. where += " AND "
  315. }
  316. where += field.TagValue + "=?"
  317. args = append(args, field.Value.Interface())
  318. }
  319. return
  320. }
  321. // GetPrimaryKey retrieves and returns primary key field name from given struct.
  322. func GetPrimaryKey(pointer interface{}) (string, error) {
  323. tagField, err := structs.TagFields(pointer, []string{OrmTagForStruct})
  324. if err != nil {
  325. return "", err
  326. }
  327. array := ([]string)(nil)
  328. for _, field := range tagField {
  329. array = strings.Split(field.TagValue, ",")
  330. if len(array) > 1 && array[1] == OrmTagForPrimary {
  331. return array[0], nil
  332. }
  333. }
  334. return "", nil
  335. }
  336. // GetPrimaryKeyCondition returns a new where condition by primary field name.
  337. // The optional parameter `where` is like follows:
  338. // 123 => primary=123
  339. // []int{1, 2, 3} => primary IN(1,2,3)
  340. // "john" => primary='john'
  341. // []string{"john", "smith"} => primary IN('john','smith')
  342. // g.Map{"id": g.Slice{1,2,3}} => id IN(1,2,3)
  343. // g.Map{"id": 1, "name": "john"} => id=1 AND name='john'
  344. // etc.
  345. //
  346. // Note that it returns the given `where` parameter directly if the `primary` is empty
  347. // or length of `where` > 1.
  348. func GetPrimaryKeyCondition(primary string, where ...interface{}) (newWhereCondition []interface{}) {
  349. if len(where) == 0 {
  350. return nil
  351. }
  352. if primary == "" {
  353. return where
  354. }
  355. if len(where) == 1 {
  356. var (
  357. rv = reflect.ValueOf(where[0])
  358. kind = rv.Kind()
  359. )
  360. if kind == reflect.Ptr {
  361. rv = rv.Elem()
  362. kind = rv.Kind()
  363. }
  364. switch kind {
  365. case reflect.Map, reflect.Struct:
  366. // Ignore the parameter `primary`.
  367. break
  368. default:
  369. return []interface{}{map[string]interface{}{
  370. primary: where[0],
  371. }}
  372. }
  373. }
  374. return where
  375. }
  376. // formatSql formats the sql string and its arguments before executing.
  377. // The internal handleArguments function might be called twice during the SQL procedure,
  378. // but do not worry about it, it's safe and efficient.
  379. func formatSql(sql string, args []interface{}) (newSql string, newArgs []interface{}) {
  380. // DO NOT do this as there may be multiple lines and comments in the sql.
  381. // sql = gstr.Trim(sql)
  382. // sql = gstr.Replace(sql, "\n", " ")
  383. // sql, _ = gregex.ReplaceString(`\s{2,}`, ` `, sql)
  384. return handleArguments(sql, args)
  385. }
  386. type formatWhereInput struct {
  387. Where interface{}
  388. Args []interface{}
  389. OmitNil bool
  390. OmitEmpty bool
  391. Schema string
  392. Table string
  393. }
  394. // formatWhere formats where statement and its arguments for `Where` and `Having` statements.
  395. func formatWhere(db DB, in formatWhereInput) (newWhere string, newArgs []interface{}) {
  396. var (
  397. buffer = bytes.NewBuffer(nil)
  398. reflectValue = reflect.ValueOf(in.Where)
  399. reflectKind = reflectValue.Kind()
  400. )
  401. for reflectKind == reflect.Ptr {
  402. reflectValue = reflectValue.Elem()
  403. reflectKind = reflectValue.Kind()
  404. }
  405. switch reflectKind {
  406. case reflect.Array, reflect.Slice:
  407. newArgs = formatWhereInterfaces(db, gconv.Interfaces(in.Where), buffer, newArgs)
  408. case reflect.Map:
  409. for key, value := range DataToMapDeep(in.Where) {
  410. if gregex.IsMatchString(regularFieldNameRegPattern, key) {
  411. if in.OmitNil && empty.IsNil(value) {
  412. continue
  413. }
  414. if in.OmitEmpty && empty.IsEmpty(value) {
  415. continue
  416. }
  417. }
  418. newArgs = formatWhereKeyValue(db, buffer, newArgs, key, value)
  419. }
  420. case reflect.Struct:
  421. // If `where` struct implements apiIterator interface,
  422. // it then uses its Iterate function to iterate its key-value pairs.
  423. // For example, ListMap and TreeMap are ordered map,
  424. // which implement apiIterator interface and are index-friendly for where conditions.
  425. if iterator, ok := in.Where.(apiIterator); ok {
  426. iterator.Iterator(func(key, value interface{}) bool {
  427. ketStr := gconv.String(key)
  428. if gregex.IsMatchString(regularFieldNameRegPattern, ketStr) {
  429. if in.OmitNil && empty.IsNil(value) {
  430. return true
  431. }
  432. if in.OmitEmpty && empty.IsEmpty(value) {
  433. return true
  434. }
  435. }
  436. newArgs = formatWhereKeyValue(db, buffer, newArgs, ketStr, value)
  437. return true
  438. })
  439. break
  440. }
  441. // Automatically mapping and filtering the struct attribute.
  442. var (
  443. reflectType = reflectValue.Type()
  444. structField reflect.StructField
  445. )
  446. data := DataToMapDeep(in.Where)
  447. if in.Table != "" {
  448. data, _ = db.GetCore().mappingAndFilterData(in.Schema, in.Table, data, true)
  449. }
  450. // Put the struct attributes in sequence in Where statement.
  451. for i := 0; i < reflectType.NumField(); i++ {
  452. structField = reflectType.Field(i)
  453. foundKey, foundValue := gutil.MapPossibleItemByKey(data, structField.Name)
  454. if foundKey != "" {
  455. if in.OmitNil && empty.IsNil(foundValue) {
  456. continue
  457. }
  458. if in.OmitEmpty && empty.IsEmpty(foundValue) {
  459. continue
  460. }
  461. newArgs = formatWhereKeyValue(db, buffer, newArgs, foundKey, foundValue)
  462. }
  463. }
  464. default:
  465. // Usually a string.
  466. var (
  467. i = 0
  468. whereStr = gconv.String(in.Where)
  469. )
  470. for {
  471. if i >= len(in.Args) {
  472. break
  473. }
  474. // Sub query, which is always used along with a string condition.
  475. if model, ok := in.Args[i].(*Model); ok {
  476. var (
  477. index = -1
  478. )
  479. whereStr, _ = gregex.ReplaceStringFunc(`(\?)`, whereStr, func(s string) string {
  480. index++
  481. if i+len(newArgs) == index {
  482. sqlWithHolder, holderArgs := model.getFormattedSqlAndArgs(queryTypeNormal, false)
  483. newArgs = append(newArgs, holderArgs...)
  484. // Automatically adding the brackets.
  485. return "(" + sqlWithHolder + ")"
  486. }
  487. return s
  488. })
  489. in.Args = gutil.SliceDelete(in.Args, i)
  490. continue
  491. }
  492. i++
  493. }
  494. buffer.WriteString(whereStr)
  495. }
  496. if buffer.Len() == 0 {
  497. return "", in.Args
  498. }
  499. newArgs = append(newArgs, in.Args...)
  500. newWhere = buffer.String()
  501. if len(newArgs) > 0 {
  502. if gstr.Pos(newWhere, "?") == -1 {
  503. if gregex.IsMatchString(lastOperatorRegPattern, newWhere) {
  504. // Eg: Where/And/Or("uid>=", 1)
  505. newWhere += "?"
  506. } else if gregex.IsMatchString(regularFieldNameRegPattern, newWhere) {
  507. newWhere = db.GetCore().QuoteString(newWhere)
  508. if len(newArgs) > 0 {
  509. if utils.IsArray(newArgs[0]) {
  510. // Eg:
  511. // Where("id", []int{1,2,3})
  512. // Where("user.id", []int{1,2,3})
  513. newWhere += " IN (?)"
  514. } else if empty.IsNil(newArgs[0]) {
  515. // Eg:
  516. // Where("id", nil)
  517. // Where("user.id", nil)
  518. newWhere += " IS NULL"
  519. newArgs = nil
  520. } else {
  521. // Eg:
  522. // Where/And/Or("uid", 1)
  523. // Where/And/Or("user.uid", 1)
  524. newWhere += "=?"
  525. }
  526. }
  527. }
  528. }
  529. }
  530. return handleArguments(newWhere, newArgs)
  531. }
  532. // formatWhereInterfaces formats `where` as []interface{}.
  533. func formatWhereInterfaces(db DB, where []interface{}, buffer *bytes.Buffer, newArgs []interface{}) []interface{} {
  534. if len(where) == 0 {
  535. return newArgs
  536. }
  537. if len(where)%2 != 0 {
  538. buffer.WriteString(gstr.Join(gconv.Strings(where), ""))
  539. return newArgs
  540. }
  541. var str string
  542. for i := 0; i < len(where); i += 2 {
  543. str = gconv.String(where[i])
  544. if buffer.Len() > 0 {
  545. buffer.WriteString(" AND " + db.GetCore().QuoteWord(str) + "=?")
  546. } else {
  547. buffer.WriteString(db.GetCore().QuoteWord(str) + "=?")
  548. }
  549. if s, ok := where[i+1].(Raw); ok {
  550. buffer.WriteString(gconv.String(s))
  551. } else {
  552. newArgs = append(newArgs, where[i+1])
  553. }
  554. }
  555. return newArgs
  556. }
  557. // formatWhereKeyValue handles each key-value pair of the parameter map.
  558. func formatWhereKeyValue(db DB, buffer *bytes.Buffer, newArgs []interface{}, key string, value interface{}) []interface{} {
  559. quotedKey := db.GetCore().QuoteWord(key)
  560. if buffer.Len() > 0 {
  561. buffer.WriteString(" AND ")
  562. }
  563. // If the value is type of slice, and there's only one '?' holder in
  564. // the key string, it automatically adds '?' holder chars according to its arguments count
  565. // and converts it to "IN" statement.
  566. var (
  567. rv = reflect.ValueOf(value)
  568. kind = rv.Kind()
  569. )
  570. switch kind {
  571. case reflect.Slice, reflect.Array:
  572. count := gstr.Count(quotedKey, "?")
  573. if count == 0 {
  574. buffer.WriteString(quotedKey + " IN(?)")
  575. newArgs = append(newArgs, value)
  576. } else if count != rv.Len() {
  577. buffer.WriteString(quotedKey)
  578. newArgs = append(newArgs, value)
  579. } else {
  580. buffer.WriteString(quotedKey)
  581. newArgs = append(newArgs, gconv.Interfaces(value)...)
  582. }
  583. default:
  584. if value == nil || empty.IsNil(rv) {
  585. if gregex.IsMatchString(regularFieldNameRegPattern, key) {
  586. // The key is a single field name.
  587. buffer.WriteString(quotedKey + " IS NULL")
  588. } else {
  589. // The key may have operation chars.
  590. buffer.WriteString(quotedKey)
  591. }
  592. } else {
  593. // It also supports "LIKE" statement, which we considers it an operator.
  594. quotedKey = gstr.Trim(quotedKey)
  595. if gstr.Pos(quotedKey, "?") == -1 {
  596. like := " like"
  597. if len(quotedKey) > len(like) && gstr.Equal(quotedKey[len(quotedKey)-len(like):], like) {
  598. // Eg: Where(g.Map{"name like": "john%"})
  599. buffer.WriteString(quotedKey + " ?")
  600. } else if gregex.IsMatchString(lastOperatorRegPattern, quotedKey) {
  601. // Eg: Where(g.Map{"age > ": 16})
  602. buffer.WriteString(quotedKey + " ?")
  603. } else if gregex.IsMatchString(regularFieldNameRegPattern, key) {
  604. // The key is a regular field name.
  605. buffer.WriteString(quotedKey + "=?")
  606. } else {
  607. // The key is not a regular field name.
  608. // Eg: Where(g.Map{"age > 16": nil})
  609. // Issue: https://github.com/gogf/gf/issues/765
  610. if empty.IsEmpty(value) {
  611. buffer.WriteString(quotedKey)
  612. break
  613. } else {
  614. buffer.WriteString(quotedKey + "=?")
  615. }
  616. }
  617. } else {
  618. buffer.WriteString(quotedKey)
  619. }
  620. if s, ok := value.(Raw); ok {
  621. buffer.WriteString(gconv.String(s))
  622. } else {
  623. newArgs = append(newArgs, value)
  624. }
  625. }
  626. }
  627. return newArgs
  628. }
  629. // handleArguments is an important function, which handles the sql and all its arguments
  630. // before committing them to underlying driver.
  631. func handleArguments(sql string, args []interface{}) (newSql string, newArgs []interface{}) {
  632. newSql = sql
  633. // insertHolderCount is used to calculate the inserting position for the '?' holder.
  634. insertHolderCount := 0
  635. // Handles the slice arguments.
  636. if len(args) > 0 {
  637. for index, arg := range args {
  638. var (
  639. reflectValue = reflect.ValueOf(arg)
  640. reflectKind = reflectValue.Kind()
  641. )
  642. for reflectKind == reflect.Ptr {
  643. reflectValue = reflectValue.Elem()
  644. reflectKind = reflectValue.Kind()
  645. }
  646. switch reflectKind {
  647. case reflect.Slice, reflect.Array:
  648. // It does not split the type of []byte.
  649. // Eg: table.Where("name = ?", []byte("john"))
  650. if _, ok := arg.([]byte); ok {
  651. newArgs = append(newArgs, arg)
  652. continue
  653. }
  654. if reflectValue.Len() == 0 {
  655. // Empty slice argument, it converts the sql to a false sql.
  656. // Eg:
  657. // Query("select * from xxx where id in(?)", g.Slice{}) -> select * from xxx where 0=1
  658. // Where("id in(?)", g.Slice{}) -> WHERE 0=1
  659. if gstr.Contains(newSql, "?") {
  660. whereKeyWord := " WHERE "
  661. if p := gstr.PosI(newSql, whereKeyWord); p == -1 {
  662. return "0=1", []interface{}{}
  663. } else {
  664. return gstr.SubStr(newSql, 0, p+len(whereKeyWord)) + "0=1", []interface{}{}
  665. }
  666. }
  667. } else {
  668. for i := 0; i < reflectValue.Len(); i++ {
  669. newArgs = append(newArgs, reflectValue.Index(i).Interface())
  670. }
  671. }
  672. // If the '?' holder count equals the length of the slice,
  673. // it does not implement the arguments splitting logic.
  674. // Eg: db.Query("SELECT ?+?", g.Slice{1, 2})
  675. if len(args) == 1 && gstr.Count(newSql, "?") == reflectValue.Len() {
  676. break
  677. }
  678. // counter is used to finding the inserting position for the '?' holder.
  679. var (
  680. counter = 0
  681. replaced = false
  682. )
  683. newSql, _ = gregex.ReplaceStringFunc(`\?`, newSql, func(s string) string {
  684. if replaced {
  685. return s
  686. }
  687. counter++
  688. if counter == index+insertHolderCount+1 {
  689. replaced = true
  690. insertHolderCount += reflectValue.Len() - 1
  691. return "?" + strings.Repeat(",?", reflectValue.Len()-1)
  692. }
  693. return s
  694. })
  695. // Special struct handling.
  696. case reflect.Struct:
  697. switch v := arg.(type) {
  698. // The underlying driver supports time.Time/*time.Time types.
  699. case time.Time, *time.Time:
  700. newArgs = append(newArgs, arg)
  701. continue
  702. // Special handling for gtime.Time/*gtime.Time.
  703. //
  704. // DO NOT use its underlying gtime.Time.Time as its argument,
  705. // because the std time.Time will be converted to certain timezone
  706. // according to underlying driver. And the underlying driver also
  707. // converts the time.Time to string automatically as the following does.
  708. case gtime.Time:
  709. newArgs = append(newArgs, v.String())
  710. continue
  711. case *gtime.Time:
  712. newArgs = append(newArgs, v.String())
  713. continue
  714. default:
  715. // It converts the struct to string in default
  716. // if it has implemented the String interface.
  717. if v, ok := arg.(apiString); ok {
  718. newArgs = append(newArgs, v.String())
  719. continue
  720. }
  721. }
  722. newArgs = append(newArgs, arg)
  723. default:
  724. newArgs = append(newArgs, arg)
  725. }
  726. }
  727. }
  728. return
  729. }
  730. // formatError customizes and returns the SQL error.
  731. func formatError(err error, s string, args ...interface{}) error {
  732. if err != nil && err != sql.ErrNoRows {
  733. return gerror.NewCodef(gcode.CodeDbOperationError, "%s, %s\n", err.Error(), FormatSqlWithArgs(s, args))
  734. }
  735. return err
  736. }
  737. // FormatSqlWithArgs binds the arguments to the sql string and returns a complete
  738. // sql string, just for debugging.
  739. func FormatSqlWithArgs(sql string, args []interface{}) string {
  740. index := -1
  741. newQuery, _ := gregex.ReplaceStringFunc(
  742. `(\?|:v\d+|\$\d+|@p\d+)`,
  743. sql,
  744. func(s string) string {
  745. index++
  746. if len(args) > index {
  747. if args[index] == nil {
  748. return "null"
  749. }
  750. var (
  751. rv = reflect.ValueOf(args[index])
  752. kind = rv.Kind()
  753. )
  754. if kind == reflect.Ptr {
  755. if rv.IsNil() || !rv.IsValid() {
  756. return "null"
  757. }
  758. rv = rv.Elem()
  759. kind = rv.Kind()
  760. }
  761. switch kind {
  762. case reflect.String, reflect.Map, reflect.Slice, reflect.Array:
  763. return `'` + gstr.QuoteMeta(gconv.String(args[index]), `'`) + `'`
  764. case reflect.Struct:
  765. if t, ok := args[index].(time.Time); ok {
  766. return `'` + t.Format(`2006-01-02 15:04:05`) + `'`
  767. }
  768. return `'` + gstr.QuoteMeta(gconv.String(args[index]), `'`) + `'`
  769. }
  770. return gconv.String(args[index])
  771. }
  772. return s
  773. })
  774. return newQuery
  775. }