gdb_func.go 22 KB

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