Files
wehub-resource-sync 5357c39144
Fuzzer / Run Fuzzer (push) Has been cancelled
Race tests / Go race tests (ubuntu-22.04) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:01:40 +08:00

528 lines
18 KiB
Go

// Copyright 2020 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package schema
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/dolthub/dolt/go/store/types"
)
func TestIndexCollectionAddIndex(t *testing.T) {
colColl := NewColCollection(
NewColumn("pk1", 1, types.IntKind, true, NotNullConstraint{}),
NewColumn("pk2", 2, types.IntKind, true, NotNullConstraint{}),
NewColumn("v1", 3, types.IntKind, false),
NewColumn("v2", 4, types.UintKind, false),
NewColumn("v3", 5, types.StringKind, false),
)
indexColl := NewIndexCollection(colColl, nil).(*indexCollectionImpl)
testIndexes := []*indexImpl{
{
name: "idx_v1",
tags: []uint64{3},
allTags: []uint64{3, 1, 2},
indexColl: indexColl,
},
{
name: "idx_v1v3v2",
tags: []uint64{3, 5, 4},
allTags: []uint64{3, 5, 4, 1, 2},
indexColl: indexColl,
comment: "hello there",
},
{
name: "idx_pk1v1",
tags: []uint64{1, 3},
allTags: []uint64{1, 3, 2},
indexColl: indexColl,
},
{
name: "idx_pk2pk1v2",
tags: []uint64{2, 1, 4},
allTags: []uint64{2, 1, 4},
indexColl: indexColl,
},
}
for _, testIndex := range testIndexes {
t.Run(testIndex.Name(), func(t *testing.T) {
assert.False(t, indexColl.Contains(testIndex.Name()))
assert.False(t, indexColl.hasIndexOnColumns(testIndex.ColumnNames()...))
assert.False(t, indexColl.hasIndexOnTags(testIndex.IndexedColumnTags()...))
assert.Nil(t, indexColl.GetByName(testIndex.Name()))
indexColl.AddIndex(testIndex)
assert.Equal(t, testIndex, indexColl.GetByName(testIndex.Name()))
assert.Equal(t, []Index{testIndex}, indexColl.AllIndexes())
for _, tag := range testIndex.IndexedColumnTags() {
assert.Equal(t, []Index{testIndex}, indexColl.IndexesWithTag(tag))
}
for _, col := range testIndex.ColumnNames() {
assert.Equal(t, []Index{testIndex}, indexColl.IndexesWithColumn(col))
}
assert.True(t, indexColl.Contains(testIndex.Name()))
assert.True(t, indexColl.hasIndexOnColumns(testIndex.ColumnNames()...))
assert.True(t, indexColl.hasIndexOnTags(testIndex.IndexedColumnTags()...))
})
indexColl.clear(t)
}
t.Run("Duplicate column set", func(t *testing.T) {
for _, testIndex := range testIndexes {
indexColl.AddIndex(testIndex)
newIndex := testIndex.copy()
newIndex.name = "dupe_" + testIndex.name
indexColl.AddIndex(newIndex)
assert.Equal(t, newIndex, indexColl.GetByName(newIndex.Name()))
assert.Equal(t, testIndex, indexColl.GetByName(testIndex.Name()))
assert.Contains(t, indexColl.AllIndexes(), newIndex)
assert.Contains(t, indexColl.AllIndexes(), testIndex)
for _, tag := range newIndex.IndexedColumnTags() {
assert.Contains(t, indexColl.IndexesWithTag(tag), newIndex)
assert.Contains(t, indexColl.IndexesWithTag(tag), testIndex)
}
for _, col := range newIndex.ColumnNames() {
assert.Contains(t, indexColl.IndexesWithColumn(col), newIndex)
assert.Contains(t, indexColl.IndexesWithColumn(col), testIndex)
}
assert.True(t, indexColl.Contains(newIndex.Name()))
assert.True(t, indexColl.Contains(testIndex.Name()))
assert.True(t, indexColl.hasIndexOnColumns(newIndex.ColumnNames()...))
assert.True(t, indexColl.hasIndexOnTags(newIndex.IndexedColumnTags()...))
}
})
}
func TestIndexCollectionAddIndexByColNames(t *testing.T) {
colColl := NewColCollection(
NewColumn("pk1", 1, types.IntKind, true, NotNullConstraint{}),
NewColumn("pk2", 2, types.IntKind, true, NotNullConstraint{}),
NewColumn("v1", 3, types.IntKind, false),
NewColumn("v2", 4, types.UintKind, false),
NewColumn("v3", 5, types.StringKind, false),
)
indexColl := NewIndexCollection(colColl, nil).(*indexCollectionImpl)
testIndexes := []struct {
cols []string
index *indexImpl
}{
{
[]string{"v1"},
&indexImpl{
name: "idx_v1",
tags: []uint64{3},
allTags: []uint64{3, 1, 2},
indexColl: indexColl,
},
},
{
[]string{"v1", "v3", "v2"},
&indexImpl{
name: "idx_v1v3v2",
tags: []uint64{3, 5, 4},
allTags: []uint64{3, 5, 4, 1, 2},
indexColl: indexColl,
},
},
{
[]string{"pk1", "v1"},
&indexImpl{
name: "idx_pk1v1",
tags: []uint64{1, 3},
allTags: []uint64{1, 3, 2},
indexColl: indexColl,
comment: "hello there",
},
},
{
[]string{"pk2", "pk1", "v2"},
&indexImpl{
name: "idx_pk2pk1v2",
tags: []uint64{2, 1, 4},
allTags: []uint64{2, 1, 4},
indexColl: indexColl,
},
},
}
for _, testIndex := range testIndexes {
t.Run(testIndex.index.Name(), func(t *testing.T) {
assert.False(t, indexColl.Contains(testIndex.index.Name()))
assert.False(t, indexColl.hasIndexOnColumns(testIndex.index.ColumnNames()...))
assert.False(t, indexColl.hasIndexOnTags(testIndex.index.IndexedColumnTags()...))
assert.Nil(t, indexColl.GetByName(testIndex.index.Name()))
resIndex, err := indexColl.AddIndexByColNames(testIndex.index.Name(), testIndex.cols, nil, IndexProperties{IsUnique: testIndex.index.IsUnique(), Comment: testIndex.index.Comment()})
assert.NoError(t, err)
assert.Equal(t, testIndex.index, resIndex)
assert.Equal(t, testIndex.index, indexColl.GetByName(resIndex.Name()))
assert.Equal(t, []Index{testIndex.index}, indexColl.AllIndexes())
for _, tag := range resIndex.IndexedColumnTags() {
assert.Equal(t, []Index{resIndex}, indexColl.IndexesWithTag(tag))
}
for _, col := range resIndex.ColumnNames() {
assert.Equal(t, []Index{resIndex}, indexColl.IndexesWithColumn(col))
}
assert.True(t, indexColl.Contains(resIndex.Name()))
assert.True(t, indexColl.hasIndexOnColumns(resIndex.ColumnNames()...))
assert.True(t, indexColl.hasIndexOnTags(resIndex.IndexedColumnTags()...))
})
indexColl.clear(t)
}
t.Run("Pre-existing", func(t *testing.T) {
for _, testIndex := range testIndexes {
_, err := indexColl.AddIndexByColNames(testIndex.index.Name(), testIndex.cols, nil, IndexProperties{IsUnique: testIndex.index.IsUnique(), Comment: testIndex.index.Comment()})
assert.NoError(t, err)
_, err = indexColl.AddIndexByColNames(testIndex.index.Name()+"copy", testIndex.cols, nil, IndexProperties{IsUnique: testIndex.index.IsUnique(), Comment: testIndex.index.Comment()})
assert.NoError(t, err)
_, err = indexColl.AddIndexByColNames(testIndex.index.Name(), []string{"v2"}, nil, IndexProperties{IsUnique: testIndex.index.IsUnique(), Comment: testIndex.index.Comment()})
assert.Error(t, err)
}
indexColl.clear(t)
})
t.Run("Non-existing Columns", func(t *testing.T) {
_, err := indexColl.AddIndexByColNames("nonsense", []string{"v4"}, nil, IndexProperties{IsUnique: false, Comment: ""})
assert.Error(t, err)
_, err = indexColl.AddIndexByColNames("nonsense", []string{"v1", "v2", "pk3"}, nil, IndexProperties{IsUnique: false, Comment: ""})
assert.Error(t, err)
})
}
func TestIndexCollectionAddIndexByColTags(t *testing.T) {
colColl := NewColCollection(
NewColumn("pk1", 1, types.IntKind, true, NotNullConstraint{}),
NewColumn("pk2", 2, types.IntKind, true, NotNullConstraint{}),
NewColumn("v1", 3, types.IntKind, false),
NewColumn("v2", 4, types.UintKind, false),
NewColumn("v3", 5, types.StringKind, false),
)
indexColl := NewIndexCollection(colColl, nil).(*indexCollectionImpl)
testIndexes := []*indexImpl{
{
name: "idx_v1",
tags: []uint64{3},
allTags: []uint64{3, 1, 2},
indexColl: indexColl,
comment: "hello there",
},
{
name: "idx_v1v3v2",
tags: []uint64{3, 5, 4},
allTags: []uint64{3, 5, 4, 1, 2},
indexColl: indexColl,
},
{
name: "idx_pk1v1",
tags: []uint64{1, 3},
allTags: []uint64{1, 3, 2},
indexColl: indexColl,
},
{
name: "idx_pk2pk1v2",
tags: []uint64{2, 1, 4},
allTags: []uint64{2, 1, 4},
indexColl: indexColl,
},
}
for _, testIndex := range testIndexes {
t.Run(testIndex.Name(), func(t *testing.T) {
assert.False(t, indexColl.Contains(testIndex.Name()))
assert.False(t, indexColl.hasIndexOnColumns(testIndex.ColumnNames()...))
assert.False(t, indexColl.hasIndexOnTags(testIndex.IndexedColumnTags()...))
assert.Nil(t, indexColl.GetByName(testIndex.Name()))
resIndex, err := indexColl.AddIndexByColTags(testIndex.Name(), testIndex.tags, nil, IndexProperties{IsUnique: testIndex.IsUnique(), Comment: testIndex.Comment()})
assert.NoError(t, err)
assert.Equal(t, testIndex, resIndex)
assert.Equal(t, testIndex, indexColl.GetByName(resIndex.Name()))
assert.Equal(t, []Index{testIndex}, indexColl.AllIndexes())
for _, tag := range resIndex.IndexedColumnTags() {
assert.Equal(t, []Index{resIndex}, indexColl.IndexesWithTag(tag))
}
for _, col := range resIndex.ColumnNames() {
assert.Equal(t, []Index{resIndex}, indexColl.IndexesWithColumn(col))
}
assert.True(t, indexColl.Contains(resIndex.Name()))
assert.True(t, indexColl.hasIndexOnColumns(resIndex.ColumnNames()...))
assert.True(t, indexColl.hasIndexOnTags(resIndex.IndexedColumnTags()...))
})
indexColl.clear(t)
}
t.Run("Pre-existing", func(t *testing.T) {
for _, testIndex := range testIndexes {
_, err := indexColl.AddIndexByColTags(testIndex.Name(), testIndex.tags, nil, IndexProperties{IsUnique: testIndex.IsUnique(), Comment: testIndex.Comment()})
assert.NoError(t, err)
_, err = indexColl.AddIndexByColTags(testIndex.Name()+"copy", testIndex.tags, nil, IndexProperties{IsUnique: testIndex.IsUnique(), Comment: testIndex.Comment()})
assert.NoError(t, err)
_, err = indexColl.AddIndexByColTags(testIndex.Name(), []uint64{4}, nil, IndexProperties{IsUnique: testIndex.IsUnique(), Comment: testIndex.Comment()})
assert.Error(t, err)
}
indexColl.clear(t)
})
t.Run("Non-existing Tags", func(t *testing.T) {
_, err := indexColl.AddIndexByColTags("nonsense", []uint64{6}, nil, IndexProperties{IsUnique: false, Comment: ""})
assert.Error(t, err)
_, err = indexColl.AddIndexByColTags("nonsense", []uint64{3, 4, 10}, nil, IndexProperties{IsUnique: false, Comment: ""})
assert.Error(t, err)
})
}
func TestIndexCollectionAllIndexes(t *testing.T) {
colColl := NewColCollection(
NewColumn("pk1", 1, types.IntKind, true, NotNullConstraint{}),
NewColumn("pk2", 2, types.IntKind, true, NotNullConstraint{}),
NewColumn("v1", 3, types.IntKind, false),
NewColumn("v2", 4, types.UintKind, false),
NewColumn("v3", 5, types.StringKind, false),
)
indexColl := NewIndexCollection(colColl, nil).(*indexCollectionImpl)
indexColl.AddIndex(&indexImpl{
name: "idx_z",
tags: []uint64{3},
})
_, err := indexColl.AddIndexByColNames("idx_a", []string{"v2"}, nil, IndexProperties{IsUnique: false, Comment: ""})
require.NoError(t, err)
_, err = indexColl.AddIndexByColTags("idx_n", []uint64{5}, nil, IndexProperties{IsUnique: false, Comment: "hello there"})
require.NoError(t, err)
assert.Equal(t, []Index{
&indexImpl{
name: "idx_a",
tags: []uint64{4},
allTags: []uint64{4, 1, 2},
indexColl: indexColl,
isUnique: false,
comment: "",
},
&indexImpl{
name: "idx_n",
tags: []uint64{5},
allTags: []uint64{5, 1, 2},
indexColl: indexColl,
isUnique: false,
comment: "hello there",
},
&indexImpl{
name: "idx_z",
tags: []uint64{3},
allTags: []uint64{3, 1, 2},
indexColl: indexColl,
isUnique: false,
comment: "",
},
}, indexColl.AllIndexes())
}
func TestIndexCollectionRemoveIndex(t *testing.T) {
colColl := NewColCollection(
NewColumn("pk1", 1, types.IntKind, true, NotNullConstraint{}),
NewColumn("pk2", 2, types.IntKind, true, NotNullConstraint{}),
NewColumn("v1", 3, types.IntKind, false),
NewColumn("v2", 4, types.UintKind, false),
NewColumn("v3", 5, types.StringKind, false),
)
indexColl := NewIndexCollection(colColl, nil).(*indexCollectionImpl)
testIndexes := []Index{
&indexImpl{
name: "idx_v1",
tags: []uint64{3},
allTags: []uint64{3, 1, 2},
indexColl: indexColl,
},
&indexImpl{
name: "idx_v1v3v2",
tags: []uint64{3, 5, 4},
allTags: []uint64{3, 5, 4, 1, 2},
indexColl: indexColl,
comment: "hello there",
},
&indexImpl{
name: "idx_pk1v1",
tags: []uint64{1, 3},
allTags: []uint64{1, 3, 2},
indexColl: indexColl,
},
&indexImpl{
name: "idx_pk2pk1v2",
tags: []uint64{2, 1, 4},
allTags: []uint64{2, 1, 4},
indexColl: indexColl,
},
}
indexColl.AddIndex(testIndexes...)
for _, testIndex := range testIndexes {
resIndex, err := indexColl.RemoveIndex(testIndex.Name())
assert.NoError(t, err)
assert.Equal(t, testIndex, resIndex)
assert.NotContains(t, indexColl.indexes, resIndex.Name())
assert.NotContains(t, indexColl.indexes, resIndex)
for _, indexes := range indexColl.colTagToIndex {
assert.NotContains(t, indexes, resIndex)
}
_, err = indexColl.RemoveIndex(testIndex.Name())
assert.Error(t, err)
}
}
func TestIndexCollectionRenameIndex(t *testing.T) {
colColl := NewColCollection(
NewColumn("pk1", 1, types.IntKind, true, NotNullConstraint{}),
NewColumn("pk2", 2, types.IntKind, true, NotNullConstraint{}),
NewColumn("v1", 3, types.IntKind, false),
NewColumn("v2", 4, types.UintKind, false),
NewColumn("v3", 5, types.StringKind, false),
)
indexColl := NewIndexCollection(colColl, nil).(*indexCollectionImpl)
index := &indexImpl{
name: "idx_a",
tags: []uint64{3},
allTags: []uint64{3, 1, 2},
indexColl: indexColl,
}
indexColl.AddIndex(index)
const newIndexName = "idx_newname"
expectedIndex := index.copy()
expectedIndex.name = newIndexName
resIndex, err := indexColl.RenameIndex(index.Name(), newIndexName)
newIndex := resIndex.(*indexImpl)
assert.NoError(t, err)
assert.Equal(t, expectedIndex, resIndex)
assert.Equal(t, indexColl.indexes, map[string]*indexImpl{newIndexName: newIndex})
for tag, indexes := range indexColl.colTagToIndex {
if tag == 3 {
assert.Equal(t, indexes, []*indexImpl{newIndex})
} else {
assert.Empty(t, indexes)
}
}
indexColl.AddIndex(index)
_, err = indexColl.RenameIndex(newIndexName, index.Name())
assert.Error(t, err)
}
func TestIndexCollectionDuplicateIndexes(t *testing.T) {
colColl := NewColCollection(
NewColumn("pk1", 1, types.IntKind, true, NotNullConstraint{}),
NewColumn("pk2", 2, types.IntKind, true, NotNullConstraint{}),
NewColumn("v1", 3, types.IntKind, false),
NewColumn("v2", 4, types.UintKind, false),
NewColumn("v3", 5, types.StringKind, false),
)
indexColl := NewIndexCollection(colColl, nil).(*indexCollectionImpl)
// Create original index
origIndex := struct {
cols []string
index *indexImpl
}{
[]string{"v1"},
&indexImpl{
name: "v1_orig",
tags: []uint64{3},
allTags: []uint64{3, 1, 2},
indexColl: indexColl,
},
}
// Create duplicate index
copyIndex := struct {
cols []string
index *indexImpl
}{
[]string{"v1"},
&indexImpl{
name: "v1_copy",
tags: []uint64{3},
allTags: []uint64{3, 1, 2},
indexColl: indexColl,
},
}
// Check that indexColl doesn't yet contain origIndex
assert.False(t, indexColl.Contains(origIndex.index.Name()))
assert.False(t, indexColl.hasIndexOnColumns(origIndex.index.ColumnNames()...))
assert.False(t, indexColl.hasIndexOnTags(origIndex.index.IndexedColumnTags()...))
assert.Nil(t, indexColl.GetByName(origIndex.index.Name()))
// Insert origIndex and see that no errors occur
resOrigIndex, err := indexColl.AddIndexByColNames(origIndex.index.Name(), origIndex.cols, nil, IndexProperties{IsUnique: origIndex.index.IsUnique(), Comment: origIndex.index.Comment()})
assert.NoError(t, err)
assert.Equal(t, origIndex.index, resOrigIndex)
assert.Equal(t, origIndex.index, indexColl.GetByName(resOrigIndex.Name()))
assert.Equal(t, []Index{origIndex.index}, indexColl.AllIndexes())
// Check that indexColl now contains origIndex
for _, tag := range resOrigIndex.IndexedColumnTags() {
assert.Equal(t, []Index{resOrigIndex}, indexColl.IndexesWithTag(tag))
}
for _, col := range resOrigIndex.ColumnNames() {
assert.Equal(t, []Index{resOrigIndex}, indexColl.IndexesWithColumn(col))
}
assert.True(t, indexColl.Contains(resOrigIndex.Name()))
assert.True(t, indexColl.hasIndexOnColumns(resOrigIndex.ColumnNames()...))
assert.True(t, indexColl.hasIndexOnTags(resOrigIndex.IndexedColumnTags()...))
// Check that indexColl doesn't yet contain copyIndex by name, but by other properties
assert.False(t, indexColl.Contains(copyIndex.index.Name()))
assert.True(t, indexColl.hasIndexOnColumns(copyIndex.index.ColumnNames()...))
assert.True(t, indexColl.hasIndexOnTags(copyIndex.index.IndexedColumnTags()...))
assert.Nil(t, indexColl.GetByName(copyIndex.index.Name()))
// Insert copyIndex and see that no errors occur
resCopyIndex, err := indexColl.AddIndexByColNames(copyIndex.index.Name(), copyIndex.cols, nil, IndexProperties{IsUnique: copyIndex.index.IsUnique(), Comment: copyIndex.index.Comment()})
assert.NoError(t, err)
assert.Equal(t, copyIndex.index, resCopyIndex)
assert.Equal(t, copyIndex.index, indexColl.GetByName(resCopyIndex.Name()))
assert.Equal(t, []Index{copyIndex.index, origIndex.index}, indexColl.AllIndexes())
// Check that indexColl contains both resOrigIndex and resCopyIndex
for _, tag := range resCopyIndex.IndexedColumnTags() {
assert.Equal(t, []Index{resOrigIndex, resCopyIndex}, indexColl.IndexesWithTag(tag))
}
for _, col := range resCopyIndex.ColumnNames() {
assert.Equal(t, []Index{resOrigIndex, resCopyIndex}, indexColl.IndexesWithColumn(col))
}
assert.True(t, indexColl.Contains(resCopyIndex.Name()))
assert.True(t, indexColl.hasIndexOnColumns(resCopyIndex.ColumnNames()...))
assert.True(t, indexColl.hasIndexOnTags(resCopyIndex.IndexedColumnTags()...))
indexColl.clear(t)
}
func (ixc *indexCollectionImpl) clear(_ *testing.T) {
ixc.indexes = make(map[string]*indexImpl)
for key := range ixc.colTagToIndex {
ixc.colTagToIndex[key] = nil
}
}