gitee.com/chunanyong/dm@v1.8.12/u.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 "io" 14 "math/big" 15 "reflect" 16 "strconv" 17 "strings" 18 "time" 19 20 "gitee.com/chunanyong/dm/util" 21 ) 22 23 var rp = newRsPool() 24 25 type DmStatement struct { 26 filterable 27 28 dmConn *DmConnection 29 rsMap map[int16]*innerRows 30 inUse bool 31 32 prepared bool 33 innerUsed bool 34 35 innerExec bool 36 37 id int32 38 39 cursorName string 40 41 readBaseColName bool 42 43 execInfo *execRetInfo 44 45 resultSetType int 46 47 resultSetConcurrency int 48 49 resultSetHoldability int 50 51 nativeSql string 52 53 maxFieldSize int 54 55 maxRows int64 56 57 escapeProcessing bool 58 59 queryTimeout int32 60 61 fetchDirection int 62 63 fetchSize int 64 65 cursorUpdateRow int64 66 67 closeOnCompletion bool 68 69 isBatch bool 70 71 closed bool 72 73 columns []column 74 75 serverParams []parameter 76 77 bindParams []parameter 78 79 paramCount int32 80 81 preExec bool 82 } 83 84 type stmtPoolInfo struct { 85 id int32 86 87 cursorName string 88 89 readBaseColName bool 90 } 91 92 type rsPoolKey struct { 93 dbGuid string 94 currentSchema string 95 sql string 96 paramCount int 97 } 98 99 func newRsPoolKey(stmt *DmStatement, sql string) rsPoolKey { 100 rpk := new(rsPoolKey) 101 rpk.dbGuid = stmt.dmConn.Guid 102 rpk.currentSchema = stmt.dmConn.Schema 103 rpk.paramCount = int(stmt.paramCount) 104 105 rpk.sql = sql 106 return *rpk 107 } 108 109 func (key rsPoolKey) equals(destKey rsPoolKey) bool { 110 return key.dbGuid == destKey.dbGuid && 111 key.currentSchema == destKey.currentSchema && 112 key.sql == destKey.sql && 113 key.paramCount == destKey.paramCount 114 115 } 116 117 type rsPoolValue struct { 118 m_lastChkTime int 119 m_TbIds []int32 120 m_TbTss []int64 121 execInfo *execRetInfo 122 } 123 124 func newRsPoolValue(execInfo *execRetInfo) rsPoolValue { 125 rpv := new(rsPoolValue) 126 rpv.execInfo = execInfo 127 rpv.m_lastChkTime = time.Now().Nanosecond() 128 copy(rpv.m_TbIds, execInfo.tbIds) 129 copy(rpv.m_TbTss, execInfo.tbTss) 130 return *rpv 131 } 132 133 func (rpv rsPoolValue) refreshed(conn *DmConnection) (bool, error) { 134 135 if conn.dmConnector.rsRefreshFreq == 0 { 136 return false, nil 137 } 138 139 if rpv.m_lastChkTime+conn.dmConnector.rsRefreshFreq*int(time.Second) > time.Now().Nanosecond() { 140 return false, nil 141 } 142 143 tss, err := conn.Access.Dm_build_1496(interface{}(rpv.m_TbIds).([]uint32)) 144 if err != nil { 145 return false, err 146 } 147 rpv.m_lastChkTime = time.Now().Nanosecond() 148 149 var tbCount int 150 if tss != nil { 151 tbCount = len(tss) 152 } 153 154 if tbCount != len(rpv.m_TbTss) { 155 return true, nil 156 } 157 158 for i := 0; i < tbCount; i++ { 159 if rpv.m_TbTss[i] != tss[i] { 160 return true, nil 161 } 162 163 } 164 return false, nil 165 } 166 167 func (rpv rsPoolValue) getResultSet(stmt *DmStatement) *innerRows { 168 destDatas := rpv.execInfo.rsDatas 169 var totalRows int 170 if rpv.execInfo.rsDatas != nil { 171 totalRows = len(rpv.execInfo.rsDatas) 172 } 173 174 if stmt.maxRows > 0 && stmt.maxRows < int64(totalRows) { 175 destDatas = make([][][]byte, stmt.maxRows) 176 copy(destDatas[:len(destDatas)], rpv.execInfo.rsDatas[:len(destDatas)]) 177 } 178 179 rs := newLocalInnerRows(stmt, stmt.columns, destDatas) 180 rs.id = 1 181 return rs 182 } 183 184 func (rpv rsPoolValue) getDataLen() int { 185 return rpv.execInfo.rsSizeof 186 } 187 188 type rsPool struct { 189 rsMap map[rsPoolKey]rsPoolValue 190 rsList *list.List 191 totalDataLen int 192 } 193 194 func newRsPool() *rsPool { 195 rp := new(rsPool) 196 rp.rsMap = make(map[rsPoolKey]rsPoolValue, 100) 197 rp.rsList = list.New() 198 return rp 199 } 200 201 func (rp *rsPool) removeInList(key rsPoolKey) { 202 for e := rp.rsList.Front(); e != nil && e.Value.(rsPoolKey).equals(key); e = e.Next() { 203 rp.rsList.Remove(e) 204 } 205 } 206 207 func (rp *rsPool) put(stmt *DmStatement, sql string, execInfo *execRetInfo) { 208 var dataLen int 209 if execInfo != nil { 210 dataLen = execInfo.rsSizeof 211 } 212 213 cacheSize := stmt.dmConn.dmConnector.rsCacheSize * 1024 * 1024 214 215 for rp.totalDataLen+dataLen > cacheSize { 216 if rp.totalDataLen == 0 { 217 return 218 } 219 220 lk := rp.rsList.Back().Value.(rsPoolKey) 221 rp.totalDataLen -= rp.rsMap[lk].getDataLen() 222 rp.rsList.Remove(rp.rsList.Back()) 223 delete(rp.rsMap, rp.rsList.Back().Value.(rsPoolKey)) 224 } 225 226 key := newRsPoolKey(stmt, sql) 227 value := newRsPoolValue(execInfo) 228 229 if _, ok := rp.rsMap[key]; !ok { 230 rp.rsList.PushFront(key) 231 } else { 232 rp.removeInList(key) 233 rp.rsList.PushFront(key) 234 } 235 236 rp.rsMap[key] = value 237 rp.totalDataLen += dataLen 238 } 239 240 func (rp *rsPool) get(stmt *DmStatement, sql string) (*rsPoolValue, error) { 241 key := newRsPoolKey(stmt, sql) 242 243 v, ok := rp.rsMap[key] 244 if ok { 245 b, err := v.refreshed(stmt.dmConn) 246 if err != nil { 247 return nil, err 248 } 249 250 if b { 251 rp.removeInList(key) 252 delete(rp.rsMap, key) 253 return nil, nil 254 } 255 256 rp.removeInList(key) 257 rp.rsList.PushFront(key) 258 return &v, nil 259 } else { 260 return nil, nil 261 } 262 } 263 264 func (s *DmStatement) Close() error { 265 if s.closed { 266 return nil 267 } 268 if len(s.filterChain.filters) == 0 { 269 return s.close() 270 } 271 return s.filterChain.reset().DmStatementClose(s) 272 } 273 274 func (s *DmStatement) NumInput() int { 275 if err := s.checkClosed(); err != nil { 276 return -1 277 } 278 if len(s.filterChain.filters) == 0 { 279 return s.numInput() 280 } 281 return s.filterChain.reset().DmStatementNumInput(s) 282 } 283 284 func (s *DmStatement) Exec(args []driver.Value) (driver.Result, error) { 285 if err := s.checkClosed(); err != nil { 286 return nil, err 287 } 288 if len(s.filterChain.filters) == 0 { 289 return s.exec(args) 290 } 291 return s.filterChain.reset().DmStatementExec(s, args) 292 } 293 294 func (s *DmStatement) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) { 295 if err := s.checkClosed(); err != nil { 296 return nil, err 297 } 298 if len(s.filterChain.filters) == 0 { 299 return s.execContext(ctx, args) 300 } 301 return s.filterChain.reset().DmStatementExecContext(s, ctx, args) 302 } 303 304 func (s *DmStatement) Query(args []driver.Value) (driver.Rows, error) { 305 if err := s.checkClosed(); err != nil { 306 return nil, err 307 } 308 if len(s.filterChain.filters) == 0 { 309 return s.query(args) 310 } 311 return s.filterChain.reset().DmStatementQuery(s, args) 312 } 313 314 func (s *DmStatement) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { 315 if err := s.checkClosed(); err != nil { 316 return nil, err 317 } 318 if len(s.filterChain.filters) == 0 { 319 return s.queryContext(ctx, args) 320 } 321 return s.filterChain.reset().DmStatementQueryContext(s, ctx, args) 322 } 323 324 func (s *DmStatement) CheckNamedValue(nv *driver.NamedValue) error { 325 if len(s.filterChain.filters) == 0 { 326 return s.checkNamedValue(nv) 327 } 328 return s.filterChain.reset().DmStatementCheckNamedValue(s, nv) 329 } 330 331 func (st *DmStatement) prepare() error { 332 var err error 333 if st.dmConn.dmConnector.escapeProcess { 334 st.nativeSql, err = st.dmConn.escape(st.nativeSql, st.dmConn.dmConnector.keyWords) 335 if err != nil { 336 return err 337 } 338 } 339 340 st.execInfo, err = st.dmConn.Access.Dm_build_1421(st, Dm_build_95) 341 if err != nil { 342 return err 343 } 344 st.prepared = true 345 return nil 346 } 347 348 func (stmt *DmStatement) close() error { 349 delete(stmt.dmConn.stmtMap, stmt.id) 350 if stmt.closed { 351 return nil 352 } 353 stmt.inUse = true 354 355 return stmt.free() 356 357 } 358 359 func (stmt *DmStatement) numInput() int { 360 return int(stmt.paramCount) 361 } 362 363 func (stmt *DmStatement) checkNamedValue(nv *driver.NamedValue) error { 364 var err error 365 var cvt = converter{stmt.dmConn, false} 366 nv.Value, err = cvt.ConvertValue(nv.Value) 367 stmt.isBatch = cvt.isBatch 368 return err 369 } 370 371 func (stmt *DmStatement) exec(args []driver.Value) (*DmResult, error) { 372 var err error 373 374 stmt.inUse = true 375 if stmt.isBatch && len(args) > 0 { 376 var tmpArg []driver.Value 377 var arg driver.Value 378 for i := len(args) - 1; i >= 0; i-- { 379 if args[i] != nil { 380 arg = args[i] 381 break 382 } 383 } 384 for _, row := range arg.([][]interface{}) { 385 tmpArg = append(tmpArg, row) 386 } 387 err = stmt.executeBatch(tmpArg) 388 } else { 389 err = stmt.executeInner(args, Dm_build_97) 390 } 391 if err != nil { 392 return nil, err 393 } 394 return newDmResult(stmt, stmt.execInfo), nil 395 } 396 397 func (stmt *DmStatement) execContext(ctx context.Context, args []driver.NamedValue) (*DmResult, error) { 398 stmt.inUse = true 399 dargs, err := namedValueToValue(stmt, args) 400 if err != nil { 401 return nil, err 402 } 403 404 if err := stmt.dmConn.watchCancel(ctx); err != nil { 405 return nil, err 406 } 407 defer stmt.dmConn.finish() 408 409 return stmt.exec(dargs) 410 } 411 412 func (stmt *DmStatement) query(args []driver.Value) (*DmRows, error) { 413 var err error 414 stmt.inUse = true 415 err = stmt.executeInner(args, Dm_build_96) 416 if err != nil { 417 return nil, err 418 } 419 420 if stmt.execInfo.hasResultSet { 421 return newDmRows(newInnerRows(0, stmt, stmt.execInfo)), nil 422 } else { 423 return newDmRows(newLocalInnerRows(stmt, nil, nil)), nil 424 } 425 } 426 427 func (stmt *DmStatement) queryContext(ctx context.Context, args []driver.NamedValue) (*DmRows, error) { 428 stmt.inUse = true 429 dargs, err := namedValueToValue(stmt, args) 430 if err != nil { 431 return nil, err 432 } 433 434 if err := stmt.dmConn.watchCancel(ctx); err != nil { 435 return nil, err 436 } 437 defer stmt.dmConn.finish() 438 439 rows, err := stmt.query(dargs) 440 if err != nil { 441 stmt.dmConn.finish() 442 return nil, err 443 } 444 rows.finish = stmt.dmConn.finish 445 return rows, err 446 } 447 448 func NewDmStmt(conn *DmConnection, sql string) (*DmStatement, error) { 449 var s *DmStatement 450 451 if s == nil { 452 s = new(DmStatement) 453 s.resetFilterable(&conn.filterable) 454 s.objId = -1 455 s.idGenerator = dmStmtIDGenerator 456 s.dmConn = conn 457 s.maxRows = int64(conn.dmConnector.maxRows) 458 s.nativeSql = sql 459 s.rsMap = make(map[int16]*innerRows) 460 s.inUse = true 461 s.isBatch = conn.isBatch 462 463 err := conn.Access.Dm_build_1403(s) 464 if err != nil { 465 return nil, err 466 } 467 468 conn.stmtMap[s.id] = s 469 } 470 471 return s, nil 472 473 } 474 475 func (stmt *DmStatement) checkClosed() error { 476 if stmt.dmConn.closed.IsSet() { 477 return driver.ErrBadConn 478 } else if stmt.closed { 479 return ECGO_STATEMENT_HANDLE_CLOSED.throw() 480 } 481 482 return nil 483 } 484 485 func (stmt *DmStatement) free() error { 486 delete(stmt.dmConn.stmtMap, stmt.id) 487 for _, rs := range stmt.rsMap { 488 rs.Close() 489 } 490 491 err := stmt.dmConn.Access.Dm_build_1408(int32(stmt.id)) 492 if err != nil { 493 return err 494 } 495 stmt.inUse = false 496 stmt.closed = true 497 return nil 498 } 499 500 func bindInParam(stmt *DmStatement, i int, dtype int32, firstRow bool) { 501 if !firstRow { 502 return 503 } 504 isNil := dtype == NULL 505 serverParam := &stmt.serverParams[i] 506 bindParam := &stmt.bindParams[i] 507 if serverParam == nil { 508 bindParam.resetType(dtype) 509 } else { 510 bindParam.name = serverParam.name 511 bindParam.typeDescriptor = serverParam.typeDescriptor 512 bindParam.mask = serverParam.mask 513 bindParam.typeFlag = serverParam.typeFlag 514 515 if (serverParam.colType != UNKNOWN && (isNil || serverParam.typeFlag == TYPE_FLAG_EXACT)) || serverParam.mask != 0 { 516 517 bindParam.colType = serverParam.colType 518 bindParam.prec = serverParam.prec 519 bindParam.scale = serverParam.scale 520 bindParam.mask = serverParam.mask 521 } else { 522 523 bindParam.resetType(dtype) 524 } 525 } 526 527 if bindParam.ioType == IO_TYPE_OUT || bindParam.ioType == IO_TYPE_INOUT { 528 bindParam.ioType = IO_TYPE_INOUT 529 } else { 530 bindParam.ioType = IO_TYPE_IN 531 } 532 } 533 534 func checkBindParameters(stmt *DmStatement, bytes []interface{}) error { 535 536 for i := 0; int32(i) < stmt.paramCount; i++ { 537 if stmt.bindParams[i].ioType == IO_TYPE_UNKNOWN { 538 539 if stmt.serverParams[i].ioType == IO_TYPE_OUT { 540 541 bytes[i] = nil 542 } else { 543 return ECGO_UNBINDED_PARAMETER.throw() 544 } 545 } 546 547 if stmt.bindParams[i].colType == CURSOR { 548 stmt.bindParams[i].ioType = IO_TYPE_INOUT 549 continue 550 } 551 552 if stmt.serverParams[i].ioType != stmt.bindParams[i].ioType { 553 554 stmt.bindParams[i].ioType = stmt.serverParams[i].ioType 555 } 556 } 557 558 for i := 0; int32(i) < stmt.paramCount; i++ { 559 if stmt.bindParams[i].ioType == IO_TYPE_INOUT || stmt.bindParams[i].ioType == IO_TYPE_OUT { 560 continue 561 } 562 switch stmt.bindParams[i].colType { 563 case CHAR, VARCHAR, VARCHAR2: 564 length := -1 565 if b, ok := bytes[i].([]byte); ok { 566 length = len(b) 567 } 568 if length > VARCHAR_PREC { 569 return ECGO_STRING_CUT.throw() 570 } 571 if length > int(stmt.bindParams[i].prec) { 572 if length < VARCHAR_PREC/4 { 573 stmt.bindParams[i].prec = VARCHAR_PREC / 4 574 } else if length < VARCHAR_PREC/2 { 575 stmt.bindParams[i].prec = VARCHAR_PREC / 2 576 } else if length < VARCHAR_PREC*3/4 { 577 stmt.bindParams[i].prec = VARCHAR_PREC * 3 / 4 578 } else { 579 stmt.bindParams[i].prec = VARCHAR_PREC 580 } 581 } 582 } 583 } 584 return nil 585 } 586 587 func bindOutParam(stmt *DmStatement, i int, dtype int32) error { 588 var err error 589 serverParam := &stmt.serverParams[i] 590 bindParam := &stmt.bindParams[i] 591 592 if bindParam.ioType == IO_TYPE_OUT || bindParam.ioType == IO_TYPE_UNKNOWN { 593 594 if serverParam == nil { 595 596 bindParam.resetType(dtype) 597 } else { 598 599 bindParam.name = serverParam.name 600 bindParam.typeDescriptor = serverParam.typeDescriptor 601 bindParam.mask = serverParam.mask 602 bindParam.typeFlag = serverParam.typeFlag 603 604 if (serverParam.colType != UNKNOWN && serverParam.typeFlag == TYPE_FLAG_EXACT) || serverParam.mask != 0 { 605 606 bindParam.colType = serverParam.colType 607 bindParam.prec = serverParam.prec 608 bindParam.scale = serverParam.scale 609 bindParam.mask = serverParam.mask 610 } else { 611 612 bindParam.resetType(dtype) 613 } 614 } 615 616 if bindParam.colType == CURSOR { 617 bindParam.ioType = IO_TYPE_INOUT 618 if bindParam.cursorStmt == nil { 619 bindParam.cursorStmt = &DmStatement{dmConn: stmt.dmConn} 620 bindParam.cursorStmt.resetFilterable(&stmt.dmConn.filterable) 621 err = bindParam.cursorStmt.dmConn.Access.Dm_build_1403(bindParam.cursorStmt) 622 } 623 } 624 } 625 626 if bindParam.ioType == IO_TYPE_IN || bindParam.ioType == IO_TYPE_INOUT { 627 bindParam.ioType = IO_TYPE_INOUT 628 } else { 629 bindParam.ioType = IO_TYPE_OUT 630 } 631 632 return err 633 } 634 635 func encodeArgs(stmt *DmStatement, args []driver.Value, firstRow bool) ([]interface{}, error) { 636 bytes := make([]interface{}, len(args), len(args)) 637 638 var err error 639 640 for i, arg := range args { 641 nextSwitch: 642 if stmt.serverParams[i].colType == CURSOR { 643 bindInParam(stmt, i, CURSOR, firstRow) 644 if stmt.bindParams[i].cursorStmt == nil { 645 stmt.bindParams[i].cursorStmt = &DmStatement{dmConn: stmt.dmConn} 646 stmt.bindParams[i].cursorStmt.resetFilterable(&stmt.dmConn.filterable) 647 err = stmt.bindParams[i].cursorStmt.dmConn.Access.Dm_build_1403(stmt.bindParams[i].cursorStmt) 648 } 649 stmt.bindParams[i].ioType = IO_TYPE_INOUT 650 continue 651 } 652 if arg == nil { 653 bindInParam(stmt, i, NULL, firstRow) 654 bytes[i] = nil 655 656 continue 657 } 658 659 switch v := arg.(type) { 660 case bool: 661 bindInParam(stmt, i, TINYINT, firstRow) 662 bytes[i], err = G2DB.fromBool(v, stmt.bindParams[i], stmt.dmConn) 663 case int8: 664 bindInParam(stmt, i, TINYINT, firstRow) 665 bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn) 666 case int16: 667 bindInParam(stmt, i, SMALLINT, firstRow) 668 bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn) 669 case int32: 670 bindInParam(stmt, i, INT, firstRow) 671 bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn) 672 case int64: 673 bindInParam(stmt, i, BIGINT, firstRow) 674 bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn) 675 case int: 676 bindInParam(stmt, i, BIGINT, firstRow) 677 bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn) 678 case uint8: 679 bindInParam(stmt, i, SMALLINT, firstRow) 680 bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn) 681 case uint16: 682 bindInParam(stmt, i, INT, firstRow) 683 bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn) 684 case uint32: 685 bindInParam(stmt, i, BIGINT, firstRow) 686 bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn) 687 688 case float32: 689 bindInParam(stmt, i, REAL, firstRow) 690 bytes[i], err = G2DB.fromFloat32(v, stmt.bindParams[i], stmt.dmConn) 691 case float64: 692 bindInParam(stmt, i, DOUBLE, firstRow) 693 bytes[i], err = G2DB.fromFloat64(float64(v), stmt.bindParams[i], stmt.dmConn) 694 case []byte: 695 if v == nil { 696 bindInParam(stmt, i, NULL, firstRow) 697 bytes[i] = nil 698 699 } else { 700 dtype := VARBINARY 701 if len(v) >= VARBINARY_PREC { 702 dtype = BLOB 703 } 704 bindInParam(stmt, i, int32(dtype), firstRow) 705 bytes[i], err = G2DB.fromBytes(v, stmt.bindParams[i], stmt.dmConn) 706 } 707 case string: 708 709 if v == "" && emptyStringToNil(stmt.serverParams[i].colType) { 710 arg = nil 711 goto nextSwitch 712 } 713 dtype := VARCHAR 714 if len(v) >= VARCHAR_PREC { 715 dtype = CLOB 716 } 717 bindInParam(stmt, i, int32(dtype), firstRow) 718 bytes[i], err = G2DB.fromString(v, stmt.bindParams[i], stmt.dmConn) 719 case time.Time: 720 bindInParam(stmt, i, DATETIME, firstRow) 721 bytes[i], err = G2DB.fromTime(v, stmt.bindParams[i], stmt.dmConn) 722 case DmTimestamp: 723 bindInParam(stmt, i, DATETIME, firstRow) 724 bytes[i], err = G2DB.fromTime(v.ToTime(), stmt.bindParams[i], stmt.dmConn) 725 case DmIntervalDT: 726 bindInParam(stmt, i, INTERVAL_DT, firstRow) 727 if stmt.bindParams[i].typeFlag != TYPE_FLAG_EXACT { 728 stmt.bindParams[i].scale = int32(v.scaleForSvr) 729 } 730 bytes[i], err = G2DB.fromDmIntervalDT(v, stmt.bindParams[i], stmt.dmConn) 731 case DmIntervalYM: 732 bindInParam(stmt, i, INTERVAL_YM, firstRow) 733 if stmt.bindParams[i].typeFlag != TYPE_FLAG_EXACT { 734 stmt.bindParams[i].scale = int32(v.scaleForSvr) 735 } 736 bytes[i], err = G2DB.fromDmdbIntervalYM(v, stmt.bindParams[i], stmt.dmConn) 737 case DmDecimal: 738 bindInParam(stmt, i, DECIMAL, firstRow) 739 bytes[i], err = G2DB.fromDecimal(v, stmt.bindParams[i], stmt.dmConn) 740 741 case DmBlob: 742 bindInParam(stmt, i, BLOB, firstRow) 743 bytes[i], err = G2DB.fromBlob(DmBlob(v), stmt.bindParams[i], stmt.dmConn) 744 if err != nil { 745 return nil, err 746 } 747 case DmClob: 748 bindInParam(stmt, i, CLOB, firstRow) 749 bytes[i], err = G2DB.fromClob(DmClob(v), stmt.bindParams[i], stmt.dmConn) 750 if err != nil { 751 return nil, err 752 } 753 case DmArray: 754 bindInParam(stmt, i, ARRAY, firstRow) 755 da := &v 756 da, err = da.create(stmt.dmConn) 757 if err != nil { 758 return nil, err 759 } 760 761 bytes[i], err = G2DB.fromArray(da, stmt.bindParams[i], stmt.dmConn) 762 case DmStruct: 763 bindInParam(stmt, i, CLASS, firstRow) 764 ds := &v 765 ds, err = ds.create(stmt.dmConn) 766 if err != nil { 767 return nil, err 768 } 769 770 bytes[i], err = G2DB.fromStruct(ds, stmt.bindParams[i], stmt.dmConn) 771 case sql.Out: 772 var cvt = converter{stmt.dmConn, false} 773 if arg, err = cvt.ConvertValue(v.Dest); err != nil { 774 return nil, err 775 } 776 goto nextSwitch 777 778 case *DmTimestamp: 779 bindInParam(stmt, i, DATETIME, firstRow) 780 bytes[i], err = G2DB.fromTime(v.ToTime(), stmt.bindParams[i], stmt.dmConn) 781 case *DmIntervalDT: 782 bindInParam(stmt, i, INTERVAL_DT, firstRow) 783 if stmt.bindParams[i].typeFlag != TYPE_FLAG_EXACT { 784 stmt.bindParams[i].scale = int32(v.scaleForSvr) 785 } 786 bytes[i], err = G2DB.fromDmIntervalDT(*v, stmt.bindParams[i], stmt.dmConn) 787 case *DmIntervalYM: 788 bindInParam(stmt, i, INTERVAL_YM, firstRow) 789 if stmt.bindParams[i].typeFlag != TYPE_FLAG_EXACT { 790 stmt.bindParams[i].scale = int32(v.scaleForSvr) 791 } 792 bytes[i], err = G2DB.fromDmdbIntervalYM(*v, stmt.bindParams[i], stmt.dmConn) 793 case *DmDecimal: 794 bindInParam(stmt, i, DECIMAL, firstRow) 795 bytes[i], err = G2DB.fromDecimal(*v, stmt.bindParams[i], stmt.dmConn) 796 case *DmBlob: 797 bindInParam(stmt, i, BLOB, firstRow) 798 bytes[i], err = G2DB.fromBlob(DmBlob(*v), stmt.bindParams[i], stmt.dmConn) 799 case *DmClob: 800 bindInParam(stmt, i, CLOB, firstRow) 801 bytes[i], err = G2DB.fromClob(DmClob(*v), stmt.bindParams[i], stmt.dmConn) 802 case *DmArray: 803 bindInParam(stmt, i, ARRAY, firstRow) 804 v, err = v.create(stmt.dmConn) 805 if err != nil { 806 return nil, err 807 } 808 809 bytes[i], err = G2DB.fromArray(v, stmt.bindParams[i], stmt.dmConn) 810 case *DmStruct: 811 bindInParam(stmt, i, CLASS, firstRow) 812 v, err = v.create(stmt.dmConn) 813 if err != nil { 814 return nil, err 815 } 816 817 bytes[i], err = G2DB.fromStruct(v, stmt.bindParams[i], stmt.dmConn) 818 case *driver.Rows: 819 if stmt.serverParams[i].colType == CURSOR { 820 bindInParam(stmt, i, CURSOR, firstRow) 821 if stmt.bindParams[i].cursorStmt == nil { 822 stmt.bindParams[i].cursorStmt = &DmStatement{dmConn: stmt.dmConn} 823 stmt.bindParams[i].cursorStmt.resetFilterable(&stmt.dmConn.filterable) 824 err = stmt.bindParams[i].cursorStmt.dmConn.Access.Dm_build_1403(stmt.bindParams[i].cursorStmt) 825 } 826 } 827 case io.Reader: 828 bindInParam(stmt, i, stmt.serverParams[i].colType, firstRow) 829 bytes[i], err = G2DB.fromReader(io.Reader(v), stmt.serverParams[i], stmt.dmConn) 830 if err != nil { 831 return nil, err 832 } 833 default: 834 err = ECGO_UNSUPPORTED_INPARAM_TYPE.throw() 835 } 836 837 if err != nil { 838 return nil, err 839 } 840 841 } 842 checkBindParameters(stmt, bytes) 843 844 return bytes, nil 845 } 846 847 type converter struct { 848 conn *DmConnection 849 isBatch bool 850 } 851 type decimalDecompose interface { 852 Decompose(buf []byte) (form byte, negative bool, coefficient []byte, exponent int32) 853 } 854 855 func (c *converter) ConvertValue(v interface{}) (driver.Value, error) { 856 if driver.IsValue(v) { 857 return v, nil 858 } 859 860 switch vr := v.(type) { 861 case driver.Valuer: 862 sv, err := callValuerValue(vr) 863 if err != nil { 864 return nil, err 865 } 866 867 return sv, nil 868 869 case decimalDecompose, DmDecimal, *DmDecimal, DmTimestamp, *DmTimestamp, DmIntervalDT, *DmIntervalDT, 870 DmIntervalYM, *DmIntervalYM, driver.Rows, *driver.Rows, DmArray, *DmArray, DmStruct, *DmStruct, sql.Out: 871 return vr, nil 872 case big.Int: 873 return NewDecimalFromBigInt(&vr) 874 case big.Float: 875 return NewDecimalFromBigFloat(&vr) 876 case DmClob: 877 878 if vr.connection == nil { 879 vr.connection = c.conn 880 } 881 return vr, nil 882 case *DmClob: 883 884 if vr.connection == nil { 885 vr.connection = c.conn 886 } 887 return vr, nil 888 case DmBlob: 889 890 if vr.connection == nil { 891 vr.connection = c.conn 892 } 893 return vr, nil 894 case *DmBlob: 895 896 if vr.connection == nil { 897 vr.connection = c.conn 898 } 899 return vr, nil 900 case io.Reader: 901 return vr, nil 902 } 903 904 rv := reflect.ValueOf(v) 905 switch rv.Kind() { 906 case reflect.Ptr: 907 if rv.IsNil() { 908 return nil, nil 909 } else { 910 return c.ConvertValue(rv.Elem().Interface()) 911 } 912 case reflect.Int: 913 return rv.Int(), nil 914 case reflect.Int8: 915 return int8(rv.Int()), nil 916 case reflect.Int16: 917 return int16(rv.Int()), nil 918 case reflect.Int32: 919 return int32(rv.Int()), nil 920 case reflect.Int64: 921 return int64(rv.Int()), nil 922 case reflect.Uint8: 923 return uint8(rv.Uint()), nil 924 case reflect.Uint16: 925 return uint16(rv.Uint()), nil 926 case reflect.Uint32: 927 return uint32(rv.Uint()), nil 928 case reflect.Uint64, reflect.Uint: 929 u64 := rv.Uint() 930 if u64 >= 1<<63 { 931 bigInt := &big.Int{} 932 bigInt.SetString(strconv.FormatUint(u64, 10), 10) 933 return NewDecimalFromBigInt(bigInt) 934 } 935 return int64(u64), nil 936 case reflect.Float32: 937 return float32(rv.Float()), nil 938 case reflect.Float64: 939 return float64(rv.Float()), nil 940 case reflect.Bool: 941 return rv.Bool(), nil 942 case reflect.Slice: 943 ek := rv.Type().Elem().Kind() 944 if ek == reflect.Uint8 { 945 return rv.Bytes(), nil 946 } else if ek == reflect.Slice { 947 c.isBatch = true 948 return v, nil 949 } 950 return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek) 951 case reflect.String: 952 return rv.String(), nil 953 } 954 return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind()) 955 } 956 957 var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem() 958 959 func callValuerValue(vr driver.Valuer) (v driver.Value, err error) { 960 if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr && 961 rv.IsNil() && 962 rv.Type().Elem().Implements(valuerReflectType) { 963 return nil, nil 964 } 965 return vr.Value() 966 } 967 968 func namedValueToValue(stmt *DmStatement, named []driver.NamedValue) ([]driver.Value, error) { 969 970 dargs := make([]driver.Value, stmt.paramCount) 971 for i, _ := range dargs { 972 found := false 973 for _, nv := range named { 974 if nv.Name != "" && strings.ToUpper(nv.Name) == strings.ToUpper(stmt.serverParams[i].name) { 975 dargs[i] = nv.Value 976 found = true 977 break 978 } 979 } 980 981 if !found && i < len(named) { 982 dargs[i] = named[i].Value 983 } 984 985 } 986 return dargs, nil 987 } 988 989 func (stmt *DmStatement) executeInner(args []driver.Value, executeType int16) (err error) { 990 991 var bytes []interface{} 992 993 if stmt.paramCount > 0 { 994 bytes, err = encodeArgs(stmt, args, true) 995 if err != nil { 996 return err 997 } 998 } 999 stmt.execInfo, err = stmt.dmConn.Access.Dm_build_1453(stmt, bytes, false) 1000 if err != nil { 1001 return err 1002 } 1003 if stmt.execInfo.outParamDatas != nil { 1004 for i, outParamData := range stmt.execInfo.outParamDatas { 1005 if stmt.bindParams[i].ioType == IO_TYPE_IN || stmt.bindParams[i].ioType == IO_TYPE_UNKNOWN { 1006 continue 1007 } 1008 1009 var v sql.Out 1010 ok := true 1011 for ok { 1012 if v, ok = args[i].(sql.Out); ok { 1013 args[i] = v.Dest 1014 } 1015 } 1016 1017 if sc, ok := args[i].(sql.Scanner); ok { 1018 var v interface{} 1019 if outParamData == nil && stmt.bindParams[i].colType != CURSOR { 1020 v = nil 1021 if err = sc.Scan(v); err != nil { 1022 return err 1023 } 1024 continue 1025 } 1026 1027 switch stmt.bindParams[i].colType { 1028 case BOOLEAN: 1029 v, err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1030 case BIT: 1031 if strings.ToLower(stmt.bindParams[i].typeName) == "boolean" { 1032 v, err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1033 } 1034 1035 v, err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1036 case TINYINT: 1037 v, err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1038 case SMALLINT: 1039 v, err = DB2G.toInt16(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1040 case INT: 1041 v, err = DB2G.toInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1042 case BIGINT: 1043 v, err = DB2G.toInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1044 case REAL: 1045 v, err = DB2G.toFloat32(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1046 case DOUBLE: 1047 v, err = DB2G.toFloat64(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1048 case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ: 1049 v, err = DB2G.toTime(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1050 case INTERVAL_DT: 1051 v = newDmIntervalDTByBytes(outParamData) 1052 case INTERVAL_YM: 1053 v = newDmIntervalYMByBytes(outParamData) 1054 case DECIMAL: 1055 v, err = DB2G.toDmDecimal(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1056 case BINARY, VARBINARY: 1057 v = util.StringUtil.BytesToHexString(outParamData, false) 1058 case BLOB: 1059 v = DB2G.toDmBlob(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1060 case CHAR, VARCHAR2, VARCHAR: 1061 v = DB2G.toString(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1062 case CLOB: 1063 v = DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.bindParams[i].column) 1064 case ARRAY: 1065 v, err = TypeDataSV.bytesToArray(outParamData, nil, stmt.bindParams[i].typeDescriptor) 1066 case CLASS: 1067 v, err = TypeDataSV.bytesToObj(outParamData, nil, stmt.bindParams[i].typeDescriptor) 1068 case CURSOR: 1069 var tmpExecInfo *execRetInfo 1070 if tmpExecInfo, err = stmt.dmConn.Access.Dm_build_1463(stmt.bindParams[i].cursorStmt, 1); err != nil { 1071 return err 1072 } 1073 if tmpExecInfo.hasResultSet { 1074 v = newDmRows(newInnerRows(0, stmt.bindParams[i].cursorStmt, tmpExecInfo)) 1075 } 1076 default: 1077 err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw() 1078 } 1079 if err == nil { 1080 err = sc.Scan(v) 1081 } 1082 } else if args[i] == nil { 1083 if outParamData == nil && stmt.bindParams[i].colType != CURSOR { 1084 continue 1085 } 1086 1087 switch stmt.bindParams[i].colType { 1088 case BOOLEAN: 1089 args[i], err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1090 case BIT: 1091 if strings.ToLower(stmt.bindParams[i].typeName) == "boolean" { 1092 args[i], err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1093 } 1094 1095 args[i], err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1096 case TINYINT: 1097 args[i], err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1098 case SMALLINT: 1099 args[i], err = DB2G.toInt16(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1100 case INT: 1101 args[i], err = DB2G.toInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1102 case BIGINT: 1103 args[i], err = DB2G.toInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1104 case REAL: 1105 args[i], err = DB2G.toFloat32(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1106 case DOUBLE: 1107 args[i], err = DB2G.toFloat64(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1108 case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ: 1109 args[i], err = DB2G.toTime(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1110 case INTERVAL_DT: 1111 args[i] = newDmIntervalDTByBytes(outParamData) 1112 case INTERVAL_YM: 1113 args[i] = newDmIntervalYMByBytes(outParamData) 1114 case DECIMAL: 1115 args[i], err = DB2G.toDmDecimal(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1116 case BINARY, VARBINARY: 1117 args[i] = util.StringUtil.BytesToHexString(outParamData, false) 1118 case BLOB: 1119 args[i] = DB2G.toDmBlob(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1120 case CHAR, VARCHAR2, VARCHAR: 1121 args[i] = DB2G.toString(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1122 case CLOB: 1123 args[i] = DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.bindParams[i].column) 1124 default: 1125 err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw() 1126 } 1127 } else { 1128 switch v := args[i].(type) { 1129 case *string: 1130 if outParamData == nil { 1131 *v = "" 1132 } else { 1133 *v = DB2G.toString(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1134 } 1135 case *sql.NullString: 1136 if outParamData == nil { 1137 v.String = "" 1138 v.Valid = false 1139 } else { 1140 v.String = DB2G.toString(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1141 v.Valid = true 1142 } 1143 case *[]byte: 1144 if outParamData == nil { 1145 *v = nil 1146 } else { 1147 var val []byte 1148 if val, err = DB2G.toBytes(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1149 return err 1150 } 1151 *v = val 1152 } 1153 case *bool: 1154 if outParamData == nil { 1155 *v = false 1156 } else { 1157 var val bool 1158 if val, err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1159 return err 1160 } 1161 *v = val 1162 } 1163 case *sql.NullBool: 1164 if outParamData == nil { 1165 v.Bool = false 1166 v.Valid = false 1167 } else { 1168 var val bool 1169 if val, err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1170 return err 1171 } 1172 v.Bool = val 1173 v.Valid = true 1174 } 1175 case *int8: 1176 if outParamData == nil { 1177 *v = 0 1178 } else { 1179 var val int8 1180 if val, err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1181 return err 1182 } 1183 *v = val 1184 } 1185 case *int16: 1186 if outParamData == nil { 1187 *v = 0 1188 } else { 1189 var val int16 1190 if val, err = DB2G.toInt16(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1191 return err 1192 } 1193 *v = val 1194 } 1195 case *int32: 1196 if outParamData == nil { 1197 *v = 0 1198 } else { 1199 var val int32 1200 if val, err = DB2G.toInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1201 return err 1202 } 1203 *v = val 1204 } 1205 case *sql.NullInt32: 1206 if outParamData == nil { 1207 v.Int32 = 0 1208 v.Valid = false 1209 } else { 1210 var val int32 1211 if val, err = DB2G.toInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1212 return err 1213 } 1214 v.Int32 = val 1215 v.Valid = true 1216 } 1217 case *int64: 1218 if outParamData == nil { 1219 *v = 0 1220 } else { 1221 var val int64 1222 if val, err = DB2G.toInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1223 return err 1224 } 1225 *v = val 1226 } 1227 case *sql.NullInt64: 1228 if outParamData == nil { 1229 v.Int64 = 0 1230 v.Valid = false 1231 } else { 1232 var val int64 1233 if val, err = DB2G.toInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1234 return err 1235 } 1236 v.Int64 = val 1237 v.Valid = true 1238 } 1239 case *uint8: 1240 if outParamData == nil { 1241 *v = 0 1242 } else { 1243 var val uint8 1244 if val, err = DB2G.toByte(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1245 return err 1246 } 1247 *v = val 1248 } 1249 case *uint16: 1250 if outParamData == nil { 1251 *v = 0 1252 } else { 1253 var val uint16 1254 if val, err = DB2G.toUInt16(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1255 return err 1256 } 1257 *v = val 1258 } 1259 case *uint32: 1260 if outParamData == nil { 1261 *v = 0 1262 } else { 1263 var val uint32 1264 if val, err = DB2G.toUInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1265 return err 1266 } 1267 *v = val 1268 } 1269 case *uint64: 1270 if outParamData == nil { 1271 *v = 0 1272 } else { 1273 var val uint64 1274 if val, err = DB2G.toUInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1275 return err 1276 } 1277 *v = val 1278 } 1279 case *int: 1280 if outParamData == nil { 1281 *v = 0 1282 } else { 1283 var val int 1284 if val, err = DB2G.toInt(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1285 return err 1286 } 1287 *v = val 1288 } 1289 case *uint: 1290 if outParamData == nil { 1291 *v = 0 1292 } else { 1293 var val uint 1294 if val, err = DB2G.toUInt(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1295 return err 1296 } 1297 *v = val 1298 } 1299 case *float32: 1300 if outParamData == nil { 1301 *v = 0.0 1302 } else { 1303 var val float32 1304 if val, err = DB2G.toFloat32(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1305 return err 1306 } 1307 *v = val 1308 } 1309 case *float64: 1310 if outParamData == nil { 1311 *v = 0.0 1312 } else { 1313 var val float64 1314 if val, err = DB2G.toFloat64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1315 return err 1316 } 1317 *v = val 1318 } 1319 case *sql.NullFloat64: 1320 if outParamData == nil { 1321 v.Float64 = 0.0 1322 v.Valid = false 1323 } else { 1324 var val float64 1325 if val, err = DB2G.toFloat64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1326 return err 1327 } 1328 v.Float64 = val 1329 v.Valid = true 1330 } 1331 case *time.Time: 1332 if outParamData == nil { 1333 *v = time.Time{} 1334 } else { 1335 var val time.Time 1336 if val, err = DB2G.toTime(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1337 return err 1338 } 1339 *v = val 1340 } 1341 case *sql.NullTime: 1342 if outParamData == nil { 1343 v.Time = time.Time{} 1344 v.Valid = false 1345 } else { 1346 var val time.Time 1347 if val, err = DB2G.toTime(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1348 return err 1349 } 1350 v.Time = val 1351 v.Valid = true 1352 } 1353 case *DmTimestamp: 1354 if outParamData == nil { 1355 *v = DmTimestamp{} 1356 } else { 1357 *v = *newDmTimestampFromBytes(outParamData, stmt.bindParams[i].column, stmt.dmConn) 1358 } 1359 case *DmIntervalDT: 1360 if outParamData == nil { 1361 *v = DmIntervalDT{} 1362 } else { 1363 *v = *newDmIntervalDTByBytes(outParamData) 1364 } 1365 case *DmIntervalYM: 1366 if outParamData == nil { 1367 *v = DmIntervalYM{} 1368 } else { 1369 *v = *newDmIntervalYMByBytes(outParamData) 1370 } 1371 case *DmDecimal: 1372 if outParamData == nil { 1373 *v = DmDecimal{} 1374 } else { 1375 var val *DmDecimal 1376 if val, err = DB2G.toDmDecimal(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil { 1377 return err 1378 } 1379 *v = *val 1380 } 1381 case *DmBlob: 1382 if outParamData == nil { 1383 *v = DmBlob{} 1384 } else { 1385 *v = *DB2G.toDmBlob(outParamData, &stmt.bindParams[i].column, stmt.dmConn) 1386 } 1387 case *DmClob: 1388 if outParamData == nil { 1389 *v = DmClob{} 1390 } else { 1391 *v = *DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.bindParams[i].column) 1392 } 1393 case *driver.Rows: 1394 if stmt.bindParams[i].colType == CURSOR { 1395 var tmpExecInfo *execRetInfo 1396 tmpExecInfo, err = stmt.dmConn.Access.Dm_build_1463(stmt.bindParams[i].cursorStmt, 1) 1397 if err != nil { 1398 return err 1399 } 1400 1401 if tmpExecInfo.hasResultSet { 1402 *v = newDmRows(newInnerRows(0, stmt.bindParams[i].cursorStmt, tmpExecInfo)) 1403 } else { 1404 *v = nil 1405 } 1406 } 1407 case *DmArray: 1408 if outParamData == nil { 1409 *v = DmArray{} 1410 } else { 1411 var val *DmArray 1412 if val, err = TypeDataSV.bytesToArray(outParamData, nil, stmt.bindParams[i].typeDescriptor); err != nil { 1413 return err 1414 } 1415 *v = *val 1416 } 1417 case *DmStruct: 1418 if outParamData == nil { 1419 *v = DmStruct{} 1420 } else { 1421 var tmp interface{} 1422 if tmp, err = TypeDataSV.bytesToObj(outParamData, nil, stmt.bindParams[i].typeDescriptor); err != nil { 1423 return err 1424 } 1425 if val, ok := tmp.(*DmStruct); ok { 1426 *v = *val 1427 } 1428 } 1429 default: 1430 err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw() 1431 } 1432 } 1433 if err != nil { 1434 return err 1435 } 1436 } 1437 1438 } 1439 return err 1440 } 1441 1442 func (stmt *DmStatement) executeBatch(args []driver.Value) (err error) { 1443 1444 var bytes [][]interface{} 1445 1446 if stmt.execInfo.retSqlType == Dm_build_110 || stmt.execInfo.retSqlType == Dm_build_115 { 1447 return ECGO_INVALID_SQL_TYPE.throw() 1448 } 1449 1450 if stmt.paramCount > 0 && args != nil && len(args) > 0 { 1451 1452 if len(args) == 1 || stmt.dmConn.dmConnector.batchType == 2 || 1453 (stmt.dmConn.dmConnector.batchNotOnCall && stmt.execInfo.retSqlType == Dm_build_111) { 1454 return stmt.executeBatchByRow(args) 1455 } else { 1456 for i, arg := range args { 1457 var newArg []driver.Value 1458 for _, a := range arg.([]interface{}) { 1459 newArg = append(newArg, a) 1460 } 1461 tmpBytes, err := encodeArgs(stmt, newArg, i == 0) 1462 if err != nil { 1463 return err 1464 } 1465 bytes = append(bytes, tmpBytes) 1466 } 1467 stmt.execInfo, err = stmt.dmConn.Access.Dm_build_1442(stmt, bytes, stmt.preExec) 1468 } 1469 } 1470 return err 1471 } 1472 1473 func (stmt *DmStatement) executeBatchByRow(args []driver.Value) (err error) { 1474 count := len(args) 1475 stmt.execInfo = NewExceInfo() 1476 stmt.execInfo.updateCounts = make([]int64, count) 1477 var sqlErrBuilder strings.Builder 1478 for i := 0; i < count; i++ { 1479 tmpExecInfo, err := stmt.dmConn.Access.Dm_build_1453(stmt, args[i].([]interface{}), stmt.preExec || i != 0) 1480 if err == nil { 1481 stmt.execInfo.union(tmpExecInfo, i, 1) 1482 } else { 1483 stmt.execInfo.updateCounts[i] = -1 1484 if stmt.dmConn.dmConnector.continueBatchOnError { 1485 sqlErrBuilder.WriteString("row[" + strconv.Itoa(i) + "]:" + err.Error() + util.LINE_SEPARATOR) 1486 } else { 1487 return ECGO_BATCH_ERROR.addDetailln(err.Error()).throw() 1488 } 1489 } 1490 } 1491 if sqlErrBuilder.Len() > 0 { 1492 return EC_BP_WITH_ERROR.addDetail(sqlErrBuilder.String()).throw() 1493 } 1494 return nil 1495 }