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__`. The column names are separated by underscores. // - Unique constraints are named as `uq__`. 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 }