aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
authorJeremy Kemper <jeremy@bitsweat.net>2005-10-16 03:45:39 +0000
committerJeremy Kemper <jeremy@bitsweat.net>2005-10-16 03:45:39 +0000
commit7117fdb8ceeb4d8cc18651a74ea52f1bed2b077c (patch)
tree20dff4d44de2dcd1401e8cf008ceca0f077d50d8 /activerecord/lib/active_record
parent22b77daeee65aa80061f247a3b36404bacd7dff5 (diff)
downloadrails-7117fdb8ceeb4d8cc18651a74ea52f1bed2b077c.tar.gz
rails-7117fdb8ceeb4d8cc18651a74ea52f1bed2b077c.tar.bz2
rails-7117fdb8ceeb4d8cc18651a74ea52f1bed2b077c.zip
r3616@asus: jeremy | 2005-09-26 23:09:28 -0700
Ticket 2292 - Sequences, schemas, and fixtures r3917@asus: jeremy | 2005-10-15 10:43:24 -0700 fix pk assert r3918@asus: jeremy | 2005-10-15 10:46:52 -0700 rework query cache connection= override r3919@asus: jeremy | 2005-10-15 10:47:45 -0700 correct fixtures usage r3920@asus: jeremy | 2005-10-15 10:53:23 -0700 correct attr assignment r3921@asus: jeremy | 2005-10-15 12:59:10 -0700 sequences r3922@asus: jeremy | 2005-10-15 16:36:09 -0700 reset fixtures work with sequences r3951@asus: jeremy | 2005-10-15 23:23:12 -0700 cut down excess features r3952@asus: jeremy | 2005-10-15 23:40:30 -0700 don't test for PostgreSQL specifically git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@2639 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'activerecord/lib/active_record')
-rwxr-xr-xactiverecord/lib/active_record/base.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb12
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb9
-rw-r--r--activerecord/lib/active_record/connection_adapters/oci_adapter.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb40
-rwxr-xr-xactiverecord/lib/active_record/fixtures.rb24
-rw-r--r--activerecord/lib/active_record/query_cache.rb17
7 files changed, 78 insertions, 36 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 48d9c6ae12..58f884595c 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -625,9 +625,9 @@ module ActiveRecord #:nodoc:
"type"
end
- # Defines the sequence_name (for Oracle) -- can be overridden in subclasses.
+ # Default sequence_name. Use set_sequence_name to override.
def sequence_name
- "#{table_name}_seq"
+ connection.default_sequence_name(table_name, primary_key)
end
# Sets the table name to use to the given value, or (if the value
@@ -675,8 +675,8 @@ module ActiveRecord #:nodoc:
# Sets the name of the sequence to use when generating ids to the given
# value, or (if the value is nil or false) to the value returned by the
- # given block. Currently useful only when using Oracle, which requires
- # explicit sequences.
+ # given block. This is required for Oracle and is useful for any
+ # database which relies on sequences for primary key generation.
#
# Setting the sequence name when using other dbs will have no effect.
# If a sequence name is not explicitly set when using Oracle, it will
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
index b5ddef32af..eab61085e3 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
@@ -114,9 +114,15 @@ module ActiveRecord
# Set the connection for the class.
def self.connection=(spec)
- raise ConnectionNotEstablished unless spec
- conn = self.send(spec.adapter_method, spec.config)
- active_connections[self] = conn
+ if spec.kind_of?(ActiveRecord::ConnectionAdapters::AbstractAdapter)
+ active_connections[self] = spec
+ elsif spec.kind_of?(ConnectionSpecification)
+ self.connection = self.send(spec.adapter_method, spec.config)
+ elsif spec.nil?
+ raise ConnectionNotEstablished
+ else
+ establish_connection spec
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
index 90dc951b6d..c45454eacc 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
@@ -90,6 +90,15 @@ module ActiveRecord
end
end
end
+
+ def default_sequence_name(table, column)
+ nil
+ end
+
+ # Set the sequence to the max value of the table's column.
+ def reset_sequence!(table, column, sequence = nil)
+ # Do nothing by default. Implement for PostgreSQL, Oracle, ...
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/oci_adapter.rb b/activerecord/lib/active_record/connection_adapters/oci_adapter.rb
index 194e5d0062..9897403797 100644
--- a/activerecord/lib/active_record/connection_adapters/oci_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/oci_adapter.rb
@@ -99,6 +99,10 @@ begin
# * <tt>:password</tt> -- Defaults to nothing
# * <tt>:host</tt> -- Defaults to localhost
class OCIAdapter < AbstractAdapter
+ def default_sequence_name(table, column)
+ "#{table}_seq"
+ end
+
def quote_string(string)
string.gsub(/'/, "''")
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index e7bedaee9e..203d390046 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -102,7 +102,7 @@ module ActiveRecord
def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
execute(sql, name)
table = sql.split(" ", 4)[2]
- id_value || last_insert_id(table, pk)
+ id_value || last_insert_id(table, sequence_name)
end
def query(sql, name = nil) #:nodoc:
@@ -198,6 +198,37 @@ module ActiveRecord
def schema_search_path #:nodoc:
@schema_search_path ||= query('SHOW search_path')[0][0]
end
+
+ def default_sequence_name(table_name, pk = 'id')
+ "#{table_name}_#{pk}_seq"
+ end
+
+ # Set the sequence to the max value of the table's pk.
+ def reset_pk_sequence!(table)
+ sequence, pk = sequence_and_pk_for(table)
+ if sequence and pk
+ select_value <<-end_sql, 'Reset sequence'
+ SELECT setval('#{sequence}', (SELECT COALESCE(MAX(#{pk})+(SELECT increment_by FROM #{sequence}), (SELECT min_value FROM #{sequence})) FROM #{table}), false)
+ end_sql
+ end
+ end
+
+ # Find a table's primary key and sequence.
+ def sequence_and_pk_for(table, column = nil)
+ execute(<<-end_sql, 'Find pk sequence')[0]
+ SELECT (name.nspname || '.' || seq.relname) AS sequence, attr.attname AS pk
+ FROM pg_class seq, pg_attribute attr, pg_depend dep, pg_namespace name, pg_constraint cons
+ WHERE seq.oid = dep.objid
+ AND seq.relnamespace = name.oid
+ AND attr.attrelid = dep.refobjid
+ AND attr.attnum = dep.refobjsubid
+ AND attr.attrelid = cons.conrelid
+ AND attr.attnum = cons.conkey[1]
+ AND cons.contype = 'p'
+ AND dep.refobjid = '#{table}'::regclass
+ end_sql
+ end
+
def rename_table(name, new_name)
execute "ALTER TABLE #{name} RENAME TO #{new_name}"
@@ -242,9 +273,10 @@ module ActiveRecord
private
BYTEA_COLUMN_TYPE_OID = 17
- def last_insert_id(table, column = nil)
- sequence_name = "#{table}_#{column || 'id'}_seq"
- @connection.exec("SELECT currval('#{sequence_name}')")[0][0].to_i
+ def last_insert_id(table, sequence_name)
+ if sequence_name
+ @connection.exec("SELECT currval('#{sequence_name}')")[0][0].to_i
+ end
end
def select(sql, name = nil)
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 6ee963951e..ef4757fcee 100755
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -257,8 +257,13 @@ class Fixtures < YAML::Omap
fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures }
fixtures.each { |fixture| fixture.insert_fixtures }
end
-
- reset_sequences(connection, table_names) if connection.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
+
+ # Cap primary key sequences to max(pk).
+ if connection.respond_to?(:reset_pk_sequence!)
+ table_names.flatten.each do |table_name|
+ connection.reset_pk_sequence!(table_name)
+ end
+ end
return fixtures.size > 1 ? fixtures : fixtures.first
ensure
@@ -266,21 +271,6 @@ class Fixtures < YAML::Omap
end
end
- # Start PostgreSQL fixtures at id 1. Skip tables without models
- # and models with nonstandard primary keys.
- def self.reset_sequences(connection, table_names)
- table_names.flatten.each do |table|
- if table_class = table.to_s.classify.constantize rescue nil
- pk = table_class.columns_hash[table_class.primary_key]
- if pk and pk.type == :integer
- connection.execute(
- "SELECT setval('#{table}_#{pk.name}_seq', (SELECT COALESCE(MAX(#{pk.name}), 0)+1 FROM #{table}), false)",
- 'Setting Sequence'
- )
- end
- end
- end
- end
attr_reader :table_name
diff --git a/activerecord/lib/active_record/query_cache.rb b/activerecord/lib/active_record/query_cache.rb
index 794caff59c..e79b3e05a7 100644
--- a/activerecord/lib/active_record/query_cache.rb
+++ b/activerecord/lib/active_record/query_cache.rb
@@ -44,14 +44,15 @@ module ActiveRecord
class Base
# Set the connection for the class with caching on
- def self.connection=(spec)
- raise ConnectionNotEstablished unless spec
-
- conn = spec.config[:query_cache] ?
- QueryCache.new(self.send(spec.adapter_method, spec.config)) :
- self.send(spec.adapter_method, spec.config)
-
- active_connections[self] = conn
+ class << self
+ alias_method :connection_without_query_cache=, :connection=
+
+ def connection=(spec)
+ if spec.is_a?(ConnectionSpecification) and spec.config[:query_cache]
+ spec = QueryCache.new(self.send(spec.adapter_method, spec.config))
+ end
+ self.connection_without_query_cache = spec
+ end
end
end