Skip to content

Commit

Permalink
adjust query counts to be consistent across databases, make sure data…
Browse files Browse the repository at this point in the history
…base log the same things
  • Loading branch information
tenderlove committed Feb 5, 2011
1 parent acccb72 commit 59f7780
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 16 deletions.
Expand Up @@ -85,6 +85,12 @@ def initialize(spec)
@checked_out = [] @checked_out = []
@automatic_reconnect = true @automatic_reconnect = true


@tables = Hash.new do |h, table_name|
with_connection do |conn|
h[table_name] = conn.table_exists?(table_name)
end
end

@columns = Hash.new do |h, table_name| @columns = Hash.new do |h, table_name|
h[table_name] = with_connection do |conn| h[table_name] = with_connection do |conn|


Expand All @@ -107,11 +113,7 @@ def initialize(spec)


@primary_keys = Hash.new do |h, table_name| @primary_keys = Hash.new do |h, table_name|
h[table_name] = with_connection do |conn| h[table_name] = with_connection do |conn|
if conn.table_exists?(table_name) @tables[table_name] ? conn.primary_key(table_name) : 'id'
conn.primary_key(table_name)
else
'id'
end
end end
end end
end end
Expand All @@ -121,10 +123,12 @@ def initialize(spec)
# * columns # * columns
# * columns_hash # * columns_hash
# * primary_keys # * primary_keys
# * tables
def clear_cache! def clear_cache!
@columns.clear @columns.clear
@columns_hash.clear @columns_hash.clear
@primary_keys.clear @primary_keys.clear
@tables.clear
end end


# Clear out internal caches for table with +table_name+ # Clear out internal caches for table with +table_name+
Expand Down
Expand Up @@ -537,7 +537,7 @@ def indexes(table_name, name = nil)#:nodoc:
def columns(table_name, name = nil)#:nodoc: def columns(table_name, name = nil)#:nodoc:
sql = "SHOW FIELDS FROM #{quote_table_name(table_name)}" sql = "SHOW FIELDS FROM #{quote_table_name(table_name)}"
columns = [] columns = []
result = execute(sql, :skip_logging) result = execute(sql)
result.each { |field| columns << MysqlColumn.new(field[0], field[4], field[1], field[2] == "YES") } result.each { |field| columns << MysqlColumn.new(field[0], field[4], field[1], field[2] == "YES") }
result.free result.free
columns columns
Expand Down
Expand Up @@ -786,7 +786,7 @@ def reset_pk_sequence!(table, pk = nil, sequence = nil) #:nodoc:
def pk_and_sequence_for(table) #:nodoc: def pk_and_sequence_for(table) #:nodoc:
# First try looking for a sequence with a dependency on the # First try looking for a sequence with a dependency on the
# given table's primary key. # given table's primary key.
result = query(<<-end_sql, 'PK and serial sequence')[0] result = exec_query(<<-end_sql, 'PK and serial sequence').rows.first
SELECT attr.attname, seq.relname SELECT attr.attname, seq.relname
FROM pg_class seq, FROM pg_class seq,
pg_attribute attr, pg_attribute attr,
Expand Down Expand Up @@ -1071,7 +1071,7 @@ def select_raw(sql, name = nil)
# - format_type includes the column size constraint, e.g. varchar(50) # - format_type includes the column size constraint, e.g. varchar(50)
# - ::regclass is a function that gives the id for a table name # - ::regclass is a function that gives the id for a table name
def column_definitions(table_name) #:nodoc: def column_definitions(table_name) #:nodoc:
query <<-end_sql exec_query(<<-end_sql).rows
SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
FROM pg_attribute a LEFT JOIN pg_attrdef d FROM pg_attribute a LEFT JOIN pg_attrdef d
ON a.attrelid = d.adrelid AND a.attnum = d.adnum ON a.attrelid = d.adrelid AND a.attnum = d.adnum
Expand Down
Expand Up @@ -152,8 +152,11 @@ def exec_query(sql, name = nil, binds = [])


# Don't cache statements without bind values # Don't cache statements without bind values
if binds.empty? if binds.empty?
stmt = @connection.prepare(sql) stmt = @connection.prepare(sql)
cols = stmt.columns cols = stmt.columns
records = stmt.to_a
stmt.close
stmt = records
else else
cache = @statements[sql] ||= { cache = @statements[sql] ||= {
:stmt => @connection.prepare(sql) :stmt => @connection.prepare(sql)
Expand Down Expand Up @@ -233,6 +236,15 @@ def tables(name = nil) #:nodoc:


def columns(table_name, name = nil) #:nodoc: def columns(table_name, name = nil) #:nodoc:
table_structure(table_name).map do |field| table_structure(table_name).map do |field|
case field["dflt_value"]
when /^null$/i
field["dflt_value"] = nil
when /^'(.*)'$/
field["dflt_value"] = $1.gsub(/''/, "'")
when /^"(.*)"$/
field["dflt_value"] = $1.gsub(/""/, '"')
end

SQLiteColumn.new(field['name'], field['dflt_value'], field['type'], field['notnull'].to_i == 0) SQLiteColumn.new(field['name'], field['dflt_value'], field['type'], field['notnull'].to_i == 0)
end end
end end
Expand Down Expand Up @@ -334,7 +346,7 @@ def select(sql, name = nil, binds = []) #:nodoc:
end end


def table_structure(table_name) def table_structure(table_name)
structure = @connection.table_info(quote_table_name(table_name)) structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})").to_hash
raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty? raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
structure structure
end end
Expand Down
4 changes: 4 additions & 0 deletions activerecord/lib/active_record/result.rb
Expand Up @@ -20,6 +20,10 @@ def each
hash_rows.each { |row| yield row } hash_rows.each { |row| yield row }
end end


def to_hash
hash_rows
end

private private
def hash_rows def hash_rows
@hash_rows ||= @rows.map { |row| @hash_rows ||= @rows.map { |row|
Expand Down
Expand Up @@ -757,10 +757,13 @@ def test_caching_of_columns
david = Developer.find(1) david = Developer.find(1)
# clear cache possibly created by other tests # clear cache possibly created by other tests
david.projects.reset_column_information david.projects.reset_column_information
assert_queries(0) { david.projects.columns; david.projects.columns }
# and again to verify that reset_column_information clears the cache correctly # One query for columns, one for primary key
assert_queries(2) { david.projects.columns; david.projects.columns }

## and again to verify that reset_column_information clears the cache correctly
david.projects.reset_column_information david.projects.reset_column_information
assert_queries(0) { david.projects.columns; david.projects.columns } assert_queries(2) { david.projects.columns; david.projects.columns }
end end


def test_attributes_are_being_set_when_initialized_from_habm_association_with_where_clause def test_attributes_are_being_set_when_initialized_from_habm_association_with_where_clause
Expand Down
2 changes: 1 addition & 1 deletion activerecord/test/cases/helper.rb
Expand Up @@ -50,7 +50,7 @@ def with_active_record_default_timezone(zone)
end end


ActiveRecord::Base.connection.class.class_eval do ActiveRecord::Base.connection.class.class_eval do
IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /SHOW FIELDS/] IGNORED_SQL = [/^PRAGMA (?!(table_info))/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/]


# FIXME: this needs to be refactored so specific database can add their own # FIXME: this needs to be refactored so specific database can add their own
# ignored SQL. This ignored SQL is for Oracle. # ignored SQL. This ignored SQL is for Oracle.
Expand Down
5 changes: 4 additions & 1 deletion activerecord/test/cases/migration_test.rb
Expand Up @@ -2022,7 +2022,10 @@ def test_changing_columns
assert ! column(:name).default assert ! column(:name).default
assert_equal :date, column(:birthdate).type assert_equal :date, column(:birthdate).type


assert_queries(1) do # One query for columns (delete_me table)
# One query for primary key (delete_me table)
# One query to do the bulk change
assert_queries(3) do
with_bulk_change_table do |t| with_bulk_change_table do |t|
t.change :name, :string, :default => 'NONAME' t.change :name, :string, :default => 'NONAME'
t.change :birthdate, :datetime t.change :birthdate, :datetime
Expand Down

0 comments on commit 59f7780

Please sign in to comment.