数据库操作
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

816 lines
18 KiB

  1. package dbquery
  2. /**
  3. * 事务操作
  4. */
  5. import (
  6. "database/sql"
  7. "errors"
  8. "log"
  9. "strconv"
  10. "strings"
  11. "git.tetele.net/tgo/helper"
  12. )
  13. type TxQuery struct {
  14. dbname string
  15. table string
  16. alias string
  17. title string
  18. where []string
  19. where_or []string
  20. join [][]string //[["tablea as a","a.id=b.id","left"]]
  21. data []string
  22. value []interface{}
  23. save_data []map[string]interface{} //批量操作的数据[["title":"a","num":1,],["title":"a","num":1,]]
  24. upd_field []string // 批量更新时需要更新的字段,为空时按除id外的字段进行更新
  25. orderby string
  26. groupby string
  27. having string
  28. page int
  29. page_size int
  30. stmt *sql.Stmt
  31. conn *sql.DB
  32. tx *sql.Tx
  33. debug bool
  34. }
  35. func NewTxQuery(t ...string) *TxQuery {
  36. var conn_type *sql.DB = DB
  37. if len(t) > 0 {
  38. switch t[0] {
  39. case "mysql":
  40. conn_type = DB
  41. case "mssql": //sql server
  42. conn_type = MSDB_CONN
  43. }
  44. }
  45. tx, err := conn_type.Begin()
  46. if err != nil {
  47. log.Println("start tx begin error", err)
  48. }
  49. return &TxQuery{
  50. conn: conn_type,
  51. tx: tx,
  52. }
  53. }
  54. func (this *TxQuery) Conn(conn *sql.DB) *TxQuery {
  55. this.conn = conn
  56. return this
  57. }
  58. func (this *TxQuery) Db(dbname string) *TxQuery {
  59. this.dbname = dbname
  60. return this
  61. }
  62. func (this *TxQuery) Table(tablename string) *TxQuery {
  63. this.table = tablename
  64. return this
  65. }
  66. func (this *TxQuery) Alias(tablename string) *TxQuery {
  67. this.alias = tablename
  68. return this
  69. }
  70. func (this *TxQuery) Title(title string) *TxQuery {
  71. this.title = title
  72. return this
  73. }
  74. func (this *TxQuery) Page(page int) *TxQuery {
  75. this.page = page
  76. return this
  77. }
  78. func (this *TxQuery) PageSize(page_num int) *TxQuery {
  79. this.page_size = page_num
  80. return this
  81. }
  82. func (this *TxQuery) Orderby(orderby string) *TxQuery {
  83. this.orderby = orderby
  84. return this
  85. }
  86. func (this *TxQuery) Groupby(groupby string) *TxQuery {
  87. this.groupby = groupby
  88. return this
  89. }
  90. func (this *TxQuery) Having(having string) *TxQuery {
  91. this.having = having
  92. return this
  93. }
  94. func (this *TxQuery) Where(where string) *TxQuery {
  95. this.where = append(this.where, where)
  96. return this
  97. }
  98. func (this *TxQuery) Wheres(wheres []string) *TxQuery {
  99. if len(wheres) > 0 {
  100. this.where = append(this.where, wheres...)
  101. }
  102. return this
  103. }
  104. func (this *TxQuery) WhereOr(where string) *TxQuery {
  105. this.where_or = append(this.where_or, where)
  106. return this
  107. }
  108. func (this *TxQuery) Value(value interface{}) *TxQuery {
  109. this.value = append(this.value, value)
  110. return this
  111. }
  112. func (this *TxQuery) SaveData(value map[string]interface{}) *TxQuery {
  113. this.save_data = append(this.save_data, value)
  114. return this
  115. }
  116. func (this *TxQuery) SaveDatas(value []map[string]interface{}) *TxQuery {
  117. this.save_data = append(this.save_data, value...)
  118. return this
  119. }
  120. func (this *TxQuery) UpdField(value string) *TxQuery {
  121. this.upd_field = append(this.upd_field, value)
  122. return this
  123. }
  124. func (this *TxQuery) UpdFields(value []string) *TxQuery {
  125. this.upd_field = append(this.upd_field, value...)
  126. return this
  127. }
  128. func (this *TxQuery) Values(values []interface{}) *TxQuery {
  129. this.value = append(this.value, values...)
  130. return this
  131. }
  132. func (this *TxQuery) Join(join []string) *TxQuery {
  133. this.join = append(this.join, join)
  134. return this
  135. }
  136. func (this *TxQuery) Data(data string) *TxQuery {
  137. this.data = append(this.data, data)
  138. return this
  139. }
  140. func (this *TxQuery) Datas(datas []string) *TxQuery {
  141. this.data = append(this.data, datas...)
  142. return this
  143. }
  144. func (this *TxQuery) Debug(debug bool) *TxQuery {
  145. this.debug = debug
  146. return this
  147. }
  148. /*
  149. * 清理上次查询
  150. */
  151. func (this *TxQuery) Clean() *TxQuery {
  152. this.title = ""
  153. this.where = this.where[0:0]
  154. this.where_or = this.where_or[0:0]
  155. this.join = this.join[0:0]
  156. this.data = this.data[0:0]
  157. this.value = this.value[0:0]
  158. this.orderby = ""
  159. this.groupby = ""
  160. this.page = 0
  161. this.page_size = 0
  162. this.save_data = this.save_data[0:0]
  163. this.upd_field = this.upd_field[0:0]
  164. this.having = ""
  165. return this
  166. }
  167. //构造子查询
  168. func (this *TxQuery) BuildSelectSql() (map[string]interface{}, error) {
  169. if this.dbname == "" && this.table == "" {
  170. return nil, errors.New("参数错误,没有数据表")
  171. }
  172. var table = ""
  173. if strings.Contains(this.table, "select ") {
  174. table = this.table
  175. } else {
  176. table = getTableName(this.dbname, this.table)
  177. }
  178. var sql, title string
  179. if this.title != "" {
  180. title = this.title
  181. } else {
  182. title = "*"
  183. }
  184. sql = helper.StringJoin("select ", title)
  185. if this.alias != "" {
  186. table = helper.StringJoin(table, " as ", this.alias)
  187. }
  188. sql = helper.StringJoin(sql, " from ", table)
  189. if len(this.join) > 0 {
  190. for _, joinitem := range this.join {
  191. if len(joinitem) < 2 {
  192. continue
  193. }
  194. if len(joinitem) == 3 {
  195. sql = helper.StringJoin(sql, " ", joinitem[2], " join ", getTableName(this.dbname, joinitem[0]), " on ", joinitem[1])
  196. } else { //默认左连接
  197. sql = helper.StringJoin(sql, " left join ", getTableName(this.dbname, joinitem[0]), " on ", joinitem[1])
  198. }
  199. }
  200. }
  201. if len(this.where) > 0 || len(this.where_or) > 0 {
  202. sql = helper.StringJoin(sql, " where ")
  203. }
  204. if len(this.where) > 0 {
  205. sql = helper.StringJoin(sql, " (", strings.Join(this.where, " and "), " ) ")
  206. }
  207. if len(this.where_or) > 0 {
  208. if len(this.where) > 0 {
  209. sql = helper.StringJoin(sql, " or ", strings.Join(this.where_or, " or "))
  210. } else {
  211. sql = helper.StringJoin(sql, strings.Join(this.where_or, " or "))
  212. }
  213. }
  214. if this.groupby != "" {
  215. sql = helper.StringJoin(sql, " group by ", this.groupby)
  216. }
  217. if this.having != "" {
  218. sql = helper.StringJoin(sql, " having ", this.having)
  219. }
  220. if this.orderby != "" {
  221. sql = helper.StringJoin(sql, " order by ", this.orderby)
  222. }
  223. if this.page > 0 || this.page_size > 0 {
  224. if this.page < 1 {
  225. this.page = 1
  226. }
  227. if this.page_size < 1 {
  228. this.page_size = 10
  229. }
  230. from := strconv.Itoa((this.page - 1) * this.page_size)
  231. offset := strconv.Itoa(this.page_size)
  232. if from != "" && offset != "" {
  233. sql = helper.StringJoin(sql, " limit ", from, " , ", offset)
  234. }
  235. }
  236. if this.debug {
  237. log.Println("query sql:", sql, this.value)
  238. }
  239. condition_len := 0 //所有条件数
  240. for _, ch2 := range sql {
  241. if string(ch2) == "?" {
  242. condition_len++
  243. }
  244. }
  245. if condition_len != len(this.value) {
  246. return nil, errors.New("参数错误,条件值错误")
  247. }
  248. return map[string]interface{}{
  249. "sql": sql,
  250. "value": this.value,
  251. }, nil
  252. }
  253. //获取表格信息
  254. func (this *TxQuery) GetTableInfo(table string) (map[string]interface{}, error) {
  255. field := []string{
  256. "COLUMN_NAME", //字段名
  257. "COLUMN_DEFAULT", //默认值
  258. "DATA_TYPE", //数据类型
  259. "COLUMN_TYPE", //数据类型+长度
  260. "COLUMN_COMMENT", //备注
  261. "IS_NULLABLE", //是否为空
  262. }
  263. sql := "select `" + strings.Join(field, "`,`") + "` from information_schema.COLUMNS where table_name = ? and table_schema = ?"
  264. stmtSql, err := this.tx.Prepare(sql)
  265. if err != nil {
  266. return nil, err
  267. }
  268. list, err := StmtForQueryList(stmtSql, []interface{}{table, this.dbname})
  269. if err != nil {
  270. return nil, err
  271. }
  272. rows := make([]interface{}, 0, len(list))
  273. fieldName := make([]string, 0, len(list))
  274. for _, item := range list {
  275. info := map[string]interface{}{
  276. "name": "",
  277. "column_type": "",
  278. "is_null": true,
  279. "data_type": "",
  280. "comment": "",
  281. "default": "",
  282. }
  283. for _, k := range field {
  284. index := helper.StrFirstToUpper(k)
  285. if v, ok := item[index]; ok {
  286. switch k {
  287. case "COLUMN_NAME":
  288. info["name"] = v
  289. case "COLUMN_DEFAULT":
  290. info["default"] = v
  291. case "DATA_TYPE":
  292. info["data_type"] = v
  293. case "COLUMN_TYPE":
  294. info["column_type"] = helper.ToInt64(v)
  295. case "COLUMN_COMMENT":
  296. info["comment"] = helper.ToInt64(v)
  297. case "IS_NULLABLE":
  298. if v == "NO" {
  299. info["is_null"] = false
  300. }
  301. }
  302. }
  303. }
  304. name := helper.ToStr(info["name"])
  305. if name != "" {
  306. rows = append(rows, info)
  307. fieldName = append(fieldName, name)
  308. }
  309. }
  310. return map[string]interface{}{
  311. "field": fieldName,
  312. "list": rows,
  313. }, nil
  314. }
  315. // 拼查询sql
  316. func (this *TxQuery) QueryStmt() error {
  317. res := map[string]interface{}{}
  318. res, err = this.BuildSelectSql()
  319. if err != nil {
  320. return err
  321. }
  322. sql := helper.ToStr(res["sql"])
  323. stmt, err = this.tx.Prepare(sql + " FOR UPDATE")
  324. if err != nil {
  325. return err
  326. }
  327. this.stmt = stmt
  328. return nil
  329. }
  330. // 拼更新sql
  331. func (this *TxQuery) UpdateStmt() error {
  332. if this.dbname == "" && this.table == "" {
  333. return errors.New("参数错误,没有数据表")
  334. }
  335. if len(this.where) < 1 {
  336. return errors.New("参数错误,缺少条件")
  337. }
  338. dbName := getTableName(this.dbname, this.table)
  339. var sql string
  340. sql = helper.StringJoin("update ", dbName, " set ", strings.Join(this.data, " , "))
  341. sql = helper.StringJoin(sql, " where ", strings.Join(this.where, " and "))
  342. if this.debug {
  343. log.Println("update sql:", sql, this.value)
  344. }
  345. condition_len := 0 //所有条件数
  346. for _, ch2 := range sql {
  347. if string(ch2) == "?" {
  348. condition_len++
  349. }
  350. }
  351. if condition_len != len(this.value) {
  352. return errors.New("参数错误,条件值错误")
  353. }
  354. stmt, err = this.tx.Prepare(sql)
  355. if err != nil {
  356. return err
  357. }
  358. this.stmt = stmt
  359. return nil
  360. }
  361. // 拼批量存在更新不存在插入sql
  362. func (this *TxQuery) UpdateAllStmt() error {
  363. if this.dbname == "" && this.table == "" {
  364. return errors.New("参数错误,没有数据表")
  365. }
  366. dbName := getTableName(this.dbname, this.table)
  367. var sql string
  368. var dataSql []string //一组用到的占位字符
  369. var valSql []string //占位字符组
  370. var updSql []string //更新字段的sql
  371. var updFieldLen = len(this.upd_field) //需要更新的字段数量,为0时更新除id外添加值
  372. dataLen := len(this.save_data)
  373. if dataLen > 0 {
  374. //批量操作
  375. this.data = this.data[0:0]
  376. this.value = this.value[0:0]
  377. var dataSqlText string //占位字符组
  378. for i := 0; i < dataLen; i++ {
  379. if i == 0 {
  380. //第一组时分配变量空间
  381. fieldLen := len(this.save_data[i])
  382. this.data = make([]string, 0, fieldLen)
  383. dataSql = make([]string, 0, fieldLen)
  384. this.value = make([]interface{}, 0, fieldLen*dataLen)
  385. valSql = make([]string, 0, dataLen)
  386. switch updFieldLen {
  387. case 0:
  388. //预览创建数据的长度
  389. updSql = make([]string, 0, fieldLen)
  390. default:
  391. //按照需要更新字段数长度
  392. updSql = make([]string, 0, updFieldLen)
  393. for _, k := range this.upd_field {
  394. updSql = append(updSql, k+"=values("+k+")") //存储需要更新的字段
  395. }
  396. }
  397. for k := range this.save_data[i] {
  398. this.data = append(this.data, k) //存储添加的字段
  399. dataSql = append(dataSql, "?") //存储需要的占位符
  400. if updFieldLen == 0 && k != "id" {
  401. updSql = append(updSql, k+"=values("+k+")") //存储需要更新的字段
  402. }
  403. }
  404. dataSqlText = strings.Join(dataSql, ",") //组成每组占位字符格式
  405. }
  406. for j := 0; j < len(this.data); j++ {
  407. this.value = append(this.value, this.save_data[i][this.data[j]]) //存储值
  408. }
  409. valSql = append(valSql, "("+dataSqlText+")") //组成占位字符组
  410. }
  411. } else {
  412. //添加一条(原理同上)
  413. fieldLen := len(this.data)
  414. dataSql = make([]string, 0, fieldLen)
  415. valSql = make([]string, 0, 1)
  416. switch updFieldLen {
  417. case 0:
  418. updSql = make([]string, 0, fieldLen)
  419. default:
  420. updSql = make([]string, 0, updFieldLen)
  421. for _, k := range this.upd_field {
  422. updSql = append(updSql, k+"=values("+k+")")
  423. }
  424. }
  425. for i := 0; i < fieldLen; i++ {
  426. dataSql = append(dataSql, "?")
  427. if updFieldLen == 0 && this.data[i] != "id" {
  428. updSql = append(updSql, this.data[i]+"=values("+this.data[i]+")")
  429. }
  430. }
  431. if updFieldLen > 0 {
  432. for _, k := range this.upd_field {
  433. updSql = append(updSql, k+"=values("+k+")")
  434. }
  435. }
  436. valSql = append(valSql, "("+strings.Join(dataSql, " , ")+")")
  437. }
  438. if len(this.data) == 0 {
  439. return errors.New("参数错误,没有字段值")
  440. }
  441. if len(this.value) == 0 {
  442. return errors.New("参数错误,条件值错误")
  443. }
  444. setText := " values "
  445. if len(valSql) > 1 {
  446. setText = " value "
  447. }
  448. sql = helper.StringJoin("insert into ", dbName, " (", strings.Join(this.data, " , "), ")", setText, strings.Join(valSql, ","), " ON DUPLICATE KEY UPDATE ", strings.Join(updSql, " , "))
  449. if this.debug {
  450. log.Println("insert on duplicate key update sql:", sql, this.value)
  451. }
  452. conditionLen := 0 //所有条件数
  453. for _, ch2 := range sql {
  454. if string(ch2) == "?" {
  455. conditionLen++
  456. }
  457. }
  458. if conditionLen != len(this.value) {
  459. return errors.New("参数错误,条件值数量不匹配")
  460. }
  461. stmt, err = this.tx.Prepare(sql)
  462. if err != nil {
  463. return err
  464. }
  465. this.stmt = stmt
  466. return nil
  467. }
  468. // 拼插入sql
  469. func (this *TxQuery) CreateStmt() error {
  470. if this.dbname == "" && this.table == "" {
  471. return errors.New("参数错误,没有数据表")
  472. }
  473. dbName := getTableName(this.dbname, this.table)
  474. var sql string
  475. sql = helper.StringJoin("insert into ", dbName, " set ", strings.Join(this.data, " , "))
  476. if this.debug {
  477. log.Println("insert sql:", sql, this.value)
  478. }
  479. condition_len := 0 //所有条件数
  480. for _, ch2 := range sql {
  481. if string(ch2) == "?" {
  482. condition_len++
  483. }
  484. }
  485. if condition_len != len(this.value) {
  486. return errors.New("参数错误,条件值错误")
  487. }
  488. stmt, err = this.tx.Prepare(sql)
  489. if err != nil {
  490. return err
  491. }
  492. this.stmt = stmt
  493. return nil
  494. }
  495. // 拼批量插入sql
  496. func (this *TxQuery) CreateAllStmt() error {
  497. if this.dbname == "" && this.table == "" {
  498. return errors.New("参数错误,没有数据表")
  499. }
  500. dbName := getTableName(this.dbname, this.table)
  501. var sql string
  502. var dataSql []string //一组用到的占位字符
  503. var valSql []string //占位字符组
  504. dataLen := len(this.save_data)
  505. if dataLen > 0 {
  506. //清空字段和值
  507. this.data = this.data[0:0]
  508. this.value = this.value[0:0]
  509. var dataSqlText string //占位字符组
  510. for i := 0; i < dataLen; i++ {
  511. if i == 0 {
  512. //第一组时分配变量空间
  513. fieldLen := len(this.save_data[i])
  514. this.data = make([]string, 0, fieldLen)
  515. dataSql = make([]string, 0, fieldLen)
  516. this.value = make([]interface{}, 0, fieldLen*dataLen)
  517. valSql = make([]string, 0, dataLen)
  518. for k := range this.save_data[i] {
  519. this.data = append(this.data, k) //存储字段
  520. dataSql = append(dataSql, "?") //存储需要的占位符
  521. }
  522. dataSqlText = strings.Join(dataSql, ",") //组成每组占位字符格式
  523. }
  524. for j := 0; j < len(this.data); j++ {
  525. this.value = append(this.value, this.save_data[i][this.data[j]]) //存储值
  526. }
  527. valSql = append(valSql, "("+dataSqlText+")") //组成占位字符组
  528. }
  529. } else {
  530. //添加一条(原理同上)
  531. fieldLen := len(this.data)
  532. dataSql = make([]string, 0, fieldLen)
  533. for i := 0; i < fieldLen; i++ {
  534. dataSql = append(dataSql, "?")
  535. }
  536. valSql = make([]string, 0, 1)
  537. valSql = append(valSql, "("+strings.Join(dataSql, " , ")+")")
  538. }
  539. if len(this.data) == 0 {
  540. return errors.New("参数错误,字段名错误")
  541. }
  542. if len(this.value) == 0 {
  543. return errors.New("参数错误,条件值错误")
  544. }
  545. //通过sql关键字优化批量操作和单个操作效率
  546. setText := " values "
  547. if len(valSql) > 1 {
  548. setText = " value "
  549. }
  550. sql = helper.StringJoin("insert into ", dbName, " (", strings.Join(this.data, " , "), ")", setText, strings.Join(valSql, ","))
  551. if len(this.value) == 0 {
  552. return errors.New("参数错误,条件值错误")
  553. }
  554. if this.debug {
  555. log.Println("insert sql:", sql, this.value)
  556. }
  557. conditionLen := 0 //所有条件数
  558. for _, ch2 := range sql {
  559. if string(ch2) == "?" {
  560. conditionLen++
  561. }
  562. }
  563. if conditionLen != len(this.value) {
  564. return errors.New("参数错误,条件值数量不匹配")
  565. }
  566. stmt, err = this.tx.Prepare(sql)
  567. if err != nil {
  568. return err
  569. }
  570. this.stmt = stmt
  571. return nil
  572. }
  573. // 拼删除sql
  574. func (this *TxQuery) DeleteStmt() error {
  575. if this.dbname == "" && this.table == "" {
  576. return errors.New("参数错误,没有数据表")
  577. }
  578. if len(this.where) < 1 {
  579. return errors.New("参数错误,缺少条件")
  580. }
  581. dbName := getTableName(this.dbname, this.table)
  582. var sql string
  583. sql = helper.StringJoin("delete from ", dbName, " where ", strings.Join(this.where, " and "))
  584. if this.page_size > 0 {
  585. sql = helper.StringJoin(sql, " limit ", strconv.Itoa(this.page_size))
  586. }
  587. if this.debug {
  588. log.Println("delete sql:", sql, this.value)
  589. }
  590. condition_len := 0 //所有条件数
  591. for _, ch2 := range sql {
  592. if string(ch2) == "?" {
  593. condition_len++
  594. }
  595. }
  596. if condition_len != len(this.value) {
  597. return errors.New("参数错误,条件值错误")
  598. }
  599. stmt, err = this.tx.Prepare(sql)
  600. if err != nil {
  601. return err
  602. }
  603. this.stmt = stmt
  604. return nil
  605. }
  606. /**
  607. * 执行查询列表
  608. * return list error
  609. */
  610. func (this *TxQuery) Select() ([]map[string]string, error) {
  611. err := this.QueryStmt()
  612. if err != nil {
  613. return []map[string]string{}, err
  614. }
  615. if this.stmt == nil {
  616. return []map[string]string{}, errors.New("缺少必要参数")
  617. }
  618. return StmtForQueryList(this.stmt, this.value)
  619. }
  620. /**
  621. * 执行查询一条数据
  622. * return row error
  623. */
  624. func (this *TxQuery) Find() (map[string]string, error) {
  625. this.page = 1
  626. this.page_size = 1
  627. err := this.QueryStmt()
  628. if err != nil {
  629. return map[string]string{}, err
  630. }
  631. if this.stmt == nil {
  632. return nil, errors.New("缺少必要参数")
  633. }
  634. return StmtForQueryRow(this.stmt, this.value)
  635. }
  636. /**
  637. * 执行更新
  638. * return is_updated error
  639. */
  640. func (this *TxQuery) Update() (int64, error) {
  641. err := this.UpdateStmt()
  642. if err != nil {
  643. return 0, err
  644. }
  645. return StmtForUpdateExec(this.stmt, this.value)
  646. }
  647. // UpdateAll 批量更新(根据唯一键判断存在则更新,不存在则创建)
  648. func (this *TxQuery) UpdateAll() (int64, error) {
  649. err := this.UpdateAllStmt()
  650. if err != nil {
  651. return 0, err
  652. }
  653. return StmtForUpdateExec(this.stmt, this.value)
  654. }
  655. /**
  656. * 执行删除
  657. * return is_delete error
  658. */
  659. func (this *TxQuery) Delete() (int64, error) {
  660. err := this.DeleteStmt()
  661. if err != nil {
  662. return 0, err
  663. }
  664. return StmtForUpdateExec(this.stmt, this.value)
  665. }
  666. /**
  667. * 执行写入
  668. * return is_insert error
  669. */
  670. func (this *TxQuery) Create() (int64, error) {
  671. err := this.CreateStmt()
  672. if err != nil {
  673. return 0, err
  674. }
  675. return StmtForInsertExec(this.stmt, this.value)
  676. }
  677. /**
  678. * 执行批量写入
  679. * return is_insert error
  680. */
  681. func (this *TxQuery) CreateAll() (int64, error) {
  682. err := this.CreateAllStmt()
  683. if err != nil {
  684. return 0, err
  685. }
  686. return StmtForInsertExec(this.stmt, this.value)
  687. }
  688. /**
  689. * 提交
  690. */
  691. func (this *TxQuery) Commit() error {
  692. return this.tx.Commit()
  693. }
  694. /**
  695. * 回滚
  696. */
  697. func (this *TxQuery) Rollback() error {
  698. return this.tx.Rollback()
  699. }