@@ -51,6 +51,12 @@ def create_table
5151 module ConnectionAdapters
5252 class SchemaDumper
5353 private
54+ def header ( stream )
55+ stream . puts <<~HEADER
56+ ActiveRecord::Schema[#{ ActiveRecord ::Migration . current_version } ].define(#{ define_params } ) do
57+ HEADER
58+ end
59+
5460 def default_primary_key? ( column )
5561 schema_type ( column ) == :integer
5662 end
@@ -75,11 +81,11 @@ def visit_TableDefinition(o)
7581 end
7682
7783 if supports_foreign_keys?
78- statements . concat ( o . foreign_keys . map { |to_table , options | foreign_key_in_create ( o . name , to_table , options ) } )
84+ statements . concat ( o . foreign_keys . map { |fk | accept fk } )
7985 end
8086
8187 if supports_check_constraints?
82- statements . concat ( o . check_constraints . map { |expression , options | check_constraint_in_create ( o . name , expression , options ) } )
88+ statements . concat ( o . check_constraints . map { |chk | accept chk } )
8389 end
8490
8591 create_sql << "(#{ statements . join ( ', ' ) } )" if statements . present?
@@ -423,7 +429,7 @@ def internal_string_options_for_primary_key # :nodoc:
423429 end
424430
425431 def drop_table ( table_name , options = { } )
426- puts_log "drop_table"
432+ puts_log "drop_table - #{ table_name } "
427433 if options [ :if_exists ]
428434 execute ( "DROP TABLE IF EXISTS #{ quote_table_name ( table_name ) } " )
429435 else
@@ -833,7 +839,9 @@ def get_database_version
833839
834840 def prepared_statements?
835841 puts_log "prepared_statements?"
836- @prepared_statements && !prepared_statements_disabled_cache . include? ( object_id )
842+ prepare = @prepared_statements && !prepared_statements_disabled_cache . include? ( object_id )
843+ puts_log "prepare = #{ prepare } "
844+ prepare
837845 end
838846 alias :prepared_statements :prepared_statements?
839847
@@ -1112,21 +1120,43 @@ def fetch_data(stmt)
11121120 end
11131121 end
11141122
1115- def select ( sql , name = nil , binds = [ ] )
1123+ def select ( sql , name = nil , binds = [ ] , prepare : false , async : false )
11161124 puts_log "select #{ sql } "
1125+ puts_log "prepare = #{ prepare } "
1126+
11171127 # Replaces {"= NULL" with " IS NULL"} OR {"IN (NULL)" with " IS NULL"
11181128 begin
11191129 sql . gsub ( /(=\s *NULL|IN\s *\( NULL\) )/i , " IS NULL" )
11201130 rescue
11211131 # ...
11221132 end
11231133
1134+ if async && async_enabled?
1135+ if current_transaction . joinable?
1136+ raise AsynchronousQueryInsideTransactionError , "Asynchronous queries are not allowed inside transactions"
1137+ end
1138+
1139+ future_result = async . new (
1140+ pool ,
1141+ sql ,
1142+ name ,
1143+ binds ,
1144+ prepare : prepare ,
1145+ )
1146+ if supports_concurrent_connections? && current_transaction . closed?
1147+ future_result . schedule! ( ActiveRecord ::Base . asynchronous_queries_session )
1148+ else
1149+ future_result . execute! ( self )
1150+ end
1151+ return future_result
1152+ end
1153+
11241154 results = [ ]
11251155
11261156 if ( binds . nil? || binds . empty? )
11271157 stmt = execute ( sql , name )
11281158 else
1129- stmt = exec_query_ret_stmt ( sql , name , binds , prepare = false )
1159+ stmt = exec_query_ret_stmt ( sql , name , binds , prepare )
11301160 end
11311161
11321162 cols = IBM_DB . resultCols ( stmt )
@@ -1452,7 +1482,8 @@ def explain(arel, binds = [])
14521482 # the executed +sql+ statement.
14531483 # Here prepare argument is not used, by default this method creates prepared statment and execute.
14541484 def exec_query_ret_stmt ( sql , name = 'SQL' , binds = [ ] , prepare = false )
1455- puts_log "exec_query_ret_stmt"
1485+ puts_log "exec_query_ret_stmt #{ sql } "
1486+ sql = transform_query ( sql )
14561487 check_if_write_query ( sql )
14571488 materialize_transactions
14581489 mark_transaction_written_if_write ( sql )
@@ -1461,6 +1492,8 @@ def exec_query_ret_stmt(sql, name = 'SQL', binds = [], prepare = false)
14611492 puts_log "Binds = #{ binds } "
14621493 param_array = type_casted_binds ( binds )
14631494 puts_log "Param array = #{ param_array } "
1495+ puts_log "Prepare flag = #{ prepare } "
1496+ puts_log "#{ caller } "
14641497
14651498 stmt = @servertype . prepare ( sql , name )
14661499 if prepare
@@ -1526,6 +1559,7 @@ def execute(sql, name=nil)
15261559 #sql='INSERT INTO ar_internal_metadata (key, value, created_at, updated_at) VALUES ('10', '10', '10', '10')
15271560 puts_log "execute"
15281561 puts_log "#{ sql } "
1562+ sql = transform_query ( sql )
15291563 check_if_write_query ( sql )
15301564 materialize_transactions
15311565 mark_transaction_written_if_write ( sql )
@@ -1725,6 +1759,9 @@ def unquoted_false
17251759
17261760 def quote_table_name ( name )
17271761 puts_log "quote_table_name"
1762+ if name . start_with? '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9'
1763+ name = "\" #{ name } \" "
1764+ end
17281765 name
17291766 #@servertype.check_reserved_words(name).gsub('"', '').gsub("'",'')
17301767 end
@@ -2378,7 +2415,9 @@ def columns(table_name)
23782415 column_nullable = ( col [ "nullable" ] == 1 ) ? true : false
23792416 # Make sure the hidden column (db2_generated_rowid_for_lobs) in DB2 z/OS isn't added to the list
23802417 if !( column_name . match ( /db2_generated_rowid_for_lobs/i ) )
2418+ puts_log "Column type = #{ column_type } "
23812419 ruby_type = simplified_type ( column_type )
2420+ puts_log "Ruby type after = #{ ruby_type } "
23822421 precision = extract_precision ( ruby_type )
23832422
23842423 if column_type . match ( /timestamp|integer|bigint|date|time|blob/i )
@@ -2429,7 +2468,7 @@ def columns(table_name)
24292468 else
24302469 error_msg = "An unexpected error occurred during retrieval of column metadata"
24312470 error_msg = error_msg + ": #{ fetch_error . message } " if !fetch_error . message . empty?
2432- raise error_msg
2471+ # raise error_msg
24332472 end
24342473 ensure # Free resources associated with the statement
24352474 IBM_DB . free_stmt ( stmt ) if stmt
@@ -2447,6 +2486,10 @@ def columns(table_name)
24472486 return columns
24482487 end
24492488
2489+ def extract_precision ( sql_type )
2490+ $1. to_i if sql_type =~ /\( (\d +)(,\d +)?\) /
2491+ end
2492+
24502493 def extract_default_function ( default_value , default )
24512494 default if has_default_function? ( default_value , default )
24522495 end
@@ -2491,7 +2534,7 @@ def foreign_keys(table_name)
24912534 else
24922535 error_msg = "An unexpected error occurred during retrieval of foreign key metadata"
24932536 error_msg = error_msg + ": #{ fetch_error . message } " if !fetch_error . message . empty?
2494- raise error_msg
2537+ # raise error_msg
24952538 end
24962539 ensure # Free resources associated with the statement
24972540 IBM_DB . free_stmt ( stmt ) if stmt
@@ -2578,6 +2621,7 @@ def add_column(table_name, column_name, type, **options) # :nodoc:
25782621 puts_log "add_column"
25792622 clear_cache!
25802623 puts_log "add_column info #{ table_name } , #{ column_name } , #{ type } , #{ options } "
2624+ puts_log caller
25812625 if ( !type . nil? && type . to_s == "primary_key" ) or ( options . key? ( :primary_key ) and options [ :primary_key ] == true )
25822626 if !type . nil? and type . to_s != "primary_key"
25832627 execute "ALTER TABLE #{ table_name } ADD COLUMN #{ column_name } #{ type } NOT NULL DEFAULT 0"
@@ -2685,6 +2729,15 @@ def table_options(table_name) # :nodoc:
26852729 end
26862730 end
26872731
2732+ def remove_columns ( table_name , *column_names , type : nil , **options )
2733+ if column_names . empty?
2734+ raise ArgumentError . new ( "You must specify at least one column name. Example: remove_columns(:people, :first_name)" )
2735+ end
2736+
2737+ remove_column_fragments = remove_columns_for_alter ( table_name , *column_names , type : type , **options )
2738+ execute "ALTER TABLE #{ quote_table_name ( table_name ) } #{ remove_column_fragments . join ( ' ' ) } "
2739+ end
2740+
26882741 # Renames a table.
26892742 # ==== Example
26902743 # rename_table('octopuses', 'octopi')
@@ -2782,7 +2835,7 @@ def add_foreign_keyList(fkey_list, table_name, column_name, new_column_name)
27822835 puts_log "add_foreign_keyList = #{ table_name } , #{ column_name } , #{ fkey_list } "
27832836 fkey_list . each do |fkey |
27842837 if fkey . options [ :column ] == column_name
2785- add_foreign_key ( table_name , fkey . to_table , column : new_column_name )
2838+ add_foreign_key ( table_name , strip_table_name_prefix_and_suffix ( fkey . to_table ) , column : new_column_name )
27862839 end
27872840 end
27882841 end
@@ -2917,6 +2970,7 @@ def initialize_type_map(m = type_map) # :nodoc:
29172970
29182971 class SchemaDumper < ConnectionAdapters ::SchemaDumper
29192972 def dump ( stream ) # Like in abstract class, we no need to call header() & trailer().
2973+ header ( stream )
29202974 extensions ( stream )
29212975 tables ( stream )
29222976 stream
@@ -3724,7 +3778,7 @@ def visit_Arel_Nodes_ValuesList(o, collector)
37243778 row . each_with_index do |value , k |
37253779 collector << ", " unless k == 0
37263780 case value
3727- when Nodes ::SqlLiteral , Nodes ::BindParam
3781+ when Nodes ::SqlLiteral , Nodes ::BindParam , ActiveModel :: Attribute
37283782 collector = visit ( value , collector )
37293783 #collector << quote(value).to_s
37303784 else
0 commit comments