Added missing FK constraint on scheduled_queries
This commit is contained in:
+15
-6
@@ -11,11 +11,12 @@ func init() {
|
||||
}
|
||||
|
||||
func Up_20230706141219(tx *sql.Tx) error {
|
||||
// If we want to drop the uniq constraint on queries.name, we first need to remove this
|
||||
// constraint on scheduled_queries, due to a FK constraint scheduled_queries (query_name) =>
|
||||
// queries (name).
|
||||
// Drop FK constraint based on queries (name) - since the uniqueness constraint on the queries
|
||||
// table changed.
|
||||
if _, err := tx.Exec(`
|
||||
ALTER TABLE scheduled_queries DROP FOREIGN KEY scheduled_queries_query_name;
|
||||
ALTER TABLE scheduled_queries
|
||||
ADD team_id_char CHAR(10) DEFAULT '',
|
||||
DROP FOREIGN KEY scheduled_queries_query_name;
|
||||
`); err != nil {
|
||||
return errors.Wrap(err, "removing FK on scheduled_queries")
|
||||
}
|
||||
@@ -26,7 +27,7 @@ func Up_20230706141219(tx *sql.Tx) error {
|
||||
DROP INDEX constraint_query_name_unique,
|
||||
|
||||
ADD team_id INT(10) UNSIGNED DEFAULT NULL,
|
||||
ADD team_id_char CHAR(10) DEFAULT '',
|
||||
ADD team_id_char CHAR(10) DEFAULT '' NOT NULL,
|
||||
|
||||
ADD platform VARCHAR(255) DEFAULT '' NOT NULL,
|
||||
ADD min_osquery_version VARCHAR(255) DEFAULT '' NOT NULL,
|
||||
@@ -35,12 +36,20 @@ func Up_20230706141219(tx *sql.Tx) error {
|
||||
ADD automations_enabled TINYINT(1) UNSIGNED DEFAULT 0 NOT NULL,
|
||||
ADD logging_type VARCHAR(255) DEFAULT 'snapshot' NOT NULL,
|
||||
|
||||
ADD FOREIGN KEY fk_queries_team_id (team_id) REFERENCES teams (id) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
ADD FOREIGN KEY fk_queries_team_id (team_id) REFERENCES teams (id) ON DELETE CASCADE,
|
||||
ADD UNIQUE INDEX idx_team_id_name_unq (team_id_char, name);
|
||||
`); err != nil {
|
||||
return errors.Wrap(err, "updating queries schema")
|
||||
}
|
||||
|
||||
// Add new FK constraint to make sure all scheduled_queries exists as 'global' queries.
|
||||
if _, err := tx.Exec(`
|
||||
ALTER TABLE scheduled_queries
|
||||
ADD FOREIGN KEY fk_scheduled_queries_queries (team_id_char, query_name) REFERENCES queries (team_id_char, name);
|
||||
`); err != nil {
|
||||
return errors.Wrap(err, "adding new FK on scheduled_queries")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1041,6 +1041,20 @@ func generateMysqlConnectionString(conf config.MysqlConfig) string {
|
||||
return dsn
|
||||
}
|
||||
|
||||
// isForeignKeyError checks if the provided error is a MySQL child foreign key
|
||||
// error (Error #1452)
|
||||
func isChildForeignKeyError(err error) bool {
|
||||
err = ctxerr.Cause(err)
|
||||
mysqlErr, ok := err.(*mysql.MySQLError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
// https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html#error_er_no_referenced_row_2
|
||||
const ER_NO_REFERENCED_ROW_2 = 1452
|
||||
return mysqlErr.Number == ER_NO_REFERENCED_ROW_2
|
||||
}
|
||||
|
||||
type patternReplacer func(string) string
|
||||
|
||||
// likePattern returns a pattern to match m with LIKE.
|
||||
|
||||
@@ -75,22 +75,7 @@ func applyPackSpecDB(ctx context.Context, tx sqlx.ExtContext, spec *fleet.PackSp
|
||||
if q.Name == "" {
|
||||
q.Name = q.QueryName
|
||||
}
|
||||
|
||||
// Check if query exists ... we have to do this manually because the FK
|
||||
// constraint was removed as part of the work required for combining queries and schedules
|
||||
var count int
|
||||
if err := tx.QueryRowxContext(
|
||||
ctx,
|
||||
`SELECT COUNT(1) FROM queries WHERE team_id_char = '' AND name = ?`,
|
||||
q.QueryName,
|
||||
).Scan(&count); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "checking if query exists")
|
||||
}
|
||||
if count == 0 {
|
||||
return ctxerr.Errorf(ctx, "cannot schedule unknown query '%s'", q.QueryName)
|
||||
}
|
||||
|
||||
if _, err := tx.ExecContext(ctx, query,
|
||||
_, err := tx.ExecContext(ctx, query,
|
||||
packID,
|
||||
q.QueryName,
|
||||
q.Name,
|
||||
@@ -102,7 +87,11 @@ func applyPackSpecDB(ctx context.Context, tx sqlx.ExtContext, spec *fleet.PackSp
|
||||
q.Platform,
|
||||
q.Version,
|
||||
q.Denylist,
|
||||
); err != nil {
|
||||
)
|
||||
switch {
|
||||
case isChildForeignKeyError(err):
|
||||
return ctxerr.Errorf(ctx, "cannot schedule unknown query '%s'", q.QueryName)
|
||||
case err != nil:
|
||||
return ctxerr.Wrapf(ctx, err, "adding query %s referencing %s", q.Name, q.QueryName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1018,7 +1018,7 @@ CREATE TABLE `queries` (
|
||||
`author_id` int(10) unsigned DEFAULT NULL,
|
||||
`observer_can_run` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`team_id` int(10) unsigned DEFAULT NULL,
|
||||
`team_id_char` char(10) COLLATE utf8mb4_unicode_ci DEFAULT '',
|
||||
`team_id_char` char(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`platform` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`min_osquery_version` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`schedule_interval` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
@@ -1029,7 +1029,7 @@ CREATE TABLE `queries` (
|
||||
KEY `author_id` (`author_id`),
|
||||
KEY `fk_queries_team_id` (`team_id`),
|
||||
CONSTRAINT `queries_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
||||
CONSTRAINT `queries_ibfk_2` FOREIGN KEY (`team_id`) REFERENCES `teams` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
CONSTRAINT `queries_ibfk_2` FOREIGN KEY (`team_id`) REFERENCES `teams` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
@@ -1073,10 +1073,13 @@ CREATE TABLE `scheduled_queries` (
|
||||
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`description` varchar(1023) COLLATE utf8mb4_unicode_ci DEFAULT '',
|
||||
`denylist` tinyint(1) DEFAULT NULL,
|
||||
`team_id_char` char(10) COLLATE utf8mb4_unicode_ci DEFAULT '',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `unique_names_in_packs` (`name`,`pack_id`),
|
||||
KEY `scheduled_queries_pack_id` (`pack_id`),
|
||||
KEY `scheduled_queries_query_name` (`query_name`),
|
||||
KEY `fk_scheduled_queries_queries` (`team_id_char`,`query_name`),
|
||||
CONSTRAINT `scheduled_queries_ibfk_1` FOREIGN KEY (`team_id_char`, `query_name`) REFERENCES `queries` (`team_id_char`, `name`),
|
||||
CONSTRAINT `scheduled_queries_pack_id` FOREIGN KEY (`pack_id`) REFERENCES `packs` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
Reference in New Issue
Block a user