github.com/wanlay/gorm-dm8@v1.0.5/dmr/u.go (about) 1 /* 2 * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 * All rights reserved. 4 */ 5 package dmr 6 7 import ( 8 "container/list" 9 "context" 10 "database/sql" 11 "database/sql/driver" 12 "fmt" 13 "io" 14 "math/big" 15 "reflect" 16 "strconv" 17 "strings" 18 "time" 19 20 "github.com/wanlay/gorm-dm8/dmr/util" 21 ) 22 23 const ( 24 BIND_IN byte = 0x01 25 26 BIND_OUT byte = 0x10 27 ) 28 29 var rp = newRsPool() 30 31 type DmStatement struct { 32 filterable 33 34 dmConn *DmConnection 35 rsMap map[int16]*innerRows 36 inUse bool 37 innerUsed bool 38 39 innerExec bool 40 41 id int32 42 43 cursorName string 44 45 readBaseColName bool 46 47 execInfo *execRetInfo 48 49 resultSetType int 50 51 resultSetConcurrency int 52 53 resultSetHoldability int 54 55 nativeSql string 56 57 maxFieldSize int 58 59 maxRows int64 60 61 escapeProcessing bool 62 63 queryTimeout int32 64 65 fetchDirection int 66 67 fetchSize int 68 69 cursorUpdateRow int64 70 71 closeOnCompletion bool 72 73 isBatch bool 74 75 closed bool 76 77 columns []column 78 79 params []parameter 80 81 paramCount int32 82 83 curRowBindIndicator []byte 84 85 preExec bool 86 } 87 88 type stmtPoolInfo struct { 89 id int32 90 91 cursorName string 92 93 readBaseColName bool 94 } 95 96 type rsPoolKey struct { 97 dbGuid string 98 currentSchema string 99 sql string 100 paramCount int 101 } 102 103 func newRsPoolKey(stmt *DmStatement, sql string) rsPoolKey { 104 rpk := new(rsPoolKey) 105 rpk.dbGuid = stmt.dmConn.Guid 106 rpk.currentSchema = stmt.dmConn.Schema 107 rpk.paramCount = int(stmt.paramCount) 108 109 rpk.sql = sql 110 return *rpk 111 } 112 113 func (key rsPoolKey) equals(destKey rsPoolKey) bool { 114 return key.dbGuid == destKey.dbGuid && 115 key.currentSchema == destKey.currentSchema && 116 key.sql == destKey.sql && 117 key.paramCount == destKey.paramCount 118 119 } 120 121 type rsPoolValue struct { 122 m_lastChkTime int 123 m_TbIds []int32 124 m_TbTss []int64 125 execInfo *execRetInfo 126 } 127 128 func newRsPoolValue(execInfo *execRetInfo) rsPoolValue { 129 rpv := new(rsPoolValue) 130 rpv.execInfo = execInfo 131 rpv.m_lastChkTime = time.Now().Nanosecond() 132 copy(rpv.m_TbIds, execInfo.tbIds) 133 copy(rpv.m_TbTss, execInfo.tbTss) 134 return *rpv 135 } 136 137 func (rpv rsPoolValue) refreshed(conn *DmConnection) (bool, error) { 138 139 if conn.dmConnector.rsRefreshFreq == 0 { 140 return false, nil 141 } 142 143 if rpv.m_lastChkTime+conn.dmConnector.rsRefreshFreq*int(time.Second) > time.Now().Nanosecond() { 144 return false, nil 145 } 146 147 tss, err := conn.Access.Dm_build_482(interface{}(rpv.m_TbIds).([]uint32)) 148 if err != nil { 149 return false, err 150 } 151 rpv.m_lastChkTime = time.Now().Nanosecond() 152 153 var tbCount int 154 if tss != nil { 155 tbCount = len(tss) 156 } 157 158 if tbCount != len(rpv.m_TbTss) { 159 return true, nil 160 } 161 162 for i := 0; i < tbCount; i++ { 163 if rpv.m_TbTss[i] != tss[i] { 164 return true, nil 165 } 166 167 } 168 return false, nil 169 } 170 171 func (rpv rsPoolValue) getResultSet(stmt *DmStatement) *innerRows { 172 destDatas := rpv.execInfo.rsDatas 173 var totalRows int 174 if rpv.execInfo.rsDatas != nil { 175 totalRows = len(rpv.execInfo.rsDatas) 176 } 177 178 if stmt.maxRows > 0 && stmt.maxRows < int64(totalRows) { 179 destDatas = make([][][]byte, stmt.maxRows) 180 copy(destDatas[:len(destDatas)], rpv.execInfo.rsDatas[:len(destDatas)]) 181 } 182 183 rs := newLocalInnerRows(stmt, stmt.columns, destDatas) 184 rs.id = 1 185 return rs 186 } 187 188 func (rpv rsPoolValue) getDataLen() int { 189 return rpv.execInfo.rsSizeof 190 } 191 192 type rsPool struct { 193 rsMap map[rsPoolKey]rsPoolValue 194 rsList *list.List 195 totalDataLen int 196 } 197 198 func newRsPool() *rsPool { 199 rp := new(rsPool) 200 rp.rsMap = make(map[rsPoolKey]rsPoolValue, 100) 201 rp.rsList = list.New() 202 return rp 203 } 204 205 func (rp *rsPool) removeInList(key rsPoolKey) { 206 for e := rp.rsList.Front(); e != nil && e.Value.(rsPoolKey).equals(key); e = e.Next() { 207 rp.rsList.Remove(e) 208 } 209 } 210 211 func (rp *rsPool) put(stmt *DmStatement, sql string, execInfo *execRetInfo) { 212 var dataLen int 213 if execInfo != nil { 214 dataLen = execInfo.rsSizeof 215 } 216 217 cacheSize := stmt.dmConn.dmConnector.rsCacheSize * 1024 * 1024 218 219 for rp.totalDataLen+dataLen > cacheSize { 220 if rp.totalDataLen == 0 { 221 return 222 } 223 224 lk := rp.rsList.Back().Value.(rsPoolKey) 225 rp.totalDataLen -= rp.rsMap[lk].getDataLen() 226 rp.rsList.Remove(rp.rsList.Back()) 227 delete(rp.rsMap, rp.rsList.Back().Value.(rsPoolKey)) 228 } 229 230 key := newRsPoolKey(stmt, sql) 231 value := newRsPoolValue(execInfo) 232 233 if _, ok := rp.rsMap[key]; !ok { 234 rp.rsList.PushFront(key) 235 } else { 236 rp.removeInList(key) 237 rp.rsList.PushFront(key) 238 } 239 240 rp.rsMap[key] = value 241 rp.totalDataLen += dataLen 242 } 243 244 func (rp *rsPool) get(stmt *DmStatement, sql string) (*rsPoolValue, error) { 245 key := newRsPoolKey(stmt, sql) 246 247 v, ok := rp.rsMap[key] 248 if ok { 249 b, err := v.refreshed(stmt.dmConn) 250 if err != nil { 251 return nil, err 252 } 253 254 if b { 255 rp.removeInList(key) 256 delete(rp.rsMap, key) 257 return nil, nil 258 } 259 260 rp.removeInList(key) 261 rp.rsList.PushFront(key) 262 return &v, nil 263 } else { 264 return nil, nil 265 } 266 } 267 268 func (s *DmStatement) Close() error { 269 if s.closed { 270 return nil 271 } 272 if len(s.filterChain.filters) == 0 { 273 return s.close() 274 } 275 return s.filterChain.reset().DmStatementClose(s) 276 } 277 278 func (s *DmStatement) NumInput() int { 279 if err := s.checkClosed(); err != nil { 280 return 0 281 } 282 if len(s.filterChain.filters) == 0 { 283 return s.numInput() 284 } 285 return s.filterChain.reset().DmStatementNumInput(s) 286 } 287 288 func (s *DmStatement) Exec(args []driver.Value) (driver.Result, error) { 289 if err := s.checkClosed(); err != nil { 290 return nil, err 291 } 292 if len(s.filterChain.filters) == 0 { 293 return s.exec(args) 294 } 295 return s.filterChain.reset().DmStatementExec(s, args) 296 } 297 298 func (s *DmStatement) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) { 299 if err := s.checkClosed(); err != nil { 300 return nil, err 301 } 302 if len(s.filterChain.filters) == 0 { 303 return s.execContext(ctx, args) 304 } 305 return s.filterChain.reset().DmStatementExecContext(s, ctx, args) 306 } 307 308 func (s *DmStatement) Query(args []driver.Value) (driver.Rows, error) { 309 if err := s.checkClosed(); err != nil { 310 return nil, err 311 } 312 if len(s.filterChain.filters) == 0 { 313 return s.query(args) 314 } 315 return s.filterChain.reset().DmStatementQuery(s, args) 316 } 317 318 func (s *DmStatement) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { 319 if err := s.checkClosed(); err != nil { 320 return nil, err 321 } 322 if len(s.filterChain.filters) == 0 { 323 return s.queryContext(ctx, args) 324 } 325 return s.filterChain.reset().DmStatementQueryContext(s, ctx, args) 326 } 327 328 func (s *DmStatement) CheckNamedValue(nv *driver.NamedValue) error { 329 if len(s.filterChain.filters) == 0 { 330 return s.checkNamedValue(nv) 331 } 332 return s.filterChain.reset().DmStatementCheckNamedValue(s, nv) 333 } 334 335 func (st *DmStatement) prepare() error { 336 var err error 337 if st.dmConn.dmConnector.escapeProcess { 338 st.nativeSql, err = st.dmConn.escape(st.nativeSql, st.dmConn.dmConnector.keyWords) 339 if err != nil { 340 return err 341 } 342 } 343 344 st.execInfo, err = st.dmConn.Access.Dm_build_407(st, Dm_build_685) 345 if err != nil { 346 return err 347 } 348 st.curRowBindIndicator = make([]byte, st.paramCount) 349 return nil 350 } 351 352 func (stmt *DmStatement) close() error { 353 stmt.inUse = true 354 if stmt.dmConn.stmtPool != nil && len(stmt.dmConn.stmtPool) < stmt.dmConn.dmConnector.stmtPoolMaxSize { 355 stmt.pool() 356 return nil 357 } else { 358 return stmt.free() 359 } 360 } 361 362 func (stmt *DmStatement) numInput() int { 363 return int(stmt.paramCount) 364 } 365 366 func (stmt *DmStatement) checkNamedValue(nv *driver.NamedValue) error { 367 var err error 368 var cvt = converter{stmt.dmConn, false} 369 nv.Value, err = cvt.ConvertValue(nv.Value) 370 stmt.isBatch = cvt.isBatch 371 return err 372 } 373 374 func (stmt *DmStatement) exec(args []driver.Value) (*DmResult, error) { 375 var err error 376 377 stmt.inUse = true 378 if stmt.isBatch && len(args) > 0 { 379 var tmpArg []driver.Value 380 var arg driver.Value 381 for i := len(args) - 1; i >= 0; i-- { 382 if args[i] != nil { 383 arg = args[i] 384 break 385 } 386 } 387 for _, row := range arg.([][]interface{}) { 388 tmpArg = append(tmpArg, row) 389 } 390 err = stmt.executeBatch(tmpArg) 391 } else { 392 err = stmt.executeInner(args, Dm_build_687) 393 } 394 if err != nil { 395 return nil, err 396 } 397 return newDmResult(stmt, stmt.execInfo), nil 398 } 399 400 func (stmt *DmStatement) execContext(ctx context.Context, args []driver.NamedValue) (*DmResult, error) { 401 stmt.inUse = true 402 dargs, err := namedValueToValue(stmt, args) 403 if err != nil { 404 return nil, err 405 } 406 407 if err := stmt.dmConn.watchCancel(ctx); err != nil { 408 return nil, err 409 } 410 defer stmt.dmConn.finish() 411 412 return stmt.exec(dargs) 413 } 414 415 func (stmt *DmStatement) query(args []driver.Value) (*DmRows, error) { 416 var err error 417 stmt.inUse = true 418 err = stmt.executeInner(args, Dm_build_686) 419 if err != nil { 420 return nil, err 421 } 422 423 return newDmRows(newInnerRows(0, stmt, stmt.execInfo)), nil 424 } 425 426 func (stmt *DmStatement) queryContext(ctx context.Context, args []driver.NamedValue) (*DmRows, error) { 427 stmt.inUse = true 428 dargs, err := namedValueToValue(stmt, args) 429 if err != nil { 430 return nil, err 431 } 432 433 if err := stmt.dmConn.watchCancel(ctx); err != nil { 434 return nil, err 435 } 436 437 rows, err := stmt.query(dargs) 438 if err != nil { 439 stmt.dmConn.finish() 440 return nil, err 441 } 442 rows.finish = stmt.dmConn.finish 443 return rows, err 444 } 445 446 func NewDmStmt(conn *DmConnection, sql string) (*DmStatement, error) { 447 var s *DmStatement 448 449 if conn.stmtMap != nil && len(conn.stmtMap) > 0 { 450 for _, sv := range conn.stmtMap { 451 if !sv.inUse { 452 sv.inUse = true 453 sv.nativeSql = sql 454 s = sv 455 break 456 } 457 } 458 } 459 460 if s == nil { 461 s = new(DmStatement) 462 s.resetFilterable(&conn.filterable) 463 s.objId = -1 464 s.idGenerator = dmStmtIDGenerator 465 s.dmConn = conn 466 s.maxRows = int64(conn.dmConnector.maxRows) 467 s.nativeSql = sql 468 s.rsMap = make(map[int16]*innerRows) 469 s.inUse = true 470 s.isBatch = conn.isBatch 471 472 if conn.stmtPool != nil && len(conn.stmtPool) > 0 { 473 len := len(conn.stmtPool) 474 spi := conn.stmtPool[0] 475 copy(conn.stmtPool, conn.stmtPool[1:]) 476 conn.stmtPool = conn.stmtPool[:len-1] 477 s.id = spi.id 478 s.cursorName = spi.cursorName 479 s.readBaseColName = spi.readBaseColName 480 } else { 481 err := conn.Access.Dm_build_389(s) 482 if err != nil { 483 return nil, err 484 } 485 } 486 conn.stmtMap[s.id] = s 487 } 488 489 return s, nil 490 491 } 492 493 func (stmt *DmStatement) checkClosed() error { 494 if stmt.dmConn.closed.IsSet() { 495 return driver.ErrBadConn 496 } else if stmt.closed { 497 return ECGO_STATEMENT_HANDLE_CLOSED.throw() 498 } 499 500 return nil 501 } 502 503 func (stmt *DmStatement) pool() { 504 for _, rs := range stmt.rsMap { 505 rs.Close() 506 } 507 508 stmt.dmConn.stmtPool = append(stmt.dmConn.stmtPool, stmtPoolInfo{stmt.id, stmt.cursorName, stmt.readBaseColName}) 509 delete(stmt.dmConn.stmtMap, stmt.id) 510 stmt.inUse = false 511 stmt.closed = true 512 } 513 514 func (stmt *DmStatement) free() error { 515 for _, rs := range stmt.rsMap { 516 rs.Close() 517 } 518 519 err := stmt.dmConn.Access.Dm_build_394(int32(stmt.id)) 520 if err != nil { 521 return err 522 } 523 delete(stmt.dmConn.stmtMap, stmt.id) 524 stmt.inUse = false 525 stmt.closed = true 526 return nil 527 } 528 529 func encodeArgs(stmt *DmStatement, args []driver.Value) ([]interface{}, error) { 530 bytes := make([]interface{}, len(args), len(args)) 531 532 var err error 533 534 for i, arg := range args { 535 nextSwitch: 536 if stmt.params[i].colType == CURSOR { 537 if stmt.params[i].cursorStmt == nil { 538 stmt.params[i].cursorStmt = &DmStatement{dmConn: stmt.dmConn} 539 stmt.params[i].cursorStmt.resetFilterable(&stmt.dmConn.filterable) 540 err = stmt.params[i].cursorStmt.dmConn.Access.Dm_build_389(stmt.params[i].cursorStmt) 541 } 542 stmt.curRowBindIndicator[i] |= BIND_OUT 543 continue 544 } 545 if arg == nil { 546 if resetColType(stmt, i, NULL) { 547 bytes[i] = ParamDataEnum_Null 548 } 549 continue 550 } 551 552 switch v := arg.(type) { 553 case bool: 554 if resetColType(stmt, i, BIT) { 555 bytes[i], err = G2DB.fromBool(v, stmt.params[i], stmt.dmConn) 556 } 557 case int8: 558 if resetColType(stmt, i, TINYINT) { 559 bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn) 560 } 561 case int16: 562 if resetColType(stmt, i, SMALLINT) { 563 bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn) 564 } 565 case int32: 566 if resetColType(stmt, i, INT) { 567 bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn) 568 } 569 case int64: 570 if resetColType(stmt, i, BIGINT) { 571 bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn) 572 } 573 case int: 574 if resetColType(stmt, i, BIGINT) { 575 bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn) 576 } 577 case uint8: 578 if resetColType(stmt, i, SMALLINT) { 579 bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn) 580 } 581 case uint16: 582 if resetColType(stmt, i, INT) { 583 bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn) 584 } 585 case uint32: 586 if resetColType(stmt, i, BIGINT) { 587 bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn) 588 } 589 590 case float32: 591 if resetColType(stmt, i, REAL) { 592 bytes[i], err = G2DB.fromFloat32(v, stmt.params[i], stmt.dmConn) 593 } 594 case float64: 595 if resetColType(stmt, i, DOUBLE) { 596 bytes[i], err = G2DB.fromFloat64(float64(v), stmt.params[i], stmt.dmConn) 597 } 598 case []byte: 599 if resetColType(stmt, i, VARBINARY) { 600 bytes[i], err = G2DB.fromBytes(v, stmt.params[i], stmt.dmConn) 601 } 602 case string: 603 604 if v == "" && emptyStringToNil(stmt.params[i].colType) { 605 arg = nil 606 goto nextSwitch 607 } 608 if resetColType(stmt, i, VARCHAR) { 609 bytes[i], err = G2DB.fromString(v, stmt.params[i], stmt.dmConn) 610 } 611 case time.Time: 612 if resetColType(stmt, i, DATETIME_TZ) { 613 bytes[i], err = G2DB.fromTime(v, stmt.params[i], stmt.dmConn) 614 } 615 case DmTimestamp: 616 if resetColType(stmt, i, DATETIME_TZ) { 617 bytes[i], err = G2DB.fromTime(v.ToTime(), stmt.params[i], stmt.dmConn) 618 } 619 case DmIntervalDT: 620 if resetColType(stmt, i, INTERVAL_DT) { 621 bytes[i], err = G2DB.fromDmIntervalDT(v, stmt.params[i], stmt.dmConn) 622 } 623 case DmIntervalYM: 624 if resetColType(stmt, i, INTERVAL_YM) { 625 bytes[i], err = G2DB.fromDmdbIntervalYM(v, stmt.params[i], stmt.dmConn) 626 } 627 case DmDecimal: 628 if resetColType(stmt, i, DECIMAL) { 629 bytes[i], err = G2DB.fromDecimal(v, stmt.params[i], stmt.dmConn) 630 } 631 632 case DmBlob: 633 if resetColType(stmt, i, BLOB) { 634 bytes[i], err = G2DB.fromBlob(DmBlob(v), stmt.params[i], stmt.dmConn) 635 if err != nil { 636 return nil, err 637 } 638 } 639 case DmClob: 640 if resetColType(stmt, i, CLOB) { 641 bytes[i], err = G2DB.fromClob(DmClob(v), stmt.params[i], stmt.dmConn) 642 if err != nil { 643 return nil, err 644 } 645 } 646 case DmArray: 647 if resetColType(stmt, i, ARRAY) { 648 da := &v 649 da, err = da.create(stmt.dmConn) 650 if err != nil { 651 return nil, err 652 } 653 654 bytes[i], err = G2DB.fromArray(da, stmt.params[i], stmt.dmConn) 655 } 656 case DmStruct: 657 if resetColType(stmt, i, RECORD) { 658 ds := &v 659 ds, err = ds.create(stmt.dmConn) 660 if err != nil { 661 return nil, err 662 } 663 664 bytes[i], err = G2DB.fromStruct(ds, stmt.params[i], stmt.dmConn) 665 } 666 case sql.Out: 667 arg = v.Dest 668 goto nextSwitch 669 670 case *DmTimestamp: 671 if resetColType(stmt, i, DATETIME_TZ) { 672 bytes[i], err = G2DB.fromTime(v.ToTime(), stmt.params[i], stmt.dmConn) 673 } 674 case *DmIntervalDT: 675 if resetColType(stmt, i, INTERVAL_DT) { 676 bytes[i], err = G2DB.fromDmIntervalDT(*v, stmt.params[i], stmt.dmConn) 677 } 678 case *DmIntervalYM: 679 if resetColType(stmt, i, INTERVAL_YM) { 680 bytes[i], err = G2DB.fromDmdbIntervalYM(*v, stmt.params[i], stmt.dmConn) 681 } 682 case *DmDecimal: 683 if resetColType(stmt, i, DECIMAL) { 684 bytes[i], err = G2DB.fromDecimal(*v, stmt.params[i], stmt.dmConn) 685 } 686 case *DmBlob: 687 if resetColType(stmt, i, BLOB) { 688 bytes[i], err = G2DB.fromBlob(DmBlob(*v), stmt.params[i], stmt.dmConn) 689 } 690 case *DmClob: 691 if resetColType(stmt, i, CLOB) { 692 bytes[i], err = G2DB.fromClob(DmClob(*v), stmt.params[i], stmt.dmConn) 693 } 694 case *DmArray: 695 if resetColType(stmt, i, ARRAY) { 696 v, err = v.create(stmt.dmConn) 697 if err != nil { 698 return nil, err 699 } 700 701 bytes[i], err = G2DB.fromArray(v, stmt.params[i], stmt.dmConn) 702 } 703 case *DmStruct: 704 if resetColType(stmt, i, RECORD) { 705 v, err = v.create(stmt.dmConn) 706 if err != nil { 707 return nil, err 708 } 709 710 bytes[i], err = G2DB.fromStruct(v, stmt.params[i], stmt.dmConn) 711 } 712 case *driver.Rows: 713 if stmt.params[i].colType == CURSOR && !resetColType(stmt, i, CURSOR) && stmt.params[i].cursorStmt == nil { 714 stmt.params[i].cursorStmt = &DmStatement{dmConn: stmt.dmConn} 715 stmt.params[i].cursorStmt.resetFilterable(&stmt.dmConn.filterable) 716 err = stmt.params[i].cursorStmt.dmConn.Access.Dm_build_389(stmt.params[i].cursorStmt) 717 } 718 case io.Reader: 719 bytes[i], err = G2DB.fromReader(io.Reader(v), stmt.params[i], stmt.dmConn) 720 if err != nil { 721 return nil, err 722 } 723 default: 724 err = ECGO_UNSUPPORTED_INPARAM_TYPE.throw() 725 } 726 727 if err != nil { 728 return nil, err 729 } 730 731 } 732 733 return bytes, nil 734 } 735 736 type converter struct { 737 conn *DmConnection 738 isBatch bool 739 } 740 type decimalDecompose interface { 741 Decompose(buf []byte) (form byte, negative bool, coefficient []byte, exponent int32) 742 } 743 744 func (c *converter) ConvertValue(v interface{}) (driver.Value, error) { 745 if driver.IsValue(v) { 746 return v, nil 747 } 748 749 switch vr := v.(type) { 750 case driver.Valuer: 751 sv, err := callValuerValue(vr) 752 if err != nil { 753 return nil, err 754 } 755 756 return sv, nil 757 758 case decimalDecompose, DmDecimal, *DmDecimal, DmTimestamp, *DmTimestamp, DmIntervalDT, *DmIntervalDT, 759 DmIntervalYM, *DmIntervalYM, driver.Rows, *driver.Rows, DmArray, *DmArray, DmStruct, *DmStruct, sql.Out: 760 return vr, nil 761 case big.Int: 762 return NewDecimalFromBigInt(&vr) 763 case big.Float: 764 return NewDecimalFromBigFloat(&vr) 765 case DmClob: 766 767 if vr.connection == nil { 768 vr.connection = c.conn 769 } 770 return vr, nil 771 case DmBlob: 772 773 if vr.connection == nil { 774 vr.connection = c.conn 775 } 776 return vr, nil 777 case *DmBlob: 778 779 if vr.connection == nil { 780 vr.connection = c.conn 781 } 782 return vr, nil 783 case io.Reader: 784 return vr, nil 785 } 786 787 rv := reflect.ValueOf(v) 788 switch rv.Kind() { 789 case reflect.Ptr: 790 if rv.IsNil() { 791 return nil, nil 792 } else { 793 return c.ConvertValue(rv.Elem().Interface()) 794 } 795 case reflect.Int: 796 return rv.Int(), nil 797 case reflect.Int8: 798 return int8(rv.Int()), nil 799 case reflect.Int16: 800 return int16(rv.Int()), nil 801 case reflect.Int32: 802 return int32(rv.Int()), nil 803 case reflect.Int64: 804 return int64(rv.Int()), nil 805 case reflect.Uint8: 806 return uint8(rv.Uint()), nil 807 case reflect.Uint16: 808 return uint16(rv.Uint()), nil 809 case reflect.Uint32: 810 return uint32(rv.Uint()), nil 811 case reflect.Uint64, reflect.Uint: 812 u64 := rv.Uint() 813 if u64 >= 1<<63 { 814 bigInt := &big.Int{} 815 bigInt.SetString(strconv.FormatUint(u64, 10), 10) 816 return NewDecimalFromBigInt(bigInt) 817 } 818 return int64(u64), nil 819 case reflect.Float32: 820 return float32(rv.Float()), nil 821 case reflect.Float64: 822 return float64(rv.Float()), nil 823 case reflect.Bool: 824 return rv.Bool(), nil 825 case reflect.Slice: 826 ek := rv.Type().Elem().Kind() 827 if ek == reflect.Uint8 { 828 return rv.Bytes(), nil 829 } else if ek == reflect.Slice { 830 c.isBatch = true 831 return v, nil 832 } 833 return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek) 834 case reflect.String: 835 return rv.String(), nil 836 } 837 return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind()) 838 } 839 840 var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem() 841 842 func callValuerValue(vr driver.Valuer) (v driver.Value, err error) { 843 if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr && 844 rv.IsNil() && 845 rv.Type().Elem().Implements(valuerReflectType) { 846 return nil, nil 847 } 848 return vr.Value() 849 } 850 851 func namedValueToValue(stmt *DmStatement, named []driver.NamedValue) ([]driver.Value, error) { 852 853 dargs := make([]driver.Value, stmt.paramCount) 854 for i, _ := range dargs { 855 found := false 856 for _, nv := range named { 857 if nv.Name != "" && strings.ToUpper(nv.Name) == strings.ToUpper(stmt.params[i].name) { 858 dargs[i] = nv.Value 859 found = true 860 break 861 } 862 } 863 864 if !found && i < len(named) { 865 dargs[i] = named[i].Value 866 } 867 868 } 869 return dargs, nil 870 } 871 872 func (stmt *DmStatement) executeInner(args []driver.Value, executeType int16) (err error) { 873 874 var bytes []interface{} 875 876 if stmt.paramCount > 0 { 877 bytes, err = encodeArgs(stmt, args) 878 if err != nil { 879 return err 880 } 881 } 882 stmt.execInfo, err = stmt.dmConn.Access.Dm_build_439(stmt, bytes, false) 883 if err != nil { 884 return err 885 } 886 if stmt.execInfo.outParamDatas != nil { 887 for i, outParamData := range stmt.execInfo.outParamDatas { 888 if stmt.curRowBindIndicator[i]&BIND_OUT == BIND_OUT { 889 if outParamData == nil { 890 if arg, ok := args[i].(*driver.Rows); ok && stmt.params[i].colType == CURSOR { 891 var tmpExecInfo *execRetInfo 892 if tmpExecInfo, err = stmt.dmConn.Access.Dm_build_449(stmt.params[i].cursorStmt, 1); err != nil { 893 return err 894 } 895 if tmpExecInfo.hasResultSet { 896 *arg = newDmRows(newInnerRows(0, stmt.params[i].cursorStmt, tmpExecInfo)) 897 } else { 898 *arg = nil 899 } 900 } else { 901 args[i] = nil 902 } 903 continue 904 } 905 if args[i] == nil { 906 switch stmt.params[i].colType { 907 case BOOLEAN: 908 args[i], err = DB2G.toBool(outParamData, &stmt.params[i].column, stmt.dmConn) 909 case BIT: 910 if strings.ToLower(stmt.params[i].typeName) == "boolean" { 911 args[i], err = DB2G.toBool(outParamData, &stmt.params[i].column, stmt.dmConn) 912 } 913 914 args[i], err = DB2G.toInt8(outParamData, &stmt.params[i].column, stmt.dmConn) 915 case TINYINT: 916 args[i], err = DB2G.toInt8(outParamData, &stmt.params[i].column, stmt.dmConn) 917 case SMALLINT: 918 args[i], err = DB2G.toInt16(outParamData, &stmt.params[i].column, stmt.dmConn) 919 case INT: 920 args[i], err = DB2G.toInt32(outParamData, &stmt.params[i].column, stmt.dmConn) 921 case BIGINT: 922 args[i], err = DB2G.toInt64(outParamData, &stmt.params[i].column, stmt.dmConn) 923 case REAL: 924 args[i], err = DB2G.toFloat32(outParamData, &stmt.params[i].column, stmt.dmConn) 925 case DOUBLE: 926 args[i], err = DB2G.toFloat64(outParamData, &stmt.params[i].column, stmt.dmConn) 927 case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ: 928 args[i], err = DB2G.toTime(outParamData, &stmt.params[i].column, stmt.dmConn) 929 case INTERVAL_DT: 930 args[i] = newDmIntervalDTByBytes(outParamData) 931 case INTERVAL_YM: 932 args[i] = newDmIntervalYMByBytes(outParamData) 933 case DECIMAL: 934 args[i], err = DB2G.toDmDecimal(outParamData, &stmt.params[i].column, stmt.dmConn) 935 case BINARY, VARBINARY: 936 args[i] = util.StringUtil.BytesToHexString(outParamData, false) 937 case BLOB: 938 args[i] = DB2G.toDmBlob(outParamData, &stmt.params[i].column, stmt.dmConn) 939 case CHAR, VARCHAR2, VARCHAR: 940 args[i] = DB2G.toString(outParamData, &stmt.params[i].column, stmt.dmConn) 941 case CLOB: 942 args[i] = DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.params[i].column) 943 default: 944 err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw() 945 } 946 } else { 947 nextSwitch: 948 switch v := args[i].(type) { 949 case sql.Out: 950 args[i] = v.Dest 951 goto nextSwitch 952 case string, *string: 953 args[i] = DB2G.toString(outParamData, &stmt.params[i].column, stmt.dmConn) 954 case []byte, *[]byte: 955 args[i], err = DB2G.toBytes(outParamData, &stmt.params[i].column, stmt.dmConn) 956 case bool, *bool: 957 args[i], err = DB2G.toBool(outParamData, &stmt.params[i].column, stmt.dmConn) 958 case int8, *int8: 959 args[i], err = DB2G.toInt8(outParamData, &stmt.params[i].column, stmt.dmConn) 960 case int16, *int16: 961 args[i], err = DB2G.toInt16(outParamData, &stmt.params[i].column, stmt.dmConn) 962 case int32, *int32: 963 args[i], err = DB2G.toInt32(outParamData, &stmt.params[i].column, stmt.dmConn) 964 case int64, *int64: 965 args[i], err = DB2G.toInt64(outParamData, &stmt.params[i].column, stmt.dmConn) 966 case uint8, *uint8: 967 args[i], err = DB2G.toByte(outParamData, &stmt.params[i].column, stmt.dmConn) 968 case uint16, *uint16: 969 args[i], err = DB2G.toUInt16(outParamData, &stmt.params[i].column, stmt.dmConn) 970 case uint32, *uint32: 971 args[i], err = DB2G.toUInt32(outParamData, &stmt.params[i].column, stmt.dmConn) 972 case uint64, *uint64: 973 args[i], err = DB2G.toUInt64(outParamData, &stmt.params[i].column, stmt.dmConn) 974 case int, *int: 975 args[i], err = DB2G.toInt(outParamData, &stmt.params[i].column, stmt.dmConn) 976 case uint, *uint: 977 args[i], err = DB2G.toUInt(outParamData, &stmt.params[i].column, stmt.dmConn) 978 case float32, *float32: 979 args[i], err = DB2G.toFloat32(outParamData, &stmt.params[i].column, stmt.dmConn) 980 case float64, *float64: 981 args[i], err = DB2G.toFloat64(outParamData, &stmt.params[i].column, stmt.dmConn) 982 case time.Time, *time.Time: 983 args[i], err = DB2G.toTime(outParamData, &stmt.params[i].column, stmt.dmConn) 984 case DmTimestamp, *DmTimestamp: 985 args[i] = newDmTimestampFromBytes(outParamData, stmt.params[i].column, stmt.dmConn) 986 case DmIntervalDT, *DmIntervalDT: 987 args[i] = newDmIntervalDTByBytes(outParamData) 988 case DmIntervalYM, *DmIntervalYM: 989 args[i] = newDmIntervalYMByBytes(outParamData) 990 case DmDecimal, *DmDecimal: 991 args[i], err = DB2G.toDmDecimal(outParamData, &stmt.params[i].column, stmt.dmConn) 992 case DmBlob, *DmBlob: 993 args[i] = DB2G.toDmBlob(outParamData, &stmt.params[i].column, stmt.dmConn) 994 case DmClob, *DmClob: 995 args[i] = DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.params[i].column) 996 case *driver.Rows: 997 if stmt.params[i].colType == CURSOR { 998 var tmpExecInfo *execRetInfo 999 tmpExecInfo, err = stmt.dmConn.Access.Dm_build_449(stmt.params[i].cursorStmt, 1) 1000 if err != nil { 1001 return err 1002 } 1003 1004 if tmpExecInfo.hasResultSet { 1005 *v = newDmRows(newInnerRows(0, stmt.params[i].cursorStmt, tmpExecInfo)) 1006 } else { 1007 *v = nil 1008 } 1009 } 1010 case DmArray, *DmArray: 1011 args[i], err = TypeDataSV.bytesToArray(outParamData, nil, stmt.params[i].typeDescriptor) 1012 case DmStruct, *DmStruct: 1013 args[i], err = TypeDataSV.bytesToRecord(outParamData, nil, stmt.params[i].typeDescriptor) 1014 default: 1015 err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw() 1016 } 1017 } 1018 } 1019 } 1020 } 1021 1022 return err 1023 } 1024 1025 func (stmt *DmStatement) executeBatch(args []driver.Value) (err error) { 1026 1027 var bytes [][]interface{} 1028 1029 if stmt.execInfo.retSqlType == Dm_build_700 || stmt.execInfo.retSqlType == Dm_build_705 { 1030 return ECGO_INVALID_SQL_TYPE.throw() 1031 } 1032 1033 if stmt.paramCount > 0 && args != nil && len(args) > 0 { 1034 1035 if len(args) == 1 || stmt.dmConn.dmConnector.batchType == 2 || 1036 (stmt.dmConn.dmConnector.batchNotOnCall && stmt.execInfo.retSqlType == Dm_build_701) { 1037 return stmt.executeBatchByRow(args) 1038 } else { 1039 for _, arg := range args { 1040 var newArg []driver.Value 1041 for _, a := range arg.([]interface{}) { 1042 newArg = append(newArg, a) 1043 } 1044 tmpBytes, err := encodeArgs(stmt, newArg) 1045 if err != nil { 1046 return err 1047 } 1048 bytes = append(bytes, tmpBytes) 1049 } 1050 stmt.execInfo, err = stmt.dmConn.Access.Dm_build_428(stmt, bytes, stmt.preExec) 1051 } 1052 } 1053 return err 1054 } 1055 1056 func (stmt *DmStatement) executeBatchByRow(args []driver.Value) (err error) { 1057 count := len(args) 1058 stmt.execInfo = NewExceInfo() 1059 stmt.execInfo.updateCounts = make([]int64, count) 1060 var sqlErrBuilder strings.Builder 1061 for i := 0; i < count; i++ { 1062 tmpExecInfo, err := stmt.dmConn.Access.Dm_build_439(stmt, args[i].([]interface{}), stmt.preExec || i != 0) 1063 if err == nil { 1064 stmt.execInfo.union(tmpExecInfo, i, 1) 1065 } else { 1066 stmt.execInfo.updateCounts[i] = -1 1067 if stmt.dmConn.dmConnector.continueBatchOnError { 1068 sqlErrBuilder.WriteString("row[" + strconv.Itoa(i) + "]:" + err.Error() + util.LINE_SEPARATOR) 1069 } else { 1070 return ECGO_BATCH_ERROR.addDetailln(err.Error()).throw() 1071 } 1072 } 1073 } 1074 if sqlErrBuilder.Len() > 0 { 1075 return EC_BP_WITH_ERROR.addDetail(sqlErrBuilder.String()).throw() 1076 } 1077 return nil 1078 }