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  }