github.com/runner-mei/ql@v1.1.0/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  }
   336  
   337  func (r *whereRset) planBinOp(x *binaryOperation) (plan, error) {
   338  	p := r.src
   339  	ok, cn := isColumnExpression(x.l)
   340  	if ok && cn == "id()" {
   341  		if v := isConstValue(x.r); v != nil {
   342  			v, err := typeCheck1(v, idCol)
   343  			if err != nil {
   344  				return nil, err
   345  			}
   346  
   347  			rv := v.(int64)
   348  			switch {
   349  			case p.hasID():
   350  				switch x.op {
   351  				case '<':
   352  					if rv <= 1 {
   353  						return &nullPlan{p.fieldNames()}, nil
   354  					}
   355  				case '>':
   356  					if rv <= 0 {
   357  						return p, nil
   358  					}
   359  				case ge:
   360  					if rv >= 1 {
   361  						return p, nil
   362  					}
   363  				case neq:
   364  					if rv <= 0 {
   365  						return p, nil
   366  					}
   367  				case eq:
   368  					if rv <= 0 {
   369  						return &nullPlan{p.fieldNames()}, nil
   370  					}
   371  				case le:
   372  					if rv <= 0 {
   373  						return &nullPlan{p.fieldNames()}, nil
   374  					}
   375  				}
   376  			}
   377  		}
   378  	}
   379  
   380  	var err error
   381  	var p2 plan
   382  	var is []string
   383  	switch x.op {
   384  	case eq, ge, '>', le, '<', neq:
   385  		if p2, is, err = p.filter(x); err != nil {
   386  			return nil, err
   387  		}
   388  
   389  		if p2 != nil {
   390  			return p2, nil
   391  		}
   392  	case andand:
   393  		var in []expression
   394  		var f func(expression)
   395  		f = func(e expression) {
   396  			b, ok := e.(*binaryOperation)
   397  			if !ok || b.op != andand {
   398  				in = append(in, e)
   399  				return
   400  			}
   401  
   402  			f(b.l)
   403  			f(b.r)
   404  		}
   405  		f(x)
   406  		out := []expression{}
   407  		p := r.src
   408  		isNewPlan := false
   409  		for _, e := range in {
   410  			p2, is2, err := p.filter(e)
   411  			if err != nil {
   412  				return nil, err
   413  			}
   414  
   415  			if p2 == nil {
   416  				is = append(is, is2...)
   417  				out = append(out, e)
   418  				continue
   419  			}
   420  
   421  			p = p2
   422  			isNewPlan = true
   423  		}
   424  
   425  		if !isNewPlan {
   426  			break
   427  		}
   428  
   429  		if len(out) == 0 {
   430  			return p, nil
   431  		}
   432  
   433  		for len(out) > 1 {
   434  			n := len(out)
   435  			e, err := newBinaryOperation(andand, out[n-2], out[n-1])
   436  			if err != nil {
   437  				return nil, err
   438  			}
   439  
   440  			out = out[:n-1]
   441  			out[n-2] = e
   442  		}
   443  
   444  		return &filterDefaultPlan{p, out[0], is}, nil
   445  	}
   446  
   447  	return &filterDefaultPlan{p, x, is}, nil
   448  }
   449  
   450  func (r *whereRset) planIdent(x *ident) (plan, error) {
   451  	p := r.src
   452  	p2, is, err := p.filter(x)
   453  	if err != nil {
   454  		return nil, err
   455  	}
   456  
   457  	if p2 != nil {
   458  		return p2, nil
   459  	}
   460  
   461  	return &filterDefaultPlan{p, x, is}, nil
   462  }
   463  
   464  func (r *whereRset) planIsNull(x *isNull) (plan, error) {
   465  	p := r.src
   466  	ok, cn := isColumnExpression(x.expr)
   467  	if !ok {
   468  		return &filterDefaultPlan{p, x, nil}, nil
   469  	}
   470  
   471  	if cn == "id()" {
   472  		switch {
   473  		case p.hasID():
   474  			switch {
   475  			case x.not: // IS NOT NULL
   476  				return p, nil
   477  			default: // IS NULL
   478  				return &nullPlan{p.fieldNames()}, nil
   479  			}
   480  		default:
   481  			switch {
   482  			case x.not: // IS NOT NULL
   483  				return &nullPlan{p.fieldNames()}, nil
   484  			default: // IS NULL
   485  				return p, nil
   486  			}
   487  		}
   488  	}
   489  
   490  	p2, is, err := p.filter(x)
   491  	if err != nil {
   492  		return nil, err
   493  	}
   494  
   495  	if p2 != nil {
   496  		return p2, nil
   497  	}
   498  
   499  	return &filterDefaultPlan{p, x, is}, nil
   500  }
   501  
   502  func (r *whereRset) planUnaryOp(x *unaryOperation) (plan, error) {
   503  	p := r.src
   504  	p2, is, err := p.filter(x)
   505  	if err != nil {
   506  		return nil, err
   507  	}
   508  
   509  	if p2 != nil {
   510  		return p2, nil
   511  	}
   512  
   513  	return &filterDefaultPlan{p, x, is}, nil
   514  }
   515  
   516  func (r *whereRset) plan(ctx *execCtx) (plan, error) {
   517  	expr, err := r.expr.clone(ctx.arg)
   518  	if err != nil {
   519  		return nil, err
   520  	}
   521  
   522  	switch r.src.(type) {
   523  	case *leftJoinDefaultPlan, *rightJoinDefaultPlan, *fullJoinDefaultPlan:
   524  		return &filterDefaultPlan{r.src, expr, nil}, nil
   525  	}
   526  
   527  	switch x := expr.(type) {
   528  	case *binaryOperation:
   529  		return r.planBinOp(x)
   530  	case *ident:
   531  		return r.planIdent(x)
   532  	case *isNull:
   533  		return r.planIsNull(x)
   534  	case *pIn:
   535  		//TODO optimize
   536  		//TODO show plan
   537  	case *pLike:
   538  		//TODO optimize
   539  	case *unaryOperation:
   540  		return r.planUnaryOp(x)
   541  	}
   542  
   543  	return &filterDefaultPlan{r.src, expr, nil}, nil
   544  }
   545  
   546  type offsetRset struct {
   547  	expr expression
   548  	src  plan
   549  }
   550  
   551  func (r *offsetRset) plan(ctx *execCtx) (plan, error) {
   552  	return &offsetDefaultPlan{expr: r.expr, src: r.src, fields: r.src.fieldNames()}, nil
   553  }
   554  
   555  type limitRset struct {
   556  	expr expression
   557  	src  plan
   558  }
   559  
   560  func (r *limitRset) plan(ctx *execCtx) (plan, error) {
   561  	return &limitDefaultPlan{expr: r.expr, src: r.src, fields: r.src.fieldNames()}, nil
   562  }
   563  
   564  type selectRset struct {
   565  	flds []*fld
   566  	src  plan
   567  }
   568  
   569  func (r *selectRset) plan(ctx *execCtx) (plan, error) {
   570  	var flds2 []*fld
   571  	if len(r.flds) != 0 {
   572  		m := map[string]struct{}{}
   573  		for _, v := range r.flds {
   574  			mentionedColumns0(v.expr, true, true, m)
   575  		}
   576  		for _, v := range r.src.fieldNames() {
   577  			delete(m, v)
   578  		}
   579  		for k := range m {
   580  			return nil, fmt.Errorf("unknown field %s", k)
   581  		}
   582  
   583  		flds2 = append(flds2, r.flds...)
   584  	}
   585  
   586  	if x, ok := r.src.(*groupByDefaultPlan); ok {
   587  		if len(r.flds) == 0 {
   588  			fields := x.fieldNames()
   589  			flds := make([]*fld, len(fields))
   590  			for i, v := range fields {
   591  				flds[i] = &fld{&ident{v}, v}
   592  			}
   593  			return &selectFieldsGroupPlan{flds: flds, src: x, fields: fields}, nil
   594  		}
   595  
   596  		p := &selectFieldsGroupPlan{flds: flds2, src: x}
   597  		for _, v := range r.flds {
   598  			p.fields = append(p.fields, v.name)
   599  		}
   600  		return p, nil
   601  	}
   602  
   603  	if len(r.flds) == 0 {
   604  		return r.src, nil
   605  	}
   606  
   607  	f0 := r.src.fieldNames()
   608  	if len(f0) == len(flds2) {
   609  		match := true
   610  		for i, v := range flds2 {
   611  			if x, ok := v.expr.(*ident); ok && x.s == f0[i] && v.name == f0[i] {
   612  				continue
   613  			}
   614  
   615  			match = false
   616  			break
   617  		}
   618  
   619  		if match {
   620  			return r.src, nil
   621  		}
   622  	}
   623  
   624  	src := r.src
   625  	if x, ok := src.(*tableDefaultPlan); ok {
   626  		isconst := true
   627  		for _, v := range flds2 {
   628  			if isConstValue(v.expr) == nil {
   629  				isconst = false
   630  				break
   631  			}
   632  		}
   633  		if isconst { // #250
   634  			src = &tableNilPlan{x.t}
   635  		}
   636  	}
   637  
   638  	p := &selectFieldsDefaultPlan{flds: flds2, src: src}
   639  	for _, v := range r.flds {
   640  		p.fields = append(p.fields, v.name)
   641  	}
   642  	return p, nil
   643  }
   644  
   645  type tableRset string
   646  
   647  func (r tableRset) plan(ctx *execCtx) (plan, error) {
   648  	switch r {
   649  	case "__Table":
   650  		return &sysTableDefaultPlan{}, nil
   651  	case "__Column":
   652  		return &sysColumnDefaultPlan{}, nil
   653  	case "__Index":
   654  		return &sysIndexDefaultPlan{}, nil
   655  	}
   656  
   657  	t, ok := ctx.db.root.tables[string(r)]
   658  	if !ok && isTesting {
   659  		if _, x0 := ctx.db.root.findIndexByName(string(r)); x0 != nil {
   660  			return &selectIndexDefaultPlan{nm: string(r), x: x0}, nil
   661  		}
   662  	}
   663  
   664  	if !ok {
   665  		return nil, fmt.Errorf("table %s does not exist", r)
   666  	}
   667  
   668  	rs := &tableDefaultPlan{t: t}
   669  	for _, col := range t.cols {
   670  		rs.fields = append(rs.fields, col.name)
   671  	}
   672  	return rs, nil
   673  }
   674  
   675  func findFld(fields []*fld, name string) (f *fld) {
   676  	for _, f = range fields {
   677  		if f.name == name {
   678  			return
   679  		}
   680  	}
   681  
   682  	return nil
   683  }
   684  
   685  type col struct {
   686  	index      int
   687  	name       string
   688  	typ        int
   689  	constraint *constraint
   690  	dflt       expression
   691  }
   692  
   693  var idCol = &col{name: "id()", typ: qInt64}
   694  
   695  func findCol(cols []*col, name string) (c *col) {
   696  	for _, c = range cols {
   697  		if c.name == name {
   698  			return
   699  		}
   700  	}
   701  
   702  	return nil
   703  }
   704  
   705  func (f *col) clone() *col {
   706  	var r col
   707  	r = *f
   708  	r.constraint = f.constraint.clone()
   709  	if f.dflt != nil {
   710  		r.dflt, _ = r.dflt.clone(nil)
   711  	}
   712  	return &r
   713  }
   714  
   715  func (f *col) typeCheck(x interface{}) (ok bool) { //NTYPE
   716  	switch x.(type) {
   717  	case nil:
   718  		return true
   719  	case bool:
   720  		return f.typ == qBool
   721  	case complex64:
   722  		return f.typ == qComplex64
   723  	case complex128:
   724  		return f.typ == qComplex128
   725  	case float32:
   726  		return f.typ == qFloat32
   727  	case float64:
   728  		return f.typ == qFloat64
   729  	case int8:
   730  		return f.typ == qInt8
   731  	case int16:
   732  		return f.typ == qInt16
   733  	case int32:
   734  		return f.typ == qInt32
   735  	case int64:
   736  		return f.typ == qInt64
   737  	case string:
   738  		return f.typ == qString
   739  	case uint8:
   740  		return f.typ == qUint8
   741  	case uint16:
   742  		return f.typ == qUint16
   743  	case uint32:
   744  		return f.typ == qUint32
   745  	case uint64:
   746  		return f.typ == qUint64
   747  	case []byte:
   748  		return f.typ == qBlob
   749  	case *big.Int:
   750  		return f.typ == qBigInt
   751  	case *big.Rat:
   752  		return f.typ == qBigRat
   753  	case time.Time:
   754  		return f.typ == qTime
   755  	case time.Duration:
   756  		return f.typ == qDuration
   757  	case chunk:
   758  		return true // was checked earlier
   759  	}
   760  	return
   761  }
   762  
   763  func cols2meta(f []*col) (s string) {
   764  	a := []string{}
   765  	for _, f := range f {
   766  		a = append(a, string(f.typ)+f.name)
   767  	}
   768  	return strings.Join(a, "|")
   769  }
   770  
   771  // DB represent the database capable of executing QL statements.
   772  type DB struct {
   773  	cc          *TCtx // Current transaction context
   774  	isMem       bool
   775  	mu          sync.Mutex
   776  	root        *root
   777  	rw          bool // DB FSM
   778  	rwmu        sync.RWMutex
   779  	store       storage
   780  	tnl         int // Transaction nesting level
   781  	exprCache   map[string]expression
   782  	exprCacheMu sync.Mutex
   783  	hasIndex2   int // 0: nope, 1: in progress, 2: yes.
   784  }
   785  
   786  var selIndex2Expr = MustCompile("select Expr from __Index2_Expr where Index2_ID == $1")
   787  
   788  func newDB(store storage) (db *DB, err error) {
   789  	db0 := &DB{
   790  		exprCache: map[string]expression{},
   791  		store:     store,
   792  	}
   793  	if db0.root, err = newRoot(store); err != nil {
   794  		return
   795  	}
   796  
   797  	ctx := &execCtx{db: db0}
   798  	for _, t := range db0.root.tables {
   799  		if err := t.constraintsAndDefaults(ctx); err != nil {
   800  			return nil, err
   801  		}
   802  	}
   803  
   804  	if !db0.hasAllIndex2() {
   805  		return db0, nil
   806  	}
   807  
   808  	db0.hasIndex2 = 2
   809  	rss, _, err := db0.Run(nil, "select id(), TableName, IndexName, IsUnique, Root from __Index2 where !IsSimple")
   810  	if err != nil {
   811  		return nil, err
   812  	}
   813  
   814  	rows, err := rss[0].Rows(-1, 0)
   815  	if err != nil {
   816  		return nil, err
   817  	}
   818  
   819  	for _, row := range rows {
   820  		defer func() {
   821  			if e := recover(); e != nil {
   822  				err = fmt.Errorf("error loading DB indices: %v", e)
   823  			}
   824  		}()
   825  
   826  		id := row[0].(int64)
   827  		tn := row[1].(string)
   828  		xn := row[2].(string)
   829  		unique := row[3].(bool)
   830  		xroot := row[4].(int64)
   831  
   832  		t := db0.root.tables[tn]
   833  		if t == nil {
   834  			return nil, fmt.Errorf("DB index refers to nonexistent table: %s", tn)
   835  		}
   836  
   837  		x, err := store.OpenIndex(unique, xroot)
   838  		if err != nil {
   839  			return nil, err
   840  		}
   841  
   842  		if v := t.indices2[xn]; v != nil {
   843  			return nil, fmt.Errorf("duplicate DB index: %s", xn)
   844  		}
   845  
   846  		ix := &index2{
   847  			unique: unique,
   848  			x:      x,
   849  			xroot:  xroot,
   850  		}
   851  
   852  		rss, _, err := db0.Execute(nil, selIndex2Expr, id)
   853  		if err != nil {
   854  			return nil, err
   855  		}
   856  
   857  		rows, err := rss[0].Rows(-1, 0)
   858  		if err != nil {
   859  			return nil, err
   860  		}
   861  
   862  		if len(rows) == 0 {
   863  			return nil, fmt.Errorf("index has no expression: %s", xn)
   864  		}
   865  
   866  		var sources []string
   867  		var list []expression
   868  		for _, row := range rows {
   869  			src, ok := row[0].(string)
   870  			if !ok {
   871  				return nil, fmt.Errorf("index %s: expression of type %T", xn, row[0])
   872  			}
   873  
   874  			expr, err := db0.str2expr(src)
   875  			if err != nil {
   876  				return nil, fmt.Errorf("index %s: expression error: %v", xn, err)
   877  			}
   878  
   879  			sources = append(sources, src)
   880  			list = append(list, expr)
   881  		}
   882  
   883  		ix.sources = sources
   884  		ix.exprList = list
   885  		if t.indices2 == nil {
   886  			t.indices2 = map[string]*index2{}
   887  		}
   888  		t.indices2[xn] = ix
   889  	}
   890  	return db0, nil
   891  }
   892  
   893  func (db *DB) deleteIndex2ByIndexName(nm string) error {
   894  	for _, s := range deleteIndex2ByIndexName.l {
   895  		if _, err := s.exec(&execCtx{db: db, arg: []interface{}{nm}}); err != nil {
   896  			return err
   897  		}
   898  	}
   899  	return nil
   900  }
   901  
   902  func (db *DB) deleteIndex2ByTableName(nm string) error {
   903  	for _, s := range deleteIndex2ByTableName.l {
   904  		if _, err := s.exec(&execCtx{db: db, arg: []interface{}{nm}}); err != nil {
   905  			return err
   906  		}
   907  	}
   908  	return nil
   909  }
   910  
   911  func (db *DB) createIndex2() error {
   912  	if db.hasIndex2 != 0 {
   913  		return nil
   914  	}
   915  
   916  	db.hasIndex2 = 1
   917  	ctx := execCtx{db: db}
   918  	for _, s := range createIndex2.l {
   919  		if _, err := s.exec(&ctx); err != nil {
   920  			db.hasIndex2 = 0
   921  			return err
   922  		}
   923  	}
   924  
   925  	for t := db.root.thead; t != nil; t = t.tnext {
   926  		for i, index := range t.indices {
   927  			if index == nil {
   928  				continue
   929  			}
   930  
   931  			expr := "id()"
   932  			if i != 0 {
   933  				expr = t.cols[i-1].name
   934  			}
   935  
   936  			if err := db.insertIndex2(t.name, index.name, []string{expr}, index.unique, true, index.xroot); err != nil {
   937  				db.hasIndex2 = 0
   938  				return err
   939  			}
   940  		}
   941  	}
   942  
   943  	db.hasIndex2 = 2
   944  	return nil
   945  }
   946  
   947  func (db *DB) insertIndex2(tableName, indexName string, expr []string, unique, isSimple bool, h int64) error {
   948  	ctx := execCtx{db: db}
   949  	ctx.arg = []interface{}{
   950  		tableName,
   951  		indexName,
   952  		unique,
   953  		isSimple,
   954  		h,
   955  	}
   956  	if _, err := insertIndex2.l[0].exec(&ctx); err != nil {
   957  		return err
   958  	}
   959  
   960  	id := db.root.lastInsertID
   961  	for _, e := range expr {
   962  		ctx.arg = []interface{}{id, e}
   963  		if _, err := insertIndex2Expr.l[0].exec(&ctx); err != nil {
   964  			return err
   965  		}
   966  	}
   967  	return nil
   968  }
   969  
   970  func (db *DB) hasAllIndex2() bool {
   971  	t := db.root.tables
   972  	if _, ok := t["__Index2"]; !ok {
   973  		return false
   974  	}
   975  
   976  	_, ok := t["__Index2_Expr"]
   977  	return ok
   978  }
   979  
   980  func (db *DB) str2expr(expr string) (expression, error) {
   981  	db.exprCacheMu.Lock()
   982  	e := db.exprCache[expr]
   983  	db.exprCacheMu.Unlock()
   984  	if e != nil {
   985  		return e, nil
   986  	}
   987  
   988  	e, err := compileExpr(expr)
   989  	if err != nil {
   990  		return nil, err
   991  	}
   992  
   993  	db.exprCacheMu.Lock()
   994  	for k := range db.exprCache {
   995  		if len(db.exprCache) < 1000 {
   996  			break
   997  		}
   998  
   999  		delete(db.exprCache, k)
  1000  	}
  1001  	db.exprCache[expr] = e
  1002  	db.exprCacheMu.Unlock()
  1003  	return e, nil
  1004  }
  1005  
  1006  // Name returns the name of the DB.
  1007  func (db *DB) Name() string { return db.store.Name() }
  1008  
  1009  // Run compiles and executes a statement list.  It returns, if applicable, a
  1010  // RecordSet slice and/or an index and error.
  1011  //
  1012  // For more details please see DB.Execute
  1013  //
  1014  // Run is safe for concurrent use by multiple goroutines.
  1015  func (db *DB) Run(ctx *TCtx, ql string, arg ...interface{}) (rs []Recordset, index int, err error) {
  1016  	l, err := Compile(ql)
  1017  	if err != nil {
  1018  		return nil, -1, err
  1019  	}
  1020  
  1021  	return db.Execute(ctx, l, arg...)
  1022  }
  1023  
  1024  func (db *DB) run(ctx *TCtx, ql string, arg ...interface{}) (rs []Recordset, index int, err error) {
  1025  	l, err := compile(ql)
  1026  	if err != nil {
  1027  		return nil, -1, err
  1028  	}
  1029  
  1030  	return db.Execute(ctx, l, arg...)
  1031  }
  1032  
  1033  // Compile parses the ql statements from src and returns a compiled list for
  1034  // DB.Execute or an error if any.
  1035  //
  1036  // Compile is safe for concurrent use by multiple goroutines.
  1037  func Compile(src string) (List, error) {
  1038  	l := newLexer(src)
  1039  	if yyParse(l) != 0 {
  1040  		return List{}, l.errs[0]
  1041  	}
  1042  
  1043  	return List{l.list, l.params}, nil
  1044  }
  1045  
  1046  func compileExpr(src string) (expression, error) {
  1047  	l := newLexer(src)
  1048  	l.inj = parseExpression
  1049  	if yyParse(l) != 0 {
  1050  		return nil, l.errs[0]
  1051  	}
  1052  
  1053  	return l.expr, nil
  1054  }
  1055  
  1056  func compile(src string) (List, error) {
  1057  	l := newLexer(src)
  1058  	l.root = true
  1059  	if yyParse(l) != 0 {
  1060  		return List{}, l.errs[0]
  1061  	}
  1062  
  1063  	return List{l.list, l.params}, nil
  1064  }
  1065  
  1066  // MustCompile is like Compile but panics if the ql statements in src cannot be
  1067  // compiled. It simplifies safe initialization of global variables holding
  1068  // compiled statement lists for DB.Execute.
  1069  //
  1070  // MustCompile is safe for concurrent use by multiple goroutines.
  1071  func MustCompile(src string) List {
  1072  	list, err := Compile(src)
  1073  	if err != nil {
  1074  		panic("ql: Compile(" + strconv.Quote(src) + "): " + err.Error()) // panic ok here
  1075  	}
  1076  
  1077  	return list
  1078  }
  1079  
  1080  func mustCompile(src string) List {
  1081  	list, err := compile(src)
  1082  	if err != nil {
  1083  		panic("ql: compile(" + strconv.Quote(src) + "): " + err.Error()) // panic ok here
  1084  	}
  1085  
  1086  	return list
  1087  }
  1088  
  1089  // Execute executes statements in a list while substituting QL parameters from
  1090  // arg.
  1091  //
  1092  // The resulting []Recordset corresponds to the SELECT FROM statements in the
  1093  // list.
  1094  //
  1095  // If err != nil then index is the zero based index of the failed QL statement.
  1096  // Empty statements do not count.
  1097  //
  1098  // The FSM STT describing the relations between DB states, statements and the
  1099  // ctx parameter.
  1100  //
  1101  //  +-----------+---------------------+------------------+------------------+------------------+
  1102  //  |\  Event   |                     |                  |                  |                  |
  1103  //  | \-------\ |     BEGIN           |                  |                  |    Other         |
  1104  //  |   State  \|     TRANSACTION     |      COMMIT      |     ROLLBACK     |    statement     |
  1105  //  +-----------+---------------------+------------------+------------------+------------------+
  1106  //  | RD        | if PC == nil        | return error     | return error     | DB.RLock         |
  1107  //  |           |     return error    |                  |                  | Execute(1)       |
  1108  //  | CC == nil |                     |                  |                  | DB.RUnlock       |
  1109  //  | TNL == 0  | DB.Lock             |                  |                  |                  |
  1110  //  |           | CC = PC             |                  |                  |                  |
  1111  //  |           | TNL++               |                  |                  |                  |
  1112  //  |           | DB.BeginTransaction |                  |                  |                  |
  1113  //  |           | State = WR          |                  |                  |                  |
  1114  //  +-----------+---------------------+------------------+------------------+------------------+
  1115  //  | WR        | if PC == nil        | if PC != CC      | if PC != CC      | if PC == nil     |
  1116  //  |           |     return error    |     return error |     return error |     DB.Rlock     |
  1117  //  | CC != nil |                     |                  |                  |     Execute(1)   |
  1118  //  | TNL != 0  | if PC != CC         | DB.Commit        | DB.Rollback      |     RUnlock      |
  1119  //  |           |     DB.Lock         | TNL--            | TNL--            | else if PC != CC |
  1120  //  |           |     CC = PC         | if TNL == 0      | if TNL == 0      |     return error |
  1121  //  |           |                     |     CC = nil     |     CC = nil     | else             |
  1122  //  |           | TNL++               |     State = RD   |     State = RD   |     Execute(2)   |
  1123  //  |           | DB.BeginTransaction |     DB.Unlock    |     DB.Unlock    |                  |
  1124  //  +-----------+---------------------+------------------+------------------+------------------+
  1125  //  CC: Curent transaction context
  1126  //  PC: Passed transaction context
  1127  //  TNL: Transaction nesting level
  1128  //
  1129  // Lock, Unlock, RLock, RUnlock semantics above are the same as in
  1130  // sync.RWMutex.
  1131  //
  1132  // (1): Statement list is executed outside of a transaction. Attempts to update
  1133  // the DB will fail, the execution context is read-only. Other statements with
  1134  // read only context will execute concurrently. If any statement fails, the
  1135  // execution of the statement list is aborted.
  1136  //
  1137  // Note that the RLock/RUnlock surrounds every single "other" statement when it
  1138  // is executed outside of a transaction. If read consistency is required by a
  1139  // list of more than one statement then an explicit BEGIN TRANSACTION / COMMIT
  1140  // or ROLLBACK wrapper must be provided. Otherwise the state of the DB may
  1141  // change in between executing any two out-of-transaction statements.
  1142  //
  1143  // (2): Statement list is executed inside an isolated transaction. Execution of
  1144  // statements can update the DB, the execution context is read-write. If any
  1145  // statement fails, the execution of the statement list is aborted and the DB
  1146  // is automatically rolled back to the TNL which was active before the start of
  1147  // execution of the statement list.
  1148  //
  1149  // Execute is safe for concurrent use by multiple goroutines, but one must
  1150  // consider the blocking issues as discussed above.
  1151  //
  1152  // ACID
  1153  //
  1154  // Atomicity: Transactions are atomic. Transactions can be nested. Commit or
  1155  // rollbacks work on the current transaction level. Transactions are made
  1156  // persistent only on the top level commit. Reads made from within an open
  1157  // transaction are dirty reads.
  1158  //
  1159  // Consistency: Transactions bring the DB from one structurally consistent
  1160  // state to other structurally consistent state.
  1161  //
  1162  // Isolation: Transactions are isolated. Isolation is implemented by
  1163  // serialization.
  1164  //
  1165  // Durability: Transactions are durable. A two phase commit protocol and a
  1166  // write ahead log is used. Database is recovered after a crash from the write
  1167  // ahead log automatically on open.
  1168  func (db *DB) Execute(ctx *TCtx, l List, arg ...interface{}) (rs []Recordset, index int, err error) {
  1169  	// Sanitize args
  1170  	for i, v := range arg {
  1171  		switch x := v.(type) {
  1172  		case nil, bool, complex64, complex128, float32, float64, string,
  1173  			int8, int16, int32, int64, int,
  1174  			uint8, uint16, uint32, uint64, uint,
  1175  			*big.Int, *big.Rat, []byte, time.Duration, time.Time:
  1176  		case big.Int:
  1177  			arg[i] = &x
  1178  		case big.Rat:
  1179  			arg[i] = &x
  1180  		default:
  1181  			return nil, 0, fmt.Errorf("cannot use arg[%d] (type %T):unsupported type", i, v)
  1182  		}
  1183  	}
  1184  
  1185  	tnl0 := -1
  1186  	if ctx != nil {
  1187  		ctx.LastInsertID, ctx.RowsAffected = 0, 0
  1188  	}
  1189  
  1190  	list := l.l
  1191  	for _, s := range list {
  1192  		r, tnla, tnl, err := db.run1(ctx, s, arg...)
  1193  		if tnl0 < 0 {
  1194  			tnl0 = tnla
  1195  		}
  1196  		if err != nil {
  1197  			for tnl > tnl0 {
  1198  				var e2 error
  1199  				if _, _, tnl, e2 = db.run1(ctx, rollbackStmt{}); e2 != nil {
  1200  					err = e2
  1201  				}
  1202  			}
  1203  			return rs, index, err
  1204  		}
  1205  
  1206  		if r != nil {
  1207  			if x, ok := r.(recordset); ok {
  1208  				x.tx = ctx
  1209  				r = x
  1210  			}
  1211  			rs = append(rs, r)
  1212  		}
  1213  	}
  1214  	return
  1215  }
  1216  
  1217  func (db *DB) run1(pc *TCtx, s stmt, arg ...interface{}) (rs Recordset, tnla, tnlb int, err error) {
  1218  	db.mu.Lock()
  1219  	tnla = db.tnl
  1220  	tnlb = db.tnl
  1221  	switch db.rw {
  1222  	case false:
  1223  		switch s.(type) {
  1224  		case beginTransactionStmt:
  1225  			defer db.mu.Unlock()
  1226  			if pc == nil {
  1227  				return nil, tnla, tnlb, errors.New("BEGIN TRANSACTION: cannot start a transaction in nil TransactionCtx")
  1228  			}
  1229  
  1230  			if err = db.store.BeginTransaction(); err != nil {
  1231  				return
  1232  			}
  1233  
  1234  			db.rwmu.Lock()
  1235  			db.beginTransaction()
  1236  			db.cc = pc
  1237  			db.tnl++
  1238  			tnlb = db.tnl
  1239  			db.rw = true
  1240  			return
  1241  		case commitStmt:
  1242  			defer db.mu.Unlock()
  1243  			return nil, tnla, tnlb, errCommitNotInTransaction
  1244  		case rollbackStmt:
  1245  			defer db.mu.Unlock()
  1246  			return nil, tnla, tnlb, errRollbackNotInTransaction
  1247  		default:
  1248  			if s.isUpdating() {
  1249  				db.mu.Unlock()
  1250  				return nil, tnla, tnlb, fmt.Errorf("attempt to update the DB outside of a transaction")
  1251  			}
  1252  
  1253  			db.rwmu.RLock() // can safely grab before Unlock
  1254  			db.mu.Unlock()
  1255  			defer db.rwmu.RUnlock()
  1256  			rs, err = s.exec(&execCtx{db, arg}) // R/O tctx
  1257  			return rs, tnla, tnlb, err
  1258  		}
  1259  	default: // case true:
  1260  		switch s.(type) {
  1261  		case beginTransactionStmt:
  1262  			defer db.mu.Unlock()
  1263  
  1264  			if pc == nil {
  1265  				return nil, tnla, tnlb, errBeginTransNoCtx
  1266  			}
  1267  
  1268  			if pc != db.cc {
  1269  				for db.rw {
  1270  					db.mu.Unlock() // Transaction isolation
  1271  					db.mu.Lock()
  1272  				}
  1273  
  1274  				db.rw = true
  1275  				db.rwmu.Lock()
  1276  			}
  1277  
  1278  			if err = db.store.BeginTransaction(); err != nil {
  1279  				return
  1280  			}
  1281  
  1282  			db.beginTransaction()
  1283  			db.cc = pc
  1284  			db.tnl++
  1285  			tnlb = db.tnl
  1286  			return
  1287  		case commitStmt:
  1288  			defer db.mu.Unlock()
  1289  			if pc != db.cc {
  1290  				return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context")
  1291  			}
  1292  
  1293  			db.commit()
  1294  			err = db.store.Commit()
  1295  			db.tnl--
  1296  			tnlb = db.tnl
  1297  			if db.tnl != 0 {
  1298  				return
  1299  			}
  1300  
  1301  			db.cc = nil
  1302  			db.rw = false
  1303  			db.rwmu.Unlock()
  1304  			return
  1305  		case rollbackStmt:
  1306  			defer db.mu.Unlock()
  1307  			defer func() { pc.LastInsertID = db.root.lastInsertID }()
  1308  			if pc != db.cc {
  1309  				return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context")
  1310  			}
  1311  
  1312  			db.rollback()
  1313  			err = db.store.Rollback()
  1314  			db.tnl--
  1315  			tnlb = db.tnl
  1316  			if db.tnl != 0 {
  1317  				return
  1318  			}
  1319  
  1320  			db.cc = nil
  1321  			db.rw = false
  1322  			db.rwmu.Unlock()
  1323  			return
  1324  		default:
  1325  			if pc == nil {
  1326  				if s.isUpdating() {
  1327  					db.mu.Unlock()
  1328  					return nil, tnla, tnlb, fmt.Errorf("attempt to update the DB outside of a transaction")
  1329  				}
  1330  
  1331  				db.mu.Unlock() // must Unlock before RLock
  1332  				db.rwmu.RLock()
  1333  				defer db.rwmu.RUnlock()
  1334  				rs, err = s.exec(&execCtx{db, arg})
  1335  				return rs, tnla, tnlb, err
  1336  			}
  1337  
  1338  			defer db.mu.Unlock()
  1339  			defer func() { pc.LastInsertID = db.root.lastInsertID }()
  1340  			if pc != db.cc {
  1341  				return nil, tnla, tnlb, fmt.Errorf("invalid passed transaction context")
  1342  			}
  1343  
  1344  			rs, err = s.exec(&execCtx{db, arg})
  1345  			return rs, tnla, tnlb, err
  1346  		}
  1347  	}
  1348  }
  1349  
  1350  // Flush ends the transaction collecting window, if applicable. IOW, if the DB
  1351  // is dirty, it schedules a 2PC (WAL + DB file) commit on the next outer most
  1352  // DB.Commit or performs it synchronously if there's currently no open
  1353  // transaction.
  1354  //
  1355  // The collecting window is an implementation detail and future versions of
  1356  // Flush may become a no operation while keeping the operation semantics.
  1357  func (db *DB) Flush() (err error) {
  1358  	return nil
  1359  }
  1360  
  1361  // Close will close the DB. Successful Close is idempotent.
  1362  func (db *DB) Close() error {
  1363  	db.mu.Lock()
  1364  	defer db.mu.Unlock()
  1365  	if db.store == nil {
  1366  		return nil
  1367  	}
  1368  
  1369  	if db.tnl != 0 {
  1370  		return fmt.Errorf("cannot close DB while open transaction exist")
  1371  	}
  1372  
  1373  	err := db.store.Close()
  1374  	db.root, db.store = nil, nil
  1375  	return err
  1376  }
  1377  
  1378  func (db *DB) do(r recordset, f func(data []interface{}) (bool, error)) (err error) {
  1379  	db.mu.Lock()
  1380  	switch db.rw {
  1381  	case false:
  1382  		db.rwmu.RLock() // can safely grab before Unlock
  1383  		db.mu.Unlock()
  1384  		defer db.rwmu.RUnlock()
  1385  	default: // case true:
  1386  		if r.tx == nil {
  1387  			db.mu.Unlock() // must Unlock before RLock
  1388  			db.rwmu.RLock()
  1389  			defer db.rwmu.RUnlock()
  1390  			break
  1391  		}
  1392  
  1393  		defer db.mu.Unlock()
  1394  		if r.tx != db.cc {
  1395  			return fmt.Errorf("invalid passed transaction context")
  1396  		}
  1397  	}
  1398  
  1399  	return r.do(r.ctx, func(id interface{}, data []interface{}) (bool, error) {
  1400  		if err = expand(data); err != nil {
  1401  			return false, err
  1402  		}
  1403  
  1404  		return f(data)
  1405  	})
  1406  }
  1407  
  1408  func (db *DB) beginTransaction() { //TODO Rewrite, must use much smaller undo info!
  1409  	root := *db.root
  1410  	root.parent = db.root
  1411  	root.tables = make(map[string]*table, len(db.root.tables))
  1412  	var tprev *table
  1413  	for t := db.root.thead; t != nil; t = t.tnext {
  1414  		t2 := t.clone()
  1415  		root.tables[t2.name] = t2
  1416  		t2.tprev = tprev
  1417  		switch {
  1418  		case tprev == nil:
  1419  			root.thead = t2
  1420  		default:
  1421  			tprev.tnext = t2
  1422  		}
  1423  		tprev = t2
  1424  	}
  1425  	db.root = &root
  1426  }
  1427  
  1428  func (db *DB) rollback() {
  1429  	db.root = db.root.parent
  1430  }
  1431  
  1432  func (db *DB) commit() {
  1433  	db.root.parent = db.root.parent.parent
  1434  }
  1435  
  1436  // Type represents a QL type (bigint, int, string, ...)
  1437  type Type int
  1438  
  1439  // Values of ColumnInfo.Type.
  1440  const (
  1441  	BigInt     Type = qBigInt
  1442  	BigRat          = qBigRat
  1443  	Blob            = qBlob
  1444  	Bool            = qBool
  1445  	Complex128      = qComplex128
  1446  	Complex64       = qComplex64
  1447  	Duration        = qDuration
  1448  	Float32         = qFloat32
  1449  	Float64         = qFloat64
  1450  	Int16           = qInt16
  1451  	Int32           = qInt32
  1452  	Int64           = qInt64
  1453  	Int8            = qInt8
  1454  	String          = qString
  1455  	Time            = qTime
  1456  	Uint16          = qUint16
  1457  	Uint32          = qUint32
  1458  	Uint64          = qUint64
  1459  	Uint8           = qUint8
  1460  )
  1461  
  1462  // String implements fmt.Stringer.
  1463  func (t Type) String() string {
  1464  	return typeStr(int(t))
  1465  }
  1466  
  1467  // ColumnInfo provides meta data describing a table column.
  1468  type ColumnInfo struct {
  1469  	Name       string // Column name.
  1470  	Type       Type   // Column type (BigInt, BigRat, ...).
  1471  	NotNull    bool   // Column cannot be NULL.
  1472  	Constraint string // Constraint expression, if any.
  1473  	Default    string // Default expression, if any.
  1474  }
  1475  
  1476  // TableInfo provides meta data describing a DB table.
  1477  type TableInfo struct {
  1478  	// Table name.
  1479  	Name string
  1480  
  1481  	// Table schema. Columns are listed in the order in which they appear
  1482  	// in the schema.
  1483  	Columns []ColumnInfo
  1484  }
  1485  
  1486  // IndexInfo provides meta data describing a DB index.  It corresponds to the
  1487  // statement
  1488  //
  1489  //	CREATE INDEX Name ON Table (Column);
  1490  type IndexInfo struct {
  1491  	Name           string   // Index name
  1492  	Table          string   // Table name.
  1493  	Column         string   // Column name.
  1494  	Unique         bool     // Whether the index is unique.
  1495  	ExpressionList []string // Index expression list.
  1496  }
  1497  
  1498  // DbInfo provides meta data describing a DB.
  1499  type DbInfo struct {
  1500  	Name    string      // DB name.
  1501  	Tables  []TableInfo // Tables in the DB.
  1502  	Indices []IndexInfo // Indices in the DB.
  1503  }
  1504  
  1505  func (db *DB) info() (r *DbInfo, err error) {
  1506  	_, hasColumn2 := db.root.tables["__Column2"]
  1507  	r = &DbInfo{Name: db.Name()}
  1508  	for nm, t := range db.root.tables {
  1509  		ti := TableInfo{Name: nm}
  1510  		m := map[string]*ColumnInfo{}
  1511  		if hasColumn2 {
  1512  			rs, err := selectColumn2.l[0].exec(&execCtx{db: db, arg: []interface{}{nm}})
  1513  			if err != nil {
  1514  				return nil, err
  1515  			}
  1516  
  1517  			if err := rs.(recordset).do(
  1518  				&execCtx{db: db, arg: []interface{}{nm}},
  1519  				func(id interface{}, data []interface{}) (bool, error) {
  1520  					ci := &ColumnInfo{NotNull: data[1].(bool), Constraint: data[2].(string), Default: data[3].(string)}
  1521  					m[data[0].(string)] = ci
  1522  					return true, nil
  1523  				},
  1524  			); err != nil {
  1525  				return nil, err
  1526  			}
  1527  		}
  1528  		for _, c := range t.cols {
  1529  			ci := ColumnInfo{Name: c.name, Type: Type(c.typ)}
  1530  			if c2 := m[c.name]; c2 != nil {
  1531  				ci.NotNull = c2.NotNull
  1532  				ci.Constraint = c2.Constraint
  1533  				ci.Default = c2.Default
  1534  			}
  1535  			ti.Columns = append(ti.Columns, ci)
  1536  		}
  1537  		r.Tables = append(r.Tables, ti)
  1538  		for i, x := range t.indices {
  1539  			if x == nil {
  1540  				continue
  1541  			}
  1542  
  1543  			var cn string
  1544  			switch {
  1545  			case i == 0:
  1546  				cn = "id()"
  1547  			default:
  1548  				cn = t.cols0[i-1].name
  1549  			}
  1550  			r.Indices = append(r.Indices, IndexInfo{x.name, nm, cn, x.unique, []string{cn}})
  1551  		}
  1552  		var a []string
  1553  		for k := range t.indices2 {
  1554  			a = append(a, k)
  1555  		}
  1556  		for _, k := range a {
  1557  			x := t.indices2[k]
  1558  			a = a[:0]
  1559  			for _, e := range x.exprList {
  1560  				a = append(a, e.String())
  1561  			}
  1562  			r.Indices = append(r.Indices, IndexInfo{k, nm, "", x.unique, a})
  1563  		}
  1564  	}
  1565  	return
  1566  }
  1567  
  1568  // Info provides meta data describing a DB or an error if any. It locks the DB
  1569  // to obtain the result.
  1570  func (db *DB) Info() (r *DbInfo, err error) {
  1571  	db.mu.Lock()
  1572  	defer db.mu.Unlock()
  1573  	return db.info()
  1574  }
  1575  
  1576  type constraint struct {
  1577  	expr expression // If expr == nil: constraint is 'NOT NULL'
  1578  }
  1579  
  1580  func (c *constraint) clone() *constraint {
  1581  	if c == nil {
  1582  		return nil
  1583  	}
  1584  
  1585  	var e expression
  1586  	if c.expr != nil {
  1587  		e, _ = c.expr.clone(nil)
  1588  	}
  1589  	return &constraint{e}
  1590  }
  1591  
  1592  type joinRset struct {
  1593  	sources []interface{}
  1594  	typ     int
  1595  	on      expression
  1596  }
  1597  
  1598  func (r *joinRset) String() string {
  1599  	a := make([]string, len(r.sources))
  1600  	for i, pair0 := range r.sources {
  1601  		pair := pair0.([]interface{})
  1602  		altName := pair[1].(string)
  1603  		switch x := pair[0].(type) {
  1604  		case string: // table name
  1605  			switch {
  1606  			case altName == "":
  1607  				a[i] = x
  1608  			default:
  1609  				a[i] = fmt.Sprintf("%s AS %s", x, altName)
  1610  			}
  1611  		case *selectStmt:
  1612  			switch {
  1613  			case altName == "":
  1614  				a[i] = fmt.Sprintf("(%s)", x)
  1615  			default:
  1616  				a[i] = fmt.Sprintf("(%s) AS %s", x, altName)
  1617  			}
  1618  		default:
  1619  			panic("internal error 054")
  1620  		}
  1621  	}
  1622  	n := len(a)
  1623  	a2 := a[:n-1]
  1624  	j := a[n-1]
  1625  	var s string
  1626  	switch r.typ {
  1627  	case crossJoin:
  1628  		return strings.Join(a, ", ")
  1629  	case leftJoin:
  1630  		s = strings.Join(a2, ",") + " LEFT"
  1631  	case rightJoin:
  1632  		s = strings.Join(a2, ",") + " RIGHT"
  1633  	case fullJoin:
  1634  		s = strings.Join(a2, ",") + " FULL"
  1635  	}
  1636  	s += " OUTER JOIN " + j + " ON " + r.on.String()
  1637  	return s
  1638  }
  1639  
  1640  func (r *joinRset) plan(ctx *execCtx) (plan, error) {
  1641  	rsets := make([]plan, len(r.sources))
  1642  	names := make([]string, len(r.sources))
  1643  	var err error
  1644  	m := map[string]bool{}
  1645  	var fields []string
  1646  	for i, v := range r.sources {
  1647  		pair := v.([]interface{})
  1648  		src := pair[0]
  1649  		nm := pair[1].(string)
  1650  		if s, ok := src.(string); ok {
  1651  			src = tableRset(s)
  1652  			if nm == "" {
  1653  				nm = s
  1654  			}
  1655  		}
  1656  		if m[nm] {
  1657  			return nil, fmt.Errorf("%s: duplicate name %s", r.String(), nm)
  1658  		}
  1659  
  1660  		if nm != "" {
  1661  			m[nm] = true
  1662  		}
  1663  		names[i] = nm
  1664  		var q plan
  1665  		switch x := src.(type) {
  1666  		case rset:
  1667  			if q, err = x.plan(ctx); err != nil {
  1668  				return nil, err
  1669  			}
  1670  		case plan:
  1671  			q = x
  1672  		default:
  1673  			panic("internal error 008")
  1674  		}
  1675  
  1676  		switch {
  1677  		case len(r.sources) == 1:
  1678  			fields = q.fieldNames()
  1679  		default:
  1680  			for _, f := range q.fieldNames() {
  1681  				if strings.Contains(f, ".") {
  1682  					return nil, fmt.Errorf("cannot join on recordset with already qualified field names (use the AS clause): %s", f)
  1683  				}
  1684  
  1685  				if f != "" && nm != "" {
  1686  					f = fmt.Sprintf("%s.%s", nm, f)
  1687  				}
  1688  				if nm == "" {
  1689  					f = ""
  1690  				}
  1691  				fields = append(fields, f)
  1692  			}
  1693  		}
  1694  		rsets[i] = q
  1695  	}
  1696  
  1697  	if len(rsets) == 1 {
  1698  		return rsets[0], nil
  1699  	}
  1700  
  1701  	right := len(rsets[len(rsets)-1].fieldNames())
  1702  	switch r.typ {
  1703  	case crossJoin:
  1704  		return &crossJoinDefaultPlan{rsets: rsets, names: names, fields: fields}, nil
  1705  	case leftJoin:
  1706  		return &leftJoinDefaultPlan{rsets: rsets, names: names, fields: fields, on: r.on, right: right}, nil
  1707  	case rightJoin:
  1708  		return &rightJoinDefaultPlan{leftJoinDefaultPlan{rsets: rsets, names: names, fields: fields, on: r.on, right: right}}, nil
  1709  	case fullJoin:
  1710  		return &fullJoinDefaultPlan{leftJoinDefaultPlan{rsets: rsets, names: names, fields: fields, on: r.on, right: right}}, nil
  1711  	default:
  1712  		panic("internal error 010")
  1713  	}
  1714  }
  1715  
  1716  type fld struct {
  1717  	expr expression
  1718  	name string
  1719  }