activerecord-jdbc-adapter 1.1.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +22 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +42 -0
- data/History.txt +10 -3
- data/{README.txt → README.rdoc} +30 -14
- data/Rakefile +49 -0
- data/activerecord-jdbc-adapter.gemspec +23 -0
- data/bench/bench_attributes.rb +13 -0
- data/bench/bench_attributes_new.rb +14 -0
- data/bench/bench_create.rb +12 -0
- data/bench/bench_find_all.rb +12 -0
- data/bench/bench_find_all_mt.rb +25 -0
- data/bench/bench_model.rb +85 -0
- data/bench/bench_new.rb +12 -0
- data/bench/bench_new_valid.rb +12 -0
- data/bench/bench_valid.rb +13 -0
- data/lib/activerecord-jdbc-adapter.rb +1 -1
- data/lib/arel/visitors/derby.rb +5 -1
- data/lib/arjdbc.rb +12 -17
- data/lib/arjdbc/db2/adapter.rb +91 -4
- data/lib/arjdbc/derby/adapter.rb +8 -8
- data/lib/arjdbc/derby/connection_methods.rb +1 -0
- data/lib/arjdbc/firebird/adapter.rb +4 -4
- data/lib/arjdbc/h2/adapter.rb +3 -2
- data/lib/arjdbc/h2/connection_methods.rb +1 -0
- data/lib/arjdbc/hsqldb/adapter.rb +5 -2
- data/lib/arjdbc/hsqldb/connection_methods.rb +1 -0
- data/lib/arjdbc/informix/adapter.rb +2 -2
- data/lib/arjdbc/informix/connection_methods.rb +1 -0
- data/lib/arjdbc/jdbc/adapter.rb +92 -22
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/mimer/adapter.rb +4 -4
- data/lib/arjdbc/mssql/adapter.rb +10 -8
- data/lib/arjdbc/mssql/connection_methods.rb +1 -0
- data/lib/arjdbc/mssql/limit_helpers.rb +7 -4
- data/lib/arjdbc/mysql/adapter.rb +30 -6
- data/lib/arjdbc/mysql/connection_methods.rb +1 -0
- data/lib/arjdbc/oracle/adapter.rb +15 -12
- data/lib/arjdbc/oracle/connection_methods.rb +1 -0
- data/lib/arjdbc/postgresql/adapter.rb +35 -16
- data/lib/arjdbc/postgresql/connection_methods.rb +1 -0
- data/lib/arjdbc/sqlite3/adapter.rb +13 -10
- data/lib/arjdbc/sqlite3/connection_methods.rb +1 -0
- data/lib/arjdbc/version.rb +1 -1
- data/lib/generators/jdbc/USAGE +10 -0
- data/pom.xml +57 -0
- data/rakelib/rails.rake +1 -1
- data/rakelib/test.rake +20 -6
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +4 -1
- data/src/java/arjdbc/jdbc/SQLBlock.java +1 -1
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +74 -0
- data/test/abstract_db_create.rb +8 -1
- data/test/activerecord/jall.sh +7 -0
- data/test/activerecord/jtest.sh +3 -0
- data/test/jdbc_common.rb +6 -4
- data/test/models/data_types.rb +1 -1
- data/test/models/string_id.rb +2 -0
- data/test/models/thing.rb +16 -0
- data/test/mysql_index_length_test.rb +58 -0
- data/test/mysql_info_test.rb +3 -3
- data/test/postgres_db_create_test.rb +1 -1
- data/test/simple.rb +11 -3
- data/test/sqlite3_simple_test.rb +16 -2
- metadata +167 -108
- data/.gemtest +0 -0
- data/Manifest.txt +0 -187
- data/rakelib/package.rake +0 -92
- data/test/pick_rails_version.rb +0 -3
| Binary file | 
    
        data/lib/arjdbc/mimer/adapter.rb
    CHANGED
    
    | @@ -44,9 +44,9 @@ module ArJdbc | |
| 44 44 | 
             
                  execute "DROP INDEX #{index_name(table_name, options)}"
         | 
| 45 45 | 
             
                end
         | 
| 46 46 |  | 
| 47 | 
            -
                def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
         | 
| 47 | 
            +
                def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) #:nodoc:
         | 
| 48 48 | 
             
                  if pk.nil? # Who called us? What does the sql look like? No idea!
         | 
| 49 | 
            -
                    execute sql, name
         | 
| 49 | 
            +
                    execute sql, name, binds
         | 
| 50 50 | 
             
                  elsif id_value # Pre-assigned id
         | 
| 51 51 | 
             
                    log(sql, name) { @connection.execute_insert sql,pk }
         | 
| 52 52 | 
             
                  else # Assume the sql contains a bind-variable for the id
         | 
| @@ -104,14 +104,14 @@ module ArJdbc | |
| 104 104 | 
             
                  @offset = options[:offset]
         | 
| 105 105 | 
             
                end
         | 
| 106 106 |  | 
| 107 | 
            -
                def select_all(sql, name = nil)
         | 
| 107 | 
            +
                def select_all(sql, name = nil, binds = [])
         | 
| 108 108 | 
             
                  @offset ||= 0
         | 
| 109 109 | 
             
                  if !@limit || @limit == -1
         | 
| 110 110 | 
             
                    range = @offset..-1
         | 
| 111 111 | 
             
                  else
         | 
| 112 112 | 
             
                    range = @offset...(@offset+@limit)
         | 
| 113 113 | 
             
                  end
         | 
| 114 | 
            -
                  select(sql, name)[range]
         | 
| 114 | 
            +
                  select(sql, name, binds)[range]
         | 
| 115 115 | 
             
                ensure
         | 
| 116 116 | 
             
                  @limit = @offset = nil
         | 
| 117 117 | 
             
                end
         | 
    
        data/lib/arjdbc/mssql/adapter.rb
    CHANGED
    
    | @@ -7,7 +7,7 @@ module ::ArJdbc | |
| 7 7 | 
             
                include LimitHelpers
         | 
| 8 8 |  | 
| 9 9 | 
             
                def self.extended(mod)
         | 
| 10 | 
            -
                  unless @lob_callback_added
         | 
| 10 | 
            +
                  unless defined?(@lob_callback_added)
         | 
| 11 11 | 
             
                    ActiveRecord::Base.class_eval do
         | 
| 12 12 | 
             
                      def after_save_with_mssql_lob
         | 
| 13 13 | 
             
                        self.class.columns.select { |c| c.sql_type =~ /image/i }.each do |c|
         | 
| @@ -34,10 +34,10 @@ module ::ArJdbc | |
| 34 34 | 
             
                  ::ActiveRecord::ConnectionAdapters::MssqlJdbcConnection
         | 
| 35 35 | 
             
                end
         | 
| 36 36 |  | 
| 37 | 
            -
                def arel2_visitors
         | 
| 37 | 
            +
                def self.arel2_visitors(config)
         | 
| 38 38 | 
             
                  require 'arel/visitors/sql_server'
         | 
| 39 | 
            -
                  visitor_class = sqlserver_version == "2000" ? ::Arel::Visitors::SQLServer2000 : ::Arel::Visitors::SQLServer
         | 
| 40 | 
            -
                  {  | 
| 39 | 
            +
                  visitor_class = config[:sqlserver_version] == "2000" ? ::Arel::Visitors::SQLServer2000 : ::Arel::Visitors::SQLServer
         | 
| 40 | 
            +
                  {}.tap {|v| %w(mssql sqlserver jdbcmssql).each {|x| v[x] = visitor_class } }
         | 
| 41 41 | 
             
                end
         | 
| 42 42 |  | 
| 43 43 | 
             
                def sqlserver_version
         | 
| @@ -45,7 +45,8 @@ module ::ArJdbc | |
| 45 45 | 
             
                end
         | 
| 46 46 |  | 
| 47 47 | 
             
                def add_version_specific_add_limit_offset
         | 
| 48 | 
            -
                   | 
| 48 | 
            +
                  config[:sqlserver_version] = version = sqlserver_version
         | 
| 49 | 
            +
                  if version == "2000"
         | 
| 49 50 | 
             
                    extend LimitHelpers::SqlServer2000AddLimitOffset
         | 
| 50 51 | 
             
                  else
         | 
| 51 52 | 
             
                    extend LimitHelpers::SqlServerAddLimitOffset
         | 
| @@ -110,7 +111,7 @@ module ::ArJdbc | |
| 110 111 | 
             
                  def type_cast(value)
         | 
| 111 112 | 
             
                    return nil if value.nil? || value == "(null)" || value == "(NULL)"
         | 
| 112 113 | 
             
                    case type
         | 
| 113 | 
            -
                    when :integer then value.to_i rescue unquote(value).to_i rescue value ? 1 : 0
         | 
| 114 | 
            +
                    when :integer then value.delete('()').to_i rescue unquote(value).to_i rescue value ? 1 : 0
         | 
| 114 115 | 
             
                    when :primary_key then value == true || value == false ? value == true ? 1 : 0 : value.to_i
         | 
| 115 116 | 
             
                    when :decimal   then self.class.value_to_decimal(unquote(value))
         | 
| 116 117 | 
             
                    when :datetime  then cast_to_datetime(value)
         | 
| @@ -347,7 +348,7 @@ module ::ArJdbc | |
| 347 348 | 
             
                  table_name = table_name.gsub(/[\[\]]/, '')
         | 
| 348 349 |  | 
| 349 350 | 
             
                  return [] if table_name =~ /^information_schema\./i
         | 
| 350 | 
            -
                  @table_columns  | 
| 351 | 
            +
                  @table_columns ||= {}
         | 
| 351 352 | 
             
                  unless @table_columns[table_name]
         | 
| 352 353 | 
             
                    @table_columns[table_name] = super
         | 
| 353 354 | 
             
                    @table_columns[table_name].each do |col|
         | 
| @@ -381,7 +382,8 @@ module ::ArJdbc | |
| 381 382 | 
             
                  end
         | 
| 382 383 | 
             
                end
         | 
| 383 384 |  | 
| 384 | 
            -
                def select(sql, name = nil)
         | 
| 385 | 
            +
                def select(sql, name = nil, binds = [])
         | 
| 386 | 
            +
                  sql = substitute_binds(sql, binds)
         | 
| 385 387 | 
             
                  log(sql, name) do
         | 
| 386 388 | 
             
                    @connection.execute_query(sql)
         | 
| 387 389 | 
             
                  end
         | 
| @@ -5,6 +5,7 @@ class ActiveRecord::Base | |
| 5 5 | 
             
                  config[:host] ||= "localhost"
         | 
| 6 6 | 
             
                  config[:port] ||= 1433
         | 
| 7 7 | 
             
                  config[:driver] ||= "net.sourceforge.jtds.jdbc.Driver"
         | 
| 8 | 
            +
                  config[:adapter_spec] = ::ArJdbc::MsSQL
         | 
| 8 9 |  | 
| 9 10 | 
             
                  url = "jdbc:jtds:sqlserver://#{config[:host]}:#{config[:port]}/#{config[:database]}"
         | 
| 10 11 |  | 
| @@ -31,10 +31,13 @@ module ::ArJdbc | |
| 31 31 | 
             
                          rest = rest_of_query[/FROM/i=~ rest_of_query.. -1]
         | 
| 32 32 | 
             
                          #need the table name for avoiding amiguity
         | 
| 33 33 | 
             
                          table_name = LimitHelpers.get_table_name(sql)
         | 
| 34 | 
            -
                          primary_key = order[/(\w*id\w*)/i]
         | 
| 34 | 
            +
                          primary_key = order[/(\w*id\w*)/i] || "id"
         | 
| 35 35 | 
             
                          #I am not sure this will cover all bases.  but all the tests pass
         | 
| 36 | 
            -
                           | 
| 37 | 
            -
             | 
| 36 | 
            +
                          if order[/ORDER/].nil?
         | 
| 37 | 
            +
                            new_order = "ORDER BY #{order}, #{table_name}.#{primary_key}" if order.index("#{table_name}.#{primary_key}").nil?
         | 
| 38 | 
            +
                          else
         | 
| 39 | 
            +
                            new_order ||= order
         | 
| 40 | 
            +
                          end
         | 
| 38 41 |  | 
| 39 42 | 
             
                          if (rest_of_query.match(/WHERE/).nil?)
         | 
| 40 43 | 
             
                            new_sql = "#{select} TOP #{limit} #{rest_of_query} WHERE #{table_name}.#{primary_key} NOT IN (#{select} TOP #{offset} #{table_name}.#{primary_key} #{rest} #{new_order}) #{order} "
         | 
| @@ -69,7 +72,7 @@ module ::ArJdbc | |
| 69 72 | 
             
                        find_select = /\b(SELECT(?:\s+DISTINCT)?)\b(.*)/im
         | 
| 70 73 | 
             
                        whole, select, rest_of_query = find_select.match(sql).to_a
         | 
| 71 74 | 
             
                        rest_of_query.strip!
         | 
| 72 | 
            -
                        if rest_of_query[0] == "1"
         | 
| 75 | 
            +
                        if rest_of_query[0...1] == "1" && rest_of_query !~ /1 AS/i
         | 
| 73 76 | 
             
                          rest_of_query[0] = "*"
         | 
| 74 77 | 
             
                        end
         | 
| 75 78 | 
             
                        if rest_of_query[0] == "*"
         | 
    
        data/lib/arjdbc/mysql/adapter.rb
    CHANGED
    
    | @@ -98,14 +98,18 @@ module ::ArJdbc | |
| 98 98 | 
             
                  'MySQL'
         | 
| 99 99 | 
             
                end
         | 
| 100 100 |  | 
| 101 | 
            -
                def arel2_visitors
         | 
| 102 | 
            -
                  { | 
| 101 | 
            +
                def self.arel2_visitors(config)
         | 
| 102 | 
            +
                  {}.tap {|v| %w(mysql mysql2 jdbcmysql).each {|a| v[a] = ::Arel::Visitors::MySQL } }
         | 
| 103 103 | 
             
                end
         | 
| 104 104 |  | 
| 105 105 | 
             
                def case_sensitive_equality_operator
         | 
| 106 106 | 
             
                  "= BINARY"
         | 
| 107 107 | 
             
                end
         | 
| 108 108 |  | 
| 109 | 
            +
                def case_sensitive_modifier(node)
         | 
| 110 | 
            +
                  Arel::Nodes::Bin.new(node)
         | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
             | 
| 109 113 | 
             
                def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
         | 
| 110 114 | 
             
                  where_sql
         | 
| 111 115 | 
             
                end
         | 
| @@ -338,6 +342,19 @@ module ::ArJdbc | |
| 338 342 | 
             
                end
         | 
| 339 343 |  | 
| 340 344 | 
             
                protected
         | 
| 345 | 
            +
                def quoted_columns_for_index(column_names, options = {})
         | 
| 346 | 
            +
                  length = options[:length] if options.is_a?(Hash)
         | 
| 347 | 
            +
             | 
| 348 | 
            +
                  case length
         | 
| 349 | 
            +
                    when Hash
         | 
| 350 | 
            +
                      column_names.map { |name| length[name] ? "#{quote_column_name(name)}(#{length[name]})" : quote_column_name(name) }
         | 
| 351 | 
            +
                    when Fixnum
         | 
| 352 | 
            +
                      column_names.map { |name| "#{quote_column_name(name)}(#{length})" }
         | 
| 353 | 
            +
                    else
         | 
| 354 | 
            +
                      column_names.map { |name| quote_column_name(name) }
         | 
| 355 | 
            +
                  end
         | 
| 356 | 
            +
                end
         | 
| 357 | 
            +
             | 
| 341 358 | 
             
                def translate_exception(exception, message)
         | 
| 342 359 | 
             
                  return super unless exception.respond_to?(:errno)
         | 
| 343 360 |  | 
| @@ -397,10 +414,6 @@ module ActiveRecord::ConnectionAdapters | |
| 397 414 | 
             
                  configure_connection
         | 
| 398 415 | 
             
                end
         | 
| 399 416 |  | 
| 400 | 
            -
                def adapter_spec(config)
         | 
| 401 | 
            -
                  # return nil to avoid extending ArJdbc::MySQL, which we've already done
         | 
| 402 | 
            -
                end
         | 
| 403 | 
            -
             | 
| 404 417 | 
             
                def jdbc_connection_class(spec)
         | 
| 405 418 | 
             
                  ::ArJdbc::MySQL.jdbc_connection_class
         | 
| 406 419 | 
             
                end
         | 
| @@ -410,6 +423,17 @@ module ActiveRecord::ConnectionAdapters | |
| 410 423 | 
             
                end
         | 
| 411 424 |  | 
| 412 425 | 
             
                alias_chained_method :columns, :query_cache, :jdbc_columns
         | 
| 426 | 
            +
             | 
| 427 | 
            +
                protected
         | 
| 428 | 
            +
                def exec_insert(sql, name, binds)
         | 
| 429 | 
            +
                  binds = binds.dup
         | 
| 430 | 
            +
             | 
| 431 | 
            +
                  # Pretend to support bind parameters
         | 
| 432 | 
            +
                  execute sql.gsub('?') { quote(*binds.shift.reverse) }, name
         | 
| 433 | 
            +
                end
         | 
| 434 | 
            +
                alias :exec_update :exec_insert
         | 
| 435 | 
            +
                alias :exec_delete :exec_insert
         | 
| 436 | 
            +
             | 
| 413 437 | 
             
              end
         | 
| 414 438 | 
             
            end
         | 
| 415 439 |  | 
| @@ -15,6 +15,7 @@ class ActiveRecord::Base | |
| 15 15 | 
             
                  config[:url] ||= "jdbc:mysql://#{config[:host]}:#{config[:port]}/#{config[:database]}"
         | 
| 16 16 | 
             
                  config[:driver] ||= "com.mysql.jdbc.Driver"
         | 
| 17 17 | 
             
                  config[:adapter_class] = ActiveRecord::ConnectionAdapters::MysqlAdapter
         | 
| 18 | 
            +
                  config[:adapter_spec] = ::ArJdbc::MySQL
         | 
| 18 19 | 
             
                  connection = jdbc_connection(config)
         | 
| 19 20 | 
             
                  ::ArJdbc::MySQL.kill_cancel_timer(connection.raw_connection)
         | 
| 20 21 | 
             
                  connection
         | 
| @@ -5,7 +5,7 @@ end | |
| 5 5 | 
             
            module ::ArJdbc
         | 
| 6 6 | 
             
              module Oracle
         | 
| 7 7 | 
             
                def self.extended(mod)
         | 
| 8 | 
            -
                  unless @lob_callback_added
         | 
| 8 | 
            +
                  unless defined?(@lob_callback_added)
         | 
| 9 9 | 
             
                    ActiveRecord::Base.class_eval do
         | 
| 10 10 | 
             
                      def after_save_with_oracle_lob
         | 
| 11 11 | 
             
                        self.class.columns.select { |c| c.sql_type =~ /LOB\(|LOB$/i }.each do |c|
         | 
| @@ -21,8 +21,12 @@ module ::ArJdbc | |
| 21 21 | 
             
                    ActiveRecord::Base.after_save :after_save_with_oracle_lob
         | 
| 22 22 | 
             
                    @lob_callback_added = true
         | 
| 23 23 | 
             
                  end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                  ActiveRecord:: | 
| 24 | 
            +
             | 
| 25 | 
            +
                  unless ActiveRecord::ConnectionAdapters::AbstractAdapter.instance_methods(false).detect {|m| m.to_s == "prefetch_primary_key?"}
         | 
| 26 | 
            +
                    require 'arjdbc/jdbc/quoted_primary_key'
         | 
| 27 | 
            +
                    ActiveRecord::Base.extend ArJdbc::QuotedPrimaryKeyExtension
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 26 30 | 
             
                  (class << mod; self; end).class_eval do
         | 
| 27 31 | 
             
                    alias_chained_method :insert, :query_dirty, :ora_insert
         | 
| 28 32 | 
             
                    alias_chained_method :columns, :query_cache, :ora_columns
         | 
| @@ -110,14 +114,13 @@ module ::ArJdbc | |
| 110 114 | 
             
                  'Oracle'
         | 
| 111 115 | 
             
                end
         | 
| 112 116 |  | 
| 113 | 
            -
                def arel2_visitors
         | 
| 117 | 
            +
                def self.arel2_visitors(config)
         | 
| 114 118 | 
             
                  { 'oracle' => Arel::Visitors::Oracle }
         | 
| 115 119 | 
             
                end
         | 
| 116 120 |  | 
| 117 | 
            -
                 | 
| 118 | 
            -
             | 
| 119 | 
            -
                 | 
| 120 | 
            -
                # end
         | 
| 121 | 
            +
                def prefetch_primary_key?(table_name = nil)
         | 
| 122 | 
            +
                  columns(table_name).detect {|c| c.primary } if table_name
         | 
| 123 | 
            +
                end
         | 
| 121 124 |  | 
| 122 125 | 
             
                def table_alias_length
         | 
| 123 126 | 
             
                  30
         | 
| @@ -163,12 +166,12 @@ module ::ArJdbc | |
| 163 166 | 
             
                  defined?(::Arel::SqlLiteral) && ::Arel::SqlLiteral === value
         | 
| 164 167 | 
             
                end
         | 
| 165 168 |  | 
| 166 | 
            -
                def ora_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
         | 
| 169 | 
            +
                def ora_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) #:nodoc:
         | 
| 167 170 | 
             
                  if (id_value && !sql_literal?(id_value)) || pk.nil?
         | 
| 168 171 | 
             
                    # Pre-assigned id or table without a primary key
         | 
| 169 172 | 
             
                    # Presence of #to_sql means an Arel literal bind variable
         | 
| 170 173 | 
             
                    # that should use #execute_id_insert below
         | 
| 171 | 
            -
                    execute sql, name
         | 
| 174 | 
            +
                    execute sql, name, binds
         | 
| 172 175 | 
             
                  else
         | 
| 173 176 | 
             
                    # Assume the sql contains a bind-variable for the id
         | 
| 174 177 | 
             
                    # Extract the table from the insert sql. Yuck.
         | 
| @@ -406,8 +409,8 @@ module ::ArJdbc | |
| 406 409 | 
             
                  end
         | 
| 407 410 | 
             
                end
         | 
| 408 411 |  | 
| 409 | 
            -
                def select(sql, name=nil)
         | 
| 410 | 
            -
                  records = execute(sql,name)
         | 
| 412 | 
            +
                def select(sql, name = nil, binds = [])
         | 
| 413 | 
            +
                  records = execute(sql, name, binds)
         | 
| 411 414 | 
             
                  records.each do |col|
         | 
| 412 415 | 
             
                      col.delete('raw_rnum_')
         | 
| 413 416 | 
             
                  end
         | 
| @@ -4,6 +4,7 @@ class ActiveRecord::Base | |
| 4 4 | 
             
                  config[:port] ||= 1521
         | 
| 5 5 | 
             
                  config[:url] ||= "jdbc:oracle:thin:@#{config[:host]}:#{config[:port]}:#{config[:database]}"
         | 
| 6 6 | 
             
                  config[:driver] ||= "oracle.jdbc.driver.OracleDriver"
         | 
| 7 | 
            +
                  config[:adapter_spec] = ::ArJdbc::Oracle
         | 
| 7 8 | 
             
                  jdbc_connection(config)
         | 
| 8 9 | 
             
                end
         | 
| 9 10 | 
             
              end
         | 
| @@ -101,8 +101,9 @@ module ::ArJdbc | |
| 101 101 | 
             
                  'PostgreSQL'
         | 
| 102 102 | 
             
                end
         | 
| 103 103 |  | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 104 | 
            +
             | 
| 105 | 
            +
                def self.arel2_visitors(config)
         | 
| 106 | 
            +
                  {}.tap {|v| %w(postgresql pg jdbcpostgresql).each {|a| v[a] = ::Arel::Visitors::PostgreSQL } }
         | 
| 106 107 | 
             
                end
         | 
| 107 108 |  | 
| 108 109 | 
             
                def postgresql_version
         | 
| @@ -245,7 +246,9 @@ module ::ArJdbc | |
| 245 246 | 
             
                  nil
         | 
| 246 247 | 
             
                end
         | 
| 247 248 |  | 
| 248 | 
            -
                def pg_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
         | 
| 249 | 
            +
                def pg_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
         | 
| 250 | 
            +
                  sql = substitute_binds(sql, binds)
         | 
| 251 | 
            +
             | 
| 249 252 | 
             
                  # Extract the table from the insert sql. Yuck.
         | 
| 250 253 | 
             
                  table = sql.split(" ", 4)[2].gsub('"', '')
         | 
| 251 254 |  | 
| @@ -253,6 +256,7 @@ module ::ArJdbc | |
| 253 256 | 
             
                  if supports_insert_with_returning? && id_value.nil?
         | 
| 254 257 | 
             
                    pk, sequence_name = *pk_and_sequence_for(table) unless pk
         | 
| 255 258 | 
             
                    if pk
         | 
| 259 | 
            +
                      sql = substitute_binds(sql, binds)
         | 
| 256 260 | 
             
                      id_value = select_value("#{sql} RETURNING #{quote_column_name(pk)}")
         | 
| 257 261 | 
             
                      clear_query_cache #FIXME: Why now?
         | 
| 258 262 | 
             
                      return id_value
         | 
| @@ -260,7 +264,7 @@ module ::ArJdbc | |
| 260 264 | 
             
                  end
         | 
| 261 265 |  | 
| 262 266 | 
             
                  # Otherwise, plain insert
         | 
| 263 | 
            -
                  execute(sql, name)
         | 
| 267 | 
            +
                  execute(sql, name, binds)
         | 
| 264 268 |  | 
| 265 269 | 
             
                  # Don't need to look up id_value if we already have it.
         | 
| 266 270 | 
             
                  # (and can't in case of non-sequence PK)
         | 
| @@ -302,35 +306,51 @@ module ::ArJdbc | |
| 302 306 | 
             
                  return @connection.columns_internal(table_name, name, s)
         | 
| 303 307 | 
             
                end
         | 
| 304 308 |  | 
| 305 | 
            -
                #  | 
| 309 | 
            +
                # Sets the maximum number columns postgres has, default 32
         | 
| 310 | 
            +
                def multi_column_index_limit=(limit)
         | 
| 311 | 
            +
                  @multi_column_index_limit = limit
         | 
| 312 | 
            +
                end
         | 
| 313 | 
            +
             | 
| 314 | 
            +
                # Gets the maximum number columns postgres has, default 32
         | 
| 315 | 
            +
                def multi_column_index_limit
         | 
| 316 | 
            +
                  defined?(@multi_column_index_limit) && @multi_column_index_limit || 32
         | 
| 317 | 
            +
                end
         | 
| 318 | 
            +
             | 
| 319 | 
            +
                # Based on postgresql_adapter.rb
         | 
| 306 320 | 
             
                def indexes(table_name, name = nil)
         | 
| 321 | 
            +
                  schema_search_path = @config[:schema_search_path] || select_rows('SHOW search_path')[0][0]
         | 
| 322 | 
            +
                  schemas = schema_search_path.split(/,/).map { |p| quote(p) }.join(',')
         | 
| 307 323 | 
             
                  result = select_rows(<<-SQL, name)
         | 
| 308 | 
            -
                    SELECT i.relname, d.indisunique, a.attname
         | 
| 309 | 
            -
                      FROM pg_class t, pg_class i, pg_index d, pg_attribute a
         | 
| 324 | 
            +
                    SELECT i.relname, d.indisunique, a.attname, a.attnum, d.indkey
         | 
| 325 | 
            +
                      FROM pg_class t, pg_class i, pg_index d, pg_attribute a,
         | 
| 326 | 
            +
                      generate_series(0,#{multi_column_index_limit - 1}) AS s(i)
         | 
| 310 327 | 
             
                     WHERE i.relkind = 'i'
         | 
| 311 328 | 
             
                       AND d.indexrelid = i.oid
         | 
| 312 329 | 
             
                       AND d.indisprimary = 'f'
         | 
| 313 330 | 
             
                       AND t.oid = d.indrelid
         | 
| 314 331 | 
             
                       AND t.relname = '#{table_name}'
         | 
| 332 | 
            +
                       AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname IN (#{schemas}) )
         | 
| 315 333 | 
             
                       AND a.attrelid = t.oid
         | 
| 316 | 
            -
                       AND  | 
| 317 | 
            -
                          OR d.indkey[2]=a.attnum OR d.indkey[3]=a.attnum
         | 
| 318 | 
            -
                          OR d.indkey[4]=a.attnum OR d.indkey[5]=a.attnum
         | 
| 319 | 
            -
                          OR d.indkey[6]=a.attnum OR d.indkey[7]=a.attnum
         | 
| 320 | 
            -
                          OR d.indkey[8]=a.attnum OR d.indkey[9]=a.attnum )
         | 
| 334 | 
            +
                       AND d.indkey[s.i]=a.attnum
         | 
| 321 335 | 
             
                    ORDER BY i.relname
         | 
| 322 336 | 
             
                  SQL
         | 
| 323 337 |  | 
| 324 338 | 
             
                  current_index = nil
         | 
| 325 339 | 
             
                  indexes = []
         | 
| 326 340 |  | 
| 341 | 
            +
                  insertion_order = []
         | 
| 342 | 
            +
                  index_order = nil
         | 
| 343 | 
            +
                  
         | 
| 327 344 | 
             
                  result.each do |row|
         | 
| 328 345 | 
             
                    if current_index != row[0]
         | 
| 346 | 
            +
                    
         | 
| 347 | 
            +
                      (index_order = row[4].split(' ')).each_with_index{ |v, i| index_order[i] = v.to_i }
         | 
| 329 348 | 
             
                      indexes << ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, row[0], row[1] == "t", [])
         | 
| 330 349 | 
             
                      current_index = row[0]
         | 
| 331 350 | 
             
                    end
         | 
| 332 | 
            -
             | 
| 333 | 
            -
                     | 
| 351 | 
            +
                    insertion_order = row[3]
         | 
| 352 | 
            +
                    ind = index_order.index(insertion_order)
         | 
| 353 | 
            +
                    indexes.last.columns[ind] = row[2]
         | 
| 334 354 | 
             
                  end
         | 
| 335 355 |  | 
| 336 356 | 
             
                  indexes
         | 
| @@ -409,8 +429,7 @@ module ::ArJdbc | |
| 409 429 |  | 
| 410 430 | 
             
                  # construct a clean list of column names from the ORDER BY clause, removing
         | 
| 411 431 | 
             
                  # any asc/desc modifiers
         | 
| 412 | 
            -
                  order_columns = order_by.split(',').collect { |s| s.split.first }
         | 
| 413 | 
            -
                  order_columns.delete_if(&:blank?)
         | 
| 432 | 
            +
                  order_columns = [order_by].flatten.map{|o| o.split(',').collect { |s| s.split.first } }.flatten.reject(&:blank?)
         | 
| 414 433 | 
             
                  order_columns = order_columns.zip((0...order_columns.size).to_a).map { |s,i| "#{s} AS alias_#{i}" }
         | 
| 415 434 |  | 
| 416 435 | 
             
                  # return a DISTINCT ON() clause that's distinct on the columns we want but includes
         | 
| @@ -10,6 +10,7 @@ class ActiveRecord::Base | |
| 10 10 | 
             
                  config[:url] ||= "jdbc:postgresql://#{config[:host]}:#{config[:port]}/#{config[:database]}"
         | 
| 11 11 | 
             
                  config[:url] << config[:pg_params] if config[:pg_params]
         | 
| 12 12 | 
             
                  config[:driver] ||= "org.postgresql.Driver"
         | 
| 13 | 
            +
                  config[:adapter_spec] = ::ArJdbc::PostgreSQL
         | 
| 13 14 | 
             
                  conn = jdbc_connection(config)
         | 
| 14 15 | 
             
                  conn.execute("SET SEARCH_PATH TO #{config[:schema_search_path]}") if config[:schema_search_path]
         | 
| 15 16 | 
             
                  conn
         | 
| @@ -16,7 +16,7 @@ module ::ArJdbc | |
| 16 16 |  | 
| 17 17 | 
             
                module Column
         | 
| 18 18 | 
             
                  def init_column(name, default, *args)
         | 
| 19 | 
            -
                    @default =  | 
| 19 | 
            +
                    @default = nil if default =~ /NULL/
         | 
| 20 20 | 
             
                  end
         | 
| 21 21 |  | 
| 22 22 | 
             
                  def type_cast(value)
         | 
| @@ -80,8 +80,8 @@ module ::ArJdbc | |
| 80 80 | 
             
                  'SQLite'
         | 
| 81 81 | 
             
                end
         | 
| 82 82 |  | 
| 83 | 
            -
                def arel2_visitors
         | 
| 84 | 
            -
                  { | 
| 83 | 
            +
                def self.arel2_visitors(config)
         | 
| 84 | 
            +
                  {}.tap {|v| %w(sqlite3 jdbcsqlite3).each {|x| v[x] = ::Arel::Visitors::SQLite } }
         | 
| 85 85 | 
             
                end
         | 
| 86 86 |  | 
| 87 87 | 
             
                def supports_ddl_transactions?
         | 
| @@ -145,7 +145,8 @@ module ::ArJdbc | |
| 145 145 | 
             
                  end
         | 
| 146 146 | 
             
                end
         | 
| 147 147 |  | 
| 148 | 
            -
                def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
         | 
| 148 | 
            +
                def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) #:nodoc:
         | 
| 149 | 
            +
                  sql = substitute_binds(sql, binds)
         | 
| 149 150 | 
             
                  @connection.execute_update(sql)
         | 
| 150 151 | 
             
                  id_value || last_insert_id
         | 
| 151 152 | 
             
                end
         | 
| @@ -194,8 +195,8 @@ module ::ArJdbc | |
| 194 195 | 
             
                  ActiveRecord::ConnectionAdapters::JdbcConnection::insert?(sql) ? last_insert_id : result
         | 
| 195 196 | 
             
                end
         | 
| 196 197 |  | 
| 197 | 
            -
                def select(sql, name=nil)
         | 
| 198 | 
            -
                  execute(sql, name).map do |row|
         | 
| 198 | 
            +
                def select(sql, name=nil, binds = [])
         | 
| 199 | 
            +
                  execute(sql, name, binds).map do |row|
         | 
| 199 200 | 
             
                    record = {}
         | 
| 200 201 | 
             
                    row.each_key do |key|
         | 
| 201 202 | 
             
                      if key.is_a?(String)
         | 
| @@ -354,10 +355,6 @@ module ActiveRecord::ConnectionAdapters | |
| 354 355 | 
             
              class SQLite3Adapter < JdbcAdapter
         | 
| 355 356 | 
             
                include ArJdbc::SQLite3
         | 
| 356 357 |  | 
| 357 | 
            -
                def adapter_spec(config)
         | 
| 358 | 
            -
                  # return nil to avoid extending ArJdbc::SQLite3, which we've already done
         | 
| 359 | 
            -
                end
         | 
| 360 | 
            -
             | 
| 361 358 | 
             
                def jdbc_connection_class(spec)
         | 
| 362 359 | 
             
                  ::ArJdbc::SQLite3.jdbc_connection_class
         | 
| 363 360 | 
             
                end
         | 
| @@ -367,6 +364,12 @@ module ActiveRecord::ConnectionAdapters | |
| 367 364 | 
             
                end
         | 
| 368 365 |  | 
| 369 366 | 
             
                alias_chained_method :columns, :query_cache, :jdbc_columns
         | 
| 367 | 
            +
             | 
| 368 | 
            +
                protected
         | 
| 369 | 
            +
             | 
| 370 | 
            +
                def last_inserted_id(result)
         | 
| 371 | 
            +
                  last_insert_id
         | 
| 372 | 
            +
                end
         | 
| 370 373 | 
             
              end
         | 
| 371 374 |  | 
| 372 375 | 
             
              SQLiteAdapter = SQLite3Adapter
         |