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

236 lines
5.5 KiB
Go
Executable File

// Copyright 2024 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 doltdb
import (
"sort"
"strings"
)
// TableNameSet is a simple set implementation providing standard set operations for table names.
type TableNameSet struct {
items map[TableName]bool
caseSensitive bool
}
func newTableNameSet(items []TableName, caseSensitive bool) *TableNameSet {
s := &TableNameSet{
items: make(map[TableName]bool, len(items)),
caseSensitive: caseSensitive,
}
for _, item := range items {
s.items[item] = true
}
return s
}
func NewTableNameSet(items []TableName) *TableNameSet {
return newTableNameSet(items, true)
}
func NewCaseInsensitiveTableNameSet(items []TableName) *TableNameSet {
newItems := make([]TableName, len(items))
for i, item := range items {
newItems[i] = item.ToLower()
}
return newTableNameSet(newItems, false)
}
// Add adds new items to the set
func (s *TableNameSet) Add(items ...TableName) {
for _, item := range items {
if !s.caseSensitive {
lowerItem := item.ToLower()
item = lowerItem
}
s.items[item] = true
}
}
// Remove removes existing items from the set
func (s *TableNameSet) Remove(items ...TableName) {
for _, item := range items {
if !s.caseSensitive {
item = item.ToLower()
}
delete(s.items, item)
}
}
// Contains returns true if the item being checked is already in the set.
func (s *TableNameSet) Contains(item TableName) bool {
if s == nil {
return false
}
if !s.caseSensitive {
item = item.ToLower()
}
_, present := s.items[item]
return present
}
// ContainsAll returns true if all the items being checked are already in the set.
func (s *TableNameSet) ContainsAll(items []TableName) bool {
if s == nil {
return false
}
for _, item := range items {
if !s.caseSensitive {
item = item.ToLower()
}
if _, present := s.items[item]; !present {
return false
}
}
return true
}
func (s *TableNameSet) Equals(other *TableNameSet) bool {
// two string sets can be equal even if one is sensitive and the other is insensitive as long al the items are a
// case sensitive match.
ss := s.AsSlice()
os := other.AsSlice()
if len(ss) != len(os) {
return false
}
sort.Slice(ss, func(i, j int) bool {
return ss[i].Less(ss[j])
})
sort.Slice(os, func(i, j int) bool {
return os[i].Less(os[j])
})
for i := range ss {
if ss[i] != os[i] {
return false
}
}
return true
}
// Size returns the number of unique TableNames in the set
func (s *TableNameSet) Size() int {
if s == nil {
return 0
}
return len(s.items)
}
// AsSlice converts the set to a slice of strings. If this is an insensitive set the resulting slice will be lowercase
// regardless of the case that was used when adding the string to the set.
func (s *TableNameSet) AsSlice() []TableName {
if s == nil {
return nil
}
size := len(s.items)
sl := make([]TableName, size)
i := 0
for k := range s.items {
sl[i] = k
i++
}
return sl
}
// AsStringSlice converts the set to a slice of strings. If this is an insensitive set the resulting slice will be lowercase
// regardless of the case that was used when adding the string to the set.
func (s *TableNameSet) AsStringSlice() []string {
if s == nil {
return nil
}
size := len(s.items)
sl := make([]string, size)
i := 0
for k := range s.items {
sl[i] = k.String()
i++
}
return sl
}
// AsSortedSlice converts the set to a slice of strings. If this is an insensitive set the resulting slice will be lowercase
// regardless of the case that was used when adding the string to the set. The slice is sorted in ascending order.
func (s *TableNameSet) AsSortedSlice() []TableName {
if s == nil {
return nil
}
slice := s.AsSlice()
sort.Slice(slice, func(i, j int) bool {
return slice[i].Less(slice[j])
})
return slice
}
// Iterate accepts a callback which will be called once for each TableName in the set until all items have been
// exhausted or callback returns false.
func (s *TableNameSet) Iterate(callBack func(TableName) (cont bool)) {
if s == nil {
return
}
for k := range s.items {
if !callBack(k) {
break
}
}
}
// LeftIntersectionRight takes a slice of strings and returns a slice of strings containing the intersection with the
// set, and a slice of strings for the ones missing from the set.
func (s *TableNameSet) LeftIntersectionRight(other *TableNameSet) (left *TableNameSet, intersection *TableNameSet, right *TableNameSet) {
left = NewTableNameSet(nil)
intersection = NewTableNameSet(nil)
right = NewTableNameSet(nil)
for os := range other.items {
if s.Contains(os) {
intersection.Add(os)
} else {
right.Add(os)
}
}
for ss := range s.items {
if !intersection.Contains(ss) {
left.Add(ss)
}
}
return left, intersection, right
}
// JoinStrings returns the sorted values from the set concatenated with a given sep
func (s *TableNameSet) JoinStrings(sep string) string {
slice := s.AsSlice()
sort.Slice(slice, func(i, j int) bool {
return slice[i].Less(slice[j])
})
ss := make([]string, len(slice))
for i, v := range slice {
ss[i] = v.String()
}
return strings.Join(ss, sep)
}