aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters
Commit message (Collapse)AuthorAgeFilesLines
* Remove public `prevent_writes` writerRyuta Kamizono2019-01-151-5/+5
| | | | | | The `@prevent_writes` should be updated only in the `while_preventing_writes`, it is not necessary to expose the attr writer.
* Deprecate `connection.visitor = ...` which is not released internal usageRyuta Kamizono2019-01-151-2/+6
| | | | | | | | | This attr writer was introduced at 7db90aa, but the usage is already removed at bd2f5c0 before v3.2.0.rc1 is released. If we'd like to customize the visitor in the connection, `arel_visitor` which is implemented in all adapters (mysql2, postgresql, sqlite3, oracle-enhanced, sqlserver) could be used for the purpose #23515.
* Remove `id_value` argument which is no longer passed to `sql_for_insert`Ryuta Kamizono2019-01-112-3/+3
| | | | Since #26002, `id_value` is no longer passed to `sql_for_insert`.
* Refactor `build_relation` in the uniqueness validator to avoid low level ↵Ryuta Kamizono2019-01-112-7/+16
| | | | predicate construction
* Enable `Lint/UselessAssignment` cop to avoid unused variable warnings (#34904)Ryuta Kamizono2019-01-091-2/+2
| | | | | | | | | | | | | | * Enable `Lint/UselessAssignment` cop to avoid unused variable warnings Since we've addressed the warning "assigned but unused variable" frequently. 370537de05092aeea552146b42042833212a1acc 3040446cece8e7a6d9e29219e636e13f180a1e03 5ed618e192e9788094bd92c51255dda1c4fd0eae 76ebafe594fc23abc3764acc7a3758ca473799e5 And also, I've found the unused args in c1b14ad which raises no warnings by the cop, it shows the value of the cop.
* :recycle: Fix mysql type map for enum and setbannzai2019-01-081-2/+2
|
* 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 ```
* Merge pull request #33985 from eugeneius/attribute_methods_schema_cacheKasper Timm Hansen2019-01-031-0/+5
|\ | | | | Only define attribute methods from schema cache
| * Only define attribute methods from schema cacheEugene Kenny2018-09-281-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | To define the attribute methods for a model, Active Record needs to know the schema of the underlying table, which is usually achieved by making a request to the database. This is undesirable behaviour while the app is booting, for two reasons: it makes the boot process dependent on the availability of the database, and it means every new process will make one query for each table, which can cause issues for large applications. However, if the application is using the schema cache dump feature, then the schema cache already contains the necessary information, and we can define the attribute methods without causing any extra database queries.
* | MariaDB: Remove version checking lower the 5.5.8Ryuta Kamizono2019-01-021-10/+2
| | | | | | | | Since we already bumped the minimum version of MySQL to 5.5.8 at #33853.
* | Add test case for `preventing_writes?`Ryuta Kamizono2019-01-021-1/+1
| | | | | | | | Since the `preventing_writes?` is public API.
* | Use high level API on `migration_context` instead of using low level API ↵Ryuta Kamizono2018-12-281-4/+2
| | | | | | | | | | | | | | | | directly Since `migration_context` has `migrations_paths` itself and provides methods which returning values from parsed migration files, so there is no reason to use the `parse_migration_filename` low level API directly.
* | Deprecate passing `migrations_paths` to ↵Ryuta Kamizono2018-12-281-2/+8
| | | | | | | | | | | | | | `connection.assume_migrated_upto_version` Since #31727, `migrations_paths` in `assume_migrated_upto_version` is no longer used.
* | Merge pull request #34742 from kamipo/row_format_dynamic_by_defaultRyuta Kamizono2018-12-211-0/+18
|\ \ | | | | | | MySQL: `ROW_FORMAT=DYNAMIC` create table option by default
| * | MySQL: `ROW_FORMAT=DYNAMIC` create table option by defaultRyuta Kamizono2018-12-191-0/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Since MySQL 5.7.9, the `innodb_default_row_format` option defines the default row format for InnoDB tables. The default setting is `DYNAMIC`. The row format is required for indexing on `varchar(255)` with `utf8mb4` columns. As long as using MySQL 5.6, CI won't be passed even if MySQL server setting is properly configured the same as MySQL 5.7 (`innodb_file_per_table = 1`, `innodb_file_format = 'Barracuda'`, and `innodb_large_prefix = 1`) since InnoDB table is created as the row format `COMPACT` by default on MySQL 5.6, therefore indexing on string with `utf8mb4` columns aren't succeeded. Making `ROW_FORMAT=DYNAMIC` create table option by default for legacy MySQL version would mitigate the indexing issue on the user side, and it makes CI would be passed on MySQL 5.6 which is configured properly.
* | | Enable `Style/RedundantBegin` cop to avoid newly adding redundant begin blockRyuta Kamizono2018-12-212-25/+21
|/ / | | | | | | | | | | | | | | | | | | Currently we sometimes find a redundant begin block in code review (e.g. https://github.com/rails/rails/pull/33604#discussion_r209784205). I'd like to enable `Style/RedundantBegin` cop to avoid that, since rescue/else/ensure are allowed inside do/end blocks in Ruby 2.5 (https://bugs.ruby-lang.org/issues/12906), so we'd probably meets with that situation than before.
* | Use `utf8mb4` charset for internal tables if the row format `DYNAMIC` by defaultRyuta Kamizono2018-12-192-10/+10
| | | | | | | | The indexing issue on `utf8mb4` columns is resolved since MySQL 5.7.9.
* | Ensure that preventing writes is invoked before `materialize_transactions` ↵Ryuta Kamizono2018-12-121-4/+2
| | | | | | | | consistently
* | An empty transaction does not raise the `ReadOnlyError` if preventing writesRyuta Kamizono2018-12-113-3/+3
| | | | | | | | | | | | BEGIN transaction would cause COMMIT or ROLLBACK, so unless COMMIT and ROLLBACK aren't treated as write queries as well as BEGIN, the `ReadOnlyError` would be raised.
* | An explain query does not raise the `ReadOnlyError` if preventing writesRyuta Kamizono2018-12-113-3/+3
| |
* | Don't treat begin and rollback transactions as write queriesRyuta Kamizono2018-12-113-3/+3
| | | | | | | | | | Otherwise `save` method would raise the `ReadOnlyError` against `BEGIN` and `ROLLBACK` queries.
* | Prevent write queries with prepared statements for mysql2 adapterRyuta Kamizono2018-12-111-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Without this change, mysql2 adapter with prepared statements won't pass `base_test.rb`. ``` % ARCONN=mysql2 be ruby -w -Itest test/cases/base_test.rb Using mysql2 Run options: --seed 27614 # Running: ....S..............................F Failure: BasicsTest#test_creating_a_record_raises_if_preventing_writes [test/cases/base_test.rb:1493]: ActiveRecord::ReadOnlyError expected but nothing was raised. rails test test/cases/base_test.rb:1492 ...F Failure: BasicsTest#test_deleting_a_record_raises_if_preventing_writes [test/cases/base_test.rb:1513]: ActiveRecord::ReadOnlyError expected but nothing was raised. rails test test/cases/base_test.rb:1510 ............................................................................................................F Failure: BasicsTest#test_updating_a_record_raises_if_preventing_writes [test/cases/base_test.rb:1503]: ActiveRecord::ReadOnlyError expected but nothing was raised. rails test test/cases/base_test.rb:1500 .......... Finished in 2.534490s, 62.7345 runs/s, 149.5370 assertions/s. 159 runs, 379 assertions, 3 failures, 0 errors, 1 skips ```
* | Prevent write queries for `exec_query`Ryuta Kamizono2018-12-112-1/+9
| | | | | | | | Follow up #34505.
* | Rename error that occurs when writing on a readEileen Uchitelle2018-12-073-3/+3
| | | | | | | | | | | | | | I originally named this `StatementInvalid` because that's what we do in GitHub, but `@tenderlove` pointed out that this means apps can't test for or explitly rescue this error. `StatementInvalid` is pretty broad so I've renamed this to `ReadOnlyError`.
* | Fix join table column quoting with SQLite.Gannon McGibbon2018-12-051-0/+4
| |
* | Merge pull request #34602 from guizmaii/masterRafael França2018-12-031-1/+2
|\ \ | | | | | | Pass the `connection` to the `@instrumenter.instrument` method call
| * | Pass the `connection` to the `@instrumenter.instrument` method calljules Ivanic2018-12-031-1/+2
| | |
* | | Address "warning: shadowing outer local variable - parts"Ryuta Kamizono2018-12-034-7/+8
|/ / | | | | | | And hide the `READ_QUERY` internal constant.
* | Add ability to prevent writes to a databaseEileen Uchitelle2018-11-305-1/+64
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This PR adds the ability to prevent writes to a database even if the database user is able to write (ie the database is a primary and not a replica). This is useful for a few reasons: 1) when converting your database from a single db to a primary/replica setup - you can fix all the writes on reads early on, 2) when we implement automatic database switching or when an app is manually switching connections this feature can be used to ensure reads are reading and writes are writing. We want to make sure we raise if we ever try to write in read mode, regardless of database type and 3) for local development if you don't want to set up multiple databases but do want to support rw/ro queries. This should be used in conjunction with `connected_to` in write mode. For example: ``` ActiveRecord::Base.connected_to(role: :writing) do Dog.connection.while_preventing_writes do Dog.create! # will raise because we're preventing writes end end ActiveRecord::Base.connected_to(role: :reading) do Dog.connection.while_preventing_writes do Dog.first # will not raise because we're not writing end end ```
* | Allow spaces in postgres table namesGannon McGibbon2018-11-281-1/+1
| | | | | | | | | | Fixes issue where "user post" is misinterpreted as "\"user\".\"post\"" when quoting table names with the postgres adapter.
* | Merge pull request #34557 from sergioisidoro/sergio-patch-load-errorRafael França2018-11-281-2/+2
|\ \ | | | | | | Patch load error in case GemSpecError
| * | Patch load error in case GemSpecErrorsergioisidoro2018-11-281-2/+2
| | |
* | | `Mutable` helper is in `ActiveModel`Ryuta Kamizono2018-11-274-4/+4
| | | | | | | | | | | | It should be referenced by full qualified name from Active Record.
* | | Merge pull request #34520 from yahonda/bump_pg93Rafael França2018-11-262-19/+17
|\ \ \ | | | | | | | | Bump the minimum version of PostgreSQL to 9.3
| * | | Bump the minimum version of PostgreSQL to 9.3Yasuo Honda2018-11-252-19/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | https://www.postgresql.org/support/versioning/ - 9.1 EOLed on September 2016. - 9.2 EOLed on September 2017. 9.3 is also not supported since Nov 8, 2018. https://www.postgresql.org/about/news/1905/ I think it may be a little bit early to drop PostgreSQL 9.3 yet. * Deprecated `supports_ranges?` since no other databases support range data type * Add `supports_materialized_views?` to abstract adapter Materialized views itself is supported by other databases, other connection adapters may support them * Remove `with_manual_interventions` It was only necessary for PostgreSQL 9.1 or earlier * Drop CI against PostgreSQL 9.2
* | | | When running exec_query MySQL always returns ActiveRecord::ResultAlireza Bashiri2018-11-251-2/+10
|/ / / | | | | | | | | | | | | When running `exec_query` with `INSERT` (or other write commands), MySQL returns `ActiveRecord::Result`.
* | | Merge pull request #34468 from gmcgibbon/redact_sql_in_errorsRafael França2018-11-234-41/+41
|\ \ \ | | | | | | | | Redact SQL in errors
| * | | Redact SQL in errorsGannon McGibbon2018-11-224-41/+41
| | | | | | | | | | | | | | | | | | | | Move `ActiveRecord::StatementInvalid` SQL to error property. Also add bindings as an error property.
* | | | Use squiggly heredoc to strip odd indentation in the executed SQLRyuta Kamizono2018-11-225-17/+17
|/ / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Before: ``` LOG: execute <unnamed>: SELECT t.oid, t.typname FROM pg_type as t WHERE t.typname IN ('int2', 'int4', 'int8', 'oid', 'float4', 'float8', 'bool') LOG: execute <unnamed>: SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype FROM pg_type as t LEFT JOIN pg_range as r ON oid = rngtypid WHERE t.typname IN ('int2', 'int4', 'int8', 'oid', 'float4', 'float8', 'text', 'varchar', 'char', 'name', 'bpchar', 'bool', 'bit', 'varbit', 'timestamptz', 'date', 'money', 'bytea', 'point', 'hstore', 'json', 'jsonb', 'cidr', 'inet', 'uuid', 'xml', 'tsvector', 'macaddr', 'citext', 'ltree', 'interval', 'path', 'line', 'polygon', 'circle', 'lseg', 'box', 'time', 'timestamp', 'numeric') OR t.typtype IN ('r', 'e', 'd') OR t.typinput::varchar = 'array_in' OR t.typelem != 0 LOG: statement: SHOW TIME ZONE LOG: statement: SELECT 1 LOG: execute <unnamed>: SELECT COUNT(*) FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','v','m') -- (r)elation/table, (v)iew, (m)aterialized view AND c.relname = 'accounts' AND n.nspname = ANY (current_schemas(false)) ``` After: ``` LOG: execute <unnamed>: SELECT t.oid, t.typname FROM pg_type as t WHERE t.typname IN ('int2', 'int4', 'int8', 'oid', 'float4', 'float8', 'bool') LOG: execute <unnamed>: SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype FROM pg_type as t LEFT JOIN pg_range as r ON oid = rngtypid WHERE t.typname IN ('int2', 'int4', 'int8', 'oid', 'float4', 'float8', 'text', 'varchar', 'char', 'name', 'bpchar', 'bool', 'bit', 'varbit', 'timestamptz', 'date', 'money', 'bytea', 'point', 'hstore', 'json', 'jsonb', 'cidr', 'inet', 'uuid', 'xml', 'tsvector', 'macaddr', 'citext', 'ltree', 'interval', 'path', 'line', 'polygon', 'circle', 'lseg', 'box', 'time', 'timestamp', 'numeric') OR t.typtype IN ('r', 'e', 'd') OR t.typinput::varchar = 'array_in' OR t.typelem != 0 LOG: statement: SHOW TIME ZONE LOG: statement: SELECT 1 LOG: execute <unnamed>: SELECT COUNT(*) FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','v','m') -- (r)elation/table, (v)iew, (m)aterialized view AND c.relname = 'accounts' AND n.nspname = ANY (current_schemas(false)) ```
* | | Fixing an issue when parsing an opclass by allowing indexed columnThomas Bianchini2018-11-211-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | in indexdef to be wrapped up by double quotes Fixes #34493. *Thomas Bianchini*
* | | Fix typo and clarify documentationJacob Evelyn2018-11-161-3/+4
| | | | | | | | | | | | | | | | | | This commit fixes a small typo in documentation of the "UNLOGGED" table option for PostgreSQL databases, and clarifies the documentation slightly.
* | | Merge pull request #34436 from gmcgibbon/fix_default_max_bind_length_sqliteRafael França2018-11-131-0/+6
|\ \ \ | | | | | | | | Adjust bind length of SQLite to default (999)
| * | | Adjust bind length of SQLite to default (999)Gannon McGibbon2018-11-131-0/+6
| | | | | | | | | | | | | | | | | | | | Change `#bind_params_length` in SQLite adapter to return the default maximum amount (999). See https://www.sqlite.org/limits.html
* | | | Add support for UNLOGGED Postgresql tablesJacob Evelyn2018-11-134-1/+36
|/ / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit adds support for the `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.create_unlogged_tables` setting, which turns `CREATE TABLE` SQL statements into `CREATE UNLOGGED TABLE` statements. This can improve PostgreSQL performance but at the cost of data durability, and thus it is highly recommended that you *DO NOT* enable this in a production environment.
* | | Deprecate `t.indexes = [...]` which is not by designRyuta Kamizono2018-11-091-2/+5
| | | | | | | | | | | | Use `t.index ...` instead.
* | | Refactor to initialize `TableDefinition` by kwargsRyuta Kamizono2018-11-092-4/+14
| | |
* | | PostgreSQL: Properly quote all `Infinity` and `NaN`Ryuta Kamizono2018-11-091-4/+4
| | | | | | | | | | | | Since quoted `Infinity` and `NaN` are valid data for PostgreSQL.
* | | Add an :if_not_exists option to create_tablefatkodima2018-11-083-4/+10
| | | | | | | | | | | | [fatkodima & Stefan Kanev]
* | | Always add records to parent of nested transactionEugene Kenny2018-11-071-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When a record with transactional callbacks is saved, it's attached to the current transaction so that the callbacks can be run when the transaction is committed. Records can also be added manually with `add_transaction_record`, even if they have no transactional callbacks. When a nested transaction is committed, its records are transferred to the parent transaction, as transactional callbacks should only be run when the outermost transaction is committed (the "real" transaction). However, this currently only happens when the record has transactional callbacks, and not when added manually with `add_transaction_record`. If a record is added to a nested transaction, we should always attach it to the parent transaction when the nested transaction is committed, regardless of whether it has any transactional callbacks. [Eugene Kenny & Ryuta Kamizono]