@@ -27,6 +27,16 @@ def self.sqlserver_connection(config) #:nodoc:
2727 ConnectionAdapters ::SQLServerAdapter . new ( conn , logger , [ driver_url , username , password ] )
2828 end
2929
30+ class << self
31+
32+ def reset_column_information_with_sqlserver_columns_cache_support
33+ connection . instance_variable_set :@sqlserver_columns_cache , { }
34+ reset_column_information_without_sqlserver_columns_cache_support
35+ end
36+ alias_method_chain :reset_column_information , :sqlserver_columns_cache_support
37+
38+ end
39+
3040 private
3141
3242 # Add basic support for SQL server locking hints
@@ -265,6 +275,7 @@ class SQLServerAdapter < AbstractAdapter
265275 def initialize ( connection , logger , connection_options = nil )
266276 super ( connection , logger )
267277 @connection_options = connection_options
278+ @sqlserver_columns_cache = { }
268279 unless SUPPORTED_VERSIONS . include? ( database_year )
269280 raise NotImplementedError , "Currently, only #{ SUPPORTED_VERSIONS . to_sentence } are supported."
270281 end
@@ -573,20 +584,25 @@ def table_exists?(table_name)
573584
574585 def columns ( table_name , name = nil )
575586 return [ ] if table_name . blank?
576- table_names = table_name . to_s . split ( '.' )
577- table_name = table_names [ -1 ]
578- table_name = table_name . gsub ( /[\[ \] ]/ , '' )
579- db_name = "#{ table_names [ 0 ] } ." if table_names . length ==3
580- column_definitions ( table_name , db_name ) . collect do |ci |
587+ cache_key = unqualify_table_name ( table_name )
588+ @sqlserver_columns_cache [ cache_key ] ||= column_definitions ( table_name ) . collect do |ci |
581589 sqlserver_options = ci . except ( :name , :default_value , :type , :null )
582590 SQLServerColumn . new ci [ :name ] , ci [ :default_value ] , ci [ :type ] , ci [ :null ] , sqlserver_options
583591 end
584592 end
585593
586-
594+ def create_table ( table_name , options = { } )
595+ super
596+ remove_sqlserver_columns_cache_for ( table_name )
597+ end
587598
588- def rename_table ( name , new_name )
589- execute "EXEC sp_rename '#{ name } ', '#{ new_name } '"
599+ def drop_table ( table_name , options = { } )
600+ super
601+ remove_sqlserver_columns_cache_for ( table_name )
602+ end
603+
604+ def rename_table ( table_name , new_name )
605+ execute "EXEC sp_rename '#{ table_name } ', '#{ new_name } '"
590606 end
591607
592608 def add_column ( table_name , column_name , type , options = { } )
@@ -595,26 +611,27 @@ def add_column(table_name, column_name, type, options = {})
595611 # TODO: Add support to mimic date columns, using constraints to mark them as such in the database
596612 # add_column_sql << " CONSTRAINT ck__#{table_name}__#{column_name}__date_only CHECK ( CONVERT(CHAR(12), #{quote_column_name(column_name)}, 14)='00:00:00:000' )" if type == :date
597613 execute ( add_column_sql )
614+ remove_sqlserver_columns_cache_for ( table_name )
598615 end
599616
600617 def remove_column ( table_name , column_name )
601618 remove_check_constraints ( table_name , column_name )
602619 remove_default_constraint ( table_name , column_name )
603620 remove_indexes ( table_name , column_name )
604621 execute "ALTER TABLE [#{ table_name } ] DROP COLUMN #{ quote_column_name ( column_name ) } "
622+ remove_sqlserver_columns_cache_for ( table_name )
605623 end
606624
607- def change_column ( table_name , column_name , type , options = { } ) #:nodoc:
625+ def change_column ( table_name , column_name , type , options = { } )
608626 sql = "ALTER TABLE #{ table_name } ALTER COLUMN #{ quote_column_name ( column_name ) } #{ type_to_sql ( type , options [ :limit ] , options [ :precision ] , options [ :scale ] ) } "
609627 sql << " NOT NULL" if options [ :null ] == false
610628 sql_commands = [ sql ]
611629 if options_include_default? ( options )
612630 remove_default_constraint ( table_name , column_name )
613631 sql_commands << "ALTER TABLE #{ table_name } ADD CONSTRAINT DF_#{ table_name } _#{ column_name } DEFAULT #{ quote ( options [ :default ] , options [ :column ] ) } FOR #{ quote_column_name ( column_name ) } "
614632 end
615- sql_commands . each { |c |
616- execute ( c )
617- }
633+ sql_commands . each { |c | execute ( c ) }
634+ remove_sqlserver_columns_cache_for ( table_name )
618635 end
619636
620637 def change_column_default ( table_name , column_name , default )
@@ -852,17 +869,39 @@ def query_requires_identity_insert?(sql)
852869 end
853870
854871 def identity_column ( table_name )
855- @table_columns ||= { }
856- @table_columns [ table_name ] = columns ( table_name ) if @table_columns [ table_name ] == nil
857- @table_columns [ table_name ] . each do |col |
858- return col . name if col . is_identity?
859- end
860- return nil
872+ idcol = columns ( table_name ) . detect ( &:is_identity? )
873+ idcol ? idcol . name : nil
861874 end
862875
863876 # SQL UTILITY METHODS ======================================#
864877
865- def column_definitions ( table_name , db_name = nil )
878+ def unqualify_table_name ( table_name )
879+ table_name . to_s . split ( '.' ) . last . gsub ( /[\[ \] ]/ , '' )
880+ end
881+
882+ def unqualify_db_name ( table_name )
883+ table_names = table_name . to_s . split ( '.' )
884+ table_names . length == 3 ? table_names . first . gsub ( /[\[ \] ]/ , '' ) : nil
885+ end
886+
887+ def get_table_name ( sql )
888+ if sql =~ /^\s *insert\s +into\s +([^\( \s ]+)\s *|^\s *update\s +([^\( \s ]+)\s */i
889+ $1 || $2
890+ elsif sql =~ /from\s +([^\( \s ]+)\s */i
891+ $1
892+ else
893+ nil
894+ end
895+ end
896+
897+ def remove_sqlserver_columns_cache_for ( table_name )
898+ cache_key = unqualify_table_name ( table_name )
899+ @sqlserver_columns_cache [ cache_key ] = nil
900+ end
901+
902+ def column_definitions ( table_name )
903+ db_name = unqualify_db_name ( table_name )
904+ table_name = unqualify_table_name ( table_name )
866905 # COL_LENGTH returns values that do not reflect how much data can be stored in certain data types.
867906 # COL_LENGTH returns -1 for varchar(max), nvarchar(max), and varbinary(max)
868907 # COL_LENGTH returns 16 for ntext, text, image types
@@ -909,19 +948,8 @@ def column_definitions(table_name, db_name = nil)
909948 end
910949 end
911950
912- def get_table_name ( sql )
913- if sql =~ /^\s *insert\s +into\s +([^\( \s ]+)\s *|^\s *update\s +([^\( \s ]+)\s */i
914- $1 || $2
915- elsif sql =~ /from\s +([^\( \s ]+)\s */i
916- $1
917- else
918- nil
919- end
920- end
921-
922951
923952
924-
925953
926954 def change_order_direction ( order )
927955 order . split ( "," ) . collect { |fragment |
@@ -933,37 +961,25 @@ def change_order_direction(order)
933961 } . join ( "," )
934962 end
935963
936- def get_special_columns ( table_name )
937- special = [ ]
938- @table_columns ||= { }
939- @table_columns [ table_name ] ||= columns ( table_name )
940- @table_columns [ table_name ] . each do |col |
941- special << col . name if col . is_special?
942- end
943- special
964+ def special_columns ( table_name )
965+ columns ( table_name ) . select ( &:is_special? ) . map ( &:name )
944966 end
945967
946968 def repair_special_columns ( sql )
947- special_cols = get_special_columns ( get_table_name ( sql ) )
969+ special_cols = special_columns ( get_table_name ( sql ) )
948970 for col in special_cols . to_a
949971 sql . gsub! ( /((\. |\s |\( )\[ ?#{ col . to_s } \] ?)\s ?=\s ?/ , '\1 LIKE ' )
950972 sql . gsub! ( /ORDER BY #{ col . to_s } /i , '' )
951973 end
952974 sql
953975 end
954976
955- def get_utf8_columns ( table_name )
956- utf8 = [ ]
957- @table_columns ||= { }
958- @table_columns [ table_name ] ||= columns ( table_name )
959- @table_columns [ table_name ] . each do |col |
960- utf8 << col . name if col . is_utf8?
961- end
962- utf8
977+ def utf8_columns ( table_name )
978+ columns ( table_name ) . select ( &:is_utf8? ) . map ( &:name )
963979 end
964-
980+
965981 def set_utf8_values! ( sql )
966- utf8_cols = get_utf8_columns ( get_table_name ( sql ) )
982+ utf8_cols = utf8_columns ( get_table_name ( sql ) )
967983 if sql =~ /^\s *UPDATE/i
968984 utf8_cols . each do |col |
969985 sql . gsub! ( "[#{ col . to_s } ] = '" , "[#{ col . to_s } ] = N'" )
0 commit comments