module ActiveRecord::ConnectionAdapters::SQLServer::SchemaStatements

Constants

COLUMN_DEFINITION_BIND_STRING_0
COLUMN_DEFINITION_BIND_STRING_1

Public Instance Methods

change_column(table_name, column_name, type, options = {}) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 141
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 }
  without_constraints = options.key?(:default) || options.key?(:limit)
  default = if !options.key?(:default) && column_object
    column_object.default
  else
    options[:default]
  end
  if without_constraints || (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, limit: options[:limit], precision: options[:precision], scale: options[:scale])}"
  sql_commands.last << ' NOT NULL' if !options[:null].nil? && options[:null] == false
  if without_constraints
    default = quote_default_expression(default, column_object || column_for(table_name, column_name))
    sql_commands << "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_constraint_name(table_name, column_name)} DEFAULT #{default} 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) }
  clear_cache!
end
change_column_default(table_name, column_name, default_or_changes) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 171
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
change_column_null(table_name, column_name, allow_null, default = nil) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 264
def change_column_null(table_name, column_name, allow_null, default = nil)
  table_id = SQLServer::Utils.extract_identifiers(table_name)
  column_id = SQLServer::Utils.extract_identifiers(column_name)
  column = column_for(table_name, column_name)
  if !allow_null.nil? && allow_null == false && !default.nil?
    do_execute("UPDATE #{table_id} SET #{column_id}=#{quote(default)} WHERE #{column_id} IS NULL")
  end
  sql = "ALTER TABLE #{table_id} ALTER COLUMN #{column_id} #{type_to_sql column.type, limit: column.limit, precision: column.precision, scale: column.scale}"
  sql << ' NOT NULL' if !allow_null.nil? && allow_null == false
  do_execute sql
end
columns(table_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 65
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
columns_for_distinct(columns, orders) click to toggle source
Calls superclass method
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 250
def columns_for_distinct(columns, orders)
  order_columns = orders.reject(&:blank?).map{ |s|
      s = s.to_sql unless s.is_a?(String)
      s.gsub(/\s+(?:ASC|DESC)\b/i, '')
       .gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, '')
    }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }

  (order_columns << super).join(", ")
end
create_schema_dumper(options) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 276
def create_schema_dumper(options)
  SQLServer::SchemaDumper.create(self, options)
end
create_table(table_name, comment: nil, **options) click to toggle source
Calls superclass method
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 10
def create_table(table_name, comment: nil, **options)
  res = super
  clear_cache!
  res
end
drop_table(table_name, options = {}) click to toggle source
Calls superclass method
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 16
def drop_table(table_name, options = {})
  # Mimic CASCADE option as best we can.
  if options[:force] == :cascade
    execute_procedure(:sp_fkeys, pktable_name: table_name).each do |fkdata|
      fktable = fkdata['FKTABLE_NAME']
      fkcolmn = fkdata['FKCOLUMN_NAME']
      pktable = fkdata['PKTABLE_NAME']
      pkcolmn = fkdata['PKCOLUMN_NAME']
      remove_foreign_key fktable, name: fkdata['FK_NAME']
      do_execute "DELETE FROM #{quote_table_name(fktable)} WHERE #{quote_column_name(fkcolmn)} IN ( SELECT #{quote_column_name(pkcolmn)} FROM #{quote_table_name(pktable)} )"
    end
  end
  if options[:if_exists] && @version_year < 2016
    execute "IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = #{quote(table_name)}) DROP TABLE #{quote_table_name(table_name)}"
  else
    super
  end
end
extract_foreign_key_action(action, fk_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 216
def extract_foreign_key_action(action, fk_name)
  case select_value("SELECT #{action}_referential_action_desc FROM sys.foreign_keys WHERE name = '#{fk_name}'")
  when 'CASCADE' then :cascade
  when 'SET_NULL' then :nullify
  end
end
foreign_keys(table_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 199
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']),
      on_delete: extract_foreign_key_action('delete', row['FK_NAME'])
    }
    ForeignKeyDefinition.new from_table, to_table, options
  end
end
indexes(table_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 35
def indexes(table_name)
  data = (select("EXEC sp_helpindex #{quote(table_name)}", "SCHEMA") || []) rescue [] # JDBC returns nil instead of an array or erring out for no results
  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)}")
      orders  = {}
      columns = []

      index[:index_keys].split(',').each do |column|
        column.strip!

        if column.ends_with?('(-)')
          column.gsub! '(-)', ''
          orders[column] = :desc
        end

        columns << column
      end

      indexes << IndexDefinition.new(table_name, name, unique, columns, where: where, orders: orders)
    end
  end
end
native_database_types() click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 6
def native_database_types
  @native_database_types ||= initialize_native_database_types.freeze
end
new_column(name, default, sql_type_metadata, null, table_name, default_function = nil, collation = nil, comment = nil, sqlserver_options = {}) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 84
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
primary_keys(table_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 97
def primary_keys(table_name)
  primaries = primary_keys_select(table_name)
  primaries.present? ? primaries : identity_columns(table_name).map(&:name)
end
primary_keys_select(table_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 102
def primary_keys_select(table_name)
  identifier = database_prefix_identifier(table_name)
  database = identifier.fully_qualified_database_quoted
  sql = %{
    SELECT KCU.COLUMN_NAME AS [name]
    FROM #{database}.INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU
    LEFT OUTER JOIN #{database}.INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
      ON KCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
      AND KCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
      AND KCU.CONSTRAINT_CATALOG = TC.CONSTRAINT_CATALOG
      AND KCU.CONSTRAINT_SCHEMA = TC.CONSTRAINT_SCHEMA
      AND TC.CONSTRAINT_TYPE = N'PRIMARY KEY'
    WHERE KCU.TABLE_NAME = #{prepared_statements ? COLUMN_DEFINITION_BIND_STRING_0 : quote(identifier.object)}
    AND KCU.TABLE_SCHEMA = #{identifier.schema.blank? ? 'schema_name()' : (prepared_statements ? COLUMN_DEFINITION_BIND_STRING_1 : quote(identifier.schema))}
    AND TC.CONSTRAINT_TYPE = N'PRIMARY KEY'
    ORDER BY KCU.ORDINAL_POSITION ASC
  }.gsub(/[[:space:]]/, ' ')
  binds = []
  if prepared_statements
    nv128 = SQLServer::Type::UnicodeVarchar.new limit: 128
    binds << Relation::QueryAttribute.new('TABLE_NAME', identifier.object, nv128)
    binds << Relation::QueryAttribute.new('TABLE_SCHEMA', identifier.schema, nv128) unless identifier.schema.blank?
  end
  sp_executesql(sql, 'SCHEMA', binds).map { |r| r['name'] }
end
remove_column(table_name, column_name, type = nil, options = {}) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 133
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
remove_index!(table_name, index_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 195
def remove_index!(table_name, index_name)
  do_execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
end
rename_column(table_name, column_name, new_column_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 181
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
rename_index(table_name, old_name, new_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 189
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
rename_table(table_name, new_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 128
def rename_table(table_name, new_name)
  do_execute "EXEC sp_rename '#{table_name}', '#{new_name}'"
  rename_table_indexes(table_name, new_name)
end
type_to_sql(type, limit: nil, precision: nil, scale: nil, **) click to toggle source
Calls superclass method
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 223
def type_to_sql(type, limit: nil, precision: nil, scale: nil, **)
  type_limitable = %w(string integer float char nchar varchar nvarchar).include?(type.to_s)
  limit = nil unless type_limitable
  case type.to_s
  when 'integer'
    case limit
    when 1          then  'tinyint'
    when 2          then  'smallint'
    when 3..4, nil  then  'integer'
    when 5..8       then  'bigint'
    else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.")
    end
  when 'datetime2'
    column_type_sql = super
    if precision
      if (0..7) === precision
        column_type_sql << "(#{precision})"
      else
        raise(ActiveRecordError, "The dattime2 type has precision of #{precision}. The allowed range of precision is from 0 to 7")
      end
    end
    column_type_sql
  else
    super
  end
end
update_table_definition(table_name, base) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 260
def update_table_definition(table_name, base)
  SQLServer::Table.new(table_name, base)
end

Private Instance Methods

column_definitions(table_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 345
def column_definitions(table_name)
  identifier  = database_prefix_identifier(table_name)
  database    = identifier.fully_qualified_database_quoted
  view_exists = view_exists?(table_name)
  view_tblnm  = view_table_name(table_name) if view_exists
  sql = %{
    SELECT DISTINCT
    #{lowercase_schema_reflection_sql('columns.TABLE_NAME')} AS table_name,
    #{lowercase_schema_reflection_sql('columns.COLUMN_NAME')} AS name,
    columns.DATA_TYPE AS type,
    columns.COLUMN_DEFAULT AS default_value,
    columns.NUMERIC_SCALE AS numeric_scale,
    columns.NUMERIC_PRECISION AS numeric_precision,
    columns.DATETIME_PRECISION AS datetime_precision,
    columns.COLLATION_NAME AS [collation],
    columns.ordinal_position,
    CASE
      WHEN columns.DATA_TYPE IN ('nchar','nvarchar','char','varchar') THEN columns.CHARACTER_MAXIMUM_LENGTH
      ELSE COL_LENGTH('#{database}.'+columns.TABLE_SCHEMA+'.'+columns.TABLE_NAME, columns.COLUMN_NAME)
    END AS [length],
    CASE
      WHEN columns.IS_NULLABLE = 'YES' THEN 1
      ELSE NULL
    END AS [is_nullable],
    CASE
      WHEN KCU.COLUMN_NAME IS NOT NULL AND TC.CONSTRAINT_TYPE = N'PRIMARY KEY' THEN 1
      ELSE NULL
    END AS [is_primary],
    c.is_identity AS [is_identity]
    FROM #{database}.INFORMATION_SCHEMA.COLUMNS columns
    LEFT OUTER JOIN #{database}.INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC
      ON TC.TABLE_NAME = columns.TABLE_NAME
      AND TC.TABLE_SCHEMA = columns.TABLE_SCHEMA
      AND TC.CONSTRAINT_TYPE = N'PRIMARY KEY'
    LEFT OUTER JOIN #{database}.INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU
      ON KCU.COLUMN_NAME = columns.COLUMN_NAME
      AND KCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
      AND KCU.CONSTRAINT_CATALOG = TC.CONSTRAINT_CATALOG
      AND KCU.CONSTRAINT_SCHEMA = TC.CONSTRAINT_SCHEMA
    INNER JOIN #{database}.sys.schemas AS s
      ON s.name = columns.TABLE_SCHEMA
      AND s.schema_id = s.schema_id
    INNER JOIN #{database}.sys.objects AS o
      ON s.schema_id = o.schema_id
      AND o.is_ms_shipped = 0
      AND o.type IN ('U', 'V')
      AND o.name = columns.TABLE_NAME
    INNER JOIN #{database}.sys.columns AS c
      ON o.object_id = c.object_id
      AND c.name = columns.COLUMN_NAME
    WHERE columns.TABLE_NAME = #{prepared_statements ? COLUMN_DEFINITION_BIND_STRING_0 : quote(identifier.object)}
      AND columns.TABLE_SCHEMA = #{identifier.schema.blank? ? 'schema_name()' : (prepared_statements ? COLUMN_DEFINITION_BIND_STRING_1 : quote(identifier.schema))}
    ORDER BY columns.ordinal_position
  }.gsub(/[ \t\r\n]+/, ' ').strip

  binds = []
  if prepared_statements
    nv128 = SQLServer::Type::UnicodeVarchar.new limit: 128
    binds << Relation::QueryAttribute.new('TABLE_NAME', identifier.object, nv128)
    binds << Relation::QueryAttribute.new('TABLE_SCHEMA', identifier.schema, nv128) unless identifier.schema.blank?
  end

  results = sp_executesql(sql, 'SCHEMA', binds)
  results.map do |ci|
    ci = ci.symbolize_keys
    ci[:_type] = ci[:type]
    ci[:table_name] = view_tblnm || table_name
    ci[:type] = case ci[:type]
                when /^bit|image|text|ntext|datetime$/
                  ci[:type]
                when /^datetime2|datetimeoffset$/i
                  "#{ci[:type]}(#{ci[:datetime_precision]})"
                when /^time$/i
                  "#{ci[:type]}(#{ci[:datetime_precision]})"
                when /^numeric|decimal$/i
                  "#{ci[:type]}(#{ci[:numeric_precision]},#{ci[:numeric_scale]})"
                when /^float|real$/i
                  "#{ci[:type]}"
                when /^char|nchar|varchar|nvarchar|binary|varbinary|bigint|int|smallint$/
                  ci[:length].to_i == -1 ? "#{ci[:type]}(max)" : "#{ci[:type]}(#{ci[:length]})"
                else
                  ci[:type]
                end
    ci[:default_value],
    ci[:default_function] = begin
      default = ci[:default_value]
      if default.nil? && view_exists
        default = select_value %{
          SELECT c.COLUMN_DEFAULT
          FROM #{database}.INFORMATION_SCHEMA.COLUMNS c
          WHERE
            c.TABLE_NAME = '#{view_tblnm}'
            AND c.COLUMN_NAME = '#{views_real_column_name(table_name, ci[:name])}'
        }.squish, 'SCHEMA'
      end
      case default
      when nil
        [nil, nil]
      when /\A\((\w+\(\))\)\Z/
        default_function = Regexp.last_match[1]
        [nil, default_function]
      when /\A\(N'(.*)'\)\Z/m
        string_literal = SQLServer::Utils.unquote_string(Regexp.last_match[1])
        [string_literal, nil]
      when /CREATE DEFAULT/mi
        [nil, nil]
      else
        type = case ci[:type]
               when /smallint|int|bigint/ then ci[:_type]
               else ci[:type]
               end
        value = default.match(/\A\((.*)\)\Z/m)[1]
        value = select_value("SELECT CAST(#{value} AS #{type}) AS value", 'SCHEMA')
        [value, nil]
      end
    end
    ci[:null] = ci[:is_nullable].to_i == 1
    ci.delete(:is_nullable)
    ci[:is_primary] = ci[:is_primary].to_i == 1
    ci[:is_identity] = ci[:is_identity].to_i == 1 unless [TrueClass, FalseClass].include?(ci[:is_identity].class)
    ci
  end
end
create_table_definition(*args) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 546
def create_table_definition(*args)
  SQLServer::TableDefinition.new(*args)
end
data_source_sql(name = nil, type: nil) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 282
def data_source_sql(name = nil, type: nil)
  scope = quoted_scope name, type: type
  table_name = lowercase_schema_reflection_sql 'TABLE_NAME'
  sql = "SELECT #{table_name}"
  sql << ' FROM INFORMATION_SCHEMA.TABLES WITH (NOLOCK)'
  sql << ' WHERE TABLE_CATALOG = DB_NAME()'
  sql << " AND TABLE_SCHEMA = #{quote(scope[:schema])}"
  sql << " AND TABLE_NAME = #{quote(scope[:name])}" if scope[:name]
  sql << " AND TABLE_TYPE = #{quote(scope[:type])}" if scope[:type]
  sql << " ORDER BY #{table_name}"
  sql
end
default_constraint_name(table_name, column_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 504
def default_constraint_name(table_name, column_name)
  "DF_#{table_name}_#{column_name}"
end
get_table_name(sql) click to toggle source

SQLServer Specific (Misc Helpers) ========================= #

# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 493
def get_table_name(sql)
  tn = if sql =~ /^\s*(INSERT|EXEC sp_executesql N'INSERT)(\s+INTO)?\s+([^\(\s]+)\s*|^\s*update\s+([^\(\s]+)\s*/i
    Regexp.last_match[3] || Regexp.last_match[4]
  elsif sql =~ /FROM\s+([^\(\s]+)\s*/i
    Regexp.last_match[1]
  else
    nil
  end
  SQLServer::Utils.extract_identifiers(tn).object
end
initialize_native_database_types() click to toggle source

SQLServer Specific ======================================== #

# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 306
def initialize_native_database_types
  {
    primary_key: 'bigint NOT NULL IDENTITY(1,1) PRIMARY KEY',
    primary_key_nonclustered: 'int NOT NULL IDENTITY(1,1) PRIMARY KEY NONCLUSTERED',
    integer: { name: 'int', limit: 4 },
    bigint: { name: 'bigint' },
    boolean: { name: 'bit' },
    decimal: { name: 'decimal' },
    money: { name: 'money' },
    smallmoney: { name: 'smallmoney' },
    float: { name: 'float' },
    real: { name: 'real' },
    date: { name: 'date' },
    datetime: { name: 'datetime' },
    datetime2: { name: 'datetime2' },
    datetimeoffset: { name: 'datetimeoffset' },
    smalldatetime: { name: 'smalldatetime' },
    timestamp: { name: 'datetime' },
    time: { name: 'time' },
    char: { name: 'char' },
    varchar: { name: 'varchar', limit: 8000 },
    varchar_max: { name: 'varchar(max)' },
    text_basic: { name: 'text' },
    nchar: { name: 'nchar' },
    string: { name: 'nvarchar', limit: 4000 },
    text: { name: 'nvarchar(max)' },
    ntext: { name: 'ntext' },
    binary_basic: { name: 'binary' },
    varbinary: { name: 'varbinary', limit: 8000 },
    binary: { name: 'varbinary(max)' },
    uuid: { name: 'uniqueidentifier' },
    ss_timestamp: { name: 'timestamp' },
    json: { name: 'nvarchar(max)' }
  }
end
lowercase_schema_reflection_sql(node) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 508
def lowercase_schema_reflection_sql(node)
  lowercase_schema_reflection ? "LOWER(#{node})" : node
end
quoted_scope(name = nil, type: nil) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 295
def quoted_scope(name = nil, type: nil)
  identifier = SQLServer::Utils.extract_identifiers(name)
  {}.tap do |scope|
    scope[:schema] = identifier.schema || 'dbo'
    scope[:name] = identifier.object if identifier.object
    scope[:type] = type if type
  end
end
remove_check_constraints(table_name, column_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 469
def remove_check_constraints(table_name, column_name)
  constraints = select_values "SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE where TABLE_NAME = '#{quote_string(table_name)}' and COLUMN_NAME = '#{quote_string(column_name)}'", 'SCHEMA'
  constraints.each do |constraint|
    do_execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{quote_column_name(constraint)}"
  end
end
remove_default_constraint(table_name, column_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 476
def remove_default_constraint(table_name, column_name)
  # If their are foreign keys in this table, we could still get back a 2D array, so flatten just in case.
  execute_procedure(:sp_helpconstraint, table_name, 'nomsg').flatten.select do |row|
    row['constraint_type'] == "DEFAULT on column #{column_name}"
  end.each do |row|
    do_execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{row['constraint_name']}"
  end
end
remove_indexes(table_name, column_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 485
def remove_indexes(table_name, column_name)
  indexes(table_name).select { |index| index.columns.include?(column_name.to_s) }.each do |index|
    remove_index(table_name, name: index.name)
  end
end
view_information(table_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 519
def view_information(table_name)
  @view_information ||= {}
  @view_information[table_name] ||= begin
    identifier = SQLServer::Utils.extract_identifiers(table_name)
    view_info = select_one "SELECT * FROM INFORMATION_SCHEMA.VIEWS WITH (NOLOCK) WHERE TABLE_NAME = #{quote(identifier.object)}", 'SCHEMA'
    if view_info
      view_info = view_info.with_indifferent_access
      if view_info[:VIEW_DEFINITION].blank? || view_info[:VIEW_DEFINITION].length == 4000
        view_info[:VIEW_DEFINITION] = begin
          select_values("EXEC sp_helptext #{identifier.object_quoted}", 'SCHEMA').join
        rescue
          warn "No view definition found, possible permissions problem.\nPlease run GRANT VIEW DEFINITION TO your_user;"
          nil
        end
      end
    end
    view_info
  end
end
view_table_name(table_name) click to toggle source

SQLServer Specific (View Reflection) ====================== #

# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 514
def view_table_name(table_name)
  view_info = view_information(table_name)
  view_info ? get_table_name(view_info['VIEW_DEFINITION']) : table_name
end
views_real_column_name(table_name, column_name) click to toggle source
# File lib/active_record/connection_adapters/sqlserver/schema_statements.rb, line 539
def views_real_column_name(table_name, column_name)
  view_definition = view_information(table_name)[:VIEW_DEFINITION]
  return column_name unless view_definition
  match_data = view_definition.match(/([\w-]*)\s+as\s+#{column_name}/im)
  match_data ? match_data[1] : column_name
end