145 lines
3.8 KiB
Go
Raw Normal View History

package sqlitesqlschema
import (
"context"
"strconv"
"github.com/SigNoz/signoz/pkg/errors"
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/sqlschema"
"github.com/SigNoz/signoz/pkg/sqlstore"
"github.com/uptrace/bun"
)
type provider struct {
settings factory.ScopedProviderSettings
fmter sqlschema.SQLFormatter
sqlstore sqlstore.SQLStore
operator sqlschema.SQLOperator
}
func NewFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[sqlschema.SQLSchema, sqlschema.Config] {
return factory.NewProviderFactory(factory.MustNewName("sqlite"), func(ctx context.Context, providerSettings factory.ProviderSettings, config sqlschema.Config) (sqlschema.SQLSchema, error) {
return New(ctx, providerSettings, config, sqlstore)
})
}
func New(ctx context.Context, providerSettings factory.ProviderSettings, config sqlschema.Config, sqlstore sqlstore.SQLStore) (sqlschema.SQLSchema, error) {
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/sqlschema/sqlitesqlschema")
fmter := Formatter{sqlschema.NewFormatter(sqlstore.BunDB().Dialect())}
return &provider{
fmter: fmter,
settings: settings,
sqlstore: sqlstore,
operator: sqlschema.NewOperator(fmter, sqlschema.OperatorSupport{
DropConstraint: false,
ColumnIfNotExistsExists: false,
AlterColumnSetNotNull: false,
}),
}, nil
}
func (provider *provider) Formatter() sqlschema.SQLFormatter {
return provider.fmter
}
func (provider *provider) Operator() sqlschema.SQLOperator {
return provider.operator
}
func (provider *provider) GetTable(ctx context.Context, tableName sqlschema.TableName) (*sqlschema.Table, []*sqlschema.UniqueConstraint, error) {
var sql string
if err := provider.
sqlstore.
BunDB().
NewRaw("SELECT sql FROM sqlite_master WHERE type IN (?) AND tbl_name = ? AND sql IS NOT NULL", bun.In([]string{"table"}), string(tableName)).
Scan(ctx, &sql); err != nil {
return nil, nil, err
}
table, uniqueConstraints, err := parseCreateTable(sql, provider.fmter)
if err != nil {
return nil, nil, err
}
return table, uniqueConstraints, nil
}
func (provider *provider) GetIndices(ctx context.Context, tableName sqlschema.TableName) ([]sqlschema.Index, error) {
rows, err := provider.
sqlstore.
BunDB().
QueryContext(ctx, "SELECT * FROM PRAGMA_index_list(?)", string(tableName))
if err != nil {
return nil, err
}
defer func() {
if err := rows.Close(); err != nil {
provider.settings.Logger().ErrorContext(ctx, "error closing rows", "error", err)
}
}()
indices := []sqlschema.Index{}
for rows.Next() {
var (
seq int
name string
unique bool
origin string
partial bool
columns []sqlschema.ColumnName
)
if err := rows.Scan(&seq, &name, &unique, &origin, &partial); err != nil {
return nil, err
}
// skip the index that was created by a UNIQUE constraint
if origin == "u" {
continue
}
// skip the index that was created by primary key constraint
if origin == "pk" {
continue
}
if err := provider.
sqlstore.
BunDB().
NewRaw("SELECT name FROM PRAGMA_index_info(?)", string(name)).
Scan(ctx, &columns); err != nil {
return nil, err
}
if unique {
indices = append(indices, (&sqlschema.UniqueIndex{
TableName: tableName,
ColumnNames: columns,
}).Named(name).(*sqlschema.UniqueIndex))
}
}
return indices, nil
}
func (provider *provider) ToggleFKEnforcement(ctx context.Context, db bun.IDB, on bool) error {
_, err := db.ExecContext(ctx, "PRAGMA foreign_keys = ?", on)
if err != nil {
return err
}
var val bool
if err := db.NewRaw("PRAGMA foreign_keys").Scan(ctx, &val); err != nil {
return err
}
if on == val {
return nil
}
return errors.NewInternalf(errors.CodeInternal, "foreign_keys(actual: %s, expected: %s), maybe a transaction is in progress?", strconv.FormatBool(val), strconv.FormatBool(on))
}