Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 8922

Show
Ignore:
Timestamp:
02/22/08 03:26:21 (9 months ago)
Author:
bitsweat
Message:

PostgreSQL: support server versions 7.4 through 8.0 and the ruby-pg driver. Closes #11127

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r8894 r8922  
    11*SVN* 
     2 
     3* PostgreSQL: support server versions 7.4 through 8.0 and the ruby-pg driver.  #11127 [jdavis] 
    24 
    35* Ensure association preloading doesn't break when an association returns nil. ##11145 [GMFlash] 
  • trunk/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

    r8663 r8922  
    11require 'active_record/connection_adapters/abstract_adapter' 
     2 
     3begin 
     4  require_library_or_gem 'pg' 
     5rescue LoadError => e 
     6  begin 
     7    require_library_or_gem 'postgres' 
     8    class PGresult 
     9      alias_method :nfields, :num_fields unless self.method_defined?(:nfields) 
     10      alias_method :ntuples, :num_tuples unless self.method_defined?(:ntuples) 
     11      alias_method :ftype, :type unless self.method_defined?(:ftype) 
     12      alias_method :cmd_tuples, :cmdtuples unless self.method_defined?(:cmd_tuples) 
     13    end 
     14  rescue LoadError 
     15    raise e 
     16  end 
     17end 
    218 
    319module ActiveRecord 
     
    521    # Establishes a connection to the database that's used by all Active Record objects 
    622    def self.postgresql_connection(config) # :nodoc: 
    7       require_library_or_gem 'postgres' unless self.class.const_defined?(:PGconn) 
    8  
    923      config = config.symbolize_keys 
    1024      host     = config[:host] 
     
    301315        # than error and "SHOW standard_conforming_strings" fails, but returns an empty 
    302316        # PGresult instead. 
    303         has_support = execute('SHOW standard_conforming_strings')[0][0] rescue false 
     317        has_support = query('SHOW standard_conforming_strings')[0][0] rescue false 
    304318        self.client_min_messages = client_min_messages_old 
    305319        has_support 
     
    370384      # REFERENTIAL INTEGRITY ==================================== 
    371385 
     386      def supports_disable_referential_integrity?() #:nodoc: 
     387        version = query("SHOW server_version")[0][0].split('.') 
     388        (version[0].to_i >= 8 && version[1].to_i >= 1) ? true : false 
     389      rescue 
     390        return false 
     391      end 
     392 
    372393      def disable_referential_integrity(&block) #:nodoc: 
    373         execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";")) 
     394        if supports_disable_referential_integrity?() then 
     395          execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";")) 
     396        end 
    374397        yield 
    375398      ensure 
    376         execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";")) 
     399        if supports_disable_referential_integrity?() then 
     400          execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";")) 
     401        end 
    377402      end 
    378403 
     
    391416      end 
    392417 
    393       # Queries the database and returns the results in an Array or nil otherwise. 
     418      # create a 2D array representing the result set 
     419      def result_as_array(res) #:nodoc: 
     420        ary = [] 
     421        for i in 0...res.ntuples do 
     422          ary << [] 
     423          for j in 0...res.nfields do 
     424            ary[i] << res.getvalue(i,j) 
     425          end 
     426        end 
     427        return ary 
     428      end 
     429 
     430 
     431      # Queries the database and returns the results in an Array-like object 
    394432      def query(sql, name = nil) #:nodoc: 
    395433        log(sql, name) do 
    396434          if @async 
    397             @connection.async_query(sql) 
     435            res = @connection.async_exec(sql) 
    398436          else 
    399             @connection.query(sql) 
    400           end 
     437            res = @connection.exec(sql) 
     438          end 
     439          return result_as_array(res) 
    401440        end 
    402441      end 
     
    416455      # Executes an UPDATE query and returns the number of affected tuples. 
    417456      def update_sql(sql, name = nil) 
    418         super.cmdtuples 
     457        super.cmd_tuples 
    419458      end 
    420459 
     
    567606          # the 8.1+ nextval('foo'::regclass). 
    568607          result = query(<<-end_sql, 'PK and custom sequence')[0] 
    569             SELECT attr.attname, split_part(def.adsrc, '''', 2) 
     608            SELECT attr.attname, 
     609              CASE 
     610                WHEN split_part(def.adsrc, '''', 2) ~ '.' THEN 
     611                  substr(split_part(def.adsrc, '''', 2), 
     612                         strpos(split_part(def.adsrc, '''', 2), '.')+1) 
     613                ELSE split_part(def.adsrc, '''', 2) 
     614              END 
    570615            FROM pg_class       t 
    571616            JOIN pg_attribute   attr ON (t.oid = attrelid) 
     
    577622          end_sql 
    578623        end 
     624 
    579625        # [primary_key, sequence] 
    580626        [result.first, result.last] 
     
    609655        rescue ActiveRecord::StatementInvalid 
    610656          # This is PostgreSQL 7.x, so we have to use a more arcane way of doing it. 
    611           begin_db_transaction 
    612           tmp_column_name = "#{column_name}_ar_tmp" 
    613           add_column(table_name, tmp_column_name, type, options) 
    614           execute "UPDATE #{quoted_table_name} SET #{quote_column_name(tmp_column_name)} = CAST(#{quote_column_name(column_name)} AS #{type_to_sql(type, options[:limit], options[:precision], options[:scale])})" 
    615           remove_column(table_name, column_name) 
    616           rename_column(table_name, tmp_column_name, column_name) 
    617           commit_db_transaction 
     657          begin 
     658            begin_db_transaction 
     659            tmp_column_name = "#{column_name}_ar_tmp" 
     660            add_column(table_name, tmp_column_name, type, options) 
     661            execute "UPDATE #{quoted_table_name} SET #{quote_column_name(tmp_column_name)} = CAST(#{quote_column_name(column_name)} AS #{type_to_sql(type, options[:limit], options[:precision], options[:scale])})" 
     662            remove_column(table_name, column_name) 
     663            rename_column(table_name, tmp_column_name, column_name) 
     664            commit_db_transaction 
     665          rescue 
     666            rollback_db_transaction 
     667          end 
    618668        end 
    619669 
     
    786836        def select_raw(sql, name = nil) 
    787837          res = execute(sql, name) 
    788           results = res.result 
     838          results = result_as_array(res) 
    789839          fields = [] 
    790840          rows = [] 
    791           if results.length > 0 
     841          if res.ntuples > 0 
    792842            fields = res.fields 
    793843            results.each do |row| 
     
    798848                # PostgreSQLColumn.string_to_decimal but would break form input 
    799849                # fields that call value_before_type_cast. 
    800                 if res.type(cell_index) == MONEY_COLUMN_TYPE_OID 
     850                if res.ftype(cell_index) == MONEY_COLUMN_TYPE_OID 
    801851                  # Because money output is formatted according to the locale, there are two 
    802852                  # cases to consider (note the decimal separators): 
  • trunk/activerecord/test/cases/defaults_test.rb

    r8681 r8922  
    6262  if current_adapter?(:PostgreSQLAdapter) 
    6363    def test_multiline_default_text 
    64       assert_equal "--- []\n\n", Default.columns_hash['multiline_default'].default 
     64      # older postgres versions represent the default with escapes ("\\012" for a newline) 
     65      assert ( "--- []\n\n" == Default.columns_hash['multiline_default'].default || 
     66               "--- []\\012\\012" == Default.columns_hash['multiline_default'].default) 
    6567    end 
    6668  end 
  • trunk/activerecord/test/cases/schema_authorization_test_postgresql.rb

    r8681 r8922  
    1919    set_session_auth 
    2020    USERS.each do |u| 
    21       @connection.execute "CREATE ROLE #{u}" 
     21      @connection.execute "CREATE USER #{u}" 
    2222      @connection.execute "CREATE SCHEMA AUTHORIZATION #{u}" 
    2323      set_session_auth u 
     
    3333    USERS.each do |u| 
    3434      @connection.execute "DROP SCHEMA #{u} CASCADE" 
    35       @connection.execute "DROP ROLE #{u}" 
     35      @connection.execute "DROP USER #{u}" 
    3636    end 
    3737  end 
  • trunk/activerecord/test/schema/postgresql.sql

    r8659 r8922  
    111111    negative_integer integer default -1, 
    112112    decimal_number decimal(3,2) default 2.78, 
    113     multiline_default text DEFAULT E'--- []\n\n'::text 
     113    multiline_default text DEFAULT '--- [] 
     114 
     115'::text 
    114116); 
    115117