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

Ticket #2292: pg_seq.2363.diff

File pg_seq.2363.diff, 13.0 kB (added by Rick, 4 years ago)

get some coalesce() action up in here

  • activerecord/test/fixtures_test.rb

    old new  
    55require 'fixtures/task' 
    66require 'fixtures/reply' 
    77 
     8# Dummy model used to test fixtures loaded from a model 
     9module TestModule 
     10  class Task < ActiveRecord::Base 
     11  end 
     12end 
     13 
    814class FixturesTest < Test::Unit::TestCase 
    915  self.use_instantiated_fixtures = true 
    1016  self.use_transactional_fixtures = false 
    1117 
    12   fixtures :topics, :developers, :accounts, :tasks 
     18  fixtures :topics, :developers, :accounts, :tasks, TestModule::Task 
    1319 
    1420  FIXTURES = %w( accounts companies customers 
    1521                 developers developers_projects entrants 
  • activerecord/test/adapter_test.rb

    old new  
    3535  ensure 
    3636    @connection.remove_index :accounts, :firm_id rescue nil 
    3737  end 
     38   
     39  # test resetting sequences in odd tables in postgreSQL 
     40  if ActiveRecord::Base.connection.respond_to?(:reset_sequences) 
     41    require 'fixtures/movie' 
     42    require 'fixtures/subscriber' 
     43    def test_reset_empty_table_with_custom_pk 
     44      Movie.destroy_all 
     45      Movie.connection.reset_sequences 'movies' 
     46      assert_equal 1, Movie.create(:name => 'fight club').id 
     47    end 
     48     
     49    def test_reset_table_with_non_integer_pk 
     50      Subscriber.destroy_all 
     51      Subscriber.connection.reset_sequences 'sequences' 
     52      assert Subscriber.new(:id => 'bob drake', :name => 'robert drake').save 
     53    end 
     54  end 
    3855end 
  • activerecord/test/inheritance_test.rb

    old new  
    1111    if ActiveRecord::ConnectionAdapters.const_defined? :SQLServerAdapter and ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::SQLServerAdapter) 
    1212      Company.connection.execute "SET IDENTITY_INSERT companies ON" 
    1313    end 
    14     Company.connection.insert "INSERT INTO companies (id, type, name) VALUES(100, 'bad_class!', 'Not happening')" 
     14    Company.connection.insert "INSERT INTO companies (id, type, name) VALUES(100, 'bad_class!', 'Not happening')", nil, 'id', 100 
    1515    #We then need to turn it back Off before continuing. 
    1616    if ActiveRecord::ConnectionAdapters.const_defined? :SQLServerAdapter and ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::SQLServerAdapter) 
    1717      Company.connection.execute "SET IDENTITY_INSERT companies OFF" 
  • activerecord/test/fixtures/db_definitions/postgresql.sql

    old new  
    66); 
    77SELECT setval('accounts_id_seq', 100); 
    88 
     9CREATE SEQUENCE companies_nonstd_seq START 101; 
     10 
    911CREATE TABLE companies ( 
    10     id serial
     12    id integer DEFAULT nextval('companies_nonstd_seq')
    1113    "type" character varying(50), 
    1214    "ruby_type" character varying(50), 
    1315    firm_id integer, 
     
    1618    rating integer default 1, 
    1719    PRIMARY KEY (id) 
    1820); 
    19 SELECT setval('companies_id_seq', 100); 
    2021 
    2122CREATE TABLE developers_projects ( 
    2223    developer_id integer NOT NULL, 
  • activerecord/test/pk_test.rb

    old new  
    3232    subscriber.id = "jdoe" 
    3333    assert_equal("jdoe", subscriber.id) 
    3434    subscriber.name = "John Doe" 
    35     assert_nothing_raised{ subscriber.save
     35    assert_nothing_raised{ subscriber.save!
    3636 
    3737    subscriberReloaded = Subscriber.find("jdoe") 
    3838    assert_equal("John Doe", subscriberReloaded.name) 
  • activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

    old new  
    104104      def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc: 
    105105        execute(sql, name) 
    106106        table = sql.split(" ", 4)[2] 
    107         return id_value || last_insert_id(table, pk
     107        return id_value || last_insert_id(table, sequence_name
    108108      end 
    109109 
    110110      def query(sql, name = nil) #:nodoc: 
     
    200200      def schema_search_path #:nodoc: 
    201201        @schema_search_path ||= query('SHOW search_path')[0][0] 
    202202      end 
    203              
     203 
     204      def default_sequence_format(table_name, pk) 
     205        "#{table_name}_#{pk}_seq" 
     206      end 
     207 
     208      # Start PostgreSQL fixtures at id 1.  Skip tables without models 
     209      # and models with nonstandard primary keys. 
     210      def reset_sequences(*table_names) 
     211        table_names.each do |table| 
     212          table_name = table.to_s.split('.') 
     213          if table_name[1] 
     214            schema  = table_name[0] 
     215            relname = table_name[1] 
     216          else 
     217            schema  = 'public' 
     218            relname = table_name[0] 
     219          end 
     220          seq_sql = <<-end_seq 
     221            SELECT attname, CASE WHEN substr(pg_get_expr(adbin, attrelid), 1, 7) = 'nextval' THEN  
     222            substr(split_part((pg_get_expr(adbin, attrelid)), '''::', 1), 10) ELSE NULL END 
     223            FROM pg_attrdef, pg_namespace, pg_class, pg_attribute, pg_constraint 
     224            WHERE pg_namespace.nspname = '#{schema}'             AND 
     225            pg_class.relnamespace      = pg_namespace.oid        AND 
     226            pg_class.relname           = '#{relname}'            AND 
     227            pg_attribute.attrelid      = pg_class.oid            AND 
     228            pg_attribute.attnum        = pg_constraint.conkey[1] AND 
     229            pg_constraint.conrelid     = pg_class.oid            AND 
     230            pg_constraint.contype      = 'p'                     AND 
     231            pg_attrdef.adrelid         = pg_class.oid            AND 
     232            pg_attrdef.adnum           = pg_attribute.attnum 
     233          end_seq 
     234          seq = execute(seq_sql, 'Retrieve sequence name') 
     235          execute( 
     236            "SELECT setval('#{seq[0][1]}', (SELECT COALESCE(MAX(#{seq[0][0]})+1, 1) FROM #{schema}.#{relname}), false)", 
     237              'Setting Sequence' 
     238          ) unless seq[0].nil? || seq[0][1].nil? 
     239        end 
     240      end 
     241 
    204242      def add_column(table_name, column_name, type, options = {}) 
    205243        native_type = native_database_types[type] 
    206244        sql_commands = ["ALTER TABLE #{table_name} ADD #{column_name} #{type_to_sql(type, options[:limit])}"] 
     
    240278      private 
    241279        BYTEA_COLUMN_TYPE_OID = 17 
    242280 
    243         def last_insert_id(table, column = "id") 
    244           sequence_name = "#{table}_#{column || 'id'}_seq" 
     281        def last_insert_id(table, sequence_name) 
    245282          @connection.exec("SELECT currval('#{sequence_name}')")[0][0].to_i 
    246283        end 
    247284 
  • activerecord/lib/active_record/connection_adapters/oci_adapter.rb

    old new  
    263263        def adapter_name() 
    264264          'OCI' 
    265265        end 
    266          
     266 
     267        def default_sequence_format(table_name, pk) 
     268          "#{table_name}_seq" 
     269        end 
     270 
    267271        private 
    268272          # Oracle column names by default are case-insensitive, but treated as upcase; 
    269273          # for neatness, we'll downcase within Rails. EXCEPT that folks CAN quote 
  • activerecord/lib/active_record/fixtures.rb

    old new  
    220220  self.all_loaded_fixtures = {} 
    221221 
    222222  def self.create_fixtures(fixtures_directory, *table_names) 
     223    class_mapping = table_names.last.is_a?(Hash) ? table_names.pop : {} 
    223224    connection = block_given? ? yield : ActiveRecord::Base.connection 
    224225    old_logger_level = ActiveRecord::Base.logger.level 
    225226 
     
    237238        fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures } 
    238239        fixtures.each { |fixture| fixture.insert_fixtures } 
    239240      end 
    240        
    241       reset_sequences(connection, table_names) if connection.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) 
    242241 
     242      if connection.respond_to?(:reset_sequences) 
     243        connection.reset_sequences(*(table_names.flatten.collect { |t| t.respond_to?(:table_name) ? t.table_name : t  })) 
     244      end 
     245 
    243246      return fixtures.size > 1 ? fixtures : fixtures.first 
    244247    ensure 
    245248      ActiveRecord::Base.logger.level = old_logger_level 
    246249    end 
    247250  end 
    248251 
    249   # Start PostgreSQL fixtures at id 1.  Skip tables without models 
    250   # and models with nonstandard primary keys. 
    251   def self.reset_sequences(connection, table_names) 
    252     table_names.flatten.each do |table| 
    253       if table_class = table.to_s.classify.constantize rescue nil 
    254         pk = table_class.columns_hash[table_class.primary_key] 
    255         if pk and pk.type == :integer 
    256           connection.execute( 
    257             "SELECT setval('#{table}_#{pk.name}_seq', (SELECT COALESCE(0, MAX(#{pk.name}))+1 FROM #{table}), false)",  
    258             'Setting Sequence' 
    259           ) 
    260         end 
    261       end 
    262     end 
    263   end 
    264  
    265252  attr_reader :table_name 
    266253 
    267254  def initialize(connection, table_name, fixture_path, file_filter = DEFAULT_FILTER_RE) 
     
    404391      class_inheritable_accessor :use_transactional_fixtures 
    405392      class_inheritable_accessor :use_instantiated_fixtures   # true, false, or :no_instances 
    406393      class_inheritable_accessor :pre_loaded_fixtures 
     394      class_inheritable_accessor :fixture_class_mapping 
    407395 
    408396      self.fixture_table_names = [] 
     397      self.fixture_class_mapping = {} 
    409398      self.use_transactional_fixtures = false 
    410399      self.use_instantiated_fixtures = true 
    411400      self.pre_loaded_fixtures = false 
     
    414403 
    415404      def self.fixtures(*table_names) 
    416405        table_names = table_names.flatten 
    417         self.fixture_table_names |= table_names 
     406        table_names.each do |table| 
     407          next unless table.respond_to?(:table_name) 
     408          fixture_class_mapping[table.table_name.to_sym] = table 
     409        end 
     410        self.fixture_table_names |= table_names.collect { |t| t.respond_to?(:table_name) ? t.table_name.to_sym : t } 
    418411        require_fixture_classes(table_names) 
    419         setup_fixture_accessors(table_names) 
     412        setup_fixture_accessors 
    420413      end 
    421414 
    422415      def self.require_fixture_classes(table_names=nil) 
    423416        (table_names || fixture_table_names).each do |table_name|  
     417          next if table_name.respond_to?(:table_name) # skip if it's an AR model instead of a table name string 
    424418          begin 
    425419            require Inflector.singularize(table_name.to_s) 
    426420          rescue LoadError 
     
    519513      private 
    520514        def load_fixtures 
    521515          @loaded_fixtures = {} 
    522           fixtures = Fixtures.create_fixtures(fixture_path, fixture_table_names
     516          fixtures = Fixtures.create_fixtures(fixture_path, fixture_table_names, fixture_class_mapping
    523517          unless fixtures.nil? 
    524518            if fixtures.instance_of?(Fixtures) 
    525519              @loaded_fixtures[fixtures.table_name] = fixtures 
  • activerecord/lib/active_record/base.rb

    old new  
    566566        "type" 
    567567      end 
    568568 
    569       # Defines the sequence_name (for Oracle) -- can be overridden in subclasses. 
     569      # Defines the sequence_name (for Oracle and PostgreSQL) -- can be overridden in subclasses. 
    570570      def sequence_name 
    571         "#{table_name}_seq" 
     571        connection.respond_to?(:default_sequence_format) ?  
     572          connection.default_sequence_format(table_name, primary_key) : 
     573          nil 
    572574      end 
    573575 
    574576      # Sets the table name to use to the given value, or (if the value 
     
    616618 
    617619      # Sets the name of the sequence to use when generating ids to the given 
    618620      # value, or (if the value is nil or false) to the value returned by the 
    619       # given block. Currently useful only when using Oracle, which requires 
    620       # explicit sequences. 
     621      # given block. Currently useful only when using Oracle and PostgreSQL,  
     622      # which require explicit sequences. 
    621623      # 
    622624      # Setting the sequence name when using other dbs will have no effect. 
    623       # If a sequence name is not explicitly set when using Oracle, it will 
    624       # default to the commonly used pattern of: #{table_name}_seq 
     625      # If a sequence name is not explicitly set, it will default to the  
     626      # commonly used pattern of: #{table_name}_seq for Oracle and #{table_name}_#{pk}_seq 
     627      # for PostgreSQL. 
    625628      # 
    626629      # Example: 
    627630      #