<commit_before>﻿using System.Linq;
using System.Text;

namespace Gigobyte.Daterpillar.Transformation.Template
{
    public sealed class MySqlTemplate : ITemplate
    {
        public MySqlTemplate() : this(MySqlTemplateSettings.Default, new MySqlTypeNameResolver())
        {
        }

        public MySqlTemplate(bool dropDatabase) : this(MySqlTemplateSettings.Default, new MySqlTypeNameResolver())
        {
            _settings.DropDatabaseIfExist = dropDatabase;
        }

        public MySqlTemplate(ITypeNameResolver nameResolver) : this(MySqlTemplateSettings.Default, nameResolver)
        {
        }

        public MySqlTemplate(MySqlTemplateSettings settings) : this(settings, new MySqlTypeNameResolver())
        {
        }

        public MySqlTemplate(MySqlTemplateSettings settings, ITypeNameResolver nameResolver)
        {
            _settings = settings;
            _nameResolver = nameResolver;
        }

        public string Transform(Schema schema)
        {
            _text.Clear();

            if (_settings.DropDatabaseIfExist)
            {
                _text.AppendLine($"DROP DATABASE IF EXISTS `{schema.Name}`;");
            }

            _text.AppendLine($"CREATE DATABASE IF NOT EXISTS `{schema.Name}`;");
            _text.AppendLine($"USE `{schema.Name}`;");
            _text.AppendLine();

            foreach (var table in schema.Tables)
            {
                Transform(table);
            }

            _text.AppendLine(schema.Script);
            return _text.ToString().Trim();
        }

        #region Private Members

        private MySqlTemplateSettings _settings;
        private ITypeNameResolver _nameResolver;
        private StringBuilder _text = new StringBuilder();

        private void Transform(Table table)
        {
            AppendComment(table);
            _text.AppendLine($"CREATE TABLE IF NOT EXISTS `{table.Name}`");
            _text.AppendLine("(");
            foreach (var column in table.Columns)
            {
                Transform(column);
            }

            foreach (var index in table.Indexes.Where(x => x.IndexType == IndexType.Primary))
            {
                _text.AppendLine($"\tPRIMARY KEY ({string.Join(", ", index.Columns.Select(x => $"`{x.Name}` {x.Order}"))}),");
            }

            foreach (var foreignKey in table.ForeignKeys)
            {
                Transform(foreignKey);
            }

            _text.RemoveLastComma();
            _text.AppendLine(");");
            _text.AppendLine();

            bool hasIndex = false;
            foreach (var index in table.Indexes.Where(x => x.IndexType == IndexType.Index))
            {
                hasIndex = true;
                Transform(index, table.Name);
            }
            if (hasIndex) _text.AppendLine();
        }

        private void Transform(Column column)
        {
            string dataType = _nameResolver.GetName(column.DataType);
            string modifiers = string.Join(" ", column.Modifiers);
            string autoIncrement = column.AutoIncrement ? " AUTO_INCREMENT " : " ";

            _text.AppendLine($"\t`{column.Name}` {dataType} {modifiers}{autoIncrement}COMMENT '{column.Comment?.Replace("'", "''")}',");
        }

        private void Transform(ForeignKey foreignKey)
        {
            _text.AppendLine($"\tFOREIGN KEY (`{foreignKey.LocalColumn}`) REFERENCES `{foreignKey.ForeignTable}`(`{foreignKey.ForeignColumn}`) ON UPDATE {foreignKey.OnUpdate} ON DELETE {foreignKey.OnDelete},");
        }

        private void Transform(Index index, string tableName)
        {
            string unique = index.Unique ? " UNIQUE " : " ";
            string columns = string.Join(", ", index.Columns.Select(x => $"`{x.Name}` {x.Order}"));
            tableName = (string.IsNullOrEmpty(index.Name) ? tableName : tableName);

            _text.AppendLine($"CREATE{unique}INDEX `{index.Name}` ON `{tableName}` ({columns});");
        }

        private void AppendComment(Table table)
        {
            if (_settings.CommentsEnabled)
            {
                if (string.IsNullOrWhiteSpace(table.Comment))
                {
                    _text.AppendLine("-- ------------------------------");
                    _text.AppendLine($"-- {table.Name.ToUpper()} TABLE");
                    _text.AppendLine("-- ------------------------------");
                }<commit_msg>Add default index name if null.<commit_after>﻿using System.Linq;
using System.Text;

namespace Gigobyte.Daterpillar.Transformation.Template
{
    public sealed class MySqlTemplate : ITemplate
    {
        public MySqlTemplate() : this(MySqlTemplateSettings.Default, new MySqlTypeNameResolver())
        {
        }

        public MySqlTemplate(bool dropDatabase) : this(MySqlTemplateSettings.Default, new MySqlTypeNameResolver())
        {
            _settings.DropDatabaseIfExist = dropDatabase;
        }

        public MySqlTemplate(ITypeNameResolver nameResolver) : this(MySqlTemplateSettings.Default, nameResolver)
        {
        }

        public MySqlTemplate(MySqlTemplateSettings settings) : this(settings, new MySqlTypeNameResolver())
        {
        }

        public MySqlTemplate(MySqlTemplateSettings settings, ITypeNameResolver nameResolver)
        {
            _settings = settings;
            _nameResolver = nameResolver;
        }

        public string Transform(Schema schema)
        {
            _text.Clear();

            if (_settings.DropDatabaseIfExist)
            {
                _text.AppendLine($"DROP DATABASE IF EXISTS `{schema.Name}`;");
            }

            _text.AppendLine($"CREATE DATABASE IF NOT EXISTS `{schema.Name}`;");
            _text.AppendLine($"USE `{schema.Name}`;");
            _text.AppendLine();

            foreach (var table in schema.Tables)
            {
                Transform(table);
            }

            _text.AppendLine(schema.Script);
            return _text.ToString().Trim();
        }

        #region Private Members

        private int _seed = 1;
        private MySqlTemplateSettings _settings;
        private ITypeNameResolver _nameResolver;
        private StringBuilder _text = new StringBuilder();

        private void Transform(Table table)
        {
            AppendComment(table);
            _text.AppendLine($"CREATE TABLE IF NOT EXISTS `{table.Name}`");
            _text.AppendLine("(");
            foreach (var column in table.Columns)
            {
                Transform(column);
            }

            foreach (var index in table.Indexes.Where(x => x.IndexType == IndexType.Primary))
            {
                _text.AppendLine($"\tPRIMARY KEY ({string.Join(", ", index.Columns.Select(x => $"`{x.Name}` {x.Order}"))}),");
            }

            foreach (var foreignKey in table.ForeignKeys)
            {
                Transform(foreignKey);
            }

            _text.RemoveLastComma();
            _text.AppendLine(");");
            _text.AppendLine();

            bool hasIndex = false;
            foreach (var index in table.Indexes.Where(x => x.IndexType == IndexType.Index))
            {
                hasIndex = true;
                Transform(index, table.Name);
            }
            if (hasIndex) _text.AppendLine();
        }

        private void Transform(Column column)
        {
            string dataType = _nameResolver.GetName(column.DataType);
            string modifiers = string.Join(" ", column.Modifiers);
            string autoIncrement = column.AutoIncrement ? " AUTO_INCREMENT " : " ";

            _text.AppendLine($"\t`{column.Name}` {dataType} {modifiers}{autoIncrement}COMMENT '{column.Comment?.Replace("'", "''")}',");
        }

        private void Transform(ForeignKey foreignKey)
        {
            _text.AppendLine($"\tFOREIGN KEY (`{foreignKey.LocalColumn}`) REFERENCES `{foreignKey.ForeignTable}`(`{foreignKey.ForeignColumn}`) ON UPDATE {foreignKey.OnUpdate} ON DELETE {foreignKey.OnDelete},");
        }

        private void Transform(Index index, string tableName)
        {
            string unique = index.Unique ? " UNIQUE " : " ";
            string columns = string.Join(", ", index.Columns.Select(x => $"`{x.Name}` {x.Order}"));
            tableName = (string.IsNullOrEmpty(index.Name) ? tableName : tableName);
            index.Name = (string.IsNullOrEmpty(index.Name) ? $"{tableName}_idx{_seed++}" : index.Name);

            _text.AppendLine($"CREATE{unique}INDEX `{index.Name}` ON `{tableName}` ({columns});");
        }

        private void AppendComment(Table table)
        {
            if (_settings.CommentsEnabled)
            {
                if (string.IsNullOrWhiteSpace(table.Comment))
                {
                    _text.AppendLine("-- ------------------------------");
                    _text.AppendLine($"-- {table.Name.ToUpper()} TABLE");
                    _text.AppendLine("-- ------------------------------");
                }
{'fraction_non_alphanumeric': 0.1294627961294628, 'fraction_numerical': 0.00011122233344455567, 'mean_word_length': 1.8848251523901187, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7390308', 'n_tokens_mistral': 2403, 'n_tokens_neox': 2315, 'n_words': 447}