github.com/cznic/ql@v1.2.1-0.20181122101857-b60735abf8a0/ql.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  //LATER profile mem
     6  //LATER profile cpu
     7  //LATER coverage
     8  
     9  package ql
    10  
    11  import (
    12  	"bytes"
    13  	"errors"
    14  	"fmt"
    15  	"math/big"
    16  	"strconv"
    17  	"strings"
    18  	"sync"
    19  	"time"
    20  
    21  	"github.com/cznic/strutil"
    22  )
    23  
    24  const (
    25  	crossJoin = iota
    26  	leftJoin
    27  	rightJoin
    28  	fullJoin
    29  )
    30  
    31  // NOTE: all rset implementations must be safe for concurrent use by multiple
    32  // goroutines.  If the do method requires any execution domain local data, they
    33  // must be held out of the implementing instance.
    34  var (
    35  	_ rset = (*distinctRset)(nil)
    36  	_ rset = (*groupByRset)(nil)
    37  	_ rset = (*joinRset)(nil)
    38  	_ rset = (*limitRset)(nil)
    39  	_ rset = (*offsetRset)(nil)
    40  	_ rset = (*orderByRset)(nil)
    41  	_ rset = (*selectRset)(nil)
    42  	_ rset = (*selectStmt)(nil)
    43  	_ rset = (*tableRset)(nil)
    44  	_ rset = (*whereRset)(nil)
    45  
    46  	isTesting bool // enables test hook: select from an index
    47  )
    48  
    49  type rset interface {
    50  	plan(ctx *execCtx) (plan, error)
    51  }
    52  
    53  type recordset struct {
    54  	ctx *execCtx
    55  	plan
    56  	tx *TCtx
    57  }
    58  
    59  func (r recordset) fieldNames() []interface{} {
    60  	f := r.plan.fieldNames()
    61  	a := make([]interface{}, len(f))
    62  	for i, v := range f {
    63  		a[i] = v
    64  	}
    65  	return a
    66  }
    67  
    68  // Do implements Recordset.
    69  func (r recordset) Do(names bool, f func(data []interface{}) (bool, error)) error {
    70  	if names {
    71  		if more, err := f(r.fieldNames()); err != nil || !more {
    72  			return err
    73  		}
    74  	}
    75  	return r.ctx.db.do(r, f)
    76  }
    77  
    78  // Fields implements Recordset.
    79  func (r recordset) Fields() (names []string, err error) {
    80  	return r.plan.fieldNames(), nil
    81  }
    82  
    83  // FirstRow implements Recordset.
    84  func (r recordset) FirstRow() (row []interface{}, err error) {
    85  	rows, err := r.Rows(1, 0)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	if len(rows) != 0 {
    91  		return rows[0], nil
    92  	}
    93  
    94  	return nil, nil
    95  }
    96  
    97  // Rows implements Recordset.
    98  func (r recordset) Rows(limit, offset int) ([][]interface{}, error) {
    99  	var rows [][]interface{}
   100  	if err := r.Do(false, func(row []interface{}) (bool, error) {
   101  		if offset > 0 {
   102  			offset--
   103  			return true, nil
   104  		}
   105  
   106  		switch {
   107  		case limit < 0:
   108  			rows = append(rows, row)
   109  			return true, nil
   110  		case limit == 0:
   111  			return false, nil
   112  		default: // limit > 0
   113  			rows = append(rows, row)
   114  			limit--
   115  			return limit > 0, nil
   116  		}
   117  	}); err != nil {
   118  		return nil, err
   119  	}
   120  
   121  	return rows, nil
   122  }
   123  
   124  // List represents a group of compiled statements.
   125  type List struct {
   126  	l      []stmt
   127  	params int
   128  }
   129  
   130  // String implements fmt.Stringer
   131  func (l List) String() string {
   132  	var b bytes.Buffer
   133  	f := strutil.IndentFormatter(&b, "\t")
   134  	for _, s := range l.l {
   135  		switch s.(type) {
   136  		case beginTransactionStmt:
   137  			f.Format("%s\n%i", s)
   138  		case commitStmt, rollbackStmt:
   139  			f.Format("%u%s\n", s)
   140  		default:
   141  			f.Format("%s\n", s)
   142  		}
   143  	}
   144  	return b.String()
   145  }
   146  
   147  // IsExplainStmt reports whether l is a single EXPLAIN statement or a single EXPLAIN
   148  // statement enclosed in a transaction.
   149  func (l List) IsExplainStmt() bool {
   150  	switch len(l.l) {
   151  	case 1:
   152  		_, ok := l.l[0].(*explainStmt)
   153  		return ok
   154  	case 3:
   155  		if _, ok := l.l[0].(beginTransactionStmt); !ok {
   156  			return false
   157  		}
   158  		if _, ok := l.l[1].(*explainStmt); !ok {
   159  			return false
   160  		}
   161  		_, ok := l.l[2].(commitStmt)
   162  		return ok
   163  	default:
   164  		return false
   165  	}
   166  }
   167  
   168  type groupByRset struct {
   169  	colNames []string
   170  	src      plan
   171  }
   172  
   173  func (r *groupByRset) plan(ctx *execCtx) (plan, error) {
   174  	fields := r.src.fieldNames()
   175  	for _, v := range r.colNames {
   176  		found := false
   177  		for _, v2 := range fields {
   178  			if v == v2 {
   179  				found = true
   180  				break
   181  			}
   182  		}
   183  		if !found {
   184  			return nil, fmt.Errorf("unknown field %s", v)
   185  		}
   186  	}
   187  	return &groupByDefaultPlan{colNames: r.colNames, src: r.src, fields: fields}, nil
   188  }
   189  
   190  // TCtx represents transaction context. It enables to execute multiple
   191  // statement lists in the same context. The same context guarantees the state
   192  // of the DB cannot change in between the separated executions.
   193  //
   194  // LastInsertID
   195  //
   196  // LastInsertID is updated by INSERT INTO statements. The value considers
   197  // performed ROLLBACK statements, if any, even though roll backed IDs are not
   198  // reused. QL clients should treat the field as read only.
   199  //
   200  // RowsAffected
   201  //
   202  // RowsAffected is updated by INSERT INTO, DELETE FROM and UPDATE statements.
   203  // The value does not (yet) consider any ROLLBACK statements involved.  QL
   204  // clients should treat the field as read only.
   205  type TCtx struct {
   206  	LastInsertID int64
   207  	RowsAffected int64
   208  }
   209  
   210  // NewRWCtx returns a new read/write transaction context.  NewRWCtx is safe for
   211  // concurrent use by multiple goroutines, every one of them will get a new,
   212  // unique context.
   213  func NewRWCtx() *TCtx { return &TCtx{} }
   214  
   215  // Recordset is a result of a select statement. It can call a user function for
   216  // every row (record) in the set using the Do method.
   217  //
   218  // Recordsets can be safely reused. Evaluation of the rows is performed lazily.
   219  // Every invocation of Do will see the current, potentially actualized data.
   220  //
   221  // Do
   222  //
   223  // Do will call f for every row (record) in the Recordset.
   224  //
   225  // If f returns more == false or err != nil then f will not be called for any
   226  // remaining rows in the set and the err value is returned from Do.
   227  //
   228  // If names == true then f is firstly called with a virtual row
   229  // consisting of field (column) names of the RecordSet.
   230  //
   231  // Do is executed in a read only context and performs a RLock of the
   232  // database.
   233  //
   234  // Do is safe for concurrent use by multiple goroutines.
   235  //
   236  // Fields
   237  //
   238  // Fields return a slice of field names of the recordset. The result is computed
   239  // without actually computing the recordset rows.
   240  //
   241  // FirstRow
   242  //
   243  // FirstRow will return the first row of the RecordSet or an error, if any. If
   244  // the Recordset has no rows the result is (nil, nil).
   245  //
   246  // Rows
   247  //
   248  // Rows will return rows in Recordset or an error, if any. The semantics of
   249  // limit and offset are the same as of the LIMIT and OFFSET clauses of the
   250  // SELECT statement. To get all rows pass limit < 0. If there are no rows to
   251  // return the result is (nil, nil).
   252  type Recordset interface {
   253  	Do(names bool, f func(data []interface{}) (more bool, err error)) error
   254  	Fields() (names []string, err error)
   255  	FirstRow() (row []interface{}, err error)
   256  	Rows(limit, offset int) (rows [][]interface{}, err error)
   257  }
   258  
   259  type assignment struct {
   260  	colName string
   261  	expr    expression
   262  }
   263  
   264  func (a *assignment) String() string {
   265  	return fmt.Sprintf("%s=%s", a.colName, a.expr)
   266  }
   267  
   268  type distinctRset struct {
   269  	src plan
   270  }
   271  
   272  func (r *distinctRset) plan(ctx *execCtx) (plan, error) {
   273  	return &distinctDefaultPlan{src: r.src, fields: r.src.fieldNames()}, nil
   274  }
   275  
   276  type orderByRset struct {
   277  	asc bool
   278  	by  []expression
   279  	src plan
   280  }
   281  
   282  func (r *orderByRset) String() string {
   283  	a := make([]string, len(r.by))
   284  	for i, v := range r.by {
   285  		a[i] = v.String()
   286  	}
   287  	s := strings.Join(a, ", ")
   288  	if !r.asc {
   289  		s += " DESC"
   290  	}
   291  	return s
   292  }
   293  
   294  func (r *orderByRset) plan(ctx *execCtx) (plan, error) {
   295  	if _, ok := r.src.(*nullPlan); ok {
   296  		return r.src, nil
   297  	}
   298  
   299  	var by []expression
   300  	fields := r.src.fieldNames()
   301  	for _, e := range r.by {
   302  		cols := mentionedColumns(e)
   303  		for k := range cols {
   304  			found := false
   305  			for _, v := range fields {
   306  				if k == v {
   307  					found = true
   308  					break
   309  				}
   310  			}
   311  			if !found {
   312  				return nil, fmt.Errorf("unknown field %s", k)
   313  			}
   314  		}
   315  		if len(cols) == 0 {
   316  			v, err := e.eval(ctx, nil)
   317  			if err != nil {
   318  				by = append(by, e)
   319  				continue
   320  			}
   321  
   322  			if isConstValue(v) != nil {
   323  				continue
   324  			}
   325  		}
   326  
   327  		by = append(by, e)
   328  	}
   329  	return &orderByDefaultPlan{asc: r.asc, by: by, src: r.src, fields: fields}, nil
   330  }
   331  
   332  type whereRset struct {
   333  	expr   expression
   334  	src    plan
   335  	sel    *selectStmt
   336  	exists bool
   337  }
   338  
   339  func (r *whereRset) String() string {
   340  	if r.sel != nil {
   341  		s := ""
   342  		if !r.exists {
   343  			s += " NOT "
   344  		}
   345  		return fmt.Sprintf("%s EXISTS ( %s )", s, strings.TrimSuffix(r.sel.String(), ";"))
   346  	}
   347  	return r.expr.String()
   348  }
   349  
   350  func (r *whereRset) planBinOp(x *binaryOperation) (plan, error) {
   351  	p := r.src
   352  	ok, cn := isColumnExpression(x.l)
   353  	if ok && cn == "id()" {
   354  		if v := isConstValue(x.r); v != nil {
   355  			v, err := typeCheck1(v, idCol)
   356  			if err != nil {
   357  				return nil, err
   358  			}
   359  
   360  			rv := v.(int64)
   361  			switch {
   362  			case p.hasID():
   363  				switch x.op {
   364  				case '<':
   365  					if rv <= 1 {
   366  						return &nullPlan{p.fieldNames()}, nil
   367  					}
   368  				case '>':
   369  					if rv <= 0 {
   370  						return p, nil
   371  					}
   372  				case ge:
   373  					if rv >= 1 {
   374  						return p, nil
   375  					}
   376  				case neq:
   377  					if rv <= 0 {
   378  						return p, nil
   379  					}
   380  				case eq:
   381  					if rv <= 0 {
   382  						return &nullPlan{p.fieldNames()}, nil
   383  					}
   384  				case le:
   385  					if rv <= 0 {
   386  						return &nullPlan{p.fieldNames()}, nil
   387  					}
   388  				}
   389  			}
   390  		}
   391  	}
   392  
   393  	var err error
   394  	var p2 plan
   395  	var is []string
   396  	switch x.op {
   397  	case eq, ge, '>', le, '<', neq:
   398  		if p2, is, err = p.filter(x); err != nil {
   399  			return nil, err
   400  		}
   401  
   402  		if p2 != nil {
   403  			return p2, nil
   404  		}
   405  	case andand:
   406  		var in []expression
   407  		var f func(expression)
   408  		f = func(e expression) {
   409  			b, ok := e.(*binaryOperation)
   410  			if !ok || b.op != andand {
   411  				in = append(in, e)
   412  				return
   413  			}
   414  
   415  			f(b.l)
   416  			f(b.r)
   417  		}
   418  		f(x)
   419  		out := []expression{}
   420  		p := r.src
   421  		isNewPlan := false
   422  		for _, e := range in {
   423  			p2, is2, err := p.filter(e)
   424  			if err != nil {
   425  				return nil, err
   426  			}
   427  
   428  			if p2 == nil {
   429  				is = append(is, is2...)
   430  				out = append(out, e)
   431  				continue
   432  			}
   433  
   434  			p = p2
   435  			isNewPlan = true
   436  		}
   437  
   438  		if !isNewPlan {
   439  			break
   440  		}
   441  
   442  		if len(out) == 0 {
   443  			return p, nil
   444  		}
   445  
   446  		for len(out) > 1 {
   447  			n := len(out)
   448  			e, err := newBinaryOperation(andand, out[n-2], out[n-1])
   449  			if err != nil {
   450  				return nil, err
   451  			}
   452  
   453  			out = out[:n-1]
   454  			out[n-2] = e
   455  		}
   456  
   457  		return &filterDefaultPlan{p, out[0], is}, nil
   458  	}
   459  
   460  	return &filterDefaultPlan{p, x, is}, nil
   461  }
   462  
   463  func (r *whereRset) planIdent(x *ident) (plan, error) {
   464  	p := r.src
   465  	p2, is, err := p.filter(x)
   466  	if err != nil {
   467  		return nil, err
   468  	}
   469  
   470  	if p2 != nil {
   471  		return p2, nil
   472  	}
   473  
   474  	return &filterDefaultPlan{p, x, is}, nil
   475  }
   476  
   477  func (r *whereRset) planIsNull(x *isNull) (plan, error) {
   478  	p := r.src
   479  	ok, cn := isColumnExpression(x.expr)
   480  	if !ok {
   481  		return &filterDefaultPlan{p, x, nil}, nil
   482  	}
   483  
   484  	if cn == "id()" {
   485  		switch {
   486  		case p.hasID():
   487  			switch {
   488  			case x.not: // IS NOT NULL
   489  				return p, nil
   490  			default: // IS NULL
   491  				return &nullPlan{p.fieldNames()}, nil
   492  			}
   493  		default:
   494  			switch {
   495  			case x.not: // IS NOT NULL
   496  				return &nullPlan{p.fieldNames()}, nil
   497  			default: // IS NULL
   498  				return p, nil
   499  			}
   500  		}
   501  	}
   502  
   503  	p2, is, err := p.filter(x)
   504  	if err != nil {
   505  		return nil, err
   506  	}
   507  
   508  	if p2 != nil {
   509  		return p2, nil
   510  	}
   511  
   512  	return &filterDefaultPlan{p, x, is}, nil
   513  }
   514  
   515  func (r *whereRset) planUnaryOp(x *unaryOperation) (plan, error) {
   516  	p := r.src
   517  	p2, is, err := p.filter(x)
   518  	if err != nil {
   519  		return nil, err
   520  	}
   521  
   522  	if p2 != nil {
   523  		return p2, nil
   524  	}
   525  
   526  	return &filterDefaultPlan{p, x, is}, nil
   527  }
   528  
   529  func (r *whereRset) plan(ctx *execCtx) (plan, error) {
   530  	o := r.src
   531  	if r.sel != nil {
   532  		var exists bool
   533  		ctx.mu.RLock()
   534  		m, ok := ctx.cache[r.sel]
   535  		ctx.mu.RUnlock()
   536  		if ok {
   537  			exists = m.(bool)
   538  		} else {
   539  			p, err := r.sel.plan(ctx)
   540  			if err != nil {
   541  				return nil, err
   542  			}
   543  			err = p.do(ctx, func(i interface{}, data []interface{}) (bool, error) {
   544  				if len(data) > 0 {
   545  					exists = true
   546  				}
   547  				return false, nil
   548  			})
   549  			if err != nil {
   550  				return nil, err
   551  			}
   552  			ctx.mu.Lock()
   553  			ctx.cache[r.sel] = true
   554  			ctx.mu.Unlock()
   555  		}
   556  		if r.exists == exists {
   557  			return o, nil
   558  		}
   559  		return &nullPlan{fields: o.fieldNames()}, nil
   560  	}
   561  	return r.planExpr(ctx)
   562  }
   563  
   564  func (r *whereRset) planExpr(ctx *execCtx) (plan, error) {
   565  	if r.expr == nil {
   566  		return &nullPlan{}, nil
   567  	}
   568  	expr, err := r.expr.clone(ctx.arg)
   569  	if err != nil {
   570  		return nil, err
   571  	}
   572  
   573  	switch r.src.(type) {
   574  	case *leftJoinDefaultPlan, *rightJoinDefaultPlan, *fullJoinDefaultPlan:
   575  		return &filterDefaultPlan{r.src, expr, nil}, nil
   576  	}
   577  
   578  	switch x := expr.(type) {
   579  	case *binaryOperation:
   580  		return r.planBinOp(x)
   581  	case *ident:
   582  		return r.planIdent(x)
   583  	case *isNull:
   584  		return r.planIsNull(x)
   585  	case *pIn:
   586  		//TODO optimize
   587  		//TODO show plan
   588  	case *pLike:
   589  		//TODO optimize
   590  	case *unaryOperation:
   591  		return r.planUnaryOp(x)
   592  	}
   593  
   594  	return &filterDefaultPlan{r.src, expr, nil}, nil
   595  }
   596  
   597  type offsetRset struct {
   598  	expr expression
   599  	src  plan
   600  }
   601  
   602  func (r *offsetRset) plan(ctx *execCtx) (plan, error) {
   603  	return &offsetDefaultPlan{expr: r.expr, src: r.src, fields: r.src.fieldNames()}, nil
   604  }
   605  
   606  type limitRset struct {
   607  	expr expression
   608  	src  plan
   609  }
   610  
   611  func (r *limitRset) plan(ctx *execCtx) (plan, error) {
   612  	return &limitDefaultPlan{expr: r.expr, src: r.src, fields: r.src.fieldNames()}, nil
   613  }
   614  
   615  type selectRset struct {
   616  	flds []*fld
   617  	src  plan
   618  }
   619  
   620  func (r *selectRset) plan(ctx *execCtx) (plan, error) {
   621  	if r.src == nil {
   622  		return nil, nil
   623  	}
   624  
   625  	var flds2 []*fld
   626  	if len(r.flds) != 0 {
   627  		m := map[string]struct{}{}
   628  		for _, v := range r.flds {
   629  			mentionedColumns0(v.expr, true, true, m)
   630  		}
   631  		for _, v := range r.src.fieldNames() {
   632  			delete(m, v)
   633  		}
   634  		for k := range m {
   635  			return nil, fmt.Errorf("unknown field %s", k)
   636  		}
   637  
   638  		flds2 = append(flds2, r.flds...)
   639  	}
   640  
   641  	if x, ok := r.src.(*groupByDefaultPlan); ok {
   642  		if len(r.flds) == 0 {
   643  			fields := x.fieldNames()
   644  			flds := make([]*fld, len(fields))
   645  			for i, v := range fields {
   646  				flds[i] = &fld{&ident{v}, v}
   647  			}
   648  			return &selectFieldsGroupPlan{flds: flds, src: x, fields: fields}, nil
   649  		}
   650  
   651  		p := &selectFieldsGroupPlan{flds: flds2, src: x}
   652  		for _, v := range r.flds {
   653  			p.fields = append(p.fields, v.name)
   654  		}
   655  		return p, nil
   656  	}
   657  
   658  	if len(r.flds) == 0 {
   659  		return r.src, nil
   660  	}
   661  
   662  	f0 := r.src.fieldNames()
   663  	if len(f0) == len(flds2) {
   664  		match := true
   665  		for i, v := range flds2 {
   666  			if x, ok := v.expr.(*ident); ok && x.s == f0[i] && v.name == f0[i] {
   667  				continue
   668  			}
   669  
   670  			match = false
   671  			break
   672  		}
   673  
   674  		if match {
   675  			return r.src, nil
   676  		}
   677  	}
   678  
   679  	src := r.src
   680  	if x, ok := src.(*tableDefaultPlan); ok {
   681  		isconst := true
   682  		for _, v := range flds2 {
   683  			if isConstValue(v.expr) == nil {
   684  				isconst = false
   685  				break
   686  			}
   687  		}
   688  		if isconst { // #250
   689  			src = &tableNilPlan{x.t}
   690  		}
   691  	}
   692  
   693  	p := &selectFieldsDefaultPlan{flds: flds2, src: src}
   694  	for _, v := range r.flds {
   695  		p.fields = append(p.fields, v.name)
   696  	}
   697  	return p, nil
   698  }
   699  
   700  type tableRset string
   701  
   702  func (r tableRset) plan(ctx *execCtx) (plan, error) {
   703  	switch r {
   704  	case "__Table":
   705  		return &sysTableDefaultPlan{}, nil
   706  	case "__Column":
   707  		return &sysColumnDefaultPlan{}, nil
   708  	case "__Index":
   709  		return &sysIndexDefaultPlan{}, nil
   710  	}
   711  
   712  	t, ok := ctx.db.root.tables[string(r)]
   713  	if !ok && isTesting {
   714  		if _, x0 := ctx.db.root.findIndexByName(string(r)); x0 != nil {
   715  			return &selectIndexDefaultPlan{nm: string(r), x: x0}, nil
   716  		}
   717  	}
   718  
   719  	if !ok {
   720  		return nil, fmt.Errorf("table %s does not exist", r)
   721  	}
   722  
   723  	rs := &tableDefaultPlan{t: t}
   724  	for _, col := range t.cols {
   725  		rs.fields = append(rs.fields, col.name)
   726  	}
   727  	return rs, nil
   728  }
   729  
   730  func findFld(fields []*fld, name string) (f *fld) {
   731  	for _, f = range fields {
   732  		if f.name == name {
   733  			return
   734  		}
   735  	}
   736  
   737  	return nil
   738  }
   739  
   740  type col struct {
   741  	index      int
   742  	name       string
   743  	typ        int
   744  	constraint *constraint
   745  	dflt       expression
   746  }
   747  
   748  var idCol = &col{name: "id()", typ: qInt64}
   749  
   750  func findCol(cols []*col, name string) (c *col) {
   751  	for _, c = range cols {
   752  		if c.name == name {
   753  			return
   754  		}
   755  	}
   756  
   757  	return nil
   758  }
   759  
   760  func (f *col) clone() *col {
   761  	r := *f
   762  	r.constraint = f.constraint.clone()
   763  	if f.dflt != nil {
   764  		r.dflt, _ = r.dflt.clone(nil)
   765  	}
   766  	return &r
   767  }
   768  
   769  func (f *col) typeCheck(x interface{}) (ok bool) { //NTYPE
   770  	switch x.(type) {
   771  	case nil:
   772  		return true
   773  	case bool:
   774  		return f.typ == qBool
   775  	case complex64:
   776  		return f.typ == qComplex64
   777  	case complex128:
   778  		return f.typ == qComplex128
   779  	case float32:
   780  		return f.typ == qFloat32
   781  	case float64:
   782  		return f.typ == qFloat64
   783  	case int8:
   784  		return f.typ == qInt8
   785  	case int16:
   786  		return f.typ == qInt16
   787  	case int32:
   788  		return f.typ == qInt32
   789  	case int64:
   790  		return f.typ == qInt64
   791  	case string:
   792  		return f.typ == qString
   793  	case uint8:
   794  		return f.typ == qUint8
   795  	case uint16:
   796  		return f.typ == qUint16
   797  	case uint32:
   798  		return f.typ == qUint32
   799  	case uint64:
   800  		return f.typ == qUint64
   801  	case []byte:
   802  		return f.typ == qBlob
   803  	case *big.Int:
   804  		return f.typ == qBigInt
   805  	case *big.Rat:
   806  		return f.typ == qBigRat
   807  	case time.Time:
   808  		return f.typ == qTime
   809  	case time.Duration:
   810  		return f.typ == qDuration
   811  	case chunk:
   812  		return true // was checked earlier
   813  	}
   814  	return
   815  }
   816  
   817  func cols2meta(f []*col) (s string) {
   818  	a := []string{}
   819  	for _, f := range f {
   820  		a = append(a, string(f.typ)+f.name)
   821  	}
   822  	return strings.Join(a, "|")
   823  }
   824  
   825  // DB represent the database capable of executing QL statements.
   826  type DB struct {
   827  	cc          *TCtx // Current transaction context
   828  	exprCache   map[string]expression
   829  	exprCacheMu sync.Mutex
   830  	hasIndex2   int // 0: nope, 1: in progress, 2: yes.
   831  	isMem       bool
   832  	mu          sync.Mutex
   833  	queue       []chan struct{}
   834  	root        *root
   835  	rw          bool // DB FSM
   836  	rwmu        sync.RWMutex
   837  	store       storage
   838  	tnl         int // Transaction nesting level
   839  }
   840  
   841  var selIndex2Expr = MustCompile("select Expr from __Index2_Expr where Index2_ID == $1")
   842  
   843  func newDB(store storage) (db *DB, err error) {
   844  	db0 := &DB{
   845  		exprCache: map[string]expression{},
   846  		store:     store,
   847  	}
   848  	if db0.root, err = newRoot(store); err != nil {
   849  		return
   850  	}
   851  
   852  	ctx := newExecCtx(db0, nil)
   853  	for _, t := range db0.root.tables {
   854  		if err := t.constraintsAndDefaults(ctx); err != nil {
   855  			return nil, err
   856  		}
   857  	}
   858  
   859  	if !db0.hasAllIndex2() {
   860  		return db0, nil
   861  	}
   862  
   863  	db0.hasIndex2 = 2
   864  	rss, _, err := db0.Run(nil, "select id(), TableName, IndexName, IsUnique, Root from __Index2 where !IsSimple")
   865  	if err != nil {
   866  		return nil, err
   867  	}
   868  
   869  	rows, err := rss[0].Rows(-1, 0)
   870  	if err != nil {
   871  		return nil, err
   872  	}
   873  
   874  	for _, row := range rows {
   875  		defer func() {
   876  			if e := recover(); e != nil {
   877  				err = fmt.Errorf("error loading DB indices: %v", e)
   878  			}
   879  		}()
   880  
   881  		id := row[0].(int64)
   882  		tn := row[1].(string)
   883  		xn := row[2].(string)
   884  		unique := row[3].(bool)
   885  		xroot := row[4].(int64)
   886  
   887  		t := db0.root.tables[tn]
   888  		if t == nil {
   889  			return nil, fmt.Errorf("DB index refers to nonexistent table: %s", tn)
   890  		}
   891  
   892  		x, err := store.OpenIndex(unique, xroot)
   893  		if err != nil {
   894  			return nil, err
   895  		}
   896  
   897  		if v := t.indices2[xn]; v != nil {
   898  			return nil, fmt.Errorf("duplicate DB index: %s", xn)
   899  		}
   900  
   901  		ix := &index2{
   902  			unique: unique,
   903  			x:      x,
   904  			xroot:  xroot,
   905  		}
   906  
   907  		rss, _, err := db0.Execute(nil, selIndex2Expr, id)
   908  		if err != nil {
   909  			return nil, err
   910  		}
   911  
   912  		rows, err := rss[0].Rows(-1, 0)
   913  		if err != nil {
   914  			return nil, err
   915  		}
   916  
   917  		if len(rows) == 0 {
   918  			return nil, fmt.Errorf("index has no expression: %s", xn)
   919  		}
   920  
   921  		var sources []string
   922  		var list []expression
   923  		for _, row := range rows {
   924  			src, ok := row[0].(string)
   925  			if !ok {
   926  				return nil, fmt.Errorf("index %s: expression of type %T", xn, row[0])
   927  			}
   928  
   929  			expr, err := db0.str2expr(src)
   930  			if err != nil {
   931  				return nil, fmt.Errorf("index %s: expression error: %v", xn, err)
   932  			}
   933  
   934  			sources = append(sources, src)
   935  			list = append(list, expr)
   936  		}
   937  
   938  		ix.sources = sources
   939  		ix.exprList = list
   940  		if t.indices2 == nil {
   941  			t.indices2 = map[string]*index2{}
   942  		}
   943  		t.indices2[xn] = ix
   944  	}
   945  	return db0, nil
   946  }
   947  
   948  func (db *DB) deleteIndex2ByIndexName(nm string) error {
   949  	for _, s := range deleteIndex2ByIndexName.l {
   950  		if _, err := s.exec(newExecCtx(db, []interface{}{nm})); err != nil {
   951  			return err
   952  		}
   953  	}
   954  	return nil
   955  }
   956  
   957  func (db *DB) deleteIndex2ByTableName(nm string) error {
   958  	for _, s := range deleteIndex2ByTableName.l {
   959  		if _, err := s.exec(newExecCtx(db, []interface{}{nm})); err != nil {
   960  			return err
   961  		}
   962  	}
   963  	return nil
   964  }
   965  
   966  func (db *DB) createIndex2() error {
   967  	if db.hasIndex2 != 0 {
   968  		return nil
   969  	}
   970  
   971  	db.hasIndex2 = 1
   972  	ctx := execCtx{db: db}
   973  	for _, s := range createIndex2.l {
   974  		if _, err := s.exec(&ctx); err != nil {
   975  			db.hasIndex2 = 0
   976  			return err
   977  		}
   978  	}
   979  
   980  	for t := db.root.thead; t != nil; t = t.tnext {
   981  		for i, index := range t.indices {
   982  			if index == nil {
   983  				continue
   984  			}
   985  
   986  			expr := "id()"
   987  			if i != 0 {
   988  				expr = t.cols0[i-1].name
   989  			}
   990  
   991  			if err := db.insertIndex2(t.name, index.name, []string{expr}, index.unique, true, index.xroot); err != nil {
   992  				db.hasIndex2 = 0
   993  				return err
   994  			}
   995  		}
   996  	}
   997  
   998  	db.hasIndex2 = 2
   999  	return nil
  1000  }
  1001  
  1002  func (db *DB) insertIndex2(tableName, indexName string, expr []string, unique, isSimple bool, h int64) error {
  1003  	ctx := execCtx{db: db}
  1004  	ctx.arg = []interface{}{
  1005  		tableName,
  1006  		indexName,
  1007  		unique,
  1008  		isSimple,
  1009  		h,
  1010  	}
  1011  	if _, err := insertIndex2.l[0].exec(&ctx); err != nil {
  1012  		return err
  1013  	}
  1014  
  1015  	id := db.root.lastInsertID
  1016  	for _, e := range expr {
  1017  		ctx.arg = []interface{}{id, e}
  1018  		if _, err := insertIndex2Expr.l[0].exec(&ctx); err != nil {
  1019  			return err
  1020  		}
  1021  	}
  1022  	return nil
  1023  }
  1024  
  1025  func (db *DB) hasAllIndex2() bool {
  1026  	t := db.root.tables
  1027  	if _, ok := t["__Index2"]; !ok {
  1028  		return false
  1029  	}
  1030  
  1031  	_, ok := t["__Index2_Expr"]
  1032  	return ok
  1033  }
  1034  
  1035  func (db *DB) str2expr(expr string) (expression, error) {
  1036  	db.exprCacheMu.Lock()
  1037  	e := db.exprCache[expr]
  1038  	db.exprCacheMu.Unlock()
  1039  	if e != nil {
  1040  		return e, nil
  1041  	}
  1042  
  1043  	e, err := compileExpr(expr)
  1044  	if err != nil {
  1045  		return nil, err
  1046  	}
  1047  
  1048  	db.exprCacheMu.Lock()
  1049  	for k := range db.exprCache {
  1050  		if len(db.exprCache) < 1000 {
  1051  			break
  1052  		}
  1053  
  1054  		delete(db.exprCache, k)
  1055  	}
  1056  	db.exprCache[expr] = e
  1057  	db.exprCacheMu.Unlock()
  1058  	return e, nil
  1059  }
  1060  
  1061  // Name returns the name of the DB.
  1062  func (db *DB) Name() string { return db.store.Name() }
  1063  
  1064  // Run compiles and executes a statement list.  It returns, if applicable, a
  1065  // RecordSet slice and/or an index and error.
  1066  //
  1067  // For more details please see DB.Execute
  1068  //
  1069  // Run is safe for concurrent use by multiple goroutines.
  1070  func (db *DB) Run(ctx *TCtx, ql string, arg ...interface{}) (rs []Recordset, index int, err error) {
  1071  	l, err := Compile(ql)
  1072  	if err != nil {
  1073  		return nil, -1, err
  1074  	}
  1075  
  1076  	return db.Execute(ctx, l, arg...)
  1077  }
  1078  
  1079  func (db *DB) run(ctx *TCtx, ql string, arg ...interface{}) (rs []Recordset, index int, err error) {
  1080  	l, err := compile(ql)
  1081  	if err != nil {
  1082  		return nil, -1, err
  1083  	}
  1084  
  1085  	return db.Execute(ctx, l, arg...)
  1086  }
  1087  
  1088  // Compile parses the ql statements from src and returns a compiled list for
  1089  // DB.Execute or an error if any.
  1090  //
  1091  // Compile is safe for concurrent use by multiple goroutines.
  1092  func Compile(src string) (List, error) {
  1093  	l, err := newLexer(src)
  1094  	if err != nil {
  1095  		return List{}, err
  1096  	}
  1097  
  1098  	if yyParse(l) != 0 {
  1099  		return List{}, l.errs
  1100  	}
  1101  
  1102  	return List{l.list, l.params}, nil
  1103  }
  1104  
  1105  func compileExpr(src string) (expression, error) {
  1106  	l, err := newLexer(src)
  1107  	if err != nil {
  1108  		return nil, err
  1109  	}
  1110  
  1111  	l.inj = parseExpression
  1112  	if yyParse(l) != 0 {
  1113  		return nil, l.errs
  1114  	}
  1115  
  1116  	return l.expr, nil
  1117  }
  1118  
  1119  func compile(src string) (List, error) {
  1120  	l, err := newLexer(src)
  1121  	if err != nil {
  1122  		return List{}, err
  1123  	}
  1124  
  1125  	l.root = true
  1126  	if yyParse(l) != 0 {
  1127  		return List{}, l.errs
  1128  	}
  1129  
  1130  	return List{l.list, l.params}, nil
  1131  }
  1132  
  1133  // MustCompile is like Compile but panics if the ql statements in src cannot be
  1134  // compiled. It simplifies safe initialization of global variables holding
  1135  // compiled statement lists for DB.Execute.
  1136  //
  1137  // MustCompile is safe for concurrent use by multiple goroutines.
  1138  func MustCompile(src string) List {
  1139  	list, err := Compile(src)
  1140  	if err != nil {
  1141  		panic("ql: Compile(" + strconv.Quote(src) + "): " + err.Error()) // panic ok here
  1142  	}
  1143  
  1144  	return list
  1145  }
  1146  
  1147  func mustCompile(src string) List {
  1148  	list, err := compile(src)
  1149  	if err != nil {
  1150  		panic("ql: compile(" + strconv.Quote(src) + "): " + err.Error()) // panic ok here
  1151  	}
  1152  
  1153  	return list
  1154  }
  1155  
  1156  // Execute executes statements in a list while substituting QL parameters from
  1157  // arg.
  1158  //
  1159  // The resulting []Recordset corresponds to the SELECT FROM statements in the
  1160  // list.
  1161  //
  1162  // If err != nil then index is the zero based index of the failed QL statement.
  1163  // Empty statements do not count.
  1164  //
  1165  // The FSM STT describing the relations between DB states, statements and the
  1166  // ctx parameter.
  1167  //
  1168  //  +-----------+---------------------+------------------+------------------+------------------+
  1169  //  |\  Event   |                     |                  |                  |                  |
  1170  //  | \-------\ |     BEGIN           |                  |                  |    Other         |
  1171  //  |   State  \|     TRANSACTION     |      COMMIT      |     ROLLBACK     |    statement     |
  1172  //  +-----------+---------------------+------------------+------------------+------------------+
  1173  //  | RD        | if PC == nil        | return error     | return error     | DB.RLock         |
  1174  //  |           |     return error    |                  |                  | Execute(1)       |
  1175  //  | CC == nil |                     |                  |                  | DB.RUnlock       |
  1176  //  | TNL == 0  | DB.Lock             |                  |                  |                  |
  1177  //  |           | CC = PC             |                  |                  |                  |
  1178  //  |           | TNL++               |                  |                  |                  |
  1179  //  |           | DB.BeginTransaction |                  |                  |                  |
  1180  //  |           | State = WR          |                  |                  |                  |
  1181  //  +-----------+---------------------+------------------+------------------+------------------+
  1182  //  | WR        | if PC == nil        | if PC != CC      | if PC != CC      | if PC == nil     |
  1183  //  |           |     return error    |     return error |     return error |     DB.Rlock     |
  1184  //  | CC != nil |                     |                  |                  |     Execute(1)   |
  1185  //  | TNL != 0  | if PC != CC         | DB.Commit        | DB.Rollback      |     RUnlock      |
  1186  //  |           |     DB.Lock         | TNL--            | TNL--            | else if PC != CC |
  1187  //  |           |     CC = PC         | if TNL == 0      | if TNL == 0      |     return error |
  1188  //  |           |                     |     CC = nil     |     CC = nil     | else             |
  1189  //  |           | TNL++               |     State = RD   |     State = RD   |     Execute(2)   |
  1190  //  |           | DB.BeginTransaction |     DB.Unlock    |     DB.Unlock    |                  |
  1191  //  +-----------+---------------------+------------------+------------------+------------------+
  1192  //  CC: Curent transaction context
  1193  //  PC: Passed transaction context
  1194  //  TNL: Transaction nesting level
  1195  //
  1196  // Lock, Unlock, RLock, RUnlock semantics above are the same as in
  1197  // sync.RWMutex.
  1198  //
  1199  // (1): Statement list is executed outside of a transaction. Attempts to update
  1200  // the DB will fail, the execution context is read-only. Other statements with
  1201  // read only context will execute concurrently. If any statement fails, the
  1202  // execution of the statement list is aborted.
  1203  //
  1204  // Note that the RLock/RUnlock surrounds every single "other" statement when it
  1205  // is executed outside of a transaction. If read consistency is required by a
  1206  // list of more than one statement then an explicit BEGIN TRANSACTION / COMMIT
  1207  // or ROLLBACK wrapper must be provided. Otherwise the state of the DB may
  1208  // change in between executing any two out-of-transaction statements.
  1209  //
  1210  // (2): Statement list is executed inside an isolated transaction. Execution of
  1211  // statements can update the DB, the execution context is read-write. If any
  1212  // statement fails, the execution of the statement list is aborted and the DB
  1213  // is automatically rolled back to the TNL which was active before the start of
  1214  // execution of the statement list.
  1215  //
  1216  // Execute is safe for concurrent use by multiple goroutines, but one must
  1217  // consider the blocking issues as discussed above.
  1218  //
  1219  // ACID
  1220  //
  1221  // Atomicity: Transactions are atomic. Transactions can be nested. Commit or
  1222  // rollbacks work on the current transaction level. Transactions are made
  1223  // persistent only on the top level commit. Reads made from within an open
  1224  // transaction are dirty reads.
  1225  //
  1226  // Consistency: Transactions bring the DB from one structurally consistent
  1227  // state to other structurally consistent state.
  1228  //
  1229  // Isolation: Transactions are isolated. Isolation is implemented by
  1230  // serialization.
  1231  //
  1232  // Durability: Transactions are durable. A two phase commit protocol and a
  1233  // write ahead log is used. Database is recovered after a crash from the write
  1234  // ahead log automatically on open.
  1235  func (db *DB) Execute(ctx *TCtx, l List, arg ...interface{}) (rs []Recordset, index int, err error) {
  1236  	// Sanitize args
  1237  	for i, v := range arg {
  1238  		switch x := v.(type) {
  1239  		case nil, bool, complex64, complex128, float32, float64, string,
  1240  			int8, int16, int32, int64, int,
  1241  			uint8, uint16, uint32, uint64, uint,
  1242  			*big.Int, *big.Rat, []byte, time.Duration, time.Time:
  1243  		case big.Int:
  1244  			arg[i] = &x
  1245  		case big.Rat:
  1246  			arg[i] = &x
  1247  		default:
  1248  			return nil, 0, fmt.Errorf("cannot use arg[%d] (type %T):unsupported type", i, v)
  1249  		}
  1250  	}
  1251  
  1252  	tnl0 := -1
  1253  	if ctx != nil {
  1254  		ctx.LastInsertID, ctx.RowsAffected = 0, 0
  1255  	}
  1256  
  1257  	list := l.l
  1258  	for _, s := range list {
  1259  		r, tnla, tnl, err := db.run1(ctx, s, arg...)
  1260  		if tnl0 < 0 {
  1261  			tnl0 = tnla
  1262  		}
  1263  		if err != nil {
  1264  			for tnl > tnl0 {
  1265  				var e2 error
  1266  				if _, _, tnl, e2 = db.run1(ctx, rollbackStmt{}); e2 != nil {
  1267  					err = e2
  1268  				}
  1269  			}
  1270  			return rs, index, err
  1271  		}
  1272  
  1273  		if r != nil {
  1274  			if x, ok := r.(recordset); ok {
  1275  				x.tx = ctx
  1276  				r = x
  1277  			}
  1278  			rs = append(rs, r)
  1279  		}
  1280  	}
  1281  	return
  1282  }
  1283  
  1284  func (db *DB) muUnlock() {
  1285  	if n := len(db.queue); n != 0 {
  1286  		db.queue[0] <- struct{}{}
  1287  		copy(db.queue, db.queue[1:])
  1288  		db.queue = db.queue[:n-1]
  1289  	}
  1290  	db.mu.Unlock()
  1291  }
  1292  
  1293  func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tnlb int, err error) {
  1294  	db.mu.Lock()
  1295  	tnla = db.tnl
  1296  	tnlb = db.tnl
  1297  	switch db.rw {
  1298  	case false:
  1299  		switch s.(type) {
  1300  		case beginTransactionStmt:
  1301  			defer db.muUnlock()
  1302  			if pc == nil {
  1303  				return nil, tnla, tnlb, errors.New("BEGIN TRANSACTION: cannot start a transaction in nil TransactionCtx")
  1304  			}
  1305  
  1306  			if err = db.store.BeginTransaction(); err != nil {
  1307  				return
  1308  			}
  1309  
  1310  			db.rwmu.Lock()
  1311  			db.beginTransaction()
  1312  			db.cc = pc
  1313  			db.tnl++
  1314  			tnlb = db.tnl
  1315  			db.rw = true
  1316  			return
  1317  		case commitStmt:
  1318  			defer db.muUnlock()
  1319  			return nil, tnla, tnlb, errCommitNotInTransaction
  1320  		case rollbackStmt:
  1321  			defer db.muUnlock()
  1322  			return nil, tnla, tnlb, errRollbackNotInTransaction
  1323  		default:
  1324  			if s.isUpdating() {
  1325  				db.muUnlock()
  1326  				return nil, tnla, tnlb, fmt.Errorf("attempt to update the DB outside of a transaction")
  1327  			}
  1328  
  1329  			db.rwmu.RLock() // can safely grab before Unlock
  1330  			db.muUnlock()
  1331  			defer db.rwmu.RUnlock()
  1332  			rs, err = s.exec(newExecCtx(db, arg)) // R/O tctx
  1333  			return rs, tnla, tnlb, err
  1334  		}
  1335  	default: // case true:
  1336  		switch s.(type) {
  1337  		case beginTransactionStmt:
  1338  			defer db.muUnlock()
  1339  
  1340  			if pc == nil {
  1341  				return nil, tnla, tnlb, errBeginTransNoCtx
  1342  			}
  1343  
  1344  			if pc != db.cc {
  1345  				for db.rw {
  1346  					ch := make(chan struct{}, 1)
  1347  					db.queue = append(db.queue, ch)
  1348  					db.mu.Unlock()
  1349  					<-ch
  1350  					db.mu.Lock()
  1351  				}
  1352  
  1353  				db.rw = true
  1354  				db.rwmu.Lock()
  1355  
  1356  			}
  1357  
  1358  			if err = db.store.BeginTransaction(); err != nil {
  1359  				return
  1360  			}
  1361  
  1362  			db.beginTransaction()
  1363  			db.cc = pc
  1364  			db.tnl++
  1365  			tnlb = db.tnl
  1366  			return
  1367  		case commitStmt:
  1368  			defer db.muUnlock()
  1369  			if pc != db.cc {
  1370  				return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context")
  1371  			}
  1372  
  1373  			db.commit()
  1374  			err = db.store.Commit()
  1375  			db.tnl--
  1376  			tnlb = db.tnl
  1377  			if db.tnl != 0 {
  1378  				return
  1379  			}
  1380  
  1381  			db.cc = nil
  1382  			db.rw = false
  1383  			db.rwmu.Unlock()
  1384  			return
  1385  		case rollbackStmt:
  1386  			defer db.muUnlock()
  1387  			defer func() { pc.LastInsertID = db.root.lastInsertID }()
  1388  			if pc != db.cc {
  1389  				return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context")
  1390  			}
  1391  
  1392  			db.rollback()
  1393  			err = db.store.Rollback()
  1394  			db.tnl--
  1395  			tnlb = db.tnl
  1396  			if db.tnl != 0 {
  1397  				return
  1398  			}
  1399  
  1400  			db.cc = nil
  1401  			db.rw = false
  1402  			db.rwmu.Unlock()
  1403  			return
  1404  		default:
  1405  			if pc == nil {
  1406  				if s.isUpdating() {
  1407  					db.muUnlock()
  1408  					return nil, tnla, tnlb, fmt.Errorf("attempt to update the DB outside of a transaction")
  1409  				}
  1410  
  1411  				db.muUnlock() // must Unlock before RLock
  1412  				db.rwmu.RLock()
  1413  				defer db.rwmu.RUnlock()
  1414  				rs, err = s.exec(newExecCtx(db, arg))
  1415  				return rs, tnla, tnlb, err
  1416  			}
  1417  
  1418  			defer db.muUnlock()
  1419  			defer func() { pc.LastInsertID = db.root.lastInsertID }()
  1420  			if pc != db.cc {
  1421  				return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context")
  1422  			}
  1423  
  1424  			rs, err = s.exec(newExecCtx(db, arg))
  1425  			return rs, tnla, tnlb, err
  1426  		}
  1427  	}
  1428  }
  1429  
  1430  // Flush ends the transaction collecting window, if applicable. IOW, if the DB
  1431  // is dirty, it schedules a 2PC (WAL + DB file) commit on the next outer most
  1432  // DB.Commit or performs it synchronously if there's currently no open
  1433  // transaction.
  1434  //
  1435  // The collecting window is an implementation detail and future versions of
  1436  // Flush may become a no operation while keeping the operation semantics.
  1437  func (db *DB) Flush() (err error) {
  1438  	return nil
  1439  }
  1440  
  1441  // Close will close the DB. Successful Close is idempotent.
  1442  func (db *DB) Close() error {
  1443  	db.mu.Lock()
  1444  	defer db.muUnlock()
  1445  	if db.store == nil {
  1446  		return nil
  1447  	}
  1448  
  1449  	if db.tnl != 0 {
  1450  		return fmt.Errorf("cannot close DB while open transaction exist")
  1451  	}
  1452  
  1453  	err := db.store.Close()
  1454  	db.root, db.store = nil, nil
  1455  	return err
  1456  }
  1457  
  1458  func (db *DB) do(r recordset, f func(data []interface{}) (bool, error)) (err error) {
  1459  	db.mu.Lock()
  1460  	switch db.rw {
  1461  	case false:
  1462  		db.rwmu.RLock() // can safely grab before Unlock
  1463  		db.muUnlock()
  1464  		defer db.rwmu.RUnlock()
  1465  	default: // case true:
  1466  		if r.tx == nil {
  1467  			db.muUnlock() // must Unlock before RLock
  1468  			db.rwmu.RLock()
  1469  			defer db.rwmu.RUnlock()
  1470  			break
  1471  		}
  1472  
  1473  		defer db.muUnlock()
  1474  		if r.tx != db.cc {
  1475  			return fmt.Errorf("invalid passed transaction context")
  1476  		}
  1477  	}
  1478  
  1479  	return r.do(r.ctx, func(id interface{}, data []interface{}) (bool, error) {
  1480  		if err = expand(data); err != nil {
  1481  			return false, err
  1482  		}
  1483  
  1484  		return f(data)
  1485  	})
  1486  }
  1487  
  1488  func (db *DB) beginTransaction() { //TODO Rewrite, must use much smaller undo info!
  1489  	root := *db.root
  1490  	root.parent = db.root
  1491  	root.tables = make(map[string]*table, len(db.root.tables))
  1492  	var tprev *table
  1493  	for t := db.root.thead; t != nil; t = t.tnext {
  1494  		t2 := t.clone()
  1495  		root.tables[t2.name] = t2
  1496  		t2.tprev = tprev
  1497  		switch {
  1498  		case tprev == nil:
  1499  			root.thead = t2
  1500  		default:
  1501  			tprev.tnext = t2
  1502  		}
  1503  		tprev = t2
  1504  	}
  1505  	db.root = &root
  1506  }
  1507  
  1508  func (db *DB) rollback() {
  1509  	db.root = db.root.parent
  1510  }
  1511  
  1512  func (db *DB) commit() {
  1513  	db.root.parent = db.root.parent.parent
  1514  }
  1515  
  1516  // Type represents a QL type (bigint, int, string, ...)
  1517  type Type int
  1518  
  1519  // Values of ColumnInfo.Type.
  1520  const (
  1521  	BigInt     Type = qBigInt
  1522  	BigRat          = qBigRat
  1523  	Blob            = qBlob
  1524  	Bool            = qBool
  1525  	Complex128      = qComplex128
  1526  	Complex64       = qComplex64
  1527  	Duration        = qDuration
  1528  	Float32         = qFloat32
  1529  	Float64         = qFloat64
  1530  	Int16           = qInt16
  1531  	Int32           = qInt32
  1532  	Int64           = qInt64
  1533  	Int8            = qInt8
  1534  	String          = qString
  1535  	Time            = qTime
  1536  	Uint16          = qUint16
  1537  	Uint32          = qUint32
  1538  	Uint64          = qUint64
  1539  	Uint8           = qUint8
  1540  )
  1541  
  1542  // String implements fmt.Stringer.
  1543  func (t Type) String() string {
  1544  	return typeStr(int(t))
  1545  }
  1546  
  1547  // ColumnInfo provides meta data describing a table column.
  1548  type ColumnInfo struct {
  1549  	Name       string // Column name.
  1550  	Type       Type   // Column type (BigInt, BigRat, ...).
  1551  	NotNull    bool   // Column cannot be NULL.
  1552  	Constraint string // Constraint expression, if any.
  1553  	Default    string // Default expression, if any.
  1554  }
  1555  
  1556  // TableInfo provides meta data describing a DB table.
  1557  type TableInfo struct {
  1558  	// Table name.
  1559  	Name string
  1560  
  1561  	// Table schema. Columns are listed in the order in which they appear
  1562  	// in the schema.
  1563  	Columns []ColumnInfo
  1564  }
  1565  
  1566  // IndexInfo provides meta data describing a DB index.  It corresponds to the
  1567  // statement
  1568  //
  1569  //	CREATE INDEX Name ON Table (Column);
  1570  type IndexInfo struct {
  1571  	Name           string   // Index name
  1572  	Table          string   // Table name.
  1573  	Column         string   // Column name.
  1574  	Unique         bool     // Whether the index is unique.
  1575  	ExpressionList []string // Index expression list.
  1576  }
  1577  
  1578  // DbInfo provides meta data describing a DB.
  1579  type DbInfo struct {
  1580  	Name    string      // DB name.
  1581  	Tables  []TableInfo // Tables in the DB.
  1582  	Indices []IndexInfo // Indices in the DB.
  1583  }
  1584  
  1585  func (db *DB) info() (r *DbInfo, err error) {
  1586  	_, hasColumn2 := db.root.tables["__Column2"]
  1587  	r = &DbInfo{Name: db.Name()}
  1588  	for nm, t := range db.root.tables {
  1589  		ti := TableInfo{Name: nm}
  1590  		m := map[string]*ColumnInfo{}
  1591  		if hasColumn2 {
  1592  			rs, err := selectColumn2.l[0].exec(newExecCtx(db, []interface{}{nm}))
  1593  			if err != nil {
  1594  				return nil, err
  1595  			}
  1596  
  1597  			if err := rs.(recordset).do(
  1598  				newExecCtx(db, []interface{}{nm}),
  1599  				func(id interface{}, data []interface{}) (bool, error) {
  1600  					ci := &ColumnInfo{NotNull: data[1].(bool), Constraint: data[2].(string), Default: data[3].(string)}
  1601  					m[data[0].(string)] = ci
  1602  					return true, nil
  1603  				},
  1604  			); err != nil {
  1605  				return nil, err
  1606  			}
  1607  		}
  1608  		for _, c := range t.cols {
  1609  			ci := ColumnInfo{Name: c.name, Type: Type(c.typ)}
  1610  			if c2 := m[c.name]; c2 != nil {
  1611  				ci.NotNull = c2.NotNull
  1612  				ci.Constraint = c2.Constraint
  1613  				ci.Default = c2.Default
  1614  			}
  1615  			ti.Columns = append(ti.Columns, ci)
  1616  		}
  1617  		r.Tables = append(r.Tables, ti)
  1618  		for i, x := range t.indices {
  1619  			if x == nil {
  1620  				continue
  1621  			}
  1622  
  1623  			var cn string
  1624  			switch {
  1625  			case i == 0:
  1626  				cn = "id()"
  1627  			default:
  1628  				cn = t.cols0[i-1].name
  1629  			}
  1630  			r.Indices = append(r.Indices, IndexInfo{x.name, nm, cn, x.unique, []string{cn}})
  1631  		}
  1632  		var a []string
  1633  		for k := range t.indices2 {
  1634  			a = append(a, k)
  1635  		}
  1636  		for _, k := range a {
  1637  			x := t.indices2[k]
  1638  			if x == nil {
  1639  				continue
  1640  			}
  1641  
  1642  			a = a[:0]
  1643  			for _, e := range x.exprList {
  1644  				a = append(a, e.String())
  1645  			}
  1646  			r.Indices = append(r.Indices, IndexInfo{k, nm, "", x.unique, a})
  1647  		}
  1648  	}
  1649  	return
  1650  }
  1651  
  1652  // Info provides meta data describing a DB or an error if any. It locks the DB
  1653  // to obtain the result.
  1654  func (db *DB) Info() (r *DbInfo, err error) {
  1655  	db.mu.Lock()
  1656  	defer db.muUnlock()
  1657  	return db.info()
  1658  }
  1659  
  1660  type constraint struct {
  1661  	expr expression // If expr == nil: constraint is 'NOT NULL'
  1662  }
  1663  
  1664  func (c *constraint) clone() *constraint {
  1665  	if c == nil {
  1666  		return nil
  1667  	}
  1668  
  1669  	var e expression
  1670  	if c.expr != nil {
  1671  		e, _ = c.expr.clone(nil)
  1672  	}
  1673  	return &constraint{e}
  1674  }
  1675  
  1676  type joinRset struct {
  1677  	sources []interface{}
  1678  	typ     int
  1679  	on      expression
  1680  }
  1681  
  1682  func (r *joinRset) isZero() bool {
  1683  	return len(r.sources) == 0 && r.typ == 0 && r.on == nil
  1684  
  1685  }
  1686  
  1687  func (r *joinRset) String() string {
  1688  	if r.isZero() {
  1689  		return ""
  1690  	}
  1691  	a := make([]string, len(r.sources))
  1692  	for i, pair0 := range r.sources {
  1693  		pair := pair0.([]interface{})
  1694  		altName := pair[1].(string)
  1695  		switch x := pair[0].(type) {
  1696  		case string: // table name
  1697  			switch {
  1698  			case altName == "":
  1699  				a[i] = x
  1700  			default:
  1701  				a[i] = fmt.Sprintf("%s AS %s", x, altName)
  1702  			}
  1703  		case *selectStmt:
  1704  			switch {
  1705  			case altName == "":
  1706  				a[i] = fmt.Sprintf("(%s)", x)
  1707  			default:
  1708  				a[i] = fmt.Sprintf("(%s) AS %s", x, altName)
  1709  			}
  1710  		default:
  1711  			panic("internal error 054")
  1712  		}
  1713  	}
  1714  	n := len(a)
  1715  	a2 := a[:n-1]
  1716  	j := a[n-1]
  1717  	var s string
  1718  	switch r.typ {
  1719  	case crossJoin:
  1720  		return strings.Join(a, ", ")
  1721  	case leftJoin:
  1722  		s = strings.Join(a2, ",") + " LEFT"
  1723  	case rightJoin:
  1724  		s = strings.Join(a2, ",") + " RIGHT"
  1725  	case fullJoin:
  1726  		s = strings.Join(a2, ",") + " FULL"
  1727  	}
  1728  	s += " OUTER JOIN " + j + " ON " + r.on.String()
  1729  	return s
  1730  }
  1731  
  1732  func (r *joinRset) plan(ctx *execCtx) (plan, error) {
  1733  	if r.isZero() {
  1734  		return nil, nil
  1735  	}
  1736  	rsets := make([]plan, len(r.sources))
  1737  	names := make([]string, len(r.sources))
  1738  	var err error
  1739  	m := map[string]bool{}
  1740  	var fields []string
  1741  	for i, v := range r.sources {
  1742  		pair := v.([]interface{})
  1743  		src := pair[0]
  1744  		nm := pair[1].(string)
  1745  		if s, ok := src.(string); ok {
  1746  			src = tableRset(s)
  1747  			if nm == "" {
  1748  				nm = s
  1749  			}
  1750  		}
  1751  		if m[nm] {
  1752  			return nil, fmt.Errorf("%s: duplicate name %s", r.String(), nm)
  1753  		}
  1754  
  1755  		if nm != "" {
  1756  			m[nm] = true
  1757  		}
  1758  		names[i] = nm
  1759  		var q plan
  1760  		switch x := src.(type) {
  1761  		case rset:
  1762  			if q, err = x.plan(ctx); err != nil {
  1763  				return nil, err
  1764  			}
  1765  		case plan:
  1766  			q = x
  1767  		default:
  1768  			panic("internal error 008")
  1769  		}
  1770  
  1771  		switch {
  1772  		case len(r.sources) == 1:
  1773  			fields = q.fieldNames()
  1774  		default:
  1775  			for _, f := range q.fieldNames() {
  1776  				if strings.Contains(f, ".") {
  1777  					return nil, fmt.Errorf("cannot join on recordset with already qualified field names (use the AS clause): %s", f)
  1778  				}
  1779  
  1780  				if f != "" && nm != "" {
  1781  					f = fmt.Sprintf("%s.%s", nm, f)
  1782  				}
  1783  				fields = append(fields, f)
  1784  			}
  1785  		}
  1786  		rsets[i] = q
  1787  	}
  1788  
  1789  	switch len(rsets) {
  1790  	case 0:
  1791  		return nil, nil
  1792  	case 1:
  1793  		return rsets[0], nil
  1794  	}
  1795  	right := len(rsets[len(rsets)-1].fieldNames())
  1796  	switch r.typ {
  1797  	case crossJoin:
  1798  		return &crossJoinDefaultPlan{rsets: rsets, names: names, fields: fields}, nil
  1799  	case leftJoin:
  1800  		return &leftJoinDefaultPlan{rsets: rsets, names: names, fields: fields, on: r.on, right: right}, nil
  1801  	case rightJoin:
  1802  		return &rightJoinDefaultPlan{leftJoinDefaultPlan{rsets: rsets, names: names, fields: fields, on: r.on, right: right}}, nil
  1803  	case fullJoin:
  1804  		return &fullJoinDefaultPlan{leftJoinDefaultPlan{rsets: rsets, names: names, fields: fields, on: r.on, right: right}}, nil
  1805  	default:
  1806  		panic("internal error 010")
  1807  	}
  1808  }
  1809  
  1810  type fld struct {
  1811  	expr expression
  1812  	name string
  1813  }