Permalink
Browse files

r3339@asus: jeremy | 2005-12-01 17:03:16 -0800

 Apply [3202] to stable.  Firebird: updated for FireRuby 0.4.0.  Closes #3009.


git-svn-id: http://svn-commit.rubyonrails.org/rails/branches/stable@3204 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
jeremy committed Dec 2, 2005
1 parent 14c2334 commit 1c86c6f4d947508421e0d516d669ebd52c70a06a
Showing with 38 additions and 68 deletions.
  1. +3 −1 activerecord/CHANGELOG
  2. +35 −67 activerecord/lib/active_record/connection_adapters/firebird_adapter.rb
View
@@ -1,4 +1,6 @@
-*SVN*
+* SVN*
+
+* Firebird: updated for FireRuby 0.4.0. #3009 [Ken Kunz <kennethkunz@gmail.com>]
* Introducing the Firebird adapter. Quote columns and use attribute_condition more consistently. Setup guide: http://wiki.rubyonrails.com/rails/pages/Firebird+Adapter #1874 [Ken Kunz <kennethkunz@gmail.com>]
@@ -3,10 +3,6 @@
require 'active_record/connection_adapters/abstract_adapter'
module FireRuby # :nodoc: all
- class ResultSet
- include Enumerable
- end
-
class Database
def self.new_from_params(database, host, port, service)
db_string = ""
@@ -25,6 +21,11 @@ module ActiveRecord
class << Base
def firebird_connection(config) # :nodoc:
require_library_or_gem 'fireruby'
+ unless defined? FireRuby::SQLType
+ raise AdapterNotFound,
+ 'The Firebird adapter requires FireRuby version 0.4.0 or greater; you appear ' <<
+ 'to be running an older version -- please update FireRuby (gem install fireruby).'
+ end
config = config.symbolize_keys
unless config.has_key?(:database)
raise ArgumentError, "No database specified. Missing argument: database."
@@ -41,23 +42,30 @@ class FirebirdColumn < Column # :nodoc:
VARCHAR_MAX_LENGTH = 32_765
BLOB_MAX_LENGTH = 32_767
- def initialize(name, domain_name, type, sub_type, length, precision, scale, default_source, null_flag)
- column_type = metadata_to_column_type(type, sub_type)
- sql_type = domain_name =~ /BOOLEAN/ ? 'BOOLEAN' : column_type
- super(name.downcase, nil, sql_type, !null_flag)
- if default_source
- @default = parse_default(default_source)
- @cast_type = firebird_cast_type(column_type, length, precision, scale)
- end
+ def initialize(name, domain, type, sub_type, length, precision, scale, default_source, null_flag)
+ @firebird_type = FireRuby::SQLType.to_base_type(type, sub_type).to_s
+ super(name.downcase, nil, @firebird_type, !null_flag)
+ @default = parse_default(default_source) if default_source
@limit = type == 'BLOB' ? BLOB_MAX_LENGTH : length
+ @domain, @sub_type, @precision, @scale = domain, sub_type, precision, scale
+ end
+
+ def type
+ if @domain =~ /BOOLEAN/
+ :boolean
+ elsif @type == :binary and @sub_type == 1
+ :text
+ else
+ @type
+ end
end
# Submits a _CAST_ query to the database, casting the default value to the specified SQL type.
# This enables Firebird to provide an actual value when context variables are used as column
# defaults (such as CURRENT_TIMESTAMP).
def default
if @default
- sql = "SELECT CAST(#{@default} AS #{@cast_type}) FROM RDB$DATABASE"
+ sql = "SELECT CAST(#{@default} AS #{column_def}) FROM RDB$DATABASE"
connection = ActiveRecord::Base.active_connections.values.detect { |conn| conn && conn.adapter_name == 'Firebird' }
if connection
type_cast connection.execute(sql).to_a.first['CAST']
@@ -68,46 +76,26 @@ def default
end
def type_cast(value)
- if type == :date and value.instance_of?(Time)
- value.to_date
- elsif type == :boolean
+ if type == :boolean
value == true or value == ActiveRecord::ConnectionAdapters::FirebirdAdapter.boolean_domain[:true]
else
super
end
end
private
- # Maps the internal type returned by Firebird metadata tables to a
- # SQL type that can be passed to #firebird_cast_type and Column#new
- def metadata_to_column_type(type, sub_type)
- case type
- when 'TEXT' then 'CHAR'
- when 'VARYING' then 'VARCHAR'
- when 'DOUBLE' then 'DOUBLE PRECISION'
- when 'BLOB' then sub_type == 1 ? 'CLOB' : 'BLOB'
- when 'SHORT', 'LONG', 'INT64'
- case sub_type
- when 1 then 'NUMERIC'
- when 2 then 'DECIMAL'
- else 'BIGINT'
- end
- else type
- end
- end
-
def parse_default(default_source)
default_source =~ /^\s*DEFAULT\s+(.*)\s*$/i
return $1 unless $1.upcase == "NULL"
end
- # Returns a column definition that can be used in a Firebird CAST statement
- def firebird_cast_type(column_type, length, precision, scale)
- case column_type
- when 'BLOB', 'CLOB' then "VARCHAR(#{VARCHAR_MAX_LENGTH})"
- when 'CHAR', 'VARCHAR' then "#{column_type}(#{length})"
- when 'NUMERIC', 'DECIMAL' then "#{column_type}(#{precision},#{scale.abs})"
- else column_type
+ def column_def
+ case @firebird_type
+ when 'BLOB' then "VARCHAR(#{VARCHAR_MAX_LENGTH})"
+ when 'CHAR', 'VARCHAR' then "#{@firebird_type}(#{@limit})"
+ when 'NUMERIC', 'DECIMAL' then "#{@firebird_type}(#{@precision},#{@scale.abs})"
+ when 'DOUBLE' then "DOUBLE PRECISION"
+ else @firebird_type
end
end
@@ -121,7 +109,7 @@ def simplified_type(field_type)
end
# The Firebird adapter relies on the FireRuby[http://rubyforge.org/projects/fireruby/]
- # extension, version 0.3.2 or later (available as a gem or from
+ # extension, version 0.4.0 or later (available as a gem or from
# RubyForge[http://rubyforge.org/projects/fireruby/]). FireRuby works with
# Firebird 1.5.x on Linux, OS X and Win32 platforms.
#
@@ -356,15 +344,13 @@ def next_sequence_value(sequence_name)
def columns(table_name, name = nil) # :nodoc:
sql = <<-END_SQL
- SELECT r.rdb$field_name, r.rdb$field_source, t.rdb$type_name, f.rdb$field_sub_type,
+ SELECT r.rdb$field_name, r.rdb$field_source, f.rdb$field_type, f.rdb$field_sub_type,
f.rdb$field_length, f.rdb$field_precision, f.rdb$field_scale,
COALESCE(r.rdb$default_source, f.rdb$default_source) rdb$default_source,
COALESCE(r.rdb$null_flag, f.rdb$null_flag) rdb$null_flag
FROM rdb$relation_fields r
JOIN rdb$fields f ON r.rdb$field_source = f.rdb$field_name
- JOIN rdb$types t ON f.rdb$field_type = t.rdb$type
- WHERE r.rdb$relation_name = '#{table_name.upcase}'
- AND t.rdb$field_name = 'RDB$FIELD_TYPE'
+ WHERE r.rdb$relation_name = '#{table_name.to_s.upcase}'
ORDER BY r.rdb$field_position
END_SQL
execute(sql, name).collect do |field|
@@ -383,32 +369,14 @@ def columns(table_name, name = nil) # :nodoc:
def select(sql, name = nil)
execute(sql, name).collect do |row|
hashed_row = {}
- # TODO: zip is slow.
- row.aliases.zip(row.values) do |column_alias, value|
- value = case value
- when Time then guess_date_or_time(value)
- when FireRuby::Blob then value.to_s
- else value
- end
- hashed_row[fb_to_ar_case(column_alias)] = value
+ row.each do |column, value|
+ value = value.to_s if FireRuby::Blob === value
+ hashed_row[fb_to_ar_case(column)] = value
end
hashed_row
end
end
- # FireRuby (as of 0.3.2) returns a Time object for TIME, TIMESTAMP and
- # DATE columns. This method guesses whether time is really a date, and
- # returns a string representing the date if it is. This date string gets
- # properly type-cast later (as a Time or Date object) based on the
- # column type.
- def guess_date_or_time(time)
- if (time.hour + time.min + time.sec + time.usec).zero?
- time.strftime("%Y-%m-%d")
- else
- time
- end
- end
-
# Maps uppercase Firebird column names to lowercase for ActiveRecord;
# mixed-case columns retain their original case.
def fb_to_ar_case(column_name)

0 comments on commit 1c86c6f

Please sign in to comment.