activerecord-jdbc-adapter 1.3.16 → 1.3.17
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/History.md +20 -0
- data/Rakefile +19 -5
- data/lib/arjdbc/jdbc.rb +5 -0
- data/lib/arjdbc/jdbc/adapter.rb +13 -2
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/mysql/adapter.rb +74 -15
- data/lib/arjdbc/mysql/bulk_change_table.rb +1 -1
- data/lib/arjdbc/mysql/schema_creation.rb +24 -1
- data/lib/arjdbc/postgresql/adapter.rb +149 -178
- data/lib/arjdbc/postgresql/base/pgconn.rb +8 -0
- data/lib/arjdbc/postgresql/base/schema_definitions.rb +131 -0
- data/lib/arjdbc/postgresql/column.rb +15 -14
- data/lib/arjdbc/postgresql/oid_types.rb +23 -10
- data/lib/arjdbc/postgresql/schema_creation.rb +21 -3
- data/lib/arjdbc/version.rb +1 -1
- data/rakelib/db.rake +1 -1
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +47 -7
- metadata +4 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 134cda5c81428ddd6306cfbf8de01390845e9332
         | 
| 4 | 
            +
              data.tar.gz: 5b4c2e9e1f691ab3cd0c8df0ab77a06a933bb433
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: bb750f2f8396290b6212c017350c1b9c2f38792122a2214e1c14a2e83e22f35e6d0dab9c808f384421a64d3c11c691d94e2909e5548ccafbc523c7c066cdd7f1
         | 
| 7 | 
            +
              data.tar.gz: 3cc35229994ff2f461fe35ff5e381c461d41d91ab80e51a8e89b054494f21283a9b897488cab748a1efe076abc3f86316939644a1dcfa2a22029a49c409fa800
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/History.md
    CHANGED
    
    | @@ -1,3 +1,23 @@ | |
| 1 | 
            +
            ## 1.3.17 (06/30/15)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            - [mysql] bulk compatibility with AR 4.2 - all _sql helper accept an options (hash)
         | 
| 4 | 
            +
            - [mysql] back-port case sensitive/insensitive comparison
         | 
| 5 | 
            +
            - [mysql] handle precision for datetimes when doing type_to_sql (AR 4.2 compat)
         | 
| 6 | 
            +
            - [mysql] foreign key support based on AR 4.2 (#656)
         | 
| 7 | 
            +
            - [postgres] foreign_key support back-ported from AR 4.2 (#656)
         | 
| 8 | 
            +
            - moved jndi callbacks to happen outside adapter's `initialize` (#649, #620)
         | 
| 9 | 
            +
            - [postgres] AR 4.2 compatibility with SchemaCreation
         | 
| 10 | 
            +
            - [postgres] re-define `lookup_cast_type` (AR 4.2) + `conn.type_map` is public
         | 
| 11 | 
            +
            - [postgres] override `valid_type?(type)` (AR 4.2 compatibility)
         | 
| 12 | 
            +
            - [postgres] back-port change_column updates from AR 4.2 for compatibility
         | 
| 13 | 
            +
            - [postgres] pass down array_member to hstore_to_string (fixes #647 on AR 4.1)
         | 
| 14 | 
            +
            - [postgres] on AR 4.2 use core's schema_definitions.rb for improved compat (#644)
         | 
| 15 | 
            +
            - back-port PGconn hack on AR 4.x (from #655 and following commits)
         | 
| 16 | 
            +
              to fix #651 as an unfortunate work-around for (non-shareable) AR internals (#652)
         | 
| 17 | 
            +
            - seems that extension methods won't work in 9K the same as in 1.7.x thus work-around
         | 
| 18 | 
            +
              (originally reported as https://github.com/jruby/jruby/issues/2533)
         | 
| 19 | 
            +
            - restore 1.8 compatibility in postgres' adapter (regression in 1.3.16 see #641)
         | 
| 20 | 
            +
             | 
| 1 21 | 
             
            ## 1.3.16 (04/13/15)
         | 
| 2 22 |  | 
| 3 23 | 
             
            - [h2] allow jdbch2 adapter to use jdbc-h2 1.4 (#639)
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -12,7 +12,6 @@ require 'appraisal' | |
| 12 12 |  | 
| 13 13 | 
             
            task :default => [:jar, :test]
         | 
| 14 14 |  | 
| 15 | 
            -
            #ugh, bundler doesn't use tasks, so gotta hook up to both tasks.
         | 
| 16 15 | 
             
            task :build => :jar
         | 
| 17 16 | 
             
            task :install => :jar
         | 
| 18 17 |  | 
| @@ -21,13 +20,27 @@ DRIVERS  = %w[derby h2 hsqldb jtds mysql postgres sqlite3].map { |a| "jdbc-#{a}" | |
| 21 20 | 
             
            TARGETS = ( ADAPTERS + DRIVERS )
         | 
| 22 21 |  | 
| 23 22 | 
             
            rake = lambda { |task| ruby "-S", "rake", task }
         | 
| 23 | 
            +
            current_version = lambda { Bundler.load_gemspec('activerecord-jdbc-adapter.gemspec').version }
         | 
| 24 24 |  | 
| 25 | 
            -
             | 
| 25 | 
            +
            ADAPTERS.each do |target|
         | 
| 26 | 
            +
              namespace target do
         | 
| 27 | 
            +
                task :build do
         | 
| 28 | 
            +
                  version = current_version.call
         | 
| 29 | 
            +
                  Dir.chdir(target) { rake.call "build" }
         | 
| 30 | 
            +
                  cp FileList["#{target}/pkg/#{target}-#{version}.gem"], "pkg"
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| 34 | 
            +
            DRIVERS.each do |target|
         | 
| 26 35 | 
             
              namespace target do
         | 
| 27 36 | 
             
                task :build do
         | 
| 28 37 | 
             
                  Dir.chdir(target) { rake.call "build" }
         | 
| 29 38 | 
             
                  cp FileList["#{target}/pkg/#{target}-*.gem"], "pkg"
         | 
| 30 39 | 
             
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
| 42 | 
            +
            TARGETS.each do |target|
         | 
| 43 | 
            +
              namespace target do
         | 
| 31 44 | 
             
                task :install do
         | 
| 32 45 | 
             
                  Dir.chdir(target) { rake.call "install" }
         | 
| 33 46 | 
             
                end
         | 
| @@ -66,15 +79,16 @@ task "release:adapters" => [ 'release' ] + ADAPTERS.map { |name| "#{name}:releas | |
| 66 79 | 
             
            task "adapters:release" => 'release:adapters'
         | 
| 67 80 |  | 
| 68 81 | 
             
            task 'release:do' => 'build:adapters' do
         | 
| 69 | 
            -
               | 
| 70 | 
            -
              version = gemspec.version; version_tag = "v#{version}"
         | 
| 82 | 
            +
              version = current_version.call; version_tag = "v#{version}"
         | 
| 71 83 |  | 
| 72 84 | 
             
              sh("git diff --no-patch --exit-code") { |ok| fail "git working dir is not clean" unless ok }
         | 
| 73 85 | 
             
              sh("git diff-index --quiet --cached HEAD") { |ok| fail "git index is not clean" unless ok }
         | 
| 74 86 |  | 
| 75 87 | 
             
              sh "git tag -a -m \"AR-JDBC #{version}\" #{version_tag}"
         | 
| 88 | 
            +
              branch = `git rev-parse --abbrev-ref HEAD`.strip
         | 
| 89 | 
            +
              puts "releasing from (current) branch #{branch.inspect}"
         | 
| 76 90 | 
             
              sh "for gem in `ls pkg/*-#{version}.gem`; do gem push $gem; done" do |ok|
         | 
| 77 | 
            -
                sh "git push origin  | 
| 91 | 
            +
                sh "git push origin #{branch} --tags" if ok
         | 
| 78 92 | 
             
              end
         | 
| 79 93 | 
             
            end
         | 
| 80 94 |  | 
    
        data/lib/arjdbc/jdbc.rb
    CHANGED
    
    
    
        data/lib/arjdbc/jdbc/adapter.rb
    CHANGED
    
    | @@ -40,6 +40,12 @@ module ActiveRecord | |
| 40 40 |  | 
| 41 41 | 
             
                  attr_reader :config
         | 
| 42 42 |  | 
| 43 | 
            +
                  def self.new(connection, logger = nil, pool = nil)
         | 
| 44 | 
            +
                    adapter = super
         | 
| 45 | 
            +
                    Jdbc::JndiConnectionPoolCallbacks.prepare(adapter, adapter.instance_variable_get(:@connection))
         | 
| 46 | 
            +
                    adapter
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 43 49 | 
             
                  # Initializes the (JDBC connection) adapter instance.
         | 
| 44 50 | 
             
                  # The passed configuration Hash's keys are symbolized, thus changes to
         | 
| 45 51 | 
             
                  # the original `config` keys won't be reflected in the adapter.
         | 
| @@ -50,6 +56,8 @@ module ActiveRecord | |
| 50 56 | 
             
                  # @param config the database configuration
         | 
| 51 57 | 
             
                  # @note `initialize(logger, config)` with 2 arguments is supported as well
         | 
| 52 58 | 
             
                  def initialize(connection, logger, config = nil)
         | 
| 59 | 
            +
                    # AR : initialize(connection, logger = nil, pool = nil)
         | 
| 60 | 
            +
                    # AR < 3.2 : initialize(connection, logger = nil)
         | 
| 53 61 | 
             
                    if config.nil? && logger.respond_to?(:key?) # (logger, config)
         | 
| 54 62 | 
             
                      config, logger, connection = logger, connection, nil
         | 
| 55 63 | 
             
                    end
         | 
| @@ -76,8 +84,6 @@ module ActiveRecord | |
| 76 84 | 
             
                    # NOTE: should not be necessary for JNDI due reconnect! on checkout :
         | 
| 77 85 | 
             
                    configure_connection if respond_to?(:configure_connection)
         | 
| 78 86 |  | 
| 79 | 
            -
                    Jdbc::JndiConnectionPoolCallbacks.prepare(self, connection)
         | 
| 80 | 
            -
             | 
| 81 87 | 
             
                    @visitor = new_visitor # nil if no AREL (AR-2.3)
         | 
| 82 88 | 
             
                  end
         | 
| 83 89 |  | 
| @@ -216,6 +222,11 @@ module ActiveRecord | |
| 216 222 | 
             
                    end
         | 
| 217 223 | 
             
                  end
         | 
| 218 224 |  | 
| 225 | 
            +
                  # @override introduced in AR 4.2
         | 
| 226 | 
            +
                  def valid_type?(type)
         | 
| 227 | 
            +
                    ! native_database_types[type].nil?
         | 
| 228 | 
            +
                  end
         | 
| 229 | 
            +
             | 
| 219 230 | 
             
                  # Allows for modification of the detected native types.
         | 
| 220 231 | 
             
                  # @param types the resolved native database types
         | 
| 221 232 | 
             
                  # @see #native_database_types
         | 
| Binary file | 
    
        data/lib/arjdbc/mysql/adapter.rb
    CHANGED
    
    | @@ -6,11 +6,6 @@ require 'active_record/connection_adapters/abstract/schema_definitions' | |
| 6 6 | 
             
            module ArJdbc
         | 
| 7 7 | 
             
              module MySQL
         | 
| 8 8 |  | 
| 9 | 
            -
                # @private
         | 
| 10 | 
            -
                AR40 = ::ActiveRecord::VERSION::MAJOR > 3
         | 
| 11 | 
            -
                # @private
         | 
| 12 | 
            -
                AR42 = ::ActiveRecord::VERSION::STRING >= '4.2'
         | 
| 13 | 
            -
             | 
| 14 9 | 
             
                require 'arjdbc/mysql/column'
         | 
| 15 10 | 
             
                require 'arjdbc/mysql/bulk_change_table'
         | 
| 16 11 | 
             
                require 'arjdbc/mysql/explain_support'
         | 
| @@ -154,13 +149,29 @@ module ArJdbc | |
| 154 149 |  | 
| 155 150 | 
             
                def case_sensitive_modifier(node)
         | 
| 156 151 | 
             
                  Arel::Nodes::Bin.new(node)
         | 
| 157 | 
            -
                end
         | 
| 152 | 
            +
                end unless AR42
         | 
| 158 153 |  | 
| 159 154 | 
             
                def case_sensitive_modifier(node, table_attribute)
         | 
| 160 155 | 
             
                  node = Arel::Nodes.build_quoted node, table_attribute
         | 
| 161 156 | 
             
                  Arel::Nodes::Bin.new(node)
         | 
| 162 157 | 
             
                end if AR42
         | 
| 163 158 |  | 
| 159 | 
            +
                def case_sensitive_comparison(table, attribute, column, value)
         | 
| 160 | 
            +
                  if column.case_sensitive?
         | 
| 161 | 
            +
                    table[attribute].eq(value)
         | 
| 162 | 
            +
                  else
         | 
| 163 | 
            +
                    super
         | 
| 164 | 
            +
                  end
         | 
| 165 | 
            +
                end if AR42
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                def case_insensitive_comparison(table, attribute, column, value)
         | 
| 168 | 
            +
                  if column.case_sensitive?
         | 
| 169 | 
            +
                    super
         | 
| 170 | 
            +
                  else
         | 
| 171 | 
            +
                    table[attribute].eq(value)
         | 
| 172 | 
            +
                  end
         | 
| 173 | 
            +
                end if AR42
         | 
| 174 | 
            +
             | 
| 164 175 | 
             
                def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
         | 
| 165 176 | 
             
                  where_sql
         | 
| 166 177 | 
             
                end
         | 
| @@ -532,12 +543,52 @@ module ArJdbc | |
| 532 543 | 
             
                # @override
         | 
| 533 544 | 
             
                def rename_index(table_name, old_name, new_name)
         | 
| 534 545 | 
             
                  if supports_rename_index?
         | 
| 546 | 
            +
                    validate_index_length!(table_name, new_name) if respond_to?(:validate_index_length!)
         | 
| 535 547 | 
             
                    execute "ALTER TABLE #{quote_table_name(table_name)} RENAME INDEX #{quote_table_name(old_name)} TO #{quote_table_name(new_name)}"
         | 
| 536 548 | 
             
                  else
         | 
| 537 549 | 
             
                    super
         | 
| 538 550 | 
             
                  end
         | 
| 539 551 | 
             
                end
         | 
| 540 552 |  | 
| 553 | 
            +
                # @private
         | 
| 554 | 
            +
                ForeignKeyDefinition = ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition if ::ActiveRecord::ConnectionAdapters.const_defined? :ForeignKeyDefinition
         | 
| 555 | 
            +
             | 
| 556 | 
            +
                def supports_foreign_keys?; true end
         | 
| 557 | 
            +
             | 
| 558 | 
            +
                def foreign_keys(table_name)
         | 
| 559 | 
            +
                  fk_info = select_all "" <<
         | 
| 560 | 
            +
                    "SELECT fk.referenced_table_name as 'to_table' " <<
         | 
| 561 | 
            +
                          ",fk.referenced_column_name as 'primary_key' " <<
         | 
| 562 | 
            +
                          ",fk.column_name as 'column' " <<
         | 
| 563 | 
            +
                          ",fk.constraint_name as 'name' " <<
         | 
| 564 | 
            +
                    "FROM information_schema.key_column_usage fk " <<
         | 
| 565 | 
            +
                    "WHERE fk.referenced_column_name is not null " <<
         | 
| 566 | 
            +
                      "AND fk.table_schema = '#{current_database}' " <<
         | 
| 567 | 
            +
                      "AND fk.table_name = '#{table_name}'"
         | 
| 568 | 
            +
             | 
| 569 | 
            +
                  create_table_info = select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"]
         | 
| 570 | 
            +
             | 
| 571 | 
            +
                  fk_info.map! do |row|
         | 
| 572 | 
            +
                    options = {
         | 
| 573 | 
            +
                      :column => row['column'], :name => row['name'], :primary_key => row['primary_key']
         | 
| 574 | 
            +
                    }
         | 
| 575 | 
            +
                    options[:on_update] = extract_foreign_key_action(create_table_info, row['name'], "UPDATE")
         | 
| 576 | 
            +
                    options[:on_delete] = extract_foreign_key_action(create_table_info, row['name'], "DELETE")
         | 
| 577 | 
            +
             | 
| 578 | 
            +
                    ForeignKeyDefinition.new(table_name, row['to_table'], options)
         | 
| 579 | 
            +
                  end
         | 
| 580 | 
            +
                end if defined? ForeignKeyDefinition
         | 
| 581 | 
            +
             | 
| 582 | 
            +
                def extract_foreign_key_action(structure, name, action)
         | 
| 583 | 
            +
                  if structure =~ /CONSTRAINT #{quote_column_name(name)} FOREIGN KEY .* REFERENCES .* ON #{action} (CASCADE|SET NULL|RESTRICT)/
         | 
| 584 | 
            +
                    case $1
         | 
| 585 | 
            +
                    when 'CASCADE'; :cascade
         | 
| 586 | 
            +
                    when 'SET NULL'; :nullify
         | 
| 587 | 
            +
                    end
         | 
| 588 | 
            +
                  end
         | 
| 589 | 
            +
                end
         | 
| 590 | 
            +
                private :extract_foreign_key_action
         | 
| 591 | 
            +
             | 
| 541 592 | 
             
                # @override
         | 
| 542 593 | 
             
                def add_column(table_name, column_name, type, options = {})
         | 
| 543 594 | 
             
                  add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
         | 
| @@ -663,31 +714,39 @@ module ArJdbc | |
| 663 714 | 
             
                  show_variable("collation_database")
         | 
| 664 715 | 
             
                end
         | 
| 665 716 |  | 
| 717 | 
            +
                # Maps logical Rails types to MySQL-specific data types.
         | 
| 666 718 | 
             
                def type_to_sql(type, limit = nil, precision = nil, scale = nil)
         | 
| 667 719 | 
             
                  case type.to_s
         | 
| 668 720 | 
             
                  when 'binary'
         | 
| 669 721 | 
             
                    case limit
         | 
| 670 | 
            -
                    when 0..0xfff; | 
| 671 | 
            -
                    when nil; | 
| 722 | 
            +
                    when 0..0xfff;           "varbinary(#{limit})"
         | 
| 723 | 
            +
                    when nil;                "blob"
         | 
| 672 724 | 
             
                    when 0x1000..0xffffffff; "blob(#{limit})"
         | 
| 673 | 
            -
                    else raise | 
| 725 | 
            +
                    else raise(ActiveRecordError, "No binary type has character length #{limit}")
         | 
| 674 726 | 
             
                    end
         | 
| 675 727 | 
             
                  when 'integer'
         | 
| 676 728 | 
             
                    case limit
         | 
| 677 729 | 
             
                    when 1; 'tinyint'
         | 
| 678 730 | 
             
                    when 2; 'smallint'
         | 
| 679 731 | 
             
                    when 3; 'mediumint'
         | 
| 680 | 
            -
                    when nil, 4, 11; 'int(11)' | 
| 732 | 
            +
                    when nil, 4, 11; 'int(11)'  # compatibility with MySQL default
         | 
| 681 733 | 
             
                    when 5..8; 'bigint'
         | 
| 682 | 
            -
                    else raise | 
| 734 | 
            +
                    else raise(ActiveRecordError, "No integer type has byte size #{limit}")
         | 
| 683 735 | 
             
                    end
         | 
| 684 736 | 
             
                  when 'text'
         | 
| 685 737 | 
             
                    case limit
         | 
| 686 | 
            -
                    when 0..0xff; | 
| 687 | 
            -
                    when nil, 0x100..0xffff; | 
| 688 | 
            -
                    when 0x10000..0xffffff; | 
| 738 | 
            +
                    when 0..0xff;               'tinytext'
         | 
| 739 | 
            +
                    when nil, 0x100..0xffff;    'text'
         | 
| 740 | 
            +
                    when 0x10000..0xffffff;     'mediumtext'
         | 
| 689 741 | 
             
                    when 0x1000000..0xffffffff; 'longtext'
         | 
| 690 | 
            -
                    else raise | 
| 742 | 
            +
                    else raise(ActiveRecordError, "No text type has character length #{limit}")
         | 
| 743 | 
            +
                    end
         | 
| 744 | 
            +
                  when 'datetime'
         | 
| 745 | 
            +
                    return super unless precision
         | 
| 746 | 
            +
             | 
| 747 | 
            +
                    case precision
         | 
| 748 | 
            +
                      when 0..6; "datetime(#{precision})"
         | 
| 749 | 
            +
                      else raise(ActiveRecordError, "No datetime type has precision of #{precision}. The allowed range of precision is from 0 to 6.")
         | 
| 691 750 | 
             
                    end
         | 
| 692 751 | 
             
                  else
         | 
| 693 752 | 
             
                    super
         | 
| @@ -131,7 +131,7 @@ module ArJdbc | |
| 131 131 | 
             
                    [add_column_sql(table_name, :created_at, :datetime, options), add_column_sql(table_name, :updated_at, :datetime, options)]
         | 
| 132 132 | 
             
                  end
         | 
| 133 133 |  | 
| 134 | 
            -
                  def remove_timestamps_sql(table_name)
         | 
| 134 | 
            +
                  def remove_timestamps_sql(table_name, options = nil)
         | 
| 135 135 | 
             
                    [remove_column_sql(table_name, :updated_at), remove_column_sql(table_name, :created_at)]
         | 
| 136 136 | 
             
                  end
         | 
| 137 137 |  | 
| @@ -8,12 +8,30 @@ module ArJdbc | |
| 8 8 | 
             
                  end
         | 
| 9 9 |  | 
| 10 10 | 
             
                  private
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def visit_DropForeignKey(name)
         | 
| 13 | 
            +
                    "DROP FOREIGN KEY #{name}"
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def visit_TableDefinition(o)
         | 
| 17 | 
            +
                    name = o.name
         | 
| 18 | 
            +
                    create_sql = "CREATE#{' TEMPORARY' if o.temporary} TABLE #{quote_table_name(name)} "
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    statements = o.columns.map { |c| accept c }
         | 
| 21 | 
            +
                    statements.concat(o.indexes.map { |column_name, options| index_in_create(name, column_name, options) })
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    create_sql << "(#{statements.join(', ')}) " if statements.present?
         | 
| 24 | 
            +
                    create_sql << "#{o.options}"
         | 
| 25 | 
            +
                    create_sql << " AS #{@conn.to_sql(o.as)}" if o.as
         | 
| 26 | 
            +
                    create_sql
         | 
| 27 | 
            +
                  end if AR42
         | 
| 28 | 
            +
             | 
| 11 29 | 
             
                  def visit_ChangeColumnDefinition(o)
         | 
| 12 30 | 
             
                    column = o.column
         | 
| 13 31 | 
             
                    options = o.options
         | 
| 14 32 | 
             
                    sql_type = type_to_sql(o.type, options[:limit], options[:precision], options[:scale])
         | 
| 15 33 | 
             
                    change_column_sql = "CHANGE #{quote_column_name(column.name)} #{quote_column_name(options[:name])} #{sql_type}"
         | 
| 16 | 
            -
                    add_column_options!(change_column_sql, options)
         | 
| 34 | 
            +
                    add_column_options!(change_column_sql, options.merge(:column => column))
         | 
| 17 35 | 
             
                    add_column_position!(change_column_sql, options)
         | 
| 18 36 | 
             
                  end
         | 
| 19 37 |  | 
| @@ -25,6 +43,11 @@ module ArJdbc | |
| 25 43 | 
             
                    end
         | 
| 26 44 | 
             
                    sql
         | 
| 27 45 | 
             
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  def index_in_create(table_name, column_name, options)
         | 
| 48 | 
            +
                    index_name, index_type, index_columns, index_options, index_algorithm, index_using = @conn.add_index_options(table_name, column_name, options)
         | 
| 49 | 
            +
                    "#{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})#{index_options} #{index_algorithm}"
         | 
| 50 | 
            +
                  end
         | 
| 28 51 | 
             
                end
         | 
| 29 52 | 
             
              end
         | 
| 30 53 |  | 
| @@ -6,21 +6,24 @@ module ArJdbc | |
| 6 6 | 
             
              # Strives to provide Rails built-in PostgreSQL adapter (API) compatibility.
         | 
| 7 7 | 
             
              module PostgreSQL
         | 
| 8 8 |  | 
| 9 | 
            +
                # @deprecated no longer used
         | 
| 9 10 | 
             
                # @private
         | 
| 10 | 
            -
                AR4_COMPAT =  | 
| 11 | 
            +
                AR4_COMPAT = AR40
         | 
| 12 | 
            +
                # @deprecated no longer used
         | 
| 11 13 | 
             
                # @private
         | 
| 12 | 
            -
                AR42_COMPAT =  | 
| 13 | 
            -
                  ( ::ActiveRecord::VERSION::MAJOR == 4 && ::ActiveRecord::VERSION::MINOR >= 2 )
         | 
| 14 | 
            +
                AR42_COMPAT = AR42
         | 
| 14 15 |  | 
| 15 16 | 
             
                require 'arjdbc/postgresql/column'
         | 
| 16 17 | 
             
                require 'arjdbc/postgresql/explain_support'
         | 
| 17 18 | 
             
                require 'arjdbc/postgresql/schema_creation' # AR 4.x
         | 
| 18 | 
            -
             | 
| 19 19 | 
             
                # @private
         | 
| 20 20 | 
             
                IndexDefinition = ::ActiveRecord::ConnectionAdapters::IndexDefinition
         | 
| 21 21 |  | 
| 22 22 | 
             
                # @private
         | 
| 23 | 
            -
                 | 
| 23 | 
            +
                ForeignKeyDefinition = ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition if ::ActiveRecord::ConnectionAdapters.const_defined? :ForeignKeyDefinition
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                # @private
         | 
| 26 | 
            +
                Type = ::ActiveRecord::Type if AR42
         | 
| 24 27 |  | 
| 25 28 | 
             
                # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
         | 
| 26 29 | 
             
                def self.jdbc_connection_class
         | 
| @@ -137,22 +140,22 @@ module ArJdbc | |
| 137 140 |  | 
| 138 141 | 
             
                # Maps logical Rails types to PostgreSQL-specific data types.
         | 
| 139 142 | 
             
                def type_to_sql(type, limit = nil, precision = nil, scale = nil)
         | 
| 140 | 
            -
                  case type. | 
| 141 | 
            -
                  when  | 
| 143 | 
            +
                  case type.to_s
         | 
| 144 | 
            +
                  when 'binary'
         | 
| 142 145 | 
             
                    # PostgreSQL doesn't support limits on binary (bytea) columns.
         | 
| 143 146 | 
             
                    # The hard limit is 1Gb, because of a 32-bit size field, and TOAST.
         | 
| 144 147 | 
             
                    case limit
         | 
| 145 | 
            -
                    when nil, 0..0x3fffffff; super(type | 
| 148 | 
            +
                    when nil, 0..0x3fffffff; super(type)
         | 
| 146 149 | 
             
                    else raise(ActiveRecordError, "No binary type has byte size #{limit}.")
         | 
| 147 150 | 
             
                    end
         | 
| 148 | 
            -
                  when  | 
| 151 | 
            +
                  when 'text'
         | 
| 149 152 | 
             
                    # PostgreSQL doesn't support limits on text columns.
         | 
| 150 153 | 
             
                    # The hard limit is 1Gb, according to section 8.3 in the manual.
         | 
| 151 154 | 
             
                    case limit
         | 
| 152 | 
            -
                    when nil, 0..0x3fffffff; super(type | 
| 155 | 
            +
                    when nil, 0..0x3fffffff; super(type)
         | 
| 153 156 | 
             
                    else raise(ActiveRecordError, "The limit on text can be at most 1GB - 1byte.")
         | 
| 154 157 | 
             
                    end
         | 
| 155 | 
            -
                  when  | 
| 158 | 
            +
                  when 'integer'
         | 
| 156 159 | 
             
                    return 'integer' unless limit
         | 
| 157 160 |  | 
| 158 161 | 
             
                    case limit
         | 
| @@ -161,7 +164,7 @@ module ArJdbc | |
| 161 164 | 
             
                      when 5..8; 'bigint'
         | 
| 162 165 | 
             
                      else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.")
         | 
| 163 166 | 
             
                    end
         | 
| 164 | 
            -
                  when  | 
| 167 | 
            +
                  when 'datetime'
         | 
| 165 168 | 
             
                    return super unless precision
         | 
| 166 169 |  | 
| 167 170 | 
             
                    case precision
         | 
| @@ -201,7 +204,7 @@ module ArJdbc | |
| 201 204 | 
             
                  when Hash
         | 
| 202 205 | 
             
                    case column.sql_type
         | 
| 203 206 | 
             
                    when 'hstore'
         | 
| 204 | 
            -
                      jdbc_column_class.hstore_to_string(value)
         | 
| 207 | 
            +
                      jdbc_column_class.hstore_to_string(value, array_member)
         | 
| 205 208 | 
             
                    when 'json', 'jsonb'
         | 
| 206 209 | 
             
                      jdbc_column_class.json_to_string(value)
         | 
| 207 210 | 
             
                    else super(value, column)
         | 
| @@ -215,7 +218,7 @@ module ArJdbc | |
| 215 218 | 
             
                  else
         | 
| 216 219 | 
             
                    super(value, column)
         | 
| 217 220 | 
             
                  end
         | 
| 218 | 
            -
                end if  | 
| 221 | 
            +
                end if AR40 && ! AR42
         | 
| 219 222 |  | 
| 220 223 | 
             
                # @private
         | 
| 221 224 | 
             
                def _type_cast(value)
         | 
| @@ -224,14 +227,14 @@ module ArJdbc | |
| 224 227 | 
             
                    # Return a bind param hash with format as binary.
         | 
| 225 228 | 
             
                    # See http://deveiate.org/code/pg/PGconn.html#method-i-exec_prepared-doc
         | 
| 226 229 | 
             
                    # for more information
         | 
| 227 | 
            -
                    { value | 
| 230 | 
            +
                    { :value => value.to_s, :format => 1 }
         | 
| 228 231 | 
             
                  when OID::Xml::Data, OID::Bit::Data
         | 
| 229 232 | 
             
                    value.to_s
         | 
| 230 233 | 
             
                  else
         | 
| 231 234 | 
             
                    super
         | 
| 232 235 | 
             
                  end
         | 
| 233 | 
            -
                end if  | 
| 234 | 
            -
                private :_type_cast if  | 
| 236 | 
            +
                end if AR42
         | 
| 237 | 
            +
                private :_type_cast if AR42
         | 
| 235 238 |  | 
| 236 239 | 
             
                NATIVE_DATABASE_TYPES = {
         | 
| 237 240 | 
             
                  :primary_key => "serial primary key",
         | 
| @@ -273,14 +276,14 @@ module ArJdbc | |
| 273 276 | 
             
                  :tstzrange => { :name => "tstzrange" },
         | 
| 274 277 | 
             
                  :int4range => { :name => "int4range" },
         | 
| 275 278 | 
             
                  :int8range => { :name => "int8range" },
         | 
| 276 | 
            -
                }) if  | 
| 279 | 
            +
                }) if AR40
         | 
| 277 280 |  | 
| 278 281 | 
             
                NATIVE_DATABASE_TYPES.update(
         | 
| 279 282 | 
             
                  :bigserial => "bigserial",
         | 
| 280 283 | 
             
                  :bigint => { :name => "bigint" },
         | 
| 281 284 | 
             
                  :bit => { :name => "bit" },
         | 
| 282 285 | 
             
                  :bit_varying => { :name => "bit varying" }
         | 
| 283 | 
            -
                ) if  | 
| 286 | 
            +
                ) if AR42
         | 
| 284 287 |  | 
| 285 288 | 
             
                def native_database_types
         | 
| 286 289 | 
             
                  NATIVE_DATABASE_TYPES
         | 
| @@ -293,13 +296,13 @@ module ArJdbc | |
| 293 296 | 
             
                  spec[:array] = 'true' if column.respond_to?(:array) && column.array
         | 
| 294 297 | 
             
                  spec[:default] = "\"#{column.default_function}\"" if column.default_function
         | 
| 295 298 | 
             
                  spec
         | 
| 296 | 
            -
                end if  | 
| 299 | 
            +
                end if AR40
         | 
| 297 300 |  | 
| 298 301 | 
             
                # Adds `:array` as a valid migration key.
         | 
| 299 302 | 
             
                # @override
         | 
| 300 303 | 
             
                def migration_keys
         | 
| 301 304 | 
             
                  super + [:array]
         | 
| 302 | 
            -
                end if  | 
| 305 | 
            +
                end if AR40
         | 
| 303 306 |  | 
| 304 307 | 
             
                # Enable standard-conforming strings if available.
         | 
| 305 308 | 
             
                def set_standard_conforming_strings
         | 
| @@ -367,12 +370,12 @@ module ArJdbc | |
| 367 370 |  | 
| 368 371 | 
             
                def supports_index_sort_order?; true end
         | 
| 369 372 |  | 
| 370 | 
            -
                def supports_partial_index?; true end if  | 
| 373 | 
            +
                def supports_partial_index?; true end if AR40
         | 
| 371 374 |  | 
| 372 375 | 
             
                # Range data-types weren't introduced until PostgreSQL 9.2.
         | 
| 373 376 | 
             
                def supports_ranges?
         | 
| 374 377 | 
             
                  postgresql_version >= 90200
         | 
| 375 | 
            -
                end if  | 
| 378 | 
            +
                end if AR40
         | 
| 376 379 |  | 
| 377 380 | 
             
                def supports_transaction_isolation?(level = nil)
         | 
| 378 381 | 
             
                  true
         | 
| @@ -518,9 +521,8 @@ module ArJdbc | |
| 518 521 | 
             
                  result = select(<<-end_sql, 'SCHEMA').first
         | 
| 519 522 | 
             
                    SELECT attr.attname
         | 
| 520 523 | 
             
                    FROM pg_attribute attr
         | 
| 521 | 
            -
                    INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = cons.conkey | 
| 522 | 
            -
                    WHERE cons.contype = 'p'
         | 
| 523 | 
            -
                      AND cons.conrelid = '#{quote_table_name(table)}'::regclass
         | 
| 524 | 
            +
                    INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = any(cons.conkey)
         | 
| 525 | 
            +
                    WHERE cons.contype = 'p' AND cons.conrelid = '#{quote_table_name(table)}'::regclass
         | 
| 524 526 | 
             
                  end_sql
         | 
| 525 527 |  | 
| 526 528 | 
             
                  result && result['attname']
         | 
| @@ -874,7 +876,7 @@ module ArJdbc | |
| 874 876 | 
             
                    sql_type = column.respond_to?(:sql_type) && column.sql_type
         | 
| 875 877 | 
             
                    sql_type && sql_type[0, 3] == 'bit' ? quote_bit(value) : super
         | 
| 876 878 | 
             
                  when Array
         | 
| 877 | 
            -
                    if  | 
| 879 | 
            +
                    if AR40 && column.array? # will be always falsy in AR < 4.0
         | 
| 878 880 | 
             
                      "'#{jdbc_column_class.array_to_string(value, column, self).gsub(/'/, "''")}'"
         | 
| 879 881 | 
             
                    elsif column.type == :json # only in AR-4.0
         | 
| 880 882 | 
             
                      super(jdbc_column_class.json_to_string(value), column)
         | 
| @@ -895,7 +897,7 @@ module ArJdbc | |
| 895 897 | 
             
                    end
         | 
| 896 898 | 
             
                  when Range
         | 
| 897 899 | 
             
                    sql_type = column.respond_to?(:sql_type) && column.sql_type
         | 
| 898 | 
            -
                    if sql_type && sql_type[-5, 5] == 'range' &&  | 
| 900 | 
            +
                    if sql_type && sql_type[-5, 5] == 'range' && AR40
         | 
| 899 901 | 
             
                      escaped = quote_string(jdbc_column_class.range_to_string(value))
         | 
| 900 902 | 
             
                      "'#{escaped}'::#{sql_type}"
         | 
| 901 903 | 
             
                    else super
         | 
| @@ -908,7 +910,7 @@ module ArJdbc | |
| 908 910 | 
             
                  else
         | 
| 909 911 | 
             
                    super
         | 
| 910 912 | 
             
                  end
         | 
| 911 | 
            -
                end unless  | 
| 913 | 
            +
                end unless AR42
         | 
| 912 914 |  | 
| 913 915 | 
             
                # @private
         | 
| 914 916 | 
             
                def _quote(value)
         | 
| @@ -932,8 +934,8 @@ module ArJdbc | |
| 932 934 | 
             
                  else
         | 
| 933 935 | 
             
                    super
         | 
| 934 936 | 
             
                  end
         | 
| 935 | 
            -
                end if  | 
| 936 | 
            -
                private :_quote if  | 
| 937 | 
            +
                end if AR42
         | 
| 938 | 
            +
                private :_quote if AR42
         | 
| 937 939 |  | 
| 938 940 | 
             
                # Quotes a string, escaping any ' (single quote) and \ (backslash) chars.
         | 
| 939 941 | 
             
                # @return [String]
         | 
| @@ -962,7 +964,7 @@ module ArJdbc | |
| 962 964 |  | 
| 963 965 | 
             
                def quote_bit(value)
         | 
| 964 966 | 
             
                  "B'#{value}'"
         | 
| 965 | 
            -
                end if  | 
| 967 | 
            +
                end if AR40
         | 
| 966 968 |  | 
| 967 969 | 
             
                def escape_bytea(string)
         | 
| 968 970 | 
             
                  return unless string
         | 
| @@ -990,7 +992,7 @@ module ArJdbc | |
| 990 992 | 
             
                # @override
         | 
| 991 993 | 
             
                def quote_table_name_for_assignment(table, attr)
         | 
| 992 994 | 
             
                  quote_column_name(attr)
         | 
| 993 | 
            -
                end if  | 
| 995 | 
            +
                end if AR40
         | 
| 994 996 |  | 
| 995 997 | 
             
                # @override
         | 
| 996 998 | 
             
                def quote_column_name(name)
         | 
| @@ -1072,35 +1074,50 @@ module ArJdbc | |
| 1072 1074 | 
             
                  change_column_null(table_name, column_name, false, default) if notnull
         | 
| 1073 1075 | 
             
                end if ::ActiveRecord::VERSION::MAJOR < 4
         | 
| 1074 1076 |  | 
| 1077 | 
            +
                # @private documented above
         | 
| 1078 | 
            +
                def add_column(table_name, column_name, type, options = {}); super end if AR42
         | 
| 1079 | 
            +
             | 
| 1075 1080 | 
             
                # Changes the column of a table.
         | 
| 1076 1081 | 
             
                def change_column(table_name, column_name, type, options = {})
         | 
| 1077 1082 | 
             
                  quoted_table_name = quote_table_name(table_name)
         | 
| 1083 | 
            +
                  quoted_column_name = quote_table_name(column_name)
         | 
| 1078 1084 |  | 
| 1079 1085 | 
             
                  sql_type = type_to_sql(type, options[:limit], options[:precision], options[:scale])
         | 
| 1080 1086 | 
             
                  sql_type << "[]" if options[:array]
         | 
| 1081 1087 |  | 
| 1088 | 
            +
                  sql = "ALTER TABLE #{quoted_table_name} ALTER COLUMN #{quoted_column_name} TYPE #{sql_type}"
         | 
| 1089 | 
            +
                  sql << " USING #{options[:using]}" if options[:using]
         | 
| 1090 | 
            +
                  if options[:cast_as]
         | 
| 1091 | 
            +
                    sql << " USING CAST(#{quoted_column_name} AS #{type_to_sql(options[:cast_as], options[:limit], options[:precision], options[:scale])})"
         | 
| 1092 | 
            +
                  end
         | 
| 1082 1093 | 
             
                  begin
         | 
| 1083 | 
            -
                    execute  | 
| 1094 | 
            +
                    execute sql
         | 
| 1084 1095 | 
             
                  rescue ActiveRecord::StatementInvalid => e
         | 
| 1085 1096 | 
             
                    raise e if postgresql_version > 80000
         | 
| 1086 | 
            -
                     | 
| 1087 | 
            -
                    begin
         | 
| 1088 | 
            -
                      begin_db_transaction
         | 
| 1089 | 
            -
                      tmp_column_name = "#{column_name}_ar_tmp"
         | 
| 1090 | 
            -
                      add_column(table_name, tmp_column_name, type, options)
         | 
| 1091 | 
            -
                      execute "UPDATE #{quoted_table_name} SET #{quote_column_name(tmp_column_name)} = CAST(#{quote_column_name(column_name)} AS #{sql_type})"
         | 
| 1092 | 
            -
                      remove_column(table_name, column_name)
         | 
| 1093 | 
            -
                      rename_column(table_name, tmp_column_name, column_name)
         | 
| 1094 | 
            -
                      commit_db_transaction
         | 
| 1095 | 
            -
                    rescue
         | 
| 1096 | 
            -
                      rollback_db_transaction
         | 
| 1097 | 
            -
                    end
         | 
| 1097 | 
            +
                    change_column_pg7(table_name, column_name, type, options)
         | 
| 1098 1098 | 
             
                  end
         | 
| 1099 1099 |  | 
| 1100 1100 | 
             
                  change_column_default(table_name, column_name, options[:default]) if options_include_default?(options)
         | 
| 1101 1101 | 
             
                  change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
         | 
| 1102 1102 | 
             
                end # unless const_defined? :SchemaCreation
         | 
| 1103 1103 |  | 
| 1104 | 
            +
                def change_column_pg7(table_name, column_name, type, options)
         | 
| 1105 | 
            +
                  quoted_table_name = quote_table_name(table_name)
         | 
| 1106 | 
            +
                  # This is PostgreSQL 7.x, so we have to use a more arcane way of doing it.
         | 
| 1107 | 
            +
                  begin
         | 
| 1108 | 
            +
                    begin_db_transaction
         | 
| 1109 | 
            +
                    tmp_column_name = "#{column_name}_ar_tmp"
         | 
| 1110 | 
            +
                    add_column(table_name, tmp_column_name, type, options)
         | 
| 1111 | 
            +
                    execute "UPDATE #{quoted_table_name} SET #{quote_column_name(tmp_column_name)} = CAST(#{quote_column_name(column_name)} AS #{sql_type})"
         | 
| 1112 | 
            +
                    remove_column(table_name, column_name)
         | 
| 1113 | 
            +
                    rename_column(table_name, tmp_column_name, column_name)
         | 
| 1114 | 
            +
                    commit_db_transaction
         | 
| 1115 | 
            +
                  rescue
         | 
| 1116 | 
            +
                    rollback_db_transaction
         | 
| 1117 | 
            +
                  end
         | 
| 1118 | 
            +
                end
         | 
| 1119 | 
            +
                private :change_column_pg7
         | 
| 1120 | 
            +
             | 
| 1104 1121 | 
             
                # Changes the default value of a table column.
         | 
| 1105 1122 | 
             
                def change_column_default(table_name, column_name, default)
         | 
| 1106 1123 | 
             
                  if column = column_for(table_name, column_name) # (backwards) compatible with AR 3.x - 4.x
         | 
| @@ -1108,8 +1125,23 @@ module ArJdbc | |
| 1108 1125 | 
             
                  else
         | 
| 1109 1126 | 
             
                    execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} SET DEFAULT #{quote(default)}"
         | 
| 1110 1127 | 
             
                  end
         | 
| 1111 | 
            -
                end # unless const_defined? :SchemaCreation
         | 
| 1128 | 
            +
                end unless AR42 # unless const_defined? :SchemaCreation
         | 
| 1129 | 
            +
             | 
| 1130 | 
            +
                # @private documented above
         | 
| 1131 | 
            +
                def change_column_default(table_name, column_name, default)
         | 
| 1132 | 
            +
                  return unless column = column_for(table_name, column_name)
         | 
| 1133 | 
            +
             | 
| 1134 | 
            +
                  alter_column_query = "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} %s"
         | 
| 1135 | 
            +
                  if default.nil?
         | 
| 1136 | 
            +
                    # <tt>DEFAULT NULL</tt> results in the same behavior as <tt>DROP DEFAULT</tt>. However, PostgreSQL will
         | 
| 1137 | 
            +
                    # cast the default to the columns type, which leaves us with a default like "default NULL::character varying".
         | 
| 1138 | 
            +
                    execute alter_column_query % "DROP DEFAULT"
         | 
| 1139 | 
            +
                  else
         | 
| 1140 | 
            +
                    execute alter_column_query % "SET DEFAULT #{quote_default_value(default, column)}"
         | 
| 1141 | 
            +
                  end
         | 
| 1142 | 
            +
                end if AR42
         | 
| 1112 1143 |  | 
| 1144 | 
            +
                # @private
         | 
| 1113 1145 | 
             
                def change_column_null(table_name, column_name, null, default = nil)
         | 
| 1114 1146 | 
             
                  unless null || default.nil?
         | 
| 1115 1147 | 
             
                    if column = column_for(table_name, column_name) # (backwards) compatible with AR 3.x - 4.x
         | 
| @@ -1119,7 +1151,16 @@ module ArJdbc | |
| 1119 1151 | 
             
                    end
         | 
| 1120 1152 | 
             
                  end
         | 
| 1121 1153 | 
             
                  execute("ALTER TABLE #{quote_table_name(table_name)} ALTER #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL")
         | 
| 1122 | 
            -
                end # unless const_defined? :SchemaCreation
         | 
| 1154 | 
            +
                end unless AR42 # unless const_defined? :SchemaCreation
         | 
| 1155 | 
            +
             | 
| 1156 | 
            +
                # @private
         | 
| 1157 | 
            +
                def change_column_null(table_name, column_name, null, default = nil)
         | 
| 1158 | 
            +
                  unless null || default.nil?
         | 
| 1159 | 
            +
                    column = column_for(table_name, column_name)
         | 
| 1160 | 
            +
                    execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote_default_value(default, column)} WHERE #{quote_column_name(column_name)} IS NULL") if column
         | 
| 1161 | 
            +
                  end
         | 
| 1162 | 
            +
                  execute("ALTER TABLE #{quote_table_name(table_name)} ALTER #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL")
         | 
| 1163 | 
            +
                end if AR42
         | 
| 1123 1164 |  | 
| 1124 1165 | 
             
                def rename_column(table_name, column_name, new_column_name)
         | 
| 1125 1166 | 
             
                  execute "ALTER TABLE #{quote_table_name(table_name)} RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}"
         | 
| @@ -1129,16 +1170,55 @@ module ArJdbc | |
| 1129 1170 | 
             
                def add_index(table_name, column_name, options = {})
         | 
| 1130 1171 | 
             
                  index_name, index_type, index_columns, index_options, index_algorithm, index_using = add_index_options(table_name, column_name, options)
         | 
| 1131 1172 | 
             
                  execute "CREATE #{index_type} INDEX #{index_algorithm} #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} #{index_using} (#{index_columns})#{index_options}"
         | 
| 1132 | 
            -
                end if  | 
| 1173 | 
            +
                end if AR40
         | 
| 1133 1174 |  | 
| 1134 1175 | 
             
                def remove_index!(table_name, index_name)
         | 
| 1135 1176 | 
             
                  execute "DROP INDEX #{quote_table_name(index_name)}"
         | 
| 1136 1177 | 
             
                end
         | 
| 1137 1178 |  | 
| 1138 1179 | 
             
                def rename_index(table_name, old_name, new_name)
         | 
| 1180 | 
            +
                  validate_index_length!(table_name, new_name) if respond_to?(:validate_index_length!)
         | 
| 1181 | 
            +
             | 
| 1139 1182 | 
             
                  execute "ALTER INDEX #{quote_column_name(old_name)} RENAME TO #{quote_table_name(new_name)}"
         | 
| 1140 1183 | 
             
                end
         | 
| 1141 1184 |  | 
| 1185 | 
            +
                def supports_foreign_keys?; true end
         | 
| 1186 | 
            +
             | 
| 1187 | 
            +
                def foreign_keys(table_name)
         | 
| 1188 | 
            +
                  fk_info = select_all "" <<
         | 
| 1189 | 
            +
                    "SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete " <<
         | 
| 1190 | 
            +
                    "FROM pg_constraint c " <<
         | 
| 1191 | 
            +
                    "JOIN pg_class t1 ON c.conrelid = t1.oid " <<
         | 
| 1192 | 
            +
                    "JOIN pg_class t2 ON c.confrelid = t2.oid " <<
         | 
| 1193 | 
            +
                    "JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid " <<
         | 
| 1194 | 
            +
                    "JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid " <<
         | 
| 1195 | 
            +
                    "JOIN pg_namespace t3 ON c.connamespace = t3.oid " <<
         | 
| 1196 | 
            +
                    "WHERE c.contype = 'f' " <<
         | 
| 1197 | 
            +
                    "  AND t1.relname = #{quote(table_name)} " <<
         | 
| 1198 | 
            +
                    "  AND t3.nspname = ANY (current_schemas(false)) " <<
         | 
| 1199 | 
            +
                    "ORDER BY c.conname "
         | 
| 1200 | 
            +
             | 
| 1201 | 
            +
                  fk_info.map! do |row|
         | 
| 1202 | 
            +
                    options = {
         | 
| 1203 | 
            +
                      :column => row['column'], :name => row['name'], :primary_key => row['primary_key']
         | 
| 1204 | 
            +
                    }
         | 
| 1205 | 
            +
                    options[:on_delete] = extract_foreign_key_action(row['on_delete'])
         | 
| 1206 | 
            +
                    options[:on_update] = extract_foreign_key_action(row['on_update'])
         | 
| 1207 | 
            +
             | 
| 1208 | 
            +
                    ForeignKeyDefinition.new(table_name, row['to_table'], options)
         | 
| 1209 | 
            +
                  end
         | 
| 1210 | 
            +
                end if defined? ForeignKeyDefinition
         | 
| 1211 | 
            +
             | 
| 1212 | 
            +
                # @private
         | 
| 1213 | 
            +
                def extract_foreign_key_action(specifier)
         | 
| 1214 | 
            +
                  case specifier
         | 
| 1215 | 
            +
                  when 'c'; :cascade
         | 
| 1216 | 
            +
                  when 'n'; :nullify
         | 
| 1217 | 
            +
                  when 'r'; :restrict
         | 
| 1218 | 
            +
                  end
         | 
| 1219 | 
            +
                end
         | 
| 1220 | 
            +
                private :extract_foreign_key_action
         | 
| 1221 | 
            +
             | 
| 1142 1222 | 
             
                def index_name_length
         | 
| 1143 1223 | 
             
                  63
         | 
| 1144 1224 | 
             
                end
         | 
| @@ -1180,12 +1260,12 @@ module ArJdbc | |
| 1180 1260 |  | 
| 1181 1261 | 
             
                    column.new(name, default_value, oid_type, type, ! notnull, default_function, oid, self)
         | 
| 1182 1262 | 
             
                  end
         | 
| 1183 | 
            -
                end if  | 
| 1263 | 
            +
                end if AR42
         | 
| 1184 1264 |  | 
| 1185 1265 | 
             
                # @private only for API compatibility
         | 
| 1186 1266 | 
             
                def new_column(name, default, cast_type, sql_type = nil, null = true, default_function = nil)
         | 
| 1187 1267 | 
             
                  jdbc_column_class.new(name, default, cast_type, sql_type, null, default_function)
         | 
| 1188 | 
            -
                end if  | 
| 1268 | 
            +
                end if AR42
         | 
| 1189 1269 |  | 
| 1190 1270 | 
             
                # @private
         | 
| 1191 1271 | 
             
                def column_for(table_name, column_name)
         | 
| @@ -1227,7 +1307,7 @@ module ArJdbc | |
| 1227 1307 | 
             
                # @private
         | 
| 1228 1308 | 
             
                TABLE_EXISTS_SQL_PREFIX =  'SELECT COUNT(*) as table_count FROM pg_class c'
         | 
| 1229 1309 | 
             
                TABLE_EXISTS_SQL_PREFIX << ' LEFT JOIN pg_namespace n ON n.oid = c.relnamespace'
         | 
| 1230 | 
            -
                if  | 
| 1310 | 
            +
                if AR42 # -- (r)elation/table, (v)iew, (m)aterialized view
         | 
| 1231 1311 | 
             
                TABLE_EXISTS_SQL_PREFIX << " WHERE c.relkind IN ('r','v','m')"
         | 
| 1232 1312 | 
             
                else
         | 
| 1233 1313 | 
             
                TABLE_EXISTS_SQL_PREFIX << " WHERE c.relkind IN ('r','v')"
         | 
| @@ -1251,6 +1331,10 @@ module ArJdbc | |
| 1251 1331 | 
             
                  end
         | 
| 1252 1332 | 
             
                end
         | 
| 1253 1333 |  | 
| 1334 | 
            +
                def drop_table(table_name, options = {})
         | 
| 1335 | 
            +
                  execute "DROP TABLE #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
         | 
| 1336 | 
            +
                end
         | 
| 1337 | 
            +
             | 
| 1254 1338 | 
             
                def truncate(table_name, name = nil)
         | 
| 1255 1339 | 
             
                  execute "TRUNCATE TABLE #{quote_table_name(table_name)}", name
         | 
| 1256 1340 | 
             
                end
         | 
| @@ -1266,7 +1350,7 @@ module ArJdbc | |
| 1266 1350 | 
             
                      AND t.relname = '#{table_name}'
         | 
| 1267 1351 | 
             
                      AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (current_schemas(false)) )
         | 
| 1268 1352 | 
             
                  SQL
         | 
| 1269 | 
            -
                end if  | 
| 1353 | 
            +
                end if AR42
         | 
| 1270 1354 |  | 
| 1271 1355 | 
             
                # Returns an array of indexes for the given table.
         | 
| 1272 1356 | 
             
                def indexes(table_name, name = nil)
         | 
| @@ -1328,7 +1412,7 @@ module ArJdbc | |
| 1328 1412 | 
             
                  when 'average' then 'avg'
         | 
| 1329 1413 | 
             
                  else operation.downcase
         | 
| 1330 1414 | 
             
                  end
         | 
| 1331 | 
            -
                end if  | 
| 1415 | 
            +
                end if AR42
         | 
| 1332 1416 |  | 
| 1333 1417 | 
             
                private
         | 
| 1334 1418 |  | 
| @@ -1391,9 +1475,9 @@ module ActiveRecord::ConnectionAdapters | |
| 1391 1475 | 
             
                include ::ArJdbc::PostgreSQL
         | 
| 1392 1476 | 
             
                include ::ArJdbc::PostgreSQL::ExplainSupport
         | 
| 1393 1477 |  | 
| 1394 | 
            -
                require 'arjdbc/postgresql/oid_types' if  | 
| 1478 | 
            +
                require 'arjdbc/postgresql/oid_types' if ::ArJdbc::AR40
         | 
| 1395 1479 | 
             
                include ::ArJdbc::PostgreSQL::OIDTypes if ::ArJdbc::PostgreSQL.const_defined?(:OIDTypes)
         | 
| 1396 | 
            -
                include ::ArJdbc::PostgreSQL::ColumnHelpers if  | 
| 1480 | 
            +
                include ::ArJdbc::PostgreSQL::ColumnHelpers if ::ArJdbc::AR42
         | 
| 1397 1481 |  | 
| 1398 1482 | 
             
                include ::ArJdbc::Util::QuotedCache
         | 
| 1399 1483 |  | 
| @@ -1405,141 +1489,28 @@ module ActiveRecord::ConnectionAdapters | |
| 1405 1489 |  | 
| 1406 1490 | 
             
                  @table_alias_length = nil
         | 
| 1407 1491 |  | 
| 1408 | 
            -
                  initialize_type_map(@type_map = Type::HashLookupTypeMap.new) if  | 
| 1492 | 
            +
                  initialize_type_map(@type_map = Type::HashLookupTypeMap.new) if ::ArJdbc::AR42
         | 
| 1409 1493 |  | 
| 1410 1494 | 
             
                  @use_insert_returning = @config.key?(:insert_returning) ?
         | 
| 1411 1495 | 
             
                    self.class.type_cast_config_to_boolean(@config[:insert_returning]) : nil
         | 
| 1412 1496 | 
             
                end
         | 
| 1413 1497 |  | 
| 1414 | 
            -
                 | 
| 1415 | 
            -
                   | 
| 1416 | 
            -
             | 
| 1417 | 
            -
             | 
| 1418 | 
            -
             | 
| 1419 | 
            -
                module ColumnMethods
         | 
| 1420 | 
            -
                  def xml(*args)
         | 
| 1421 | 
            -
                    options = args.extract_options!
         | 
| 1422 | 
            -
                    column(args[0], 'xml', options)
         | 
| 1423 | 
            -
                  end
         | 
| 1424 | 
            -
             | 
| 1425 | 
            -
                  def tsvector(*args)
         | 
| 1426 | 
            -
                    options = args.extract_options!
         | 
| 1427 | 
            -
                    column(args[0], 'tsvector', options)
         | 
| 1428 | 
            -
                  end
         | 
| 1429 | 
            -
             | 
| 1430 | 
            -
                  def int4range(name, options = {})
         | 
| 1431 | 
            -
                    column(name, 'int4range', options)
         | 
| 1432 | 
            -
                  end
         | 
| 1433 | 
            -
             | 
| 1434 | 
            -
                  def int8range(name, options = {})
         | 
| 1435 | 
            -
                    column(name, 'int8range', options)
         | 
| 1436 | 
            -
                  end
         | 
| 1437 | 
            -
             | 
| 1438 | 
            -
                  def tsrange(name, options = {})
         | 
| 1439 | 
            -
                    column(name, 'tsrange', options)
         | 
| 1440 | 
            -
                  end
         | 
| 1441 | 
            -
             | 
| 1442 | 
            -
                  def tstzrange(name, options = {})
         | 
| 1443 | 
            -
                    column(name, 'tstzrange', options)
         | 
| 1444 | 
            -
                  end
         | 
| 1445 | 
            -
             | 
| 1446 | 
            -
                  def numrange(name, options = {})
         | 
| 1447 | 
            -
                    column(name, 'numrange', options)
         | 
| 1448 | 
            -
                  end
         | 
| 1449 | 
            -
             | 
| 1450 | 
            -
                  def daterange(name, options = {})
         | 
| 1451 | 
            -
                    column(name, 'daterange', options)
         | 
| 1452 | 
            -
                  end
         | 
| 1453 | 
            -
             | 
| 1454 | 
            -
                  def hstore(name, options = {})
         | 
| 1455 | 
            -
                    column(name, 'hstore', options)
         | 
| 1456 | 
            -
                  end
         | 
| 1457 | 
            -
             | 
| 1458 | 
            -
                  def ltree(name, options = {})
         | 
| 1459 | 
            -
                    column(name, 'ltree', options)
         | 
| 1460 | 
            -
                  end
         | 
| 1461 | 
            -
             | 
| 1462 | 
            -
                  def inet(name, options = {})
         | 
| 1463 | 
            -
                    column(name, 'inet', options)
         | 
| 1464 | 
            -
                  end
         | 
| 1465 | 
            -
             | 
| 1466 | 
            -
                  def cidr(name, options = {})
         | 
| 1467 | 
            -
                    column(name, 'cidr', options)
         | 
| 1468 | 
            -
                  end
         | 
| 1469 | 
            -
             | 
| 1470 | 
            -
                  def macaddr(name, options = {})
         | 
| 1471 | 
            -
                    column(name, 'macaddr', options)
         | 
| 1472 | 
            -
                  end
         | 
| 1473 | 
            -
             | 
| 1474 | 
            -
                  def uuid(name, options = {})
         | 
| 1475 | 
            -
                    column(name, 'uuid', options)
         | 
| 1476 | 
            -
                  end
         | 
| 1477 | 
            -
             | 
| 1478 | 
            -
                  def json(name, options = {})
         | 
| 1479 | 
            -
                    column(name, 'json', options)
         | 
| 1480 | 
            -
                  end
         | 
| 1481 | 
            -
             | 
| 1482 | 
            -
                  def jsonb(name, options = {})
         | 
| 1483 | 
            -
                    column(name, :jsonb, options)
         | 
| 1484 | 
            -
                  end
         | 
| 1485 | 
            -
             | 
| 1486 | 
            -
                  def bit(name, options)
         | 
| 1487 | 
            -
                    column(name, 'bit', options)
         | 
| 1488 | 
            -
                  end
         | 
| 1489 | 
            -
             | 
| 1490 | 
            -
                  def bit_varying(name, options)
         | 
| 1491 | 
            -
                    column(name, 'bit varying', options)
         | 
| 1492 | 
            -
                  end
         | 
| 1498 | 
            +
                if ::ArJdbc::AR42
         | 
| 1499 | 
            +
                  require 'active_record/connection_adapters/postgresql/schema_definitions'
         | 
| 1500 | 
            +
                else
         | 
| 1501 | 
            +
                  require 'arjdbc/postgresql/base/schema_definitions'
         | 
| 1493 1502 | 
             
                end
         | 
| 1494 1503 |  | 
| 1495 | 
            -
                 | 
| 1496 | 
            -
                  include ColumnMethods
         | 
| 1497 | 
            -
             | 
| 1498 | 
            -
                  def primary_key(name, type = :primary_key, options = {})
         | 
| 1499 | 
            -
                    return super unless type == :uuid
         | 
| 1500 | 
            -
                    options[:default] = options.fetch(:default, 'uuid_generate_v4()')
         | 
| 1501 | 
            -
                    options[:primary_key] = true
         | 
| 1502 | 
            -
                    column name, type, options
         | 
| 1503 | 
            -
                  end if ::ActiveRecord::VERSION::MAJOR > 3 # 3.2 super expects (name)
         | 
| 1504 | 
            -
             | 
| 1505 | 
            -
                  def column(name, type = nil, options = {})
         | 
| 1506 | 
            -
                    super
         | 
| 1507 | 
            -
                    column = self[name]
         | 
| 1508 | 
            -
                    # NOTE: <= 3.1 no #new_column_definition hard-coded ColumnDef.new :
         | 
| 1509 | 
            -
                    # column = self[name] || ColumnDefinition.new(@base, name, type)
         | 
| 1510 | 
            -
                    # thus we simply do not support array column definitions on <= 3.1
         | 
| 1511 | 
            -
                    column.array = options[:array] if column.is_a?(ColumnDefinition)
         | 
| 1512 | 
            -
                    self
         | 
| 1513 | 
            -
                  end
         | 
| 1504 | 
            +
                ColumnDefinition = ActiveRecord::ConnectionAdapters::PostgreSQL::ColumnDefinition
         | 
| 1514 1505 |  | 
| 1515 | 
            -
             | 
| 1516 | 
            -
             | 
| 1517 | 
            -
                  if ::ActiveRecord::VERSION::MAJOR > 3
         | 
| 1518 | 
            -
             | 
| 1519 | 
            -
                    def create_column_definition(name, type)
         | 
| 1520 | 
            -
                      ColumnDefinition.new name, type
         | 
| 1521 | 
            -
                    end
         | 
| 1522 | 
            -
             | 
| 1523 | 
            -
                  else # no #create_column_definition on 3.2
         | 
| 1524 | 
            -
             | 
| 1525 | 
            -
                    def new_column_definition(base, name, type)
         | 
| 1526 | 
            -
                      definition = ColumnDefinition.new base, name, type
         | 
| 1527 | 
            -
                      @columns << definition
         | 
| 1528 | 
            -
                      @columns_hash[name] = definition
         | 
| 1529 | 
            -
                      definition
         | 
| 1530 | 
            -
                    end
         | 
| 1531 | 
            -
             | 
| 1532 | 
            -
                  end
         | 
| 1533 | 
            -
             | 
| 1534 | 
            -
                end
         | 
| 1506 | 
            +
                ColumnMethods = ActiveRecord::ConnectionAdapters::PostgreSQL::ColumnMethods
         | 
| 1507 | 
            +
                TableDefinition = ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition
         | 
| 1535 1508 |  | 
| 1536 1509 | 
             
                def table_definition(*args)
         | 
| 1537 1510 | 
             
                  new_table_definition(TableDefinition, *args)
         | 
| 1538 1511 | 
             
                end
         | 
| 1539 1512 |  | 
| 1540 | 
            -
                 | 
| 1541 | 
            -
                  include ColumnMethods
         | 
| 1542 | 
            -
                end
         | 
| 1513 | 
            +
                Table = ActiveRecord::ConnectionAdapters::PostgreSQL::Table
         | 
| 1543 1514 |  | 
| 1544 1515 | 
             
                def update_table_definition(table_name, base)
         | 
| 1545 1516 | 
             
                  Table.new(table_name, base)
         |