| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|\
| |
| |
| | |
Add compact_blank shortcut for reject(&:blank?)
|
| | |
|
| | |
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Introduced in bba7c63a663b073034f4c73f0d59655751694e5a
Before:
```
$ TESTOPTS="-n=/test_yaml_dump_and_load/" bundle exec rake
test:postgresql
:scisors: ... :scisors:
Using postgresql
Run options: -n=/test_yaml_dump_and_load/ --seed 36896
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
/home/u/code/rails/activerecord/lib/active_record/connection_adapters/postgresql/column.rb:15:
warning: instance variable @serial not initialized
.
Finished in 0.195325s, 5.1197 runs/s, 35.8376 assertions/s.
1 runs, 7 assertions, 0 failures, 0 errors, 0 skips
```
Co-authored-by: Ryuta Kamizono <kamipo@gmail.com>
|
|\ \
| | |
| | | |
Deduplicate various Active Record schema cache structures
|
| |/
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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.
|
|\ \
| | |
| | | |
Enable `Layout/EmptyLinesAroundAccessModifier` cop
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
We sometimes say "✂️ newline after `private`" in a code review (e.g.
https://github.com/rails/rails/pull/18546#discussion_r23188776,
https://github.com/rails/rails/pull/34832#discussion_r244847195).
Now `Layout/EmptyLinesAroundAccessModifier` cop have new enforced style
`EnforcedStyle: only_before` (https://github.com/rubocop-hq/rubocop/pull/7059).
That cop and enforced style will reduce the our code review cost.
|
|/ /
| |
| |
| | |
Otherwise `Model.table_exists?` returns the staled cache result.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Currently, almost all "Dangerous query method" warnings are false alarm.
As long as almost all the warnings are false alarm, developers think
"Let's ignore the warnings by using `Arel.sql()`, it actually is false
alarm in practice.", so I think we should effort to reduce false alarm
in order to make the warnings valuable.
This allows column name with function (e.g. `length(title)`) as safe SQL
string, which is very common false alarm pattern, even in the our
codebase.
Related 6c82b6c99, 6607ecb2a, #36420.
Fixes #32995.
|
| | |
|
| |
| |
| |
| |
| | |
`split(/\s*,\s*/)` to order args and then `permit.match?` one by one is
much slower than `permit.match?` once.
|
|/
|
|
|
|
|
|
|
|
|
|
|
| |
Currently `posts.title` is regarded as a safe SQL string, but
`"posts"."title"` (it is a result of `quote_table_name("posts.title")`)
is regarded as an unsafe SQL string even though a result of
`quote_table_name` should obviously be regarded as a safe SQL string,
since the column name matcher doesn't respect quotation, it is a little
annoying.
This changes the column name matcher to allow quoted identifiers as safe
SQL string, now all results of the `quote_table_name` are regarded as
safe SQL string.
|
|
|
|
|
|
|
|
|
|
| |
This commit adds "TRANSACTION" to savepoint and commit, rollback statements
because none of savepoint statements were removed by #36153 since they are not "SCHEMA" statements.
Although, only savepoint statements can be labeled as "TRANSACTION"
I think all of transaction related method should add this label.
Follow up #36153
|
|
|
|
|
|
|
|
|
| |
We can revert migrations using `change_column_comment` or
`change_table_comment` at current master.
However, results are not what we expect: comments are remained in new
status.
This change tells previous comment to these methods in a way like
`change_column_default`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Running this migration on mysql at current master fails
because `add_references_for_alter` is missing.
```
change_table :users, bulk: true do |t|
t.references :article
end
```
This is also true for postgresql adapter,
but its `bulk_alter_table` implementation can fallback in such case.
postgresql's implementation is desirable to prevent unknown failure like this.
|
|
|
|
|
|
| |
* remove useless `@type_metadata` and `@array`
* move the compatibility code (for array) into column
* etc.
|
|
|
|
|
|
|
|
|
|
| |
All adapters (sqlite3, mysql2, postgresql, oracle-enhanced, sqlserver)
doesn't use `sequence_name` in `sql_for_insert`.
https://github.com/rsim/oracle-enhanced/blob/4e0db270a93859c9713fd079dbb315b9fe550e57/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb#L79-L85
https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/959fe8f49744460b876bc205c73259f8d4f37629/lib/active_record/connection_adapters/sqlserver/database_statements.rb#L226-L249
It can be handled in `exec_insert` like postgresql adapter if we want.
|
|
|
|
|
|
|
|
| |
free.
The previous implementation would allocate 2 arrays per comparisons.
I tried relying on Struct, but they do allocate one Hash inside `Struct#hash`.
|
|\
| |
| | |
Raise `ArgumentError` for invalid `:limit` and `:precision` like as other options
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
options
When I've added new `:size` option in #35071, I've found that invalid
`:limit` and `:precision` raises `ActiveRecordError` unlike other
invalid options.
I think that is hard to distinguish argument errors and statement
invalid errors since the `StatementInvalid` is a subclass of the
`ActiveRecordError`.
https://github.com/rails/rails/blob/c9e4c848eeeb8999b778fa1ae52185ca5537fffe/activerecord/lib/active_record/errors.rb#L103
```ruby
begin
# execute any migration
rescue ActiveRecord::StatementInvalid
# statement invalid
rescue ActiveRecord::ActiveRecordError, ArgumentError
# `ActiveRecordError` except `StatementInvalid` is maybe an argument error
end
```
I'd say this is the inconsistency worth fixing.
Before:
```ruby
add_column :items, :attr1, :binary, size: 10 # => ArgumentError
add_column :items, :attr2, :decimal, scale: 10 # => ArgumentError
add_column :items, :attr3, :integer, limit: 10 # => ActiveRecordError
add_column :items, :attr4, :datetime, precision: 10 # => ActiveRecordError
```
After:
```ruby
add_column :items, :attr1, :binary, size: 10 # => ArgumentError
add_column :items, :attr2, :decimal, scale: 10 # => ArgumentError
add_column :items, :attr3, :integer, limit: 10 # => ArgumentError
add_column :items, :attr4, :datetime, precision: 10 # => ArgumentError
```
|
|/
|
|
|
|
|
|
|
| |
The `table_name` was added at #23677 to detect whether serial column or
not correctly.
We can do that detection before initialize column object, it makes
column object size smaller, and it probably helps column object
de-duplication.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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`
```
|
|
|
|
| |
This is to easier make `truncate_tables` to bulk statements.
|
|
|
|
|
|
|
| |
Foreign keys could be created to the same table.
So `remove_foreign_key :from_table, :to_table` is sometimes ambiguous.
This allows `remove_foreign_key` to remove the select one on the same
table with giving both `to_table` and `options`.
|
|
|
|
|
| |
Also, improving an argument error message for `limit`, extracting around
`type_to_sql` code into schema statements, and more exercise tests.
|
|\
| |
| | |
Reduce unused allocations when casting UUIDs for Postgres
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Using the subscript method `#[]` on a string has several overloads and
rather complex implementation. One of the overloads is the capability to
accept a regular expression and then run a match, then return the
receiver (if it matched) or one of the groups from the MatchData.
The function of the `UUID#cast` method is to cast a UUID to a type and
format acceptable by postgres. Naturally UUIDs are supposed to be
string and of a certain format, but it had been determined that it was
not ideal for the framework to send just any old string to Postgres and
allow the engine to complain when "foobar" or "" was sent, being
obviously of the wrong format for a valid UUID. Therefore this code was
written to facilitate the checking, and if it were not of the correct
format, a `nil` would be returned as is conventional in Rails.
Now, the subscript method will allocate one or more strings on a match
and return one of them, based on the index parameter. However, there
is no need for a new string, as a UUID of the correct format is already
such, and so long as the format was verified then the string supplied is
adequate for consumption by the database.
The subscript method also creates a MatchData object which will never be
used, and so must eventually be garbage collected.
Garbage collection indeed. This innocuous method tends to be called
quite a lot, for example if the primary key of a table is a uuid, then
this method will be called. If the foreign key of a relation is a UUID,
once again this method is called. If that foreign key is belonging to
a has_many relationship with dozens of objects, then again dozens of
UUIDs shall be cast to a dup of themselves, and spawn dozens of
MatchData objects, and so on.
So, for users that:
* Use UUIDs as primary keys
* Use Postgres
* Operate on collections of objects
This accomplishes a significant savings in total allocations, and may
save many garbage collections.
|
|/ |
|
|
|
|
|
| |
It makes to ease to handle all short-hand methods (e.g. validates
arguments etc).
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Since #31230, `change_column` is executed as a bulk statement.
That caused incorrect type casting column default by looking up the
before changed type, not the after changed type.
In a bulk statement, we can't use `change_column_default_for_alter` if
the statement changes the column type.
This fixes the type casting to use the constructed target sql_type.
Fixes #34938.
|
|
|
|
| |
Since #26002, `id_value` is no longer passed to `sql_for_insert`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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.
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
Otherwise `save` method would raise the `ReadOnlyError` against `BEGIN`
and `ROLLBACK` queries.
|
|
|
|
|
|
|
| |
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`.
|
|
|
|
| |
And hide the `READ_QUERY` internal constant.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
```
|
|
|
|
|
| |
Fixes issue where "user post" is misinterpreted as "\"user\".\"post\""
when quoting table names with the postgres adapter.
|
|
|
|
| |
It should be referenced by full qualified name from Active Record.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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))
```
|
|
|
|
|
|
|
|
| |
in indexdef to be wrapped up by double quotes
Fixes #34493.
*Thomas Bianchini*
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
Since quoted `Infinity` and `NaN` are valid data for PostgreSQL.
|