activerecord 6.0.0 → 7.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +996 -594
- data/MIT-LICENSE +1 -1
- data/README.rdoc +34 -34
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +22 -20
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +41 -30
- data/lib/active_record/associations/association.rb +106 -41
- data/lib/active_record/associations/association_scope.rb +30 -21
- data/lib/active_record/associations/belongs_to_association.rb +69 -14
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +20 -6
- data/lib/active_record/associations/builder/association.rb +39 -6
- data/lib/active_record/associations/builder/belongs_to.rb +47 -17
- data/lib/active_record/associations/builder/collection_association.rb +14 -6
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -10
- data/lib/active_record/associations/builder/has_many.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +13 -16
- data/lib/active_record/associations/builder/singular_association.rb +7 -3
- data/lib/active_record/associations/collection_association.rb +90 -53
- data/lib/active_record/associations/collection_proxy.rb +54 -19
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +21 -1
- data/lib/active_record/associations/has_many_association.rb +41 -10
- data/lib/active_record/associations/has_many_through_association.rb +29 -12
- data/lib/active_record/associations/has_one_association.rb +33 -9
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +41 -17
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/join_dependency.rb +97 -54
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +237 -54
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +153 -0
- data/lib/active_record/associations/preloader/through_association.rb +51 -17
- data/lib/active_record/associations/preloader.rb +55 -121
- data/lib/active_record/associations/singular_association.rb +16 -4
- data/lib/active_record/associations/through_association.rb +26 -15
- data/lib/active_record/associations.rb +454 -440
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +11 -14
- data/lib/active_record/attribute_methods/before_type_cast.rb +36 -11
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +75 -34
- data/lib/active_record/attribute_methods/primary_key.rb +53 -31
- data/lib/active_record/attribute_methods/query.rb +31 -22
- data/lib/active_record/attribute_methods/read.rb +16 -17
- data/lib/active_record/attribute_methods/serialization.rb +177 -35
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +18 -15
- data/lib/active_record/attribute_methods/write.rb +16 -28
- data/lib/active_record/attribute_methods.rb +227 -100
- data/lib/active_record/attributes.rb +94 -56
- data/lib/active_record/autosave_association.rb +119 -73
- data/lib/active_record/base.rb +31 -21
- data/lib/active_record/callbacks.rb +168 -55
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -25
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +367 -565
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -57
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +277 -89
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +241 -69
- data/lib/active_record/connection_adapters/abstract/quoting.rb +122 -134
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +324 -72
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +17 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +611 -211
- data/lib/active_record/connection_adapters/abstract/transaction.rb +425 -82
- data/lib/active_record/connection_adapters/abstract_adapter.rb +698 -211
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +464 -239
- data/lib/active_record/connection_adapters/column.rb +28 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +32 -137
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +90 -43
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +41 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +18 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +13 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +53 -15
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +127 -63
- data/lib/active_record/connection_adapters/pool_config.rb +83 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +54 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +127 -100
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +9 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -15
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +35 -8
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -4
- data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +139 -106
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +98 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +176 -4
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -118
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -11
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +585 -295
- data/lib/active_record/connection_adapters/schema_cache.rb +399 -60
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +99 -48
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +80 -54
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +27 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +102 -24
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +425 -174
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -1
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +176 -0
- data/lib/active_record/connection_handling.rb +243 -115
- data/lib/active_record/core.rb +481 -199
- data/lib/active_record/counter_cache.rb +69 -32
- data/lib/active_record/database_configurations/connection_url_resolver.rb +107 -0
- data/lib/active_record/database_configurations/database_config.rb +77 -10
- data/lib/active_record/database_configurations/hash_config.rb +148 -26
- data/lib/active_record/database_configurations/url_config.rb +44 -45
- data/lib/active_record/database_configurations.rb +190 -114
- data/lib/active_record/delegated_type.rb +279 -0
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +38 -0
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +5 -6
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +171 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +96 -0
- data/lib/active_record/encryption/null_encryptor.rb +25 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +224 -73
- data/lib/active_record/errors.rb +254 -36
- data/lib/active_record/explain.rb +30 -17
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +2 -2
- data/lib/active_record/fixture_set/file.rb +22 -15
- data/lib/active_record/fixture_set/model_metadata.rb +15 -6
- data/lib/active_record/fixture_set/render_context.rb +3 -1
- data/lib/active_record/fixture_set/table_row.rb +88 -16
- data/lib/active_record/fixture_set/table_rows.rb +4 -5
- data/lib/active_record/fixtures.rb +229 -116
- data/lib/active_record/future_result.rb +178 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +121 -48
- data/lib/active_record/insert_all.rb +178 -29
- data/lib/active_record/integration.rb +16 -14
- data/lib/active_record/internal_metadata.rb +132 -21
- data/lib/active_record/legacy_yaml_adapter.rb +3 -36
- data/lib/active_record/locking/optimistic.rb +64 -33
- data/lib/active_record/locking/pessimistic.rb +21 -8
- data/lib/active_record/log_subscriber.rb +61 -30
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +19 -19
- data/lib/active_record/middleware/database_selector.rb +25 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +160 -55
- data/lib/active_record/migration/compatibility.rb +286 -43
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -2
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +421 -193
- data/lib/active_record/model_schema.rb +217 -125
- data/lib/active_record/nested_attributes.rb +62 -27
- data/lib/active_record/no_touching.rb +4 -4
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +322 -319
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -15
- data/lib/active_record/query_logs.rb +193 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +54 -14
- data/lib/active_record/railtie.rb +250 -72
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +25 -11
- data/lib/active_record/railties/databases.rake +312 -197
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +45 -3
- data/lib/active_record/reflection.rb +389 -146
- data/lib/active_record/relation/batches/batch_enumerator.rb +61 -16
- data/lib/active_record/relation/batches.rb +214 -73
- data/lib/active_record/relation/calculations.rb +379 -124
- data/lib/active_record/relation/delegation.rb +36 -23
- data/lib/active_record/relation/finder_methods.rb +159 -49
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +41 -33
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -11
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -7
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +20 -13
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +79 -53
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +1156 -279
- data/lib/active_record/relation/record_fetch_warning.rb +12 -11
- data/lib/active_record/relation/spawn_methods.rb +10 -9
- data/lib/active_record/relation/where_clause.rb +100 -66
- data/lib/active_record/relation.rb +829 -194
- data/lib/active_record/result.rb +76 -56
- data/lib/active_record/runtime_registry.rb +71 -13
- data/lib/active_record/sanitization.rb +86 -47
- data/lib/active_record/schema.rb +39 -23
- data/lib/active_record/schema_dumper.rb +140 -33
- data/lib/active_record/schema_migration.rb +74 -29
- data/lib/active_record/scoping/default.rb +73 -19
- data/lib/active_record/scoping/named.rb +10 -28
- data/lib/active_record/scoping.rb +65 -35
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +34 -8
- data/lib/active_record/serialization.rb +11 -4
- data/lib/active_record/signed_id.rb +138 -0
- data/lib/active_record/statement_cache.rb +26 -10
- data/lib/active_record/store.rb +19 -14
- data/lib/active_record/suppressor.rb +15 -17
- data/lib/active_record/table_metadata.rb +46 -36
- data/lib/active_record/tasks/database_tasks.rb +371 -205
- data/lib/active_record/tasks/mysql_database_tasks.rb +43 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +54 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -13
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +189 -104
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +35 -25
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +31 -27
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +131 -99
- data/lib/active_record/translation.rb +3 -5
- data/lib/active_record/type/adapter_specific_registry.rb +33 -18
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +11 -6
- data/lib/active_record/type/time.rb +14 -0
- data/lib/active_record/type/type_map.rb +17 -21
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +7 -2
- data/lib/active_record/type_caster/connection.rb +4 -5
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +13 -8
- data/lib/active_record/validations/numericality.rb +36 -0
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +88 -18
- data/lib/active_record/validations.rb +15 -8
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +446 -40
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/attributes/attribute.rb +4 -8
- data/lib/arel/collectors/bind.rb +8 -1
- data/lib/arel/collectors/composite.rb +15 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/crud.rb +30 -22
- data/lib/arel/delete_manager.rb +23 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/binary.rb +82 -9
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/casted.rb +22 -10
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +14 -13
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +68 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
- data/lib/arel/nodes/node.rb +122 -11
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/table_alias.rb +11 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes/update_statement.rb +11 -4
- data/lib/arel/nodes.rb +10 -3
- data/lib/arel/predications.rb +31 -28
- data/lib/arel/select_manager.rb +18 -9
- data/lib/arel/table.rb +21 -10
- data/lib/arel/tree_manager.rb +8 -15
- data/lib/arel/update_manager.rb +25 -5
- data/lib/arel/visitors/dot.rb +94 -90
- data/lib/arel/visitors/mysql.rb +34 -6
- data/lib/arel/visitors/postgresql.rb +5 -16
- data/lib/arel/visitors/sqlite.rb +25 -1
- data/lib/arel/visitors/to_sql.rb +227 -81
- data/lib/arel/visitors/visitor.rb +2 -3
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +37 -15
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +6 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/migration.rb +9 -3
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +49 -4
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +117 -30
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/null_relation.rb +0 -68
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
data/lib/arel/nodes/in.rb
CHANGED
|
@@ -43,7 +43,19 @@ module Arel # :nodoc: all
|
|
|
43
43
|
|
|
44
44
|
class Concat < InfixOperation
|
|
45
45
|
def initialize(left, right)
|
|
46
|
-
super("||", left, right)
|
|
46
|
+
super(:"||", left, right)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class Contains < InfixOperation
|
|
51
|
+
def initialize(left, right)
|
|
52
|
+
super(:"@>", left, right)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class Overlaps < InfixOperation
|
|
57
|
+
def initialize(left, right)
|
|
58
|
+
super(:"&&", left, right)
|
|
47
59
|
end
|
|
48
60
|
end
|
|
49
61
|
|
|
@@ -5,9 +5,9 @@ module Arel # :nodoc: all
|
|
|
5
5
|
class InsertStatement < Arel::Nodes::Node
|
|
6
6
|
attr_accessor :relation, :columns, :values, :select
|
|
7
7
|
|
|
8
|
-
def initialize
|
|
8
|
+
def initialize(relation = nil)
|
|
9
9
|
super()
|
|
10
|
-
@relation =
|
|
10
|
+
@relation = relation
|
|
11
11
|
@columns = []
|
|
12
12
|
@values = nil
|
|
13
13
|
@select = nil
|
|
@@ -5,7 +5,7 @@ module Arel # :nodoc: all
|
|
|
5
5
|
###
|
|
6
6
|
# Class that represents a join source
|
|
7
7
|
#
|
|
8
|
-
#
|
|
8
|
+
# https://www.sqlite.org/syntaxdiagrams.html#join-source
|
|
9
9
|
|
|
10
10
|
class JoinSource < Arel::Nodes::Binary
|
|
11
11
|
def initialize(single_source, joinop = [])
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Arel # :nodoc: all
|
|
4
4
|
module Nodes
|
|
5
|
-
class
|
|
5
|
+
class Nary < Arel::Nodes::NodeExpression
|
|
6
6
|
attr_reader :children
|
|
7
7
|
|
|
8
8
|
def initialize(children)
|
|
@@ -18,8 +18,12 @@ module Arel # :nodoc: all
|
|
|
18
18
|
children[1]
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
def fetch_attribute(&block)
|
|
22
|
+
children.any? && children.all? { |child| child.fetch_attribute(&block) }
|
|
23
|
+
end
|
|
24
|
+
|
|
21
25
|
def hash
|
|
22
|
-
children.hash
|
|
26
|
+
[self.class, children].hash
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
def eql?(other)
|
|
@@ -28,5 +32,8 @@ module Arel # :nodoc: all
|
|
|
28
32
|
end
|
|
29
33
|
alias :== :eql?
|
|
30
34
|
end
|
|
35
|
+
|
|
36
|
+
And = Class.new(Nary)
|
|
37
|
+
Or = Class.new(Nary)
|
|
31
38
|
end
|
|
32
39
|
end
|
data/lib/arel/nodes/node.rb
CHANGED
|
@@ -2,11 +2,119 @@
|
|
|
2
2
|
|
|
3
3
|
module Arel # :nodoc: all
|
|
4
4
|
module Nodes
|
|
5
|
-
|
|
6
|
-
#
|
|
5
|
+
# = Using +Arel::Nodes::Node+
|
|
6
|
+
#
|
|
7
|
+
# Active Record uses Arel to compose SQL statements. Instead of building SQL strings directly, it's building an
|
|
8
|
+
# abstract syntax tree (AST) of the statement using various types of Arel::Nodes::Node. Each node represents a
|
|
9
|
+
# fragment of a SQL statement.
|
|
10
|
+
#
|
|
11
|
+
# The intermediate representation allows Arel to compile the statement into the database's specific SQL dialect
|
|
12
|
+
# only before sending it without having to care about the nuances of each database when building the statement.
|
|
13
|
+
# It also allows easier composition of statements without having to resort to (brittle and unsafe) string manipulation.
|
|
14
|
+
#
|
|
15
|
+
# == Building constraints
|
|
16
|
+
#
|
|
17
|
+
# One of the most common use cases of Arel is generating constraints for +SELECT+ statements. To help with that,
|
|
18
|
+
# most nodes include a couple of useful factory methods to create subtree structures for common constraints. For
|
|
19
|
+
# a full list of those, please refer to Arel::Predications.
|
|
20
|
+
#
|
|
21
|
+
# The following example creates an equality constraint where the value of the name column on the users table
|
|
22
|
+
# matches the value DHH.
|
|
23
|
+
#
|
|
24
|
+
# users = Arel::Table.new(:users)
|
|
25
|
+
# constraint = users[:name].eq("DHH")
|
|
26
|
+
#
|
|
27
|
+
# # => Arel::Nodes::Equality.new(
|
|
28
|
+
# # Arel::Attributes::Attribute.new(users, "name"),
|
|
29
|
+
# # Arel::Nodes::Casted.new(
|
|
30
|
+
# # "DHH",
|
|
31
|
+
# # Arel::Attributes::Attribute.new(users, "name")
|
|
32
|
+
# # )
|
|
33
|
+
# # )
|
|
34
|
+
#
|
|
35
|
+
# The resulting SQL fragment will look like this:
|
|
36
|
+
#
|
|
37
|
+
# "users"."name" = 'DHH'
|
|
38
|
+
#
|
|
39
|
+
# The constraint fragments can be used with regular ActiveRecord::Relation objects instead of a Hash. The
|
|
40
|
+
# following two examples show two ways of creating the same query.
|
|
41
|
+
#
|
|
42
|
+
# User.where(name: 'DHH')
|
|
43
|
+
#
|
|
44
|
+
# # SELECT "users".* FROM "users" WHERE "users"."name" = 'DHH'
|
|
45
|
+
#
|
|
46
|
+
# users = User.arel_table
|
|
47
|
+
#
|
|
48
|
+
# User.where(users[:name].eq('DHH'))
|
|
49
|
+
#
|
|
50
|
+
# # SELECT "users".* FROM "users" WHERE "users"."name" = 'DHH'
|
|
51
|
+
#
|
|
52
|
+
# == Functions
|
|
53
|
+
#
|
|
54
|
+
# Arel comes with built-in support for SQL functions like +COUNT+, +SUM+, +MIN+, +MAX+, and +AVG+. The
|
|
55
|
+
# Arel::Expressions module includes factory methods for the default functions.
|
|
56
|
+
#
|
|
57
|
+
# employees = Employee.arel_table
|
|
58
|
+
#
|
|
59
|
+
# Employee.select(employees[:department_id], employees[:salary].average).group(employees[:department_id])
|
|
60
|
+
#
|
|
61
|
+
# # SELECT "employees"."department_id", AVG("employees"."salary")
|
|
62
|
+
# # FROM "employees" GROUP BY "employees"."department_id"
|
|
63
|
+
#
|
|
64
|
+
# It’s also possible to use custom functions by using the Arel::Nodes::NamedFunction node type. It accepts a
|
|
65
|
+
# function name and an array of parameters.
|
|
66
|
+
#
|
|
67
|
+
# Arel::Nodes::NamedFunction.new('date_trunc', [Arel::Nodes.build_quoted('day'), User.arel_table[:created_at]])
|
|
68
|
+
#
|
|
69
|
+
# # date_trunc('day', "users"."created_at")
|
|
70
|
+
#
|
|
71
|
+
# == Quoting & bind params
|
|
72
|
+
#
|
|
73
|
+
# Values that you pass to Arel nodes need to be quoted or wrapped in bind params. This ensures they are properly
|
|
74
|
+
# converted into the correct format without introducing a possible SQL injection vulnerability. Most factory
|
|
75
|
+
# methods (like +eq+, +gt+, +lteq+, …) quote passed values automatically. When not using a factory method, it’s
|
|
76
|
+
# possible to convert a value and wrap it in an Arel::Nodes::Quoted node (if necessary) by calling +Arel::Nodes.
|
|
77
|
+
# build_quoted+.
|
|
78
|
+
#
|
|
79
|
+
# Arel::Nodes.build_quoted("foo") # 'foo'
|
|
80
|
+
# Arel::Nodes.build_quoted(12.3) # 12.3
|
|
81
|
+
#
|
|
82
|
+
# Instead of quoting values and embedding them directly in the SQL statement, it’s also possible to create bind
|
|
83
|
+
# params. This keeps the actual values outside of the statement and allows using the prepared statement feature
|
|
84
|
+
# of some databases.
|
|
85
|
+
#
|
|
86
|
+
# attribute = ActiveRecord::Relation::QueryAttribute.new(:name, "DHH", ActiveRecord::Type::String.new)
|
|
87
|
+
# Arel::Nodes::BindParam.new(attribute)
|
|
88
|
+
#
|
|
89
|
+
# When ActiveRecord runs the query, bind params are replaced by placeholders (like +$1+) and the values are passed
|
|
90
|
+
# separately.
|
|
91
|
+
#
|
|
92
|
+
# == SQL Literals
|
|
93
|
+
#
|
|
94
|
+
# For cases where there is no way to represent a particular SQL fragment using Arel nodes, you can use an SQL
|
|
95
|
+
# literal. SQL literals are strings that Arel will treat “as is”.
|
|
96
|
+
#
|
|
97
|
+
# Arel.sql('LOWER("users"."name")').eq('dhh')
|
|
98
|
+
#
|
|
99
|
+
# # LOWER("users"."name") = 'dhh'
|
|
100
|
+
#
|
|
101
|
+
# Please keep in mind that passing data as raw SQL literals might introduce a possible SQL injection. However,
|
|
102
|
+
# `Arel.sql` supports binding parameters which will ensure proper quoting. This can be useful when you need to
|
|
103
|
+
# control the exact SQL you run, but you still have potentially user-supplied values.
|
|
104
|
+
#
|
|
105
|
+
# Arel.sql('LOWER("users"."name") = ?', 'dhh')
|
|
106
|
+
#
|
|
107
|
+
# # LOWER("users"."name") = 'dhh'
|
|
108
|
+
#
|
|
109
|
+
# You can also combine SQL literals.
|
|
110
|
+
#
|
|
111
|
+
# sql = Arel.sql('SELECT * FROM "users" WHERE ')
|
|
112
|
+
# sql += Arel.sql('LOWER("users"."name") = :name', name: 'dhh')
|
|
113
|
+
# sql += Arel.sql('AND "users"."age" > :age', age: 35)
|
|
114
|
+
#
|
|
115
|
+
# # SELECT * FROM "users" WHERE LOWER("users"."name") = 'dhh' AND "users"."age" > '35'
|
|
7
116
|
class Node
|
|
8
117
|
include Arel::FactoryMethods
|
|
9
|
-
include Enumerable
|
|
10
118
|
|
|
11
119
|
###
|
|
12
120
|
# Factory method to create a Nodes::Not node that has the recipient of
|
|
@@ -19,7 +127,7 @@ module Arel # :nodoc: all
|
|
|
19
127
|
# Factory method to create a Nodes::Grouping node that has an Nodes::Or
|
|
20
128
|
# node as a child.
|
|
21
129
|
def or(right)
|
|
22
|
-
Nodes::Grouping.new Nodes::Or.new(self, right)
|
|
130
|
+
Nodes::Grouping.new Nodes::Or.new([self, right])
|
|
23
131
|
end
|
|
24
132
|
|
|
25
133
|
###
|
|
@@ -28,6 +136,10 @@ module Arel # :nodoc: all
|
|
|
28
136
|
Nodes::And.new [self, right]
|
|
29
137
|
end
|
|
30
138
|
|
|
139
|
+
def invert
|
|
140
|
+
Arel::Nodes::Not.new(self)
|
|
141
|
+
end
|
|
142
|
+
|
|
31
143
|
# FIXME: this method should go away. I don't like people calling
|
|
32
144
|
# to_sql on non-head nodes. This forces us to walk the AST until we
|
|
33
145
|
# can find a node that has a "relation" member.
|
|
@@ -35,16 +147,15 @@ module Arel # :nodoc: all
|
|
|
35
147
|
# Maybe we should just use `Table.engine`? :'(
|
|
36
148
|
def to_sql(engine = Table.engine)
|
|
37
149
|
collector = Arel::Collectors::SQLString.new
|
|
38
|
-
|
|
39
|
-
|
|
150
|
+
engine.with_connection do |connection|
|
|
151
|
+
connection.visitor.accept(self, collector).value
|
|
152
|
+
end
|
|
40
153
|
end
|
|
41
154
|
|
|
42
|
-
|
|
43
|
-
def each(&block)
|
|
44
|
-
return enum_for(:each) unless block_given?
|
|
45
|
-
|
|
46
|
-
::Arel::Visitors::DepthFirst.new(block).accept self
|
|
155
|
+
def fetch_attribute
|
|
47
156
|
end
|
|
157
|
+
|
|
158
|
+
def equality?; false; end
|
|
48
159
|
end
|
|
49
160
|
end
|
|
50
161
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Arel # :nodoc: all
|
|
4
|
+
module Nodes
|
|
5
|
+
class Ordering < Unary
|
|
6
|
+
def nulls_first
|
|
7
|
+
NullsFirst.new(self)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def nulls_last
|
|
11
|
+
NullsLast.new(self)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class NullsFirst < Ordering
|
|
16
|
+
def reverse
|
|
17
|
+
NullsLast.new(expr.reverse)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class NullsLast < Ordering
|
|
22
|
+
def reverse
|
|
23
|
+
NullsFirst.new(expr.reverse)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -6,9 +6,9 @@ module Arel # :nodoc: all
|
|
|
6
6
|
attr_accessor :projections, :wheres, :groups, :windows, :comment
|
|
7
7
|
attr_accessor :havings, :source, :set_quantifier, :optimizer_hints
|
|
8
8
|
|
|
9
|
-
def initialize
|
|
9
|
+
def initialize(relation = nil)
|
|
10
10
|
super()
|
|
11
|
-
@source = JoinSource.new
|
|
11
|
+
@source = JoinSource.new(relation)
|
|
12
12
|
|
|
13
13
|
# https://ronsavage.github.io/SQL/sql-92.bnf.html#set%20quantifier
|
|
14
14
|
@set_quantifier = nil
|
|
@@ -6,9 +6,9 @@ module Arel # :nodoc: all
|
|
|
6
6
|
attr_reader :cores
|
|
7
7
|
attr_accessor :limit, :orders, :lock, :offset, :with
|
|
8
8
|
|
|
9
|
-
def initialize(
|
|
9
|
+
def initialize(relation = nil)
|
|
10
10
|
super()
|
|
11
|
-
@cores =
|
|
11
|
+
@cores = [SelectCore.new(relation)]
|
|
12
12
|
@orders = []
|
|
13
13
|
@limit = nil
|
|
14
14
|
@lock = nil
|
|
@@ -8,9 +8,25 @@ module Arel # :nodoc: all
|
|
|
8
8
|
include Arel::AliasPredication
|
|
9
9
|
include Arel::OrderPredications
|
|
10
10
|
|
|
11
|
+
attr_reader :retryable
|
|
12
|
+
|
|
13
|
+
def initialize(string, retryable: false)
|
|
14
|
+
@retryable = retryable
|
|
15
|
+
super(string)
|
|
16
|
+
end
|
|
17
|
+
|
|
11
18
|
def encode_with(coder)
|
|
12
19
|
coder.scalar = self.to_s
|
|
13
20
|
end
|
|
21
|
+
|
|
22
|
+
def fetch_attribute
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def +(other)
|
|
26
|
+
raise ArgumentError, "Expected Arel node" unless Arel.arel_node?(other)
|
|
27
|
+
|
|
28
|
+
Fragments.new([self, other])
|
|
29
|
+
end
|
|
14
30
|
end
|
|
15
31
|
end
|
|
16
32
|
end
|
|
@@ -8,20 +8,28 @@ module Arel # :nodoc: all
|
|
|
8
8
|
alias :table_alias :name
|
|
9
9
|
|
|
10
10
|
def [](name)
|
|
11
|
-
Attribute.new(self, name)
|
|
11
|
+
relation.is_a?(Table) ? relation[name, self] : Attribute.new(self, name)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def table_name
|
|
15
15
|
relation.respond_to?(:name) ? relation.name : name
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
def type_cast_for_database(
|
|
19
|
-
relation.type_cast_for_database(
|
|
18
|
+
def type_cast_for_database(attr_name, value)
|
|
19
|
+
relation.type_cast_for_database(attr_name, value)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def type_for_attribute(name)
|
|
23
|
+
relation.type_for_attribute(name)
|
|
20
24
|
end
|
|
21
25
|
|
|
22
26
|
def able_to_type_cast?
|
|
23
27
|
relation.respond_to?(:able_to_type_cast?) && relation.able_to_type_cast?
|
|
24
28
|
end
|
|
29
|
+
|
|
30
|
+
def to_cte
|
|
31
|
+
Arel::Nodes::Cte.new(name, relation)
|
|
32
|
+
end
|
|
25
33
|
end
|
|
26
34
|
end
|
|
27
35
|
end
|
data/lib/arel/nodes/unary.rb
CHANGED
|
@@ -3,15 +3,19 @@
|
|
|
3
3
|
module Arel # :nodoc: all
|
|
4
4
|
module Nodes
|
|
5
5
|
class UpdateStatement < Arel::Nodes::Node
|
|
6
|
-
attr_accessor :relation, :wheres, :values, :orders, :limit, :offset, :key
|
|
6
|
+
attr_accessor :relation, :wheres, :values, :groups, :havings, :orders, :limit, :offset, :comment, :key
|
|
7
7
|
|
|
8
|
-
def initialize
|
|
9
|
-
|
|
8
|
+
def initialize(relation = nil)
|
|
9
|
+
super()
|
|
10
|
+
@relation = relation
|
|
10
11
|
@wheres = []
|
|
11
12
|
@values = []
|
|
13
|
+
@groups = []
|
|
14
|
+
@havings = []
|
|
12
15
|
@orders = []
|
|
13
16
|
@limit = nil
|
|
14
17
|
@offset = nil
|
|
18
|
+
@comment = nil
|
|
15
19
|
@key = nil
|
|
16
20
|
end
|
|
17
21
|
|
|
@@ -22,7 +26,7 @@ module Arel # :nodoc: all
|
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
def hash
|
|
25
|
-
[@relation, @wheres, @values, @orders, @limit, @offset, @key].hash
|
|
29
|
+
[@relation, @wheres, @values, @orders, @limit, @offset, @comment, @key].hash
|
|
26
30
|
end
|
|
27
31
|
|
|
28
32
|
def eql?(other)
|
|
@@ -30,9 +34,12 @@ module Arel # :nodoc: all
|
|
|
30
34
|
self.relation == other.relation &&
|
|
31
35
|
self.wheres == other.wheres &&
|
|
32
36
|
self.values == other.values &&
|
|
37
|
+
self.groups == other.groups &&
|
|
38
|
+
self.havings == other.havings &&
|
|
33
39
|
self.orders == other.orders &&
|
|
34
40
|
self.limit == other.limit &&
|
|
35
41
|
self.offset == other.offset &&
|
|
42
|
+
self.comment == other.comment &&
|
|
36
43
|
self.key == other.key
|
|
37
44
|
end
|
|
38
45
|
alias :== :eql?
|
data/lib/arel/nodes.rb
CHANGED
|
@@ -8,6 +8,7 @@ require "arel/nodes/select_core"
|
|
|
8
8
|
require "arel/nodes/insert_statement"
|
|
9
9
|
require "arel/nodes/update_statement"
|
|
10
10
|
require "arel/nodes/bind_param"
|
|
11
|
+
require "arel/nodes/fragments"
|
|
11
12
|
|
|
12
13
|
# terminal
|
|
13
14
|
|
|
@@ -18,6 +19,8 @@ require "arel/nodes/false"
|
|
|
18
19
|
# unary
|
|
19
20
|
require "arel/nodes/unary"
|
|
20
21
|
require "arel/nodes/grouping"
|
|
22
|
+
require "arel/nodes/homogeneous_in"
|
|
23
|
+
require "arel/nodes/ordering"
|
|
21
24
|
require "arel/nodes/ascending"
|
|
22
25
|
require "arel/nodes/descending"
|
|
23
26
|
require "arel/nodes/unqualified_column"
|
|
@@ -26,7 +29,8 @@ require "arel/nodes/with"
|
|
|
26
29
|
# binary
|
|
27
30
|
require "arel/nodes/binary"
|
|
28
31
|
require "arel/nodes/equality"
|
|
29
|
-
require "arel/nodes/
|
|
32
|
+
require "arel/nodes/filter"
|
|
33
|
+
require "arel/nodes/in"
|
|
30
34
|
require "arel/nodes/join_source"
|
|
31
35
|
require "arel/nodes/delete_statement"
|
|
32
36
|
require "arel/nodes/table_alias"
|
|
@@ -35,9 +39,10 @@ require "arel/nodes/unary_operation"
|
|
|
35
39
|
require "arel/nodes/over"
|
|
36
40
|
require "arel/nodes/matches"
|
|
37
41
|
require "arel/nodes/regexp"
|
|
42
|
+
require "arel/nodes/cte"
|
|
38
43
|
|
|
39
|
-
# nary
|
|
40
|
-
require "arel/nodes/
|
|
44
|
+
# nary (And and Or)
|
|
45
|
+
require "arel/nodes/nary"
|
|
41
46
|
|
|
42
47
|
# function
|
|
43
48
|
# FIXME: Function + Alias can be rewritten as a Function and Alias node.
|
|
@@ -60,9 +65,11 @@ require "arel/nodes/inner_join"
|
|
|
60
65
|
require "arel/nodes/outer_join"
|
|
61
66
|
require "arel/nodes/right_outer_join"
|
|
62
67
|
require "arel/nodes/string_join"
|
|
68
|
+
require "arel/nodes/leading_join"
|
|
63
69
|
|
|
64
70
|
require "arel/nodes/comment"
|
|
65
71
|
|
|
66
72
|
require "arel/nodes/sql_literal"
|
|
73
|
+
require "arel/nodes/bound_sql_literal"
|
|
67
74
|
|
|
68
75
|
require "arel/nodes/casted"
|
data/lib/arel/predications.rb
CHANGED
|
@@ -38,21 +38,27 @@ module Arel # :nodoc: all
|
|
|
38
38
|
if unboundable?(other.begin) == 1 || unboundable?(other.end) == -1
|
|
39
39
|
self.in([])
|
|
40
40
|
elsif open_ended?(other.begin)
|
|
41
|
-
if
|
|
42
|
-
|
|
41
|
+
if open_ended?(other.end)
|
|
42
|
+
if infinity?(other.begin) == 1 || infinity?(other.end) == -1
|
|
43
|
+
self.in([])
|
|
44
|
+
else
|
|
45
|
+
not_in([])
|
|
46
|
+
end
|
|
43
47
|
elsif other.exclude_end?
|
|
44
48
|
lt(other.end)
|
|
45
49
|
else
|
|
46
50
|
lteq(other.end)
|
|
47
51
|
end
|
|
48
|
-
elsif
|
|
52
|
+
elsif open_ended?(other.end)
|
|
49
53
|
gteq(other.begin)
|
|
50
54
|
elsif other.exclude_end?
|
|
51
55
|
gteq(other.begin).and(lt(other.end))
|
|
56
|
+
elsif other.begin == other.end
|
|
57
|
+
eq(other.begin)
|
|
52
58
|
else
|
|
53
59
|
left = quoted_node(other.begin)
|
|
54
60
|
right = quoted_node(other.end)
|
|
55
|
-
Nodes::Between.new(self,
|
|
61
|
+
Nodes::Between.new(self, Nodes::And.new([left, right]))
|
|
56
62
|
end
|
|
57
63
|
end
|
|
58
64
|
|
|
@@ -60,13 +66,6 @@ module Arel # :nodoc: all
|
|
|
60
66
|
case other
|
|
61
67
|
when Arel::SelectManager
|
|
62
68
|
Arel::Nodes::In.new(self, other.ast)
|
|
63
|
-
when Range
|
|
64
|
-
if $VERBOSE
|
|
65
|
-
warn <<-eowarn
|
|
66
|
-
Passing a range to `#in` is deprecated. Call `#between`, instead.
|
|
67
|
-
eowarn
|
|
68
|
-
end
|
|
69
|
-
between(other)
|
|
70
69
|
when Enumerable
|
|
71
70
|
Nodes::In.new self, quoted_array(other)
|
|
72
71
|
else
|
|
@@ -86,14 +85,18 @@ Passing a range to `#in` is deprecated. Call `#between`, instead.
|
|
|
86
85
|
if unboundable?(other.begin) == 1 || unboundable?(other.end) == -1
|
|
87
86
|
not_in([])
|
|
88
87
|
elsif open_ended?(other.begin)
|
|
89
|
-
if
|
|
90
|
-
|
|
88
|
+
if open_ended?(other.end)
|
|
89
|
+
if infinity?(other.begin) == 1 || infinity?(other.end) == -1
|
|
90
|
+
not_in([])
|
|
91
|
+
else
|
|
92
|
+
self.in([])
|
|
93
|
+
end
|
|
91
94
|
elsif other.exclude_end?
|
|
92
95
|
gteq(other.end)
|
|
93
96
|
else
|
|
94
97
|
gt(other.end)
|
|
95
98
|
end
|
|
96
|
-
elsif
|
|
99
|
+
elsif open_ended?(other.end)
|
|
97
100
|
lt(other.begin)
|
|
98
101
|
else
|
|
99
102
|
left = lt(other.begin)
|
|
@@ -110,13 +113,6 @@ Passing a range to `#in` is deprecated. Call `#between`, instead.
|
|
|
110
113
|
case other
|
|
111
114
|
when Arel::SelectManager
|
|
112
115
|
Arel::Nodes::NotIn.new(self, other.ast)
|
|
113
|
-
when Range
|
|
114
|
-
if $VERBOSE
|
|
115
|
-
warn <<-eowarn
|
|
116
|
-
Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
|
|
117
|
-
eowarn
|
|
118
|
-
end
|
|
119
|
-
not_between(other)
|
|
120
116
|
when Enumerable
|
|
121
117
|
Nodes::NotIn.new self, quoted_array(other)
|
|
122
118
|
else
|
|
@@ -220,12 +216,23 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
|
|
|
220
216
|
Nodes::Concat.new self, other
|
|
221
217
|
end
|
|
222
218
|
|
|
223
|
-
|
|
219
|
+
def contains(other)
|
|
220
|
+
Arel::Nodes::Contains.new self, quoted_node(other)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def overlaps(other)
|
|
224
|
+
Arel::Nodes::Overlaps.new self, quoted_node(other)
|
|
225
|
+
end
|
|
224
226
|
|
|
227
|
+
def quoted_array(others)
|
|
228
|
+
others.map { |v| quoted_node(v) }
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
private
|
|
225
232
|
def grouping_any(method_id, others, *extras)
|
|
226
233
|
nodes = others.map { |expr| send(method_id, expr, *extras) }
|
|
227
234
|
Nodes::Grouping.new nodes.inject { |memo, node|
|
|
228
|
-
Nodes::Or.new(memo, node)
|
|
235
|
+
Nodes::Or.new([memo, node])
|
|
229
236
|
}
|
|
230
237
|
end
|
|
231
238
|
|
|
@@ -238,10 +245,6 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
|
|
|
238
245
|
Nodes.build_quoted(other, self)
|
|
239
246
|
end
|
|
240
247
|
|
|
241
|
-
def quoted_array(others)
|
|
242
|
-
others.map { |v| quoted_node(v) }
|
|
243
|
-
end
|
|
244
|
-
|
|
245
248
|
def infinity?(value)
|
|
246
249
|
value.respond_to?(:infinite?) && value.infinite?
|
|
247
250
|
end
|
|
@@ -251,7 +254,7 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
|
|
|
251
254
|
end
|
|
252
255
|
|
|
253
256
|
def open_ended?(value)
|
|
254
|
-
infinity?(value) || unboundable?(value)
|
|
257
|
+
value.nil? || infinity?(value) || unboundable?(value)
|
|
255
258
|
end
|
|
256
259
|
end
|
|
257
260
|
end
|
data/lib/arel/select_manager.rb
CHANGED
|
@@ -7,10 +7,8 @@ module Arel # :nodoc: all
|
|
|
7
7
|
STRING_OR_SYMBOL_CLASS = [Symbol, String]
|
|
8
8
|
|
|
9
9
|
def initialize(table = nil)
|
|
10
|
-
|
|
11
|
-
@ast = Nodes::SelectStatement.new
|
|
10
|
+
@ast = Nodes::SelectStatement.new(table)
|
|
12
11
|
@ctx = @ast.cores.last
|
|
13
|
-
from table
|
|
14
12
|
end
|
|
15
13
|
|
|
16
14
|
def initialize_copy(other)
|
|
@@ -48,7 +46,7 @@ module Arel # :nodoc: all
|
|
|
48
46
|
end
|
|
49
47
|
|
|
50
48
|
def as(other)
|
|
51
|
-
create_table_alias grouping(@ast), Nodes::SqlLiteral.new(other)
|
|
49
|
+
create_table_alias grouping(@ast), Nodes::SqlLiteral.new(other, retryable: true)
|
|
52
50
|
end
|
|
53
51
|
|
|
54
52
|
def lock(locking = Arel.sql("FOR UPDATE"))
|
|
@@ -98,7 +96,7 @@ module Arel # :nodoc: all
|
|
|
98
96
|
end
|
|
99
97
|
|
|
100
98
|
def froms
|
|
101
|
-
@ast.cores.
|
|
99
|
+
@ast.cores.filter_map { |x| x.from }
|
|
102
100
|
end
|
|
103
101
|
|
|
104
102
|
def join(relation, klass = Nodes::InnerJoin)
|
|
@@ -183,11 +181,18 @@ module Arel # :nodoc: all
|
|
|
183
181
|
@ast.orders
|
|
184
182
|
end
|
|
185
183
|
|
|
184
|
+
def where(expr)
|
|
185
|
+
if Arel::TreeManager === expr
|
|
186
|
+
expr = expr.ast
|
|
187
|
+
end
|
|
188
|
+
@ctx.wheres << expr
|
|
189
|
+
self
|
|
190
|
+
end
|
|
191
|
+
|
|
186
192
|
def where_sql(engine = Table.engine)
|
|
187
193
|
return if @ctx.wheres.empty?
|
|
188
194
|
|
|
189
|
-
|
|
190
|
-
Nodes::SqlLiteral.new viz.accept(@ctx, Collectors::SQLString.new).value
|
|
195
|
+
Nodes::SqlLiteral.new("WHERE #{Nodes::And.new(@ctx.wheres).to_sql(engine)}")
|
|
191
196
|
end
|
|
192
197
|
|
|
193
198
|
def union(operation, other = nil)
|
|
@@ -245,8 +250,12 @@ module Arel # :nodoc: all
|
|
|
245
250
|
end
|
|
246
251
|
|
|
247
252
|
def comment(*values)
|
|
248
|
-
|
|
249
|
-
|
|
253
|
+
if values.any?
|
|
254
|
+
@ctx.comment = Nodes::Comment.new(values)
|
|
255
|
+
self
|
|
256
|
+
else
|
|
257
|
+
@ctx.comment
|
|
258
|
+
end
|
|
250
259
|
end
|
|
251
260
|
|
|
252
261
|
private
|