gitee.com/curryzheng/dm@v0.0.1/zi.go (about) 1 /* 2 * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 * All rights reserved. 4 */ 5 6 package dm 7 8 import ( 9 "bytes" 10 "context" 11 "database/sql/driver" 12 "fmt" 13 "reflect" 14 "time" 15 ) 16 17 type statFilter struct { 18 } 19 20 //DmDriver 21 func (sf *statFilter) DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnection, error) { 22 conn, err := filterChain.DmDriverOpen(d, dsn) 23 if err != nil { 24 return nil, err 25 } 26 conn.statInfo.init(conn) 27 conn.statInfo.setConstructNano() 28 conn.statInfo.getConnStat().incrementConn() 29 return conn, nil 30 } 31 32 func (sf *statFilter) DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnector, error) { 33 return filterChain.DmDriverOpenConnector(d, dsn) 34 } 35 36 //DmConnector 37 func (sf *statFilter) DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (*DmConnection, error) { 38 conn, err := filterChain.DmConnectorConnect(c, ctx) 39 if err != nil { 40 return nil, err 41 } 42 conn.statInfo.init(conn) 43 conn.statInfo.setConstructNano() 44 conn.statInfo.getConnStat().incrementConn() 45 return conn, nil 46 } 47 48 func (sf *statFilter) DmConnectorDriver(filterChain *filterChain, c *DmConnector) *DmDriver { 49 return filterChain.DmConnectorDriver(c) 50 } 51 52 //DmConnection 53 func (sf *statFilter) DmConnectionBegin(filterChain *filterChain, c *DmConnection) (*DmConnection, error) { 54 return filterChain.DmConnectionBegin(c) 55 } 56 57 func (sf *statFilter) DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error) { 58 return filterChain.DmConnectionBeginTx(c, ctx, opts) 59 } 60 61 func (sf *statFilter) DmConnectionCommit(filterChain *filterChain, c *DmConnection) error { 62 err := filterChain.DmConnectionCommit(c) 63 if err != nil { 64 return err 65 } 66 c.statInfo.getConnStat().incrementCommitCount() 67 return nil 68 } 69 70 func (sf *statFilter) DmConnectionRollback(filterChain *filterChain, c *DmConnection) error { 71 err := filterChain.DmConnectionRollback(c) 72 if err != nil { 73 return err 74 } 75 c.statInfo.getConnStat().incrementRollbackCount() 76 return nil 77 } 78 79 func (sf *statFilter) DmConnectionClose(filterChain *filterChain, c *DmConnection) error { 80 if !c.closed.IsSet() { 81 c.statInfo.getConnStat().decrementStmtByActiveStmtCount(int64(getActiveStmtCount(c))) 82 c.statInfo.getConnStat().decrementConn() 83 } 84 85 return filterChain.DmConnectionClose(c) 86 } 87 88 func (sf *statFilter) DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) error { 89 return c.ping(ctx) 90 } 91 92 func (sf *statFilter) DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmResult, error) { 93 connExecBefore(c, query) 94 dr, err := filterChain.DmConnectionExec(c, query, args) 95 if err != nil { 96 connExecuteErrorAfter(c, args, err) 97 return nil, err 98 } 99 connExecAfter(c, query, args, int(dr.affectedRows)) 100 return dr, nil 101 } 102 103 func (sf *statFilter) DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) { 104 connExecBefore(c, query) 105 dr, err := filterChain.DmConnectionExecContext(c, ctx, query, args) 106 if err != nil { 107 connExecuteErrorAfter(c, args, err) 108 return nil, err 109 } 110 connExecAfter(c, query, args, int(dr.affectedRows)) 111 return dr, nil 112 } 113 114 func (sf *statFilter) DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmRows, error) { 115 connQueryBefore(c, query) 116 dr, err := filterChain.DmConnectionQuery(c, query, args) 117 if err != nil { 118 connExecuteErrorAfter(c, args, err) 119 return nil, err 120 } 121 connQueryAfter(c, query, args, dr) 122 return dr, nil 123 } 124 125 func (sf *statFilter) DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) { 126 connQueryBefore(c, query) 127 dr, err := filterChain.DmConnectionQueryContext(c, ctx, query, args) 128 if err != nil { 129 connExecuteErrorAfter(c, args, err) 130 return nil, err 131 } 132 connQueryAfter(c, query, args, dr) 133 return dr, nil 134 } 135 136 func (sf *statFilter) DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (*DmStatement, error) { 137 stmt, err := filterChain.DmConnectionPrepare(c, query) 138 if err != nil { 139 return nil, err 140 } 141 statementCreateAfter(c, stmt) 142 return stmt, nil 143 } 144 145 func (sf *statFilter) DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (*DmStatement, error) { 146 stmt, err := filterChain.DmConnectionPrepareContext(c, ctx, query) 147 if err != nil { 148 return nil, err 149 } 150 statementCreateAfter(c, stmt) 151 return stmt, nil 152 } 153 154 func (sf *statFilter) DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) error { 155 return filterChain.DmConnectionResetSession(c, ctx) 156 } 157 158 func (sf *statFilter) DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) error { 159 return filterChain.DmConnectionCheckNamedValue(c, nv) 160 } 161 162 //DmStatement 163 func (sf *statFilter) DmStatementClose(filterChain *filterChain, s *DmStatement) error { 164 if !s.closed { 165 statementCloseBefore(s) 166 } 167 return filterChain.DmStatementClose(s) 168 } 169 170 func (sf *statFilter) DmStatementNumInput(filterChain *filterChain, s *DmStatement) int { 171 return filterChain.DmStatementNumInput(s) 172 } 173 174 func (sf *statFilter) DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error) { 175 stmtExecBefore(s) 176 dr, err := filterChain.DmStatementExec(s, args) 177 if err != nil { 178 statementExecuteErrorAfter(s, args, err) 179 return nil, err 180 } 181 stmtExecAfter(s, args, int(dr.affectedRows)) 182 return dr, nil 183 } 184 185 func (sf *statFilter) DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) { 186 stmtExecBefore(s) 187 dr, err := filterChain.DmStatementExecContext(s, ctx, args) 188 if err != nil { 189 statementExecuteErrorAfter(s, args, err) 190 return nil, err 191 } 192 stmtExecAfter(s, args, int(dr.affectedRows)) 193 return dr, nil 194 } 195 196 func (sf *statFilter) DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error) { 197 stmtQueryBefore(s) 198 dr, err := filterChain.DmStatementQuery(s, args) 199 if err != nil { 200 statementExecuteErrorAfter(s, args, err) 201 return nil, err 202 } 203 stmtQueryAfter(s, args, dr) 204 return dr, nil 205 } 206 207 func (sf *statFilter) DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) { 208 stmtQueryBefore(s) 209 dr, err := filterChain.DmStatementQueryContext(s, ctx, args) 210 if err != nil { 211 statementExecuteErrorAfter(s, args, err) 212 return nil, err 213 } 214 stmtQueryAfter(s, args, dr) 215 return dr, nil 216 } 217 218 func (sf *statFilter) DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error { 219 return filterChain.DmStatementCheckNamedValue(s, nv) 220 } 221 222 //DmResult 223 func (sf *statFilter) DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error) { 224 return filterChain.DmResultLastInsertId(r) 225 } 226 227 func (sf *statFilter) DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error) { 228 return filterChain.DmResultRowsAffected(r) 229 } 230 231 //DmRows 232 func (sf *statFilter) DmRowsColumns(filterChain *filterChain, r *DmRows) []string { 233 return filterChain.DmRowsColumns(r) 234 } 235 236 func (sf *statFilter) DmRowsClose(filterChain *filterChain, r *DmRows) error { 237 if !r.CurrentRows.closed { 238 resultSetCloseBefore(r) 239 } 240 return filterChain.DmRowsClose(r) 241 } 242 243 func (sf *statFilter) DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error { 244 return filterChain.DmRowsNext(r, dest) 245 } 246 247 func (sf *statFilter) DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool { 248 return filterChain.DmRowsHasNextResultSet(r) 249 } 250 251 func (sf *statFilter) DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error { 252 return filterChain.DmRowsNextResultSet(r) 253 } 254 255 func (sf *statFilter) DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type { 256 return filterChain.DmRowsColumnTypeScanType(r, index) 257 } 258 259 func (sf *statFilter) DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string { 260 return filterChain.DmRowsColumnTypeDatabaseTypeName(r, index) 261 } 262 263 func (sf *statFilter) DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) { 264 return filterChain.DmRowsColumnTypeLength(r, index) 265 } 266 267 func (sf *statFilter) DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) { 268 return filterChain.DmRowsColumnTypeNullable(r, index) 269 } 270 271 func (sf *statFilter) DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) { 272 return filterChain.DmRowsColumnTypePrecisionScale(r, index) 273 } 274 275 func getActiveStmtCount(conn *DmConnection) int { 276 if conn.stmtMap == nil { 277 return 0 278 } else { 279 return len(conn.stmtMap) 280 } 281 } 282 283 func statementCreateAfter(conn *DmConnection, stmt *DmStatement) { 284 stmt.statInfo.setConstructNano() 285 conn.statInfo.getConnStat().incrementStmt() 286 } 287 288 func connExecBefore(conn *DmConnection, sql string) { 289 conn.statInfo.setLastExecuteSql(sql) 290 conn.statInfo.setFirstResultSet(false) 291 conn.statInfo.setLastExecuteType(ExecuteUpdate) 292 internalBeforeConnExecute(conn, sql) 293 } 294 295 func connExecAfter(conn *DmConnection, sql string, args interface{}, updateCount int) { 296 internalAfterConnExecute(conn, args, updateCount) 297 } 298 299 func connQueryBefore(conn *DmConnection, sql string) { 300 conn.statInfo.setLastExecuteSql(sql) 301 conn.statInfo.setFirstResultSet(true) 302 conn.statInfo.setLastExecuteType(ExecuteQuery) 303 internalBeforeConnExecute(conn, sql) 304 } 305 306 func connQueryAfter(conn *DmConnection, sql string, args interface{}, resultSet *DmRows) { 307 if resultSet != nil { 308 connResultSetCreateAfter(resultSet, conn) 309 } 310 internalAfterConnExecute(conn, args, 0) 311 } 312 313 func stmtExecBefore(stmt *DmStatement) { 314 stmt.statInfo.setLastExecuteSql(stmt.nativeSql) 315 stmt.statInfo.setFirstResultSet(false) 316 stmt.statInfo.setLastExecuteType(ExecuteUpdate) 317 internalBeforeStatementExecute(stmt, stmt.nativeSql) 318 } 319 320 func stmtExecAfter(stmt *DmStatement, args interface{}, updateCount int) { 321 internalAfterStatementExecute(stmt, args, updateCount) 322 } 323 324 func stmtQueryBefore(stmt *DmStatement) { 325 stmt.statInfo.setLastExecuteSql(stmt.nativeSql) 326 stmt.statInfo.setFirstResultSet(true) 327 stmt.statInfo.setLastExecuteType(ExecuteQuery) 328 internalBeforeStatementExecute(stmt, stmt.nativeSql) 329 } 330 331 func stmtQueryAfter(stmt *DmStatement, args interface{}, resultSet *DmRows) { 332 if resultSet != nil { 333 stmtResultSetCreateAfter(resultSet, stmt) 334 } 335 internalAfterStatementExecute(stmt, args, 0) 336 } 337 338 func internalBeforeConnExecute(conn *DmConnection, sql string) { 339 connStat := conn.statInfo.getConnStat() 340 connStat.incrementExecuteCount() 341 conn.statInfo.beforeExecute() 342 343 sqlStat := conn.statInfo.getSqlStat() 344 if sqlStat == nil || sqlStat.Removed == 1 || !(sqlStat.Sql == sql) { 345 sqlStat = connStat.createSqlStat(sql) 346 conn.statInfo.setSqlStat(sqlStat) 347 } 348 349 inTransaction := false 350 inTransaction = !conn.autoCommit 351 352 if sqlStat != nil { 353 sqlStat.ExecuteLastStartTime = time.Now().UnixNano() 354 sqlStat.incrementRunningCount() 355 356 if inTransaction { 357 sqlStat.incrementInTransactionCount() 358 } 359 } 360 } 361 362 func internalAfterConnExecute(conn *DmConnection, args interface{}, updateCount int) { 363 nowNano := time.Now().UnixNano() 364 nanos := nowNano - conn.statInfo.getLastExecuteStartNano() 365 366 conn.statInfo.afterExecute(nanos) 367 368 sqlStat := conn.statInfo.getSqlStat() 369 370 if sqlStat != nil { 371 sqlStat.incrementExecuteSuccessCount() 372 373 sqlStat.decrementRunningCount() 374 375 parameters := buildSlowParameters(args) 376 377 sqlStat.addExecuteTimeAndResultHoldTimeHistogramRecord(conn.statInfo.getLastExecuteType(), conn.statInfo.isFirstResultSet(), 378 nanos, parameters) 379 380 if !conn.statInfo.isFirstResultSet() && 381 conn.statInfo.getLastExecuteType() == ExecuteUpdate { 382 if updateCount < 0 { 383 updateCount = 0 384 } 385 sqlStat.addUpdateCount(int64(updateCount)) 386 } 387 } 388 389 } 390 391 func internalBeforeStatementExecute(stmt *DmStatement, sql string) { 392 connStat := stmt.dmConn.statInfo.getConnStat() 393 connStat.incrementExecuteCount() 394 stmt.statInfo.beforeExecute() 395 396 sqlStat := stmt.statInfo.getSqlStat() 397 if sqlStat == nil || sqlStat.Removed == 1 || !(sqlStat.Sql == sql) { 398 sqlStat = connStat.createSqlStat(sql) 399 stmt.statInfo.setSqlStat(sqlStat) 400 } 401 402 inTransaction := false 403 inTransaction = !stmt.dmConn.autoCommit 404 405 if sqlStat != nil { 406 sqlStat.ExecuteLastStartTime = time.Now().UnixNano() 407 sqlStat.incrementRunningCount() 408 409 if inTransaction { 410 sqlStat.incrementInTransactionCount() 411 } 412 } 413 } 414 415 func internalAfterStatementExecute(stmt *DmStatement, args interface{}, updateCount int) { 416 nowNano := time.Now().UnixNano() 417 nanos := nowNano - stmt.statInfo.getLastExecuteStartNano() 418 419 stmt.statInfo.afterExecute(nanos) 420 421 sqlStat := stmt.statInfo.getSqlStat() 422 423 if sqlStat != nil { 424 sqlStat.incrementExecuteSuccessCount() 425 426 sqlStat.decrementRunningCount() 427 428 parameters := "" 429 if stmt.paramCount > 0 { 430 parameters = buildStmtSlowParameters(stmt, args) 431 } 432 sqlStat.addExecuteTimeAndResultHoldTimeHistogramRecord(stmt.statInfo.getLastExecuteType(), stmt.statInfo.isFirstResultSet(), 433 nanos, parameters) 434 435 if (!stmt.statInfo.isFirstResultSet()) && 436 stmt.statInfo.getLastExecuteType() == ExecuteUpdate { 437 updateCount := stmt.execInfo.updateCount 438 if updateCount < 0 { 439 updateCount = 0 440 } 441 sqlStat.addUpdateCount(updateCount) 442 } 443 444 } 445 446 } 447 448 func buildSlowParameters(args interface{}) string { 449 switch v := args.(type) { 450 case []driver.Value: 451 sb := bytes.NewBufferString("") 452 for i := 0; i < len(v); i++ { 453 if i != 0 { 454 sb.WriteString(",") 455 } else { 456 sb.WriteString("[") 457 } 458 459 sb.WriteString(fmt.Sprint(v[i])) 460 } 461 462 if len(v) > 0 { 463 sb.WriteString("]") 464 } 465 return sb.String() 466 case []driver.NamedValue: 467 sb := bytes.NewBufferString("") 468 for i := 0; i < len(v); i++ { 469 if i != 0 { 470 sb.WriteString(",") 471 } else { 472 sb.WriteString("[") 473 } 474 475 sb.WriteString(fmt.Sprint(v[i])) 476 } 477 if len(v) > 0 { 478 sb.WriteString("]") 479 } 480 return sb.String() 481 default: 482 return "" 483 } 484 } 485 486 func buildStmtSlowParameters(stmt *DmStatement, args interface{}) string { 487 switch v := args.(type) { 488 case []driver.Value: 489 sb := bytes.NewBufferString("") 490 for i := 0; i < int(stmt.paramCount); i++ { 491 if i != 0 { 492 sb.WriteString(",") 493 } else { 494 sb.WriteString("[") 495 } 496 497 sb.WriteString(fmt.Sprint(v[i])) 498 } 499 if len(v) > 0 { 500 sb.WriteString("]") 501 } 502 return sb.String() 503 case []driver.NamedValue: 504 sb := bytes.NewBufferString("") 505 for i := 0; i < int(stmt.paramCount); i++ { 506 if i != 0 { 507 sb.WriteString(",") 508 } else { 509 sb.WriteString("[") 510 } 511 512 sb.WriteString(fmt.Sprint(v[i])) 513 } 514 if len(v) > 0 { 515 sb.WriteString("]") 516 } 517 return sb.String() 518 default: 519 return "" 520 } 521 } 522 523 func connExecuteErrorAfter(conn *DmConnection, args interface{}, err error) { 524 nanos := time.Now().UnixNano() - conn.statInfo.getLastExecuteStartNano() 525 conn.statInfo.getConnStat().incrementErrorCount() 526 conn.statInfo.afterExecute(nanos) 527 528 // SQL 529 sqlStat := conn.statInfo.getSqlStat() 530 if sqlStat != nil { 531 sqlStat.decrementRunningCount() 532 sqlStat.error(err) 533 parameters := buildSlowParameters(args) 534 sqlStat.addExecuteTimeAndResultHoldTimeHistogramRecord(conn.statInfo.getLastExecuteType(), conn.statInfo.isFirstResultSet(), 535 nanos, parameters) 536 } 537 538 } 539 540 func statementExecuteErrorAfter(stmt *DmStatement, args interface{}, err error) { 541 nanos := time.Now().UnixNano() - stmt.statInfo.getLastExecuteStartNano() 542 stmt.dmConn.statInfo.getConnStat().incrementErrorCount() 543 stmt.statInfo.afterExecute(nanos) 544 545 // SQL 546 sqlStat := stmt.statInfo.getSqlStat() 547 if sqlStat != nil { 548 sqlStat.decrementRunningCount() 549 sqlStat.error(err) 550 parameters := "" 551 if stmt.paramCount > 0 { 552 parameters = buildStmtSlowParameters(stmt, args) 553 } 554 sqlStat.addExecuteTimeAndResultHoldTimeHistogramRecord(stmt.statInfo.getLastExecuteType(), stmt.statInfo.isFirstResultSet(), 555 nanos, parameters) 556 } 557 558 } 559 560 func statementCloseBefore(stmt *DmStatement) { 561 stmt.dmConn.statInfo.getConnStat().decrementStmt() 562 } 563 564 func connResultSetCreateAfter(dmdbResultSet *DmRows, conn *DmConnection) { 565 dmdbResultSet.statInfo.setSql(conn.statInfo.getLastExecuteSql()) 566 dmdbResultSet.statInfo.setSqlStat(conn.statInfo.getSqlStat()) 567 dmdbResultSet.statInfo.setConstructNano() 568 } 569 570 func stmtResultSetCreateAfter(dmdbResultSet *DmRows, stmt *DmStatement) { 571 dmdbResultSet.statInfo.setSql(stmt.statInfo.getLastExecuteSql()) 572 dmdbResultSet.statInfo.setSqlStat(stmt.statInfo.getSqlStat()) 573 dmdbResultSet.statInfo.setConstructNano() 574 } 575 576 func resultSetCloseBefore(resultSet *DmRows) { 577 nanos := time.Now().UnixNano() - resultSet.statInfo.getConstructNano() 578 fetchRowCount := getFetchedRows(resultSet) 579 sqlStat := resultSet.statInfo.getSqlStat() 580 if sqlStat != nil && resultSet.statInfo.getCloseCount() == 0 { 581 sqlStat.addFetchRowCount(fetchRowCount) 582 stmtExecuteNano := resultSet.statInfo.getLastExecuteTimeNano() 583 sqlStat.addResultSetHoldTimeNano2(stmtExecuteNano, nanos) 584 if resultSet.statInfo.getReadStringLength() > 0 { 585 sqlStat.addStringReadLength(resultSet.statInfo.getReadStringLength()) 586 } 587 if resultSet.statInfo.getReadBytesLength() > 0 { 588 sqlStat.addReadBytesLength(resultSet.statInfo.getReadBytesLength()) 589 } 590 if resultSet.statInfo.getOpenInputStreamCount() > 0 { 591 sqlStat.addInputStreamOpenCount(int64(resultSet.statInfo.getOpenInputStreamCount())) 592 } 593 if resultSet.statInfo.getOpenReaderCount() > 0 { 594 sqlStat.addReaderOpenCount(int64(resultSet.statInfo.getOpenReaderCount())) 595 } 596 } 597 598 resultSet.statInfo.incrementCloseCount() 599 } 600 601 func getFetchedRows(rs *DmRows) int64 { 602 if rs.CurrentRows.currentPos >= rs.CurrentRows.totalRowCount { 603 return rs.CurrentRows.totalRowCount 604 } else { 605 return rs.CurrentRows.currentPos + 1 606 } 607 }