Beispiel #1
0
        /// <summary>
        /// Provides an opportunity for derived implementations to also update the schema
        /// </summary>
        /// <param name="connection">Connection to the database</param>
        /// <param name="table">Name of the table to create schema modifications for</param>
        protected override void AdditionalSchemaModifications(IDbConnection connection, TableName table)
        {
            // Use the current database prefix if one is not provided
            var schema = table.Schema;

            if (string.IsNullOrWhiteSpace(schema))
            {
                schema = connection.Database;
            }
            var tableName = table.Name;

            // If any of our columns do not exist, run the schema upgrade
            var columns = connection.GetColumns(schema, tableName);
            var indexes = connection.GetIndexes(schema, tableName);

            if (!columns.ContainsKey("leased_until") ||
                !columns.ContainsKey("leased_by") ||
                !columns.ContainsKey("leased_at") ||
                !indexes.ContainsKey("idx_receive_lease"))
            {
                connection.ExecuteCommands($@"
                    {MySqlMagic.CreateColumnIfNotExistsSql(schema, tableName, "leased_until", "datetime(6) null")}
                    ----
                    {MySqlMagic.CreateColumnIfNotExistsSql(schema, tableName, "leased_by", $"varchar({LeasedByColumnSize}) null")}
                    ----
                    {MySqlMagic.CreateColumnIfNotExistsSql(schema, tableName, "leased_at", "datetime(6) null")}
                    ----
                    {MySqlMagic.DropIndexIfExistsSql(schema, tableName, "idx_receive")}
                    ----
                    {MySqlMagic.CreateIndexIfNotExistsSql(schema, tableName, "idx_receive_lease", "visible, expiration, processing, leased_until")}");
            }
        }
Beispiel #2
0
        public void CreateAndDropColumnAndIndexSql()
        {
            // Drop all tables first
            MySqlTestHelper.DropAllTables();

            // Open a connection
            using var connection = new MySqlConnection(MySqlTestHelper.ConnectionString);
            connection.Open();

            // Create a table to test with
            var          schema    = connection.Database;
            const string tableName = "tableName";

            CreateTables(connection, tableName);

            // This column should already exist, so it should do nothing
            var sql     = MySqlMagic.CreateColumnIfNotExistsSql(schema, tableName, "col1", "varchar(255) null");
            var command = connection.CreateCommand();

            command.CommandText = sql;
            var result = command.ExecuteScalar() as string;

            Assert.AreEqual("column exists", result);

            // Now create a new column
            sql                 = MySqlMagic.CreateColumnIfNotExistsSql(schema, tableName, "date1", "datetime(6) null");
            command             = connection.CreateCommand();
            command.CommandText = sql;
            result              = command.ExecuteScalar() as string;
            Assert.AreEqual(null, result);
            var columns = connection.GetColumns("", tableName);

            Assert.AreEqual(3, columns.Count);
            Assert.AreEqual("bigint", columns["id1"]);
            Assert.AreEqual("mediumblob", columns["col1"]);
            Assert.AreEqual("datetime", columns["date1"]);

            // Now lets add an index
            sql                 = MySqlMagic.CreateIndexIfNotExistsSql(schema, tableName, "idx1", "col1(10), date1");
            command             = connection.CreateCommand();
            command.CommandText = sql;
            result              = command.ExecuteScalar() as string;
            Assert.AreEqual(null, result);

            // Check the index got added
            var indexes = connection.GetIndexes("", tableName);

            Assert.AreEqual(2, indexes.Count);
            Assert.AreEqual("id1", indexes["PRIMARY"]);
            Assert.AreEqual("col1,date1", indexes["idx1"]);

            // Try again and it should exist
            sql                 = MySqlMagic.CreateIndexIfNotExistsSql(schema, tableName, "idx1", "col1(10), date1");
            command             = connection.CreateCommand();
            command.CommandText = sql;
            result              = command.ExecuteScalar() as string;
            Assert.AreEqual("index exists", result);

            // Now drop the index
            sql                 = MySqlMagic.DropIndexIfExistsSql(schema, tableName, "idx1");
            command             = connection.CreateCommand();
            command.CommandText = sql;
            result              = command.ExecuteScalar() as string;
            Assert.AreEqual(null, result);

            // Check the index got removed
            indexes = connection.GetIndexes("", tableName);
            Assert.AreEqual(1, indexes.Count);
            Assert.AreEqual("id1", indexes["PRIMARY"]);

            // Try again and it should not exist
            sql                 = MySqlMagic.DropIndexIfExistsSql(schema, tableName, "idx1");
            command             = connection.CreateCommand();
            command.CommandText = sql;
            result              = command.ExecuteScalar() as string;
            Assert.AreEqual("index does not exist", result);

            // Now drop the column
            sql                 = MySqlMagic.DropColumnIfExistsSql(schema, tableName, "date1");
            command             = connection.CreateCommand();
            command.CommandText = sql;
            command.CommandText = sql;
            result              = command.ExecuteScalar() as string;
            Assert.AreEqual(null, result);
            columns = connection.GetColumns("", tableName);
            Assert.AreEqual(2, columns.Count);
            Assert.AreEqual("bigint", columns["id1"]);
            Assert.AreEqual("mediumblob", columns["col1"]);

            // Now drop the column again and nothing happens
            sql                 = MySqlMagic.DropColumnIfExistsSql(schema, tableName, "date1");
            command             = connection.CreateCommand();
            command.CommandText = sql;
            command.CommandText = sql;
            result              = command.ExecuteScalar() as string;
            Assert.AreEqual("column does not exist", result);
        }
        void InnerEnsureTableIsCreated(TableName table)
        {
            using (var connection = _connectionProvider.GetConnection())
            {
                var tableNames = connection.GetTableNames();
                if (tableNames.Contains(table))
                {
                    // Use the current database prefix if one is not provided
                    var schema = table.Schema;
                    if (string.IsNullOrWhiteSpace(schema))
                    {
                        schema = connection.Database;
                    }
                    var tableName = table.Name;

                    // Check if the schema needs to be upgraded
                    var columns = connection.GetColumns(schema, tableName);
                    if (!columns.ContainsKey("processing") &&
                        columns.ContainsKey("ordering_key") &&
                        columns.ContainsKey("leased_until") &&
                        columns.ContainsKey("leased_by") &&
                        columns.ContainsKey("leased_for") &&
                        columns.ContainsKey("leased_at"))
                    {
                        _log.Info("Database already contains a table named {tableName} - will not create anything", table.QualifiedName);
                    }
                    else
                    {
                        connection.ExecuteCommands($@"
                            {MySqlMagic.DropColumnIfExistsSql(schema, tableName, "processing")}
                            ----
                            {MySqlMagic.CreateColumnIfNotExistsSql(schema, tableName, "ordering_key", $"varchar({OrderingKeyColumnSize}) NULL after `visible`")}
                            ----
                            {MySqlMagic.CreateColumnIfNotExistsSql(schema, tableName, "leased_until", "datetime(6) NULL after `body`")}
                            ----
                            {MySqlMagic.CreateColumnIfNotExistsSql(schema, tableName, "leased_by", $"varchar({LeasedByColumnSize}) NULL after `leased_until`")}
                            ----
                            {MySqlMagic.CreateColumnIfNotExistsSql(schema, tableName, "leased_for", $"varchar({OrderingKeyColumnSize}) NULL after `leased_by`")}
                            ----
                            {MySqlMagic.CreateColumnIfNotExistsSql(schema, tableName, "leased_at", "datetime(6) NULL after `leased_for`")}
                            ----
                            {MySqlMagic.DropIndexIfExistsSql(schema, tableName, "idx_receive")}
                            ----
                            {MySqlMagic.DropIndexIfExistsSql(schema, tableName, "idx_receive_lease")}
                            ----
                            {MySqlMagic.CreateIndexIfNotExistsSql(schema, tableName, "idx_receive", "`priority` DESC, `visible` ASC, `id` ASC, `expiration` ASC, `leased_until` DESC, `leased_for` ASC")}
                            ----
                            {MySqlMagic.CreateIndexIfNotExistsSql(schema, tableName, "idx_leased_for", "`leased_for`")}");
                    }
                }
                else
                {
                    _log.Info("Table {tableName} does not exist - it will be created now", table.QualifiedName);

                    connection.ExecuteCommands($@"
                        CREATE TABLE {table.QualifiedName} (
                            `id` BIGINT NOT NULL AUTO_INCREMENT,
                            `priority` INT NOT NULL,
                            `expiration` DATETIME(6) NOT NULL,
                            `visible` DATETIME(6) NOT NULL,
                            `ordering_key` varchar({OrderingKeyColumnSize}) NULL,
                            `headers` LONGBLOB NOT NULL,
                            `body` LONGBLOB NOT NULL,
                            `leased_until` datetime(6) NULL,
                            `leased_by` varchar({LeasedByColumnSize}) NULL,
                            `leased_for` varchar({OrderingKeyColumnSize}) NULL,
                            `leased_at` datetime(6) NULL,
                            PRIMARY KEY (`id`)
                        );
                        ----
                        CREATE INDEX `idx_receive` ON {table.QualifiedName} (
                            `priority` DESC,
                            `visible` ASC,
                            `id` ASC,
                            `expiration` ASC,
                            `leased_until` DESC,
                            `leased_for` ASC
                        );
                        ----
                        CREATE INDEX `idx_leased_for` ON {table.QualifiedName} (
                            `leased_for`
                        );
                        ----
                        CREATE INDEX `idx_expiration` ON {table.QualifiedName} (
                            `expiration`
                        );");
                }

                connection.Complete();
            }
        }