Permalink
Browse files

Do not type cast all the database url values.

We should only type cast when we need to use.

Related to 4b005fb
  • Loading branch information...
rafaelfranca committed Feb 21, 2013
1 parent 5fc3b87 commit e54acf1308e2e4df047bf90798208e03e1370098
@@ -151,8 +151,8 @@
*Justin George*
* The `DATABASE_URL` environment variable now converts ints, floats, and
the strings true and false to Ruby types. For example, SQLite requires
* The database adpters now converts the options passed thought `DATABASE_URL`
environment variable to the proper Ruby types before using. For example, SQLite requires
that the timeout value is an integer, and PostgreSQL requires that the
prepared_statements option is a boolean. These now work as expected:
@@ -161,7 +161,7 @@
DATABASE_URL=sqlite3://localhost/test_db?timeout=500
DATABASE_URL=postgresql://localhost/test_db?prepared_statements=false
*Aaron Stone*
*Aaron Stone + Rafael Mendonça França*
* `Relation#merge` now only overwrites where values on the LHS of the
merge. Consider:
@@ -61,12 +61,30 @@ class AbstractAdapter
include MonitorMixin
include ColumnDumper
SIMPLE_INT = /\A\d+\z/
define_callbacks :checkout, :checkin
attr_accessor :visitor, :pool
attr_reader :schema_cache, :last_use, :in_use, :logger
alias :in_use? :in_use
def self.type_cast_config_to_integer(config)
if config =~ SIMPLE_INT
config.to_i
else
config
end
end
def self.type_cast_config_to_boolean(config)
if config == "false"
false
else
config
end
end
def initialize(connection, logger = nil, pool = nil) #:nodoc:
super()
@@ -31,7 +31,7 @@ def has_default?
return false if blob_or_text_column? #mysql forbids defaults on blob and text columns
super
end
def blob_or_text_column?
sql_type =~ /blob/i || type == :text
end
@@ -140,7 +140,7 @@ def initialize(connection, logger, connection_options, config)
@connection_options, @config = connection_options, config
@quoted_column_names, @quoted_table_names = {}, {}
if config.fetch(:prepared_statements) { true }
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
@visitor = Arel::Visitors::MySQL.new self
else
@visitor = BindSubstitution.new self
@@ -581,7 +581,7 @@ def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
end
def strict_mode?
@config.fetch(:strict, true)
self.class.type_cast_config_to_boolean(@config.fetch(:strict, true))
end
protected
@@ -722,7 +722,7 @@ def configure_connection
# Increase timeout so the server doesn't disconnect us.
wait_timeout = @config[:wait_timeout]
wait_timeout = 2147483 unless wait_timeout.is_a?(Fixnum)
variables[:wait_timeout] = wait_timeout
variables[:wait_timeout] = self.class.type_cast_config_to_integer(wait_timeout)
# Make MySQL reject illegal values rather than truncating or blanking them, see
# http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html#sqlmode_strict_all_tables
@@ -65,10 +65,6 @@ def resolve_hash_connection(spec) # :nodoc:
ConnectionSpecification.new(spec, adapter_method)
end
# For DATABASE_URL, accept a limited concept of ints and floats
SIMPLE_INT = /\A\d+\z/
SIMPLE_FLOAT = /\A\d+\.\d+\z/
def self.connection_url_to_hash(url) # :nodoc:
config = URI.parse url
adapter = config.scheme
@@ -89,28 +85,11 @@ def self.connection_url_to_hash(url) # :nodoc:
if config.query
options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
options.each { |key, value| options[key] = type_cast_value(value) }
spec.merge!(options)
end
spec
end
def self.type_cast_value(value)
case value
when SIMPLE_INT
value.to_i
when SIMPLE_FLOAT
value.to_f
when 'true'
true
when 'false'
false
else
value
end
end
end
end
end
@@ -126,7 +126,7 @@ def cache
def initialize(connection, logger, connection_options, config)
super
@statements = StatementPool.new(@connection,
config.fetch(:statement_limit) { 1000 })
self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }))
@client_encoding = nil
connect
end
@@ -478,7 +478,7 @@ class BindSubstitution < Arel::Visitors::PostgreSQL # :nodoc:
def initialize(connection, logger, connection_parameters, config)
super(connection, logger)
if config.fetch(:prepared_statements) { true }
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
@visitor = Arel::Visitors::PostgreSQL.new self
else
@visitor = BindSubstitution.new self
@@ -492,15 +492,15 @@ def initialize(connection, logger, connection_parameters, config)
connect
@statements = StatementPool.new @connection,
config.fetch(:statement_limit) { 1000 }
self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 })
if postgresql_version < 80200
raise "Your version of PostgreSQL (#{postgresql_version}) is too old, please upgrade!"
end
initialize_type_map
@local_tz = execute('SHOW TIME ZONE', 'SCHEMA').first["TimeZone"]
@use_insert_returning = @config.key?(:insert_returning) ? @config[:insert_returning] : true
@use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
end
# Clears the prepared statements cache.
@@ -26,7 +26,7 @@ def sqlite3_connection(config) # :nodoc:
:results_as_hash => true
)
db.busy_timeout(config[:timeout]) if config[:timeout]
db.busy_timeout(ConnectionAdapters::SQLite3Adapter.type_cast_config_to_integer(config[:timeout])) if config[:timeout]
ConnectionAdapters::SQLite3Adapter.new(db, logger, config)
end
@@ -107,10 +107,10 @@ def initialize(connection, logger, config)
@active = nil
@statements = StatementPool.new(@connection,
config.fetch(:statement_limit) { 1000 })
self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }))
@config = config
if config.fetch(:prepared_statements) { true }
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
@visitor = Arel::Visitors::SQLite.new self
else
@visitor = BindSubstitution.new self
@@ -43,27 +43,6 @@ def test_url_port
encoding: "utf8" }, spec)
end
def test_url_query_numeric
spec = resolve 'abstract://foo:123?encoding=utf8&int=500&float=10.9'
assert_equal({
adapter: "abstract",
port: 123,
int: 500,
float: 10.9,
host: "foo",
encoding: "utf8" }, spec)
end
def test_url_query_boolean
spec = resolve 'abstract://foo:123?true=true&false=false'
assert_equal({
adapter: "abstract",
port: 123,
true: true,
false: false,
host: "foo" }, spec)
end
def test_encoded_password
password = 'am@z1ng_p@ssw0rd#!'
encoded_password = URI.encode_www_form_component(password)

0 comments on commit e54acf1

Please sign in to comment.