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