modernc.org/ql@v1.4.7/driver.go (about) 1 // Copyright 2014 The ql 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 5 // database/sql/driver 6 7 package ql // import "modernc.org/ql" 8 9 import ( 10 "bytes" 11 "database/sql" 12 "database/sql/driver" 13 "errors" 14 "fmt" 15 "io" 16 "math/big" 17 "net/url" 18 "os" 19 "path/filepath" 20 "strconv" 21 "strings" 22 "sync" 23 "time" 24 ) 25 26 var ( 27 _ driver.Conn = (*driverConn)(nil) 28 _ driver.Driver = (*sqlDriver)(nil) 29 _ driver.Execer = (*driverConn)(nil) 30 _ driver.Queryer = (*driverConn)(nil) 31 _ driver.Result = (*driverResult)(nil) 32 _ driver.Rows = (*driverRows)(nil) 33 _ driver.Stmt = (*driverStmt)(nil) 34 _ driver.Tx = (*driverConn)(nil) 35 36 txBegin = MustCompile("BEGIN TRANSACTION;") 37 txCommit = MustCompile("COMMIT;") 38 txRollback = MustCompile("ROLLBACK;") 39 40 errNoResult = errors.New("query statement does not produce a result set (no top level SELECT)") 41 ) 42 43 type errList []error 44 45 func (e *errList) append(err error) { 46 if err != nil { 47 *e = append(*e, err) 48 } 49 } 50 51 func (e errList) error() error { 52 if len(e) == 0 { 53 return nil 54 } 55 56 return e 57 } 58 59 func (e errList) Error() string { 60 a := make([]string, len(e)) 61 for i, v := range e { 62 a[i] = v.Error() 63 } 64 return strings.Join(a, "\n") 65 } 66 67 func params(args []driver.Value) []interface{} { 68 r := make([]interface{}, len(args)) 69 for i, v := range args { 70 r[i] = interface{}(v) 71 } 72 return r 73 } 74 75 var ( 76 file2Driver = &sqlDriver{dbs: map[string]*driverDB{}} 77 file2DriverOnce sync.Once 78 fileDriver = &sqlDriver{dbs: map[string]*driverDB{}} 79 fileDriverOnce sync.Once 80 memDriver = &sqlDriver{isMem: true, dbs: map[string]*driverDB{}} 81 memDriverOnce sync.Once 82 ) 83 84 // RegisterDriver registers a QL database/sql/driver[0] named "ql". The name 85 // parameter of 86 // 87 // sql.Open("ql", name) 88 // 89 // is interpreted as a path name to a named DB file which will be created if 90 // not present. The underlying QL database data are persisted on db.Close(). 91 // RegisterDriver can be safely called multiple times, it'll register the 92 // driver only once. 93 // 94 // The name argument can be optionally prefixed by "file://". In that case the 95 // prefix is stripped before interpreting it as a file name. 96 // 97 // The name argument can be optionally prefixed by "memory://". In that case 98 // the prefix is stripped before interpreting it as a name of a memory-only, 99 // volatile DB. 100 // 101 // The ql2 driver can open both the original (V1) files and the new (V2) ones. 102 // It defaults to V1 on creating a new database. 103 // 104 // [0]: http://golang.org/pkg/database/sql/driver/ 105 func RegisterDriver() { 106 fileDriverOnce.Do(func() { sql.Register("ql", fileDriver) }) 107 } 108 109 // RegisterDriver2 registers a QL database/sql/driver[0] named "ql2". The name 110 // parameter of 111 // 112 // sql.Open("ql2", name) 113 // 114 // is interpreted as a path name to a named DB file which will be created if 115 // not present. The underlying QL database data are persisted on db.Close(). 116 // RegisterDriver can be safely called multiple times, it'll register the 117 // driver only once. 118 // 119 // The name argument can be optionally prefixed by "file://". In that case the 120 // prefix is stripped before interpreting it as a file name. 121 // 122 // The name argument can be optionally prefixed by "memory://". In that case 123 // the prefix is stripped before interpreting it as a name of a memory-only, 124 // volatile DB. 125 // 126 // The ql2 driver can open both the original (V1) files and the new (V2) ones. 127 // It defaults to V2 on creating a new database. 128 // 129 // [0]: http://golang.org/pkg/database/sql/driver/ 130 func RegisterDriver2() { 131 file2DriverOnce.Do(func() { sql.Register("ql2", file2Driver) }) 132 } 133 134 // RegisterMemDriver registers a QL memory database/sql/driver[0] named 135 // "ql-mem". The name parameter of 136 // 137 // sql.Open("ql-mem", name) 138 // 139 // is interpreted as an unique memory DB name which will be created if not 140 // present. The underlying QL memory database data are not persisted on 141 // db.Close(). RegisterMemDriver can be safely called multiple times, it'll 142 // register the driver only once. 143 // 144 // [0]: http://golang.org/pkg/database/sql/driver/ 145 func RegisterMemDriver() { 146 memDriverOnce.Do(func() { sql.Register("ql-mem", memDriver) }) 147 } 148 149 type driverDB struct { 150 db *DB 151 name string 152 refcount int 153 } 154 155 func newDriverDB(db *DB, name string) *driverDB { 156 return &driverDB{db: db, name: name, refcount: 1} 157 } 158 159 // sqlDriver implements the interface required by database/sql/driver. 160 type sqlDriver struct { 161 dbs map[string]*driverDB 162 isMem bool 163 mu sync.Mutex 164 } 165 166 func (d *sqlDriver) lock() func() { 167 d.mu.Lock() 168 return d.mu.Unlock 169 } 170 171 // Open returns a new connection to the database. The name is a string in a 172 // driver-specific format. 173 // 174 // Open may return a cached connection (one previously closed), but doing so is 175 // unnecessary; the sql package maintains a pool of idle connections for 176 // efficient re-use. 177 // 178 // The returned connection is only used by one goroutine at a time. 179 // 180 // The name supported URL parameters: 181 // 182 // headroom Size of the WAL headroom. See https://gitlab.com/cznic/ql/issues/140. 183 func (d *sqlDriver) Open(name string) (driver.Conn, error) { 184 switch { 185 case d == fileDriver || d == file2Driver: 186 if !strings.Contains(name, "://") && !strings.HasPrefix(name, "file") { 187 name = "file://" + name 188 } 189 case d == memDriver: 190 if !strings.Contains(name, "://") && !strings.HasPrefix(name, "memory") { 191 name = "memory://" + name 192 } 193 default: 194 return nil, fmt.Errorf("open: unexpected/unsupported instance of driver.Driver: %p", d) 195 } 196 197 name = filepath.ToSlash(name) // Ensure / separated URLs on Windows 198 uri, err := url.Parse(name) 199 if err != nil { 200 return nil, err 201 } 202 203 switch uri.Scheme { 204 case "file": 205 // ok 206 case "memory": 207 d = memDriver 208 default: 209 return nil, fmt.Errorf("open: unexpected/unsupported scheme: %s", uri.Scheme) 210 } 211 212 name = filepath.Clean(filepath.Join(uri.Host, uri.Path)) 213 if d == fileDriver && (name == "" || name == "." || name == string(os.PathSeparator)) { 214 return nil, fmt.Errorf("invalid DB name %q", name) 215 } 216 217 var headroom int64 218 if a := uri.Query()["headroom"]; len(a) != 0 { 219 if headroom, err = strconv.ParseInt(a[0], 10, 64); err != nil { 220 return nil, err 221 } 222 } 223 224 var reWAL bool 225 if a := uri.Query()["removeemptywal"]; len(a) != 0 { 226 n, err := strconv.ParseInt(a[0], 10, 64) 227 if err != nil { 228 return nil, err 229 } 230 231 reWAL = n != 0 232 } 233 234 ff := 0 235 if d == file2Driver { 236 ff = 2 237 } 238 defer d.lock()() 239 db := d.dbs[name] 240 if db == nil { 241 var err error 242 var db0 *DB 243 switch d.isMem { 244 case true: 245 db0, err = OpenMem() 246 default: 247 db0, err = OpenFile(name, &Options{CanCreate: true, Headroom: headroom, FileFormat: ff, RemoveEmptyWAL: reWAL}) 248 } 249 if err != nil { 250 return nil, err 251 } 252 253 db = newDriverDB(db0, name) 254 d.dbs[name] = db 255 return newDriverConn(d, db), nil 256 } 257 258 db.refcount++ 259 return newDriverConn(d, db), nil 260 } 261 262 // driverConn is a connection to a database. It is not used concurrently by 263 // multiple goroutines. 264 // 265 // Conn is assumed to be stateful. 266 type driverConn struct { 267 ctx *TCtx 268 db *driverDB 269 driver *sqlDriver 270 stop map[*driverStmt]struct{} 271 tnl int 272 } 273 274 func newDriverConn(d *sqlDriver, ddb *driverDB) driver.Conn { 275 r := &driverConn{ 276 db: ddb, 277 driver: d, 278 stop: map[*driverStmt]struct{}{}, 279 } 280 return r 281 } 282 283 // Prepare returns a prepared statement, bound to this connection. 284 func (c *driverConn) Prepare(query string) (driver.Stmt, error) { 285 list, err := Compile(query) 286 if err != nil { 287 return nil, err 288 } 289 290 s := &driverStmt{conn: c, stmt: list} 291 c.stop[s] = struct{}{} 292 return s, nil 293 } 294 295 // Close invalidates and potentially stops any current prepared statements and 296 // transactions, marking this connection as no longer in use. 297 // 298 // Because the sql package maintains a free pool of connections and only calls 299 // Close when there's a surplus of idle connections, it shouldn't be necessary 300 // for drivers to do their own connection caching. 301 func (c *driverConn) Close() error { 302 var err errList 303 for s := range c.stop { 304 err.append(s.Close()) 305 } 306 defer c.driver.lock()() 307 dbs, name := c.driver.dbs, c.db.name 308 v := dbs[name] 309 v.refcount-- 310 if v.refcount == 0 { 311 err.append(c.db.db.Close()) 312 delete(dbs, name) 313 } 314 return err.error() 315 } 316 317 // Begin starts and returns a new transaction. 318 func (c *driverConn) Begin() (driver.Tx, error) { 319 if c.ctx == nil { 320 c.ctx = NewRWCtx() 321 } 322 323 if _, _, err := c.db.db.Execute(c.ctx, txBegin); err != nil { 324 return nil, err 325 } 326 327 c.tnl++ 328 return c, nil 329 } 330 331 func (c *driverConn) Commit() error { 332 if c.tnl == 0 || c.ctx == nil { 333 return errCommitNotInTransaction 334 } 335 336 if _, _, err := c.db.db.Execute(c.ctx, txCommit); err != nil { 337 return err 338 } 339 340 c.tnl-- 341 if c.tnl == 0 { 342 c.ctx = nil 343 } 344 return nil 345 } 346 347 func (c *driverConn) Rollback() error { 348 if c.tnl == 0 || c.ctx == nil { 349 return errRollbackNotInTransaction 350 } 351 352 if _, _, err := c.db.db.Execute(c.ctx, txRollback); err != nil { 353 return err 354 } 355 356 c.tnl-- 357 if c.tnl == 0 { 358 c.ctx = nil 359 } 360 return nil 361 } 362 363 // Execer is an optional interface that may be implemented by a Conn. 364 // 365 // If a Conn does not implement Execer, the sql package's DB.Exec will first 366 // prepare a query, execute the statement, and then close the statement. 367 // 368 // Exec may return driver.ErrSkip. 369 func (c *driverConn) Exec(query string, args []driver.Value) (driver.Result, error) { 370 list, err := Compile(query) 371 if err != nil { 372 return nil, err 373 } 374 375 return driverExec(c.db, c.ctx, list, args) 376 } 377 378 func driverExec(db *driverDB, ctx *TCtx, list List, args []driver.Value) (driver.Result, error) { 379 if _, _, err := db.db.Execute(ctx, list, params(args)...); err != nil { 380 return nil, err 381 } 382 383 if len(list.l) == 1 { 384 switch list.l[0].(type) { 385 case *createTableStmt, *dropTableStmt, *alterTableAddStmt, 386 *alterTableDropColumnStmt, *truncateTableStmt: 387 return driver.ResultNoRows, nil 388 } 389 } 390 391 r := &driverResult{} 392 if ctx != nil { 393 r.lastInsertID, r.rowsAffected = ctx.LastInsertID, ctx.RowsAffected 394 } 395 return r, nil 396 } 397 398 // Queryer is an optional interface that may be implemented by a Conn. 399 // 400 // If a Conn does not implement Queryer, the sql package's DB.Query will first 401 // prepare a query, execute the statement, and then close the statement. 402 // 403 // Query may return driver.ErrSkip. 404 func (c *driverConn) Query(query string, args []driver.Value) (driver.Rows, error) { 405 list, err := Compile(query) 406 if err != nil { 407 return nil, err 408 } 409 410 return driverQuery(c.db, c.ctx, list, args) 411 } 412 413 func driverQuery(db *driverDB, ctx *TCtx, list List, args []driver.Value) (driver.Rows, error) { 414 rss, _, err := db.db.Execute(ctx, list, params(args)...) 415 if err != nil { 416 return nil, err 417 } 418 419 switch n := len(rss); n { 420 case 0: 421 return nil, errNoResult 422 default: 423 return newDriverMultiRows(rss), nil 424 } 425 } 426 427 // driverResult is the result of a query execution. 428 type driverResult struct { 429 lastInsertID int64 430 rowsAffected int64 431 } 432 433 // LastInsertId returns the database's auto-generated ID after, for example, an 434 // INSERT into a table with primary key. 435 func (r *driverResult) LastInsertId() (int64, error) { // -golint 436 return r.lastInsertID, nil 437 } 438 439 // RowsAffected returns the number of rows affected by the query. 440 func (r *driverResult) RowsAffected() (int64, error) { 441 return r.rowsAffected, nil 442 } 443 444 // driverRows is an iterator over an executed query's results. 445 type driverRows struct { 446 rs Recordset 447 done chan int 448 rows chan interface{} 449 } 450 451 func newdriverRows(rs Recordset) *driverRows { 452 r := &driverRows{ 453 rs: rs, 454 done: make(chan int), 455 rows: make(chan interface{}, 500), 456 } 457 go func() { 458 err := io.EOF 459 if e := r.rs.Do(false, func(data []interface{}) (bool, error) { 460 select { 461 case r.rows <- data: 462 return true, nil 463 case <-r.done: 464 return false, nil 465 } 466 }); e != nil { 467 err = e 468 } 469 470 select { 471 case r.rows <- err: 472 case <-r.done: 473 } 474 }() 475 return r 476 } 477 478 // Columns returns the names of the columns. The number of columns of the 479 // result is inferred from the length of the slice. If a particular column 480 // name isn't known, an empty string should be returned for that entry. 481 func (r *driverRows) Columns() []string { 482 f, _ := r.rs.Fields() 483 return f 484 } 485 486 // Close closes the rows iterator. 487 func (r *driverRows) Close() error { 488 close(r.done) 489 return nil 490 } 491 492 // Next is called to populate the next row of data into the provided slice. The 493 // provided slice will be the same size as the Columns() are wide. 494 // 495 // The dest slice may be populated only with a driver Value type, but excluding 496 // string. All string values must be converted to []byte. 497 // 498 // Next should return io.EOF when there are no more rows. 499 func (r *driverRows) Next(dest []driver.Value) error { 500 select { 501 case rx := <-r.rows: 502 switch x := rx.(type) { 503 case error: 504 return x 505 case []interface{}: 506 if g, e := len(x), len(dest); g != e { 507 return fmt.Errorf("field count mismatch: got %d, need %d", g, e) 508 } 509 510 for i, xi := range x { 511 switch v := xi.(type) { 512 case nil, int64, float64, bool, []byte, time.Time: 513 dest[i] = v 514 case complex64, complex128, *big.Int, *big.Rat, idealComplex: 515 var buf bytes.Buffer 516 fmt.Fprintf(&buf, "%v", v) 517 dest[i] = buf.Bytes() 518 case int8: 519 dest[i] = int64(v) 520 case int16: 521 dest[i] = int64(v) 522 case int32: 523 dest[i] = int64(v) 524 case int: 525 dest[i] = int64(v) 526 case uint8: 527 dest[i] = int64(v) 528 case uint16: 529 dest[i] = int64(v) 530 case uint32: 531 dest[i] = int64(v) 532 case uint64: 533 dest[i] = int64(v) 534 case uint: 535 dest[i] = int64(v) 536 case time.Duration: 537 dest[i] = int64(v) 538 case string: 539 dest[i] = []byte(v) 540 case idealInt: 541 dest[i] = int64(v) 542 case idealUint: 543 dest[i] = int64(v) 544 case idealFloat: 545 dest[i] = float64(v) 546 default: 547 return fmt.Errorf("internal error 004") 548 } 549 } 550 return nil 551 default: 552 return fmt.Errorf("internal error 005") 553 } 554 case <-r.done: 555 return io.EOF 556 } 557 } 558 559 type driverMultiRows struct { 560 rs []Recordset 561 pos int 562 active *driverRows 563 } 564 565 func newDriverMultiRows(rs []Recordset) *driverMultiRows { 566 return &driverMultiRows{ 567 rs: rs, 568 active: newdriverRows(rs[0]), 569 } 570 } 571 func (r *driverMultiRows) Columns() []string { 572 return r.active.Columns() 573 } 574 func (r *driverMultiRows) Close() error { 575 return r.active.Close() 576 } 577 578 func (r *driverMultiRows) HasNextResultSet() bool { 579 return r.pos+1 < len(r.rs) 580 } 581 func (r *driverMultiRows) NextResultSet() error { 582 if r.HasNextResultSet() { 583 r.active.Close() 584 r.pos++ 585 r.active = newdriverRows(r.rs[r.pos]) 586 return nil 587 } 588 return io.EOF 589 } 590 591 func (r *driverMultiRows) Next(dest []driver.Value) error { 592 return r.active.Next(dest) 593 } 594 595 // driverStmt is a prepared statement. It is bound to a driverConn and not used 596 // by multiple goroutines concurrently. 597 type driverStmt struct { 598 conn *driverConn 599 stmt List 600 } 601 602 // Close closes the statement. 603 // 604 // As of Go 1.1, a Stmt will not be closed if it's in use by any queries. 605 func (s *driverStmt) Close() error { 606 delete(s.conn.stop, s) 607 return nil 608 } 609 610 // NumInput returns the number of placeholder parameters. 611 // 612 // If NumInput returns >= 0, the sql package will sanity check argument counts 613 // from callers and return errors to the caller before the statement's Exec or 614 // Query methods are called. 615 // 616 // NumInput may also return -1, if the driver doesn't know its number of 617 // placeholders. In that case, the sql package will not sanity check Exec or 618 // Query argument counts. 619 func (s *driverStmt) NumInput() int { 620 if x := s.stmt; len(x.l) == 1 { 621 return x.params 622 } 623 624 return -1 625 } 626 627 // Exec executes a query that doesn't return rows, such as an INSERT or UPDATE. 628 func (s *driverStmt) Exec(args []driver.Value) (driver.Result, error) { 629 c := s.conn 630 return driverExec(c.db, c.ctx, s.stmt, args) 631 } 632 633 // Exec executes a query that may return rows, such as a SELECT. 634 func (s *driverStmt) Query(args []driver.Value) (driver.Rows, error) { 635 c := s.conn 636 return driverQuery(c.db, c.ctx, s.stmt, args) 637 }