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