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(¤tRows.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 }