fakedb_test.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package sql
  5. import (
  6. "context"
  7. "database/sql/driver"
  8. "errors"
  9. "fmt"
  10. "io"
  11. "reflect"
  12. "sort"
  13. "strconv"
  14. "strings"
  15. "sync"
  16. "testing"
  17. "time"
  18. )
  19. // fakeDriver is a fake database that implements Go's driver.Driver
  20. // interface, just for testing.
  21. //
  22. // It speaks a query language that's semantically similar to but
  23. // syntactically different and simpler than SQL. The syntax is as
  24. // follows:
  25. //
  26. // WIPE
  27. // CREATE|<tablename>|<col>=<type>,<col>=<type>,...
  28. // where types are: "string", [u]int{8,16,32,64}, "bool"
  29. // INSERT|<tablename>|col=val,col2=val2,col3=?
  30. // SELECT|<tablename>|projectcol1,projectcol2|filtercol=?,filtercol2=?
  31. // SELECT|<tablename>|projectcol1,projectcol2|filtercol=?param1,filtercol2=?param2
  32. //
  33. // Any of these can be preceded by PANIC|<method>|, to cause the
  34. // named method on fakeStmt to panic.
  35. //
  36. // Any of these can be proceeded by WAIT|<duration>|, to cause the
  37. // named method on fakeStmt to sleep for the specified duration.
  38. //
  39. // Multiple of these can be combined when separated with a semicolon.
  40. //
  41. // When opening a fakeDriver's database, it starts empty with no
  42. // tables. All tables and data are stored in memory only.
  43. type fakeDriver struct {
  44. mu sync.Mutex // guards 3 following fields
  45. openCount int // conn opens
  46. closeCount int // conn closes
  47. waitCh chan struct{}
  48. waitingCh chan struct{}
  49. dbs map[string]*fakeDB
  50. }
  51. type fakeConnector struct {
  52. name string
  53. waiter func(context.Context)
  54. closed bool
  55. }
  56. func (c *fakeConnector) Connect(context.Context) (driver.Conn, error) {
  57. conn, err := fdriver.Open(c.name)
  58. conn.(*fakeConn).waiter = c.waiter
  59. return conn, err
  60. }
  61. func (c *fakeConnector) Driver() driver.Driver {
  62. return fdriver
  63. }
  64. func (c *fakeConnector) Close() error {
  65. if c.closed {
  66. return errors.New("fakedb: connector is closed")
  67. }
  68. c.closed = true
  69. return nil
  70. }
  71. type fakeDriverCtx struct {
  72. fakeDriver
  73. }
  74. var _ driver.DriverContext = &fakeDriverCtx{}
  75. func (cc *fakeDriverCtx) OpenConnector(name string) (driver.Connector, error) {
  76. return &fakeConnector{name: name}, nil
  77. }
  78. type fakeDB struct {
  79. name string
  80. mu sync.Mutex
  81. tables map[string]*table
  82. badConn bool
  83. allowAny bool
  84. }
  85. type fakeError struct {
  86. Message string
  87. Wrapped error
  88. }
  89. func (err fakeError) Error() string {
  90. return err.Message
  91. }
  92. func (err fakeError) Unwrap() error {
  93. return err.Wrapped
  94. }
  95. type table struct {
  96. mu sync.Mutex
  97. colname []string
  98. coltype []string
  99. rows []*row
  100. }
  101. func (t *table) columnIndex(name string) int {
  102. for n, nname := range t.colname {
  103. if name == nname {
  104. return n
  105. }
  106. }
  107. return -1
  108. }
  109. type row struct {
  110. cols []any // must be same size as its table colname + coltype
  111. }
  112. type memToucher interface {
  113. // touchMem reads & writes some memory, to help find data races.
  114. touchMem()
  115. }
  116. type fakeConn struct {
  117. db *fakeDB // where to return ourselves to
  118. currTx *fakeTx
  119. // Every operation writes to line to enable the race detector
  120. // check for data races.
  121. line int64
  122. // Stats for tests:
  123. mu sync.Mutex
  124. stmtsMade int
  125. stmtsClosed int
  126. numPrepare int
  127. // bad connection tests; see isBad()
  128. bad bool
  129. stickyBad bool
  130. skipDirtySession bool // tests that use Conn should set this to true.
  131. // dirtySession tests ResetSession, true if a query has executed
  132. // until ResetSession is called.
  133. dirtySession bool
  134. // The waiter is called before each query. May be used in place of the "WAIT"
  135. // directive.
  136. waiter func(context.Context)
  137. }
  138. func (c *fakeConn) touchMem() {
  139. c.line++
  140. }
  141. func (c *fakeConn) incrStat(v *int) {
  142. c.mu.Lock()
  143. *v++
  144. c.mu.Unlock()
  145. }
  146. type fakeTx struct {
  147. c *fakeConn
  148. }
  149. type boundCol struct {
  150. Column string
  151. Placeholder string
  152. Ordinal int
  153. }
  154. type fakeStmt struct {
  155. memToucher
  156. c *fakeConn
  157. q string // just for debugging
  158. cmd string
  159. table string
  160. panic string
  161. wait time.Duration
  162. next *fakeStmt // used for returning multiple results.
  163. closed bool
  164. colName []string // used by CREATE, INSERT, SELECT (selected columns)
  165. colType []string // used by CREATE
  166. colValue []any // used by INSERT (mix of strings and "?" for bound params)
  167. placeholders int // used by INSERT/SELECT: number of ? params
  168. whereCol []boundCol // used by SELECT (all placeholders)
  169. placeholderConverter []driver.ValueConverter // used by INSERT
  170. }
  171. var fdriver driver.Driver = &fakeDriver{}
  172. func init() {
  173. Register("test", fdriver)
  174. }
  175. func contains(list []string, y string) bool {
  176. for _, x := range list {
  177. if x == y {
  178. return true
  179. }
  180. }
  181. return false
  182. }
  183. type Dummy struct {
  184. driver.Driver
  185. }
  186. func TestDrivers(t *testing.T) {
  187. unregisterAllDrivers()
  188. Register("test", fdriver)
  189. Register("invalid", Dummy{})
  190. all := Drivers()
  191. if len(all) < 2 || !sort.StringsAreSorted(all) || !contains(all, "test") || !contains(all, "invalid") {
  192. t.Fatalf("Drivers = %v, want sorted list with at least [invalid, test]", all)
  193. }
  194. }
  195. // hook to simulate connection failures
  196. var hookOpenErr struct {
  197. sync.Mutex
  198. fn func() error
  199. }
  200. func setHookOpenErr(fn func() error) {
  201. hookOpenErr.Lock()
  202. defer hookOpenErr.Unlock()
  203. hookOpenErr.fn = fn
  204. }
  205. // Supports dsn forms:
  206. // <dbname>
  207. // <dbname>;<opts> (only currently supported option is `badConn`,
  208. // which causes driver.ErrBadConn to be returned on
  209. // every other conn.Begin())
  210. func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
  211. hookOpenErr.Lock()
  212. fn := hookOpenErr.fn
  213. hookOpenErr.Unlock()
  214. if fn != nil {
  215. if err := fn(); err != nil {
  216. return nil, err
  217. }
  218. }
  219. parts := strings.Split(dsn, ";")
  220. if len(parts) < 1 {
  221. return nil, errors.New("fakedb: no database name")
  222. }
  223. name := parts[0]
  224. db := d.getDB(name)
  225. d.mu.Lock()
  226. d.openCount++
  227. d.mu.Unlock()
  228. conn := &fakeConn{db: db}
  229. if len(parts) >= 2 && parts[1] == "badConn" {
  230. conn.bad = true
  231. }
  232. if d.waitCh != nil {
  233. d.waitingCh <- struct{}{}
  234. <-d.waitCh
  235. d.waitCh = nil
  236. d.waitingCh = nil
  237. }
  238. return conn, nil
  239. }
  240. func (d *fakeDriver) getDB(name string) *fakeDB {
  241. d.mu.Lock()
  242. defer d.mu.Unlock()
  243. if d.dbs == nil {
  244. d.dbs = make(map[string]*fakeDB)
  245. }
  246. db, ok := d.dbs[name]
  247. if !ok {
  248. db = &fakeDB{name: name}
  249. d.dbs[name] = db
  250. }
  251. return db
  252. }
  253. func (db *fakeDB) wipe() {
  254. db.mu.Lock()
  255. defer db.mu.Unlock()
  256. db.tables = nil
  257. }
  258. func (db *fakeDB) createTable(name string, columnNames, columnTypes []string) error {
  259. db.mu.Lock()
  260. defer db.mu.Unlock()
  261. if db.tables == nil {
  262. db.tables = make(map[string]*table)
  263. }
  264. if _, exist := db.tables[name]; exist {
  265. return fmt.Errorf("fakedb: table %q already exists", name)
  266. }
  267. if len(columnNames) != len(columnTypes) {
  268. return fmt.Errorf("fakedb: create table of %q len(names) != len(types): %d vs %d",
  269. name, len(columnNames), len(columnTypes))
  270. }
  271. db.tables[name] = &table{colname: columnNames, coltype: columnTypes}
  272. return nil
  273. }
  274. // must be called with db.mu lock held
  275. func (db *fakeDB) table(table string) (*table, bool) {
  276. if db.tables == nil {
  277. return nil, false
  278. }
  279. t, ok := db.tables[table]
  280. return t, ok
  281. }
  282. func (db *fakeDB) columnType(table, column string) (typ string, ok bool) {
  283. db.mu.Lock()
  284. defer db.mu.Unlock()
  285. t, ok := db.table(table)
  286. if !ok {
  287. return
  288. }
  289. for n, cname := range t.colname {
  290. if cname == column {
  291. return t.coltype[n], true
  292. }
  293. }
  294. return "", false
  295. }
  296. func (c *fakeConn) isBad() bool {
  297. if c.stickyBad {
  298. return true
  299. } else if c.bad {
  300. if c.db == nil {
  301. return false
  302. }
  303. // alternate between bad conn and not bad conn
  304. c.db.badConn = !c.db.badConn
  305. return c.db.badConn
  306. } else {
  307. return false
  308. }
  309. }
  310. func (c *fakeConn) isDirtyAndMark() bool {
  311. if c.skipDirtySession {
  312. return false
  313. }
  314. if c.currTx != nil {
  315. c.dirtySession = true
  316. return false
  317. }
  318. if c.dirtySession {
  319. return true
  320. }
  321. c.dirtySession = true
  322. return false
  323. }
  324. func (c *fakeConn) Begin() (driver.Tx, error) {
  325. if c.isBad() {
  326. return nil, fakeError{Wrapped: driver.ErrBadConn}
  327. }
  328. if c.currTx != nil {
  329. return nil, errors.New("fakedb: already in a transaction")
  330. }
  331. c.touchMem()
  332. c.currTx = &fakeTx{c: c}
  333. return c.currTx, nil
  334. }
  335. var hookPostCloseConn struct {
  336. sync.Mutex
  337. fn func(*fakeConn, error)
  338. }
  339. func setHookpostCloseConn(fn func(*fakeConn, error)) {
  340. hookPostCloseConn.Lock()
  341. defer hookPostCloseConn.Unlock()
  342. hookPostCloseConn.fn = fn
  343. }
  344. var testStrictClose *testing.T
  345. // setStrictFakeConnClose sets the t to Errorf on when fakeConn.Close
  346. // fails to close. If nil, the check is disabled.
  347. func setStrictFakeConnClose(t *testing.T) {
  348. testStrictClose = t
  349. }
  350. func (c *fakeConn) ResetSession(ctx context.Context) error {
  351. c.dirtySession = false
  352. c.currTx = nil
  353. if c.isBad() {
  354. return fakeError{Message: "Reset Session: bad conn", Wrapped: driver.ErrBadConn}
  355. }
  356. return nil
  357. }
  358. var _ driver.Validator = (*fakeConn)(nil)
  359. func (c *fakeConn) IsValid() bool {
  360. return !c.isBad()
  361. }
  362. func (c *fakeConn) Close() (err error) {
  363. drv := fdriver.(*fakeDriver)
  364. defer func() {
  365. if err != nil && testStrictClose != nil {
  366. testStrictClose.Errorf("failed to close a test fakeConn: %v", err)
  367. }
  368. hookPostCloseConn.Lock()
  369. fn := hookPostCloseConn.fn
  370. hookPostCloseConn.Unlock()
  371. if fn != nil {
  372. fn(c, err)
  373. }
  374. if err == nil {
  375. drv.mu.Lock()
  376. drv.closeCount++
  377. drv.mu.Unlock()
  378. }
  379. }()
  380. c.touchMem()
  381. if c.currTx != nil {
  382. return errors.New("fakedb: can't close fakeConn; in a Transaction")
  383. }
  384. if c.db == nil {
  385. return errors.New("fakedb: can't close fakeConn; already closed")
  386. }
  387. if c.stmtsMade > c.stmtsClosed {
  388. return errors.New("fakedb: can't close; dangling statement(s)")
  389. }
  390. c.db = nil
  391. return nil
  392. }
  393. func checkSubsetTypes(allowAny bool, args []driver.NamedValue) error {
  394. for _, arg := range args {
  395. switch arg.Value.(type) {
  396. case int64, float64, bool, nil, []byte, string, time.Time:
  397. default:
  398. if !allowAny {
  399. return fmt.Errorf("fakedb: invalid argument ordinal %[1]d: %[2]v, type %[2]T", arg.Ordinal, arg.Value)
  400. }
  401. }
  402. }
  403. return nil
  404. }
  405. func (c *fakeConn) Exec(query string, args []driver.Value) (driver.Result, error) {
  406. // Ensure that ExecContext is called if available.
  407. panic("ExecContext was not called.")
  408. }
  409. func (c *fakeConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
  410. // This is an optional interface, but it's implemented here
  411. // just to check that all the args are of the proper types.
  412. // ErrSkip is returned so the caller acts as if we didn't
  413. // implement this at all.
  414. err := checkSubsetTypes(c.db.allowAny, args)
  415. if err != nil {
  416. return nil, err
  417. }
  418. return nil, driver.ErrSkip
  419. }
  420. func (c *fakeConn) Query(query string, args []driver.Value) (driver.Rows, error) {
  421. // Ensure that ExecContext is called if available.
  422. panic("QueryContext was not called.")
  423. }
  424. func (c *fakeConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
  425. // This is an optional interface, but it's implemented here
  426. // just to check that all the args are of the proper types.
  427. // ErrSkip is returned so the caller acts as if we didn't
  428. // implement this at all.
  429. err := checkSubsetTypes(c.db.allowAny, args)
  430. if err != nil {
  431. return nil, err
  432. }
  433. return nil, driver.ErrSkip
  434. }
  435. func errf(msg string, args ...any) error {
  436. return errors.New("fakedb: " + fmt.Sprintf(msg, args...))
  437. }
  438. // parts are table|selectCol1,selectCol2|whereCol=?,whereCol2=?
  439. // (note that where columns must always contain ? marks,
  440. // just a limitation for fakedb)
  441. func (c *fakeConn) prepareSelect(stmt *fakeStmt, parts []string) (*fakeStmt, error) {
  442. if len(parts) != 3 {
  443. stmt.Close()
  444. return nil, errf("invalid SELECT syntax with %d parts; want 3", len(parts))
  445. }
  446. stmt.table = parts[0]
  447. stmt.colName = strings.Split(parts[1], ",")
  448. for n, colspec := range strings.Split(parts[2], ",") {
  449. if colspec == "" {
  450. continue
  451. }
  452. nameVal := strings.Split(colspec, "=")
  453. if len(nameVal) != 2 {
  454. stmt.Close()
  455. return nil, errf("SELECT on table %q has invalid column spec of %q (index %d)", stmt.table, colspec, n)
  456. }
  457. column, value := nameVal[0], nameVal[1]
  458. _, ok := c.db.columnType(stmt.table, column)
  459. if !ok {
  460. stmt.Close()
  461. return nil, errf("SELECT on table %q references non-existent column %q", stmt.table, column)
  462. }
  463. if !strings.HasPrefix(value, "?") {
  464. stmt.Close()
  465. return nil, errf("SELECT on table %q has pre-bound value for where column %q; need a question mark",
  466. stmt.table, column)
  467. }
  468. stmt.placeholders++
  469. stmt.whereCol = append(stmt.whereCol, boundCol{Column: column, Placeholder: value, Ordinal: stmt.placeholders})
  470. }
  471. return stmt, nil
  472. }
  473. // parts are table|col=type,col2=type2
  474. func (c *fakeConn) prepareCreate(stmt *fakeStmt, parts []string) (*fakeStmt, error) {
  475. if len(parts) != 2 {
  476. stmt.Close()
  477. return nil, errf("invalid CREATE syntax with %d parts; want 2", len(parts))
  478. }
  479. stmt.table = parts[0]
  480. for n, colspec := range strings.Split(parts[1], ",") {
  481. nameType := strings.Split(colspec, "=")
  482. if len(nameType) != 2 {
  483. stmt.Close()
  484. return nil, errf("CREATE table %q has invalid column spec of %q (index %d)", stmt.table, colspec, n)
  485. }
  486. stmt.colName = append(stmt.colName, nameType[0])
  487. stmt.colType = append(stmt.colType, nameType[1])
  488. }
  489. return stmt, nil
  490. }
  491. // parts are table|col=?,col2=val
  492. func (c *fakeConn) prepareInsert(ctx context.Context, stmt *fakeStmt, parts []string) (*fakeStmt, error) {
  493. if len(parts) != 2 {
  494. stmt.Close()
  495. return nil, errf("invalid INSERT syntax with %d parts; want 2", len(parts))
  496. }
  497. stmt.table = parts[0]
  498. for n, colspec := range strings.Split(parts[1], ",") {
  499. nameVal := strings.Split(colspec, "=")
  500. if len(nameVal) != 2 {
  501. stmt.Close()
  502. return nil, errf("INSERT table %q has invalid column spec of %q (index %d)", stmt.table, colspec, n)
  503. }
  504. column, value := nameVal[0], nameVal[1]
  505. ctype, ok := c.db.columnType(stmt.table, column)
  506. if !ok {
  507. stmt.Close()
  508. return nil, errf("INSERT table %q references non-existent column %q", stmt.table, column)
  509. }
  510. stmt.colName = append(stmt.colName, column)
  511. if !strings.HasPrefix(value, "?") {
  512. var subsetVal any
  513. // Convert to driver subset type
  514. switch ctype {
  515. case "string":
  516. subsetVal = []byte(value)
  517. case "blob":
  518. subsetVal = []byte(value)
  519. case "int32":
  520. i, err := strconv.Atoi(value)
  521. if err != nil {
  522. stmt.Close()
  523. return nil, errf("invalid conversion to int32 from %q", value)
  524. }
  525. subsetVal = int64(i) // int64 is a subset type, but not int32
  526. case "table": // For testing cursor reads.
  527. c.skipDirtySession = true
  528. vparts := strings.Split(value, "!")
  529. substmt, err := c.PrepareContext(ctx, fmt.Sprintf("SELECT|%s|%s|", vparts[0], strings.Join(vparts[1:], ",")))
  530. if err != nil {
  531. return nil, err
  532. }
  533. cursor, err := (substmt.(driver.StmtQueryContext)).QueryContext(ctx, []driver.NamedValue{})
  534. substmt.Close()
  535. if err != nil {
  536. return nil, err
  537. }
  538. subsetVal = cursor
  539. default:
  540. stmt.Close()
  541. return nil, errf("unsupported conversion for pre-bound parameter %q to type %q", value, ctype)
  542. }
  543. stmt.colValue = append(stmt.colValue, subsetVal)
  544. } else {
  545. stmt.placeholders++
  546. stmt.placeholderConverter = append(stmt.placeholderConverter, converterForType(ctype))
  547. stmt.colValue = append(stmt.colValue, value)
  548. }
  549. }
  550. return stmt, nil
  551. }
  552. // hook to simulate broken connections
  553. var hookPrepareBadConn func() bool
  554. func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
  555. panic("use PrepareContext")
  556. }
  557. func (c *fakeConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
  558. c.numPrepare++
  559. if c.db == nil {
  560. panic("nil c.db; conn = " + fmt.Sprintf("%#v", c))
  561. }
  562. if c.stickyBad || (hookPrepareBadConn != nil && hookPrepareBadConn()) {
  563. return nil, fakeError{Message: "Preapre: Sticky Bad", Wrapped: driver.ErrBadConn}
  564. }
  565. c.touchMem()
  566. var firstStmt, prev *fakeStmt
  567. for _, query := range strings.Split(query, ";") {
  568. parts := strings.Split(query, "|")
  569. if len(parts) < 1 {
  570. return nil, errf("empty query")
  571. }
  572. stmt := &fakeStmt{q: query, c: c, memToucher: c}
  573. if firstStmt == nil {
  574. firstStmt = stmt
  575. }
  576. if len(parts) >= 3 {
  577. switch parts[0] {
  578. case "PANIC":
  579. stmt.panic = parts[1]
  580. parts = parts[2:]
  581. case "WAIT":
  582. wait, err := time.ParseDuration(parts[1])
  583. if err != nil {
  584. return nil, errf("expected section after WAIT to be a duration, got %q %v", parts[1], err)
  585. }
  586. parts = parts[2:]
  587. stmt.wait = wait
  588. }
  589. }
  590. cmd := parts[0]
  591. stmt.cmd = cmd
  592. parts = parts[1:]
  593. if c.waiter != nil {
  594. c.waiter(ctx)
  595. if err := ctx.Err(); err != nil {
  596. return nil, err
  597. }
  598. }
  599. if stmt.wait > 0 {
  600. wait := time.NewTimer(stmt.wait)
  601. select {
  602. case <-wait.C:
  603. case <-ctx.Done():
  604. wait.Stop()
  605. return nil, ctx.Err()
  606. }
  607. }
  608. c.incrStat(&c.stmtsMade)
  609. var err error
  610. switch cmd {
  611. case "WIPE":
  612. // Nothing
  613. case "SELECT":
  614. stmt, err = c.prepareSelect(stmt, parts)
  615. case "CREATE":
  616. stmt, err = c.prepareCreate(stmt, parts)
  617. case "INSERT":
  618. stmt, err = c.prepareInsert(ctx, stmt, parts)
  619. case "NOSERT":
  620. // Do all the prep-work like for an INSERT but don't actually insert the row.
  621. // Used for some of the concurrent tests.
  622. stmt, err = c.prepareInsert(ctx, stmt, parts)
  623. default:
  624. stmt.Close()
  625. return nil, errf("unsupported command type %q", cmd)
  626. }
  627. if err != nil {
  628. return nil, err
  629. }
  630. if prev != nil {
  631. prev.next = stmt
  632. }
  633. prev = stmt
  634. }
  635. return firstStmt, nil
  636. }
  637. func (s *fakeStmt) ColumnConverter(idx int) driver.ValueConverter {
  638. if s.panic == "ColumnConverter" {
  639. panic(s.panic)
  640. }
  641. if len(s.placeholderConverter) == 0 {
  642. return driver.DefaultParameterConverter
  643. }
  644. return s.placeholderConverter[idx]
  645. }
  646. func (s *fakeStmt) Close() error {
  647. if s.panic == "Close" {
  648. panic(s.panic)
  649. }
  650. if s.c == nil {
  651. panic("nil conn in fakeStmt.Close")
  652. }
  653. if s.c.db == nil {
  654. panic("in fakeStmt.Close, conn's db is nil (already closed)")
  655. }
  656. s.touchMem()
  657. if !s.closed {
  658. s.c.incrStat(&s.c.stmtsClosed)
  659. s.closed = true
  660. }
  661. if s.next != nil {
  662. s.next.Close()
  663. }
  664. return nil
  665. }
  666. var errClosed = errors.New("fakedb: statement has been closed")
  667. // hook to simulate broken connections
  668. var hookExecBadConn func() bool
  669. func (s *fakeStmt) Exec(args []driver.Value) (driver.Result, error) {
  670. panic("Using ExecContext")
  671. }
  672. var errFakeConnSessionDirty = errors.New("fakedb: session is dirty")
  673. func (s *fakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
  674. if s.panic == "Exec" {
  675. panic(s.panic)
  676. }
  677. if s.closed {
  678. return nil, errClosed
  679. }
  680. if s.c.stickyBad || (hookExecBadConn != nil && hookExecBadConn()) {
  681. return nil, fakeError{Message: "Exec: Sticky Bad", Wrapped: driver.ErrBadConn}
  682. }
  683. if s.c.isDirtyAndMark() {
  684. return nil, errFakeConnSessionDirty
  685. }
  686. err := checkSubsetTypes(s.c.db.allowAny, args)
  687. if err != nil {
  688. return nil, err
  689. }
  690. s.touchMem()
  691. if s.wait > 0 {
  692. time.Sleep(s.wait)
  693. }
  694. select {
  695. default:
  696. case <-ctx.Done():
  697. return nil, ctx.Err()
  698. }
  699. db := s.c.db
  700. switch s.cmd {
  701. case "WIPE":
  702. db.wipe()
  703. return driver.ResultNoRows, nil
  704. case "CREATE":
  705. if err := db.createTable(s.table, s.colName, s.colType); err != nil {
  706. return nil, err
  707. }
  708. return driver.ResultNoRows, nil
  709. case "INSERT":
  710. return s.execInsert(args, true)
  711. case "NOSERT":
  712. // Do all the prep-work like for an INSERT but don't actually insert the row.
  713. // Used for some of the concurrent tests.
  714. return s.execInsert(args, false)
  715. }
  716. return nil, fmt.Errorf("fakedb: unimplemented statement Exec command type of %q", s.cmd)
  717. }
  718. // When doInsert is true, add the row to the table.
  719. // When doInsert is false do prep-work and error checking, but don't
  720. // actually add the row to the table.
  721. func (s *fakeStmt) execInsert(args []driver.NamedValue, doInsert bool) (driver.Result, error) {
  722. db := s.c.db
  723. if len(args) != s.placeholders {
  724. panic("error in pkg db; should only get here if size is correct")
  725. }
  726. db.mu.Lock()
  727. t, ok := db.table(s.table)
  728. db.mu.Unlock()
  729. if !ok {
  730. return nil, fmt.Errorf("fakedb: table %q doesn't exist", s.table)
  731. }
  732. t.mu.Lock()
  733. defer t.mu.Unlock()
  734. var cols []any
  735. if doInsert {
  736. cols = make([]any, len(t.colname))
  737. }
  738. argPos := 0
  739. for n, colname := range s.colName {
  740. colidx := t.columnIndex(colname)
  741. if colidx == -1 {
  742. return nil, fmt.Errorf("fakedb: column %q doesn't exist or dropped since prepared statement was created", colname)
  743. }
  744. var val any
  745. if strvalue, ok := s.colValue[n].(string); ok && strings.HasPrefix(strvalue, "?") {
  746. if strvalue == "?" {
  747. val = args[argPos].Value
  748. } else {
  749. // Assign value from argument placeholder name.
  750. for _, a := range args {
  751. if a.Name == strvalue[1:] {
  752. val = a.Value
  753. break
  754. }
  755. }
  756. }
  757. argPos++
  758. } else {
  759. val = s.colValue[n]
  760. }
  761. if doInsert {
  762. cols[colidx] = val
  763. }
  764. }
  765. if doInsert {
  766. t.rows = append(t.rows, &row{cols: cols})
  767. }
  768. return driver.RowsAffected(1), nil
  769. }
  770. // hook to simulate broken connections
  771. var hookQueryBadConn func() bool
  772. func (s *fakeStmt) Query(args []driver.Value) (driver.Rows, error) {
  773. panic("Use QueryContext")
  774. }
  775. func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
  776. if s.panic == "Query" {
  777. panic(s.panic)
  778. }
  779. if s.closed {
  780. return nil, errClosed
  781. }
  782. if s.c.stickyBad || (hookQueryBadConn != nil && hookQueryBadConn()) {
  783. return nil, fakeError{Message: "Query: Sticky Bad", Wrapped: driver.ErrBadConn}
  784. }
  785. if s.c.isDirtyAndMark() {
  786. return nil, errFakeConnSessionDirty
  787. }
  788. err := checkSubsetTypes(s.c.db.allowAny, args)
  789. if err != nil {
  790. return nil, err
  791. }
  792. s.touchMem()
  793. db := s.c.db
  794. if len(args) != s.placeholders {
  795. panic("error in pkg db; should only get here if size is correct")
  796. }
  797. setMRows := make([][]*row, 0, 1)
  798. setColumns := make([][]string, 0, 1)
  799. setColType := make([][]string, 0, 1)
  800. for {
  801. db.mu.Lock()
  802. t, ok := db.table(s.table)
  803. db.mu.Unlock()
  804. if !ok {
  805. return nil, fmt.Errorf("fakedb: table %q doesn't exist", s.table)
  806. }
  807. if s.table == "magicquery" {
  808. if len(s.whereCol) == 2 && s.whereCol[0].Column == "op" && s.whereCol[1].Column == "millis" {
  809. if args[0].Value == "sleep" {
  810. time.Sleep(time.Duration(args[1].Value.(int64)) * time.Millisecond)
  811. }
  812. }
  813. }
  814. if s.table == "tx_status" && s.colName[0] == "tx_status" {
  815. txStatus := "autocommit"
  816. if s.c.currTx != nil {
  817. txStatus = "transaction"
  818. }
  819. cursor := &rowsCursor{
  820. parentMem: s.c,
  821. posRow: -1,
  822. rows: [][]*row{
  823. {
  824. {
  825. cols: []any{
  826. txStatus,
  827. },
  828. },
  829. },
  830. },
  831. cols: [][]string{
  832. {
  833. "tx_status",
  834. },
  835. },
  836. colType: [][]string{
  837. {
  838. "string",
  839. },
  840. },
  841. errPos: -1,
  842. }
  843. return cursor, nil
  844. }
  845. t.mu.Lock()
  846. colIdx := make(map[string]int) // select column name -> column index in table
  847. for _, name := range s.colName {
  848. idx := t.columnIndex(name)
  849. if idx == -1 {
  850. t.mu.Unlock()
  851. return nil, fmt.Errorf("fakedb: unknown column name %q", name)
  852. }
  853. colIdx[name] = idx
  854. }
  855. mrows := []*row{}
  856. rows:
  857. for _, trow := range t.rows {
  858. // Process the where clause, skipping non-match rows. This is lazy
  859. // and just uses fmt.Sprintf("%v") to test equality. Good enough
  860. // for test code.
  861. for _, wcol := range s.whereCol {
  862. idx := t.columnIndex(wcol.Column)
  863. if idx == -1 {
  864. t.mu.Unlock()
  865. return nil, fmt.Errorf("fakedb: invalid where clause column %q", wcol)
  866. }
  867. tcol := trow.cols[idx]
  868. if bs, ok := tcol.([]byte); ok {
  869. // lazy hack to avoid sprintf %v on a []byte
  870. tcol = string(bs)
  871. }
  872. var argValue any
  873. if wcol.Placeholder == "?" {
  874. argValue = args[wcol.Ordinal-1].Value
  875. } else {
  876. // Assign arg value from placeholder name.
  877. for _, a := range args {
  878. if a.Name == wcol.Placeholder[1:] {
  879. argValue = a.Value
  880. break
  881. }
  882. }
  883. }
  884. if fmt.Sprintf("%v", tcol) != fmt.Sprintf("%v", argValue) {
  885. continue rows
  886. }
  887. }
  888. mrow := &row{cols: make([]any, len(s.colName))}
  889. for seli, name := range s.colName {
  890. mrow.cols[seli] = trow.cols[colIdx[name]]
  891. }
  892. mrows = append(mrows, mrow)
  893. }
  894. var colType []string
  895. for _, column := range s.colName {
  896. colType = append(colType, t.coltype[t.columnIndex(column)])
  897. }
  898. t.mu.Unlock()
  899. setMRows = append(setMRows, mrows)
  900. setColumns = append(setColumns, s.colName)
  901. setColType = append(setColType, colType)
  902. if s.next == nil {
  903. break
  904. }
  905. s = s.next
  906. }
  907. cursor := &rowsCursor{
  908. parentMem: s.c,
  909. posRow: -1,
  910. rows: setMRows,
  911. cols: setColumns,
  912. colType: setColType,
  913. errPos: -1,
  914. }
  915. return cursor, nil
  916. }
  917. func (s *fakeStmt) NumInput() int {
  918. if s.panic == "NumInput" {
  919. panic(s.panic)
  920. }
  921. return s.placeholders
  922. }
  923. // hook to simulate broken connections
  924. var hookCommitBadConn func() bool
  925. func (tx *fakeTx) Commit() error {
  926. tx.c.currTx = nil
  927. if hookCommitBadConn != nil && hookCommitBadConn() {
  928. return fakeError{Message: "Commit: Hook Bad Conn", Wrapped: driver.ErrBadConn}
  929. }
  930. tx.c.touchMem()
  931. return nil
  932. }
  933. // hook to simulate broken connections
  934. var hookRollbackBadConn func() bool
  935. func (tx *fakeTx) Rollback() error {
  936. tx.c.currTx = nil
  937. if hookRollbackBadConn != nil && hookRollbackBadConn() {
  938. return fakeError{Message: "Rollback: Hook Bad Conn", Wrapped: driver.ErrBadConn}
  939. }
  940. tx.c.touchMem()
  941. return nil
  942. }
  943. type rowsCursor struct {
  944. parentMem memToucher
  945. cols [][]string
  946. colType [][]string
  947. posSet int
  948. posRow int
  949. rows [][]*row
  950. closed bool
  951. // errPos and err are for making Next return early with error.
  952. errPos int
  953. err error
  954. // a clone of slices to give out to clients, indexed by the
  955. // original slice's first byte address. we clone them
  956. // just so we're able to corrupt them on close.
  957. bytesClone map[*byte][]byte
  958. // Every operation writes to line to enable the race detector
  959. // check for data races.
  960. // This is separate from the fakeConn.line to allow for drivers that
  961. // can start multiple queries on the same transaction at the same time.
  962. line int64
  963. }
  964. func (rc *rowsCursor) touchMem() {
  965. rc.parentMem.touchMem()
  966. rc.line++
  967. }
  968. func (rc *rowsCursor) Close() error {
  969. rc.touchMem()
  970. rc.parentMem.touchMem()
  971. rc.closed = true
  972. return nil
  973. }
  974. func (rc *rowsCursor) Columns() []string {
  975. return rc.cols[rc.posSet]
  976. }
  977. func (rc *rowsCursor) ColumnTypeScanType(index int) reflect.Type {
  978. return colTypeToReflectType(rc.colType[rc.posSet][index])
  979. }
  980. var rowsCursorNextHook func(dest []driver.Value) error
  981. func (rc *rowsCursor) Next(dest []driver.Value) error {
  982. if rowsCursorNextHook != nil {
  983. return rowsCursorNextHook(dest)
  984. }
  985. if rc.closed {
  986. return errors.New("fakedb: cursor is closed")
  987. }
  988. rc.touchMem()
  989. rc.posRow++
  990. if rc.posRow == rc.errPos {
  991. return rc.err
  992. }
  993. if rc.posRow >= len(rc.rows[rc.posSet]) {
  994. return io.EOF // per interface spec
  995. }
  996. for i, v := range rc.rows[rc.posSet][rc.posRow].cols {
  997. // TODO(bradfitz): convert to subset types? naah, I
  998. // think the subset types should only be input to
  999. // driver, but the sql package should be able to handle
  1000. // a wider range of types coming out of drivers. all
  1001. // for ease of drivers, and to prevent drivers from
  1002. // messing up conversions or doing them differently.
  1003. dest[i] = v
  1004. if bs, ok := v.([]byte); ok {
  1005. if rc.bytesClone == nil {
  1006. rc.bytesClone = make(map[*byte][]byte)
  1007. }
  1008. clone, ok := rc.bytesClone[&bs[0]]
  1009. if !ok {
  1010. clone = make([]byte, len(bs))
  1011. copy(clone, bs)
  1012. rc.bytesClone[&bs[0]] = clone
  1013. }
  1014. dest[i] = clone
  1015. }
  1016. }
  1017. return nil
  1018. }
  1019. func (rc *rowsCursor) HasNextResultSet() bool {
  1020. rc.touchMem()
  1021. return rc.posSet < len(rc.rows)-1
  1022. }
  1023. func (rc *rowsCursor) NextResultSet() error {
  1024. rc.touchMem()
  1025. if rc.HasNextResultSet() {
  1026. rc.posSet++
  1027. rc.posRow = -1
  1028. return nil
  1029. }
  1030. return io.EOF // Per interface spec.
  1031. }
  1032. // fakeDriverString is like driver.String, but indirects pointers like
  1033. // DefaultValueConverter.
  1034. //
  1035. // This could be surprising behavior to retroactively apply to
  1036. // driver.String now that Go1 is out, but this is convenient for
  1037. // our TestPointerParamsAndScans.
  1038. //
  1039. type fakeDriverString struct{}
  1040. func (fakeDriverString) ConvertValue(v any) (driver.Value, error) {
  1041. switch c := v.(type) {
  1042. case string, []byte:
  1043. return v, nil
  1044. case *string:
  1045. if c == nil {
  1046. return nil, nil
  1047. }
  1048. return *c, nil
  1049. }
  1050. return fmt.Sprintf("%v", v), nil
  1051. }
  1052. type anyTypeConverter struct{}
  1053. func (anyTypeConverter) ConvertValue(v any) (driver.Value, error) {
  1054. return v, nil
  1055. }
  1056. func converterForType(typ string) driver.ValueConverter {
  1057. switch typ {
  1058. case "bool":
  1059. return driver.Bool
  1060. case "nullbool":
  1061. return driver.Null{Converter: driver.Bool}
  1062. case "byte", "int16":
  1063. return driver.NotNull{Converter: driver.DefaultParameterConverter}
  1064. case "int32":
  1065. return driver.Int32
  1066. case "nullbyte", "nullint32", "nullint16":
  1067. return driver.Null{Converter: driver.DefaultParameterConverter}
  1068. case "string":
  1069. return driver.NotNull{Converter: fakeDriverString{}}
  1070. case "nullstring":
  1071. return driver.Null{Converter: fakeDriverString{}}
  1072. case "int64":
  1073. // TODO(coopernurse): add type-specific converter
  1074. return driver.NotNull{Converter: driver.DefaultParameterConverter}
  1075. case "nullint64":
  1076. // TODO(coopernurse): add type-specific converter
  1077. return driver.Null{Converter: driver.DefaultParameterConverter}
  1078. case "float64":
  1079. // TODO(coopernurse): add type-specific converter
  1080. return driver.NotNull{Converter: driver.DefaultParameterConverter}
  1081. case "nullfloat64":
  1082. // TODO(coopernurse): add type-specific converter
  1083. return driver.Null{Converter: driver.DefaultParameterConverter}
  1084. case "datetime":
  1085. return driver.NotNull{Converter: driver.DefaultParameterConverter}
  1086. case "nulldatetime":
  1087. return driver.Null{Converter: driver.DefaultParameterConverter}
  1088. case "any":
  1089. return anyTypeConverter{}
  1090. }
  1091. panic("invalid fakedb column type of " + typ)
  1092. }
  1093. func colTypeToReflectType(typ string) reflect.Type {
  1094. switch typ {
  1095. case "bool":
  1096. return reflect.TypeOf(false)
  1097. case "nullbool":
  1098. return reflect.TypeOf(NullBool{})
  1099. case "int16":
  1100. return reflect.TypeOf(int16(0))
  1101. case "nullint16":
  1102. return reflect.TypeOf(NullInt16{})
  1103. case "int32":
  1104. return reflect.TypeOf(int32(0))
  1105. case "nullint32":
  1106. return reflect.TypeOf(NullInt32{})
  1107. case "string":
  1108. return reflect.TypeOf("")
  1109. case "nullstring":
  1110. return reflect.TypeOf(NullString{})
  1111. case "int64":
  1112. return reflect.TypeOf(int64(0))
  1113. case "nullint64":
  1114. return reflect.TypeOf(NullInt64{})
  1115. case "float64":
  1116. return reflect.TypeOf(float64(0))
  1117. case "nullfloat64":
  1118. return reflect.TypeOf(NullFloat64{})
  1119. case "datetime":
  1120. return reflect.TypeOf(time.Time{})
  1121. case "any":
  1122. return reflect.TypeOf(new(any)).Elem()
  1123. }
  1124. panic("invalid fakedb column type of " + typ)
  1125. }