github.com/xiyichan/dm8@v0.0.0-20211213021639-be727be3e136/v.go (about)

     1  /*
     2   * Copyright (c) 2000-2018, 达梦数据库有限公司.
     3   * All rights reserved.
     4   */
     5  package dm
     6  
     7  import (
     8  	"database/sql/driver"
     9  	"io"
    10  	"reflect"
    11  )
    12  
    13  type DmRows struct {
    14  	filterable
    15  	CurrentRows *innerRows
    16  	finish      func()
    17  }
    18  
    19  func (r *DmRows) Columns() []string {
    20  	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
    21  		return nil
    22  	}
    23  	if len(r.filterChain.filters) == 0 {
    24  		return r.columns()
    25  	}
    26  	return r.filterChain.reset().DmRowsColumns(r)
    27  }
    28  
    29  func (r *DmRows) Close() error {
    30  	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
    31  		return err
    32  	}
    33  	if len(r.filterChain.filters) == 0 {
    34  		return r.close()
    35  	}
    36  	return r.filterChain.reset().DmRowsClose(r)
    37  }
    38  
    39  func (r *DmRows) Next(dest []driver.Value) error {
    40  	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
    41  		return err
    42  	}
    43  	if len(r.filterChain.filters) == 0 {
    44  		return r.next(dest)
    45  	}
    46  	return r.filterChain.reset().DmRowsNext(r, dest)
    47  }
    48  
    49  func (r *DmRows) HasNextResultSet() bool {
    50  	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
    51  		return false
    52  	}
    53  	if len(r.filterChain.filters) == 0 {
    54  		return r.hasNextResultSet()
    55  	}
    56  	return r.filterChain.reset().DmRowsHasNextResultSet(r)
    57  }
    58  
    59  func (r *DmRows) NextResultSet() error {
    60  	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
    61  		return err
    62  	}
    63  	if len(r.filterChain.filters) == 0 {
    64  		return r.nextResultSet()
    65  	}
    66  	return r.filterChain.reset().DmRowsNextResultSet(r)
    67  }
    68  
    69  func (r *DmRows) ColumnTypeScanType(index int) reflect.Type {
    70  	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
    71  		return nil
    72  	}
    73  	if len(r.filterChain.filters) == 0 {
    74  		return r.columnTypeScanType(index)
    75  	}
    76  	return r.filterChain.reset().DmRowsColumnTypeScanType(r, index)
    77  }
    78  
    79  func (r *DmRows) ColumnTypeDatabaseTypeName(index int) string {
    80  	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
    81  		return ""
    82  	}
    83  	if len(r.filterChain.filters) == 0 {
    84  		return r.columnTypeDatabaseTypeName(index)
    85  	}
    86  	return r.filterChain.reset().DmRowsColumnTypeDatabaseTypeName(r, index)
    87  }
    88  
    89  func (r *DmRows) ColumnTypeLength(index int) (length int64, ok bool) {
    90  	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
    91  		return -1, false
    92  	}
    93  	if len(r.filterChain.filters) == 0 {
    94  		return r.columnTypeLength(index)
    95  	}
    96  	return r.filterChain.reset().DmRowsColumnTypeLength(r, index)
    97  }
    98  
    99  func (r *DmRows) ColumnTypeNullable(index int) (nullable, ok bool) {
   100  	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
   101  		return false, false
   102  	}
   103  	if len(r.filterChain.filters) == 0 {
   104  		return r.columnTypeNullable(index)
   105  	}
   106  	return r.filterChain.reset().DmRowsColumnTypeNullable(r, index)
   107  }
   108  
   109  func (r *DmRows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
   110  	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
   111  		return -1, -1, false
   112  	}
   113  	if len(r.filterChain.filters) == 0 {
   114  		return r.columnTypePrecisionScale(index)
   115  	}
   116  	return r.filterChain.reset().DmRowsColumnTypePrecisionScale(r, index)
   117  }
   118  
   119  func (rows *DmRows) columns() []string {
   120  	return rows.CurrentRows.Columns()
   121  }
   122  
   123  func (rows *DmRows) close() error {
   124  	if f := rows.finish; f != nil {
   125  		f()
   126  		rows.finish = nil
   127  	}
   128  	return rows.CurrentRows.Close()
   129  }
   130  
   131  func (rows *DmRows) next(dest []driver.Value) error {
   132  	return rows.CurrentRows.Next(dest)
   133  }
   134  
   135  func (rows *DmRows) hasNextResultSet() bool {
   136  	return rows.CurrentRows.HasNextResultSet()
   137  }
   138  
   139  func (rows *DmRows) nextResultSet() error {
   140  	return rows.CurrentRows.NextResultSet()
   141  }
   142  
   143  func (rows *DmRows) columnTypeScanType(index int) reflect.Type {
   144  	return rows.CurrentRows.ColumnTypeScanType(index)
   145  }
   146  
   147  func (rows *DmRows) columnTypeDatabaseTypeName(index int) string {
   148  	return rows.CurrentRows.ColumnTypeDatabaseTypeName(index)
   149  }
   150  
   151  func (rows *DmRows) columnTypeLength(index int) (length int64, ok bool) {
   152  	return rows.CurrentRows.ColumnTypeLength(index)
   153  }
   154  
   155  func (rows *DmRows) columnTypeNullable(index int) (nullable, ok bool) {
   156  	return rows.CurrentRows.ColumnTypeNullable(index)
   157  }
   158  
   159  func (rows *DmRows) columnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
   160  	return rows.CurrentRows.ColumnTypePrecisionScale(index)
   161  }
   162  
   163  type innerRows struct {
   164  	dmStmt *DmStatement
   165  
   166  	id int16
   167  
   168  	columns []column
   169  
   170  	datas [][][]byte
   171  
   172  	datasOffset int
   173  
   174  	datasStartPos int64
   175  
   176  	currentPos int64
   177  
   178  	totalRowCount int64
   179  
   180  	fetchSize int
   181  
   182  	sizeOfRow int
   183  
   184  	isBdta bool
   185  
   186  	nextExecInfo *execInfo
   187  
   188  	next *innerRows
   189  
   190  	dmRows *DmRows
   191  
   192  	closed bool
   193  }
   194  
   195  func (innerRows *innerRows) checkClosed() error {
   196  	if innerRows.closed {
   197  		return ECGO_RESULTSET_CLOSED.throw()
   198  	}
   199  	return nil
   200  }
   201  
   202  func (innerRows *innerRows) Columns() []string {
   203  	err := innerRows.checkClosed()
   204  	if err != nil {
   205  		panic(err)
   206  	}
   207  
   208  	columnNames := make([]string, len(innerRows.columns))
   209  
   210  	for i, column := range innerRows.columns {
   211  		columnNames[i] = column.name
   212  	}
   213  
   214  	return columnNames
   215  }
   216  
   217  func (innerRows *innerRows) Close() error {
   218  	if innerRows.closed {
   219  		return nil
   220  	}
   221  
   222  	innerRows.closed = true
   223  
   224  	if innerRows.dmStmt.innerUsed {
   225  		innerRows.dmStmt.close()
   226  	} else {
   227  		delete(innerRows.dmStmt.rsMap, innerRows.id)
   228  	}
   229  
   230  	innerRows.dmStmt = nil
   231  
   232  	return nil
   233  }
   234  
   235  func (innerRows *innerRows) Next(dest []driver.Value) error {
   236  	err := innerRows.checkClosed()
   237  	if err != nil {
   238  		return err
   239  	}
   240  
   241  	if innerRows.totalRowCount == 0 || innerRows.currentPos >= innerRows.totalRowCount {
   242  		return io.EOF
   243  	}
   244  
   245  	if innerRows.currentPos+1 == innerRows.totalRowCount {
   246  		innerRows.currentPos++
   247  		innerRows.datasOffset++
   248  		return io.EOF
   249  	}
   250  
   251  	if innerRows.currentPos+1 < innerRows.datasStartPos || innerRows.currentPos+1 >= innerRows.datasStartPos+int64(len(innerRows.datas)) {
   252  		if innerRows.fetchData(innerRows.currentPos + 1) {
   253  			innerRows.currentPos++
   254  			err := innerRows.getRowData(dest)
   255  			if err != nil {
   256  				return err
   257  			}
   258  		} else {
   259  			innerRows.currentPos++
   260  			innerRows.datasOffset++
   261  			return io.EOF
   262  		}
   263  	} else {
   264  		innerRows.currentPos++
   265  		innerRows.datasOffset++
   266  		err := innerRows.getRowData(dest)
   267  		if err != nil {
   268  			return err
   269  		}
   270  	}
   271  
   272  	return nil
   273  }
   274  
   275  func (innerRows *innerRows) HasNextResultSet() bool {
   276  	err := innerRows.checkClosed()
   277  	if err != nil {
   278  		panic(err)
   279  	}
   280  
   281  	if innerRows.nextExecInfo != nil {
   282  		return innerRows.nextExecInfo.hasResultSet
   283  	}
   284  
   285  	innerRows.nextExecInfo, err = innerRows.dmStmt.dmConn.Access.Dm_build_1401(innerRows.dmStmt, 0)
   286  	if err != nil {
   287  		panic(err)
   288  	}
   289  
   290  	if innerRows.nextExecInfo.hasResultSet {
   291  		innerRows.next = newInnerRows(innerRows.id+1, innerRows.dmStmt, innerRows.nextExecInfo)
   292  		return true
   293  	}
   294  
   295  	return false
   296  }
   297  
   298  func (innerRows *innerRows) NextResultSet() error {
   299  	err := innerRows.checkClosed()
   300  	if err != nil {
   301  		return err
   302  	}
   303  
   304  	if innerRows.nextExecInfo == nil {
   305  		innerRows.HasNextResultSet()
   306  	}
   307  
   308  	if innerRows.next == nil {
   309  		return io.EOF
   310  	}
   311  
   312  	innerRows.next.dmRows = innerRows.dmRows
   313  	innerRows.dmRows.CurrentRows = innerRows.next
   314  	return nil
   315  }
   316  
   317  func (innerRows *innerRows) ColumnTypeScanType(index int) reflect.Type {
   318  	err := innerRows.checkClosed()
   319  	if err != nil {
   320  		panic(err)
   321  	}
   322  	column := innerRows.checkIndex(index)
   323  	return column.ScanType()
   324  }
   325  
   326  func (innerRows *innerRows) ColumnTypeDatabaseTypeName(index int) string {
   327  	err := innerRows.checkClosed()
   328  	if err != nil {
   329  		panic(err)
   330  	}
   331  	column := innerRows.checkIndex(index)
   332  	return column.typeName
   333  }
   334  
   335  func (innerRows *innerRows) ColumnTypeLength(index int) (length int64, ok bool) {
   336  	err := innerRows.checkClosed()
   337  	if err != nil {
   338  		panic(err)
   339  	}
   340  	column := innerRows.checkIndex(index)
   341  	return column.Length()
   342  }
   343  
   344  func (innerRows *innerRows) ColumnTypeNullable(index int) (nullable, ok bool) {
   345  	err := innerRows.checkClosed()
   346  	if err != nil {
   347  		panic(err)
   348  	}
   349  	column := innerRows.checkIndex(index)
   350  	return column.nullable, true
   351  }
   352  
   353  func (innerRows *innerRows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
   354  	err := innerRows.checkClosed()
   355  	if err != nil {
   356  		panic(err)
   357  	}
   358  	column := innerRows.checkIndex(index)
   359  	return column.PrecisionScale()
   360  }
   361  
   362  func newDmRows(currentRows *innerRows) *DmRows {
   363  	dr := new(DmRows)
   364  	dr.resetFilterable(&currentRows.dmStmt.filterable)
   365  	dr.CurrentRows = currentRows
   366  	dr.idGenerator = dmRowsIDGenerator
   367  	currentRows.dmRows = dr
   368  	return dr
   369  }
   370  
   371  func newInnerRows(id int16, stmt *DmStatement, execInfo *execInfo) *innerRows {
   372  	rows := new(innerRows)
   373  	rows.id = id
   374  	rows.dmStmt = stmt
   375  	rows.columns = stmt.columns
   376  	rows.datas = execInfo.rsDatas
   377  	rows.totalRowCount = execInfo.updateCount
   378  	rows.isBdta = execInfo.rsBdta
   379  	rows.fetchSize = stmt.fetchSize
   380  
   381  	if len(execInfo.rsDatas) == 0 {
   382  		rows.sizeOfRow = 0
   383  	} else {
   384  		rows.sizeOfRow = execInfo.rsSizeof / len(execInfo.rsDatas)
   385  	}
   386  
   387  	rows.currentPos = -1
   388  	rows.datasOffset = -1
   389  	rows.datasStartPos = 0
   390  
   391  	rows.nextExecInfo = nil
   392  	rows.next = nil
   393  
   394  	if rows.dmStmt.rsMap != nil {
   395  		rows.dmStmt.rsMap[rows.id] = rows
   396  	}
   397  
   398  	if stmt.dmConn.dmConnector.enRsCache && execInfo.rsCacheOffset > 0 &&
   399  		int64(len(execInfo.rsDatas)) == execInfo.updateCount {
   400  		rp.put(stmt, stmt.nativeSql, execInfo)
   401  	}
   402  
   403  	return rows
   404  }
   405  
   406  func newLocalInnerRows(stmt *DmStatement, columns []column, rsDatas [][][]byte) *innerRows {
   407  	rows := new(innerRows)
   408  	rows.id = 0
   409  	rows.dmStmt = stmt
   410  	rows.fetchSize = stmt.fetchSize
   411  
   412  	if columns == nil {
   413  		rows.columns = make([]column, 0)
   414  	} else {
   415  		rows.columns = columns
   416  	}
   417  
   418  	if rsDatas == nil {
   419  		rows.datas = make([][][]byte, 0)
   420  		rows.totalRowCount = 0
   421  	} else {
   422  		rows.datas = rsDatas
   423  		rows.totalRowCount = int64(len(rsDatas))
   424  	}
   425  
   426  	rows.isBdta = false
   427  	return rows
   428  }
   429  
   430  func (innerRows *innerRows) checkIndex(index int) *column {
   431  	if index < 0 || index > len(innerRows.columns)-1 {
   432  		panic(ECGO_INVALID_SEQUENCE_NUMBER)
   433  	}
   434  
   435  	return &innerRows.columns[index]
   436  }
   437  
   438  func (innerRows *innerRows) fetchData(startPos int64) bool {
   439  	execInfo, err := innerRows.dmStmt.dmConn.Access.Dm_build_1408(innerRows, startPos)
   440  	if err != nil {
   441  		panic(err)
   442  	}
   443  
   444  	innerRows.totalRowCount = execInfo.updateCount
   445  	if execInfo.rsDatas != nil {
   446  		innerRows.datas = execInfo.rsDatas
   447  		innerRows.datasStartPos = startPos
   448  		innerRows.datasOffset = 0
   449  		return true
   450  	}
   451  
   452  	return false
   453  }
   454  
   455  func (innerRows *innerRows) getRowData(dest []driver.Value) (err error) {
   456  	for i, column := range innerRows.columns {
   457  
   458  		if i <= len(dest)-1 {
   459  			if column.colType == CURSOR {
   460  				var tmpExecInfo *execInfo
   461  				tmpExecInfo, err = innerRows.dmStmt.dmConn.Access.Dm_build_1401(innerRows.dmStmt, 1)
   462  				if err != nil {
   463  					return err
   464  				}
   465  
   466  				if tmpExecInfo.hasResultSet {
   467  					dest[i] = newDmRows(newInnerRows(innerRows.id+1, innerRows.dmStmt, tmpExecInfo))
   468  				} else {
   469  					dest[i] = nil
   470  				}
   471  				continue
   472  			}
   473  
   474  			dest[i], err = column.getColumnData(innerRows.datas[innerRows.datasOffset][i+1], innerRows.dmStmt.dmConn)
   475  			innerRows.columns[i].isBdta = innerRows.isBdta
   476  			if err != nil {
   477  				return err
   478  			}
   479  		} else {
   480  			return nil
   481  		}
   482  	}
   483  
   484  	return nil
   485  }
   486  
   487  func (innerRows *innerRows) getRowCount() int64 {
   488  	innerRows.checkClosed()
   489  
   490  	if innerRows.totalRowCount == INT64_MAX {
   491  		return -1
   492  	}
   493  
   494  	return innerRows.totalRowCount
   495  }