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  }