Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

partition ranges, covering indexes, smarter iterators #1116

Merged
merged 13 commits into from
Dec 16, 2020
Next Next commit
covering indexes
  • Loading branch information
Brian Hendriks committed Dec 11, 2020
commit be2c221df9a14dcb58d710f74b4375e38cb6d4de
33 changes: 30 additions & 3 deletions go/libraries/doltcore/sqle/index_lookup.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,40 @@ func (il *doltIndexLookup) Union(indexLookups ...sql.IndexLookup) (sql.IndexLook

// RowIter returns a row iterator for this index lookup. The iterator will return the single matching row for the index.
func (il *doltIndexLookup) RowIter(ctx *sql.Context) (sql.RowIter, error) {
return il.RowIterWithProjection(ctx, nil)
}

func (il *doltIndexLookup) RowIterWithProjection(ctx *sql.Context, columns []string) (sql.RowIter, error) {
readRanges := make([]*noms.ReadRange, len(il.ranges))
for i, lookupRange := range il.ranges {
readRanges[i] = lookupRange.ToReadRange()
}
return NewIndexLookupRowIterAdapter(ctx, il.idx, &doltIndexKeyIter{
indexMapIter: noms.NewNomsRangeReader(il.idx.IndexSchema(), il.idx.IndexRowData(), readRanges),
}), nil

idxItr := &doltIndexKeyIter{indexMapIter: noms.NewNomsRangeReader(il.idx.IndexSchema(), il.idx.IndexRowData(), readRanges)}

covers := il.indexCoversCols(columns)
if covers {
return NewCoveringIndexRowIterAdapter(ctx, il.idx, idxItr), nil
} else {
return NewIndexLookupRowIterAdapter(ctx, il.idx, idxItr), nil
}
}

func (il *doltIndexLookup) indexCoversCols(cols []string) bool {
if cols == nil {
return false
}

idxCols := il.idx.IndexSchema().GetAllCols()
covers := true
for _, colName := range cols {
if _, ok := idxCols.GetByName(colName); !ok {
covers = false
break
}
}

return covers
}

type doltIndexKeyIter struct {
Expand Down
55 changes: 55 additions & 0 deletions go/libraries/doltcore/sqle/index_row_iter.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package sqle

import (
"context"
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
"io"
"runtime"

Expand Down Expand Up @@ -150,3 +151,57 @@ func (i *indexLookupRowIterAdapter) processKey(_ context.Context, valInt interfa
i.buffer[val.position] = sqlRow
return nil
}

type coveringIndexRowIterAdapter struct {
idx DoltIndex
keyIter IndexLookupKeyIterator
ctx *sql.Context
pkCols *schema.ColCollection
nonPKCols *schema.ColCollection
nbf *types.NomsBinFormat
}

func NewCoveringIndexRowIterAdapter(ctx *sql.Context, idx DoltIndex, keyIter IndexLookupKeyIterator) *coveringIndexRowIterAdapter {
sch := idx.Schema()
return &coveringIndexRowIterAdapter{
idx: idx,
keyIter: keyIter,
ctx: ctx,
pkCols: sch.GetPKCols(),
nonPKCols: sch.GetNonPKCols(),
nbf: idx.TableData().Format(),
}
}

// Next returns the next row from the iterator.
func (ci *coveringIndexRowIterAdapter) Next() (sql.Row, error) {
taggedVals, err := ci.keyIter.NextKey(ci.ctx)

if err != nil {
return nil, err
}

pk, err := taggedVals.NomsTupleForPKCols(ci.nbf, ci.pkCols).Value(ci.ctx)

if err != nil {
return nil, err
}

nonPK, err := taggedVals.NomsTupleForNonPKCols(ci.nbf, ci.nonPKCols).Value(ci.ctx)

if err != nil {
return nil, err
}

r, err := row.FromNoms(ci.idx.Schema(), pk.(types.Tuple), nonPK.(types.Tuple))

if err != nil {
return nil, err
}

return sqlutil.DoltRowToSqlRow(r, ci.idx.Schema())
}

func (ci *coveringIndexRowIterAdapter) Close() error {
return nil
}
13 changes: 12 additions & 1 deletion go/libraries/doltcore/sqle/indexed_dolt_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,28 @@ func (idt *IndexedDoltTable) PartitionRows(ctx *sql.Context, _ sql.Partition) (s
type WritableIndexedDoltTable struct {
*WritableDoltTable
indexLookup *doltIndexLookup
projectedCols []string
}

var _ sql.IndexedTable = (*WritableIndexedDoltTable)(nil)
var _ sql.UpdatableTable = (*WritableIndexedDoltTable)(nil)
var _ sql.DeletableTable = (*WritableIndexedDoltTable)(nil)
var _ sql.ReplaceableTable = (*WritableIndexedDoltTable)(nil)
var _ sql.ProjectedTable = (*WritableIndexedDoltTable)(nil)

func (t *WritableIndexedDoltTable) Partitions(ctx *sql.Context) (sql.PartitionIter, error) {
return sqlutil.NewSinglePartitionIter(), nil
}

func (t *WritableIndexedDoltTable) PartitionRows(ctx *sql.Context, _ sql.Partition) (sql.RowIter, error) {
return t.indexLookup.RowIter(ctx)
return t.indexLookup.RowIterWithProjection(ctx, t.projectedCols)
}

func (t *WritableIndexedDoltTable) WithProjection(colNames []string) sql.Table {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably return a copy of the table, rather than just modifying in place

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do this in a bunch of places with the system tables. Any particular reason you think I should return a copy?

t.projectedCols = colNames
return t
}

func (t *WritableIndexedDoltTable) Projection() []string {
return t.projectedCols
}
10 changes: 10 additions & 0 deletions go/libraries/doltcore/sqle/sqlutil/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,13 @@ func ToDoltCol(tag uint64, col *sql.Column) (schema.Column, error) {

return schema.NewColumnWithTypeInfo(col.Name, tag, typeInfo, col.PrimaryKey, col.Default.String(), col.AutoIncrement, col.Comment, constraints...)
}

func GetColNamesFromSqlSchema(sqlSch sql.Schema) []string {
colNames := make([]string, len(sqlSch))

for i, col := range sqlSch {
colNames[i] = col.Name
}

return colNames
}
1 change: 1 addition & 0 deletions go/libraries/doltcore/sqle/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ func (t *WritableDoltTable) WithIndexLookup(lookup sql.IndexLookup) sql.Table {
return &WritableIndexedDoltTable{
WritableDoltTable: t,
indexLookup: dil,
projectedCols: sqlutil.GetColNamesFromSqlSchema(t.sqlSch),
}
}

Expand Down