diff --git a/go/libraries/doltcore/merge/fulltext_rebuild.go b/go/libraries/doltcore/merge/fulltext_rebuild.go index a488029f8e..bb3fe65f93 100644 --- a/go/libraries/doltcore/merge/fulltext_rebuild.go +++ b/go/libraries/doltcore/merge/fulltext_rebuild.go @@ -224,5 +224,5 @@ func createRowIterForTable(ctx *sql.Context, t *doltdb.Table, sch schema.Schema) return nil, err } - return index.NewProllyRowIter(sch, rows, iter, nil) + return index.NewProllyRowIterForMap(sch, rows, iter, nil) } diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 2939beddee..ca4d095f41 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -121,19 +121,20 @@ func TestSingleScript(t *testing.T) { var scripts = []queries.ScriptTest{ // TODO next: a change on both sides to a generated column can never be a merge conflict, ignore it { - Name: "merge a virtual column", + Name: "merge a virtual column created on another branch", SetUpScript: []string{ - "create table t1 (id bigint primary key, v1 bigint, v2 bigint, v3 bigint as (v1 + v2), index (v3))", - "insert into t1 (id, v1, v2) values (1, 2, 3), (4, 5, 6)", + "create table t1 (id bigint primary key, v1 bigint, v2 bigint)", + "insert into t1 (id, v1, v2) values (1, 1, 1), (2, 2, 2)", "call dolt_commit('-Am', 'first commit')", - "call dolt_checkout('-b', 'branch1')", - "insert into t1 (id, v1, v2) values (7, 8, 9)", + "call dolt_branch('branch1')", + "insert into t1 (id, v1, v2) values (3, 3, 3)", + "call dolt_commit('-Am', 'main commit')", + "call dolt_checkout('branch1')", + "alter table t1 add column v3 bigint as (v1 + v2)", + "alter table t1 add key idx_v3 (v3)", + "insert into t1 (id, v1, v2) values (4, 4, 4)", "call dolt_commit('-Am', 'branch1 commit')", "call dolt_checkout('main')", - "call dolt_checkout('-b', 'branch2')", - "insert into t1 (id, v1, v2) values (10, 11, 12)", - "call dolt_commit('-Am', 'branch2 commit')", - "call dolt_checkout('main')", }, Assertions: []queries.ScriptTestAssertion{ { @@ -143,14 +144,14 @@ func TestSingleScript(t *testing.T) { { Query: "select * from t1 order by id", Expected: []sql.Row{ - {1, 2, 3, 5}, - {4, 5, 6, 11}, - {7, 8, 9, 17}, + {1, 1, 1, 2}, + {2, 2, 2, 4}, + {3, 3, 3, 6}, }, }, { - Query: "select id from t1 where v3 = 17", - Expected: []sql.Row{{7}}, + Query: "select id from t1 where v3 = 6", + Expected: []sql.Row{{3}}, }, { Query: "call dolt_merge('branch2')", @@ -159,15 +160,15 @@ func TestSingleScript(t *testing.T) { { Query: "select * from t1 order by id", Expected: []sql.Row{ - {1, 2, 3, 5}, - {4, 5, 6, 11}, - {7, 8, 9, 17}, - {10, 11, 12, 23}, + {1, 1, 1, 2}, + {2, 2, 2, 4}, + {3, 3, 3, 6}, + {4, 4, 4, 8}, }, }, { - Query: "select id from t1 where v3 = 23", - Expected: []sql.Row{{10}}, + Query: "select id from t1 where v3 = 8", + Expected: []sql.Row{{4}}, }, }, }, diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries_merge.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries_merge.go index cdcb49a34c..8c05568f0e 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_queries_merge.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries_merge.go @@ -4418,14 +4418,14 @@ var GeneratedColumnMergeTestScripts = []queries.ScriptTest{ Name: "merge a virtual column", SetUpScript: []string{ "create table t1 (id bigint primary key, v1 bigint, v2 bigint, v3 bigint as (v1 + v2), index (v3))", - "insert into t1 (id, v1, v2) values (1, 1, 1), (2, 2, 2)", + "insert into t1 (id, v1, v2) values (1, 2, 3), (4, 5, 6)", "call dolt_commit('-Am', 'first commit')", "call dolt_checkout('-b', 'branch1')", - "insert into t1 (id, v1, v2) values (3, 3, 3)", + "insert into t1 (id, v1, v2) values (7, 8, 9)", "call dolt_commit('-Am', 'branch1 commit')", "call dolt_checkout('main')", "call dolt_checkout('-b', 'branch2')", - "insert into t1 (id, v1, v2) values (4, 4, 4)", + "insert into t1 (id, v1, v2) values (10, 11, 12)", "call dolt_commit('-Am', 'branch2 commit')", "call dolt_checkout('main')", }, @@ -4437,14 +4437,14 @@ var GeneratedColumnMergeTestScripts = []queries.ScriptTest{ { Query: "select * from t1 order by id", Expected: []sql.Row{ - {1, 1, 1, 2}, - {2, 2, 2, 4}, - {3, 3, 3, 6}, + {1, 2, 3, 5}, + {4, 5, 6, 11}, + {7, 8, 9, 17}, }, }, { - Query: "select id from t1 where v3 = 6", - Expected: []sql.Row{{3}}, + Query: "select id from t1 where v3 = 17", + Expected: []sql.Row{{7}}, }, { Query: "call dolt_merge('branch2')", @@ -4453,15 +4453,15 @@ var GeneratedColumnMergeTestScripts = []queries.ScriptTest{ { Query: "select * from t1 order by id", Expected: []sql.Row{ - {1, 1, 1, 2}, - {2, 2, 2, 4}, - {3, 3, 3, 6}, - {4, 4, 4, 8}, + {1, 2, 3, 5}, + {4, 5, 6, 11}, + {7, 8, 9, 17}, + {10, 11, 12, 23}, }, }, { - Query: "select id from t1 where v3 = 8", - Expected: []sql.Row{{4}}, + Query: "select id from t1 where v3 = 23", + Expected: []sql.Row{{10}}, }, }, }, diff --git a/go/libraries/doltcore/sqle/index/key_builder.go b/go/libraries/doltcore/sqle/index/key_builder.go index 986827c9f3..52f346250e 100644 --- a/go/libraries/doltcore/sqle/index/key_builder.go +++ b/go/libraries/doltcore/sqle/index/key_builder.go @@ -22,6 +22,7 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/sqle/sqlfmt" "github.com/dolthub/dolt/go/libraries/doltcore/sqle/sqlutil" "github.com/dolthub/dolt/go/store/pool" + "github.com/dolthub/dolt/go/store/prolly" "github.com/dolthub/dolt/go/store/prolly/tree" "github.com/dolthub/dolt/go/store/val" "github.com/dolthub/go-mysql-server/memory" @@ -219,49 +220,15 @@ func (b SecondaryKeyBuilder) SecondaryKeyFromRow(ctx context.Context, k, v val.T return b.builder.Build(b.pool), nil } -// TODO: dedupe +// buildRow returns a row for the given key/value tuple pair func buildRow(ctx *sql.Context, key, value val.Tuple, sch schema.Schema, ns tree.NodeStore) (sql.Row, error) { - pkCols := sch.GetPKCols() - valueCols := sch.GetNonPKCols() - allCols := sch.GetAllCols() - - row := make(sql.Row, allCols.Size()) - - // Skip adding the key tuple if we're working with a keyless table, since the table row data is - // always all contained in the value tuple for keyless tables. - if !schema.IsKeyless(sch) { - keyDesc := sch.GetKeyDescriptor() - for i := range keyDesc.Types { - value, err := GetField(ctx, keyDesc, i, key, ns) - if err != nil { - return nil, err - } - - pkCol := pkCols.GetColumns()[i] - row[allCols.TagToIdx[pkCol.Tag]+1] = value - } + prollyRowIter := prolly.NewPointLookup(key, value) + iter, err := NewProllyRowIterForSchema(sch, prollyRowIter, sch.GetKeyDescriptor(), sch.GetValueDescriptor(), sch.GetAllCols().Tags, ns) + if err != nil { + return nil, err } - - valueColIndex := 0 - valueDescriptor := sch.GetValueDescriptor() - for valueTupleIndex := range valueDescriptor.Types { - // Skip processing the first value in the value tuple for keyless tables, since that field - // always holds the cardinality of the row and shouldn't be passed in to an expression. - if schema.IsKeyless(sch) && valueTupleIndex == 0 { - continue - } - - value, err := GetField(ctx, valueDescriptor, valueTupleIndex, value, ns) - if err != nil { - return nil, err - } - - col := valueCols.GetColumns()[valueColIndex] - row[allCols.TagToIdx[col.Tag]] = value - valueColIndex += 1 - } - - return row, nil + + return iter.Next(ctx) } diff --git a/go/libraries/doltcore/sqle/index/prolly_row_iter.go b/go/libraries/doltcore/sqle/index/prolly_row_iter.go index b3aa20e769..c00be1efc9 100644 --- a/go/libraries/doltcore/sqle/index/prolly_row_iter.go +++ b/go/libraries/doltcore/sqle/index/prolly_row_iter.go @@ -39,25 +39,42 @@ type prollyRowIter struct { var _ sql.RowIter = prollyRowIter{} -func NewProllyRowIter(sch schema.Schema, rows prolly.Map, iter prolly.MapIter, projections []uint64) (sql.RowIter, error) { +func NewProllyRowIterForMap(sch schema.Schema, rows prolly.Map, iter prolly.MapIter, projections []uint64) (sql.RowIter, error) { if projections == nil { projections = sch.GetAllCols().Tags } - keyProj, valProj, ordProj := projectionMappings(sch, projections) kd, vd := rows.Descriptors() + ns := rows.NodeStore() + return NewProllyRowIterForSchema(sch, iter, kd, vd, projections, ns) +} + +func NewProllyRowIterForSchema( + sch schema.Schema, + iter prolly.MapIter, + kd val.TupleDesc, + vd val.TupleDesc, + projections []uint64, + ns tree.NodeStore, +) (sql.RowIter, error) { if schema.IsKeyless(sch) { - return &prollyKeylessIter{ - iter: iter, - valDesc: vd, - valProj: valProj, - ordProj: ordProj, - rowLen: len(projections), - ns: rows.NodeStore(), - }, nil + return NewKeylessProllyRowIter(sch, iter, vd, projections, ns) } + return NewKeyedProllyRowIter(sch, iter, kd, vd, projections, ns) +} + +func NewKeyedProllyRowIter( + sch schema.Schema, + iter prolly.MapIter, + kd val.TupleDesc, + vd val.TupleDesc, + projections []uint64, + ns tree.NodeStore, +) (sql.RowIter, error) { + keyProj, valProj, ordProj := projectionMappings(sch, projections) + return prollyRowIter{ iter: iter, keyDesc: kd, @@ -66,7 +83,26 @@ func NewProllyRowIter(sch schema.Schema, rows prolly.Map, iter prolly.MapIter, p valProj: valProj, ordProj: ordProj, rowLen: len(projections), - ns: rows.NodeStore(), + ns: ns, + }, nil +} + +func NewKeylessProllyRowIter( + sch schema.Schema, + iter prolly.MapIter, + vd val.TupleDesc, + projections []uint64, + ns tree.NodeStore, +) (sql.RowIter, error) { + _, valProj, ordProj := projectionMappings(sch, projections) + + return &prollyKeylessIter{ + iter: iter, + valDesc: vd, + valProj: valProj, + ordProj: ordProj, + rowLen: len(projections), + ns: ns, }, nil } diff --git a/go/libraries/doltcore/sqle/rows.go b/go/libraries/doltcore/sqle/rows.go index 01ae345469..cbd75848a6 100644 --- a/go/libraries/doltcore/sqle/rows.go +++ b/go/libraries/doltcore/sqle/rows.go @@ -197,7 +197,7 @@ func ProllyRowIterFromPartition( return nil, err } - return index.NewProllyRowIter(sch, rows, iter, projections) + return index.NewProllyRowIterForMap(sch, rows, iter, projections) } // SqlTableToRowIter returns a |sql.RowIter| for a full table scan for the given |table|. If @@ -255,7 +255,7 @@ func DoltTablePartitionToRowIter(ctx *sql.Context, name string, table *doltdb.Ta if err != nil { return nil, nil, err } - rowIter, err := index.NewProllyRowIter(sch, idx, iter, nil) + rowIter, err := index.NewProllyRowIterForMap(sch, idx, iter, nil) if err != nil { return nil, nil, err } diff --git a/go/libraries/doltcore/table/table_iterator.go b/go/libraries/doltcore/table/table_iterator.go index 86b7c28c83..b331dcd0a2 100644 --- a/go/libraries/doltcore/table/table_iterator.go +++ b/go/libraries/doltcore/table/table_iterator.go @@ -71,7 +71,7 @@ func NewTableIterator(ctx context.Context, sch schema.Schema, idx durable.Index, if err != nil { return nil, err } - rowItr, err = index.NewProllyRowIter(sch, m, itr, nil) + rowItr, err = index.NewProllyRowIterForMap(sch, m, itr, nil) if err != nil { return nil, err }