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 }