PageRenderTime 1491ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/github.com/go-xorm/xorm/engine.go

https://github.com/housecream/server
Go | 1563 lines | 1212 code | 184 blank | 167 comment | 333 complexity | 36369cbd9473ea558f3fbc562d29e3e0 MD5 | raw file
  1. // Copyright 2015 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. "bufio"
  7. "bytes"
  8. "database/sql"
  9. "encoding/gob"
  10. "errors"
  11. "fmt"
  12. "io"
  13. "os"
  14. "reflect"
  15. "strconv"
  16. "strings"
  17. "sync"
  18. "time"
  19. "github.com/go-xorm/core"
  20. )
  21. // Engine is the major struct of xorm, it means a database manager.
  22. // Commonly, an application only need one engine
  23. type Engine struct {
  24. db *core.DB
  25. dialect core.Dialect
  26. ColumnMapper core.IMapper
  27. TableMapper core.IMapper
  28. TagIdentifier string
  29. Tables map[reflect.Type]*core.Table
  30. mutex *sync.RWMutex
  31. Cacher core.Cacher
  32. showSQL bool
  33. showExecTime bool
  34. logger core.ILogger
  35. TZLocation *time.Location
  36. DatabaseTZ *time.Location // The timezone of the database
  37. disableGlobalCache bool
  38. tagHandlers map[string]tagHandler
  39. }
  40. // ShowSQL show SQL statement or not on logger if log level is great than INFO
  41. func (engine *Engine) ShowSQL(show ...bool) {
  42. engine.logger.ShowSQL(show...)
  43. if len(show) == 0 {
  44. engine.showSQL = true
  45. } else {
  46. engine.showSQL = show[0]
  47. }
  48. }
  49. // ShowExecTime show SQL statement and execute time or not on logger if log level is great than INFO
  50. func (engine *Engine) ShowExecTime(show ...bool) {
  51. if len(show) == 0 {
  52. engine.showExecTime = true
  53. } else {
  54. engine.showExecTime = show[0]
  55. }
  56. }
  57. // Logger return the logger interface
  58. func (engine *Engine) Logger() core.ILogger {
  59. return engine.logger
  60. }
  61. // SetLogger set the new logger
  62. func (engine *Engine) SetLogger(logger core.ILogger) {
  63. engine.logger = logger
  64. engine.dialect.SetLogger(logger)
  65. }
  66. // SetDisableGlobalCache disable global cache or not
  67. func (engine *Engine) SetDisableGlobalCache(disable bool) {
  68. if engine.disableGlobalCache != disable {
  69. engine.disableGlobalCache = disable
  70. }
  71. }
  72. // DriverName return the current sql driver's name
  73. func (engine *Engine) DriverName() string {
  74. return engine.dialect.DriverName()
  75. }
  76. // DataSourceName return the current connection string
  77. func (engine *Engine) DataSourceName() string {
  78. return engine.dialect.DataSourceName()
  79. }
  80. // SetMapper set the name mapping rules
  81. func (engine *Engine) SetMapper(mapper core.IMapper) {
  82. engine.SetTableMapper(mapper)
  83. engine.SetColumnMapper(mapper)
  84. }
  85. // SetTableMapper set the table name mapping rule
  86. func (engine *Engine) SetTableMapper(mapper core.IMapper) {
  87. engine.TableMapper = mapper
  88. }
  89. // SetColumnMapper set the column name mapping rule
  90. func (engine *Engine) SetColumnMapper(mapper core.IMapper) {
  91. engine.ColumnMapper = mapper
  92. }
  93. // SupportInsertMany If engine's database support batch insert records like
  94. // "insert into user values (name, age), (name, age)".
  95. // When the return is ture, then engine.Insert(&users) will
  96. // generate batch sql and exeute.
  97. func (engine *Engine) SupportInsertMany() bool {
  98. return engine.dialect.SupportInsertMany()
  99. }
  100. // QuoteStr Engine's database use which character as quote.
  101. // mysql, sqlite use ` and postgres use "
  102. func (engine *Engine) QuoteStr() string {
  103. return engine.dialect.QuoteStr()
  104. }
  105. // Quote Use QuoteStr quote the string sql
  106. func (engine *Engine) Quote(value string) string {
  107. value = strings.TrimSpace(value)
  108. if len(value) == 0 {
  109. return value
  110. }
  111. if string(value[0]) == engine.dialect.QuoteStr() || value[0] == '`' {
  112. return value
  113. }
  114. value = strings.Replace(value, ".", engine.dialect.QuoteStr()+"."+engine.dialect.QuoteStr(), -1)
  115. return engine.dialect.QuoteStr() + value + engine.dialect.QuoteStr()
  116. }
  117. // QuoteTo quotes string and writes into the buffer
  118. func (engine *Engine) QuoteTo(buf *bytes.Buffer, value string) {
  119. if buf == nil {
  120. return
  121. }
  122. value = strings.TrimSpace(value)
  123. if value == "" {
  124. return
  125. }
  126. if string(value[0]) == engine.dialect.QuoteStr() || value[0] == '`' {
  127. buf.WriteString(value)
  128. return
  129. }
  130. value = strings.Replace(value, ".", engine.dialect.QuoteStr()+"."+engine.dialect.QuoteStr(), -1)
  131. buf.WriteString(engine.dialect.QuoteStr())
  132. buf.WriteString(value)
  133. buf.WriteString(engine.dialect.QuoteStr())
  134. }
  135. func (engine *Engine) quote(sql string) string {
  136. return engine.dialect.QuoteStr() + sql + engine.dialect.QuoteStr()
  137. }
  138. // SqlType will be depracated, please use SQLType instead
  139. //
  140. // Deprecated: use SQLType instead
  141. func (engine *Engine) SqlType(c *core.Column) string {
  142. return engine.SQLType(c)
  143. }
  144. // SQLType A simple wrapper to dialect's core.SqlType method
  145. func (engine *Engine) SQLType(c *core.Column) string {
  146. return engine.dialect.SqlType(c)
  147. }
  148. // AutoIncrStr Database's autoincrement statement
  149. func (engine *Engine) AutoIncrStr() string {
  150. return engine.dialect.AutoIncrStr()
  151. }
  152. // SetMaxOpenConns is only available for go 1.2+
  153. func (engine *Engine) SetMaxOpenConns(conns int) {
  154. engine.db.SetMaxOpenConns(conns)
  155. }
  156. // SetMaxIdleConns set the max idle connections on pool, default is 2
  157. func (engine *Engine) SetMaxIdleConns(conns int) {
  158. engine.db.SetMaxIdleConns(conns)
  159. }
  160. // SetDefaultCacher set the default cacher. Xorm's default not enable cacher.
  161. func (engine *Engine) SetDefaultCacher(cacher core.Cacher) {
  162. engine.Cacher = cacher
  163. }
  164. // NoCache If you has set default cacher, and you want temporilly stop use cache,
  165. // you can use NoCache()
  166. func (engine *Engine) NoCache() *Session {
  167. session := engine.NewSession()
  168. session.IsAutoClose = true
  169. return session.NoCache()
  170. }
  171. // NoCascade If you do not want to auto cascade load object
  172. func (engine *Engine) NoCascade() *Session {
  173. session := engine.NewSession()
  174. session.IsAutoClose = true
  175. return session.NoCascade()
  176. }
  177. // MapCacher Set a table use a special cacher
  178. func (engine *Engine) MapCacher(bean interface{}, cacher core.Cacher) {
  179. v := rValue(bean)
  180. tb := engine.autoMapType(v)
  181. tb.Cacher = cacher
  182. }
  183. // NewDB provides an interface to operate database directly
  184. func (engine *Engine) NewDB() (*core.DB, error) {
  185. return core.OpenDialect(engine.dialect)
  186. }
  187. // DB return the wrapper of sql.DB
  188. func (engine *Engine) DB() *core.DB {
  189. return engine.db
  190. }
  191. // Dialect return database dialect
  192. func (engine *Engine) Dialect() core.Dialect {
  193. return engine.dialect
  194. }
  195. // NewSession New a session
  196. func (engine *Engine) NewSession() *Session {
  197. session := &Session{Engine: engine}
  198. session.Init()
  199. return session
  200. }
  201. // Close the engine
  202. func (engine *Engine) Close() error {
  203. return engine.db.Close()
  204. }
  205. // Ping tests if database is alive
  206. func (engine *Engine) Ping() error {
  207. session := engine.NewSession()
  208. defer session.Close()
  209. engine.logger.Infof("PING DATABASE %v", engine.DriverName())
  210. return session.Ping()
  211. }
  212. // logging sql
  213. func (engine *Engine) logSQL(sqlStr string, sqlArgs ...interface{}) {
  214. if engine.showSQL && !engine.showExecTime {
  215. if len(sqlArgs) > 0 {
  216. engine.logger.Infof("[SQL] %v %v", sqlStr, sqlArgs)
  217. } else {
  218. engine.logger.Infof("[SQL] %v", sqlStr)
  219. }
  220. }
  221. }
  222. func (engine *Engine) logSQLQueryTime(sqlStr string, args []interface{}, executionBlock func() (*core.Stmt, *core.Rows, error)) (*core.Stmt, *core.Rows, error) {
  223. if engine.showSQL && engine.showExecTime {
  224. b4ExecTime := time.Now()
  225. stmt, res, err := executionBlock()
  226. execDuration := time.Since(b4ExecTime)
  227. if len(args) > 0 {
  228. engine.logger.Infof("[SQL] %s %v - took: %v", sqlStr, args, execDuration)
  229. } else {
  230. engine.logger.Infof("[SQL] %s - took: %v", sqlStr, execDuration)
  231. }
  232. return stmt, res, err
  233. }
  234. return executionBlock()
  235. }
  236. func (engine *Engine) logSQLExecutionTime(sqlStr string, args []interface{}, executionBlock func() (sql.Result, error)) (sql.Result, error) {
  237. if engine.showSQL && engine.showExecTime {
  238. b4ExecTime := time.Now()
  239. res, err := executionBlock()
  240. execDuration := time.Since(b4ExecTime)
  241. if len(args) > 0 {
  242. engine.logger.Infof("[sql] %s [args] %v - took: %v", sqlStr, args, execDuration)
  243. } else {
  244. engine.logger.Infof("[sql] %s - took: %v", sqlStr, execDuration)
  245. }
  246. return res, err
  247. }
  248. return executionBlock()
  249. }
  250. // Sql provides raw sql input parameter. When you have a complex SQL statement
  251. // and cannot use Where, Id, In and etc. Methods to describe, you can use SQL.
  252. //
  253. // Deprecated: use SQL instead.
  254. func (engine *Engine) Sql(querystring string, args ...interface{}) *Session {
  255. return engine.SQL(querystring, args...)
  256. }
  257. // SQL method let's you manually write raw SQL and operate
  258. // For example:
  259. //
  260. // engine.SQL("select * from user").Find(&users)
  261. //
  262. // This code will execute "select * from user" and set the records to users
  263. func (engine *Engine) SQL(query interface{}, args ...interface{}) *Session {
  264. session := engine.NewSession()
  265. session.IsAutoClose = true
  266. return session.SQL(query, args...)
  267. }
  268. // NoAutoTime Default if your struct has "created" or "updated" filed tag, the fields
  269. // will automatically be filled with current time when Insert or Update
  270. // invoked. Call NoAutoTime if you dont' want to fill automatically.
  271. func (engine *Engine) NoAutoTime() *Session {
  272. session := engine.NewSession()
  273. session.IsAutoClose = true
  274. return session.NoAutoTime()
  275. }
  276. // NoAutoCondition disable auto generate Where condition from bean or not
  277. func (engine *Engine) NoAutoCondition(no ...bool) *Session {
  278. session := engine.NewSession()
  279. session.IsAutoClose = true
  280. return session.NoAutoCondition(no...)
  281. }
  282. // DBMetas Retrieve all tables, columns, indexes' informations from database.
  283. func (engine *Engine) DBMetas() ([]*core.Table, error) {
  284. tables, err := engine.dialect.GetTables()
  285. if err != nil {
  286. return nil, err
  287. }
  288. for _, table := range tables {
  289. colSeq, cols, err := engine.dialect.GetColumns(table.Name)
  290. if err != nil {
  291. return nil, err
  292. }
  293. for _, name := range colSeq {
  294. table.AddColumn(cols[name])
  295. }
  296. indexes, err := engine.dialect.GetIndexes(table.Name)
  297. if err != nil {
  298. return nil, err
  299. }
  300. table.Indexes = indexes
  301. for _, index := range indexes {
  302. for _, name := range index.Cols {
  303. if col := table.GetColumn(name); col != nil {
  304. col.Indexes[index.Name] = index.Type
  305. } else {
  306. return nil, fmt.Errorf("Unknown col %s in index %v of table %v, columns %v", name, index.Name, table.Name, table.ColumnsSeq())
  307. }
  308. }
  309. }
  310. }
  311. return tables, nil
  312. }
  313. // DumpAllToFile dump database all table structs and data to a file
  314. func (engine *Engine) DumpAllToFile(fp string, tp ...core.DbType) error {
  315. f, err := os.Create(fp)
  316. if err != nil {
  317. return err
  318. }
  319. defer f.Close()
  320. return engine.DumpAll(f, tp...)
  321. }
  322. // DumpAll dump database all table structs and data to w
  323. func (engine *Engine) DumpAll(w io.Writer, tp ...core.DbType) error {
  324. tables, err := engine.DBMetas()
  325. if err != nil {
  326. return err
  327. }
  328. return engine.DumpTables(tables, w, tp...)
  329. }
  330. // DumpTablesToFile dump specified tables to SQL file.
  331. func (engine *Engine) DumpTablesToFile(tables []*core.Table, fp string, tp ...core.DbType) error {
  332. f, err := os.Create(fp)
  333. if err != nil {
  334. return err
  335. }
  336. defer f.Close()
  337. return engine.DumpTables(tables, f, tp...)
  338. }
  339. // DumpTables dump specify tables to io.Writer
  340. func (engine *Engine) DumpTables(tables []*core.Table, w io.Writer, tp ...core.DbType) error {
  341. return engine.dumpTables(tables, w, tp...)
  342. }
  343. // dumpTables dump database all table structs and data to w with specify db type
  344. func (engine *Engine) dumpTables(tables []*core.Table, w io.Writer, tp ...core.DbType) error {
  345. var dialect core.Dialect
  346. var distDBName string
  347. if len(tp) == 0 {
  348. dialect = engine.dialect
  349. distDBName = string(engine.dialect.DBType())
  350. } else {
  351. dialect = core.QueryDialect(tp[0])
  352. if dialect == nil {
  353. return errors.New("Unsupported database type")
  354. }
  355. dialect.Init(nil, engine.dialect.URI(), "", "")
  356. distDBName = string(tp[0])
  357. }
  358. _, err := io.WriteString(w, fmt.Sprintf("/*Generated by xorm v%s %s, from %s to %s*/\n\n",
  359. Version, time.Now().In(engine.TZLocation).Format("2006-01-02 15:04:05"), engine.dialect.DBType(), strings.ToUpper(distDBName)))
  360. if err != nil {
  361. return err
  362. }
  363. for i, table := range tables {
  364. if i > 0 {
  365. _, err = io.WriteString(w, "\n")
  366. if err != nil {
  367. return err
  368. }
  369. }
  370. _, err = io.WriteString(w, dialect.CreateTableSql(table, "", table.StoreEngine, "")+";\n")
  371. if err != nil {
  372. return err
  373. }
  374. for _, index := range table.Indexes {
  375. _, err = io.WriteString(w, dialect.CreateIndexSql(table.Name, index)+";\n")
  376. if err != nil {
  377. return err
  378. }
  379. }
  380. cols := table.ColumnsSeq()
  381. colNames := dialect.Quote(strings.Join(cols, dialect.Quote(", ")))
  382. rows, err := engine.DB().Query("SELECT " + colNames + " FROM " + engine.Quote(table.Name))
  383. if err != nil {
  384. return err
  385. }
  386. defer rows.Close()
  387. for rows.Next() {
  388. dest := make([]interface{}, len(cols))
  389. err = rows.ScanSlice(&dest)
  390. if err != nil {
  391. return err
  392. }
  393. _, err = io.WriteString(w, "INSERT INTO "+dialect.Quote(table.Name)+" ("+colNames+") VALUES (")
  394. if err != nil {
  395. return err
  396. }
  397. var temp string
  398. for i, d := range dest {
  399. col := table.GetColumn(cols[i])
  400. if col == nil {
  401. return errors.New("unknow column error")
  402. }
  403. if d == nil {
  404. temp += ", NULL"
  405. } else if col.SQLType.IsText() || col.SQLType.IsTime() {
  406. var v = fmt.Sprintf("%s", d)
  407. if strings.HasSuffix(v, " +0000 UTC") {
  408. temp += fmt.Sprintf(", '%s'", v[0:len(v)-len(" +0000 UTC")])
  409. } else {
  410. temp += ", '" + strings.Replace(v, "'", "''", -1) + "'"
  411. }
  412. } else if col.SQLType.IsBlob() {
  413. if reflect.TypeOf(d).Kind() == reflect.Slice {
  414. temp += fmt.Sprintf(", %s", dialect.FormatBytes(d.([]byte)))
  415. } else if reflect.TypeOf(d).Kind() == reflect.String {
  416. temp += fmt.Sprintf(", '%s'", d.(string))
  417. }
  418. } else if col.SQLType.IsNumeric() {
  419. switch reflect.TypeOf(d).Kind() {
  420. case reflect.Slice:
  421. temp += fmt.Sprintf(", %s", string(d.([]byte)))
  422. case reflect.Int16, reflect.Int8, reflect.Int32, reflect.Int64, reflect.Int:
  423. if col.SQLType.Name == core.Bool {
  424. temp += fmt.Sprintf(", %v", strconv.FormatBool(reflect.ValueOf(d).Int() > 0))
  425. } else {
  426. temp += fmt.Sprintf(", %v", d)
  427. }
  428. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  429. if col.SQLType.Name == core.Bool {
  430. temp += fmt.Sprintf(", %v", strconv.FormatBool(reflect.ValueOf(d).Uint() > 0))
  431. } else {
  432. temp += fmt.Sprintf(", %v", d)
  433. }
  434. default:
  435. temp += fmt.Sprintf(", %v", d)
  436. }
  437. } else {
  438. s := fmt.Sprintf("%v", d)
  439. if strings.Contains(s, ":") || strings.Contains(s, "-") {
  440. if strings.HasSuffix(s, " +0000 UTC") {
  441. temp += fmt.Sprintf(", '%s'", s[0:len(s)-len(" +0000 UTC")])
  442. } else {
  443. temp += fmt.Sprintf(", '%s'", s)
  444. }
  445. } else {
  446. temp += fmt.Sprintf(", %s", s)
  447. }
  448. }
  449. }
  450. _, err = io.WriteString(w, temp[2:]+");\n")
  451. if err != nil {
  452. return err
  453. }
  454. }
  455. // FIXME: Hack for postgres
  456. if string(dialect.DBType()) == core.POSTGRES && table.AutoIncrColumn() != nil {
  457. _, err = io.WriteString(w, "SELECT setval('table_id_seq', COALESCE((SELECT MAX("+table.AutoIncrColumn().Name+") FROM "+dialect.Quote(table.Name)+"), 1), false);\n")
  458. if err != nil {
  459. return err
  460. }
  461. }
  462. }
  463. return nil
  464. }
  465. func (engine *Engine) tableName(beanOrTableName interface{}) (string, error) {
  466. v := rValue(beanOrTableName)
  467. if v.Type().Kind() == reflect.String {
  468. return beanOrTableName.(string), nil
  469. } else if v.Type().Kind() == reflect.Struct {
  470. return engine.tbName(v), nil
  471. }
  472. return "", errors.New("bean should be a struct or struct's point")
  473. }
  474. func (engine *Engine) tbName(v reflect.Value) string {
  475. if tb, ok := v.Interface().(TableName); ok {
  476. return tb.TableName()
  477. }
  478. if v.Type().Kind() == reflect.Ptr {
  479. if tb, ok := reflect.Indirect(v).Interface().(TableName); ok {
  480. return tb.TableName()
  481. }
  482. } else if v.CanAddr() {
  483. if tb, ok := v.Addr().Interface().(TableName); ok {
  484. return tb.TableName()
  485. }
  486. }
  487. return engine.TableMapper.Obj2Table(reflect.Indirect(v).Type().Name())
  488. }
  489. // Cascade use cascade or not
  490. func (engine *Engine) Cascade(trueOrFalse ...bool) *Session {
  491. session := engine.NewSession()
  492. session.IsAutoClose = true
  493. return session.Cascade(trueOrFalse...)
  494. }
  495. // Where method provide a condition query
  496. func (engine *Engine) Where(query interface{}, args ...interface{}) *Session {
  497. session := engine.NewSession()
  498. session.IsAutoClose = true
  499. return session.Where(query, args...)
  500. }
  501. // Id will be depracated, please use ID instead
  502. func (engine *Engine) Id(id interface{}) *Session {
  503. session := engine.NewSession()
  504. session.IsAutoClose = true
  505. return session.Id(id)
  506. }
  507. // ID method provoide a condition as (id) = ?
  508. func (engine *Engine) ID(id interface{}) *Session {
  509. session := engine.NewSession()
  510. session.IsAutoClose = true
  511. return session.ID(id)
  512. }
  513. // Before apply before Processor, affected bean is passed to closure arg
  514. func (engine *Engine) Before(closures func(interface{})) *Session {
  515. session := engine.NewSession()
  516. session.IsAutoClose = true
  517. return session.Before(closures)
  518. }
  519. // After apply after insert Processor, affected bean is passed to closure arg
  520. func (engine *Engine) After(closures func(interface{})) *Session {
  521. session := engine.NewSession()
  522. session.IsAutoClose = true
  523. return session.After(closures)
  524. }
  525. // Charset set charset when create table, only support mysql now
  526. func (engine *Engine) Charset(charset string) *Session {
  527. session := engine.NewSession()
  528. session.IsAutoClose = true
  529. return session.Charset(charset)
  530. }
  531. // StoreEngine set store engine when create table, only support mysql now
  532. func (engine *Engine) StoreEngine(storeEngine string) *Session {
  533. session := engine.NewSession()
  534. session.IsAutoClose = true
  535. return session.StoreEngine(storeEngine)
  536. }
  537. // Distinct use for distinct columns. Caution: when you are using cache,
  538. // distinct will not be cached because cache system need id,
  539. // but distinct will not provide id
  540. func (engine *Engine) Distinct(columns ...string) *Session {
  541. session := engine.NewSession()
  542. session.IsAutoClose = true
  543. return session.Distinct(columns...)
  544. }
  545. // Select customerize your select columns or contents
  546. func (engine *Engine) Select(str string) *Session {
  547. session := engine.NewSession()
  548. session.IsAutoClose = true
  549. return session.Select(str)
  550. }
  551. // Cols only use the parameters as select or update columns
  552. func (engine *Engine) Cols(columns ...string) *Session {
  553. session := engine.NewSession()
  554. session.IsAutoClose = true
  555. return session.Cols(columns...)
  556. }
  557. // AllCols indicates that all columns should be use
  558. func (engine *Engine) AllCols() *Session {
  559. session := engine.NewSession()
  560. session.IsAutoClose = true
  561. return session.AllCols()
  562. }
  563. // MustCols specify some columns must use even if they are empty
  564. func (engine *Engine) MustCols(columns ...string) *Session {
  565. session := engine.NewSession()
  566. session.IsAutoClose = true
  567. return session.MustCols(columns...)
  568. }
  569. // UseBool xorm automatically retrieve condition according struct, but
  570. // if struct has bool field, it will ignore them. So use UseBool
  571. // to tell system to do not ignore them.
  572. // If no parameters, it will use all the bool field of struct, or
  573. // it will use parameters's columns
  574. func (engine *Engine) UseBool(columns ...string) *Session {
  575. session := engine.NewSession()
  576. session.IsAutoClose = true
  577. return session.UseBool(columns...)
  578. }
  579. // Omit only not use the parameters as select or update columns
  580. func (engine *Engine) Omit(columns ...string) *Session {
  581. session := engine.NewSession()
  582. session.IsAutoClose = true
  583. return session.Omit(columns...)
  584. }
  585. // Nullable set null when column is zero-value and nullable for update
  586. func (engine *Engine) Nullable(columns ...string) *Session {
  587. session := engine.NewSession()
  588. session.IsAutoClose = true
  589. return session.Nullable(columns...)
  590. }
  591. // In will generate "column IN (?, ?)"
  592. func (engine *Engine) In(column string, args ...interface{}) *Session {
  593. session := engine.NewSession()
  594. session.IsAutoClose = true
  595. return session.In(column, args...)
  596. }
  597. // Incr provides a update string like "column = column + ?"
  598. func (engine *Engine) Incr(column string, arg ...interface{}) *Session {
  599. session := engine.NewSession()
  600. session.IsAutoClose = true
  601. return session.Incr(column, arg...)
  602. }
  603. // Decr provides a update string like "column = column - ?"
  604. func (engine *Engine) Decr(column string, arg ...interface{}) *Session {
  605. session := engine.NewSession()
  606. session.IsAutoClose = true
  607. return session.Decr(column, arg...)
  608. }
  609. // SetExpr provides a update string like "column = {expression}"
  610. func (engine *Engine) SetExpr(column string, expression string) *Session {
  611. session := engine.NewSession()
  612. session.IsAutoClose = true
  613. return session.SetExpr(column, expression)
  614. }
  615. // Table temporarily change the Get, Find, Update's table
  616. func (engine *Engine) Table(tableNameOrBean interface{}) *Session {
  617. session := engine.NewSession()
  618. session.IsAutoClose = true
  619. return session.Table(tableNameOrBean)
  620. }
  621. // Alias set the table alias
  622. func (engine *Engine) Alias(alias string) *Session {
  623. session := engine.NewSession()
  624. session.IsAutoClose = true
  625. return session.Alias(alias)
  626. }
  627. // Limit will generate "LIMIT start, limit"
  628. func (engine *Engine) Limit(limit int, start ...int) *Session {
  629. session := engine.NewSession()
  630. session.IsAutoClose = true
  631. return session.Limit(limit, start...)
  632. }
  633. // Desc will generate "ORDER BY column1 DESC, column2 DESC"
  634. func (engine *Engine) Desc(colNames ...string) *Session {
  635. session := engine.NewSession()
  636. session.IsAutoClose = true
  637. return session.Desc(colNames...)
  638. }
  639. // Asc will generate "ORDER BY column1,column2 Asc"
  640. // This method can chainable use.
  641. //
  642. // engine.Desc("name").Asc("age").Find(&users)
  643. // // SELECT * FROM user ORDER BY name DESC, age ASC
  644. //
  645. func (engine *Engine) Asc(colNames ...string) *Session {
  646. session := engine.NewSession()
  647. session.IsAutoClose = true
  648. return session.Asc(colNames...)
  649. }
  650. // OrderBy will generate "ORDER BY order"
  651. func (engine *Engine) OrderBy(order string) *Session {
  652. session := engine.NewSession()
  653. session.IsAutoClose = true
  654. return session.OrderBy(order)
  655. }
  656. // Join the join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
  657. func (engine *Engine) Join(joinOperator string, tablename interface{}, condition string, args ...interface{}) *Session {
  658. session := engine.NewSession()
  659. session.IsAutoClose = true
  660. return session.Join(joinOperator, tablename, condition, args...)
  661. }
  662. // GroupBy generate group by statement
  663. func (engine *Engine) GroupBy(keys string) *Session {
  664. session := engine.NewSession()
  665. session.IsAutoClose = true
  666. return session.GroupBy(keys)
  667. }
  668. // Having generate having statement
  669. func (engine *Engine) Having(conditions string) *Session {
  670. session := engine.NewSession()
  671. session.IsAutoClose = true
  672. return session.Having(conditions)
  673. }
  674. func (engine *Engine) autoMapType(v reflect.Value) *core.Table {
  675. t := v.Type()
  676. engine.mutex.Lock()
  677. defer engine.mutex.Unlock()
  678. table, ok := engine.Tables[t]
  679. if !ok {
  680. var err error
  681. table, err = engine.mapType(v)
  682. if err != nil {
  683. engine.logger.Error(err)
  684. } else {
  685. engine.Tables[t] = table
  686. if engine.Cacher != nil {
  687. if v.CanAddr() {
  688. engine.GobRegister(v.Addr().Interface())
  689. } else {
  690. engine.GobRegister(v.Interface())
  691. }
  692. }
  693. }
  694. }
  695. return table
  696. }
  697. // GobRegister register one struct to gob for cache use
  698. func (engine *Engine) GobRegister(v interface{}) *Engine {
  699. //fmt.Printf("Type: %[1]T => Data: %[1]#v\n", v)
  700. gob.Register(v)
  701. return engine
  702. }
  703. // Table table struct
  704. type Table struct {
  705. *core.Table
  706. Name string
  707. }
  708. // TableInfo get table info according to bean's content
  709. func (engine *Engine) TableInfo(bean interface{}) *Table {
  710. v := rValue(bean)
  711. return &Table{engine.autoMapType(v), engine.tbName(v)}
  712. }
  713. func addIndex(indexName string, table *core.Table, col *core.Column, indexType int) {
  714. if index, ok := table.Indexes[indexName]; ok {
  715. index.AddColumn(col.Name)
  716. col.Indexes[index.Name] = indexType
  717. } else {
  718. index := core.NewIndex(indexName, indexType)
  719. index.AddColumn(col.Name)
  720. table.AddIndex(index)
  721. col.Indexes[index.Name] = indexType
  722. }
  723. }
  724. func (engine *Engine) newTable() *core.Table {
  725. table := core.NewEmptyTable()
  726. if !engine.disableGlobalCache {
  727. table.Cacher = engine.Cacher
  728. }
  729. return table
  730. }
  731. // TableName table name interface to define customerize table name
  732. type TableName interface {
  733. TableName() string
  734. }
  735. var (
  736. tpTableName = reflect.TypeOf((*TableName)(nil)).Elem()
  737. )
  738. func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) {
  739. t := v.Type()
  740. table := engine.newTable()
  741. if tb, ok := v.Interface().(TableName); ok {
  742. table.Name = tb.TableName()
  743. } else {
  744. if v.CanAddr() {
  745. if tb, ok = v.Addr().Interface().(TableName); ok {
  746. table.Name = tb.TableName()
  747. }
  748. }
  749. if table.Name == "" {
  750. table.Name = engine.TableMapper.Obj2Table(t.Name())
  751. }
  752. }
  753. table.Type = t
  754. var idFieldColName string
  755. var hasCacheTag, hasNoCacheTag bool
  756. for i := 0; i < t.NumField(); i++ {
  757. tag := t.Field(i).Tag
  758. ormTagStr := tag.Get(engine.TagIdentifier)
  759. var col *core.Column
  760. fieldValue := v.Field(i)
  761. fieldType := fieldValue.Type()
  762. if ormTagStr != "" {
  763. col = &core.Column{FieldName: t.Field(i).Name, Nullable: true, IsPrimaryKey: false,
  764. IsAutoIncrement: false, MapType: core.TWOSIDES, Indexes: make(map[string]int)}
  765. tags := splitTag(ormTagStr)
  766. if len(tags) > 0 {
  767. if tags[0] == "-" {
  768. continue
  769. }
  770. var ctx = tagContext{
  771. table: table,
  772. col: col,
  773. fieldValue: fieldValue,
  774. indexNames: make(map[string]int),
  775. engine: engine,
  776. }
  777. if strings.ToUpper(tags[0]) == "EXTENDS" {
  778. if err := ExtendsTagHandler(&ctx); err != nil {
  779. return nil, err
  780. }
  781. continue
  782. }
  783. for j, key := range tags {
  784. if ctx.ignoreNext {
  785. ctx.ignoreNext = false
  786. continue
  787. }
  788. k := strings.ToUpper(key)
  789. ctx.tagName = k
  790. pStart := strings.Index(k, "(")
  791. if pStart == 0 {
  792. return nil, errors.New("( could not be the first charactor")
  793. }
  794. if pStart > -1 {
  795. if !strings.HasSuffix(k, ")") {
  796. return nil, errors.New("cannot match ) charactor")
  797. }
  798. ctx.tagName = k[:pStart]
  799. ctx.params = strings.Split(k[pStart+1:len(k)-1], ",")
  800. }
  801. if j > 0 {
  802. ctx.preTag = strings.ToUpper(tags[j-1])
  803. }
  804. if j < len(tags)-1 {
  805. ctx.nextTag = strings.ToUpper(tags[j+1])
  806. } else {
  807. ctx.nextTag = ""
  808. }
  809. if h, ok := engine.tagHandlers[ctx.tagName]; ok {
  810. if err := h(&ctx); err != nil {
  811. return nil, err
  812. }
  813. } else {
  814. if strings.HasPrefix(key, "'") && strings.HasSuffix(key, "'") {
  815. col.Name = key[1 : len(key)-1]
  816. } else {
  817. col.Name = key
  818. }
  819. }
  820. if ctx.hasCacheTag {
  821. hasCacheTag = true
  822. }
  823. if ctx.hasNoCacheTag {
  824. hasNoCacheTag = true
  825. }
  826. }
  827. if col.SQLType.Name == "" {
  828. col.SQLType = core.Type2SQLType(fieldType)
  829. }
  830. engine.dialect.SqlType(col)
  831. if col.Length == 0 {
  832. col.Length = col.SQLType.DefaultLength
  833. }
  834. if col.Length2 == 0 {
  835. col.Length2 = col.SQLType.DefaultLength2
  836. }
  837. if col.Name == "" {
  838. col.Name = engine.ColumnMapper.Obj2Table(t.Field(i).Name)
  839. }
  840. if ctx.isUnique {
  841. ctx.indexNames[col.Name] = core.UniqueType
  842. } else if ctx.isIndex {
  843. ctx.indexNames[col.Name] = core.IndexType
  844. }
  845. for indexName, indexType := range ctx.indexNames {
  846. addIndex(indexName, table, col, indexType)
  847. }
  848. }
  849. } else {
  850. var sqlType core.SQLType
  851. if fieldValue.CanAddr() {
  852. if _, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
  853. sqlType = core.SQLType{Name: core.Text}
  854. }
  855. }
  856. if _, ok := fieldValue.Interface().(core.Conversion); ok {
  857. sqlType = core.SQLType{Name: core.Text}
  858. } else {
  859. sqlType = core.Type2SQLType(fieldType)
  860. }
  861. col = core.NewColumn(engine.ColumnMapper.Obj2Table(t.Field(i).Name),
  862. t.Field(i).Name, sqlType, sqlType.DefaultLength,
  863. sqlType.DefaultLength2, true)
  864. }
  865. if col.IsAutoIncrement {
  866. col.Nullable = false
  867. }
  868. table.AddColumn(col)
  869. if fieldType.Kind() == reflect.Int64 && (strings.ToUpper(col.FieldName) == "ID" || strings.HasSuffix(strings.ToUpper(col.FieldName), ".ID")) {
  870. idFieldColName = col.Name
  871. }
  872. } // end for
  873. if idFieldColName != "" && len(table.PrimaryKeys) == 0 {
  874. col := table.GetColumn(idFieldColName)
  875. col.IsPrimaryKey = true
  876. col.IsAutoIncrement = true
  877. col.Nullable = false
  878. table.PrimaryKeys = append(table.PrimaryKeys, col.Name)
  879. table.AutoIncrement = col.Name
  880. }
  881. if hasCacheTag {
  882. if engine.Cacher != nil { // !nash! use engine's cacher if provided
  883. engine.logger.Info("enable cache on table:", table.Name)
  884. table.Cacher = engine.Cacher
  885. } else {
  886. engine.logger.Info("enable LRU cache on table:", table.Name)
  887. table.Cacher = NewLRUCacher2(NewMemoryStore(), time.Hour, 10000) // !nashtsai! HACK use LRU cacher for now
  888. }
  889. }
  890. if hasNoCacheTag {
  891. engine.logger.Info("no cache on table:", table.Name)
  892. table.Cacher = nil
  893. }
  894. return table, nil
  895. }
  896. // IsTableEmpty if a table has any reocrd
  897. func (engine *Engine) IsTableEmpty(bean interface{}) (bool, error) {
  898. session := engine.NewSession()
  899. defer session.Close()
  900. return session.IsTableEmpty(bean)
  901. }
  902. // IsTableExist if a table is exist
  903. func (engine *Engine) IsTableExist(beanOrTableName interface{}) (bool, error) {
  904. session := engine.NewSession()
  905. defer session.Close()
  906. return session.IsTableExist(beanOrTableName)
  907. }
  908. // IdOf get id from one struct
  909. //
  910. // Deprecated: use IDOf instead.
  911. func (engine *Engine) IdOf(bean interface{}) core.PK {
  912. return engine.IDOf(bean)
  913. }
  914. // IDOf get id from one struct
  915. func (engine *Engine) IDOf(bean interface{}) core.PK {
  916. return engine.IdOfV(reflect.ValueOf(bean))
  917. }
  918. // IdOfV get id from one value of struct
  919. //
  920. // Deprecated: use IDOfV instead.
  921. func (engine *Engine) IdOfV(rv reflect.Value) core.PK {
  922. return engine.IDOfV(rv)
  923. }
  924. // IDOfV get id from one value of struct
  925. func (engine *Engine) IDOfV(rv reflect.Value) core.PK {
  926. v := reflect.Indirect(rv)
  927. table := engine.autoMapType(v)
  928. pk := make([]interface{}, len(table.PrimaryKeys))
  929. for i, col := range table.PKColumns() {
  930. pkField := v.FieldByName(col.FieldName)
  931. switch pkField.Kind() {
  932. case reflect.String:
  933. pk[i] = pkField.String()
  934. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  935. pk[i] = pkField.Int()
  936. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  937. pk[i] = pkField.Uint()
  938. }
  939. }
  940. return core.PK(pk)
  941. }
  942. // CreateIndexes create indexes
  943. func (engine *Engine) CreateIndexes(bean interface{}) error {
  944. session := engine.NewSession()
  945. defer session.Close()
  946. return session.CreateIndexes(bean)
  947. }
  948. // CreateUniques create uniques
  949. func (engine *Engine) CreateUniques(bean interface{}) error {
  950. session := engine.NewSession()
  951. defer session.Close()
  952. return session.CreateUniques(bean)
  953. }
  954. func (engine *Engine) getCacher2(table *core.Table) core.Cacher {
  955. return table.Cacher
  956. }
  957. func (engine *Engine) getCacher(v reflect.Value) core.Cacher {
  958. if table := engine.autoMapType(v); table != nil {
  959. return table.Cacher
  960. }
  961. return engine.Cacher
  962. }
  963. // ClearCacheBean if enabled cache, clear the cache bean
  964. func (engine *Engine) ClearCacheBean(bean interface{}, id string) error {
  965. v := rValue(bean)
  966. t := v.Type()
  967. if t.Kind() != reflect.Struct {
  968. return errors.New("error params")
  969. }
  970. tableName := engine.tbName(v)
  971. table := engine.autoMapType(v)
  972. cacher := table.Cacher
  973. if cacher == nil {
  974. cacher = engine.Cacher
  975. }
  976. if cacher != nil {
  977. cacher.ClearIds(tableName)
  978. cacher.DelBean(tableName, id)
  979. }
  980. return nil
  981. }
  982. // ClearCache if enabled cache, clear some tables' cache
  983. func (engine *Engine) ClearCache(beans ...interface{}) error {
  984. for _, bean := range beans {
  985. v := rValue(bean)
  986. t := v.Type()
  987. if t.Kind() != reflect.Struct {
  988. return errors.New("error params")
  989. }
  990. tableName := engine.tbName(v)
  991. table := engine.autoMapType(v)
  992. cacher := table.Cacher
  993. if cacher == nil {
  994. cacher = engine.Cacher
  995. }
  996. if cacher != nil {
  997. cacher.ClearIds(tableName)
  998. cacher.ClearBeans(tableName)
  999. }
  1000. }
  1001. return nil
  1002. }
  1003. // Sync the new struct changes to database, this method will automatically add
  1004. // table, column, index, unique. but will not delete or change anything.
  1005. // If you change some field, you should change the database manually.
  1006. func (engine *Engine) Sync(beans ...interface{}) error {
  1007. for _, bean := range beans {
  1008. v := rValue(bean)
  1009. tableName := engine.tbName(v)
  1010. table := engine.autoMapType(v)
  1011. s := engine.NewSession()
  1012. defer s.Close()
  1013. isExist, err := s.Table(bean).isTableExist(tableName)
  1014. if err != nil {
  1015. return err
  1016. }
  1017. if !isExist {
  1018. err = engine.CreateTables(bean)
  1019. if err != nil {
  1020. return err
  1021. }
  1022. }
  1023. /*isEmpty, err := engine.IsEmptyTable(bean)
  1024. if err != nil {
  1025. return err
  1026. }*/
  1027. var isEmpty bool
  1028. if isEmpty {
  1029. err = engine.DropTables(bean)
  1030. if err != nil {
  1031. return err
  1032. }
  1033. err = engine.CreateTables(bean)
  1034. if err != nil {
  1035. return err
  1036. }
  1037. } else {
  1038. for _, col := range table.Columns() {
  1039. isExist, err := engine.dialect.IsColumnExist(tableName, col.Name)
  1040. if err != nil {
  1041. return err
  1042. }
  1043. if !isExist {
  1044. session := engine.NewSession()
  1045. session.Statement.setRefValue(v)
  1046. defer session.Close()
  1047. err = session.addColumn(col.Name)
  1048. if err != nil {
  1049. return err
  1050. }
  1051. }
  1052. }
  1053. for name, index := range table.Indexes {
  1054. session := engine.NewSession()
  1055. session.Statement.setRefValue(v)
  1056. defer session.Close()
  1057. if index.Type == core.UniqueType {
  1058. //isExist, err := session.isIndexExist(table.Name, name, true)
  1059. isExist, err := session.isIndexExist2(tableName, index.Cols, true)
  1060. if err != nil {
  1061. return err
  1062. }
  1063. if !isExist {
  1064. session := engine.NewSession()
  1065. session.Statement.setRefValue(v)
  1066. defer session.Close()
  1067. err = session.addUnique(tableName, name)
  1068. if err != nil {
  1069. return err
  1070. }
  1071. }
  1072. } else if index.Type == core.IndexType {
  1073. isExist, err := session.isIndexExist2(tableName, index.Cols, false)
  1074. if err != nil {
  1075. return err
  1076. }
  1077. if !isExist {
  1078. session := engine.NewSession()
  1079. session.Statement.setRefValue(v)
  1080. defer session.Close()
  1081. err = session.addIndex(tableName, name)
  1082. if err != nil {
  1083. return err
  1084. }
  1085. }
  1086. } else {
  1087. return errors.New("unknow index type")
  1088. }
  1089. }
  1090. }
  1091. }
  1092. return nil
  1093. }
  1094. // Sync2 synchronize structs to database tables
  1095. func (engine *Engine) Sync2(beans ...interface{}) error {
  1096. s := engine.NewSession()
  1097. defer s.Close()
  1098. return s.Sync2(beans...)
  1099. }
  1100. func (engine *Engine) unMap(beans ...interface{}) (e error) {
  1101. engine.mutex.Lock()
  1102. defer engine.mutex.Unlock()
  1103. for _, bean := range beans {
  1104. t := rType(bean)
  1105. if _, ok := engine.Tables[t]; ok {
  1106. delete(engine.Tables, t)
  1107. }
  1108. }
  1109. return
  1110. }
  1111. // Drop all mapped table
  1112. func (engine *Engine) dropAll() error {
  1113. session := engine.NewSession()
  1114. defer session.Close()
  1115. err := session.Begin()
  1116. if err != nil {
  1117. return err
  1118. }
  1119. err = session.dropAll()
  1120. if err != nil {
  1121. session.Rollback()
  1122. return err
  1123. }
  1124. return session.Commit()
  1125. }
  1126. // CreateTables create tabls according bean
  1127. func (engine *Engine) CreateTables(beans ...interface{}) error {
  1128. session := engine.NewSession()
  1129. defer session.Close()
  1130. err := session.Begin()
  1131. if err != nil {
  1132. return err
  1133. }
  1134. for _, bean := range beans {
  1135. err = session.CreateTable(bean)
  1136. if err != nil {
  1137. session.Rollback()
  1138. return err
  1139. }
  1140. }
  1141. return session.Commit()
  1142. }
  1143. // DropTables drop specify tables
  1144. func (engine *Engine) DropTables(beans ...interface{}) error {
  1145. session := engine.NewSession()
  1146. defer session.Close()
  1147. err := session.Begin()
  1148. if err != nil {
  1149. return err
  1150. }
  1151. for _, bean := range beans {
  1152. err = session.DropTable(bean)
  1153. if err != nil {
  1154. session.Rollback()
  1155. return err
  1156. }
  1157. }
  1158. return session.Commit()
  1159. }
  1160. func (engine *Engine) createAll() error {
  1161. session := engine.NewSession()
  1162. defer session.Close()
  1163. return session.createAll()
  1164. }
  1165. // Exec raw sql
  1166. func (engine *Engine) Exec(sql string, args ...interface{}) (sql.Result, error) {
  1167. session := engine.NewSession()
  1168. defer session.Close()
  1169. return session.Exec(sql, args...)
  1170. }
  1171. // Query a raw sql and return records as []map[string][]byte
  1172. func (engine *Engine) Query(sql string, paramStr ...interface{}) (resultsSlice []map[string][]byte, err error) {
  1173. session := engine.NewSession()
  1174. defer session.Close()
  1175. return session.Query(sql, paramStr...)
  1176. }
  1177. // Insert one or more records
  1178. func (engine *Engine) Insert(beans ...interface{}) (int64, error) {
  1179. session := engine.NewSession()
  1180. defer session.Close()
  1181. return session.Insert(beans...)
  1182. }
  1183. // InsertOne insert only one record
  1184. func (engine *Engine) InsertOne(bean interface{}) (int64, error) {
  1185. session := engine.NewSession()
  1186. defer session.Close()
  1187. return session.InsertOne(bean)
  1188. }
  1189. // Update records, bean's non-empty fields are updated contents,
  1190. // condiBean' non-empty filds are conditions
  1191. // CAUTION:
  1192. // 1.bool will defaultly be updated content nor conditions
  1193. // You should call UseBool if you have bool to use.
  1194. // 2.float32 & float64 may be not inexact as conditions
  1195. func (engine *Engine) Update(bean interface{}, condiBeans ...interface{}) (int64, error) {
  1196. session := engine.NewSession()
  1197. defer session.Close()
  1198. return session.Update(bean, condiBeans...)
  1199. }
  1200. // Delete records, bean's non-empty fields are conditions
  1201. func (engine *Engine) Delete(bean interface{}) (int64, error) {
  1202. session := engine.NewSession()
  1203. defer session.Close()
  1204. return session.Delete(bean)
  1205. }
  1206. // Get retrieve one record from table, bean's non-empty fields
  1207. // are conditions
  1208. func (engine *Engine) Get(bean interface{}) (bool, error) {
  1209. session := engine.NewSession()
  1210. defer session.Close()
  1211. return session.Get(bean)
  1212. }
  1213. // Find retrieve records from table, condiBeans's non-empty fields
  1214. // are conditions. beans could be []Struct, []*Struct, map[int64]Struct
  1215. // map[int64]*Struct
  1216. func (engine *Engine) Find(beans interface{}, condiBeans ...interface{}) error {
  1217. session := engine.NewSession()
  1218. defer session.Close()
  1219. return session.Find(beans, condiBeans...)
  1220. }
  1221. // Iterate record by record handle records from table, bean's non-empty fields
  1222. // are conditions.
  1223. func (engine *Engine) Iterate(bean interface{}, fun IterFunc) error {
  1224. session := engine.NewSession()
  1225. defer session.Close()
  1226. return session.Iterate(bean, fun)
  1227. }
  1228. // Rows return sql.Rows compatible Rows obj, as a forward Iterator object for iterating record by record, bean's non-empty fields
  1229. // are conditions.
  1230. func (engine *Engine) Rows(bean interface{}) (*Rows, error) {
  1231. session := engine.NewSession()
  1232. return session.Rows(bean)
  1233. }
  1234. // Count counts the records. bean's non-empty fields are conditions.
  1235. func (engine *Engine) Count(bean interface{}) (int64, error) {
  1236. session := engine.NewSession()
  1237. defer session.Close()
  1238. return session.Count(bean)
  1239. }
  1240. // Sum sum the records by some column. bean's non-empty fields are conditions.
  1241. func (engine *Engine) Sum(bean interface{}, colName string) (float64, error) {
  1242. session := engine.NewSession()
  1243. defer session.Close()
  1244. return session.Sum(bean, colName)
  1245. }
  1246. // Sums sum the records by some columns. bean's non-empty fields are conditions.
  1247. func (engine *Engine) Sums(bean interface{}, colNames ...string) ([]float64, error) {
  1248. session := engine.NewSession()
  1249. defer session.Close()
  1250. return session.Sums(bean, colNames...)
  1251. }
  1252. // SumsInt like Sums but return slice of int64 instead of float64.
  1253. func (engine *Engine) SumsInt(bean interface{}, colNames ...string) ([]int64, error) {
  1254. session := engine.NewSession()
  1255. defer session.Close()
  1256. return session.SumsInt(bean, colNames...)
  1257. }
  1258. // ImportFile SQL DDL file
  1259. func (engine *Engine) ImportFile(ddlPath string) ([]sql.Result, error) {
  1260. file, err := os.Open(ddlPath)
  1261. if err != nil {
  1262. return nil, err
  1263. }
  1264. defer file.Close()
  1265. return engine.Import(file)
  1266. }
  1267. // Import SQL DDL from io.Reader
  1268. func (engine *Engine) Import(r io.Reader) ([]sql.Result, error) {
  1269. var results []sql.Result
  1270. var lastError error
  1271. scanner := bufio.NewScanner(r)
  1272. semiColSpliter := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
  1273. if atEOF && len(data) == 0 {
  1274. return 0, nil, nil
  1275. }
  1276. if i := bytes.IndexByte(data, ';'); i >= 0 {
  1277. return i + 1, data[0:i], nil
  1278. }
  1279. // If we're at EOF, we have a final, non-terminated line. Return it.
  1280. if atEOF {
  1281. return len(data), data, nil
  1282. }
  1283. // Request more data.
  1284. return 0, nil, nil
  1285. }
  1286. scanner.Split(semiColSpliter)
  1287. for scanner.Scan() {
  1288. query := strings.Trim(scanner.Text(), " \t\n\r")
  1289. if len(query) > 0 {
  1290. engine.logSQL(query)
  1291. result, err := engine.DB().Exec(query)
  1292. results = append(results, result)
  1293. if err != nil {
  1294. return nil, err
  1295. //lastError = err
  1296. }
  1297. }
  1298. }
  1299. return results, lastError
  1300. }
  1301. // TZTime change one time to xorm time location
  1302. func (engine *Engine) TZTime(t time.Time) time.Time {
  1303. if !t.IsZero() { // if time is not initialized it's not suitable for Time.In()
  1304. return t.In(engine.TZLocation)
  1305. }
  1306. return t
  1307. }
  1308. // NowTime return current time
  1309. func (engine *Engine) NowTime(sqlTypeName string) interface{} {
  1310. t := time.Now()
  1311. return engine.FormatTime(sqlTypeName, t)
  1312. }
  1313. // NowTime2 return current time
  1314. func (engine *Engine) NowTime2(sqlTypeName string) (interface{}, time.Time) {
  1315. t := time.Now()
  1316. return engine.FormatTime(sqlTypeName, t), t
  1317. }
  1318. // FormatTime format time
  1319. func (engine *Engine) FormatTime(sqlTypeName string, t time.Time) (v interface{}) {
  1320. return engine.formatTime(engine.TZLocation, sqlTypeName, t)
  1321. }
  1322. func (engine *Engine) formatColTime(col *core.Column, t time.Time) (v interface{}) {
  1323. if col.DisableTimeZone {
  1324. return engine.formatTime(nil, col.SQLType.Name, t)
  1325. } else if col.TimeZone != nil {
  1326. return engine.formatTime(col.TimeZone, col.SQLType.Name, t)
  1327. }
  1328. return engine.formatTime(engine.TZLocation, col.SQLType.Name, t)
  1329. }
  1330. func (engine *Engine) formatTime(tz *time.Location, sqlTypeName string, t time.Time) (v interface{}) {
  1331. if engine.dialect.DBType() == core.ORACLE {
  1332. return t
  1333. }
  1334. if tz != nil {
  1335. t = t.In(tz)
  1336. } else {
  1337. t = engine.TZTime(t)
  1338. }
  1339. switch sqlTypeName {
  1340. case core.Time:
  1341. s := t.Format("2006-01-02 15:04:05") //time.RFC3339
  1342. v = s[11:19]
  1343. case core.Date:
  1344. v = t.Format("2006-01-02")
  1345. case core.DateTime, core.TimeStamp:
  1346. if engine.dialect.DBType() == "ql" {
  1347. v = t
  1348. } else if engine.dialect.DBType() == "sqlite3" {
  1349. v = t.UTC().Format("2006-01-02 15:04:05")
  1350. } else {
  1351. v = t.Format("2006-01-02 15:04:05")
  1352. }
  1353. case core.TimeStampz:
  1354. if engine.dialect.DBType() == core.MSSQL {
  1355. v = t.Format("2006-01-02T15:04:05.9999999Z07:00")
  1356. } else if engine.DriverName() == "mssql" {
  1357. v = t
  1358. } else {
  1359. v = t.Format(time.RFC3339Nano)
  1360. }
  1361. case core.BigInt, core.Int:
  1362. v = t.Unix()
  1363. default:
  1364. v = t
  1365. }
  1366. return
  1367. }
  1368. // Unscoped always disable struct tag "deleted"
  1369. func (engine *Engine) Unscoped() *Session {
  1370. session := engine.NewSession()
  1371. session.IsAutoClose = true
  1372. return session.Unscoped()
  1373. }