mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-06-04 11:25:52 +08:00

* feat(organization): add hname and alias for organization * fix: boolean values are not shown in the list panel's column * fix: moved logic to component level * fix: added type * fix: added test cases * fix: added test cases * chore: update copy webpack plugin * Revert "fix: display same key with multiple data types in filter suggestions by enhancing the deduping logic (#7255)" This reverts commit 1e85981a17a8e715e948308d3e85072d976907d3. * fix: use query search v2 for traces data source to handle multiple data types for the same key * fix(QueryBuilderSearchV2): add user typed option if it doesn't exist in the payload * fix(QueryBuilderSearchV2): increase the height of search dropdown for non-logs data sources * fix: display span scope selector for trace data source * chore: remove the span scope selector from qb search v1 and move the component to search v2 * fix: write test to ensure that we display span scope selector for traces data source * fix: limit converting -> only to log data source * fix: don't display empty suggestion if only spaces are typed * chore: tests for span scope selector * chore: qb search flow (key, operator, value) test cases * refactor: fix the Maximum update depth reached issue while running tests * chore: overall improvements to span scope selector tests Resource attr filter: style fix and quick filter changes (#7691) * chore: resource attr filter init * chore: resource attr filter api integration * chore: operator config updated * chore: fliter show hide logic and styles * chore: add support for custom operator list to qb * chore: minor refactor * chore: minor code refactor * test: quick filters test suite added * test: quick filters test suite added * test: all errors test suite added * chore: style fix * test: all errors mock fix * chore: test case fix and mixpanel update * chore: color update * chore: minor refactor * chore: style fix * chore: set default query in exceptions tab * chore: style fix * chore: minor refactor * chore: minor refactor * chore: minor refactor * chore: test update * chore: fix filter header with no query name * fix: scroll fix * chore: add data source traces to quick filters * chore: replace div with fragment --------- Co-authored-by: Aditya Singh <adityasingh@Adityas-MacBook-Pro.local> fix: handle rate operators for table panel (#7695) * fix: handle rate operators for table panel chore: fix error rate (#7701) Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com> * feat(organization): minor cleanups * feat(organization): better naming for api and usecase * feat(organization): better packaging for modules * feat(organization): change hname to displayName * feat(organization): update the migration to use dialect * feat(organization): update the migration to use dialect * feat(organization): update the migration to use dialect * feat(organization): revert back to impl * feat(organization): remove DI from organization * feat(organization): address review comments * feat(organization): address review comments * feat(organization): address review comments --------- Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
426 lines
9.7 KiB
Go
426 lines
9.7 KiB
Go
package sqlitesqlstore
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"reflect"
|
|
"slices"
|
|
|
|
"github.com/SigNoz/signoz/pkg/errors"
|
|
"github.com/uptrace/bun"
|
|
)
|
|
|
|
var (
|
|
Identity = "id"
|
|
Integer = "INTEGER"
|
|
Text = "TEXT"
|
|
)
|
|
|
|
var (
|
|
Org = "org"
|
|
User = "user"
|
|
CloudIntegration = "cloud_integration"
|
|
)
|
|
|
|
var (
|
|
OrgReference = `("org_id") REFERENCES "organizations" ("id")`
|
|
UserReference = `("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE`
|
|
CloudIntegrationReference = `("cloud_integration_id") REFERENCES "cloud_integration" ("id") ON DELETE CASCADE`
|
|
)
|
|
|
|
type dialect struct {
|
|
}
|
|
|
|
func (dialect *dialect) MigrateIntToTimestamp(ctx context.Context, bun bun.IDB, table string, column string) error {
|
|
columnType, err := dialect.GetColumnType(ctx, bun, table, column)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if columnType != "INTEGER" {
|
|
return nil
|
|
}
|
|
|
|
// if the columns is integer then do this
|
|
if _, err := bun.ExecContext(ctx, `ALTER TABLE `+table+` RENAME COLUMN `+column+` TO `+column+`_old`); err != nil {
|
|
return err
|
|
}
|
|
|
|
// add new timestamp column
|
|
if _, err := bun.
|
|
NewAddColumn().
|
|
Table(table).
|
|
ColumnExpr(column + " TIMESTAMP").
|
|
Exec(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
// copy data from old column to new column, converting from int (unix timestamp) to timestamp
|
|
if _, err := bun.
|
|
NewUpdate().
|
|
Table(table).
|
|
Set(column + " = datetime(" + column + "_old, 'unixepoch')").
|
|
Where("1=1").
|
|
Exec(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
// drop old column
|
|
if _, err := bun.NewDropColumn().Table(table).Column(column + "_old").Exec(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (dialect *dialect) MigrateIntToBoolean(ctx context.Context, bun bun.IDB, table string, column string) error {
|
|
columnExists, err := dialect.ColumnExists(ctx, bun, table, column)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !columnExists {
|
|
return nil
|
|
}
|
|
|
|
columnType, err := dialect.GetColumnType(ctx, bun, table, column)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if columnType != "INTEGER" {
|
|
return nil
|
|
}
|
|
|
|
if _, err := bun.ExecContext(ctx, `ALTER TABLE `+table+` RENAME COLUMN `+column+` TO `+column+`_old`); err != nil {
|
|
return err
|
|
}
|
|
|
|
// add new boolean column
|
|
if _, err := bun.NewAddColumn().Table(table).ColumnExpr(column + " BOOLEAN").Exec(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
// copy data from old column to new column, converting from int to boolean
|
|
if _, err := bun.
|
|
NewUpdate().
|
|
Table(table).
|
|
Set(column + " = CASE WHEN " + column + "_old = 1 THEN true ELSE false END").
|
|
Where("1=1").
|
|
Exec(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
// drop old column
|
|
if _, err := bun.NewDropColumn().Table(table).Column(column + "_old").Exec(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (dialect *dialect) GetColumnType(ctx context.Context, bun bun.IDB, table string, column string) (string, error) {
|
|
var columnType string
|
|
|
|
err := bun.
|
|
NewSelect().
|
|
ColumnExpr("type").
|
|
TableExpr("pragma_table_info(?)", table).
|
|
Where("name = ?", column).
|
|
Scan(ctx, &columnType)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return columnType, nil
|
|
}
|
|
|
|
func (dialect *dialect) ColumnExists(ctx context.Context, bun bun.IDB, table string, column string) (bool, error) {
|
|
var count int
|
|
err := bun.NewSelect().
|
|
ColumnExpr("COUNT(*)").
|
|
TableExpr("pragma_table_info(?)", table).
|
|
Where("name = ?", column).
|
|
Scan(ctx, &count)
|
|
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return count > 0, nil
|
|
}
|
|
|
|
func (dialect *dialect) AddColumn(ctx context.Context, bun bun.IDB, table string, column string, columnExpr string) error {
|
|
exists, err := dialect.ColumnExists(ctx, bun, table, column)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exists {
|
|
_, err = bun.
|
|
NewAddColumn().
|
|
Table(table).
|
|
ColumnExpr(column + " " + columnExpr).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (dialect *dialect) RenameColumn(ctx context.Context, bun bun.IDB, table string, oldColumnName string, newColumnName string) (bool, error) {
|
|
oldColumnExists, err := dialect.ColumnExists(ctx, bun, table, oldColumnName)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
newColumnExists, err := dialect.ColumnExists(ctx, bun, table, newColumnName)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if newColumnExists {
|
|
return true, nil
|
|
}
|
|
|
|
if !oldColumnExists {
|
|
return false, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "old column: %s doesn't exist", oldColumnName)
|
|
}
|
|
|
|
_, err = bun.
|
|
ExecContext(ctx, "ALTER TABLE "+table+" RENAME COLUMN "+oldColumnName+" TO "+newColumnName)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
func (dialect *dialect) DropColumn(ctx context.Context, bun bun.IDB, table string, column string) error {
|
|
exists, err := dialect.ColumnExists(ctx, bun, table, column)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if exists {
|
|
_, err = bun.
|
|
NewDropColumn().
|
|
Table(table).
|
|
Column(column).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (dialect *dialect) TableExists(ctx context.Context, bun bun.IDB, table interface{}) (bool, error) {
|
|
|
|
count := 0
|
|
err := bun.
|
|
NewSelect().
|
|
ColumnExpr("count(*)").
|
|
Table("sqlite_master").
|
|
Where("type = ?", "table").
|
|
Where("name = ?", bun.Dialect().Tables().Get(reflect.TypeOf(table)).Name).
|
|
Scan(ctx, &count)
|
|
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if count == 0 {
|
|
return false, nil
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func (dialect *dialect) RenameTableAndModifyModel(ctx context.Context, bun bun.IDB, oldModel interface{}, newModel interface{}, references []string, cb func(context.Context) error) error {
|
|
if len(references) == 0 {
|
|
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "cannot run migration without reference")
|
|
}
|
|
exists, err := dialect.TableExists(ctx, bun, newModel)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if exists {
|
|
return nil
|
|
}
|
|
|
|
var fkReferences []string
|
|
for _, reference := range references {
|
|
if reference == Org && !slices.Contains(fkReferences, OrgReference) {
|
|
fkReferences = append(fkReferences, OrgReference)
|
|
} else if reference == User && !slices.Contains(fkReferences, UserReference) {
|
|
fkReferences = append(fkReferences, UserReference)
|
|
} else if reference == CloudIntegration && !slices.Contains(fkReferences, CloudIntegrationReference) {
|
|
fkReferences = append(fkReferences, CloudIntegrationReference)
|
|
}
|
|
}
|
|
|
|
createTable := bun.
|
|
NewCreateTable().
|
|
IfNotExists().
|
|
Model(newModel)
|
|
|
|
for _, fk := range fkReferences {
|
|
createTable = createTable.ForeignKey(fk)
|
|
}
|
|
|
|
_, err = createTable.Exec(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = cb(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = bun.
|
|
NewDropTable().
|
|
IfExists().
|
|
Model(oldModel).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (dialect *dialect) AddNotNullDefaultToColumn(ctx context.Context, bun bun.IDB, table string, column, columnType, defaultValue string) error {
|
|
if _, err := bun.NewAddColumn().Table(table).ColumnExpr(fmt.Sprintf("%s_new %s NOT NULL DEFAULT %s ", column, columnType, defaultValue)).Exec(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := bun.NewUpdate().Table(table).Set(fmt.Sprintf("%s_new = %s", column, column)).Where("1=1").Exec(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := bun.NewDropColumn().Table(table).ColumnExpr(column).Exec(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := bun.ExecContext(ctx, fmt.Sprintf("ALTER TABLE %s RENAME COLUMN %s_new TO %s", table, column, column)); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (dialect *dialect) UpdatePrimaryKey(ctx context.Context, bun bun.IDB, oldModel interface{}, newModel interface{}, reference string, cb func(context.Context) error) error {
|
|
if reference == "" {
|
|
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "cannot run migration without reference")
|
|
}
|
|
oldTableName := bun.Dialect().Tables().Get(reflect.TypeOf(oldModel)).Name
|
|
newTableName := bun.Dialect().Tables().Get(reflect.TypeOf(newModel)).Name
|
|
|
|
columnType, err := dialect.GetColumnType(ctx, bun, oldTableName, Identity)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if columnType == Text {
|
|
return nil
|
|
}
|
|
|
|
fkReference := ""
|
|
if reference == Org {
|
|
fkReference = OrgReference
|
|
} else if reference == User {
|
|
fkReference = UserReference
|
|
}
|
|
|
|
_, err = bun.
|
|
NewCreateTable().
|
|
IfNotExists().
|
|
Model(newModel).
|
|
ForeignKey(fkReference).
|
|
Exec(ctx)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = cb(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = bun.
|
|
NewDropTable().
|
|
IfExists().
|
|
Model(oldModel).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = bun.
|
|
ExecContext(ctx, fmt.Sprintf("ALTER TABLE %s RENAME TO %s", newTableName, oldTableName))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (dialect *dialect) AddPrimaryKey(ctx context.Context, bun bun.IDB, oldModel interface{}, newModel interface{}, reference string, cb func(context.Context) error) error {
|
|
if reference == "" {
|
|
return errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "cannot run migration without reference")
|
|
}
|
|
oldTableName := bun.Dialect().Tables().Get(reflect.TypeOf(oldModel)).Name
|
|
newTableName := bun.Dialect().Tables().Get(reflect.TypeOf(newModel)).Name
|
|
|
|
identityExists, err := dialect.ColumnExists(ctx, bun, oldTableName, Identity)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if identityExists {
|
|
return nil
|
|
}
|
|
|
|
fkReference := ""
|
|
if reference == Org {
|
|
fkReference = OrgReference
|
|
} else if reference == User {
|
|
fkReference = UserReference
|
|
}
|
|
|
|
_, err = bun.
|
|
NewCreateTable().
|
|
IfNotExists().
|
|
Model(newModel).
|
|
ForeignKey(fkReference).
|
|
Exec(ctx)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = cb(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = bun.
|
|
NewDropTable().
|
|
IfExists().
|
|
Model(oldModel).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = bun.
|
|
ExecContext(ctx, fmt.Sprintf("ALTER TABLE %s RENAME TO %s", newTableName, oldTableName))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|