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