<commit_before>module ActiveRecord
  module ConnectionAdapters
    module SQLServer
      module SchemaStatements

        def native_database_types
          @native_database_types ||= initialize_native_database_types.freeze
        end

        def tables(name = nil)
          ActiveSupport::Deprecation.warn 'Passing arguments to #tables is deprecated without replacement.' if name
          tables_sql('BASE TABLE')
        end

        def table_exists?(table_name)
          ActiveSupport::Deprecation.warn(<<-MSG.squish)
            #table_exists? currently checks both tables and views.
            This behavior is deprecated and will be changed with Rails 5.1 to only check tables.
            Use #data_source_exists? instead.
          MSG
          data_source_exists?(table_name)
        end

        def data_source_exists?(table_name)
          return false if table_name.blank?
          unquoted_table_name = SQLServer::Utils.extract_identifiers(table_name).object
          super(unquoted_table_name)
        end

        def views
          tables_sql('VIEW')
        end

        def view_exists?(table_name)
          identifier = SQLServer::Utils.extract_identifiers(table_name)
          super(identifier.object)
        end

        def create_table(table_name, comment: nil, **options)
          res = super
          clear_cache!
          res
        end

        def indexes(table_name, name = nil)
          data = select("EXEC sp_helpindex #{quote(table_name)}", name) rescue []
          data.reduce([]) do |indexes, index|
            index = index.with_indifferent_access
            if index[:index_description] =~ /primary key/
              indexes
            else
              name    = index[:index_name]
              unique  = index[:index_description] =~ /unique/
              where   = select_value("SELECT [filter_definition] FROM sys.indexes WHERE name = #{quote(name)}")
              columns = index[:index_keys].split(',').map do |column|
                column.strip!
                column.gsub! '(-)', '' if column.ends_with?('(-)')
                column
              end
              indexes << IndexDefinition.new(table_name, name, unique, columns, nil, nil, where)
            end
          end
        end

        def columns(table_name)
          return [] if table_name.blank?
          column_definitions(table_name).map do |ci|
            sqlserver_options = ci.slice :ordinal_position, :is_primary, :is_identity
            sql_type_metadata = fetch_type_metadata ci[:type], sqlserver_options
            new_column(
              ci[:name],
              ci[:default_value],
              sql_type_metadata,
              ci[:null],
              ci[:table_name],
              ci[:default_function],
              ci[:collation],
              nil,
              sqlserver_options
            )
          end
        end

        def new_column(name, default, sql_type_metadata, null, table_name, default_function = nil, collation = nil, comment = nil, sqlserver_options = {})
          SQLServerColumn.new(
            name,
            default,
            sql_type_metadata,
            null, table_name,
            default_function,
            collation,
            comment,
            sqlserver_options
          )
        end

        def primary_keys(table_name)
          primaries = schema_cache.columns(table_name).select(&:is_primary?).map(&:name)
          primaries.present? ? primaries : identity_columns(table_name).map(&:name)
        end

        def rename_table(table_name, new_name)
          do_execute "EXEC sp_rename '#{table_name}', '#{new_name}'"
          rename_table_indexes(table_name, new_name)
        end

        def remove_column(table_name, column_name, type = nil, options = {})
          raise ArgumentError.new('You must specify at least one column name.  Example: remove_column(:people, :first_name)') if column_name.is_a? Array
          remove_check_constraints(table_name, column_name)
          remove_default_constraint(table_name, column_name)
          remove_indexes(table_name, column_name)
          do_execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
        end

        def change_column(table_name, column_name, type, options = {})
          sql_commands = []
          indexes = []
          column_object = schema_cache.columns(table_name).find { |c| c.name.to_s == column_name.to_s }
          if options_include_default?(options) || (column_object && column_object.type != type.to_sym)
            remove_default_constraint(table_name, column_name)
            indexes = indexes(table_name).select { |index| index.columns.include?(column_name.to_s) }
            remove_indexes(table_name, column_name)
          end
          sql_commands << "UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote_default_expression(options[:default], column_object)} WHERE #{quote_column_name(column_name)} IS NULL" if !options[:null].nil? && options[:null] == false && !options[:default].nil?
          sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
          sql_commands[-1] << ' NOT NULL' if !options[:null].nil? && options[:null] == false
          if options_include_default?(options)
            sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_constraint_name(table_name, column_name)} DEFAULT #{quote_default_expression(options[:default], column_object)} FOR #{quote_column_name(column_name)}"
          end
          # Add any removed indexes back
          indexes.each do |index|
            sql_commands << "CREATE INDEX #{quote_table_name(index.name)} ON #{quote_table_name(table_name)} (#{index.columns.map { |c| quote_column_name(c) }.join(', ')})"
          end
          sql_commands.each { |c| do_execute(c) }
        end

        def change_column_default(table_name, column_name, default_or_changes)
          clear_cache!
          column = column_for(table_name, column_name)
          return unless column
          remove_default_constraint(table_name, column_name)
          default = extract_new_default_value(default_or_changes)
          do_execute "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_constraint_name(table_name, column_name)} DEFAULT #{quote_default_expression(default, column)} FOR #{quote_column_name(column_name)}"
          clear_cache!
        end

        def rename_column(table_name, column_name, new_column_name)
          clear_cache!
          detect_column_for! table_name, column_name
          identifier = SQLServer::Utils.extract_identifiers("#{table_name}.#{column_name}")
          execute_procedure :sp_rename, identifier.quoted, new_column_name, 'COLUMN'
          rename_column_indexes(table_name, column_name, new_column_name)
          clear_cache!
        end

        def rename_index(table_name, old_name, new_name)
          raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{allowed_index_name_length} characters" if new_name.length > allowed_index_name_length
          identifier = SQLServer::Utils.extract_identifiers("#{table_name}.#{old_name}")
          execute_procedure :sp_rename, identifier.quoted, new_name, 'INDEX'
        end

        def remove_index!(table_name, index_name)
          do_execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
        end

        def foreign_keys(table_name)
          identifier = SQLServer::Utils.extract_identifiers(table_name)
          fk_info = execute_procedure :sp_fkeys, nil, identifier.schema, nil, identifier.object, identifier.schema
          fk_info.map do |row|
            from_table = identifier.object
            to_table = row['PKTABLE_NAME']
            options = {
              name: row['FK_NAME'],
              column: row['FKCOLUMN_NAME'],
              primary_key: row['PKCOLUMN_NAME'],
              on_update: extract_foreign_key_action('update', row['FK_NAME']),<commit_msg>[Rails5] Pass a few `Migration::ColumnsTest` examples.<commit_after>module ActiveRecord
  module ConnectionAdapters
    module SQLServer
      module SchemaStatements

        def native_database_types
          @native_database_types ||= initialize_native_database_types.freeze
        end

        def tables(name = nil)
          ActiveSupport::Deprecation.warn 'Passing arguments to #tables is deprecated without replacement.' if name
          tables_sql('BASE TABLE')
        end

        def table_exists?(table_name)
          ActiveSupport::Deprecation.warn(<<-MSG.squish)
            #table_exists? currently checks both tables and views.
            This behavior is deprecated and will be changed with Rails 5.1 to only check tables.
            Use #data_source_exists? instead.
          MSG
          data_source_exists?(table_name)
        end

        def data_source_exists?(table_name)
          return false if table_name.blank?
          unquoted_table_name = SQLServer::Utils.extract_identifiers(table_name).object
          super(unquoted_table_name)
        end

        def views
          tables_sql('VIEW')
        end

        def view_exists?(table_name)
          identifier = SQLServer::Utils.extract_identifiers(table_name)
          super(identifier.object)
        end

        def create_table(table_name, comment: nil, **options)
          res = super
          clear_cache!
          res
        end

        def indexes(table_name, name = nil)
          data = select("EXEC sp_helpindex #{quote(table_name)}", name) rescue []
          data.reduce([]) do |indexes, index|
            index = index.with_indifferent_access
            if index[:index_description] =~ /primary key/
              indexes
            else
              name    = index[:index_name]
              unique  = index[:index_description] =~ /unique/
              where   = select_value("SELECT [filter_definition] FROM sys.indexes WHERE name = #{quote(name)}")
              columns = index[:index_keys].split(',').map do |column|
                column.strip!
                column.gsub! '(-)', '' if column.ends_with?('(-)')
                column
              end
              indexes << IndexDefinition.new(table_name, name, unique, columns, nil, nil, where)
            end
          end
        end

        def columns(table_name)
          return [] if table_name.blank?
          column_definitions(table_name).map do |ci|
            sqlserver_options = ci.slice :ordinal_position, :is_primary, :is_identity
            sql_type_metadata = fetch_type_metadata ci[:type], sqlserver_options
            new_column(
              ci[:name],
              ci[:default_value],
              sql_type_metadata,
              ci[:null],
              ci[:table_name],
              ci[:default_function],
              ci[:collation],
              nil,
              sqlserver_options
            )
          end
        end

        def new_column(name, default, sql_type_metadata, null, table_name, default_function = nil, collation = nil, comment = nil, sqlserver_options = {})
          SQLServerColumn.new(
            name,
            default,
            sql_type_metadata,
            null, table_name,
            default_function,
            collation,
            comment,
            sqlserver_options
          )
        end

        def primary_keys(table_name)
          primaries = schema_cache.columns(table_name).select(&:is_primary?).map(&:name)
          primaries.present? ? primaries : identity_columns(table_name).map(&:name)
        end

        def rename_table(table_name, new_name)
          do_execute "EXEC sp_rename '#{table_name}', '#{new_name}'"
          rename_table_indexes(table_name, new_name)
        end

        def remove_column(table_name, column_name, type = nil, options = {})
          raise ArgumentError.new('You must specify at least one column name.  Example: remove_column(:people, :first_name)') if column_name.is_a? Array
          remove_check_constraints(table_name, column_name)
          remove_default_constraint(table_name, column_name)
          remove_indexes(table_name, column_name)
          do_execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
        end

        def change_column(table_name, column_name, type, options = {})
          sql_commands = []
          indexes = []
          column_object = schema_cache.columns(table_name).find { |c| c.name.to_s == column_name.to_s }
          if options_include_default?(options) || (column_object && column_object.type != type.to_sym)
            remove_default_constraint(table_name, column_name)
            indexes = indexes(table_name).select { |index| index.columns.include?(column_name.to_s) }
            remove_indexes(table_name, column_name)
          end
          sql_commands << "UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote_default_expression(options[:default], column_object)} WHERE #{quote_column_name(column_name)} IS NULL" if !options[:null].nil? && options[:null] == false && !options[:default].nil?
          sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
          sql_commands[-1] << ' NOT NULL' if !options[:null].nil? && options[:null] == false
          if options_include_default?(options)
            sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_constraint_name(table_name, column_name)} DEFAULT #{quote_default_expression(options[:default], column_object)} FOR #{quote_column_name(column_name)}"
          end
          # Add any removed indexes back
          indexes.each do |index|
            sql_commands << "CREATE INDEX #{quote_table_name(index.name)} ON #{quote_table_name(table_name)} (#{index.columns.map { |c| quote_column_name(c) }.join(', ')})"
          end
          sql_commands.each { |c| do_execute(c) }
        end

        def change_column_default(table_name, column_name, default_or_changes)
          clear_cache!
          column = column_for(table_name, column_name)
          return unless column
          remove_default_constraint(table_name, column_name)
          default = extract_new_default_value(default_or_changes)
          do_execute "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_constraint_name(table_name, column_name)} DEFAULT #{quote_default_expression(default, column)} FOR #{quote_column_name(column_name)}"
          clear_cache!
        end

        def rename_column(table_name, column_name, new_column_name)
          clear_cache!
          identifier = SQLServer::Utils.extract_identifiers("#{table_name}.#{column_name}")
          execute_procedure :sp_rename, identifier.quoted, new_column_name, 'COLUMN'
          rename_column_indexes(table_name, column_name, new_column_name)
          clear_cache!
        end

        def rename_index(table_name, old_name, new_name)
          raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{allowed_index_name_length} characters" if new_name.length > allowed_index_name_length
          identifier = SQLServer::Utils.extract_identifiers("#{table_name}.#{old_name}")
          execute_procedure :sp_rename, identifier.quoted, new_name, 'INDEX'
        end

        def remove_index!(table_name, index_name)
          do_execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
        end

        def foreign_keys(table_name)
          identifier = SQLServer::Utils.extract_identifiers(table_name)
          fk_info = execute_procedure :sp_fkeys, nil, identifier.schema, nil, identifier.object, identifier.schema
          fk_info.map do |row|
            from_table = identifier.object
            to_table = row['PKTABLE_NAME']
            options = {
              name: row['FK_NAME'],
              column: row['FKCOLUMN_NAME'],
              primary_key: row['PKCOLUMN_NAME'],
              on_update: extract_foreign_key_action('update', row['FK_NAME']),
{'fraction_non_alphanumeric': 0.09679190046352769, 'fraction_numerical': 0.00042693339838985116, 'mean_word_length': 2.614858906525573, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 5, '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': '1219460', 'n_tokens_mistral': 4590, 'n_tokens_neox': 4545, 'n_words': 945}