Remove unused store/sqlstore functions (#19354)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
5e147dd150
Коммит
509f49c813
@@ -39,12 +39,6 @@ func newSqlEmojiStore(sqlStore *SqlStore, metrics einterfaces.MetricsInterface)
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es SqlEmojiStore) createIndexesIfNotExists() {
|
|
||||||
es.CreateIndexIfNotExists("idx_emoji_update_at", "Emoji", "UpdateAt")
|
|
||||||
es.CreateIndexIfNotExists("idx_emoji_create_at", "Emoji", "CreateAt")
|
|
||||||
es.CreateIndexIfNotExists("idx_emoji_delete_at", "Emoji", "DeleteAt")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (es SqlEmojiStore) Save(emoji *model.Emoji) (*model.Emoji, error) {
|
func (es SqlEmojiStore) Save(emoji *model.Emoji) (*model.Emoji, error) {
|
||||||
emoji.PreSave()
|
emoji.PreSave()
|
||||||
if err := emoji.IsValid(); err != nil {
|
if err := emoji.IsValid(); err != nil {
|
||||||
|
|||||||
@@ -77,11 +77,6 @@ func newSqlGroupStore(sqlStore *SqlStore) store.GroupStore {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlGroupStore) createIndexesIfNotExists() {
|
|
||||||
s.CreateColumnIfNotExistsNoDefault("Channels", "GroupConstrained", "tinyint(1)", "boolean")
|
|
||||||
s.CreateColumnIfNotExistsNoDefault("Teams", "GroupConstrained", "tinyint(1)", "boolean")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqlGroupStore) Create(group *model.Group) (*model.Group, error) {
|
func (s *SqlGroupStore) Create(group *model.Group) (*model.Group, error) {
|
||||||
if group.Id != "" {
|
if group.Id != "" {
|
||||||
return nil, store.NewErrInvalidInput("Group", "id", group.Id)
|
return nil, store.NewErrInvalidInput("Group", "id", group.Id)
|
||||||
|
|||||||
@@ -132,13 +132,6 @@ type SqlStore struct {
|
|||||||
metrics einterfaces.MetricsInterface
|
metrics einterfaces.MetricsInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
// ColumnInfo holds information about a column.
|
|
||||||
type ColumnInfo struct {
|
|
||||||
DataType string
|
|
||||||
DefaultValue string
|
|
||||||
CharMaximumLength int
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(settings model.SqlSettings, metrics einterfaces.MetricsInterface) *SqlStore {
|
func New(settings model.SqlSettings, metrics einterfaces.MetricsInterface) *SqlStore {
|
||||||
store := &SqlStore{
|
store := &SqlStore{
|
||||||
rrCounter: 0,
|
rrCounter: 0,
|
||||||
@@ -201,25 +194,12 @@ func New(settings model.SqlSettings, metrics einterfaces.MetricsInterface) *SqlS
|
|||||||
store.stores.scheme = newSqlSchemeStore(store)
|
store.stores.scheme = newSqlSchemeStore(store)
|
||||||
store.stores.group = newSqlGroupStore(store)
|
store.stores.group = newSqlGroupStore(store)
|
||||||
store.stores.productNotices = newSqlProductNoticesStore(store)
|
store.stores.productNotices = newSqlProductNoticesStore(store)
|
||||||
err = store.GetMaster().CreateTablesIfNotExists()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if IsDuplicate(err) {
|
|
||||||
mlog.Warn("Duplicate key error occurred; assuming table already created and proceeding.", mlog.Err(err))
|
|
||||||
} else {
|
|
||||||
mlog.Fatal("Error creating database tables.", mlog.Err(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = upgradeDatabase(store, model.CurrentVersion)
|
err = upgradeDatabase(store, model.CurrentVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mlog.Fatal("Failed to upgrade database.", mlog.Err(err))
|
mlog.Fatal("Failed to upgrade database.", mlog.Err(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
store.stores.system.(*SqlSystemStore).createIndexesIfNotExists()
|
|
||||||
store.stores.emoji.(*SqlEmojiStore).createIndexesIfNotExists()
|
|
||||||
store.stores.UserTermsOfService.(SqlUserTermsOfServiceStore).createIndexesIfNotExists()
|
|
||||||
store.stores.group.(*SqlGroupStore).createIndexesIfNotExists()
|
|
||||||
store.stores.preference.(*SqlPreferenceStore).deleteUnusedFeatures()
|
store.stores.preference.(*SqlPreferenceStore).deleteUnusedFeatures()
|
||||||
|
|
||||||
return store
|
return store
|
||||||
@@ -646,73 +626,6 @@ func (ss *SqlStore) DoesColumnExist(tableName string, columnName string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SqlStore) DoesIndexExist(indexName string, tableName string) bool {
|
|
||||||
if ss.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
_, err := ss.GetMaster().SelectStr("SELECT $1::regclass", indexName)
|
|
||||||
// It should fail if the index does not exist
|
|
||||||
return err == nil
|
|
||||||
} else if ss.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
count, err := ss.GetMaster().SelectInt("SELECT COUNT(0) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() and table_name = ? AND index_name = ?", tableName, indexName)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to check index", mlog.Err(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
if count <= 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mlog.Fatal("Failed to check if index exists because of missing driver")
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetColumnInfo returns data type information about the given column.
|
|
||||||
func (ss *SqlStore) GetColumnInfo(tableName, columnName string) (*ColumnInfo, error) {
|
|
||||||
var columnInfo ColumnInfo
|
|
||||||
if ss.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
err := ss.GetMaster().SelectOne(&columnInfo,
|
|
||||||
`SELECT data_type as DataType, COALESCE(column_default, '') as DefaultValue,
|
|
||||||
COALESCE(character_maximum_length, 0) as CharMaximumLength
|
|
||||||
FROM information_schema.columns
|
|
||||||
WHERE lower(table_name) = lower($1)
|
|
||||||
AND lower(column_name) = lower($2)`,
|
|
||||||
tableName, columnName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &columnInfo, nil
|
|
||||||
} else if ss.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
err := ss.GetMaster().SelectOne(&columnInfo,
|
|
||||||
`SELECT data_type as DataType, COALESCE(column_default, '') as DefaultValue,
|
|
||||||
COALESCE(character_maximum_length, 0) as CharMaximumLength
|
|
||||||
FROM information_schema.columns
|
|
||||||
WHERE table_schema = DATABASE()
|
|
||||||
AND lower(table_name) = lower(?)
|
|
||||||
AND lower(column_name) = lower(?)`,
|
|
||||||
tableName, columnName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &columnInfo, nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("Driver not supported for this method")
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsVarchar returns true if the column type matches one of the varchar types
|
|
||||||
// either in MySQL or PostgreSQL.
|
|
||||||
func (ss *SqlStore) IsVarchar(columnType string) bool {
|
|
||||||
if ss.DriverName() == model.DatabaseDriverPostgres && columnType == "character varying" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if ss.DriverName() == model.DatabaseDriverMysql && columnType == "varchar" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) DoesTriggerExist(triggerName string) bool {
|
func (ss *SqlStore) DoesTriggerExist(triggerName string) bool {
|
||||||
if ss.DriverName() == model.DatabaseDriverPostgres {
|
if ss.DriverName() == model.DatabaseDriverPostgres {
|
||||||
count, err := ss.GetMaster().SelectInt(`
|
count, err := ss.GetMaster().SelectInt(`
|
||||||
@@ -781,48 +694,6 @@ func (ss *SqlStore) CreateColumnIfNotExists(tableName string, columnName string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SqlStore) CreateColumnIfNotExistsNoDefault(tableName string, columnName string, mySqlColType string, postgresColType string) bool {
|
|
||||||
|
|
||||||
if ss.DoesColumnExist(tableName, columnName) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if ss.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
_, err := ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " ADD " + columnName + " " + postgresColType)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to create column", mlog.Err(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
|
|
||||||
} else if ss.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
_, err := ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " ADD " + columnName + " " + mySqlColType)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to create column", mlog.Err(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
|
|
||||||
} else {
|
|
||||||
mlog.Fatal("Failed to create column because of missing driver")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) RemoveColumnIfExists(tableName string, columnName string) bool {
|
|
||||||
|
|
||||||
if !ss.DoesColumnExist(tableName, columnName) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " DROP COLUMN " + columnName)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to drop column", mlog.Err(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) RemoveTableIfExists(tableName string) bool {
|
func (ss *SqlStore) RemoveTableIfExists(tableName string) bool {
|
||||||
if !ss.DoesTableExist(tableName) {
|
if !ss.DoesTableExist(tableName) {
|
||||||
return false
|
return false
|
||||||
@@ -836,335 +707,6 @@ func (ss *SqlStore) RemoveTableIfExists(tableName string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SqlStore) RenameColumnIfExists(tableName string, oldColumnName string, newColumnName string, colType string) bool {
|
|
||||||
if !ss.DoesColumnExist(tableName, oldColumnName) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
if ss.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
_, err = ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " CHANGE " + oldColumnName + " " + newColumnName + " " + colType)
|
|
||||||
} else if ss.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
_, err = ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " RENAME COLUMN " + oldColumnName + " TO " + newColumnName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to rename column", mlog.Err(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) GetMaxLengthOfColumnIfExists(tableName string, columnName string) string {
|
|
||||||
if !ss.DoesColumnExist(tableName, columnName) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var result string
|
|
||||||
var err error
|
|
||||||
if ss.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
result, err = ss.GetMaster().SelectStr("SELECT CHARACTER_MAXIMUM_LENGTH FROM information_schema.columns WHERE table_name = '" + tableName + "' AND COLUMN_NAME = '" + columnName + "'")
|
|
||||||
} else if ss.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
result, err = ss.GetMaster().SelectStr("SELECT character_maximum_length FROM information_schema.columns WHERE table_name = '" + strings.ToLower(tableName) + "' AND column_name = '" + strings.ToLower(columnName) + "'")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to get max length of column", mlog.Err(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) AlterColumnTypeIfExists(tableName string, columnName string, mySqlColType string, postgresColType string) bool {
|
|
||||||
if !ss.DoesColumnExist(tableName, columnName) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
if ss.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
_, err = ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " MODIFY " + columnName + " " + mySqlColType)
|
|
||||||
} else if ss.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
query := "ALTER TABLE " + strings.ToLower(tableName) + " ALTER COLUMN " + strings.ToLower(columnName) + " TYPE " + postgresColType
|
|
||||||
// We need to explicitly cast when moving from text based to jsonb datatypes.
|
|
||||||
if postgresColType == "jsonb" {
|
|
||||||
query += " USING " + strings.ToLower(columnName) + "::jsonb"
|
|
||||||
}
|
|
||||||
_, err = ss.GetMaster().ExecNoTimeout(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
msg := "Failed to alter column type."
|
|
||||||
fields := []mlog.Field{mlog.Err(err)}
|
|
||||||
if mySqlColType == "JSON" && postgresColType == "jsonb" {
|
|
||||||
msg += " It is likely you have invalid JSON values in the column. Please fix the values manually and run the migration again."
|
|
||||||
fields = append(fields,
|
|
||||||
mlog.String("tableName", tableName),
|
|
||||||
mlog.String("columnName", columnName),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
mlog.Fatal(msg, fields...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) RemoveDefaultIfColumnExists(tableName, columnName string) bool {
|
|
||||||
if !ss.DoesColumnExist(tableName, columnName) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " ALTER COLUMN " + columnName + " DROP DEFAULT")
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to drop column default", mlog.String("table", tableName), mlog.String("column", columnName), mlog.Err(err))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) AlterDefaultIfColumnExists(tableName string, columnName string, mySqlColDefault *string, postgresColDefault *string) bool {
|
|
||||||
if !ss.DoesColumnExist(tableName, columnName) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultValue string
|
|
||||||
if ss.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
// Some column types in MySQL cannot have defaults, so don't try to configure anything.
|
|
||||||
if mySqlColDefault == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultValue = *mySqlColDefault
|
|
||||||
} else if ss.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
// Postgres doesn't have the same limitation, but preserve the interface.
|
|
||||||
if postgresColDefault == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
tableName = strings.ToLower(tableName)
|
|
||||||
columnName = strings.ToLower(columnName)
|
|
||||||
defaultValue = *postgresColDefault
|
|
||||||
} else {
|
|
||||||
mlog.Fatal("Failed to alter column default because of missing driver")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if defaultValue == "" {
|
|
||||||
defaultValue = "''"
|
|
||||||
}
|
|
||||||
|
|
||||||
query := "ALTER TABLE " + tableName + " ALTER COLUMN " + columnName + " SET DEFAULT " + defaultValue
|
|
||||||
_, err := ss.GetMaster().ExecNoTimeout(query)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to alter column default", mlog.String("table", tableName), mlog.String("column", columnName), mlog.String("default value", defaultValue), mlog.Err(err))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) AlterPrimaryKey(tableName string, columnNames []string) bool {
|
|
||||||
var currentPrimaryKey string
|
|
||||||
var err error
|
|
||||||
// get the current primary key as a comma separated list of columns
|
|
||||||
switch ss.DriverName() {
|
|
||||||
case model.DatabaseDriverMysql:
|
|
||||||
query := `
|
|
||||||
SELECT GROUP_CONCAT(column_name ORDER BY seq_in_index) AS PK
|
|
||||||
FROM
|
|
||||||
information_schema.statistics
|
|
||||||
WHERE
|
|
||||||
table_schema = DATABASE()
|
|
||||||
AND table_name = ?
|
|
||||||
AND index_name = 'PRIMARY'
|
|
||||||
GROUP BY
|
|
||||||
index_name`
|
|
||||||
currentPrimaryKey, err = ss.GetMaster().SelectStr(query, tableName)
|
|
||||||
case model.DatabaseDriverPostgres:
|
|
||||||
query := `
|
|
||||||
SELECT string_agg(a.attname, ',') AS pk
|
|
||||||
FROM
|
|
||||||
pg_constraint AS c
|
|
||||||
CROSS JOIN
|
|
||||||
(SELECT unnest(conkey) FROM pg_constraint WHERE conrelid='` + strings.ToLower(tableName) + `'::REGCLASS AND contype='p') AS cols(colnum)
|
|
||||||
INNER JOIN
|
|
||||||
pg_attribute AS a ON a.attrelid = c.conrelid
|
|
||||||
AND cols.colnum = a.attnum
|
|
||||||
WHERE
|
|
||||||
c.contype = 'p'
|
|
||||||
AND c.conrelid = '` + strings.ToLower(tableName) + `'::REGCLASS`
|
|
||||||
currentPrimaryKey, err = ss.GetMaster().SelectStr(query)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to get current primary key", mlog.String("table", tableName), mlog.Err(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
primaryKey := strings.Join(columnNames, ",")
|
|
||||||
if strings.EqualFold(currentPrimaryKey, primaryKey) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// alter primary key
|
|
||||||
var alterQuery string
|
|
||||||
if ss.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
alterQuery = "ALTER TABLE " + tableName + " DROP PRIMARY KEY, ADD PRIMARY KEY (" + primaryKey + ")"
|
|
||||||
} else if ss.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
alterQuery = "ALTER TABLE " + tableName + " DROP CONSTRAINT " + strings.ToLower(tableName) + "_pkey, ADD PRIMARY KEY (" + strings.ToLower(primaryKey) + ")"
|
|
||||||
}
|
|
||||||
_, err = ss.GetMaster().ExecNoTimeout(alterQuery)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to alter primary key", mlog.String("table", tableName), mlog.Err(err))
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) CreateUniqueIndexIfNotExists(indexName string, tableName string, columnName string) bool {
|
|
||||||
return ss.createIndexIfNotExists(indexName, tableName, []string{columnName}, IndexTypeDefault, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) CreateIndexIfNotExists(indexName string, tableName string, columnName string) bool {
|
|
||||||
return ss.createIndexIfNotExists(indexName, tableName, []string{columnName}, IndexTypeDefault, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) CreateCompositeIndexIfNotExists(indexName string, tableName string, columnNames []string) bool {
|
|
||||||
return ss.createIndexIfNotExists(indexName, tableName, columnNames, IndexTypeDefault, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) CreateUniqueCompositeIndexIfNotExists(indexName string, tableName string, columnNames []string) bool {
|
|
||||||
return ss.createIndexIfNotExists(indexName, tableName, columnNames, IndexTypeDefault, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) CreateFullTextIndexIfNotExists(indexName string, tableName string, columnName string) bool {
|
|
||||||
return ss.createIndexIfNotExists(indexName, tableName, []string{columnName}, IndexTypeFullText, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) CreateFullTextFuncIndexIfNotExists(indexName string, tableName string, function string) bool {
|
|
||||||
return ss.createIndexIfNotExists(indexName, tableName, []string{function}, IndexTypeFullTextFunc, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) createIndexIfNotExists(indexName string, tableName string, columnNames []string, indexType string, unique bool) bool {
|
|
||||||
|
|
||||||
uniqueStr := ""
|
|
||||||
if unique {
|
|
||||||
uniqueStr = "UNIQUE "
|
|
||||||
}
|
|
||||||
|
|
||||||
if ss.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
_, errExists := ss.GetMaster().SelectStr("SELECT $1::regclass", indexName)
|
|
||||||
// It should fail if the index does not exist
|
|
||||||
if errExists == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
query := ""
|
|
||||||
if indexType == IndexTypeFullText {
|
|
||||||
if len(columnNames) != 1 {
|
|
||||||
mlog.Fatal("Unable to create multi column full text index")
|
|
||||||
}
|
|
||||||
columnName := columnNames[0]
|
|
||||||
postgresColumnNames := convertMySQLFullTextColumnsToPostgres(columnName)
|
|
||||||
query = "CREATE INDEX " + indexName + " ON " + tableName + " USING gin(to_tsvector('english', " + postgresColumnNames + "))"
|
|
||||||
} else if indexType == IndexTypeFullTextFunc {
|
|
||||||
if len(columnNames) != 1 {
|
|
||||||
mlog.Fatal("Unable to create multi column full text index")
|
|
||||||
}
|
|
||||||
columnName := columnNames[0]
|
|
||||||
query = "CREATE INDEX " + indexName + " ON " + tableName + " USING gin(to_tsvector('english', " + columnName + "))"
|
|
||||||
} else {
|
|
||||||
query = "CREATE " + uniqueStr + "INDEX " + indexName + " ON " + tableName + " (" + strings.Join(columnNames, ", ") + ")"
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := ss.GetMaster().ExecNoTimeout(query)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to create index", mlog.Err(errExists), mlog.Err(err))
|
|
||||||
}
|
|
||||||
} else if ss.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
|
|
||||||
count, err := ss.GetMaster().SelectInt("SELECT COUNT(0) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() and table_name = ? AND index_name = ?", tableName, indexName)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to check index", mlog.Err(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
if count > 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fullTextIndex := ""
|
|
||||||
if indexType == IndexTypeFullText {
|
|
||||||
fullTextIndex = " FULLTEXT "
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ss.GetMaster().ExecNoTimeout("CREATE " + uniqueStr + fullTextIndex + " INDEX " + indexName + " ON " + tableName + " (" + strings.Join(columnNames, ", ") + ")")
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to create index", mlog.String("table", tableName), mlog.String("index_name", indexName), mlog.Err(err))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mlog.Fatal("Failed to create index because of missing driver")
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) CreateForeignKeyIfNotExists(
|
|
||||||
tableName, columnName, refTableName, refColumnName string,
|
|
||||||
onDeleteCascade bool,
|
|
||||||
) (err error) {
|
|
||||||
deleteClause := ""
|
|
||||||
if onDeleteCascade {
|
|
||||||
deleteClause = "ON DELETE CASCADE"
|
|
||||||
}
|
|
||||||
constraintName := "FK_" + tableName + "_" + refTableName
|
|
||||||
sQuery := `
|
|
||||||
ALTER TABLE ` + tableName + `
|
|
||||||
ADD CONSTRAINT ` + constraintName + `
|
|
||||||
FOREIGN KEY (` + columnName + `) REFERENCES ` + refTableName + ` (` + refColumnName + `)
|
|
||||||
` + deleteClause + `;`
|
|
||||||
_, err = ss.GetMaster().ExecNoTimeout(sQuery)
|
|
||||||
if IsConstraintAlreadyExistsError(err) {
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
mlog.Warn("Could not create foreign key: " + err.Error())
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ss *SqlStore) RemoveIndexIfExists(indexName string, tableName string) bool {
|
|
||||||
|
|
||||||
if ss.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
_, err := ss.GetMaster().SelectStr("SELECT $1::regclass", indexName)
|
|
||||||
// It should fail if the index does not exist
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ss.GetMaster().ExecNoTimeout("DROP INDEX " + indexName)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to remove index", mlog.Err(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
} else if ss.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
|
|
||||||
count, err := ss.GetMaster().SelectInt("SELECT COUNT(0) AS index_exists FROM information_schema.statistics WHERE TABLE_SCHEMA = DATABASE() and table_name = ? AND index_name = ?", tableName, indexName)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to check index", mlog.Err(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
if count <= 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ss.GetMaster().ExecNoTimeout("DROP INDEX " + indexName + " ON " + tableName)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal("Failed to remove index", mlog.Err(err))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mlog.Fatal("Failed to create index because of missing driver")
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsConstraintAlreadyExistsError(err error) bool {
|
func IsConstraintAlreadyExistsError(err error) bool {
|
||||||
switch dbErr := err.(type) {
|
switch dbErr := err.(type) {
|
||||||
case *pq.Error:
|
case *pq.Error:
|
||||||
@@ -1420,9 +962,6 @@ func (ss *SqlStore) GetLicense() *model.License {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SqlStore) migrate(direction migrationDirection) error {
|
func (ss *SqlStore) migrate(direction migrationDirection) error {
|
||||||
// we need to compute missing migrations (if any) and manually save unnecessary migrations
|
|
||||||
// to the db_migrations table. So that previous migrations won't get applied
|
|
||||||
|
|
||||||
var assetNamesForDriver []string
|
var assetNamesForDriver []string
|
||||||
for _, assetName := range migrations.AssetNames() {
|
for _, assetName := range migrations.AssetNames() {
|
||||||
if strings.HasPrefix(assetName, ss.DriverName()) {
|
if strings.HasPrefix(assetName, ss.DriverName()) {
|
||||||
|
|||||||
@@ -784,138 +784,3 @@ func TestMySQLReadTimeout(t *testing.T) {
|
|||||||
_, err = store.GetMaster().ExecNoTimeout(`SELECT SLEEP(3)`)
|
_, err = store.GetMaster().ExecNoTimeout(`SELECT SLEEP(3)`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveIndexIfExists(t *testing.T) {
|
|
||||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
|
||||||
sqlStore := ss.(*SqlStore)
|
|
||||||
|
|
||||||
_, err := sqlStore.GetMaster().ExecNoTimeout(`CREATE INDEX idx_posts_create_at ON Posts (CreateAt)`)
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
ok := sqlStore.RemoveIndexIfExists("idx_posts_create_at", "Posts")
|
|
||||||
require.True(t, ok)
|
|
||||||
|
|
||||||
ok = sqlStore.RemoveIndexIfExists("idx_posts_create_at", "Posts")
|
|
||||||
require.False(t, ok)
|
|
||||||
|
|
||||||
_, err = sqlStore.GetMaster().ExecNoTimeout(`CREATE INDEX idx_posts_create_at ON Posts (CreateAt)`)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
ok = sqlStore.RemoveIndexIfExists("idx_posts_create_at", "Posts")
|
|
||||||
require.True(t, ok)
|
|
||||||
|
|
||||||
ok = sqlStore.RemoveIndexIfExists("idx_posts_create_at", "Posts")
|
|
||||||
require.False(t, ok)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAlterDefaultIfColumnExists(t *testing.T) {
|
|
||||||
StoreTest(t, func(t *testing.T, ss store.Store) {
|
|
||||||
var query string
|
|
||||||
def := new(string)
|
|
||||||
sqlStore := ss.(*SqlStore)
|
|
||||||
|
|
||||||
t.Run("non existent table", func(t *testing.T) {
|
|
||||||
ok := sqlStore.AlterDefaultIfColumnExists("NotExistent", "NotExistent", nil, nil)
|
|
||||||
require.False(t, ok)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("non existent column", func(t *testing.T) {
|
|
||||||
ok := sqlStore.AlterDefaultIfColumnExists("Posts", "NotExistent", nil, nil)
|
|
||||||
require.False(t, ok)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("empty string", func(t *testing.T) {
|
|
||||||
ok := sqlStore.AlterDefaultIfColumnExists("Posts", "Id", model.NewString(""), model.NewString(""))
|
|
||||||
require.True(t, ok)
|
|
||||||
|
|
||||||
if sqlStore.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
query = `SELECT column_default
|
|
||||||
FROM information_schema.columns
|
|
||||||
WHERE table_schema = DATABASE()
|
|
||||||
AND table_name = 'Posts'
|
|
||||||
AND column_name = 'Id'`
|
|
||||||
} else if sqlStore.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
query = `SELECT column_default
|
|
||||||
FROM information_schema.columns
|
|
||||||
WHERE table_name = 'posts'
|
|
||||||
AND column_name = 'id'`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := sqlStore.GetMaster().SelectOne(&def, query)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, def)
|
|
||||||
if sqlStore.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
require.Equal(t, "", *def)
|
|
||||||
} else if sqlStore.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
require.Equal(t, "''::character varying", *def)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("nil input", func(t *testing.T) {
|
|
||||||
ok := sqlStore.AlterDefaultIfColumnExists("Posts", "Id", nil, nil)
|
|
||||||
require.True(t, ok)
|
|
||||||
|
|
||||||
err := sqlStore.GetMaster().SelectOne(&def, query)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, def)
|
|
||||||
if sqlStore.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
require.Equal(t, "", *def)
|
|
||||||
} else if sqlStore.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
require.Equal(t, "''::character varying", *def)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("remove", func(t *testing.T) {
|
|
||||||
ok := sqlStore.RemoveDefaultIfColumnExists("Posts", "Id")
|
|
||||||
require.True(t, ok)
|
|
||||||
|
|
||||||
err := sqlStore.GetMaster().SelectOne(&def, query)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Nil(t, def)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("string default", func(t *testing.T) {
|
|
||||||
ok := sqlStore.AlterDefaultIfColumnExists("Posts", "Id", model.NewString("'test'"), model.NewString("'test'"))
|
|
||||||
require.True(t, ok)
|
|
||||||
|
|
||||||
err := sqlStore.GetMaster().SelectOne(&def, query)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, def)
|
|
||||||
if sqlStore.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
require.Equal(t, "test", *def)
|
|
||||||
} else if sqlStore.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
require.Equal(t, "'test'::character varying", *def)
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = sqlStore.RemoveDefaultIfColumnExists("Posts", "Id")
|
|
||||||
require.True(t, ok)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("int default", func(t *testing.T) {
|
|
||||||
ok := sqlStore.AlterDefaultIfColumnExists("Posts", "UpdateAt", model.NewString("0"), model.NewString("0"))
|
|
||||||
require.True(t, ok)
|
|
||||||
|
|
||||||
if sqlStore.DriverName() == model.DatabaseDriverMysql {
|
|
||||||
query = `SELECT column_default
|
|
||||||
FROM information_schema.columns
|
|
||||||
WHERE table_schema = DATABASE()
|
|
||||||
AND table_name = 'Posts'
|
|
||||||
AND column_name = 'UpdateAt'`
|
|
||||||
} else if sqlStore.DriverName() == model.DatabaseDriverPostgres {
|
|
||||||
query = `SELECT column_default
|
|
||||||
FROM information_schema.columns
|
|
||||||
WHERE table_name = 'posts'
|
|
||||||
AND column_name = 'updateat'`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := sqlStore.GetMaster().SelectOne(&def, query)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, def)
|
|
||||||
require.Equal(t, "0", *def)
|
|
||||||
|
|
||||||
ok = sqlStore.RemoveDefaultIfColumnExists("Posts", "UpdateAt")
|
|
||||||
require.True(t, ok)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -34,9 +34,6 @@ func newSqlSystemStore(sqlStore *SqlStore) store.SystemStore {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SqlSystemStore) createIndexesIfNotExists() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s SqlSystemStore) Save(system *model.System) error {
|
func (s SqlSystemStore) Save(system *model.System) error {
|
||||||
query := "INSERT INTO Systems (Name, Value) VALUES (:Name, :Value)"
|
query := "INSERT INTO Systems (Name, Value) VALUES (:Name, :Value)"
|
||||||
if _, err := s.GetMasterX().NamedExec(query, system); err != nil {
|
if _, err := s.GetMasterX().NamedExec(query, system); err != nil {
|
||||||
|
|||||||
@@ -28,9 +28,6 @@ func newSqlUserTermsOfServiceStore(sqlStore *SqlStore) store.UserTermsOfServiceS
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SqlUserTermsOfServiceStore) createIndexesIfNotExists() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s SqlUserTermsOfServiceStore) GetByUser(userId string) (*model.UserTermsOfService, error) {
|
func (s SqlUserTermsOfServiceStore) GetByUser(userId string) (*model.UserTermsOfService, error) {
|
||||||
var userTermsOfService model.UserTermsOfService
|
var userTermsOfService model.UserTermsOfService
|
||||||
query := `
|
query := `
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user