aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
Commit message (Collapse)AuthorAgeFilesLines
* Merge the redundant `when Symbol` case to the `when String, ...`Ryuta Kamizono2019-01-041-2/+1
|
* 2x faster `connection.type_cast`Ryuta Kamizono2019-01-041-6/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `nil`, `Numeric`, and `String` are most basic objects which are passed to `type_cast`. But now each `when *types_which_need_no_typecasting` evaluation allocates extra two arrays, it makes `type_cast` slower. The `types_which_need_no_typecasting` was introduced at #15351, but the method isn't useful (never used any adapters) since all adapters (sqlite3, mysql2, postgresql, oracle-enhanced, sqlserver) still overrides the `_type_cast`. Just expanding the method would make the `type_cast` 2x faster. ```ruby module ActiveRecord module TypeCastFast def type_cast_fast(value, column = nil) value = id_value_for_database(value) if value.is_a?(Base) if column value = type_cast_from_column(column, value) end _type_cast_fast(value) rescue TypeError to_type = column ? " to #{column.type}" : "" raise TypeError, "can't cast #{value.class}#{to_type}" end private def _type_cast_fast(value) case value when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data value.to_s when true then unquoted_true when false then unquoted_false # BigDecimals need to be put in a non-normalized form and quoted. when BigDecimal then value.to_s("F") when nil, Numeric, String then value when Type::Time::Value then quoted_time(value) when Date, Time then quoted_date(value) else raise TypeError end end end end conn = ActiveRecord::Base.connection conn.extend ActiveRecord::TypeCastFast Benchmark.ips do |x| x.report("type_cast") { conn.type_cast("foo") } x.report("type_cast_fast") { conn.type_cast_fast("foo") } x.compare! end ``` ``` Warming up -------------------------------------- type_cast 58.733k i/100ms type_cast_fast 101.364k i/100ms Calculating ------------------------------------- type_cast 708.066k (± 5.9%) i/s - 3.583M in 5.080866s type_cast_fast 1.424M (± 2.3%) i/s - 7.197M in 5.055860s Comparison: type_cast_fast: 1424240.0 i/s type_cast: 708066.0 i/s - 2.01x slower ```
* Add `Style/RedundantFreeze` to remove redudant `.freeze`Yasuo Honda2018-09-291-3/+3
| | | | | | | | | | | | | | | | | | | | | Since Rails 6.0 will support Ruby 2.4.1 or higher `# frozen_string_literal: true` magic comment is enough to make string object frozen. This magic comment is enabled by `Style/FrozenStringLiteralComment` cop. * Exclude these files not to auto correct false positive `Regexp#freeze` - 'actionpack/lib/action_dispatch/journey/router/utils.rb' - 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb' It has been fixed by https://github.com/rubocop-hq/rubocop/pull/6333 Once the newer version of RuboCop released and available at Code Climate these exclude entries should be removed. * Replace `String#freeze` with `String#-@` manually if explicit frozen string objects are required - 'actionpack/test/controller/test_case_test.rb' - 'activemodel/test/cases/type/string_test.rb' - 'activesupport/lib/active_support/core_ext/string/strip.rb' - 'activesupport/test/core_ext/string_ext_test.rb' - 'railties/test/generators/actions_test.rb'
* Implement change() to convert to "2001-01-01" firstSean Prashad2018-07-171-0/+1
| | | | (cherry picked from commit da34d4766c33a042aeb92778a492fa810ec23001)
* Ensure that leading date is stripped by quoted_timeAndrew White2018-03-111-1/+1
| | | | | | | | In #24542, quoted_time was introduced to strip the leading date component for time columns because it was having a significant effect in mariadb. However, it assumed that the date component was always 2000-01-01 which isn't the case, especially if the source wasn't another time column.
* Remove deprecated support to `quoted_id` when typecasting an Active Record ↵Rafael Mendonça França2017-10-231-17/+0
| | | | object
* Update links to use https instead of http [ci skip]Yoshiyuki Hirano2017-08-221-1/+1
|
* Refactor Active Record to let Arel manage bind paramsSean Griffin2017-07-241-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A common source of bugs and code bloat within Active Record has been the need for us to maintain the list of bind values separately from the AST they're associated with. This makes any sort of AST manipulation incredibly difficult, as any time we want to potentially insert or remove an AST node, we need to traverse the entire tree to find where the associated bind parameters are. With this change, the bind parameters now live on the AST directly. Active Record does not need to know or care about them until the final AST traversal for SQL construction. Rather than returning just the SQL, the Arel collector will now return both the SQL and the bind parameters. At this point the connection adapter will have all the values that it had before. A bit of this code is janky and something I'd like to refactor later. In particular, I don't like how we're handling associations in the predicate builder, the special casing of `StatementCache::Substitute` in `QueryAttribute`, or generally how we're handling bind value replacement in the statement cache when prepared statements are disabled. This also mostly reverts #26378, as it moved all the code into a location that I wanted to delete. /cc @metaskills @yahonda, this change will affect the adapters Fixes #29766. Fixes #29804. Fixes #26541. Close #28539. Close #24769. Close #26468. Close #26202. There are probably other issues/PRs that can be closed because of this commit, but that's all I could find on the first few pages.
* Use frozen-string-literal in ActiveRecordKir Shatrov2017-07-191-0/+2
|
* Change sqlite3 boolean serialization to use 1 and 0Lisa Ugray2017-07-111-4/+4
| | | | | | | | | | | | | | | | | | | | Abstract boolean serialization has been using 't' and 'f', with MySQL overriding that to use 1 and 0. This has the advantage that SQLite natively recognizes 1 and 0 as true and false, but does not natively recognize 't' and 'f'. This change in serialization requires a migration of stored boolean data for SQLite databases, so it's implemented behind a configuration flag whose default false value is deprecated. The flag itself can be deprecated in a future version of Rails. While loaded models will give the correct result for boolean columns without migrating old data, where() clauses will interact incorrectly with old data. While working in this area, also change the abstract adapter to use `"TRUE"` and `"FALSE"` as quoted values and `true` and `false` for unquoted. These are supported by PostreSQL, and MySQL remains overriden.
* Revert "Merge pull request #29540 from kirs/rubocop-frozen-string"Matthew Draper2017-07-021-1/+0
| | | | | This reverts commit 3420a14590c0e6915d8b6c242887f74adb4120f9, reversing changes made to afb66a5a598ce4ac74ad84b125a5abf046dcf5aa.
* Enforce frozen string in RubocopKir Shatrov2017-07-011-0/+1
|
* Clarify deprecation message for #quoted_idMatthew Draper2017-05-051-1/+8
| | | | | In this case, it's the method definition that's more at fault, rather than the current caller.
* Make internal methods to privateRyuta Kamizono2017-03-271-11/+4
|
* Fix `LogSubscriber` to allow legacy `binds`Ryuta Kamizono2017-03-231-8/+7
| | | | Follow up of #27939.
* Merge pull request #27939 from kamipo/fix_select_all_with_legacy_bindsRafael França2017-03-201-1/+5
|\ | | | | Fix `select_all` with legacy `binds`
| * Fix `select_all` with legacy `binds`Ryuta Kamizono2017-02-121-1/+5
| | | | | | | | Fixes #27923.
* | Deprecate using `#quoted_id` in quotingRyuta Kamizono2017-02-241-0/+2
| | | | | | | | | | Originally `quoted_id` was used in legacy quoting mechanism. Now we use type casting mechanism for that. Let's deprecate `quoted_id`.
* | Fix type casting AR object to respect the primary key cast type's serializationRyuta Kamizono2017-02-241-2/+13
| |
* | Merge pull request #26630 from kamipo/quoted_binaryRafael França2017-02-131-1/+6
|\ \ | |/ |/| Extract `quoted_binary` and use it rather than override `_quote`
| * Extract `quoted_binary` and use it rather than override `_quote`Ryuta Kamizono2016-09-271-1/+6
| | | | | | | | | | | | | | Each databases have different binary representation. Therefore all adapters overrides `_quote` for quoting binary. Extract `quoted_binary` for quoting binary and use it rather than override `_quote`.
* | Missing require "active_support/multibyte/chars"Akira Matsuda2017-01-271-0/+1
| | | | | | | | this probably fixes #25840
* | Remove deprecated support to passing a column to #quoteRafael Mendonça França2016-12-291-11/+1
|/
* normalizes indentation and whitespace across the projectXavier Noria2016-08-061-38/+38
|
* applies new string literal convention in activerecord/libXavier Noria2016-08-061-6/+6
| | | | | The current code base is not uniform. After some discussion, we have chosen to go with double quotes by default.
* Remove `prepare_binds_for_database` internal methodRyuta Kamizono2016-07-281-4/+0
| | | | To avoid relying on the connection adapter for type casting binds.
* Merge pull request #25408 from kamipo/should_not_reuse_quoted_trueYves Senn2016-07-271-4/+4
|\ | | | | Quoting booleans should return a frozen string
| * Quoting booleans should return a frozen stringRyuta Kamizono2016-07-271-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If reuse `QUOTED_TRUE` and `QUOTED_FALSE` without frozen, causing the following issue. ``` Loading development environment (Rails 5.1.0.alpha) irb(main):001:0> ActiveRecord::Base.connection.quote(true) << ' foo' => "1 foo" irb(main):002:0> ActiveRecord::Base.connection.quote(true) << ' foo' => "1 foo foo" irb(main):003:0> type = ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::MysqlString.new => #<ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::MysqlString:0x007fd40c15e018 @precision=nil, @scale=nil, @limit=nil> irb(main):004:0> type.serialize(true) << ' bar' => "1 foo foo bar" irb(main):005:0> type.cast(true) << ' bar' => "1 foo foo bar bar" ```
* | Extract `type_casted_binds` methodRyuta Kamizono2016-07-261-0/+4
|/ | | | | Because `type_cast` against `binds` always requires `attr.value_for_database` and this pattern appears frequently.
* Add `quoted_time` for truncating the date part of a time column valueRyuta Kamizono2016-04-141-0/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Context #24522. TIME column on MariaDB doesn't ignore the date part of the string when it coerces to time. ``` root@localhost [test] > CREATE TABLE `foos` (`id` int AUTO_INCREMENT PRIMARY KEY, `start` time(0), `finish` time(4)) ENGINE=InnoDB; Query OK, 0 rows affected (0.02 sec) root@localhost [test] > INSERT INTO `foos` (`start`, `finish`) VALUES ('2000-01-01 12:30:00', '2000-01-01 12:30:00.999900'); Query OK, 1 row affected, 2 warnings (0.00 sec) Note (Code 1265): Data truncated for column 'start' at row 1 Note (Code 1265): Data truncated for column 'finish' at row 1 root@localhost [test] > SELECT `foos`.* FROM `foos`; +----+----------+---------------+ | id | start | finish | +----+----------+---------------+ | 1 | 12:30:00 | 12:30:00.9999 | +----+----------+---------------+ 1 row in set (0.00 sec) root@localhost [test] > SELECT `foos`.* FROM `foos` WHERE `foos`.`start` = '2000-01-01 12:30:00' LIMIT 1; Empty set (0.00 sec) root@localhost [test] > SELECT `foos`.* FROM `foos` WHERE `foos`.`start` = '12:30:00' LIMIT 1; +----+----------+---------------+ | id | start | finish | +----+----------+---------------+ | 1 | 12:30:00 | 12:30:00.9999 | +----+----------+---------------+ 1 row in set (0.00 sec) ```
* Move `@quoted_{column|table}_names` cache up to the abstract adapterRyuta Kamizono2016-03-311-1/+1
|
* Add expression support on the schema defaultRyuta Kamizono2016-01-131-3/+7
| | | | | | | | Example: create_table :posts do |t| t.datetime :published_at, default: -> { 'NOW()' } end
* mysql2 adapter instead of mysql [ci skip]Rajarshi Das2015-12-201-1/+1
|
* applies new doc guidelines to Active Record.Yves Senn2015-10-141-4/+4
| | | | | | | | | | | | | | | | | | | The focus of this change is to make the API more accessible. References to method and classes should be linked to make it easy to navigate around. This patch makes exzessiv use of `rdoc-ref:` to provide more readable docs. This makes it possible to document `ActiveRecord::Base#save` even though the method is within a separate module `ActiveRecord::Persistence`. The goal here is to bring the API closer to the actual code that you would write. This commit only deals with Active Record. The other gems will be updated accordingly but in different commits. The pass through Active Record is not completely finished yet. A follow up commit will change the spots I haven't yet had the time to update. /cc @fxn
* Move comment about microseconds [ci skip]Ryuta Kamizono2015-05-031-0/+2
| | | | The microseconds handling was already moved to `Quoting#quoted_date`.
* Freeze static arguments for gsubbrainopia2015-04-021-1/+1
|
* Prefer string patterns for gsubbrainopia2015-04-021-1/+1
| | | | | | | | | | | | | | | | | https://github.com/ruby/ruby/pull/579 - there is a new optimization since ruby 2.2 Previously regexp patterns were faster (since a string was converted to regexp underneath anyway). But now string patterns are faster and better reflect the purpose. Benchmark.ips do |bm| bm.report('regexp') { 'this is ::a random string'.gsub(/::/, '/') } bm.report('string') { 'this is ::a random string'.gsub('::', '/') } bm.compare! end # string: 753724.4 i/s # regexp: 501443.1 i/s - 1.50x slower
* `type_cast_for_database` -> `serialize`Sean Griffin2015-02-171-2/+2
|
* Register adapter specific types with the global type registrySean Griffin2015-02-151-21/+0
| | | | | | We do this in the adapter classes specifically, so the types aren't registered if we don't use that adapter. Constants under the PostgreSQL namespace for example are never loaded if we're using mysql.
* Refactor `quote_default_expression`Ryuta Kamizono2015-02-111-0/+5
| | | | | | | `quote_default_expression` and `quote_default_value` are almost the same handling for do not quote default function of `:uuid` columns. Rename `quote_default_value` to `quote_default_expression`, and remove duplicate code.
* Refactor microsecond precision to be database agnosticSean Griffin2015-02-101-1/+6
| | | | | | | | | | The various databases don't actually need significantly different handling for this behavior, and they can achieve it without knowing about the type of the object. The old implementation was returning a string, which will cause problems such as breaking TZ aware attributes, and making it impossible for the adapters to supply their logic for time objects.
* Allow a symbol to be passed to `attribute`, in place of a type objectSean Griffin2015-02-061-0/+21
| | | | | | | | | | | | | | | | | | The same is not true of `define_attribute`, which is meant to be the low level no-magic API that sits underneath. The differences between the two APIs are: - `attribute` - Lazy (the attribute will be defined after the schema has loaded) - Allows either a type object or a symbol - `define_attribute` - Runs immediately (might get trampled by schema loading) - Requires a type object This was the last blocker in terms of public interface requirements originally discussed for this feature back in May. All the implementation blockers have been cleared, so this feature is probably ready for release (pending one more look-over by me).
* rm `Column#cast_type`Sean Griffin2015-02-031-0/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The type from the column is never used, except when being passed to the attributes API. While leaving the type on the column wasn't necessarily a bad thing, I worry that it's existence there implies that it is something which should be used. During the design and implementation process of the attributes API, there have been plenty of cases where getting the "right" type object was hard, but I had easy access to the column objects. For any contributor who isn't intimately familiar with the intents behind the type casting system, grabbing the type from the column might easily seem like the "correct" thing to do. As such, the goal of this change is to express that the column is not something that should be used for type casting. The only places that are "valid" (at the time of this commit) uses of acquiring a type object from the column are fixtures (as the YAML file is going to mirror the database more closely than the AR object), and looking up the type during schema detection to pass to the attributes API Many of the failing tests were removed, as they've been made obsolete over the last year. All of the PG column tests were testing nothing beyond polymorphism. The Mysql2 tests were duplicating the mysql tests, since they now share a column class. The implementation is a little hairy, and slightly verbose, but it felt preferable to going back to 20 constructor options for the columns. If you are git blaming to figure out wtf I was thinking with them, and have a better idea, go for it. Just don't use a type object for this.
* Remove most uses of `Column#cast_type`Sean Griffin2015-01-301-2/+25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The goal is to remove the type object from the column, and remove columns from the type casting process entirely. The primary motivation for this is clarity. The connection adapter does not have sufficient type information, since the type we want to work with might have been overriden at the class level. By taking this object from the column, it is easy to mistakenly think that the column object which exists on the connection adapter is sufficient. It isn't. A concrete example of this is `serialize`. In 4.2 and earlier, `where` worked in a very inconsistent and confusing manner. If you passed a single value to `where`, it would serialize it before querying, and do the right thing. However, passing it as part of an array, hash, or range would cause it to not work. This is because it would stop using prepared statements, so the type casting would come from arel. Arel would have no choice but to get the column from the connection adapter, which would treat it as any other string column, and query for the wrong value. There are a handful of cases where using the column object to find the cast type is appropriate. These are cases where there is not actually a class involved, such as the migration DSL, or fixtures. For all other cases, the API should be designed as such that the type is provided before we get to the connection adapter. (For an example of this, see the work done to decorate the arel table object with a type caster, or the introduction of `QueryAttribute` to `Relation`). There are times that it is appropriate to use information from the column to change behavior in the connection adapter. These cases are when the primitive used to represent that type before it goes to the database does not sufficiently express what needs to happen. An example of this that affects every adapter is binary vs varchar, where the primitive used for both is a string. In this case it is appropriate to look at the column object to determine which quoting method to use, as this is something schema dependent. An example of something which would not be appropriate is to look at the type and see that it is a datetime, and performing string parsing when given a string instead of a date. This is the type of logic that should live entirely on the type. The value which comes out of the type should be a sufficiently generic primitive that the adapter can be expected to know how to work with it. The one place that is still using the column for type information which should not be necessary is the connection adapter type caster which is sometimes given to the arel table when we can't find the associated table. This will hopefully go away in the near future.
* Remove Relation#bind_paramsSean Griffin2015-01-271-7/+1
| | | | | | | | `bound_attributes` is now used universally across the board, removing the need for the conversion layer. These changes are mostly mechanical, with the exception of the log subscriber. Additional, we had to implement `hash` on the attribute objects, so they could be used as a key for query caching.
* Don't default to YAML dumping when quoting valuesSean Griffin2015-01-141-2/+1
| | | | | | | This behavior exists only to support fixtures, so we should handle it there. Leaving it in `#quote` can cause very subtle bugs to slip through, by things appearing to work when they should be blowing up loudly, such as #18385.
* Deprecate passing a column to `quote`Sean Griffin2015-01-101-0/+6
| | | | | It's only used to grab the type for type casting purposes, and we would like to remove the type from the columns entirely.
* Stop passing a column to `quote` when prepared statements are turned offSean Griffin2015-01-101-3/+3
| | | | | | | I'm planning on deprecating the column argument to mirror the deprecation in [arel]. [arel]: https://github.com/rails/arel/commit/6160bfbda1d1781c3b08a33ec4955f170e95be11
* Stop passing a column to `quote` in `insert_fixture`Sean Griffin2015-01-101-0/+10
| | | | | | | I'm planning on deprecating the column argument to mirror the deprecation in [arel]. [arel]: https://github.com/rails/arel/commit/6160bfbda1d1781c3b08a33ec4955f170e95be11
* 💣 I forgot to commit the arity changeSean Griffin2015-01-011-1/+1
|