ibm_db 2.6.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -65,7 +65,7 @@ module ActiveRecord
65
65
  # the insert or update, and then proceeds to update that record with
66
66
  # the actual large object through a prepared statement (param binding).
67
67
  after_save :handle_lobs
68
- def handle_lobs()
68
+ def handle_lobs()
69
69
  if self.class.connection.kind_of?(ConnectionAdapters::IBM_DBAdapter)
70
70
  # Checks that the insert or update had at least a BLOB, CLOB or XML field
71
71
  self.class.connection.sql.each do |clob_sql|
@@ -78,9 +78,8 @@ module ActiveRecord
78
78
  values = []
79
79
  params = []
80
80
  # Selects only binary, text and xml columns
81
- self.class.columns.select{|col| col.type == :binary ||
82
- col.type == :text ||
83
- col.type == :xml}.each do |col|
81
+ self.class.columns.select{|col| col.sql_type.to_s =~ /blob|binary|clob|text|xml/i
82
+ }.each do |col|
84
83
  # Adds the selected columns to the query
85
84
  if counter == 0
86
85
  update_query << "#{col.name}"
@@ -92,14 +91,14 @@ module ActiveRecord
92
91
  # (except for a CLOB field where '' can be a value)
93
92
  if self[col.name].nil? ||
94
93
  self[col.name] == {} ||
95
- self[col.name] == [] ||
96
- (self[col.name] == '' && col.type != :text)
94
+ self[col.name] == [] ||
95
+ (self[col.name] == '' && !(col.sql_type.to_s =~ /text|clob/i))
97
96
  params << 'NULL'
98
97
  else
99
- if self.class.serialized_attributes[col.name]
100
- values << YAML.dump(self[col.name])
101
- else
102
- values << self[col.name]
98
+ if (col.cast_type.is_a?(::ActiveRecord::Type::Serialized))
99
+ values << YAML.dump(self[col.name])
100
+ else
101
+ values << self[col.name]
103
102
  end
104
103
  params << '?'
105
104
  end
@@ -283,22 +282,49 @@ module ActiveRecord
283
282
  module SchemaStatements
284
283
  def create_table_definition(name, temporary, options,as = nil)
285
284
  TableDefinition.new self, name, temporary, options
285
+ end
286
+
287
+ def remove_foreign_key(from_table, options_or_to_table = {})
288
+ return unless supports_foreign_keys?
289
+
290
+ if options_or_to_table.is_a?(Hash)
291
+ options = options_or_to_table
292
+ else
293
+ options = { column: foreign_key_column_for(options_or_to_table) }
294
+ end
295
+
296
+ fk_name_to_delete = options.fetch(:name) do
297
+ fk_to_delete = foreign_keys(@servertype.set_case(from_table)).detect {|fk| "#{@servertype.set_case(fk.column)}" == "#{servertype.set_case(options[:column])}"}
298
+
299
+ if fk_to_delete
300
+ fk_to_delete.name
301
+ else
302
+ raise ArgumentError, "Table '#{from_table}' has no foreign key on column '#{options[:column]}'"
303
+ end
304
+ end
305
+
306
+ at = create_alter_table from_table
307
+ at.drop_foreign_key fk_name_to_delete
308
+
309
+ execute schema_creation.accept(at)
286
310
  end
287
311
  end
312
+
288
313
  class IBM_DBColumn < Column
289
314
 
290
315
  # Casts value (which is a String) to an appropriate instance
316
+ =begin
291
317
  def type_cast(value)
292
318
  # Casts the database NULL value to nil
293
319
  return nil if value == 'NULL'
294
320
  # Invokes parent's method for default casts
295
321
  super
296
322
  end
297
-
323
+ =end
298
324
  # Used to convert from BLOBs to Strings
299
325
  def self.binary_to_string(value)
300
326
  # Returns a string removing the eventual BLOB scalar function
301
- value.to_s.gsub(/"SYSIBM"."BLOB"\('(.*)'\)/i,'\1')
327
+ value.to_s.gsub(/"SYSIBM"."BLOB"\('(.*)'\)/i,'\1')
302
328
  end
303
329
 
304
330
  private
@@ -946,24 +972,7 @@ module ActiveRecord
946
972
  end
947
973
  end
948
974
  end
949
- =begin
950
- # Returns an array of hashes with the column names as keys and
951
- # column values as values. +sql+ is the select query,
952
- # and +name+ is an optional description for logging
953
- def select(sql, name = nil)
954
- # Replaces {"= NULL" with " IS NULL"} OR {"IN (NULL)" with " IS NULL"}
955
- sql.gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" )
956
-
957
- results = []
958
- # Invokes the method +execute+ in order to log and execute the SQL
959
- # IBM_DB.Statement is returned from which results can be fetched
960
- stmt = execute(sql, name)
961
975
 
962
- results = fetch_data(stmt)
963
- # The array of record hashes is returned
964
- results
965
- end
966
- =end
967
976
  def select(sql, name = nil, binds = [])
968
977
  # Replaces {"= NULL" with " IS NULL"} OR {"IN (NULL)" with " IS NULL"}
969
978
  sql.gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" )
@@ -1062,14 +1071,12 @@ module ActiveRecord
1062
1071
  end
1063
1072
  end
1064
1073
  if item.at(1).nil? ||
1065
- item.at(1) == {} ||
1066
- (item.at(1) == '' && !(col.type.to_sym == :text))
1074
+ item.at(1) == {} ||
1075
+ (item.at(1) == '' && !(col.sql_type.to_s =~ /text|clob/i))
1067
1076
 
1068
1077
  params << 'NULL'
1069
-
1070
- elsif col.type.to_sym == :xml ||
1071
- col.type.to_sym == :text ||
1072
- col.type.to_sym == :binary
1078
+
1079
+ elsif (!col.nil? && (col.sql_type.to_s =~ /blob|binary|clob|text|xml/i) )
1073
1080
  # Add a '?' for the parameter or a NULL if the value is nil or empty
1074
1081
  # (except for a CLOB field where '' can be a value)
1075
1082
  insert_values << quote_value_for_pstmt(item.at(1))
@@ -1430,8 +1437,8 @@ module ActiveRecord
1430
1437
  case value
1431
1438
  when String, ActiveSupport::Multibyte::Chars then
1432
1439
  value = value.to_s
1433
- if column && [:integer, :float].include?(column.type)
1434
- value = column.type == :integer ? value.to_i : value.to_f
1440
+ if column && column.sql_type.to_s =~ /int|serial|float/i
1441
+ value = column.sql_type.to_s =~ /int|serial/i ? value.to_i : value.to_f
1435
1442
  value
1436
1443
  else
1437
1444
  value
@@ -1458,38 +1465,38 @@ module ActiveRecord
1458
1465
  return value.quoted_id if value.respond_to?(:quoted_id)
1459
1466
 
1460
1467
  case value
1461
- # If it's a numeric value and the column type is not a string, it shouldn't be quoted
1468
+ # If it's a numeric value and the column sql_type is not a string, it shouldn't be quoted
1462
1469
  # (IBM_DB doesn't accept quotes on numeric types)
1463
1470
  when Numeric
1464
- # If the column type is text or string, return the quote value
1465
- if column && column.type.to_sym == :text || column && column.type.to_sym == :string
1471
+ # If the column sql_type is text or string, return the quote value
1472
+ if (column && ( column.sql_type.to_s =~ /text|char/i ))
1466
1473
  unless caller[0] =~ /insert_fixture/i
1467
1474
  "'#{value}'"
1468
1475
  else
1469
1476
  "#{value}"
1470
1477
  end
1471
1478
  else
1472
- # value is Numeric, column.type is not a string,
1479
+ # value is Numeric, column.sql_type is not a string,
1473
1480
  # therefore it converts the number to string without quoting it
1474
1481
  value.to_s
1475
1482
  end
1476
1483
  when String, ActiveSupport::Multibyte::Chars
1477
- if column && column.type.to_sym == :binary && !(column.sql_type =~ /for bit data/i)
1484
+ if column && column.sql_type.to_s =~ /binary|blob/i && !(column.sql_type.to_s =~ /for bit data/i)
1478
1485
  # If quoting is required for the insert/update of a BLOB
1479
1486
  unless caller[0] =~ /add_column_options/i
1480
1487
  # Invokes a convertion from string to binary
1481
1488
  @servertype.set_binary_value
1482
1489
  else
1483
- # Quoting required for the default value of a column
1490
+ # Quoting required for the default value of a column
1484
1491
  @servertype.set_binary_default(value)
1485
1492
  end
1486
- elsif column && column.type.to_sym == :text
1493
+ elsif column && column.sql_type.to_s =~ /text|clob/i
1487
1494
  unless caller[0] =~ /add_column_options/i
1488
1495
  "'<ibm>@@@IBMTEXT@@@</ibm>'"
1489
1496
  else
1490
1497
  @servertype.set_text_default(quote_string(value))
1491
1498
  end
1492
- elsif column && column.type.to_sym == :xml
1499
+ elsif column && column.sql_type.to_s =~ /xml/i
1493
1500
  unless caller[0] =~ /add_column_options/i
1494
1501
  "'<ibm>@@@IBMXML@@@</ibm>'"
1495
1502
  else
@@ -1944,20 +1951,24 @@ module ActiveRecord
1944
1951
  #FKCOLUMN_NAME:: fk_row[7] Name of the column containing the foreign key.
1945
1952
  #FK_NAME:: fk_row[11] The name of the foreign key.
1946
1953
 
1954
+ table_name = @servertype.set_case(table_name.to_s)
1955
+ foreignKeys = []
1947
1956
  stmt = IBM_DB.foreignkeys( @connection, nil,
1948
1957
  @servertype.set_case(@schema),
1949
- @servertype.set_case(table_name))
1950
- foreignKeys = []
1958
+ @servertype.set_case(table_name), "FK_TABLE")
1951
1959
 
1952
1960
  if(stmt)
1953
1961
  begin
1954
1962
  while ( fk_row = IBM_DB.fetch_array(stmt) )
1955
1963
  options = {
1956
- column: fk_row[3],
1964
+ column: fk_row[7],
1957
1965
  name: fk_row[11],
1958
- primary_key: fk_row[7],
1966
+ primary_key: fk_row[3],
1959
1967
  }
1960
- foreignKeys << ForeignKeyDefinition.new(table_name, fk_row[6], options)
1968
+ options[:on_delete] = extract_foreign_key_action(fk_row[9])
1969
+ options[:on_update] = extract_foreign_key_action(fk_row[10])
1970
+ #foreignKeys << ForeignKeyDefinition.new(table_name, fk_row[6], options)
1971
+ foreignKeys << ForeignKeyDefinition.new(table_name, fk_row[2], options)
1961
1972
  end
1962
1973
 
1963
1974
  rescue StandardError => fetch_error # Handle driver fetch errors
@@ -1983,6 +1994,40 @@ module ActiveRecord
1983
1994
  #Returns the foreignKeys array
1984
1995
  return foreignKeys
1985
1996
  end
1997
+ def extract_foreign_key_action(specifier) # :nodoc:
1998
+ case specifier
1999
+ when 0; :cascade
2000
+ when 1; :restrict
2001
+ when 2; :nullify
2002
+ when 3; :noaction
2003
+ end
2004
+ end
2005
+
2006
+ def supports_disable_referential_integrity? #:nodoc:
2007
+ true
2008
+ end
2009
+
2010
+ def disable_referential_integrity #:nodoc:
2011
+ if supports_disable_referential_integrity?
2012
+ alter_foreign_keys(tables, true)
2013
+ end
2014
+
2015
+ yield
2016
+ ensure
2017
+ if supports_disable_referential_integrity?
2018
+ alter_foreign_keys(tables, false)
2019
+ end
2020
+
2021
+ end
2022
+
2023
+ def alter_foreign_keys(tables, not_enforced)
2024
+ enforced = not_enforced ? 'NOT ENFORCED' : 'ENFORCED'
2025
+ tables.each do |table|
2026
+ foreign_keys(table).each do |fk|
2027
+ execute("ALTER TABLE #{@servertype.set_case(fk.from_table)} ALTER FOREIGN KEY #{@servertype.set_case(fk.name)} #{enforced}")
2028
+ end
2029
+ end
2030
+ end
1986
2031
 
1987
2032
  # Renames a table.
1988
2033
  # ==== Example
@@ -2020,32 +2065,6 @@ module ActiveRecord
2020
2065
  @servertype.change_column(table_name, column_name, type, options)
2021
2066
  end
2022
2067
 
2023
- =begin
2024
- #overrides the abstract adapter method to generate proper sql
2025
- #specifying the column options, like default value and nullability clause
2026
- def add_column_options!(sql,options={})
2027
- #add default null option only if :default option is not specified and
2028
- #:null option is not specified or is true
2029
- if (options[:default].nil? && (options[:null].nil? || options[:null] == true))
2030
- sql << " DEFAULT NULL"
2031
- else
2032
- if( !options[:default].nil?)
2033
- #check, :column option is passed only in case of create_table but not in case of add_column
2034
- if (!options[:column].nil?)
2035
- sql << " DEFAULT #{quote(options[:default],options[:column])}"
2036
- else
2037
- sql << " DEFAULT #{quote(options[:default])}"
2038
- end
2039
- end
2040
- #append NOT NULL to sql only---
2041
- #---if options[:null] is not nil and is equal to false
2042
- unless options[:null] == nil
2043
- sql << " NOT NULL" if (options[:null] == false)
2044
- end
2045
- end
2046
- end
2047
- =end
2048
-
2049
2068
  #Add distinct clause to the sql if there is no order by specified
2050
2069
  def distinct(columns, order_by)
2051
2070
  if order_by.nil?
@@ -2054,6 +2073,17 @@ module ActiveRecord
2054
2073
  "#{columns}"
2055
2074
  end
2056
2075
  end
2076
+
2077
+ def columns_for_distinct(columns, orders) #:nodoc:
2078
+ order_columns = orders.reject(&:blank?).map{ |s|
2079
+ # Convert Arel node to string
2080
+ s = s.to_sql unless s.is_a?(String)
2081
+ # Remove any ASC/DESC modifiers
2082
+ s.gsub(/\s+(?:ASC|DESC)\b/i, '')
2083
+ .gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, '')
2084
+ }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
2085
+ [super, *order_columns].join(', ')
2086
+ end
2057
2087
 
2058
2088
  # Sets a new default value for a column. This does not set the default
2059
2089
  # value to +NULL+, instead, it needs DatabaseStatements#execute which
@@ -2429,206 +2459,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
2429
2459
  def get_double_mapping
2430
2460
  return "double"
2431
2461
  end
2432
- =begin
2433
- # Commenting this code, as offset handling is now part of sql and we need to handle it in select and also
2434
- # need not set cursor type during prepare or execute
2435
- # Fetches all the results available. IBM_DB.fetch_assoc(stmt) returns
2436
- # an hash for each single record.
2437
- # The loop stops when there aren't any more valid records to fetch
2438
- def select(stmt)
2439
- results = []
2440
- begin
2441
- if (!@offset.nil? && @offset >= 0) || (!@limit.nil? && @limit > 0)
2442
- # We know at this point that there is an offset and/or a limit
2443
- # Check if the cursor type is set correctly
2444
- cursor_type = IBM_DB.get_option stmt, IBM_DB::SQL_ATTR_CURSOR_TYPE, 0
2445
- @offset = 0 if @offset.nil?
2446
- if (cursor_type == IBM_DB::SQL_CURSOR_STATIC)
2447
- index = 0
2448
- # Get @limit rows starting at @offset
2449
- while (index < @limit)
2450
- # We increment the offset by 1 because for DB2 the offset of the initial row is 1 instead of 0
2451
- if single_hash = IBM_DB.fetch_assoc(stmt, @offset + index + 1)
2452
- # Add the record to the +results+ array
2453
- results << single_hash
2454
- index = index + 1
2455
- else
2456
- # break from the while loop
2457
- break
2458
- end
2459
- end
2460
- else # cursor != IBM_DB::SQL_CURSOR_STATIC
2461
- # If the result set contains a LOB, the cursor type will never be SQL_CURSOR_STATIC
2462
- # because DB2 does not allow this. We can't use the offset mechanism because the cursor
2463
- # is not scrollable. In this case, ignore first @offset rows and return rows starting
2464
- # at @offset to @offset + @limit
2465
- index = 0
2466
- while (index < @offset + @limit)
2467
- if single_hash = IBM_DB.fetch_assoc(stmt)
2468
- # Add the record to the +results+ array only from row @offset to @offset + @limit
2469
- if (index >= @offset)
2470
- results << single_hash
2471
- end
2472
- index = index + 1
2473
- else
2474
- # break from the while loop
2475
- break
2476
- end
2477
- end
2478
- end
2479
- # This is the case where limit is set to zero
2480
- # Simply return an empty +results+
2481
- elsif (!@limit.nil? && @limit == 0)
2482
- results
2483
- # No limits or offsets specified
2484
- else
2485
- while single_hash = IBM_DB.fetch_assoc(stmt)
2486
- # Add the record to the +results+ array
2487
- results << single_hash
2488
- end
2489
- return results
2490
- end
2491
- rescue StandardError => fetch_error # Handle driver fetch errors
2492
- error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
2493
- if error_msg && !error_msg.empty?
2494
- raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
2495
- else
2496
- error_msg = "An unexpected error occurred during data retrieval"
2497
- error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
2498
- raise error_msg
2499
- end
2500
- ensure
2501
- # Assign the instance variables to nil. We will not be using them again
2502
- @offset = nil
2503
- @limit = nil
2504
- end
2505
- end
2506
2462
 
2507
- # Fetches all the results available. IBM_DB.fetch_array(stmt) returns
2508
- # an array for each single record.
2509
- # The loop stops when there aren't any more valid records to fetch
2510
- def select_rows(sql, name, stmt, results)
2511
- begin
2512
- if (!@offset.nil? && @offset >= 0) || (!@limit.nil? && @limit > 0)
2513
- # We know at this point that there is an offset and/or a limit
2514
- # Check if the cursor type is set correctly
2515
- cursor_type = IBM_DB.get_option stmt, IBM_DB::SQL_ATTR_CURSOR_TYPE, 0
2516
- @offset = 0 if @offset.nil?
2517
- if (cursor_type == IBM_DB::SQL_CURSOR_STATIC)
2518
- index = 0
2519
- # Get @limit rows starting at @offset
2520
- while (index < @limit)
2521
- # We increment the offset by 1 because for DB2 the offset of the initial row is 1 instead of 0
2522
- if single_array = IBM_DB.fetch_array(stmt, @offset + index + 1)
2523
- # Add the array to the +results+ array
2524
- results << single_array
2525
- index = index + 1
2526
- else
2527
- # break from the while loop
2528
- break
2529
- end
2530
- end
2531
- else # cursor != IBM_DB::SQL_CURSOR_STATIC
2532
- # If the result set contains a LOB, the cursor type will never be SQL_CURSOR_STATIC
2533
- # because DB2 does not allow this. We can't use the offset mechanism because the cursor
2534
- # is not scrollable. In this case, ignore first @offset rows and return rows starting
2535
- # at @offset to @offset + @limit
2536
- index = 0
2537
- while (index < @offset + @limit)
2538
- if single_array = IBM_DB.fetch_array(stmt)
2539
- # Add the array to the +results+ array only from row @offset to @offset + @limit
2540
- if (index >= @offset)
2541
- results << single_array
2542
- end
2543
- index = index + 1
2544
- else
2545
- # break from the while loop
2546
- break
2547
- end
2548
- end
2549
- end
2550
- # This is the case where limit is set to zero
2551
- # Simply return an empty +results+
2552
- elsif (!@limit.nil? && @limit == 0)
2553
- results
2554
- # No limits or offsets specified
2555
- else
2556
- while single_array = IBM_DB.fetch_array(stmt)
2557
- # Add the array to the +results+ array
2558
- results << single_array
2559
- end
2560
- end
2561
- rescue StandardError => fetch_error # Handle driver fetch errors
2562
- error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
2563
- if error_msg && !error_msg.empty?
2564
- raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
2565
- else
2566
- error_msg = "An unexpected error occurred during data retrieval"
2567
- error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
2568
- raise error_msg
2569
- end
2570
- ensure
2571
- # Assign the instance variables to nil. We will not be using them again
2572
- @offset = nil
2573
- @limit = nil
2574
- end
2575
- return results
2576
- end
2577
-
2578
- # Praveen
2579
- def prepare(sql,name = nil)
2580
- # Check if there is a limit and/or an offset
2581
- # If so then make sure and use a static cursor type
2582
- begin
2583
- if (!@offset.nil? && @offset >= 0) || (!@limit.nil? && @limit > 0)
2584
- # Set the cursor type to static so we can later utilize the offset and limit correctly
2585
- if stmt = IBM_DB.prepare(@adapter.connection, sql,
2586
- {IBM_DB::SQL_ATTR_CURSOR_TYPE => IBM_DB::SQL_CURSOR_STATIC})
2587
- stmt # Return the statement object
2588
- else
2589
- raise StatementInvalid, IBM_DB.getErrormsg(@adapter.connection, IBM_DB::DB_CONN )
2590
- end
2591
- else
2592
- if stmt = IBM_DB.prepare(@adapter.connection, sql)
2593
- stmt # Return the statement object
2594
- else
2595
- raise StatementInvalid, IBM_DB.getErrormsg(@adapter.connection, IBM_DB::DB_CONN )
2596
- end
2597
- end
2598
- rescue StandardError => prep_err
2599
- error_msg = "Failed to prepare sql #{sql}"
2600
- error_msg = error_msg + ": #{prep_err.message}" if !prep_err.message.empty?
2601
- raise error_msg
2602
- end
2603
- end
2604
-
2605
- # Praveen
2606
- def execute(sql, name = nil)
2607
- # Check if there is a limit and/or an offset
2608
- # If so then make sure and use a static cursor type
2609
- begin
2610
- if (!@offset.nil? && @offset >= 0) || (!@limit.nil? && @limit > 0)
2611
- # Set the cursor type to static so we can later utilize the offset and limit correctly
2612
- if stmt = IBM_DB.exec(@adapter.connection, sql,
2613
- {IBM_DB::SQL_ATTR_CURSOR_TYPE => IBM_DB::SQL_CURSOR_STATIC})
2614
- stmt # Return the statement object
2615
- else
2616
- raise StatementInvalid, IBM_DB.getErrormsg(@adapter.connection, IBM_DB::DB_CONN )
2617
- end
2618
- else
2619
- if stmt = IBM_DB.exec(@adapter.connection, sql)
2620
- stmt # Return the statement object
2621
- else
2622
- raise StatementInvalid, IBM_DB.getErrormsg(@adapter.connection, IBM_DB::DB_CONN )
2623
- end
2624
- end
2625
- rescue StandardError => exec_err
2626
- error_msg = "Failed to execute statement"
2627
- error_msg = error_msg + ": #{exec_err.message}" if !exec_err.message.empty?
2628
- raise error_msg
2629
- end
2630
- end
2631
- =end
2632
2463
  def get_limit_offset_clauses(limit, offset)
2633
2464
  retHash = {"endSegment"=> "", "startSegment" => ""}
2634
2465
  if(offset.nil? && limit.nil?)
@@ -2982,7 +2813,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
2982
2813
  is_nullable = true
2983
2814
  @adapter.columns(table_name).select do |col|
2984
2815
  if (col.name == column_name)
2985
- sql_type = @adapter.type_to_sql(col.type, col.limit, col.precision, col.scale)
2816
+ sql_type = @adapter.type_to_sql(col.sql_type, col.limit, col.precision, col.scale)
2986
2817
  is_nullable = col.null
2987
2818
  end
2988
2819
  end
@@ -3004,7 +2835,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
3004
2835
  sql_type = nil
3005
2836
  @adapter.columns(table_name).select do |col|
3006
2837
  if (col.name == column_name)
3007
- sql_type = @adapter.type_to_sql(col.type, col.limit, col.precision, col.scale)
2838
+ sql_type = @adapter.type_to_sql(col.sql_type, col.limit, col.precision, col.scale)
3008
2839
  end
3009
2840
  end
3010
2841
  if !null.nil?