Changeset 8922
- Timestamp:
- 02/22/08 03:26:21 (9 months ago)
- Files:
-
- trunk/activerecord/CHANGELOG (modified) (1 diff)
- trunk/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb (modified) (11 diffs)
- trunk/activerecord/test/cases/defaults_test.rb (modified) (1 diff)
- trunk/activerecord/test/cases/schema_authorization_test_postgresql.rb (modified) (2 diffs)
- trunk/activerecord/test/schema/postgresql.sql (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/activerecord/CHANGELOG
r8894 r8922 1 1 *SVN* 2 3 * PostgreSQL: support server versions 7.4 through 8.0 and the ruby-pg driver. #11127 [jdavis] 2 4 3 5 * 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 1 1 require 'active_record/connection_adapters/abstract_adapter' 2 3 begin 4 require_library_or_gem 'pg' 5 rescue 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 17 end 2 18 3 19 module ActiveRecord … … 5 21 # Establishes a connection to the database that's used by all Active Record objects 6 22 def self.postgresql_connection(config) # :nodoc: 7 require_library_or_gem 'postgres' unless self.class.const_defined?(:PGconn)8 9 23 config = config.symbolize_keys 10 24 host = config[:host] … … 301 315 # than error and "SHOW standard_conforming_strings" fails, but returns an empty 302 316 # PGresult instead. 303 has_support = execute('SHOW standard_conforming_strings')[0][0] rescue false317 has_support = query('SHOW standard_conforming_strings')[0][0] rescue false 304 318 self.client_min_messages = client_min_messages_old 305 319 has_support … … 370 384 # REFERENTIAL INTEGRITY ==================================== 371 385 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 372 393 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 374 397 yield 375 398 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 377 402 end 378 403 … … 391 416 end 392 417 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 394 432 def query(sql, name = nil) #:nodoc: 395 433 log(sql, name) do 396 434 if @async 397 @connection.async_query(sql)435 res = @connection.async_exec(sql) 398 436 else 399 @connection.query(sql) 400 end 437 res = @connection.exec(sql) 438 end 439 return result_as_array(res) 401 440 end 402 441 end … … 416 455 # Executes an UPDATE query and returns the number of affected tuples. 417 456 def update_sql(sql, name = nil) 418 super.cmd tuples457 super.cmd_tuples 419 458 end 420 459 … … 567 606 # the 8.1+ nextval('foo'::regclass). 568 607 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 570 615 FROM pg_class t 571 616 JOIN pg_attribute attr ON (t.oid = attrelid) … … 577 622 end_sql 578 623 end 624 579 625 # [primary_key, sequence] 580 626 [result.first, result.last] … … 609 655 rescue ActiveRecord::StatementInvalid 610 656 # 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 618 668 end 619 669 … … 786 836 def select_raw(sql, name = nil) 787 837 res = execute(sql, name) 788 results = res .result838 results = result_as_array(res) 789 839 fields = [] 790 840 rows = [] 791 if res ults.length> 0841 if res.ntuples > 0 792 842 fields = res.fields 793 843 results.each do |row| … … 798 848 # PostgreSQLColumn.string_to_decimal but would break form input 799 849 # fields that call value_before_type_cast. 800 if res. type(cell_index) == MONEY_COLUMN_TYPE_OID850 if res.ftype(cell_index) == MONEY_COLUMN_TYPE_OID 801 851 # Because money output is formatted according to the locale, there are two 802 852 # cases to consider (note the decimal separators): trunk/activerecord/test/cases/defaults_test.rb
r8681 r8922 62 62 if current_adapter?(:PostgreSQLAdapter) 63 63 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) 65 67 end 66 68 end trunk/activerecord/test/cases/schema_authorization_test_postgresql.rb
r8681 r8922 19 19 set_session_auth 20 20 USERS.each do |u| 21 @connection.execute "CREATE ROLE#{u}"21 @connection.execute "CREATE USER #{u}" 22 22 @connection.execute "CREATE SCHEMA AUTHORIZATION #{u}" 23 23 set_session_auth u … … 33 33 USERS.each do |u| 34 34 @connection.execute "DROP SCHEMA #{u} CASCADE" 35 @connection.execute "DROP ROLE#{u}"35 @connection.execute "DROP USER #{u}" 36 36 end 37 37 end trunk/activerecord/test/schema/postgresql.sql
r8659 r8922 111 111 negative_integer integer default -1, 112 112 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 114 116 ); 115 117