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  }