session_insert.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. // Copyright 2016 The Xorm Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package xorm
  5. import (
  6. "errors"
  7. "fmt"
  8. "reflect"
  9. "sort"
  10. "strconv"
  11. "strings"
  12. "github.com/xormplus/builder"
  13. "github.com/xormplus/core"
  14. )
  15. // Insert insert one or more beans
  16. func (session *Session) Insert(beans ...interface{}) (int64, error) {
  17. var affected int64
  18. var err error
  19. if session.isAutoClose {
  20. defer session.Close()
  21. }
  22. for _, bean := range beans {
  23. switch bean.(type) {
  24. case map[string]interface{}:
  25. cnt, err := session.insertMapInterface(bean.(map[string]interface{}))
  26. if err != nil {
  27. return affected, err
  28. }
  29. affected += cnt
  30. case []map[string]interface{}:
  31. s := bean.([]map[string]interface{})
  32. session.autoResetStatement = false
  33. for i := 0; i < len(s); i++ {
  34. cnt, err := session.insertMapInterface(s[i])
  35. if err != nil {
  36. return affected, err
  37. }
  38. affected += cnt
  39. }
  40. case map[string]string:
  41. cnt, err := session.insertMapString(bean.(map[string]string))
  42. if err != nil {
  43. return affected, err
  44. }
  45. affected += cnt
  46. case []map[string]string:
  47. s := bean.([]map[string]string)
  48. session.autoResetStatement = false
  49. for i := 0; i < len(s); i++ {
  50. cnt, err := session.insertMapString(s[i])
  51. if err != nil {
  52. return affected, err
  53. }
  54. affected += cnt
  55. }
  56. default:
  57. sliceValue := reflect.Indirect(reflect.ValueOf(bean))
  58. if sliceValue.Kind() == reflect.Slice {
  59. size := sliceValue.Len()
  60. if size > 0 {
  61. if session.engine.SupportInsertMany() {
  62. cnt, err := session.innerInsertMulti(bean)
  63. if err != nil {
  64. return affected, err
  65. }
  66. affected += cnt
  67. } else {
  68. for i := 0; i < size; i++ {
  69. cnt, err := session.innerInsert(sliceValue.Index(i).Interface())
  70. if err != nil {
  71. return affected, err
  72. }
  73. affected += cnt
  74. }
  75. }
  76. }
  77. } else {
  78. cnt, err := session.innerInsert(bean)
  79. if err != nil {
  80. return affected, err
  81. }
  82. affected += cnt
  83. }
  84. }
  85. }
  86. return affected, err
  87. }
  88. func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error) {
  89. sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
  90. if sliceValue.Kind() != reflect.Slice {
  91. return 0, errors.New("needs a pointer to a slice")
  92. }
  93. if sliceValue.Len() <= 0 {
  94. return 0, errors.New("could not insert a empty slice")
  95. }
  96. if err := session.statement.setRefBean(sliceValue.Index(0).Interface()); err != nil {
  97. return 0, err
  98. }
  99. tableName := session.statement.TableName()
  100. if len(tableName) <= 0 {
  101. return 0, ErrTableNotFound
  102. }
  103. table := session.statement.RefTable
  104. size := sliceValue.Len()
  105. var colNames []string
  106. var colMultiPlaces []string
  107. var args []interface{}
  108. var cols []*core.Column
  109. for i := 0; i < size; i++ {
  110. v := sliceValue.Index(i)
  111. vv := reflect.Indirect(v)
  112. elemValue := v.Interface()
  113. var colPlaces []string
  114. // handle BeforeInsertProcessor
  115. // !nashtsai! does user expect it's same slice to passed closure when using Before()/After() when insert multi??
  116. for _, closure := range session.beforeClosures {
  117. closure(elemValue)
  118. }
  119. if processor, ok := interface{}(elemValue).(BeforeInsertProcessor); ok {
  120. processor.BeforeInsert()
  121. }
  122. // --
  123. if i == 0 {
  124. for _, col := range table.Columns() {
  125. ptrFieldValue, err := col.ValueOfV(&vv)
  126. if err != nil {
  127. return 0, err
  128. }
  129. fieldValue := *ptrFieldValue
  130. if col.IsAutoIncrement && isZero(fieldValue.Interface()) {
  131. continue
  132. }
  133. if col.MapType == core.ONLYFROMDB {
  134. continue
  135. }
  136. if col.IsDeleted {
  137. continue
  138. }
  139. if session.statement.omitColumnMap.contain(col.Name) {
  140. continue
  141. }
  142. if len(session.statement.columnMap) > 0 && !session.statement.columnMap.contain(col.Name) {
  143. continue
  144. }
  145. if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime {
  146. val, t := session.engine.nowTime(col)
  147. args = append(args, val)
  148. var colName = col.Name
  149. session.afterClosures = append(session.afterClosures, func(bean interface{}) {
  150. col := table.GetColumn(colName)
  151. setColumnTime(bean, col, t)
  152. })
  153. } else if col.IsVersion && session.statement.checkVersion {
  154. args = append(args, 1)
  155. var colName = col.Name
  156. session.afterClosures = append(session.afterClosures, func(bean interface{}) {
  157. col := table.GetColumn(colName)
  158. setColumnInt(bean, col, 1)
  159. })
  160. } else {
  161. arg, err := session.value2Interface(col, fieldValue)
  162. if err != nil {
  163. return 0, err
  164. }
  165. args = append(args, arg)
  166. }
  167. colNames = append(colNames, col.Name)
  168. cols = append(cols, col)
  169. colPlaces = append(colPlaces, "?")
  170. }
  171. } else {
  172. for _, col := range cols {
  173. ptrFieldValue, err := col.ValueOfV(&vv)
  174. if err != nil {
  175. return 0, err
  176. }
  177. fieldValue := *ptrFieldValue
  178. if col.IsAutoIncrement && isZero(fieldValue.Interface()) {
  179. continue
  180. }
  181. if col.MapType == core.ONLYFROMDB {
  182. continue
  183. }
  184. if col.IsDeleted {
  185. continue
  186. }
  187. if session.statement.omitColumnMap.contain(col.Name) {
  188. continue
  189. }
  190. if len(session.statement.columnMap) > 0 && !session.statement.columnMap.contain(col.Name) {
  191. continue
  192. }
  193. if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime {
  194. val, t := session.engine.nowTime(col)
  195. args = append(args, val)
  196. var colName = col.Name
  197. session.afterClosures = append(session.afterClosures, func(bean interface{}) {
  198. col := table.GetColumn(colName)
  199. setColumnTime(bean, col, t)
  200. })
  201. } else if col.IsVersion && session.statement.checkVersion {
  202. args = append(args, 1)
  203. var colName = col.Name
  204. session.afterClosures = append(session.afterClosures, func(bean interface{}) {
  205. col := table.GetColumn(colName)
  206. setColumnInt(bean, col, 1)
  207. })
  208. } else {
  209. arg, err := session.value2Interface(col, fieldValue)
  210. if err != nil {
  211. return 0, err
  212. }
  213. args = append(args, arg)
  214. }
  215. colPlaces = append(colPlaces, "?")
  216. }
  217. }
  218. colMultiPlaces = append(colMultiPlaces, strings.Join(colPlaces, ", "))
  219. }
  220. cleanupProcessorsClosures(&session.beforeClosures)
  221. var sql string
  222. if session.engine.dialect.DBType() == core.ORACLE {
  223. temp := fmt.Sprintf(") INTO %s (%v) VALUES (",
  224. session.engine.Quote(tableName),
  225. quoteColumns(colNames, session.engine.Quote, ","))
  226. sql = fmt.Sprintf("INSERT ALL INTO %s (%v) VALUES (%v) SELECT 1 FROM DUAL",
  227. session.engine.Quote(tableName),
  228. quoteColumns(colNames, session.engine.Quote, ","),
  229. strings.Join(colMultiPlaces, temp))
  230. } else {
  231. sql = fmt.Sprintf("INSERT INTO %s (%v) VALUES (%v)",
  232. session.engine.Quote(tableName),
  233. quoteColumns(colNames, session.engine.Quote, ","),
  234. strings.Join(colMultiPlaces, "),("))
  235. }
  236. res, err := session.exec(sql, args...)
  237. if err != nil {
  238. session.engine.logger.Errorf("[SQL][%p] %v", session, err)
  239. return 0, err
  240. }
  241. session.cacheInsert(tableName)
  242. lenAfterClosures := len(session.afterClosures)
  243. for i := 0; i < size; i++ {
  244. elemValue := reflect.Indirect(sliceValue.Index(i)).Addr().Interface()
  245. // handle AfterInsertProcessor
  246. if session.isAutoCommit {
  247. // !nashtsai! does user expect it's same slice to passed closure when using Before()/After() when insert multi??
  248. for _, closure := range session.afterClosures {
  249. closure(elemValue)
  250. }
  251. if processor, ok := interface{}(elemValue).(AfterInsertProcessor); ok {
  252. processor.AfterInsert()
  253. }
  254. } else {
  255. if lenAfterClosures > 0 {
  256. if value, has := session.afterInsertBeans[elemValue]; has && value != nil {
  257. *value = append(*value, session.afterClosures...)
  258. } else {
  259. afterClosures := make([]func(interface{}), lenAfterClosures)
  260. copy(afterClosures, session.afterClosures)
  261. session.afterInsertBeans[elemValue] = &afterClosures
  262. }
  263. } else {
  264. if _, ok := interface{}(elemValue).(AfterInsertProcessor); ok {
  265. session.afterInsertBeans[elemValue] = nil
  266. }
  267. }
  268. }
  269. }
  270. cleanupProcessorsClosures(&session.afterClosures)
  271. return res.RowsAffected()
  272. }
  273. // InsertMulti insert multiple records
  274. func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
  275. if session.isAutoClose {
  276. defer session.Close()
  277. }
  278. sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
  279. if sliceValue.Kind() != reflect.Slice {
  280. return 0, ErrParamsType
  281. }
  282. if sliceValue.Len() <= 0 {
  283. return 0, nil
  284. }
  285. return session.innerInsertMulti(rowsSlicePtr)
  286. }
  287. func (session *Session) innerInsert(bean interface{}) (int64, error) {
  288. if err := session.statement.setRefBean(bean); err != nil {
  289. return 0, err
  290. }
  291. if len(session.statement.TableName()) <= 0 {
  292. return 0, ErrTableNotFound
  293. }
  294. table := session.statement.RefTable
  295. // handle BeforeInsertProcessor
  296. for _, closure := range session.beforeClosures {
  297. closure(bean)
  298. }
  299. cleanupProcessorsClosures(&session.beforeClosures) // cleanup after used
  300. if processor, ok := interface{}(bean).(BeforeInsertProcessor); ok {
  301. processor.BeforeInsert()
  302. }
  303. colNames, args, err := session.genInsertColumns(bean)
  304. if err != nil {
  305. return 0, err
  306. }
  307. // insert expr columns, override if exists
  308. exprColumns := session.statement.getExpr()
  309. exprColVals := make([]string, 0, len(exprColumns))
  310. for _, v := range exprColumns {
  311. // remove the expr columns
  312. for i, colName := range colNames {
  313. if colName == strings.Trim(v.colName, "`") {
  314. colNames = append(colNames[:i], colNames[i+1:]...)
  315. args = append(args[:i], args[i+1:]...)
  316. }
  317. }
  318. // append expr column to the end
  319. colNames = append(colNames, v.colName)
  320. exprColVals = append(exprColVals, v.expr)
  321. }
  322. colPlaces := strings.Repeat("?, ", len(colNames)-len(exprColumns))
  323. if len(exprColVals) > 0 {
  324. colPlaces = colPlaces + strings.Join(exprColVals, ", ")
  325. } else {
  326. if len(colPlaces) > 0 {
  327. colPlaces = colPlaces[0 : len(colPlaces)-2]
  328. }
  329. }
  330. var sqlStr string
  331. var tableName = session.statement.TableName()
  332. var output string
  333. if session.engine.dialect.DBType() == core.MSSQL && len(table.AutoIncrement) > 0 {
  334. output = fmt.Sprintf(" OUTPUT Inserted.%s", table.AutoIncrement)
  335. }
  336. if len(colPlaces) > 0 {
  337. if session.statement.cond.IsValid() {
  338. condSQL, condArgs, err := builder.ToSQL(session.statement.cond)
  339. if err != nil {
  340. return 0, err
  341. }
  342. sqlStr = fmt.Sprintf("INSERT INTO %s (%v)%s SELECT %v FROM %v WHERE %v",
  343. session.engine.Quote(tableName),
  344. quoteColumns(colNames, session.engine.Quote, ","),
  345. output,
  346. colPlaces,
  347. session.engine.Quote(tableName),
  348. condSQL,
  349. )
  350. args = append(args, condArgs...)
  351. } else {
  352. sqlStr = fmt.Sprintf("INSERT INTO %s (%v)%s VALUES (%v)",
  353. session.engine.Quote(tableName),
  354. quoteColumns(colNames, session.engine.Quote, ","),
  355. output,
  356. colPlaces)
  357. }
  358. } else {
  359. if session.engine.dialect.DBType() == core.MYSQL {
  360. sqlStr = fmt.Sprintf("INSERT INTO %s VALUES ()", session.engine.Quote(tableName))
  361. } else {
  362. sqlStr = fmt.Sprintf("INSERT INTO %s%s DEFAULT VALUES", session.engine.Quote(tableName), output)
  363. }
  364. }
  365. if len(table.AutoIncrement) > 0 && session.engine.dialect.DBType() == core.POSTGRES {
  366. sqlStr = sqlStr + " RETURNING " + session.engine.Quote(table.AutoIncrement)
  367. }
  368. handleAfterInsertProcessorFunc := func(bean interface{}) {
  369. if session.isAutoCommit {
  370. for _, closure := range session.afterClosures {
  371. closure(bean)
  372. }
  373. if processor, ok := interface{}(bean).(AfterInsertProcessor); ok {
  374. processor.AfterInsert()
  375. }
  376. } else {
  377. lenAfterClosures := len(session.afterClosures)
  378. if lenAfterClosures > 0 {
  379. if value, has := session.afterInsertBeans[bean]; has && value != nil {
  380. *value = append(*value, session.afterClosures...)
  381. } else {
  382. afterClosures := make([]func(interface{}), lenAfterClosures)
  383. copy(afterClosures, session.afterClosures)
  384. session.afterInsertBeans[bean] = &afterClosures
  385. }
  386. } else {
  387. if _, ok := interface{}(bean).(AfterInsertProcessor); ok {
  388. session.afterInsertBeans[bean] = nil
  389. }
  390. }
  391. }
  392. cleanupProcessorsClosures(&session.afterClosures) // cleanup after used
  393. }
  394. // for postgres, many of them didn't implement lastInsertId, so we should
  395. // implemented it ourself.
  396. if session.engine.dialect.DBType() == core.ORACLE && len(table.AutoIncrement) > 0 {
  397. res, err := session.queryBytes("select seq_atable.currval from dual", args...)
  398. if err != nil {
  399. return 0, err
  400. }
  401. defer handleAfterInsertProcessorFunc(bean)
  402. session.cacheInsert(tableName)
  403. if table.Version != "" && session.statement.checkVersion {
  404. verValue, err := table.VersionColumn().ValueOf(bean)
  405. if err != nil {
  406. session.engine.logger.Errorf("[SQL][%p] %v", session, err)
  407. } else if verValue.IsValid() && verValue.CanSet() {
  408. session.incrVersionFieldValue(verValue)
  409. }
  410. }
  411. if len(res) < 1 {
  412. return 0, errors.New("insert no error but not returned id")
  413. }
  414. idByte := res[0][table.AutoIncrement]
  415. id, err := strconv.ParseInt(string(idByte), 10, 64)
  416. if err != nil || id <= 0 {
  417. return 1, err
  418. }
  419. aiValue, err := table.AutoIncrColumn().ValueOf(bean)
  420. if err != nil {
  421. session.engine.logger.Errorf("[SQL][%p] %v", session, err)
  422. }
  423. if aiValue == nil || !aiValue.IsValid() || !aiValue.CanSet() {
  424. return 1, nil
  425. }
  426. aiValue.Set(int64ToIntValue(id, aiValue.Type()))
  427. return 1, nil
  428. } else if len(table.AutoIncrement) > 0 && (session.engine.dialect.DBType() == core.POSTGRES || session.engine.dialect.DBType() == core.MSSQL) {
  429. res, err := session.queryBytes(sqlStr, args...)
  430. if err != nil {
  431. return 0, err
  432. }
  433. defer handleAfterInsertProcessorFunc(bean)
  434. session.cacheInsert(tableName)
  435. if table.Version != "" && session.statement.checkVersion {
  436. verValue, err := table.VersionColumn().ValueOf(bean)
  437. if err != nil {
  438. session.engine.logger.Errorf("[SQL][%p] %v", session, err)
  439. } else if verValue.IsValid() && verValue.CanSet() {
  440. session.incrVersionFieldValue(verValue)
  441. }
  442. }
  443. if len(res) < 1 {
  444. return 0, errors.New("insert successfully but not returned id")
  445. }
  446. idByte := res[0][table.AutoIncrement]
  447. id, err := strconv.ParseInt(string(idByte), 10, 64)
  448. if err != nil || id <= 0 {
  449. return 1, err
  450. }
  451. aiValue, err := table.AutoIncrColumn().ValueOf(bean)
  452. if err != nil {
  453. session.engine.logger.Errorf("[SQL][%p] %v", session, err)
  454. }
  455. if aiValue == nil || !aiValue.IsValid() || !aiValue.CanSet() {
  456. return 1, nil
  457. }
  458. aiValue.Set(int64ToIntValue(id, aiValue.Type()))
  459. return 1, nil
  460. } else {
  461. res, err := session.exec(sqlStr, args...)
  462. if err != nil {
  463. session.engine.logger.Errorf("[SQL][%p] %v", session, err)
  464. return 0, err
  465. }
  466. defer handleAfterInsertProcessorFunc(bean)
  467. session.cacheInsert(tableName)
  468. if table.Version != "" && session.statement.checkVersion {
  469. verValue, err := table.VersionColumn().ValueOf(bean)
  470. if err != nil {
  471. session.engine.logger.Errorf("[SQL][%p] %v", session, err)
  472. } else if verValue.IsValid() && verValue.CanSet() {
  473. session.incrVersionFieldValue(verValue)
  474. }
  475. }
  476. if table.AutoIncrement == "" {
  477. return res.RowsAffected()
  478. }
  479. var id int64
  480. id, err = res.LastInsertId()
  481. if err != nil || id <= 0 {
  482. return res.RowsAffected()
  483. }
  484. aiValue, err := table.AutoIncrColumn().ValueOf(bean)
  485. if err != nil {
  486. session.engine.logger.Errorf("[SQL][%p] %v", session, err)
  487. }
  488. if aiValue == nil || !aiValue.IsValid() || !aiValue.CanSet() {
  489. return res.RowsAffected()
  490. }
  491. aiValue.Set(int64ToIntValue(id, aiValue.Type()))
  492. return res.RowsAffected()
  493. }
  494. }
  495. // InsertOne insert only one struct into database as a record.
  496. // The in parameter bean must a struct or a point to struct. The return
  497. // parameter is inserted and error
  498. func (session *Session) InsertOne(bean interface{}) (int64, error) {
  499. if session.isAutoClose {
  500. defer session.Close()
  501. }
  502. return session.innerInsert(bean)
  503. }
  504. func (session *Session) cacheInsert(table string) error {
  505. if !session.statement.UseCache {
  506. return nil
  507. }
  508. cacher := session.engine.getCacher(table)
  509. if cacher == nil {
  510. return nil
  511. }
  512. session.engine.logger.Debug("[cache] clear sql:", table)
  513. cacher.ClearIds(table)
  514. return nil
  515. }
  516. // genInsertColumns generates insert needed columns
  517. func (session *Session) genInsertColumns(bean interface{}) ([]string, []interface{}, error) {
  518. table := session.statement.RefTable
  519. colNames := make([]string, 0, len(table.ColumnsSeq()))
  520. args := make([]interface{}, 0, len(table.ColumnsSeq()))
  521. for _, col := range table.Columns() {
  522. if col.MapType == core.ONLYFROMDB {
  523. continue
  524. }
  525. if col.IsDeleted {
  526. continue
  527. }
  528. if session.statement.omitColumnMap.contain(col.Name) {
  529. continue
  530. }
  531. if len(session.statement.columnMap) > 0 && !session.statement.columnMap.contain(col.Name) {
  532. continue
  533. }
  534. if _, ok := session.statement.incrColumns[col.Name]; ok {
  535. continue
  536. } else if _, ok := session.statement.decrColumns[col.Name]; ok {
  537. continue
  538. }
  539. fieldValuePtr, err := col.ValueOf(bean)
  540. if err != nil {
  541. return nil, nil, err
  542. }
  543. fieldValue := *fieldValuePtr
  544. if col.IsAutoIncrement {
  545. switch fieldValue.Type().Kind() {
  546. case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64:
  547. if fieldValue.Int() == 0 {
  548. continue
  549. }
  550. case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64:
  551. if fieldValue.Uint() == 0 {
  552. continue
  553. }
  554. case reflect.String:
  555. if len(fieldValue.String()) == 0 {
  556. continue
  557. }
  558. case reflect.Ptr:
  559. if fieldValue.Pointer() == 0 {
  560. continue
  561. }
  562. }
  563. }
  564. // !evalphobia! set fieldValue as nil when column is nullable and zero-value
  565. if _, ok := getFlagForColumn(session.statement.nullableMap, col); ok {
  566. if col.Nullable && isZero(fieldValue.Interface()) {
  567. var nilValue *int
  568. fieldValue = reflect.ValueOf(nilValue)
  569. }
  570. }
  571. if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime /*&& isZero(fieldValue.Interface())*/ {
  572. // if time is non-empty, then set to auto time
  573. val, t := session.engine.nowTime(col)
  574. args = append(args, val)
  575. var colName = col.Name
  576. session.afterClosures = append(session.afterClosures, func(bean interface{}) {
  577. col := table.GetColumn(colName)
  578. setColumnTime(bean, col, t)
  579. })
  580. } else if col.IsVersion && session.statement.checkVersion {
  581. args = append(args, 1)
  582. } else {
  583. arg, err := session.value2Interface(col, fieldValue)
  584. if err != nil {
  585. return colNames, args, err
  586. }
  587. args = append(args, arg)
  588. }
  589. colNames = append(colNames, col.Name)
  590. }
  591. return colNames, args, nil
  592. }
  593. func (session *Session) insertMapInterface(m map[string]interface{}) (int64, error) {
  594. if len(m) == 0 {
  595. return 0, ErrParamsType
  596. }
  597. tableName := session.statement.TableName()
  598. if len(tableName) <= 0 {
  599. return 0, ErrTableNotFound
  600. }
  601. var columns = make([]string, 0, len(m))
  602. for k := range m {
  603. columns = append(columns, k)
  604. }
  605. sort.Strings(columns)
  606. qm := strings.Repeat("?,", len(columns))
  607. var args = make([]interface{}, 0, len(m))
  608. for _, colName := range columns {
  609. args = append(args, m[colName])
  610. }
  611. // insert expr columns, override if exists
  612. exprColumns := session.statement.getExpr()
  613. for _, col := range exprColumns {
  614. columns = append(columns, strings.Trim(col.colName, "`"))
  615. qm = qm + col.expr + ","
  616. }
  617. qm = qm[:len(qm)-1]
  618. var sql string
  619. if session.statement.cond.IsValid() {
  620. condSQL, condArgs, err := builder.ToSQL(session.statement.cond)
  621. if err != nil {
  622. return 0, err
  623. }
  624. sql = fmt.Sprintf("INSERT INTO %s (`%s`) SELECT %s FROM %s WHERE %s",
  625. session.engine.Quote(tableName),
  626. strings.Join(columns, "`,`"),
  627. qm,
  628. session.engine.Quote(tableName),
  629. condSQL,
  630. )
  631. args = append(args, condArgs...)
  632. } else {
  633. sql = fmt.Sprintf("INSERT INTO %s (`%s`) VALUES (%s)", session.engine.Quote(tableName), strings.Join(columns, "`,`"), qm)
  634. }
  635. if err := session.cacheInsert(tableName); err != nil {
  636. return 0, err
  637. }
  638. res, err := session.exec(sql, args...)
  639. if err != nil {
  640. session.engine.logger.Errorf("[SQL][%p] %v", session, err)
  641. return 0, err
  642. }
  643. affected, err := res.RowsAffected()
  644. if err != nil {
  645. return 0, err
  646. }
  647. return affected, nil
  648. }
  649. func (session *Session) insertMapString(m map[string]string) (int64, error) {
  650. if len(m) == 0 {
  651. return 0, ErrParamsType
  652. }
  653. tableName := session.statement.TableName()
  654. if len(tableName) <= 0 {
  655. return 0, ErrTableNotFound
  656. }
  657. var columns = make([]string, 0, len(m))
  658. for k := range m {
  659. columns = append(columns, k)
  660. }
  661. sort.Strings(columns)
  662. var args = make([]interface{}, 0, len(m))
  663. for _, colName := range columns {
  664. args = append(args, m[colName])
  665. }
  666. qm := strings.Repeat("?,", len(columns))
  667. qm = "(" + qm[:len(qm)-1] + ")"
  668. // insert expr columns, override if exists
  669. exprColumns := session.statement.getExpr()
  670. for _, col := range exprColumns {
  671. columns = append(columns, strings.Trim(col.colName, "`"))
  672. qm = qm + col.expr + ","
  673. }
  674. qm = qm[:len(qm)-1]
  675. var sql string
  676. if session.statement.cond.IsValid() {
  677. qm = "(" + qm[:len(qm)-1] + ")"
  678. condSQL, condArgs, err := builder.ToSQL(session.statement.cond)
  679. if err != nil {
  680. return 0, err
  681. }
  682. sql = fmt.Sprintf("INSERT INTO %s (`%s`) SELECT %s FROM %s WHERE %s",
  683. session.engine.Quote(tableName),
  684. strings.Join(columns, "`,`"),
  685. qm,
  686. session.engine.Quote(tableName),
  687. condSQL,
  688. )
  689. args = append(args, condArgs...)
  690. } else {
  691. sql = fmt.Sprintf("INSERT INTO %s (`%s`) VALUES (%s)", session.engine.Quote(tableName), strings.Join(columns, "`,`"), qm)
  692. }
  693. if err := session.cacheInsert(tableName); err != nil {
  694. return 0, err
  695. }
  696. res, err := session.exec(sql, args...)
  697. if err != nil {
  698. session.engine.logger.Errorf("[SQL][%p] %v", session, err)
  699. return 0, err
  700. }
  701. affected, err := res.RowsAffected()
  702. if err != nil {
  703. return 0, err
  704. }
  705. return affected, nil
  706. }