signoz/pkg/sqlschema/index.go
2025-10-02 15:48:59 +05:30

192 lines
4.1 KiB
Go

package sqlschema
import (
"strings"
"github.com/SigNoz/signoz/pkg/valuer"
)
var (
IndexTypeUnique = IndexType{s: valuer.NewString("uq")}
IndexTypeIndex = IndexType{s: valuer.NewString("ix")}
)
type IndexType struct{ s valuer.String }
func (i IndexType) String() string {
return i.s.String()
}
type Index interface {
// The name of the index.
// - Indexes are named as `ix_<table_name>_<column_names>`. The column names are separated by underscores.
// - Unique constraints are named as `uq_<table_name>_<column_names>`. The column names are separated by underscores.
// The name is autogenerated and should not be set by the user.
Name() string
// Add name to the index. This is typically used to override the autogenerated name because the database might have a different name.
Named(name string) Index
// The type of the index.
Type() IndexType
// The columns that the index is applied to.
Columns() []ColumnName
// The SQL representation of the index.
ToCreateSQL(fmter SQLFormatter) []byte
// Drop the index.
ToDropSQL(fmter SQLFormatter) []byte
}
type UniqueIndex struct {
TableName TableName
ColumnNames []ColumnName
name string
}
func (index *UniqueIndex) Name() string {
if index.name != "" {
return index.name
}
var b strings.Builder
b.WriteString(IndexTypeUnique.String())
b.WriteString("_")
b.WriteString(string(index.TableName))
b.WriteString("_")
for i, column := range index.ColumnNames {
if i > 0 {
b.WriteString("_")
}
b.WriteString(string(column))
}
return b.String()
}
func (index *UniqueIndex) Named(name string) Index {
copyOfColumnNames := make([]ColumnName, len(index.ColumnNames))
copy(copyOfColumnNames, index.ColumnNames)
return &UniqueIndex{
TableName: index.TableName,
ColumnNames: copyOfColumnNames,
name: name,
}
}
func (*UniqueIndex) Type() IndexType {
return IndexTypeUnique
}
func (index *UniqueIndex) Columns() []ColumnName {
return index.ColumnNames
}
func (index *UniqueIndex) ToCreateSQL(fmter SQLFormatter) []byte {
sql := []byte{}
sql = append(sql, "CREATE UNIQUE INDEX IF NOT EXISTS "...)
sql = fmter.AppendIdent(sql, index.Name())
sql = append(sql, " ON "...)
sql = fmter.AppendIdent(sql, string(index.TableName))
sql = append(sql, " ("...)
for i, column := range index.ColumnNames {
if i > 0 {
sql = append(sql, ", "...)
}
sql = fmter.AppendIdent(sql, string(column))
}
sql = append(sql, ")"...)
return sql
}
func (index *UniqueIndex) ToDropSQL(fmter SQLFormatter) []byte {
sql := []byte{}
sql = append(sql, "DROP INDEX IF EXISTS "...)
sql = fmter.AppendIdent(sql, index.Name())
return sql
}
type NormalIndex struct {
TableName TableName
ColumnNames []ColumnName
name string
}
func (index *NormalIndex) Name() string {
if index.name != "" {
return index.name
}
var b strings.Builder
b.WriteString(IndexTypeIndex.String())
b.WriteString("_")
b.WriteString(string(index.TableName))
b.WriteString("_")
for i, column := range index.ColumnNames {
if i > 0 {
b.WriteString("_")
}
b.WriteString(string(column))
}
return b.String()
}
func (index *NormalIndex) Named(name string) Index {
copyOfColumnNames := make([]ColumnName, len(index.ColumnNames))
copy(copyOfColumnNames, index.ColumnNames)
return &NormalIndex{
TableName: index.TableName,
ColumnNames: copyOfColumnNames,
name: name,
}
}
func (*NormalIndex) Type() IndexType {
return IndexTypeIndex
}
func (index *NormalIndex) Columns() []ColumnName {
return index.ColumnNames
}
func (index *NormalIndex) ToCreateSQL(fmter SQLFormatter) []byte {
sql := []byte{}
sql = append(sql, "CREATE INDEX IF NOT EXISTS "...)
sql = fmter.AppendIdent(sql, index.Name())
sql = append(sql, " ON "...)
sql = fmter.AppendIdent(sql, string(index.TableName))
sql = append(sql, " ("...)
for i, column := range index.ColumnNames {
if i > 0 {
sql = append(sql, ", "...)
}
sql = fmter.AppendIdent(sql, string(column))
}
sql = append(sql, ")"...)
return sql
}
func (index *NormalIndex) ToDropSQL(fmter SQLFormatter) []byte {
sql := []byte{}
sql = append(sql, "DROP INDEX IF EXISTS "...)
sql = fmter.AppendIdent(sql, index.Name())
return sql
}