github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/indexed_dolt_table.go (about) 1 // Copyright 2020 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package sqle 16 17 import ( 18 "sync" 19 20 "github.com/dolthub/go-mysql-server/sql" 21 22 "github.com/dolthub/dolt/go/libraries/doltcore/sqle/index" 23 "github.com/dolthub/dolt/go/store/types" 24 ) 25 26 // IndexedDoltTable is a wrapper for a DoltTable. It implements the sql.Table interface like 27 // DoltTable, but its RowIter function returns values that match a sql.Range, instead of all 28 // rows. It's returned by the DoltTable.IndexedAccess function. 29 type IndexedDoltTable struct { 30 *DoltTable 31 idx index.DoltIndex 32 lb index.LookupBuilder 33 isDoltFormat bool 34 mu *sync.Mutex 35 } 36 37 func NewIndexedDoltTable(t *DoltTable, idx index.DoltIndex) *IndexedDoltTable { 38 return &IndexedDoltTable{ 39 DoltTable: t, 40 idx: idx, 41 isDoltFormat: types.IsFormat_DOLT(t.Format()), 42 mu: &sync.Mutex{}, 43 } 44 } 45 46 var _ sql.IndexedTable = (*IndexedDoltTable)(nil) 47 var _ sql.CommentedTable = (*IndexedDoltTable)(nil) 48 49 func (idt *IndexedDoltTable) LookupPartitions(ctx *sql.Context, lookup sql.IndexLookup) (sql.PartitionIter, error) { 50 return index.NewRangePartitionIter(ctx, idt.DoltTable, lookup, idt.isDoltFormat) 51 } 52 53 func (idt *IndexedDoltTable) Partitions(ctx *sql.Context) (sql.PartitionIter, error) { 54 panic("should call LookupPartitions on an IndexedDoltTable") 55 } 56 57 func (idt *IndexedDoltTable) PartitionRows(ctx *sql.Context, part sql.Partition) (sql.RowIter, error) { 58 idt.mu.Lock() 59 defer idt.mu.Unlock() 60 key, canCache, err := idt.DoltTable.DataCacheKey(ctx) 61 if err != nil { 62 return nil, err 63 } 64 65 if idt.lb == nil || !canCache || idt.lb.Key() != key { 66 idt.lb, err = index.NewLookupBuilder(ctx, idt.DoltTable, idt.idx, key, idt.DoltTable.projectedCols, idt.DoltTable.sqlSch, idt.isDoltFormat) 67 if err != nil { 68 return nil, err 69 } 70 } 71 72 return idt.lb.NewRowIter(ctx, part) 73 } 74 75 func (idt *IndexedDoltTable) PartitionRows2(ctx *sql.Context, part sql.Partition) (sql.RowIter, error) { 76 idt.mu.Lock() 77 defer idt.mu.Unlock() 78 key, canCache, err := idt.DoltTable.DataCacheKey(ctx) 79 if err != nil { 80 return nil, err 81 } 82 if idt.lb == nil || !canCache || idt.lb.Key() != key { 83 idt.lb, err = index.NewLookupBuilder(ctx, idt.DoltTable, idt.idx, key, idt.DoltTable.projectedCols, idt.DoltTable.sqlSch, idt.isDoltFormat) 84 if err != nil { 85 return nil, err 86 } 87 } 88 89 return idt.lb.NewRowIter(ctx, part) 90 } 91 92 var _ sql.IndexedTable = (*WritableIndexedDoltTable)(nil) 93 var _ sql.UpdatableTable = (*WritableIndexedDoltTable)(nil) 94 var _ sql.DeletableTable = (*WritableIndexedDoltTable)(nil) 95 var _ sql.ReplaceableTable = (*WritableIndexedDoltTable)(nil) 96 var _ sql.StatisticsTable = (*WritableIndexedDoltTable)(nil) 97 var _ sql.ProjectedTable = (*WritableIndexedDoltTable)(nil) 98 99 func NewWritableIndexedDoltTable(t *WritableDoltTable, idx index.DoltIndex) *WritableIndexedDoltTable { 100 return &WritableIndexedDoltTable{ 101 WritableDoltTable: t, 102 idx: idx, 103 isDoltFormat: types.IsFormat_DOLT(idx.Format()), 104 mu: &sync.Mutex{}, 105 } 106 } 107 108 type WritableIndexedDoltTable struct { 109 *WritableDoltTable 110 idx index.DoltIndex 111 isDoltFormat bool 112 lb index.LookupBuilder 113 mu *sync.Mutex 114 } 115 116 func (t *WritableIndexedDoltTable) LookupPartitions(ctx *sql.Context, lookup sql.IndexLookup) (sql.PartitionIter, error) { 117 return index.NewRangePartitionIter(ctx, t.DoltTable, lookup, t.isDoltFormat) 118 } 119 120 func (t *WritableIndexedDoltTable) Partitions(ctx *sql.Context) (sql.PartitionIter, error) { 121 panic("called partitions on a lookup indexed table") 122 } 123 124 func (t *WritableIndexedDoltTable) PartitionRows(ctx *sql.Context, part sql.Partition) (sql.RowIter, error) { 125 t.mu.Lock() 126 defer t.mu.Unlock() 127 key, canCache, err := t.DataCacheKey(ctx) 128 if err != nil { 129 return nil, err 130 } 131 if t.lb == nil || !canCache || t.lb.Key() != key { 132 t.lb, err = index.NewLookupBuilder(ctx, t.DoltTable, t.idx, key, t.projectedCols, t.sqlSch, t.isDoltFormat) 133 if err != nil { 134 return nil, err 135 } 136 } 137 138 return t.lb.NewRowIter(ctx, part) 139 } 140 141 // WithProjections implements sql.ProjectedTable 142 func (t *WritableIndexedDoltTable) WithProjections(colNames []string) sql.Table { 143 return &WritableIndexedDoltTable{ 144 WritableDoltTable: t.WithProjections(colNames).(*WritableDoltTable), 145 idx: t.idx, 146 } 147 } 148 149 // Projections implements sql.ProjectedTable 150 func (t *WritableIndexedDoltTable) Projections() []string { 151 if t.projectedCols == nil { 152 return nil 153 } 154 155 names := make([]string, len(t.projectedCols)) 156 cols := t.sch.GetAllCols() 157 for i := range t.projectedCols { 158 col := cols.TagToCol[t.projectedCols[i]] 159 names[i] = col.Name 160 } 161 return names 162 }