You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

sql.go 11 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. // Copyright 2011 The Go Authors. All rights reserved.
  18. // Use of this source code is governed by a BSD-style
  19. // license that can be found in the LICENSE file.
  20. // Package sql provides a generic interface around SQL (or SQL-like)
  21. // databases.
  22. //
  23. // The sql package must be used in conjunction with a database driver.
  24. // See https://golang.org/s/sqldrivers for a list of drivers.
  25. //
  26. // Drivers that do not support context cancellation will not return until
  27. // after the query is completed.
  28. //
  29. // For usage examples, see the wiki page at
  30. // https://golang.org/s/sqlwiki.
  31. package util
  32. import (
  33. "context"
  34. "database/sql/driver"
  35. "errors"
  36. "fmt"
  37. "io"
  38. "sync"
  39. )
  40. // ScanRows is the result of a query. Its cursor starts before the first row
  41. // of the result set. Use Next to advance from row to row.
  42. type ScanRows struct {
  43. //dc *driverConn // owned; must call releaseConn when closed to release
  44. dc driver.Conn
  45. releaseConn func(error)
  46. rowsi driver.Rows
  47. cancel func() // called when ScanRows is closed, may be nil.
  48. //closeStmt *driverStmt // if non-nil, statement to Close on close
  49. // closemu prevents ScanRows from closing while there
  50. // is an active streaming result. It is held for read during non-close operations
  51. // and exclusively during close.
  52. //
  53. // closemu guards lasterr and closed.
  54. closemu sync.RWMutex
  55. closed bool
  56. lasterr error // non-nil only if closed is true
  57. // lastcols is only used in Scan, Next, and NextResultSet which are expected
  58. // not to be called concurrently.
  59. lastcols []driver.Value
  60. }
  61. func NewScanRows(rowsi driver.Rows) *ScanRows {
  62. return &ScanRows{rowsi: rowsi}
  63. }
  64. // lasterrOrErrLocked returns either lasterr or the provided err.
  65. // rs.closemu must be read-locked.
  66. func (rs *ScanRows) lasterrOrErrLocked(err error) error {
  67. if rs.lasterr != nil && rs.lasterr != io.EOF {
  68. return rs.lasterr
  69. }
  70. return err
  71. }
  72. // bypassRowsAwaitDone is only used for testing.
  73. // If true, it will not close the ScanRows automatically from the context.
  74. var bypassRowsAwaitDone = false
  75. func (rs *ScanRows) initContextClose(ctx, txctx context.Context) {
  76. if ctx.Done() == nil && (txctx == nil || txctx.Done() == nil) {
  77. return
  78. }
  79. if bypassRowsAwaitDone {
  80. return
  81. }
  82. ctx, rs.cancel = context.WithCancel(ctx)
  83. go rs.awaitDone(ctx, txctx)
  84. }
  85. // awaitDone blocks until either ctx or txctx is canceled. The ctx is provided
  86. // from the query context and is canceled when the query ScanRows is closed.
  87. // If the query was issued in a transaction, the transaction's context
  88. // is also provided in txctx to ensure ScanRows is closed if the Tx is closed.
  89. func (rs *ScanRows) awaitDone(ctx, txctx context.Context) {
  90. var txctxDone <-chan struct{}
  91. if txctx != nil {
  92. txctxDone = txctx.Done()
  93. }
  94. select {
  95. case <-ctx.Done():
  96. case <-txctxDone:
  97. }
  98. rs.close(ctx.Err())
  99. }
  100. // Next prepares the next result row for reading with the Scan method. It
  101. // returns true on success, or false if there is no next result row or an error
  102. // happened while preparing it. Err should be consulted to distinguish between
  103. // the two cases.
  104. //
  105. // Every call to Scan, even the first one, must be preceded by a call to Next.
  106. func (rs *ScanRows) Next() bool {
  107. var doClose, ok bool
  108. withLock(rs.closemu.RLocker(), func() {
  109. doClose, ok = rs.nextLocked()
  110. })
  111. if doClose {
  112. rs.Close()
  113. }
  114. return ok
  115. }
  116. func (rs *ScanRows) nextLocked() (doClose, ok bool) {
  117. if rs.closed {
  118. return false, false
  119. }
  120. // Lock the driver connection before calling the driver interface
  121. // rowsi to prevent a Tx from rolling back the connection at the same time.
  122. //rs.dc.Lock()
  123. //defer rs.dc.Unlock()
  124. if rs.lastcols == nil {
  125. rs.lastcols = make([]driver.Value, len(rs.rowsi.Columns()))
  126. }
  127. rs.lasterr = rs.rowsi.Next(rs.lastcols)
  128. if rs.lasterr != nil {
  129. // Close the connection if there is a driver error.
  130. if rs.lasterr != io.EOF {
  131. return true, false
  132. }
  133. nextResultSet, ok := rs.rowsi.(driver.RowsNextResultSet)
  134. if !ok {
  135. return true, false
  136. }
  137. // The driver is at the end of the current result set.
  138. // Test to see if there is another result set after the current one.
  139. // Only close ScanRows if there is no further result sets to read.
  140. if !nextResultSet.HasNextResultSet() {
  141. doClose = true
  142. }
  143. return doClose, false
  144. }
  145. return false, true
  146. }
  147. // NextResultSet prepares the next result set for reading. It reports whether
  148. // there is further result sets, or false if there is no further result set
  149. // or if there is an error advancing to it. The Err method should be consulted
  150. // to distinguish between the two cases.
  151. //
  152. // After calling NextResultSet, the Next method should always be called before
  153. // scanning. If there are further result sets they may not have rows in the result
  154. // set.
  155. func (rs *ScanRows) NextResultSet() bool {
  156. var doClose bool
  157. defer func() {
  158. if doClose {
  159. rs.Close()
  160. }
  161. }()
  162. rs.closemu.RLock()
  163. defer rs.closemu.RUnlock()
  164. if rs.closed {
  165. return false
  166. }
  167. rs.lastcols = nil
  168. nextResultSet, ok := rs.rowsi.(driver.RowsNextResultSet)
  169. if !ok {
  170. doClose = true
  171. return false
  172. }
  173. // Lock the driver connection before calling the driver interface
  174. // rowsi to prevent a Tx from rolling back the connection at the same time.
  175. //rs.dc.Lock()
  176. //defer rs.dc.Unlock()
  177. rs.lasterr = nextResultSet.NextResultSet()
  178. if rs.lasterr != nil {
  179. doClose = true
  180. return false
  181. }
  182. return true
  183. }
  184. // Err returns the error, if any, that was encountered during iteration.
  185. // Err may be called after an explicit or implicit Close.
  186. func (rs *ScanRows) Err() error {
  187. rs.closemu.RLock()
  188. defer rs.closemu.RUnlock()
  189. return rs.lasterrOrErrLocked(nil)
  190. }
  191. //
  192. var errRowsClosed = errors.New("sql: ScanRows are closed")
  193. // Scan copies the columns in the current row into the values pointed
  194. // at by dest. The number of values in dest must be the same as the
  195. // number of columns in ScanRows.
  196. //
  197. // Scan converts columns read from the database into the following
  198. // common Go types and special types provided by the sql package:
  199. //
  200. // *string
  201. // *[]byte
  202. // *int, *int8, *int16, *int32, *int64
  203. // *uint, *uint8, *uint16, *uint32, *uint64
  204. // *bool
  205. // *float32, *float64
  206. // *interface{}
  207. // *RawBytes
  208. // *ScanRows (cursor value)
  209. // any type implementing Scanner (see Scanner docs)
  210. //
  211. // In the most simple case, if the type of the value from the source
  212. // column is an integer, bool or string type T and dest is of type *T,
  213. // Scan simply assigns the value through the pointer.
  214. //
  215. // Scan also converts between string and numeric types, as long as no
  216. // information would be lost. While Scan stringifies all numbers
  217. // scanned from numeric database columns into *string, scans into
  218. // numeric types are checked for overflow. For example, a float64 with
  219. // value 300 or a string with value "300" can scan into a uint16, but
  220. // not into a uint8, though float64(255) or "255" can scan into a
  221. // uint8. One exception is that scans of some float64 numbers to
  222. // strings may lose information when stringifying. In general, scan
  223. // floating point columns into *float64.
  224. //
  225. // If a dest argument has type *[]byte, Scan saves in that argument a
  226. // copy of the corresponding data. The copy is owned by the caller and
  227. // can be modified and held indefinitely. The copy can be avoided by
  228. // using an argument of type *RawBytes instead; see the documentation
  229. // for RawBytes for restrictions on its use.
  230. //
  231. // If an argument has type *interface{}, Scan copies the value
  232. // provided by the underlying driver without conversion. When scanning
  233. // from a source value of type []byte to *interface{}, a copy of the
  234. // slice is made and the caller owns the result.
  235. //
  236. // Source values of type time.Time may be scanned into values of type
  237. // *time.Time, *interface{}, *string, or *[]byte. When converting to
  238. // the latter two, time.RFC3339Nano is used.
  239. //
  240. // Source values of type bool may be scanned into types *bool,
  241. // *interface{}, *string, *[]byte, or *RawBytes.
  242. //
  243. // For scanning into *bool, the source may be true, false, 1, 0, or
  244. // string inputs parseable by strconv.ParseBool.
  245. //
  246. // Scan can also convert a cursor returned from a query, such as
  247. // "select cursor(select * from my_table) from dual", into a
  248. // *ScanRows value that can itself be scanned from. The parent
  249. // select query will close any cursor *ScanRows if the parent *ScanRows is closed.
  250. //
  251. // If any of the first arguments implementing Scanner returns an error,
  252. // that error will be wrapped in the returned error
  253. func (rs *ScanRows) Scan(dest ...interface{}) error {
  254. rs.closemu.RLock()
  255. if rs.lasterr != nil && rs.lasterr != io.EOF {
  256. rs.closemu.RUnlock()
  257. return rs.lasterr
  258. }
  259. if rs.closed {
  260. err := rs.lasterrOrErrLocked(errRowsClosed)
  261. rs.closemu.RUnlock()
  262. return err
  263. }
  264. rs.closemu.RUnlock()
  265. if rs.lastcols == nil {
  266. return errors.New("sql: Scan called without calling Next")
  267. }
  268. if len(dest) != len(rs.lastcols) {
  269. return fmt.Errorf("sql: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest))
  270. }
  271. for i, sv := range rs.lastcols {
  272. err := convertAssignRows(dest[i], sv, rs)
  273. if err != nil {
  274. return fmt.Errorf(`sql: Scan error on column index %d, name %q: %w`, i, rs.rowsi.Columns()[i], err)
  275. }
  276. }
  277. return nil
  278. }
  279. // rowsCloseHook returns a function so tests may install the
  280. // hook through a test only mutex.
  281. var rowsCloseHook = func() func(*ScanRows, *error) { return nil }
  282. // Close closes the ScanRows, preventing further enumeration. If Next is called
  283. // and returns false and there are no further result sets,
  284. // the ScanRows are closed automatically and it will suffice to check the
  285. // result of Err. Close is idempotent and does not affect the result of Err.
  286. func (rs *ScanRows) Close() error {
  287. //return rs.close(nil)
  288. return nil
  289. }
  290. func (rs *ScanRows) close(err error) error {
  291. rs.closemu.Lock()
  292. defer rs.closemu.Unlock()
  293. if rs.closed {
  294. return nil
  295. }
  296. rs.closed = true
  297. if rs.lasterr == nil {
  298. rs.lasterr = err
  299. }
  300. err = rs.rowsi.Close()
  301. //withLock(rs.dc, func() {
  302. // err = rs.rowsi.Close()
  303. //})
  304. if fn := rowsCloseHook(); fn != nil {
  305. fn(rs, &err)
  306. }
  307. if rs.cancel != nil {
  308. rs.cancel()
  309. }
  310. //if rs.closeStmt != nil {
  311. // rs.closeStmt.Close()
  312. //}
  313. rs.releaseConn(err)
  314. return err
  315. }
  316. // withLock runs while holding lk.
  317. func withLock(lk sync.Locker, fn func()) {
  318. lk.Lock()
  319. defer lk.Unlock() // in case fn panics
  320. fn()
  321. }