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

Allow primary keys to contain address columns sorted by their resolved values. #8870

Merged
merged 13 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ require (
github.com/cespare/xxhash/v2 v2.2.0
github.com/creasty/defaults v1.6.0
github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2
github.com/dolthub/go-mysql-server v0.19.1-0.20250217184825-710ac92191f9
github.com/dolthub/go-mysql-server v0.19.1-0.20250218220938-e4840a923dc0
github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63
github.com/dolthub/swiss v0.1.0
github.com/esote/minmaxheap v1.0.0
Expand Down
4 changes: 2 additions & 2 deletions go/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ github.com/dolthub/fslock v0.0.3 h1:iLMpUIvJKMKm92+N1fmHVdxJP5NdyDK5bK7z7Ba2s2U=
github.com/dolthub/fslock v0.0.3/go.mod h1:QWql+P17oAAMLnL4HGB5tiovtDuAjdDTPbuqx7bYfa0=
github.com/dolthub/go-icu-regex v0.0.0-20241215010122-db690dd53c90 h1:Sni8jrP0sy/w9ZYXoff4g/ixe+7bFCZlfCqXKJSU+zM=
github.com/dolthub/go-icu-regex v0.0.0-20241215010122-db690dd53c90/go.mod h1:ylU4XjUpsMcvl/BKeRRMXSH7e7WBrPXdSLvnRJYrxEA=
github.com/dolthub/go-mysql-server v0.19.1-0.20250217184825-710ac92191f9 h1:tj14wYwj3Z902PqGh/2eDpIA97AoJrLiWRyK1/cZ6R8=
github.com/dolthub/go-mysql-server v0.19.1-0.20250217184825-710ac92191f9/go.mod h1:JTlrabhq5TJqvlL+J3NKlm0EzTHQQugUAH6yAxWi4Ww=
github.com/dolthub/go-mysql-server v0.19.1-0.20250218220938-e4840a923dc0 h1:seiyp5wL3jiPHknx716R990AKwHpE16Nx87v8snisQQ=
github.com/dolthub/go-mysql-server v0.19.1-0.20250218220938-e4840a923dc0/go.mod h1:JTlrabhq5TJqvlL+J3NKlm0EzTHQQugUAH6yAxWi4Ww=
github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63 h1:OAsXLAPL4du6tfbBgK0xXHZkOlos63RdKYS3Sgw/dfI=
github.com/dolthub/gozstd v0.0.0-20240423170813-23a2903bca63/go.mod h1:lV7lUeuDhH5thVGDCKXbatwKy2KW80L4rMT46n+Y2/Q=
github.com/dolthub/ishell v0.0.0-20240701202509-2b217167d718 h1:lT7hE5k+0nkBdj/1UOSFwjWpNxf+LCApbRHgnCA17XE=
Expand Down
6 changes: 3 additions & 3 deletions go/libraries/doltcore/diff/diff_stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ func reportPkChanges(ctx context.Context, vMapping val.OrdinalMapping, fromD, to
case tree.RemovedDiff:
stat.Removes++
case tree.ModifiedDiff:
stat.CellChanges = prollyCountCellDiff(vMapping, fromD, toD, val.Tuple(change.From), val.Tuple(change.To))
stat.CellChanges = prollyCountCellDiff(ctx, vMapping, fromD, toD, val.Tuple(change.From), val.Tuple(change.To))
stat.Changes++
default:
return errors.New("unknown change type")
Expand Down Expand Up @@ -269,7 +269,7 @@ func reportKeylessChanges(ctx context.Context, vMapping val.OrdinalMapping, from

// prollyCountCellDiff counts the number of changes columns between two tuples
// |from| and |to|. |mapping| should map columns from |from| to |to|.
func prollyCountCellDiff(mapping val.OrdinalMapping, fromD, toD val.TupleDesc, from val.Tuple, to val.Tuple) uint64 {
func prollyCountCellDiff(ctx context.Context, mapping val.OrdinalMapping, fromD, toD val.TupleDesc, from, to val.Tuple) uint64 {
newCols := uint64(toD.Count())
changed := uint64(0)
for i, j := range mapping {
Expand All @@ -286,7 +286,7 @@ func prollyCountCellDiff(mapping val.OrdinalMapping, fromD, toD val.TupleDesc, f
continue
}

if fromD.CompareField(toD.GetField(j, to), i, from) != 0 {
if fromD.CompareField(ctx, toD.GetField(j, to), i, from) != 0 {
// column was modified
changed++
continue
Expand Down
4 changes: 2 additions & 2 deletions go/libraries/doltcore/doltdb/durable/artifact_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func NewEmptyArtifactIndex(ctx context.Context, vrw types.ValueReadWriter, ns tr
panic("TODO")

case types.Format_DOLT:
kd := tableSch.GetKeyDescriptor()
kd := tableSch.GetKeyDescriptor(ns)
m, err := prolly.NewArtifactMapFromTuples(ctx, ns, kd)
if err != nil {
return nil, err
Expand Down Expand Up @@ -108,7 +108,7 @@ func artifactIndexFromAddr(ctx context.Context, vrw types.ValueReadWriter, ns tr
if fileId != serial.MergeArtifactsFileID {
return nil, fmt.Errorf("unexpected file ID for artifact node, expected %s, found %s", serial.MergeArtifactsFileID, fileId)
}
kd := tableSch.GetKeyDescriptor()
kd := tableSch.GetKeyDescriptor(ns)
m := prolly.NewArtifactMap(root, ns, kd)
return ArtifactIndexFromProllyMap(m), nil

Expand Down
2 changes: 1 addition & 1 deletion go/libraries/doltcore/doltdb/durable/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func newEmptyIndex(ctx context.Context, vrw types.ValueReadWriter, ns tree.NodeS
return IndexFromNomsMap(m, vrw, ns), nil

case types.Format_DOLT:
kd, vd := sch.GetMapDescriptors()
kd, vd := sch.GetMapDescriptors(ns)
if isKeylessSecondary {
kd = prolly.AddHashToSchema(kd)
}
Expand Down
16 changes: 7 additions & 9 deletions go/libraries/doltcore/doltdb/ignore.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"strings"

"github.com/dolthub/dolt/go/libraries/doltcore/doltdb/durable"
"github.com/dolthub/dolt/go/store/prolly/tree"
"github.com/dolthub/dolt/go/store/types"
"github.com/dolthub/dolt/go/store/val"
)
Expand Down Expand Up @@ -61,7 +60,7 @@ var ConvertTupleToIgnoreBoolean = convertTupleToIgnoreBoolean
// GetIgnoreTablePatternKey is a function that converts a Tuple to a string for the pattern field. This is used to handle the Doltgres extended string type.
var GetIgnoreTablePatternKey = getIgnoreTablePatternKey

func convertTupleToIgnoreBoolean(valueDesc val.TupleDesc, valueTuple val.Tuple) (bool, error) {
func convertTupleToIgnoreBoolean(ctx context.Context, valueDesc val.TupleDesc, valueTuple val.Tuple) (bool, error) {
if !valueDesc.Equals(val.NewTupleDescriptor(val.Type{Enc: val.Int8Enc, Nullable: false})) {
return false, fmt.Errorf("dolt_ignore had unexpected value type, this should never happen")
}
Expand All @@ -72,7 +71,7 @@ func convertTupleToIgnoreBoolean(valueDesc val.TupleDesc, valueTuple val.Tuple)
return ignore, nil
}

func getIgnoreTablePatternKey(keyDesc val.TupleDesc, keyTuple val.Tuple, _ tree.NodeStore) (string, error) {
func getIgnoreTablePatternKey(ctx context.Context, keyDesc val.TupleDesc, keyTuple val.Tuple) (string, error) {
if !keyDesc.Equals(val.NewTupleDescriptor(val.Type{Enc: val.StringEnc, Nullable: false})) {
return "", fmt.Errorf("dolt_ignore had unexpected key type, this should never happen")
}
Expand Down Expand Up @@ -111,9 +110,10 @@ func GetIgnoredTablePatterns(ctx context.Context, roots Roots, schemas []string)
if err != nil {
return nil, err
}
keyDesc, valueDesc := ignoreTableSchema.GetMapDescriptors()
m := durable.MapFromIndex(index)
keyDesc, valueDesc := ignoreTableSchema.GetMapDescriptors(m.NodeStore())

ignoreTableMap, err := durable.ProllyMapFromIndex(index).IterAll(ctx)
ignoreTableMap, err := m.IterAll(ctx)
if err != nil {
return nil, err
}
Expand All @@ -126,14 +126,12 @@ func GetIgnoredTablePatterns(ctx context.Context, roots Roots, schemas []string)
return nil, err
}

m := durable.MapFromIndex(index)

pattern, err := GetIgnoreTablePatternKey(keyDesc, keyTuple, m.NodeStore())
pattern, err := GetIgnoreTablePatternKey(ctx, keyDesc, keyTuple)
if err != nil {
return nil, err
}

ignore, err := ConvertTupleToIgnoreBoolean(valueDesc, valueTuple)
ignore, err := ConvertTupleToIgnoreBoolean(ctx, valueDesc, valueTuple)
if err != nil {
return nil, err
}
Expand Down
8 changes: 4 additions & 4 deletions go/libraries/doltcore/merge/keyless_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,15 +358,15 @@ func assertProllyConflicts(t *testing.T, ctx context.Context, tbl *doltdb.Table,

if expectedConf.base != nil {
_, value := expectedConf.base.HashAndValue()
require.Equal(t, valDesc.Format(value), valDesc.Format(base))
require.Equal(t, valDesc.Format(ctx, value), valDesc.Format(ctx, base))
}
if expectedConf.ours != nil {
_, value := expectedConf.ours.HashAndValue()
require.Equal(t, valDesc.Format(value), valDesc.Format(ours))
require.Equal(t, valDesc.Format(ctx, value), valDesc.Format(ctx, ours))
}
if expectedConf.theirs != nil {
_, value := expectedConf.theirs.HashAndValue()
require.Equal(t, valDesc.Format(value), valDesc.Format(theirs))
require.Equal(t, valDesc.Format(ctx, value), valDesc.Format(ctx, theirs))
}
}

Expand Down Expand Up @@ -457,7 +457,7 @@ func assertKeylessProllyRows(t *testing.T, ctx context.Context, tbl *doltdb.Tabl
copy(h[:], hashId.GetField(0))
expectedVal, ok := expectedSet[h]
assert.True(t, ok)
assert.Equal(t, valDesc.Format(expectedVal), valDesc.Format(value))
assert.Equal(t, valDesc.Format(ctx, expectedVal), valDesc.Format(ctx, value))
}

require.Equal(t, len(expected), c)
Expand Down
2 changes: 1 addition & 1 deletion go/libraries/doltcore/merge/merge_prolly_indexes.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func buildIndex(
if err != nil {
return nil, err
}
kd := postMergeSchema.GetKeyDescriptor()
kd := postMergeSchema.GetKeyDescriptor(ns)
kb := val.NewTupleBuilder(kd)
p := m.Pool()

Expand Down
58 changes: 30 additions & 28 deletions go/libraries/doltcore/merge/merge_prolly_rows.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ func mergeProllyTable(
// conflicts are detected, this function attempts to resolve them automatically if possible, and
// if not, they are recorded as conflicts in the table's artifacts.
func mergeProllyTableData(ctx *sql.Context, tm *TableMerger, finalSch schema.Schema, mergeTbl *doltdb.Table, valueMerger *valueMerger, mergeInfo MergeInfo, diffInfo tree.ThreeWayDiffInfo) (*doltdb.Table, *MergeStats, error) {
ns := tm.ns

iter, err := threeWayDiffer(ctx, tm, valueMerger, diffInfo)
if err != nil {
return nil, nil, err
Expand All @@ -128,7 +130,7 @@ func mergeProllyTableData(ctx *sql.Context, tm *TableMerger, finalSch schema.Sch
if err != nil {
return nil, nil, err
}
leftEditor := durable.ProllyMapFromIndex(lr).Rewriter(finalSch.GetKeyDescriptor(), finalSch.GetValueDescriptor())
leftEditor := durable.ProllyMapFromIndex(lr).Rewriter(finalSch.GetKeyDescriptor(ns), finalSch.GetValueDescriptor(ns))

ai, err := mergeTbl.GetArtifacts(ctx)
if err != nil {
Expand Down Expand Up @@ -419,17 +421,17 @@ func (cv checkValidator) validateDiff(ctx *sql.Context, diff tree.ThreeWayDiff)
return 0, nil
case tree.DiffOpLeftAdd, tree.DiffOpLeftModify:
valueTuple = diff.Left
valueDesc = cv.tableMerger.leftSch.GetValueDescriptor()
valueDesc = cv.tableMerger.leftSch.GetValueDescriptor(cv.tableMerger.ns)
case tree.DiffOpRightAdd, tree.DiffOpRightModify:
valueTuple = diff.Right
valueDesc = cv.tableMerger.rightSch.GetValueDescriptor()
valueDesc = cv.tableMerger.rightSch.GetValueDescriptor(cv.tableMerger.ns)
case tree.DiffOpConvergentAdd, tree.DiffOpConvergentModify:
// both sides made the same change, just take the left
valueTuple = diff.Left
valueDesc = cv.tableMerger.leftSch.GetValueDescriptor()
valueDesc = cv.tableMerger.leftSch.GetValueDescriptor(cv.tableMerger.ns)
case tree.DiffOpDivergentModifyResolved:
valueTuple = diff.Merged
valueDesc = cv.tableMerger.leftSch.GetValueDescriptor()
valueDesc = cv.tableMerger.leftSch.GetValueDescriptor(cv.tableMerger.ns)
}

for checkName, checkExpression := range cv.checkExpressions {
Expand Down Expand Up @@ -571,14 +573,14 @@ func (uv uniqValidator) validateDiff(ctx *sql.Context, diff tree.ThreeWayDiff) (
value = diff.Right
// Don't remap the value to the merged schema if the table is keyless or if the mapping is an identity mapping.
if !uv.valueMerger.keyless && !uv.valueMerger.rightMapping.IsIdentityMapping() {
modifiedValue := remapTuple(value, uv.tm.rightSch.GetValueDescriptor(), uv.valueMerger.rightMapping)
modifiedValue := remapTuple(value, uv.tm.rightSch.GetValueDescriptor(uv.valueMerger.ns), uv.valueMerger.rightMapping)
value = val.NewTuple(uv.valueMerger.syncPool, modifiedValue...)
}
case tree.DiffOpLeftAdd, tree.DiffOpLeftModify:
value = diff.Left
// Don't remap the value to the merged schema if the table is keyless or if the mapping is an identity mapping.
if !uv.valueMerger.keyless && !uv.valueMerger.leftMapping.IsIdentityMapping() {
modifiedValue := remapTuple(value, uv.tm.leftSch.GetValueDescriptor(), uv.valueMerger.leftMapping)
modifiedValue := remapTuple(value, uv.tm.leftSch.GetValueDescriptor(uv.valueMerger.ns), uv.valueMerger.leftMapping)
value = val.NewTuple(uv.valueMerger.syncPool, modifiedValue...)
}
case tree.DiffOpRightDelete:
Expand Down Expand Up @@ -802,7 +804,7 @@ func (idx uniqIndex) findCollisions(ctx context.Context, key, value val.Tuple, c
// collided with row(|key|, |value|) and pass both to |cb|
err = idx.clustered.Get(ctx, clusteredKey, func(k val.Tuple, v val.Tuple) error {
if k == nil {
s := idx.clusteredKeyDesc.Format(clusteredKey)
s := idx.clusteredKeyDesc.Format(ctx, clusteredKey)
return errors.New("failed to find key: " + s)
}
collisionDetected = true
Expand Down Expand Up @@ -1101,7 +1103,7 @@ func (m *primaryMerger) merge(ctx *sql.Context, diff tree.ThreeWayDiff, sourceSc
ctx,
diff.Key,
diff.Right,
sourceSch.GetValueDescriptor(),
sourceSch.GetValueDescriptor(m.valueMerger.ns),
m.valueMerger.rightMapping,
m.tableMerger,
m.tableMerger.rightSch,
Expand Down Expand Up @@ -1139,7 +1141,7 @@ func (m *primaryMerger) merge(ctx *sql.Context, diff tree.ThreeWayDiff, sourceSc
ctx,
diff.Key,
merged,
m.finalSch.GetValueDescriptor(),
m.finalSch.GetValueDescriptor(m.valueMerger.ns),
m.valueMerger.rightMapping,
m.tableMerger,
m.tableMerger.rightSch,
Expand Down Expand Up @@ -1170,7 +1172,7 @@ func (m *primaryMerger) merge(ctx *sql.Context, diff tree.ThreeWayDiff, sourceSc
return fmt.Errorf("cannot merge keyless tables with reordered columns")
}
} else {
tempTupleValue, err := remapTupleWithColumnDefaults(ctx, diff.Key, newTupleValue, sourceSch.GetValueDescriptor(),
tempTupleValue, err := remapTupleWithColumnDefaults(ctx, diff.Key, newTupleValue, sourceSch.GetValueDescriptor(m.valueMerger.ns),
m.valueMerger.leftMapping, m.tableMerger, m.tableMerger.leftSch, m.finalSch, m.defaults, m.valueMerger.syncPool, false)
if err != nil {
return err
Expand Down Expand Up @@ -1284,7 +1286,7 @@ func newSecondaryMerger(ctx *sql.Context, tm *TableMerger, valueMerger *valueMer
}
// Use the mergedSchema to work with the secondary indexes, to pull out row data using the right
// pri_index -> sec_index mapping.
lm, err := GetMutableSecondaryIdxsWithPending(ctx, leftSchema, mergedSchema, tm.name.Name, ls, secondaryMergerPendingSize)
lm, err := GetMutableSecondaryIdxsWithPending(ctx, tm.ns, leftSchema, mergedSchema, tm.name.Name, ls, secondaryMergerPendingSize)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1339,7 +1341,7 @@ func (m *secondaryMerger) merge(ctx *sql.Context, diff tree.ThreeWayDiff, leftSc
ctx,
diff.Key,
diff.Right,
m.valueMerger.rightSchema.GetValueDescriptor(),
m.valueMerger.rightSchema.GetValueDescriptor(m.valueMerger.ns),
m.valueMerger.rightMapping,
m.tableMerger,
m.tableMerger.rightSch,
Expand All @@ -1364,7 +1366,7 @@ func (m *secondaryMerger) merge(ctx *sql.Context, diff tree.ThreeWayDiff, leftSc
diff.Key,
diff.Base,
// Only the right side was modified, so the base schema must be the same as the left schema
leftSchema.GetValueDescriptor(),
leftSchema.GetValueDescriptor(m.valueMerger.ns),
m.valueMerger.baseMapping,
tm,
m.tableMerger.ancSch,
Expand Down Expand Up @@ -1453,7 +1455,7 @@ func remapTupleWithColumnDefaults(
pool pool.BuffPool,
rightSide bool,
) (val.Tuple, error) {
tb := val.NewTupleBuilder(mergedSch.GetValueDescriptor())
tb := val.NewTupleBuilder(mergedSch.GetValueDescriptor(tm.ns))

var secondPass []int
for to, from := range mapping {
Expand Down Expand Up @@ -1631,10 +1633,10 @@ func newValueMerger(merged, leftSch, rightSch, baseSch schema.Schema, syncPool p

return &valueMerger{
numCols: merged.GetNonPKCols().StoredSize(),
baseVD: baseSch.GetValueDescriptor(),
rightVD: rightSch.GetValueDescriptor(),
resultVD: merged.GetValueDescriptor(),
leftVD: leftSch.GetValueDescriptor(),
baseVD: baseSch.GetValueDescriptor(ns),
rightVD: rightSch.GetValueDescriptor(ns),
resultVD: merged.GetValueDescriptor(ns),
leftVD: leftSch.GetValueDescriptor(ns),
resultSchema: merged,
leftMapping: leftMapping,
rightMapping: rightMapping,
Expand Down Expand Up @@ -1763,7 +1765,7 @@ func (m *valueMerger) processBaseColumn(ctx context.Context, i int, left, right,
if err != nil {
return false, err
}
if isEqual(m.baseVD.Comparator(), i, baseCol, rightCol, m.rightVD.Types[rightColIdx]) {
if isEqual(ctx, m.baseVD.Comparator(), i, baseCol, rightCol, m.rightVD.Types[rightColIdx]) {
// right column did not change, so there is no conflict.
return false, nil
}
Expand All @@ -1786,7 +1788,7 @@ func (m *valueMerger) processBaseColumn(ctx context.Context, i int, left, right,
if err != nil {
return false, err
}
if isEqual(m.baseVD.Comparator(), i, baseCol, leftCol, m.leftVD.Types[leftColIdx]) {
if isEqual(ctx, m.baseVD.Comparator(), i, baseCol, leftCol, m.leftVD.Types[leftColIdx]) {
// left column did not change, so there is no conflict.
return false, nil
}
Expand Down Expand Up @@ -1826,7 +1828,7 @@ func (m *valueMerger) processBaseColumn(ctx context.Context, i int, left, right,
if err != nil {
return false, err
}
if modifiedVD.Comparator().CompareValues(i, baseCol, modifiedCol, modifiedVD.Types[modifiedColIdx]) == 0 {
if modifiedVD.Comparator().CompareValues(ctx, i, baseCol, modifiedCol, modifiedVD.Types[modifiedColIdx]) == 0 {
return false, nil
}
return true, nil
Expand Down Expand Up @@ -1877,7 +1879,7 @@ func (m *valueMerger) processColumn(ctx *sql.Context, i int, left, right, base v
return nil, false, err
}

if isEqual(m.leftVD.Comparator(), i, leftCol, rightCol, resultType) {
if isEqual(ctx, m.leftVD.Comparator(), i, leftCol, rightCol, resultType) {
// Columns are equal, returning either would be correct.
// However, for certain types the two columns may have different bytes.
// We need to ensure that merges are deterministic regardless of the merge direction.
Expand Down Expand Up @@ -1931,14 +1933,14 @@ func (m *valueMerger) processColumn(ctx *sql.Context, i int, left, right, base v
if err != nil {
return nil, true, nil
}
rightModified = !isEqual(m.resultVD.Comparator(), i, rightCol, baseCol, resultType)
rightModified = !isEqual(ctx, m.resultVD.Comparator(), i, rightCol, baseCol, resultType)
}

leftCol, err = convert(ctx, m.leftVD, m.resultVD, m.resultSchema, leftColIdx, i, left, leftCol, m.ns)
if err != nil {
return nil, true, nil
}
if isEqual(m.resultVD.Comparator(), i, leftCol, rightCol, resultType) {
if isEqual(ctx, m.resultVD.Comparator(), i, leftCol, rightCol, resultType) {
// Columns are equal, returning either would be correct.
// However, for certain types the two columns may have different bytes.
// We need to ensure that merges are deterministic regardless of the merge direction.
Expand All @@ -1949,7 +1951,7 @@ func (m *valueMerger) processColumn(ctx *sql.Context, i int, left, right, base v
return rightCol, false, nil
}

leftModified = !isEqual(m.resultVD.Comparator(), i, leftCol, baseCol, resultType)
leftModified = !isEqual(ctx, m.resultVD.Comparator(), i, leftCol, baseCol, resultType)

switch {
case leftModified && rightModified:
Expand Down Expand Up @@ -2132,8 +2134,8 @@ func mergeJSON(ctx context.Context, ns tree.NodeStore, base, left, right sql.JSO
}
}

func isEqual(cmp val.TupleComparator, i int, left []byte, right []byte, resultType val.Type) bool {
return cmp.CompareValues(i, left, right, resultType) == 0
func isEqual(ctx context.Context, cmp val.TupleComparator, i int, left []byte, right []byte, resultType val.Type) bool {
return cmp.CompareValues(ctx, i, left, right, resultType) == 0
}

func getColumn(tuple *val.Tuple, mapping *val.OrdinalMapping, idx int) (col []byte, colIndex int, exists bool) {
Expand Down
Loading
Loading