github.com/xiyichan/dm8@v0.0.0-20211213021639-be727be3e136/o.go (about) 1 /* 2 * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 * All rights reserved. 4 */ 5 package dm 6 7 import ( 8 "bytes" 9 "context" 10 "database/sql" 11 "database/sql/driver" 12 "fmt" 13 "github.com/xiyichan/dm8/parser" 14 "golang.org/x/text/encoding" 15 "sync/atomic" 16 ) 17 18 type DmConnection struct { 19 filterable 20 21 dmConnector *DmConnector 22 Access *dm_build_1285 23 stmtMap map[int32]*DmStatement 24 stmtPool []stmtPoolInfo 25 lastExecInfo *execInfo 26 lexer *parser.Lexer 27 encode encoding.Encoding 28 encodeBuffer *bytes.Buffer 29 transformReaderDst []byte 30 transformReaderSrc []byte 31 32 serverEncoding string 33 GlobalServerSeries int 34 ServerVersion string 35 Malini2 bool 36 Execute2 bool 37 LobEmptyCompOrcl bool 38 IsoLevel int32 39 ReadOnly bool 40 NewLobFlag bool 41 sslEncrypt int 42 MaxRowSize int32 43 DDLAutoCommit bool 44 BackslashEscape bool 45 SvrStat int16 46 SvrMode int16 47 ConstParaOpt bool 48 DbTimezone int16 49 LifeTimeRemainder int16 50 InstanceName string 51 Schema string 52 LastLoginIP string 53 LastLoginTime string 54 FailedAttempts int32 55 LoginWarningID int32 56 GraceTimeRemainder int32 57 Guid string 58 DbName string 59 StandbyHost string 60 StandbyPort int32 61 StandbyCount uint16 62 SessionID int64 63 OracleDateFormat string 64 OracleTimestampFormat string 65 OracleTimestampTZFormat string 66 OracleTimeFormat string 67 OracleTimeTZFormat string 68 OracleDateLanguage byte 69 Local bool 70 TrxStatus int32 71 trxFinish bool 72 sessionID int64 73 autoCommit bool 74 isBatch bool 75 76 watching bool 77 watcher chan<- context.Context 78 closech chan struct{} 79 finished chan<- struct{} 80 canceled atomicError 81 closed atomicBool 82 } 83 84 func (conn *DmConnection) setTrxFinish(status int32) { 85 switch status & Dm_build_122 { 86 case Dm_build_119, Dm_build_120, Dm_build_121: 87 conn.trxFinish = true 88 default: 89 conn.trxFinish = false 90 } 91 } 92 93 func (dmConn *DmConnection) init() { 94 if dmConn.dmConnector.stmtPoolMaxSize > 0 { 95 dmConn.stmtPool = make([]stmtPoolInfo, 0, dmConn.dmConnector.stmtPoolMaxSize) 96 } 97 98 dmConn.stmtMap = make(map[int32]*DmStatement) 99 dmConn.DbTimezone = 0 100 dmConn.GlobalServerSeries = 0 101 dmConn.MaxRowSize = 0 102 dmConn.LobEmptyCompOrcl = false 103 dmConn.ReadOnly = false 104 dmConn.DDLAutoCommit = false 105 dmConn.ConstParaOpt = false 106 dmConn.IsoLevel = -1 107 dmConn.sessionID = -1 108 dmConn.Malini2 = true 109 dmConn.NewLobFlag = true 110 dmConn.Execute2 = true 111 dmConn.serverEncoding = ENCODING_GB18030 112 dmConn.TrxStatus = Dm_build_70 113 114 dmConn.idGenerator = dmConnIDGenerator 115 } 116 117 func (dmConn *DmConnection) reset() { 118 dmConn.DbTimezone = 0 119 dmConn.GlobalServerSeries = 0 120 dmConn.MaxRowSize = 0 121 dmConn.LobEmptyCompOrcl = false 122 dmConn.ReadOnly = false 123 dmConn.DDLAutoCommit = false 124 dmConn.ConstParaOpt = false 125 dmConn.IsoLevel = -1 126 dmConn.sessionID = -1 127 dmConn.Malini2 = true 128 dmConn.NewLobFlag = true 129 dmConn.Execute2 = true 130 dmConn.serverEncoding = ENCODING_GB18030 131 dmConn.TrxStatus = Dm_build_70 132 } 133 134 func (dc *DmConnection) checkClosed() error { 135 if dc.closed.IsSet() { 136 return driver.ErrBadConn 137 } 138 139 return nil 140 } 141 142 func (dc *DmConnection) executeInner(query string, execType int16) (interface{}, error) { 143 144 stmt, err := NewDmStmt(dc, query) 145 146 if err != nil { 147 return nil, err 148 } 149 150 if execType == Dm_build_87 { 151 defer stmt.close() 152 } 153 154 stmt.innerUsed = true 155 if stmt.dmConn.dmConnector.escapeProcess { 156 stmt.nativeSql, err = stmt.dmConn.escape(stmt.nativeSql, stmt.dmConn.dmConnector.keyWords) 157 if err != nil { 158 stmt.close() 159 return nil, err 160 } 161 } 162 163 var optParamList []OptParameter 164 165 if stmt.dmConn.ConstParaOpt { 166 optParamList = make([]OptParameter, 0) 167 stmt.nativeSql, optParamList, err = stmt.dmConn.execOpt(stmt.nativeSql, optParamList, stmt.dmConn.getServerEncoding()) 168 if err != nil { 169 stmt.close() 170 optParamList = nil 171 } 172 } 173 174 if execType == Dm_build_86 && dc.dmConnector.enRsCache { 175 rpv, err := rp.get(stmt, query) 176 if err != nil { 177 return nil, err 178 } 179 180 if rpv != nil { 181 stmt.execInfo = rpv.execInfo 182 dc.lastExecInfo = rpv.execInfo 183 return newDmRows(rpv.getResultSet(stmt)), nil 184 } 185 } 186 187 var info *execInfo 188 189 if optParamList != nil && len(optParamList) > 0 { 190 info, err = dc.Access.Dm_build_1363(stmt, optParamList) 191 if err != nil { 192 stmt.nativeSql = query 193 info, err = dc.Access.Dm_build_1369(stmt, execType) 194 } 195 } else { 196 info, err = dc.Access.Dm_build_1369(stmt, execType) 197 } 198 199 dc.lastExecInfo = info 200 if err != nil { 201 stmt.close() 202 return nil, err 203 } 204 205 if info.hasResultSet { 206 return newDmRows(newInnerRows(0, stmt, info)), nil 207 } else { 208 return newDmResult(stmt, info), nil 209 } 210 } 211 212 func g2dbIsoLevel(isoLevel int32) int32 { 213 switch isoLevel { 214 case 1: 215 return Dm_build_74 216 case 2: 217 return Dm_build_75 218 case 4: 219 return Dm_build_76 220 case 6: 221 return Dm_build_77 222 default: 223 return -1 224 } 225 } 226 227 func (dc *DmConnection) Begin() (driver.Tx, error) { 228 if len(dc.filterChain.filters) == 0 { 229 return dc.begin() 230 } else { 231 return dc.filterChain.reset().DmConnectionBegin(dc) 232 } 233 } 234 235 func (dc *DmConnection) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { 236 if len(dc.filterChain.filters) == 0 { 237 return dc.beginTx(ctx, opts) 238 } 239 return dc.filterChain.reset().DmConnectionBeginTx(dc, ctx, opts) 240 } 241 242 func (dc *DmConnection) Commit() error { 243 if len(dc.filterChain.filters) == 0 { 244 return dc.commit() 245 } else { 246 return dc.filterChain.reset().DmConnectionCommit(dc) 247 } 248 } 249 250 func (dc *DmConnection) Rollback() error { 251 if len(dc.filterChain.filters) == 0 { 252 return dc.rollback() 253 } else { 254 return dc.filterChain.reset().DmConnectionRollback(dc) 255 } 256 } 257 258 func (dc *DmConnection) Close() error { 259 if len(dc.filterChain.filters) == 0 { 260 return dc.close() 261 } else { 262 return dc.filterChain.reset().DmConnectionClose(dc) 263 } 264 } 265 266 func (dc *DmConnection) Ping(ctx context.Context) error { 267 if len(dc.filterChain.filters) == 0 { 268 return dc.ping(ctx) 269 } else { 270 return dc.filterChain.reset().DmConnectionPing(dc, ctx) 271 } 272 } 273 274 func (dc *DmConnection) Exec(query string, args []driver.Value) (driver.Result, error) { 275 if len(dc.filterChain.filters) == 0 { 276 return dc.exec(query, args) 277 } 278 return dc.filterChain.reset().DmConnectionExec(dc, query, args) 279 } 280 281 func (dc *DmConnection) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { 282 if len(dc.filterChain.filters) == 0 { 283 return dc.execContext(ctx, query, args) 284 } 285 return dc.filterChain.reset().DmConnectionExecContext(dc, ctx, query, args) 286 } 287 288 func (dc *DmConnection) Query(query string, args []driver.Value) (driver.Rows, error) { 289 if len(dc.filterChain.filters) == 0 { 290 return dc.query(query, args) 291 } 292 return dc.filterChain.reset().DmConnectionQuery(dc, query, args) 293 } 294 295 func (dc *DmConnection) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { 296 if len(dc.filterChain.filters) == 0 { 297 return dc.queryContext(ctx, query, args) 298 } 299 return dc.filterChain.reset().DmConnectionQueryContext(dc, ctx, query, args) 300 } 301 302 func (dc *DmConnection) Prepare(query string) (driver.Stmt, error) { 303 if len(dc.filterChain.filters) == 0 { 304 return dc.prepare(query) 305 } 306 return dc.filterChain.reset().DmConnectionPrepare(dc, query) 307 } 308 309 func (dc *DmConnection) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { 310 if len(dc.filterChain.filters) == 0 { 311 return dc.prepareContext(ctx, query) 312 } 313 return dc.filterChain.reset().DmConnectionPrepareContext(dc, ctx, query) 314 } 315 316 func (dc *DmConnection) ResetSession(ctx context.Context) error { 317 if len(dc.filterChain.filters) == 0 { 318 return dc.resetSession(ctx) 319 } 320 return dc.filterChain.reset().DmConnectionResetSession(dc, ctx) 321 } 322 323 func (dc *DmConnection) CheckNamedValue(nv *driver.NamedValue) error { 324 if len(dc.filterChain.filters) == 0 { 325 return dc.checkNamedValue(nv) 326 } 327 return dc.filterChain.reset().DmConnectionCheckNamedValue(dc, nv) 328 } 329 330 func (dc *DmConnection) begin() (*DmConnection, error) { 331 return dc.beginTx(context.Background(), driver.TxOptions{driver.IsolationLevel(sql.LevelDefault), false}) 332 } 333 334 func (dc *DmConnection) beginTx(ctx context.Context, opts driver.TxOptions) (*DmConnection, error) { 335 err := dc.checkClosed() 336 if err != nil { 337 return nil, err 338 } 339 340 if err := dc.watchCancel(ctx); err != nil { 341 return nil, err 342 } 343 defer dc.finish() 344 345 dc.autoCommit = false 346 347 if sql.IsolationLevel(opts.Isolation) == sql.LevelDefault { 348 opts.Isolation = driver.IsolationLevel(sql.LevelReadCommitted) 349 } 350 351 dc.ReadOnly = opts.ReadOnly 352 353 if dc.IsoLevel == int32(opts.Isolation) { 354 return dc, nil 355 } 356 357 switch sql.IsolationLevel(opts.Isolation) { 358 case sql.LevelDefault: 359 return dc, nil 360 case sql.LevelReadUncommitted, sql.LevelReadCommitted, sql.LevelSerializable: 361 dc.IsoLevel = int32(opts.Isolation) 362 case sql.LevelRepeatableRead: 363 if dc.CompatibleMysql() { 364 dc.IsoLevel = int32(sql.LevelReadCommitted) 365 } else { 366 return nil, ECGO_INVALID_TRAN_ISOLATION.throw() 367 } 368 default: 369 return nil, ECGO_INVALID_TRAN_ISOLATION.throw() 370 } 371 372 err = dc.Access.Dm_build_1423(dc) 373 if err != nil { 374 return nil, err 375 } 376 return dc, nil 377 } 378 379 func (dc *DmConnection) commit() error { 380 err := dc.checkClosed() 381 if err != nil { 382 return err 383 } 384 385 defer func() { 386 dc.autoCommit = dc.dmConnector.autoCommit 387 }() 388 389 if !dc.autoCommit { 390 err = dc.Access.Commit() 391 if err != nil { 392 return err 393 } 394 dc.trxFinish = true 395 return nil 396 } else if !dc.dmConnector.alwayseAllowCommit { 397 return ECGO_COMMIT_IN_AUTOCOMMIT_MODE.throw() 398 } 399 400 return nil 401 } 402 403 func (dc *DmConnection) rollback() error { 404 err := dc.checkClosed() 405 if err != nil { 406 return err 407 } 408 409 defer func() { 410 dc.autoCommit = dc.dmConnector.autoCommit 411 }() 412 413 if !dc.autoCommit { 414 err = dc.Access.Rollback() 415 if err != nil { 416 return err 417 } 418 dc.trxFinish = true 419 return nil 420 } else if !dc.dmConnector.alwayseAllowCommit { 421 return ECGO_ROLLBACK_IN_AUTOCOMMIT_MODE.throw() 422 } 423 424 return nil 425 } 426 427 func (dc *DmConnection) reconnect() error { 428 err := dc.Access.Close() 429 if err != nil { 430 return err 431 } 432 433 for _, stmt := range dc.stmtMap { 434 stmt.closed = true 435 for id, _ := range stmt.rsMap { 436 delete(stmt.rsMap, id) 437 } 438 } 439 440 if dc.stmtPool != nil { 441 dc.stmtPool = dc.stmtPool[:0] 442 } 443 444 dc.dmConnector.reConnection = dc 445 446 if dc.dmConnector.group != nil { 447 _, err = dc.dmConnector.group.connect(dc.dmConnector) 448 if err != nil { 449 return err 450 } 451 } else { 452 _, err = dc.dmConnector.connect(context.Background()) 453 } 454 455 for _, stmt := range dc.stmtMap { 456 err = dc.Access.Dm_build_1341(stmt) 457 if err != nil { 458 return err 459 } 460 461 if stmt.paramCount > 0 { 462 err = stmt.prepare() 463 if err != nil { 464 return err 465 } 466 } 467 } 468 469 return nil 470 } 471 472 func (dc *DmConnection) close() error { 473 if dc.closed.IsSet() { 474 return nil 475 } 476 477 close(dc.closech) 478 if dc.Access == nil { 479 return nil 480 } 481 482 err := dc.rollback() 483 if err != nil { 484 return err 485 } 486 487 for _, stmt := range dc.stmtMap { 488 err = stmt.free() 489 if err != nil { 490 return err 491 } 492 } 493 494 if dc.stmtPool != nil { 495 for _, spi := range dc.stmtPool { 496 err = dc.Access.Dm_build_1346(spi.id) 497 if err != nil { 498 return err 499 } 500 } 501 dc.stmtPool = nil 502 } 503 504 err = dc.Access.Close() 505 if err != nil { 506 return err 507 } 508 509 dc.closed.Set(true) 510 return nil 511 } 512 513 func (dc *DmConnection) ping(ctx context.Context) error { 514 rows, err := dc.query("select 1", nil) 515 if err != nil { 516 return err 517 } 518 return rows.close() 519 } 520 521 func (dc *DmConnection) exec(query string, args []driver.Value) (*DmResult, error) { 522 err := dc.checkClosed() 523 if err != nil { 524 return nil, err 525 } 526 527 if args != nil && len(args) > 0 { 528 stmt, err := dc.prepare(query) 529 dc.lastExecInfo = stmt.execInfo 530 defer stmt.close() 531 if err != nil { 532 return nil, err 533 } 534 535 return stmt.exec(args) 536 } else { 537 r1, err := dc.executeInner(query, Dm_build_87) 538 if err != nil { 539 return nil, err 540 } 541 542 if r2, ok := r1.(*DmResult); ok { 543 return r2, nil 544 } else { 545 return nil, ECGO_NOT_EXEC_SQL.throw() 546 } 547 } 548 } 549 550 func (dc *DmConnection) execContext(ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) { 551 552 err := dc.checkClosed() 553 if err != nil { 554 return nil, err 555 } 556 557 if err := dc.watchCancel(ctx); err != nil { 558 return nil, err 559 } 560 defer dc.finish() 561 562 if args != nil && len(args) > 0 { 563 stmt, err := dc.prepare(query) 564 dc.lastExecInfo = stmt.execInfo 565 defer stmt.close() 566 if err != nil { 567 return nil, err 568 } 569 570 return stmt.execContext(ctx, args) 571 } else { 572 r1, err := dc.executeInner(query, Dm_build_87) 573 if err != nil { 574 return nil, err 575 } 576 577 if r2, ok := r1.(*DmResult); ok { 578 return r2, nil 579 } else { 580 return nil, ECGO_NOT_EXEC_SQL.throw() 581 } 582 } 583 } 584 585 func (dc *DmConnection) query(query string, args []driver.Value) (*DmRows, error) { 586 587 err := dc.checkClosed() 588 if err != nil { 589 return nil, err 590 } 591 592 if args != nil && len(args) > 0 { 593 stmt, err := dc.prepare(query) 594 dc.lastExecInfo = stmt.execInfo 595 if err != nil { 596 stmt.close() 597 return nil, err 598 } 599 600 stmt.innerUsed = true 601 return stmt.query(args) 602 603 } else { 604 r1, err := dc.executeInner(query, Dm_build_86) 605 if err != nil { 606 return nil, err 607 } 608 609 if r2, ok := r1.(*DmRows); ok { 610 return r2, nil 611 } else { 612 return nil, ECGO_NOT_QUERY_SQL.throw() 613 } 614 } 615 } 616 617 func (dc *DmConnection) queryContext(ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) { 618 619 err := dc.checkClosed() 620 if err != nil { 621 return nil, err 622 } 623 624 if err := dc.watchCancel(ctx); err != nil { 625 return nil, err 626 } 627 defer dc.finish() 628 629 if args != nil && len(args) > 0 { 630 stmt, err := dc.prepare(query) 631 dc.lastExecInfo = stmt.execInfo 632 if err != nil { 633 stmt.close() 634 return nil, err 635 } 636 637 stmt.innerUsed = true 638 return stmt.queryContext(ctx, args) 639 640 } else { 641 r1, err := dc.executeInner(query, Dm_build_86) 642 if err != nil { 643 return nil, err 644 } 645 646 if r2, ok := r1.(*DmRows); ok { 647 return r2, nil 648 } else { 649 return nil, ECGO_NOT_QUERY_SQL.throw() 650 } 651 } 652 653 } 654 655 func (dc *DmConnection) prepare(query string) (*DmStatement, error) { 656 err := dc.checkClosed() 657 if err != nil { 658 return nil, err 659 } 660 661 stmt, err := NewDmStmt(dc, query) 662 if err != nil { 663 return nil, err 664 } 665 666 err = stmt.prepare() 667 return stmt, err 668 } 669 670 func (dc *DmConnection) prepareContext(ctx context.Context, query string) (*DmStatement, error) { 671 err := dc.checkClosed() 672 if err != nil { 673 return nil, err 674 } 675 676 if err := dc.watchCancel(ctx); err != nil { 677 return nil, err 678 } 679 defer dc.finish() 680 681 stmt, err := dc.prepare(query) 682 if err != nil { 683 return nil, err 684 } 685 686 return stmt, nil 687 } 688 689 func (dc *DmConnection) resetSession(ctx context.Context) error { 690 err := dc.checkClosed() 691 if err != nil { 692 return err 693 } 694 695 for _, stmt := range dc.stmtMap { 696 stmt.inUse = false 697 } 698 699 return nil 700 } 701 702 func (dc *DmConnection) checkNamedValue(nv *driver.NamedValue) error { 703 var err error 704 var cvt = converter{dc, false} 705 nv.Value, err = cvt.ConvertValue(nv.Value) 706 dc.isBatch = cvt.isBatch 707 return err 708 } 709 710 func (dc *DmConnection) getServerEncoding() string { 711 if dc.dmConnector.charCode != "" { 712 return dc.dmConnector.charCode 713 } 714 return dc.serverEncoding 715 } 716 717 func (dc *DmConnection) lobFetchAll() bool { 718 return dc.dmConnector.lobMode == 2 719 } 720 721 func (conn *DmConnection) CompatibleOracle() bool { 722 return conn.dmConnector.compatibleMode == COMPATIBLE_MODE_ORACLE 723 } 724 725 func (conn *DmConnection) CompatibleMysql() bool { 726 return conn.dmConnector.compatibleMode == COMPATIBLE_MODE_MYSQL 727 } 728 729 func (conn *DmConnection) cancel(err error) { 730 conn.canceled.Set(err) 731 fmt.Println(conn.close()) 732 } 733 734 func (conn *DmConnection) finish() { 735 if !conn.watching || conn.finished == nil { 736 return 737 } 738 select { 739 case conn.finished <- struct{}{}: 740 conn.watching = false 741 case <-conn.closech: 742 } 743 } 744 745 func (conn *DmConnection) startWatcher() { 746 watcher := make(chan context.Context, 1) 747 conn.watcher = watcher 748 finished := make(chan struct{}) 749 conn.finished = finished 750 go func() { 751 for { 752 var ctx context.Context 753 select { 754 case ctx = <-watcher: 755 case <-conn.closech: 756 return 757 } 758 759 select { 760 case <-ctx.Done(): 761 conn.cancel(ctx.Err()) 762 case <-finished: 763 case <-conn.closech: 764 return 765 } 766 } 767 }() 768 } 769 770 func (conn *DmConnection) watchCancel(ctx context.Context) error { 771 if conn.watching { 772 773 return conn.close() 774 } 775 776 if err := ctx.Err(); err != nil { 777 return err 778 } 779 780 if ctx.Done() == nil { 781 return nil 782 } 783 784 if conn.watcher == nil { 785 return nil 786 } 787 788 conn.watching = true 789 conn.watcher <- ctx 790 return nil 791 } 792 793 type noCopy struct{} 794 795 func (*noCopy) Lock() {} 796 797 type atomicBool struct { 798 _noCopy noCopy 799 value uint32 800 } 801 802 func (ab *atomicBool) IsSet() bool { 803 return atomic.LoadUint32(&ab.value) > 0 804 } 805 806 func (ab *atomicBool) Set(value bool) { 807 if value { 808 atomic.StoreUint32(&ab.value, 1) 809 } else { 810 atomic.StoreUint32(&ab.value, 0) 811 } 812 } 813 814 func (ab *atomicBool) TrySet(value bool) bool { 815 if value { 816 return atomic.SwapUint32(&ab.value, 1) == 0 817 } 818 return atomic.SwapUint32(&ab.value, 0) > 0 819 } 820 821 type atomicError struct { 822 _noCopy noCopy 823 value atomic.Value 824 } 825 826 func (ae *atomicError) Set(value error) { 827 ae.value.Store(value) 828 } 829 830 func (ae *atomicError) Value() error { 831 if v := ae.value.Load(); v != nil { 832 833 return v.(error) 834 } 835 return nil 836 }