diff --git a/lib/active_record/connection_adapters/odbc_adapter.rb b/lib/active_record/connection_adapters/odbc_adapter.rb index bda26fc4..fdf68026 100644 --- a/lib/active_record/connection_adapters/odbc_adapter.rb +++ b/lib/active_record/connection_adapters/odbc_adapter.rb @@ -152,7 +152,7 @@ def initialize_type_map(map) map.register_type ODBC::SQL_TIMESTAMP, Type::DateTime.new map.register_type ODBC::SQL_GUID, Type::String.new - alias_type map, ODBC::SQL_BIT, ODBC::SQL_BIT + alias_type map, ODBC::SQL_BIT, 'boolean' alias_type map, ODBC::SQL_VARCHAR, ODBC::SQL_CHAR alias_type map, ODBC::SQL_WCHAR, ODBC::SQL_CHAR alias_type map, ODBC::SQL_WVARCHAR, ODBC::SQL_CHAR diff --git a/lib/odbc_adapter/adapters/mysql_odbc_adapter.rb b/lib/odbc_adapter/adapters/mysql_odbc_adapter.rb index fdf8c4b1..11711672 100644 --- a/lib/odbc_adapter/adapters/mysql_odbc_adapter.rb +++ b/lib/odbc_adapter/adapters/mysql_odbc_adapter.rb @@ -5,8 +5,22 @@ module Adapters class MySQLODBCAdapter < ActiveRecord::ConnectionAdapters::ODBCAdapter PRIMARY_KEY = 'INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY'.freeze + class BindSubstitution < Arel::Visitors::MySQL + include Arel::Visitors::BindVisitor + end + def arel_visitor - Arel::Visitors::MySQL.new(self) + BindSubstitution.new(self) + end + + # Explicitly turning off prepared statements in the MySQL adapter because + # of a weird bug with SQLDescribeParam returning a string type for LIMIT + # parameters. This is blocking them from running with an error: + # + # You have an error in your SQL syntax; ... + # ... right syntax to use near ''1'' at line 1: ... + def prepared_statements + false end def truncate(table_name, name = nil) diff --git a/lib/odbc_adapter/column.rb b/lib/odbc_adapter/column.rb index d230de24..31c099ff 100644 --- a/lib/odbc_adapter/column.rb +++ b/lib/odbc_adapter/column.rb @@ -2,7 +2,7 @@ module ODBCAdapter class Column < ActiveRecord::ConnectionAdapters::Column attr_reader :native_type - def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, native_type = nil) + def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, native_type = nil, default_function = nil, collation = nil) super(name, default, sql_type_metadata, null, table_name, default_function, collation) @native_type = native_type end diff --git a/lib/odbc_adapter/database_statements.rb b/lib/odbc_adapter/database_statements.rb index 5e6e29ad..67274091 100644 --- a/lib/odbc_adapter/database_statements.rb +++ b/lib/odbc_adapter/database_statements.rb @@ -5,24 +5,15 @@ module DatabaseStatements SQL_NULLABLE = 1 SQL_NULLABLE_UNKNOWN = 2 - # Returns an array of arrays containing the field values. - # Order is the same as that returned by #columns. - def select_rows(sql, name = nil) - log(sql, name) do - stmt = @connection.run(sql) - result = stmt.fetch_all - stmt.drop - result - end - end - # Executes the SQL statement in the context of this connection. # Returns the number of rows affected. def execute(sql, name = nil, binds = []) log(sql, name) do - prepared_binds = - prepare_binds_for_database(binds).map { |bind| _type_cast(bind) } - @connection.do(sql, *prepared_binds) + if prepared_statements + @connection.do(sql, *prepared_binds(binds)) + else + @connection.do(sql) + end end end @@ -31,10 +22,13 @@ def execute(sql, name = nil, binds = []) # the executed +sql+ statement. def exec_query(sql, name = 'SQL', binds = [], prepare: false) log(sql, name) do - prepared_binds = - prepare_binds_for_database(binds).map { |bind| _type_cast(bind) } + stmt = + if prepared_statements + @connection.run(sql, *prepared_binds(binds)) + else + @connection.run(sql) + end - stmt = @connection.run(sql, *prepared_binds) columns = stmt.columns values = stmt.to_a stmt.drop @@ -138,5 +132,9 @@ def nullability(col_name, is_nullable, nullable) # So force nullability of 'id' columns col_name == 'id' ? false : result end + + def prepared_binds(binds) + prepare_binds_for_database(binds).map { |bind| _type_cast(bind) } + end end end diff --git a/lib/odbc_adapter/schema_statements.rb b/lib/odbc_adapter/schema_statements.rb index 5d0f0828..d03c1e75 100644 --- a/lib/odbc_adapter/schema_statements.rb +++ b/lib/odbc_adapter/schema_statements.rb @@ -74,7 +74,7 @@ def columns(table_name, name = nil) # SQLColumns: IS_NULLABLE, SQLColumns: NULLABLE col_nullable = nullability(col_name, col[17], col[10]) - args = { sql_type: col_native_type, type: col_sql_type, limit: col_limit } + args = { sql_type: col_sql_type, type: col_sql_type, limit: col_limit } args[:sql_type] = 'boolean' if col_native_type == self.class::BOOLEAN_TYPE if [ODBC::SQL_DECIMAL, ODBC::SQL_NUMERIC].include?(col_sql_type) @@ -83,7 +83,7 @@ def columns(table_name, name = nil) end sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(**args) - cols << new_column(format_case(col_name), col_default, sql_type_metadata, col_nullable, table_name) + cols << new_column(format_case(col_name), col_default, sql_type_metadata, col_nullable, table_name, col_native_type) end end diff --git a/test/metadata_test.rb b/test/metadata_test.rb index b93bd466..eaa75091 100644 --- a/test/metadata_test.rb +++ b/test/metadata_test.rb @@ -1,8 +1,8 @@ require 'test_helper' class MetadataTest < Minitest::Test - def test_tables - assert_equal %w[ar_internal_metadata todos users], User.connection.tables.sort + def test_data_sources + assert_equal %w[ar_internal_metadata todos users], User.connection.data_sources.sort end def test_column_names