aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
Commit message (Collapse)AuthorAgeFilesLines
* Merge branch 'master' into add_database_exist_methodGuillermo Iguaran2019-07-081-0/+1
|\
| * Merge pull request #35891 from Shopify/schema-cache-deduplicationKasper Timm Hansen2019-06-191-0/+1
| |\ | | | | | | Deduplicate various Active Record schema cache structures
| | * Deduplicate various Active Record schema cache structuresJean Boussier2019-06-031-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Real world database schemas contain a lot of duplicated data. Some column names like `id`, `created_at` etc can easily be repeated hundreds of times. Same for SqlTypeMetada, most database will contain only a limited number of possible combinations. This result in a lot of wasted memory. The idea here is to make these data sctructures immutable, use a registry to substitute similar instances with pre-existing ones.
* | | Add database_exists? method to connection adaptersGuilherme Mansur2019-06-171-0/+10
|/ / | | | | | | | | | | | | | | When SQLite connects it will silently create a database if the database does not exist. This behaviour causes different issues because of inconsistent behaviour between adapters: #36383, #32914. This commit adds a `database_exists?` method as a way to check the database without creating it. This is a stepping stone to fully resolving the above issues.
* | Clear schema cache when a table is created/dropped/renamedRyuta Kamizono2019-06-131-0/+2
| | | | | | | | Otherwise `Model.table_exists?` returns the staled cache result.
* | Fix sqlite3 collation parsing when using decimal columns.Martin Schuster2019-06-041-2/+2
|/ | | | | | If an sqlite3 table contains a decimal column behind columns with a collation definition, then parsing the collation of all preceeding columns will fail -- the collation will be missed without notice.
* Put all `explain` methods into `DatabaseStatements` moduleRyuta Kamizono2019-05-221-8/+0
| | | | | Almost all database statements methods except `explain` was moved into `DatabaseStatements` at #35922. This moves the last one method.
* Remove SQLite version support caveats [ci skip]Eugene Kenny2019-05-121-2/+2
| | | | | | | | | Since d1a74c1e012ed96f7179e53b9190b7da0a369e11, Active Record requires SQLite version 3.8.0 or greater, so savepoints and partial indexes are always available. That commit also added a runtime version check, so we can remove the minimum version requirement from the internal adapter documentation.
* moves sqlite3 methods that mirror Abstract::DatabaseStatements into ↵Michael Glass2019-04-101-80/+0
| | | | Sqlite3::DatabaseStatements and make those that are private in Abstract::DatabaseStatements private for sqlite3
* Use `execute_batch2` rather than `execute_batch` to fix performance ↵Ryuta Kamizono2019-04-041-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | regression for fixture loading d8d6bd5 makes fixture loading to bulk statements by using `execute_batch` for sqlite3 adapter. But `execute_batch` is slower and it caused the performance regression for fixture loading. In sqlite3 1.4.0, it have new batch method `execute_batch2`. I've confirmed `execute_batch2` is extremely faster than `execute_batch`. So I think it is worth to upgrade sqlite3 to 1.4.0 to use that method. Before: ``` % ARCONN=sqlite3 bundle exec ruby -w -Itest test/cases/associations/eager_test.rb -n test_eager_loading_too_may_ids Using sqlite3 Run options: -n test_eager_loading_too_may_ids --seed 35790 # Running: . Finished in 202.437406s, 0.0049 runs/s, 0.0049 assertions/s. 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips ARCONN=sqlite3 bundle exec ruby -w -Itest -n test_eager_loading_too_may_ids 142.57s user 60.83s system 98% cpu 3:27.08 total ``` After: ``` % ARCONN=sqlite3 bundle exec ruby -w -Itest test/cases/associations/eager_test.rb -n test_eager_loading_too_may_ids Using sqlite3 Run options: -n test_eager_loading_too_may_ids --seed 16649 # Running: . Finished in 8.471032s, 0.1180 runs/s, 0.1180 assertions/s. 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips ARCONN=sqlite3 bundle exec ruby -w -Itest -n test_eager_loading_too_may_ids 10.71s user 1.36s system 95% cpu 12.672 total ```
* Cache database version in schema cacheAli Ibrahim2019-04-031-12/+12
| | | | | | | | | | | | | | | * The database version will get cached in the schema cache file during the schema cache dump. When the database version check happens, the version will be pulled from the schema cache and thus avoid querying the database for the version. * If the schema cache file doesn't exist, we'll query the database for the version and cache it on the schema cache object. * To facilitate this change, all connection adapters now implement #get_database_version and #database_version. #database_version returns the value from the schema cache. * To take advantage of the cached database version, the database version check will now happen after the schema cache is set on the connection in the connection pool.
* SQLite3: Make fixture loading to bulk statementsRyuta Kamizono2019-03-171-12/+0
|
* Make `truncate_tables` to bulk statementsRyuta Kamizono2019-03-171-4/+2
| | | | | | | | | | | | | | | | | | Before: ``` (16.4ms) TRUNCATE TABLE `author_addresses` (20.5ms) TRUNCATE TABLE `authors` (19.4ms) TRUNCATE TABLE `posts` ``` After: ``` Truncate Tables (19.5ms) TRUNCATE TABLE `author_addresses`; TRUNCATE TABLE `authors`; TRUNCATE TABLE `posts` ```
* Extract `truncate` and `truncate_tables` into database statementsRyuta Kamizono2019-03-171-4/+4
| | | | This is to easier make `truncate_tables` to bulk statements.
* SQLite3: Set `busy_timeout` in `configure_connection`Ryuta Kamizono2019-03-101-2/+2
| | | | It is to work that on `reconnect!` after `disconnect!`
* Fix `reconnect!` to work after `disconnect!`Ryuta Kamizono2019-03-101-4/+14
|
* Ensure `clear_cache!` clears the prepared statements cacheRyuta Kamizono2019-03-061-7/+5
| | | | | | | | | | | Since #23461, all adapters supports prepared statements, so that clears the prepared statements cache is no longer database specific. Actually, I struggled to identify the cause of random CI failure in #23461, that was missing `@statements.clear` in `clear_cache!`. This extracts `clear_cache!` to ensure the common concerns in the abstract adapter.
* Add insert_all to ActiveRecord models (#35077)Bob Lail2019-03-051-0/+20
| | | | | Adds a method to ActiveRecord allowing records to be inserted in bulk without instantiating ActiveRecord models. This method supports options for handling uniqueness violations by skipping duplicate records or overwriting them in an UPSERT operation. ActiveRecord already supports bulk-update and bulk-destroy actions that execute SQL UPDATE and DELETE commands directly. It also supports bulk-read actions through `pluck`. It makes sense for it also to support bulk-creation.
* Allow `truncate` for SQLite3 adapter and add `rails db:seed:replant` (#34779)Bogdan2019-03-041-0/+4
| | | | | | | | | | | | | * Add `ActiveRecord::Base.connection.truncate` for SQLite3 adapter. SQLite doesn't support `TRUNCATE TABLE`, but SQLite3 adapter can support `ActiveRecord::Base.connection.truncate` by using `DELETE FROM`. `DELETE` without `WHERE` uses "The Truncate Optimization", see https://www.sqlite.org/lang_delete.html. * Add `rails db:seed:replant` that truncates database tables and loads the seeds Closes #34765
* SQLite3: Implement `add_foreign_key` and `remove_foreign_key`Ryuta Kamizono2019-02-111-3/+2
| | | | | | | | | | | | I implemented Foreign key create in `create_table` for SQLite3 at #24743. This follows #24743 to implement `add_foreign_key` and `remove_foreign_key`. Unfortunately SQLite3 has one limitation that `PRAGMA foreign_key_list(table-name)` doesn't have constraint name. So we couldn't implement find/remove foreign key by name for now. Fixes #35207. Closes #31343.
* More exercise table name prefix and suffix testsRyuta Kamizono2019-02-111-1/+5
|
* Relax sqlite3 version dependencySergey Ponomarev2019-02-041-1/+1
|
* Remove deprecated `#insert_fixtures` from the database adaptersRafael Mendonça França2019-01-171-8/+0
|
* Remove deprecated ↵Rafael Mendonça França2019-01-171-5/+0
| | | | `ActiveRecord::ConnectionAdapters::SQLite3Adapter#valid_alter_table_type?`
* Change `SQLite3Adapter` to always represent boolean values as integersRafael Mendonça França2019-01-171-16/+9
|
* An empty transaction does not raise the `ReadOnlyError` if preventing writesRyuta Kamizono2018-12-111-1/+1
| | | | | | 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-111-1/+1
|
* Don't treat begin and rollback transactions as write queriesRyuta Kamizono2018-12-111-1/+1
| | | | | Otherwise `save` method would raise the `ReadOnlyError` against `BEGIN` and `ROLLBACK` queries.
* Prevent write queries for `exec_query`Ryuta Kamizono2018-12-111-1/+5
| | | | Follow up #34505.
* Rename error that occurs when writing on a readEileen Uchitelle2018-12-071-1/+1
| | | | | | | 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`.
* Address "warning: shadowing outer local variable - parts"Ryuta Kamizono2018-12-031-1/+2
| | | | And hide the `READ_QUERY` internal constant.
* Add ability to prevent writes to a databaseEileen Uchitelle2018-11-301-0/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 ```
* Merge pull request #34468 from gmcgibbon/redact_sql_in_errorsRafael França2018-11-231-4/+4
|\ | | | | Redact SQL in errors
| * Redact SQL in errorsGannon McGibbon2018-11-221-4/+4
| | | | | | | | | | 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-221-1/+1
|/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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)) ```
* 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
* Consistently extract checking version for all adaptersRyuta Kamizono2018-10-171-5/+6
| | | | | | | I don't prefer to extract it for one adapter even though all adapters also does. Related to #34227.
* Add `Style/RedundantFreeze` to remove redudant `.freeze`Yasuo Honda2018-09-291-1/+1
| | | | | | | | | | | | | | | | | | | | | 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'
* Deprecate ActiveRecord::Result#to_hash in favor of #to_aKevin Cheng2018-09-181-1/+1
| | | | | | | method returns an array of hashes, not a hash e.g. Hash.try_convert(result) calls #to_hash and raises a TypeError [Gannon McGibbon + Kevin Cheng]
* SQLite3: Support multiple args function for expression indexesRyuta Kamizono2018-09-141-3/+6
| | | | | Follow up #33874. Related #23393.
* SQLite3 adapter supports expression indexesgkemmey2018-09-131-0/+4
|
* Merge pull request #32647 from eugeneius/lazy_transactionsMatthew Draper2018-08-231-0/+8
|\ | | | | Omit BEGIN/COMMIT statements for empty transactions
| * Omit BEGIN/COMMIT statements for empty transactionsEugene Kenny2018-08-131-0/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If a transaction is opened and closed without any queries being run, we can safely omit the `BEGIN` and `COMMIT` statements, as they only exist to modify the connection's behaviour inside the transaction. This removes the overhead of those statements when saving a record with no changes, which makes workarounds like `save if changed?` unnecessary. This implementation buffers transactions inside the transaction manager and materializes them the next time the connection is used. For this to work, the adapter needs to guard all connection use with a call to `materialize_transactions`. Because of this, adapters must opt in to get this new behaviour by implementing `supports_lazy_transactions?`. If `raw_connection` is used to get a reference to the underlying database connection, the behaviour is disabled and transactions are opened eagerly, as we can't know how the connection will be used. However when the connection is checked back into the pool, we can assume that the application won't use the reference again and reenable lazy transactions. This prevents a single `raw_connection` call from disabling lazy transactions for the lifetime of the connection.
* | SQLite3: Fix rename reference column not to lose foreign key constraintRyuta Kamizono2018-08-201-11/+15
| | | | | | | | Fixes #33520.
* | SQLite3 adapter `alter_table` method restores foreign keysYasuo Honda2018-08-111-1/+9
|/ | | | Related to #33520
* SQLite: Don't leak internal schema objectsRyuta Kamizono2018-07-091-3/+0
| | | | | | | | | | | | | | Related #31201. If creating custom primary key (like a string) in SQLite, it would also create an internal index implicitly which named begin with "sqlite_". It need to be hidden since the internal object names are reserved and prohibited for public use. See https://www.sqlite.org/fileformat2.html#intschema Fixes #33320.
* Merge pull request #33242 from brasic/sqlite-readonlyRyuta Kamizono2018-07-031-1/+3
|\ | | | | | | Support readonly option in SQLite3Adapter
| * Support readonly option in SQLite3AdapterCarl Brasic2018-07-021-1/+3
|/ | | | | | | | | | | | | | | | | Readonly sqlite database files are very useful as a data format for storing configuration/lookup data that is too complicated for YAML files. But since such files would typically be committed to a source control repository, it's important to ensure that they are truly safe from being inadvertently modified. Unfortunately using unix permissions isn't enough, as sqlite will "helpfully" add the write bit to a database file whenever it's written to. sqlite3-ruby has supported a `:readonly` option since version 1.3.2 (see https://github.com/sparklemotion/sqlite3-ruby/commit/c20c9f5dd2990042) This simply passes that option through to the adapter if present in the config hash. I think this is best considered an adapter-specific option since no other supported database has an identical concept.
* Disable foreign keys during `alter_table` for sqlite3 adapterYasuo Honda2018-05-221-5/+10
| | | | | | | | | | | | | | | | | | | | | | | | | Unlike other databases, changing SQLite3 table definitions need to create a temporary table. While changing table operations, the original table needs dropped which caused `SQLite3::ConstraintException: FOREIGN KEY constraint failed` if the table is referenced by foreign keys. This pull request disables foreign keys by `disable_referential_integrity`. Also `disable_referential_integrity` method needs to execute `defer_foreign_keys = ON` to defer re-enabling foreign keys until the transaction is committed. https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys Fixes #31988 - This `defer_foreign_keys = ON` has been supported since SQLite 3.8.0 https://www.sqlite.org/releaselog/3_8_0.html and Rails 6 requires SQLite 3.8 #32923 now - <Models>.reset_column_information added to address `ActiveModel::UnknownAttributeError` ``` Error: ActiveRecord::Migration::ForeignKeyChangeColumnTest#test_change_column_of_parent_table: ActiveModel::UnknownAttributeError: unknown attribute 'name' for ActiveRecord::Migration::ForeignKeyChangeColumnTest::Post. ```
* Bump minimum SQLite version to 3.8Yasuo Honda2018-05-211-6/+6
| | | | | | | | | | | | | | These OS versions have SQLite 3.8 or higher by default. - macOS 10.10 (Yosemite) or higher - Ubuntu 14.04 LTS or higher Raising the minimum version of SQLite 3.8 introduces these changes: - All of bundled adapters support `supports_multi_insert?` - SQLite 3.8 always satisifies `supports_foreign_keys_in_create?` and `supports_partial_index?` - sqlite adapter can support `alter_table` method for foreign key referenced tables by #32865 - Deprecated `supports_multi_insert?` method