activerecord 4.2.8 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +612 -1583
- data/MIT-LICENSE +4 -2
- data/README.rdoc +13 -12
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record.rb +41 -22
- data/lib/active_record/aggregations.rb +267 -251
- data/lib/active_record/association_relation.rb +11 -6
- data/lib/active_record/associations.rb +1737 -1597
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +125 -58
- data/lib/active_record/associations/association_scope.rb +103 -132
- data/lib/active_record/associations/belongs_to_association.rb +65 -60
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +27 -40
- data/lib/active_record/associations/builder/belongs_to.rb +69 -55
- data/lib/active_record/associations/builder/collection_association.rb +10 -33
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +52 -66
- data/lib/active_record/associations/builder/has_many.rb +8 -4
- data/lib/active_record/associations/builder/has_one.rb +46 -5
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +134 -286
- data/lib/active_record/associations/collection_proxy.rb +241 -146
- data/lib/active_record/associations/foreign_association.rb +10 -1
- data/lib/active_record/associations/has_many_association.rb +34 -97
- data/lib/active_record/associations/has_many_through_association.rb +60 -87
- data/lib/active_record/associations/has_one_association.rb +61 -49
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency.rb +137 -167
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -88
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/preloader.rb +90 -92
- data/lib/active_record/associations/preloader/association.rb +90 -123
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/singular_association.rb +18 -39
- data/lib/active_record/associations/through_association.rb +38 -18
- data/lib/active_record/attribute_assignment.rb +56 -183
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods.rb +120 -135
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -8
- data/lib/active_record/attribute_methods/dirty.rb +174 -144
- data/lib/active_record/attribute_methods/primary_key.rb +91 -83
- data/lib/active_record/attribute_methods/query.rb +6 -5
- data/lib/active_record/attribute_methods/read.rb +20 -76
- data/lib/active_record/attribute_methods/serialization.rb +40 -20
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
- data/lib/active_record/attribute_methods/write.rb +32 -54
- data/lib/active_record/attributes.rb +214 -82
- data/lib/active_record/autosave_association.rb +91 -37
- data/lib/active_record/base.rb +57 -45
- data/lib/active_record/callbacks.rb +100 -74
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +796 -296
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -115
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +170 -53
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +356 -227
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +664 -244
- data/lib/active_record/connection_adapters/abstract/transaction.rb +191 -83
- data/lib/active_record/connection_adapters/abstract_adapter.rb +460 -204
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +510 -627
- data/lib/active_record/connection_adapters/column.rb +56 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +174 -152
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +58 -188
- data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -114
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +10 -5
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +470 -290
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +551 -356
- data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -345
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +176 -41
- data/lib/active_record/core.rb +251 -231
- data/lib/active_record/counter_cache.rb +67 -49
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +163 -86
- data/lib/active_record/errors.rb +188 -53
- data/lib/active_record/explain.rb +23 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +10 -5
- data/lib/active_record/fixture_set/file.rb +35 -9
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +228 -499
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +158 -112
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +123 -29
- data/lib/active_record/internal_metadata.rb +53 -0
- data/lib/active_record/legacy_yaml_adapter.rb +21 -3
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +87 -96
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +76 -33
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +626 -283
- data/lib/active_record/migration/command_recorder.rb +177 -90
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/model_schema.rb +314 -112
- data/lib/active_record/nested_attributes.rb +264 -222
- data/lib/active_record/no_touching.rb +14 -1
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +557 -125
- data/lib/active_record/query_cache.rb +19 -23
- data/lib/active_record/querying.rb +43 -29
- data/lib/active_record/railtie.rb +147 -46
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +330 -197
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +428 -279
- data/lib/active_record/relation.rb +518 -341
- data/lib/active_record/relation/batches.rb +207 -55
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/calculations.rb +267 -253
- data/lib/active_record/relation/delegation.rb +70 -80
- data/lib/active_record/relation/finder_methods.rb +277 -241
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +78 -87
- data/lib/active_record/relation/predicate_builder.rb +114 -119
- data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -26
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +575 -394
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -13
- data/lib/active_record/relation/where_clause.rb +190 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/result.rb +79 -42
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +144 -121
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +112 -93
- data/lib/active_record/schema_migration.rb +24 -17
- data/lib/active_record/scoping.rb +45 -26
- data/lib/active_record/scoping/default.rb +101 -85
- data/lib/active_record/scoping/named.rb +86 -33
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/statement_cache.rb +73 -36
- data/lib/active_record/store.rb +127 -42
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +75 -0
- data/lib/active_record/tasks/database_tasks.rb +308 -99
- data/lib/active_record/tasks/mysql_database_tasks.rb +55 -99
- data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +38 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +86 -40
- data/lib/active_record/touch_later.rb +66 -0
- data/lib/active_record/transactions.rb +216 -150
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type.rb +78 -23
- data/lib/active_record/type/adapter_specific_registry.rb +129 -0
- data/lib/active_record/type/date.rb +4 -45
- data/lib/active_record/type/date_time.rb +4 -49
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +24 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +11 -16
- data/lib/active_record/type/type_map.rb +15 -17
- data/lib/active_record/type/unsigned_integer.rb +9 -7
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -0
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +13 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +42 -55
- data/lib/active_record/version.rb +3 -1
- data/lib/arel.rb +51 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record.rb +7 -5
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration.rb +31 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +19 -22
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +164 -60
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -163
- data/lib/active_record/attribute_set.rb +0 -81
- data/lib/active_record/attribute_set/builder.rb +0 -106
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -58
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -110
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,13 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
class TransactionState
|
4
|
-
attr_reader :parent
|
5
|
-
|
6
|
-
VALID_STATES = Set.new([:committed, :rolledback, nil])
|
7
|
-
|
8
6
|
def initialize(state = nil)
|
9
7
|
@state = state
|
10
|
-
@
|
8
|
+
@children = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_child(state)
|
12
|
+
@children << state
|
11
13
|
end
|
12
14
|
|
13
15
|
def finalized?
|
@@ -15,27 +17,55 @@ module ActiveRecord
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def committed?
|
18
|
-
@state == :committed
|
20
|
+
@state == :committed || @state == :fully_committed
|
21
|
+
end
|
22
|
+
|
23
|
+
def fully_committed?
|
24
|
+
@state == :fully_committed
|
19
25
|
end
|
20
26
|
|
21
27
|
def rolledback?
|
22
|
-
@state == :rolledback
|
28
|
+
@state == :rolledback || @state == :fully_rolledback
|
29
|
+
end
|
30
|
+
|
31
|
+
def fully_rolledback?
|
32
|
+
@state == :fully_rolledback
|
33
|
+
end
|
34
|
+
|
35
|
+
def fully_completed?
|
36
|
+
completed?
|
23
37
|
end
|
24
38
|
|
25
39
|
def completed?
|
26
40
|
committed? || rolledback?
|
27
41
|
end
|
28
42
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
43
|
+
def rollback!
|
44
|
+
@children.each { |c| c.rollback! }
|
45
|
+
@state = :rolledback
|
46
|
+
end
|
47
|
+
|
48
|
+
def full_rollback!
|
49
|
+
@children.each { |c| c.rollback! }
|
50
|
+
@state = :fully_rolledback
|
51
|
+
end
|
52
|
+
|
53
|
+
def commit!
|
54
|
+
@state = :committed
|
55
|
+
end
|
56
|
+
|
57
|
+
def full_commit!
|
58
|
+
@state = :fully_committed
|
59
|
+
end
|
60
|
+
|
61
|
+
def nullify!
|
62
|
+
@state = nil
|
34
63
|
end
|
35
64
|
end
|
36
65
|
|
37
66
|
class NullTransaction #:nodoc:
|
38
67
|
def initialize; end
|
68
|
+
def state; end
|
39
69
|
def closed?; true; end
|
40
70
|
def open?; false; end
|
41
71
|
def joinable?; false; end
|
@@ -43,59 +73,65 @@ module ActiveRecord
|
|
43
73
|
end
|
44
74
|
|
45
75
|
class Transaction #:nodoc:
|
76
|
+
attr_reader :connection, :state, :records, :savepoint_name, :isolation_level
|
46
77
|
|
47
|
-
|
48
|
-
attr_writer :joinable
|
49
|
-
|
50
|
-
def initialize(connection, options)
|
78
|
+
def initialize(connection, options, run_commit_callbacks: false)
|
51
79
|
@connection = connection
|
52
80
|
@state = TransactionState.new
|
53
81
|
@records = []
|
82
|
+
@isolation_level = options[:isolation]
|
83
|
+
@materialized = false
|
54
84
|
@joinable = options.fetch(:joinable, true)
|
85
|
+
@run_commit_callbacks = run_commit_callbacks
|
55
86
|
end
|
56
87
|
|
57
88
|
def add_record(record)
|
58
89
|
records << record
|
59
90
|
end
|
60
91
|
|
61
|
-
def
|
62
|
-
@
|
92
|
+
def materialize!
|
93
|
+
@materialized = true
|
94
|
+
end
|
95
|
+
|
96
|
+
def materialized?
|
97
|
+
@materialized
|
63
98
|
end
|
64
99
|
|
65
100
|
def rollback_records
|
66
|
-
ite = records.uniq
|
101
|
+
ite = records.uniq(&:object_id)
|
102
|
+
already_run_callbacks = {}
|
67
103
|
while record = ite.shift
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
record.logger.error(e) if record.respond_to?(:logger) && record.logger
|
73
|
-
end
|
104
|
+
trigger_callbacks = record.trigger_transactional_callbacks?
|
105
|
+
should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
|
106
|
+
already_run_callbacks[record] ||= trigger_callbacks
|
107
|
+
record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
|
74
108
|
end
|
75
109
|
ensure
|
76
110
|
ite.each do |i|
|
77
|
-
i.rolledback!(full_rollback?, false)
|
111
|
+
i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
|
78
112
|
end
|
79
113
|
end
|
80
114
|
|
81
|
-
def
|
82
|
-
|
115
|
+
def before_commit_records
|
116
|
+
records.uniq.each(&:before_committed!) if @run_commit_callbacks
|
83
117
|
end
|
84
118
|
|
85
119
|
def commit_records
|
86
|
-
ite = records.uniq
|
120
|
+
ite = records.uniq(&:object_id)
|
121
|
+
already_run_callbacks = {}
|
87
122
|
while record = ite.shift
|
88
|
-
|
89
|
-
record.
|
90
|
-
|
91
|
-
|
92
|
-
record.
|
123
|
+
if @run_commit_callbacks
|
124
|
+
trigger_callbacks = record.trigger_transactional_callbacks?
|
125
|
+
should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
|
126
|
+
already_run_callbacks[record] ||= trigger_callbacks
|
127
|
+
record.committed!(should_run_callbacks: should_run_callbacks)
|
128
|
+
else
|
129
|
+
# if not running callbacks, only adds the record to the parent transaction
|
130
|
+
connection.add_transaction_record(record)
|
93
131
|
end
|
94
132
|
end
|
95
133
|
ensure
|
96
|
-
ite.each
|
97
|
-
i.committed!(false)
|
98
|
-
end
|
134
|
+
ite.each { |i| i.committed!(should_run_callbacks: false) }
|
99
135
|
end
|
100
136
|
|
101
137
|
def full_rollback?; true; end
|
@@ -105,52 +141,55 @@ module ActiveRecord
|
|
105
141
|
end
|
106
142
|
|
107
143
|
class SavepointTransaction < Transaction
|
144
|
+
def initialize(connection, savepoint_name, parent_transaction, *args)
|
145
|
+
super(connection, *args)
|
108
146
|
|
109
|
-
|
110
|
-
|
111
|
-
if
|
147
|
+
parent_transaction.state.add_child(@state)
|
148
|
+
|
149
|
+
if isolation_level
|
112
150
|
raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
|
113
151
|
end
|
114
|
-
|
152
|
+
|
153
|
+
@savepoint_name = savepoint_name
|
115
154
|
end
|
116
155
|
|
117
|
-
def
|
118
|
-
connection.
|
156
|
+
def materialize!
|
157
|
+
connection.create_savepoint(savepoint_name)
|
119
158
|
super
|
120
|
-
|
159
|
+
end
|
160
|
+
|
161
|
+
def rollback
|
162
|
+
connection.rollback_to_savepoint(savepoint_name) if materialized?
|
163
|
+
@state.rollback!
|
121
164
|
end
|
122
165
|
|
123
166
|
def commit
|
124
|
-
connection.release_savepoint(savepoint_name)
|
125
|
-
|
126
|
-
parent = connection.transaction_manager.current_transaction
|
127
|
-
records.each { |r| parent.add_record(r) }
|
167
|
+
connection.release_savepoint(savepoint_name) if materialized?
|
168
|
+
@state.commit!
|
128
169
|
end
|
129
170
|
|
130
171
|
def full_rollback?; false; end
|
131
172
|
end
|
132
173
|
|
133
174
|
class RealTransaction < Transaction
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
if options[:isolation]
|
138
|
-
connection.begin_isolated_db_transaction(options[:isolation])
|
175
|
+
def materialize!
|
176
|
+
if isolation_level
|
177
|
+
connection.begin_isolated_db_transaction(isolation_level)
|
139
178
|
else
|
140
179
|
connection.begin_db_transaction
|
141
180
|
end
|
181
|
+
|
182
|
+
super
|
142
183
|
end
|
143
184
|
|
144
185
|
def rollback
|
145
|
-
connection.rollback_db_transaction
|
146
|
-
|
147
|
-
rollback_records
|
186
|
+
connection.rollback_db_transaction if materialized?
|
187
|
+
@state.full_rollback!
|
148
188
|
end
|
149
189
|
|
150
190
|
def commit
|
151
|
-
connection.commit_db_transaction
|
152
|
-
|
153
|
-
commit_records
|
191
|
+
connection.commit_db_transaction if materialized?
|
192
|
+
@state.full_commit!
|
154
193
|
end
|
155
194
|
end
|
156
195
|
|
@@ -158,43 +197,104 @@ module ActiveRecord
|
|
158
197
|
def initialize(connection)
|
159
198
|
@stack = []
|
160
199
|
@connection = connection
|
200
|
+
@has_unmaterialized_transactions = false
|
201
|
+
@materializing_transactions = false
|
202
|
+
@lazy_transactions_enabled = true
|
161
203
|
end
|
162
204
|
|
163
205
|
def begin_transaction(options = {})
|
164
|
-
|
165
|
-
|
166
|
-
|
206
|
+
@connection.lock.synchronize do
|
207
|
+
run_commit_callbacks = !current_transaction.joinable?
|
208
|
+
transaction =
|
209
|
+
if @stack.empty?
|
210
|
+
RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks)
|
211
|
+
else
|
212
|
+
SavepointTransaction.new(@connection, "active_record_#{@stack.size}", @stack.last, options,
|
213
|
+
run_commit_callbacks: run_commit_callbacks)
|
214
|
+
end
|
215
|
+
|
216
|
+
if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && options[:_lazy] != false
|
217
|
+
@has_unmaterialized_transactions = true
|
167
218
|
else
|
168
|
-
|
219
|
+
transaction.materialize!
|
220
|
+
end
|
221
|
+
@stack.push(transaction)
|
222
|
+
transaction
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def disable_lazy_transactions!
|
227
|
+
materialize_transactions
|
228
|
+
@lazy_transactions_enabled = false
|
229
|
+
end
|
230
|
+
|
231
|
+
def enable_lazy_transactions!
|
232
|
+
@lazy_transactions_enabled = true
|
233
|
+
end
|
234
|
+
|
235
|
+
def lazy_transactions_enabled?
|
236
|
+
@lazy_transactions_enabled
|
237
|
+
end
|
238
|
+
|
239
|
+
def materialize_transactions
|
240
|
+
return if @materializing_transactions
|
241
|
+
return unless @has_unmaterialized_transactions
|
242
|
+
|
243
|
+
@connection.lock.synchronize do
|
244
|
+
begin
|
245
|
+
@materializing_transactions = true
|
246
|
+
@stack.each { |t| t.materialize! unless t.materialized? }
|
247
|
+
ensure
|
248
|
+
@materializing_transactions = false
|
169
249
|
end
|
170
|
-
|
171
|
-
|
250
|
+
@has_unmaterialized_transactions = false
|
251
|
+
end
|
172
252
|
end
|
173
253
|
|
174
254
|
def commit_transaction
|
175
|
-
@
|
255
|
+
@connection.lock.synchronize do
|
256
|
+
transaction = @stack.last
|
257
|
+
|
258
|
+
begin
|
259
|
+
transaction.before_commit_records
|
260
|
+
ensure
|
261
|
+
@stack.pop
|
262
|
+
end
|
263
|
+
|
264
|
+
transaction.commit
|
265
|
+
transaction.commit_records
|
266
|
+
end
|
176
267
|
end
|
177
268
|
|
178
|
-
def rollback_transaction
|
179
|
-
@
|
269
|
+
def rollback_transaction(transaction = nil)
|
270
|
+
@connection.lock.synchronize do
|
271
|
+
transaction ||= @stack.pop
|
272
|
+
transaction.rollback
|
273
|
+
transaction.rollback_records
|
274
|
+
end
|
180
275
|
end
|
181
276
|
|
182
277
|
def within_new_transaction(options = {})
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
278
|
+
@connection.lock.synchronize do
|
279
|
+
transaction = begin_transaction options
|
280
|
+
yield
|
281
|
+
rescue Exception => error
|
282
|
+
if transaction
|
283
|
+
rollback_transaction
|
284
|
+
after_failure_actions(transaction, error)
|
285
|
+
end
|
286
|
+
raise
|
287
|
+
ensure
|
288
|
+
if !error && transaction
|
289
|
+
if Thread.current.status == "aborting"
|
290
|
+
rollback_transaction
|
291
|
+
else
|
292
|
+
begin
|
293
|
+
commit_transaction
|
294
|
+
rescue Exception
|
295
|
+
rollback_transaction(transaction) unless transaction.state.completed?
|
296
|
+
raise
|
297
|
+
end
|
198
298
|
end
|
199
299
|
end
|
200
300
|
end
|
@@ -209,7 +309,15 @@ module ActiveRecord
|
|
209
309
|
end
|
210
310
|
|
211
311
|
private
|
312
|
+
|
212
313
|
NULL_TRANSACTION = NullTransaction.new
|
314
|
+
|
315
|
+
# Deallocate invalidated prepared statements outside of the transaction
|
316
|
+
def after_failure_actions(transaction, error)
|
317
|
+
return unless transaction.is_a?(RealTransaction)
|
318
|
+
return unless error.is_a?(ActiveRecord::PreparedStatementCacheExpired)
|
319
|
+
@connection.clear_cache!
|
320
|
+
end
|
213
321
|
end
|
214
322
|
end
|
215
323
|
end
|
@@ -1,14 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/connection_adapters/determine_if_preparable_visitor"
|
4
|
+
require "active_record/connection_adapters/schema_cache"
|
5
|
+
require "active_record/connection_adapters/sql_type_metadata"
|
6
|
+
require "active_record/connection_adapters/abstract/schema_dumper"
|
7
|
+
require "active_record/connection_adapters/abstract/schema_creation"
|
8
|
+
require "active_support/concurrency/load_interlock_aware_monitor"
|
9
|
+
require "active_support/deprecation"
|
10
|
+
require "arel/collectors/bind"
|
11
|
+
require "arel/collectors/composite"
|
12
|
+
require "arel/collectors/sql_string"
|
13
|
+
require "arel/collectors/substitute_binds"
|
14
|
+
require "concurrent/atomic/thread_local_var"
|
12
15
|
|
13
16
|
module ActiveRecord
|
14
17
|
module ConnectionAdapters # :nodoc:
|
@@ -17,22 +20,22 @@ module ActiveRecord
|
|
17
20
|
autoload :Column
|
18
21
|
autoload :ConnectionSpecification
|
19
22
|
|
20
|
-
autoload_at
|
23
|
+
autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
|
21
24
|
autoload :IndexDefinition
|
22
25
|
autoload :ColumnDefinition
|
23
26
|
autoload :ChangeColumnDefinition
|
27
|
+
autoload :ForeignKeyDefinition
|
24
28
|
autoload :TableDefinition
|
25
29
|
autoload :Table
|
26
30
|
autoload :AlterTable
|
27
|
-
autoload :
|
31
|
+
autoload :ReferenceDefinition
|
28
32
|
end
|
29
33
|
|
30
|
-
autoload_at
|
34
|
+
autoload_at "active_record/connection_adapters/abstract/connection_pool" do
|
31
35
|
autoload :ConnectionHandler
|
32
|
-
autoload :ConnectionManagement
|
33
36
|
end
|
34
37
|
|
35
|
-
autoload_under
|
38
|
+
autoload_under "abstract" do
|
36
39
|
autoload :SchemaStatements
|
37
40
|
autoload :DatabaseStatements
|
38
41
|
autoload :DatabaseLimits
|
@@ -42,7 +45,7 @@ module ActiveRecord
|
|
42
45
|
autoload :Savepoints
|
43
46
|
end
|
44
47
|
|
45
|
-
autoload_at
|
48
|
+
autoload_at "active_record/connection_adapters/abstract/transaction" do
|
46
49
|
autoload :TransactionManager
|
47
50
|
autoload :NullTransaction
|
48
51
|
autoload :RealTransaction
|
@@ -54,34 +57,37 @@ module ActiveRecord
|
|
54
57
|
# related classes form the abstraction layer which makes this possible.
|
55
58
|
# An AbstractAdapter represents a connection to a database, and provides an
|
56
59
|
# abstract interface for database-specific functionality such as establishing
|
57
|
-
# a connection, escaping values, building the right SQL fragments for
|
58
|
-
# and
|
60
|
+
# a connection, escaping values, building the right SQL fragments for +:offset+
|
61
|
+
# and +:limit+ options, etc.
|
59
62
|
#
|
60
63
|
# All the concrete database adapters follow the interface laid down in this class.
|
61
|
-
# ActiveRecord::Base.connection returns an AbstractAdapter object, which
|
64
|
+
# {ActiveRecord::Base.connection}[rdoc-ref:ConnectionHandling#connection] returns an AbstractAdapter object, which
|
62
65
|
# you can use.
|
63
66
|
#
|
64
67
|
# Most of the methods in the adapter are useful during migrations. Most
|
65
|
-
# notably, the instance methods provided by
|
68
|
+
# notably, the instance methods provided by SchemaStatements are very useful.
|
66
69
|
class AbstractAdapter
|
67
|
-
ADAPTER_NAME =
|
70
|
+
ADAPTER_NAME = "Abstract"
|
71
|
+
include ActiveSupport::Callbacks
|
72
|
+
define_callbacks :checkout, :checkin
|
73
|
+
|
68
74
|
include Quoting, DatabaseStatements, SchemaStatements
|
69
75
|
include DatabaseLimits
|
70
76
|
include QueryCache
|
71
|
-
include
|
72
|
-
include MonitorMixin
|
73
|
-
include ColumnDumper
|
77
|
+
include Savepoints
|
74
78
|
|
75
79
|
SIMPLE_INT = /\A\d+\z/
|
76
80
|
|
77
|
-
|
78
|
-
|
79
|
-
attr_accessor :visitor, :pool
|
80
|
-
attr_reader :schema_cache, :owner, :logger
|
81
|
+
attr_accessor :pool
|
82
|
+
attr_reader :visitor, :owner, :logger, :lock
|
81
83
|
alias :in_use? :owner
|
82
84
|
|
85
|
+
set_callback :checkin, :after, :enable_lazy_transactions!
|
86
|
+
|
83
87
|
def self.type_cast_config_to_integer(config)
|
84
|
-
if config
|
88
|
+
if config.is_a?(Integer)
|
89
|
+
config
|
90
|
+
elsif SIMPLE_INT.match?(config)
|
85
91
|
config.to_i
|
86
92
|
else
|
87
93
|
config
|
@@ -96,83 +102,169 @@ module ActiveRecord
|
|
96
102
|
end
|
97
103
|
end
|
98
104
|
|
99
|
-
|
105
|
+
def self.build_read_query_regexp(*parts) # :nodoc:
|
106
|
+
parts = parts.map { |part| /\A[\(\s]*#{part}/i }
|
107
|
+
Regexp.union(*parts)
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.quoted_column_names # :nodoc:
|
111
|
+
@quoted_column_names ||= {}
|
112
|
+
end
|
100
113
|
|
101
|
-
def
|
114
|
+
def self.quoted_table_names # :nodoc:
|
115
|
+
@quoted_table_names ||= {}
|
116
|
+
end
|
117
|
+
|
118
|
+
def initialize(connection, logger = nil, config = {}) # :nodoc:
|
102
119
|
super()
|
103
120
|
|
104
121
|
@connection = connection
|
105
122
|
@owner = nil
|
106
123
|
@instrumenter = ActiveSupport::Notifications.instrumenter
|
107
124
|
@logger = logger
|
108
|
-
@
|
109
|
-
@
|
110
|
-
@
|
111
|
-
@
|
125
|
+
@config = config
|
126
|
+
@pool = ActiveRecord::ConnectionAdapters::NullPool.new
|
127
|
+
@idle_since = Concurrent.monotonic_time
|
128
|
+
@visitor = arel_visitor
|
129
|
+
@statements = build_statement_pool
|
130
|
+
@lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
|
131
|
+
|
132
|
+
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
|
133
|
+
@prepared_statement_status = Concurrent::ThreadLocalVar.new(true)
|
134
|
+
@visitor.extend(DetermineIfPreparableVisitor)
|
135
|
+
else
|
136
|
+
@prepared_statement_status = Concurrent::ThreadLocalVar.new(false)
|
137
|
+
end
|
138
|
+
|
139
|
+
@advisory_locks_enabled = self.class.type_cast_config_to_boolean(
|
140
|
+
config.fetch(:advisory_locks, true)
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
def replica?
|
145
|
+
@config[:replica] || false
|
146
|
+
end
|
147
|
+
|
148
|
+
# Determines whether writes are currently being prevents.
|
149
|
+
#
|
150
|
+
# Returns true if the connection is a replica, or if +prevent_writes+
|
151
|
+
# is set to true.
|
152
|
+
def preventing_writes?
|
153
|
+
replica? || ActiveRecord::Base.connection_handler.prevent_writes
|
154
|
+
end
|
155
|
+
|
156
|
+
def migrations_paths # :nodoc:
|
157
|
+
@config[:migrations_paths] || Migrator.migrations_paths
|
158
|
+
end
|
159
|
+
|
160
|
+
def migration_context # :nodoc:
|
161
|
+
MigrationContext.new(migrations_paths, schema_migration)
|
162
|
+
end
|
163
|
+
|
164
|
+
def schema_migration # :nodoc:
|
165
|
+
@schema_migration ||= begin
|
166
|
+
conn = self
|
167
|
+
spec_name = conn.pool.spec.name
|
168
|
+
name = "#{spec_name}::SchemaMigration"
|
169
|
+
|
170
|
+
Class.new(ActiveRecord::SchemaMigration) do
|
171
|
+
define_singleton_method(:name) { name }
|
172
|
+
define_singleton_method(:to_s) { name }
|
173
|
+
|
174
|
+
self.connection_specification_name = spec_name
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def prepared_statements
|
180
|
+
@prepared_statement_status.value
|
112
181
|
end
|
113
182
|
|
114
183
|
class Version
|
115
184
|
include Comparable
|
116
185
|
|
117
|
-
|
118
|
-
|
186
|
+
attr_reader :full_version_string
|
187
|
+
|
188
|
+
def initialize(version_string, full_version_string = nil)
|
189
|
+
@version = version_string.split(".").map(&:to_i)
|
190
|
+
@full_version_string = full_version_string
|
119
191
|
end
|
120
192
|
|
121
193
|
def <=>(version_string)
|
122
|
-
@version <=> version_string.split(
|
194
|
+
@version <=> version_string.split(".").map(&:to_i)
|
123
195
|
end
|
124
|
-
end
|
125
196
|
|
126
|
-
|
127
|
-
|
128
|
-
super(bvs.map { |bv| conn.quote(*bv.reverse) })
|
197
|
+
def to_s
|
198
|
+
@version.join(".")
|
129
199
|
end
|
130
200
|
end
|
131
201
|
|
132
|
-
|
133
|
-
|
134
|
-
super(bvs)
|
135
|
-
end
|
202
|
+
def valid_type?(type) # :nodoc:
|
203
|
+
!native_database_types[type].nil?
|
136
204
|
end
|
137
205
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
206
|
+
# this method must only be called while holding connection pool's mutex
|
207
|
+
def lease
|
208
|
+
if in_use?
|
209
|
+
msg = +"Cannot lease connection, "
|
210
|
+
if @owner == Thread.current
|
211
|
+
msg << "it is already leased by the current thread."
|
212
|
+
else
|
213
|
+
msg << "it is already in use by a different thread: #{@owner}. " \
|
214
|
+
"Current thread: #{Thread.current}."
|
215
|
+
end
|
216
|
+
raise ActiveRecordError, msg
|
143
217
|
end
|
218
|
+
|
219
|
+
@owner = Thread.current
|
144
220
|
end
|
145
221
|
|
146
|
-
def
|
147
|
-
|
222
|
+
def schema_cache
|
223
|
+
@pool.get_schema_cache(self)
|
148
224
|
end
|
149
225
|
|
150
|
-
def
|
151
|
-
|
226
|
+
def schema_cache=(cache)
|
227
|
+
cache.connection = self
|
228
|
+
@pool.set_schema_cache(cache)
|
152
229
|
end
|
153
230
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
231
|
+
# this method must only be called while holding connection pool's mutex
|
232
|
+
def expire
|
233
|
+
if in_use?
|
234
|
+
if @owner != Thread.current
|
235
|
+
raise ActiveRecordError, "Cannot expire connection, " \
|
236
|
+
"it is owned by a different thread: #{@owner}. " \
|
237
|
+
"Current thread: #{Thread.current}."
|
158
238
|
end
|
239
|
+
|
240
|
+
@idle_since = Concurrent.monotonic_time
|
241
|
+
@owner = nil
|
242
|
+
else
|
243
|
+
raise ActiveRecordError, "Cannot expire connection, it is not currently leased."
|
159
244
|
end
|
160
245
|
end
|
161
246
|
|
162
|
-
|
163
|
-
|
164
|
-
|
247
|
+
# this method must only be called while holding connection pool's mutex (and a desire for segfaults)
|
248
|
+
def steal! # :nodoc:
|
249
|
+
if in_use?
|
250
|
+
if @owner != Thread.current
|
251
|
+
pool.send :remove_connection_from_thread_cache, self, @owner
|
252
|
+
|
253
|
+
@owner = Thread.current
|
254
|
+
end
|
255
|
+
else
|
256
|
+
raise ActiveRecordError, "Cannot steal connection, it is not currently leased."
|
257
|
+
end
|
165
258
|
end
|
166
259
|
|
167
|
-
|
168
|
-
|
260
|
+
# Seconds since this connection was returned to the pool
|
261
|
+
def seconds_idle # :nodoc:
|
262
|
+
return 0 if in_use?
|
263
|
+
Concurrent.monotonic_time - @idle_since
|
169
264
|
end
|
170
265
|
|
171
266
|
def unprepared_statement
|
172
|
-
|
173
|
-
yield
|
174
|
-
ensure
|
175
|
-
@prepared_statements = old_prepared_statements
|
267
|
+
@prepared_statement_status.bind(false) { yield }
|
176
268
|
end
|
177
269
|
|
178
270
|
# Returns the human-readable name of the adapter. Use mixed case - one
|
@@ -181,15 +273,9 @@ module ActiveRecord
|
|
181
273
|
self.class::ADAPTER_NAME
|
182
274
|
end
|
183
275
|
|
184
|
-
# Does this adapter
|
185
|
-
def
|
186
|
-
|
187
|
-
end
|
188
|
-
|
189
|
-
# Can this adapter determine the primary key for tables not attached
|
190
|
-
# to an Active Record class, such as join tables?
|
191
|
-
def supports_primary_key?
|
192
|
-
false
|
276
|
+
# Does the database for this adapter exist?
|
277
|
+
def self.database_exists?(config)
|
278
|
+
raise NotImplementedError
|
193
279
|
end
|
194
280
|
|
195
281
|
# Does this adapter support DDL rollbacks in transactions? That is, would
|
@@ -207,6 +293,11 @@ module ActiveRecord
|
|
207
293
|
false
|
208
294
|
end
|
209
295
|
|
296
|
+
# Does this adapter support application-enforced advisory locking?
|
297
|
+
def supports_advisory_locks?
|
298
|
+
false
|
299
|
+
end
|
300
|
+
|
210
301
|
# Should primary key values be selected from their corresponding
|
211
302
|
# sequence before the insert statement? If true, next_sequence_value
|
212
303
|
# is called before each insert to set the record's primary key.
|
@@ -224,6 +315,11 @@ module ActiveRecord
|
|
224
315
|
false
|
225
316
|
end
|
226
317
|
|
318
|
+
# Does this adapter support expression indices?
|
319
|
+
def supports_expression_index?
|
320
|
+
false
|
321
|
+
end
|
322
|
+
|
227
323
|
# Does this adapter support explain?
|
228
324
|
def supports_explain?
|
229
325
|
false
|
@@ -250,11 +346,89 @@ module ActiveRecord
|
|
250
346
|
false
|
251
347
|
end
|
252
348
|
|
349
|
+
# Does this adapter support creating invalid constraints?
|
350
|
+
def supports_validate_constraints?
|
351
|
+
false
|
352
|
+
end
|
353
|
+
|
354
|
+
# Does this adapter support creating foreign key constraints
|
355
|
+
# in the same statement as creating the table?
|
356
|
+
def supports_foreign_keys_in_create?
|
357
|
+
supports_foreign_keys?
|
358
|
+
end
|
359
|
+
deprecate :supports_foreign_keys_in_create?
|
360
|
+
|
253
361
|
# Does this adapter support views?
|
254
362
|
def supports_views?
|
255
363
|
false
|
256
364
|
end
|
257
365
|
|
366
|
+
# Does this adapter support materialized views?
|
367
|
+
def supports_materialized_views?
|
368
|
+
false
|
369
|
+
end
|
370
|
+
|
371
|
+
# Does this adapter support datetime with precision?
|
372
|
+
def supports_datetime_with_precision?
|
373
|
+
false
|
374
|
+
end
|
375
|
+
|
376
|
+
# Does this adapter support json data type?
|
377
|
+
def supports_json?
|
378
|
+
false
|
379
|
+
end
|
380
|
+
|
381
|
+
# Does this adapter support metadata comments on database objects (tables, columns, indexes)?
|
382
|
+
def supports_comments?
|
383
|
+
false
|
384
|
+
end
|
385
|
+
|
386
|
+
# Can comments for tables, columns, and indexes be specified in create/alter table statements?
|
387
|
+
def supports_comments_in_create?
|
388
|
+
false
|
389
|
+
end
|
390
|
+
|
391
|
+
# Does this adapter support multi-value insert?
|
392
|
+
def supports_multi_insert?
|
393
|
+
true
|
394
|
+
end
|
395
|
+
deprecate :supports_multi_insert?
|
396
|
+
|
397
|
+
# Does this adapter support virtual columns?
|
398
|
+
def supports_virtual_columns?
|
399
|
+
false
|
400
|
+
end
|
401
|
+
|
402
|
+
# Does this adapter support foreign/external tables?
|
403
|
+
def supports_foreign_tables?
|
404
|
+
false
|
405
|
+
end
|
406
|
+
|
407
|
+
# Does this adapter support optimizer hints?
|
408
|
+
def supports_optimizer_hints?
|
409
|
+
false
|
410
|
+
end
|
411
|
+
|
412
|
+
def supports_lazy_transactions?
|
413
|
+
false
|
414
|
+
end
|
415
|
+
|
416
|
+
def supports_insert_returning?
|
417
|
+
false
|
418
|
+
end
|
419
|
+
|
420
|
+
def supports_insert_on_duplicate_skip?
|
421
|
+
false
|
422
|
+
end
|
423
|
+
|
424
|
+
def supports_insert_on_duplicate_update?
|
425
|
+
false
|
426
|
+
end
|
427
|
+
|
428
|
+
def supports_insert_conflict_target?
|
429
|
+
false
|
430
|
+
end
|
431
|
+
|
258
432
|
# This is meant to be implemented by the adapters that support extensions
|
259
433
|
def disable_extension(name)
|
260
434
|
end
|
@@ -263,6 +437,24 @@ module ActiveRecord
|
|
263
437
|
def enable_extension(name)
|
264
438
|
end
|
265
439
|
|
440
|
+
def advisory_locks_enabled? # :nodoc:
|
441
|
+
supports_advisory_locks? && @advisory_locks_enabled
|
442
|
+
end
|
443
|
+
|
444
|
+
# This is meant to be implemented by the adapters that support advisory
|
445
|
+
# locks
|
446
|
+
#
|
447
|
+
# Return true if we got the lock, otherwise false
|
448
|
+
def get_advisory_lock(lock_id) # :nodoc:
|
449
|
+
end
|
450
|
+
|
451
|
+
# This is meant to be implemented by the adapters that support advisory
|
452
|
+
# locks.
|
453
|
+
#
|
454
|
+
# Return true if we released the lock, otherwise false
|
455
|
+
def release_advisory_lock(lock_id) # :nodoc:
|
456
|
+
end
|
457
|
+
|
266
458
|
# A list of extensions, to be filled in by adapters that support them.
|
267
459
|
def extensions
|
268
460
|
[]
|
@@ -273,14 +465,6 @@ module ActiveRecord
|
|
273
465
|
{}
|
274
466
|
end
|
275
467
|
|
276
|
-
# QUOTING ==================================================
|
277
|
-
|
278
|
-
# Returns a bind substitution value given a bind +column+
|
279
|
-
# NOTE: The column param is currently being used by the sqlserver-adapter
|
280
|
-
def substitute_at(column, _unused = 0)
|
281
|
-
Arel::Nodes::BindParam.new
|
282
|
-
end
|
283
|
-
|
284
468
|
# REFERENTIAL INTEGRITY ====================================
|
285
469
|
|
286
470
|
# Override to turn off referential integrity while executing <tt>&block</tt>.
|
@@ -311,6 +495,22 @@ module ActiveRecord
|
|
311
495
|
reset_transaction
|
312
496
|
end
|
313
497
|
|
498
|
+
# Immediately forget this connection ever existed. Unlike disconnect!,
|
499
|
+
# this will not communicate with the server.
|
500
|
+
#
|
501
|
+
# After calling this method, the behavior of all other methods becomes
|
502
|
+
# undefined. This is called internally just before a forked process gets
|
503
|
+
# rid of a connection that belonged to its parent.
|
504
|
+
def discard!
|
505
|
+
# This should be overridden by concrete adapters.
|
506
|
+
#
|
507
|
+
# Prevent @connection's finalizer from touching the socket, or
|
508
|
+
# otherwise communicating with its server, when it is collected.
|
509
|
+
if schema_cache.connection == self
|
510
|
+
schema_cache.connection = nil
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
314
514
|
# Reset the state of this connection, directing the DBMS to clear
|
315
515
|
# transactions and other connection-related server-side state. Usually a
|
316
516
|
# database-dependent operation.
|
@@ -321,11 +521,9 @@ module ActiveRecord
|
|
321
521
|
# this should be overridden by concrete adapters
|
322
522
|
end
|
323
523
|
|
324
|
-
|
325
|
-
# Clear any caching the database adapter may be doing, for example
|
326
|
-
# clearing the prepared statement cache. This is database specific.
|
524
|
+
# Clear any caching the database adapter may be doing.
|
327
525
|
def clear_cache!
|
328
|
-
|
526
|
+
@lock.synchronize { @statements.clear } if @statements
|
329
527
|
end
|
330
528
|
|
331
529
|
# Returns true if its required to reload the connection between requests for development mode.
|
@@ -334,172 +532,230 @@ module ActiveRecord
|
|
334
532
|
end
|
335
533
|
|
336
534
|
# Checks whether the connection to the database is still active (i.e. not stale).
|
337
|
-
# This is done under the hood by calling
|
535
|
+
# This is done under the hood by calling #active?. If the connection
|
338
536
|
# is no longer active, then this method will reconnect to the database.
|
339
|
-
def verify!
|
537
|
+
def verify!
|
340
538
|
reconnect! unless active?
|
341
539
|
end
|
342
540
|
|
343
541
|
# Provides access to the underlying database driver for this adapter. For
|
344
|
-
# example, this method returns a
|
345
|
-
# and a
|
542
|
+
# example, this method returns a Mysql2::Client object in case of Mysql2Adapter,
|
543
|
+
# and a PG::Connection object in case of PostgreSQLAdapter.
|
346
544
|
#
|
347
545
|
# This is useful for when you need to call a proprietary method such as
|
348
546
|
# PostgreSQL's lo_* methods.
|
349
547
|
def raw_connection
|
548
|
+
disable_lazy_transactions!
|
350
549
|
@connection
|
351
550
|
end
|
352
551
|
|
353
|
-
def
|
354
|
-
|
355
|
-
|
356
|
-
def release_savepoint(name = nil)
|
552
|
+
def default_uniqueness_comparison(attribute, value, klass) # :nodoc:
|
553
|
+
attribute.eq(value)
|
357
554
|
end
|
358
555
|
|
359
|
-
def
|
360
|
-
|
556
|
+
def case_sensitive_comparison(attribute, value) # :nodoc:
|
557
|
+
attribute.eq(value)
|
361
558
|
end
|
362
559
|
|
363
|
-
def
|
364
|
-
|
365
|
-
value = case_sensitive_modifier(value, table_attr) unless value.nil?
|
366
|
-
table_attr.eq(value)
|
367
|
-
end
|
560
|
+
def case_insensitive_comparison(attribute, value) # :nodoc:
|
561
|
+
column = column_for_attribute(attribute)
|
368
562
|
|
369
|
-
|
370
|
-
|
563
|
+
if can_perform_case_insensitive_comparison_for?(column)
|
564
|
+
attribute.lower.eq(attribute.relation.lower(value))
|
565
|
+
else
|
566
|
+
attribute.eq(value)
|
567
|
+
end
|
371
568
|
end
|
372
569
|
|
373
|
-
def
|
374
|
-
|
570
|
+
def can_perform_case_insensitive_comparison_for?(column)
|
571
|
+
true
|
375
572
|
end
|
573
|
+
private :can_perform_case_insensitive_comparison_for?
|
376
574
|
|
377
575
|
# Check the connection back in to the connection pool
|
378
576
|
def close
|
379
577
|
pool.checkin self
|
380
578
|
end
|
381
579
|
|
382
|
-
def
|
383
|
-
|
384
|
-
|
580
|
+
def column_name_for_operation(operation, node) # :nodoc:
|
581
|
+
visitor.compile(node)
|
582
|
+
end
|
583
|
+
|
584
|
+
def default_index_type?(index) # :nodoc:
|
585
|
+
index.using.nil?
|
586
|
+
end
|
587
|
+
|
588
|
+
# Called by ActiveRecord::InsertAll,
|
589
|
+
# Passed an instance of ActiveRecord::InsertAll::Builder,
|
590
|
+
# This method implements standard bulk inserts for all databases, but
|
591
|
+
# should be overridden by adapters to implement common features with
|
592
|
+
# non-standard syntax like handling duplicates or returning values.
|
593
|
+
def build_insert_sql(insert) # :nodoc:
|
594
|
+
if insert.skip_duplicates? || insert.update_duplicates?
|
595
|
+
raise NotImplementedError, "#{self.class} should define `build_insert_sql` to implement adapter-specific logic for handling duplicates during INSERT"
|
385
596
|
end
|
597
|
+
|
598
|
+
"INSERT #{insert.into} #{insert.values_list}"
|
386
599
|
end
|
387
600
|
|
388
|
-
def
|
389
|
-
Column.new(name, default, cast_type, sql_type, null)
|
601
|
+
def get_database_version # :nodoc:
|
390
602
|
end
|
391
603
|
|
392
|
-
def
|
393
|
-
|
604
|
+
def database_version # :nodoc:
|
605
|
+
schema_cache.database_version
|
394
606
|
end
|
395
607
|
|
396
|
-
def
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
register_class_with_limit m, %r(char)i, Type::String
|
405
|
-
register_class_with_limit m, %r(binary)i, Type::Binary
|
406
|
-
register_class_with_limit m, %r(text)i, Type::Text
|
407
|
-
register_class_with_limit m, %r(date)i, Type::Date
|
408
|
-
register_class_with_limit m, %r(time)i, Type::Time
|
409
|
-
register_class_with_limit m, %r(datetime)i, Type::DateTime
|
410
|
-
register_class_with_limit m, %r(float)i, Type::Float
|
411
|
-
register_class_with_limit m, %r(int)i, Type::Integer
|
412
|
-
|
413
|
-
m.alias_type %r(blob)i, 'binary'
|
414
|
-
m.alias_type %r(clob)i, 'text'
|
415
|
-
m.alias_type %r(timestamp)i, 'datetime'
|
416
|
-
m.alias_type %r(numeric)i, 'decimal'
|
417
|
-
m.alias_type %r(number)i, 'decimal'
|
418
|
-
m.alias_type %r(double)i, 'float'
|
419
|
-
|
420
|
-
m.register_type(%r(decimal)i) do |sql_type|
|
421
|
-
scale = extract_scale(sql_type)
|
422
|
-
precision = extract_precision(sql_type)
|
423
|
-
|
424
|
-
if scale == 0
|
425
|
-
# FIXME: Remove this class as well
|
426
|
-
Type::DecimalWithoutScale.new(precision: precision)
|
427
|
-
else
|
428
|
-
Type::Decimal.new(precision: precision, scale: scale)
|
608
|
+
def check_version # :nodoc:
|
609
|
+
end
|
610
|
+
|
611
|
+
private
|
612
|
+
|
613
|
+
def type_map
|
614
|
+
@type_map ||= Type::TypeMap.new.tap do |mapping|
|
615
|
+
initialize_type_map(mapping)
|
429
616
|
end
|
430
617
|
end
|
431
|
-
end
|
432
618
|
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
619
|
+
def initialize_type_map(m = type_map)
|
620
|
+
register_class_with_limit m, %r(boolean)i, Type::Boolean
|
621
|
+
register_class_with_limit m, %r(char)i, Type::String
|
622
|
+
register_class_with_limit m, %r(binary)i, Type::Binary
|
623
|
+
register_class_with_limit m, %r(text)i, Type::Text
|
624
|
+
register_class_with_precision m, %r(date)i, Type::Date
|
625
|
+
register_class_with_precision m, %r(time)i, Type::Time
|
626
|
+
register_class_with_precision m, %r(datetime)i, Type::DateTime
|
627
|
+
register_class_with_limit m, %r(float)i, Type::Float
|
628
|
+
register_class_with_limit m, %r(int)i, Type::Integer
|
629
|
+
|
630
|
+
m.alias_type %r(blob)i, "binary"
|
631
|
+
m.alias_type %r(clob)i, "text"
|
632
|
+
m.alias_type %r(timestamp)i, "datetime"
|
633
|
+
m.alias_type %r(numeric)i, "decimal"
|
634
|
+
m.alias_type %r(number)i, "decimal"
|
635
|
+
m.alias_type %r(double)i, "float"
|
636
|
+
|
637
|
+
m.register_type %r(^json)i, Type::Json.new
|
638
|
+
|
639
|
+
m.register_type(%r(decimal)i) do |sql_type|
|
640
|
+
scale = extract_scale(sql_type)
|
641
|
+
precision = extract_precision(sql_type)
|
642
|
+
|
643
|
+
if scale == 0
|
644
|
+
# FIXME: Remove this class as well
|
645
|
+
Type::DecimalWithoutScale.new(precision: precision)
|
646
|
+
else
|
647
|
+
Type::Decimal.new(precision: precision, scale: scale)
|
648
|
+
end
|
649
|
+
end
|
650
|
+
end
|
437
651
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
652
|
+
def reload_type_map
|
653
|
+
type_map.clear
|
654
|
+
initialize_type_map
|
655
|
+
end
|
656
|
+
|
657
|
+
def register_class_with_limit(mapping, key, klass)
|
658
|
+
mapping.register_type(key) do |*args|
|
659
|
+
limit = extract_limit(args.last)
|
660
|
+
klass.new(limit: limit)
|
661
|
+
end
|
442
662
|
end
|
443
|
-
end
|
444
663
|
|
445
|
-
|
446
|
-
|
664
|
+
def register_class_with_precision(mapping, key, klass)
|
665
|
+
mapping.register_type(key) do |*args|
|
666
|
+
precision = extract_precision(args.last)
|
667
|
+
klass.new(precision: precision)
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
def extract_scale(sql_type)
|
672
|
+
case sql_type
|
447
673
|
when /\((\d+)\)/ then 0
|
448
674
|
when /\((\d+)(,(\d+))\)/ then $3.to_i
|
675
|
+
end
|
449
676
|
end
|
450
|
-
end
|
451
677
|
|
452
|
-
|
453
|
-
|
454
|
-
|
678
|
+
def extract_precision(sql_type)
|
679
|
+
$1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
|
680
|
+
end
|
455
681
|
|
456
|
-
|
457
|
-
|
458
|
-
when /^bigint/i
|
459
|
-
8
|
460
|
-
when /\((.*)\)/
|
461
|
-
$1.to_i
|
682
|
+
def extract_limit(sql_type)
|
683
|
+
$1.to_i if sql_type =~ /\((.*)\)/
|
462
684
|
end
|
463
|
-
end
|
464
685
|
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
686
|
+
def translate_exception_class(e, sql, binds)
|
687
|
+
message = "#{e.class.name}: #{e.message}"
|
688
|
+
|
689
|
+
exception = translate_exception(
|
690
|
+
e, message: message, sql: sql, binds: binds
|
691
|
+
)
|
692
|
+
exception.set_backtrace e.backtrace
|
693
|
+
exception
|
470
694
|
end
|
471
695
|
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
696
|
+
def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil) # :doc:
|
697
|
+
@instrumenter.instrument(
|
698
|
+
"sql.active_record",
|
699
|
+
sql: sql,
|
700
|
+
name: name,
|
701
|
+
binds: binds,
|
702
|
+
type_casted_binds: type_casted_binds,
|
703
|
+
statement_name: statement_name,
|
704
|
+
connection_id: object_id,
|
705
|
+
connection: self) do
|
706
|
+
@lock.synchronize do
|
707
|
+
yield
|
708
|
+
end
|
709
|
+
rescue => e
|
710
|
+
raise translate_exception_class(e, sql, binds)
|
711
|
+
end
|
712
|
+
end
|
476
713
|
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
raise translate_exception_class(e, sql)
|
487
|
-
end
|
714
|
+
def translate_exception(exception, message:, sql:, binds:)
|
715
|
+
# override in derived class
|
716
|
+
case exception
|
717
|
+
when RuntimeError
|
718
|
+
exception
|
719
|
+
else
|
720
|
+
ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
|
721
|
+
end
|
722
|
+
end
|
488
723
|
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
end
|
724
|
+
def without_prepared_statement?(binds)
|
725
|
+
!prepared_statements || binds.empty?
|
726
|
+
end
|
493
727
|
|
494
|
-
|
495
|
-
|
496
|
-
|
728
|
+
def column_for(table_name, column_name)
|
729
|
+
column_name = column_name.to_s
|
730
|
+
columns(table_name).detect { |c| c.name == column_name } ||
|
731
|
+
raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
|
732
|
+
end
|
497
733
|
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
734
|
+
def column_for_attribute(attribute)
|
735
|
+
table_name = attribute.relation.name
|
736
|
+
schema_cache.columns_hash(table_name)[attribute.name.to_s]
|
737
|
+
end
|
738
|
+
|
739
|
+
def collector
|
740
|
+
if prepared_statements
|
741
|
+
Arel::Collectors::Composite.new(
|
742
|
+
Arel::Collectors::SQLString.new,
|
743
|
+
Arel::Collectors::Bind.new,
|
744
|
+
)
|
745
|
+
else
|
746
|
+
Arel::Collectors::SubstituteBinds.new(
|
747
|
+
self,
|
748
|
+
Arel::Collectors::SQLString.new,
|
749
|
+
)
|
750
|
+
end
|
751
|
+
end
|
752
|
+
|
753
|
+
def arel_visitor
|
754
|
+
Arel::Visitors::ToSql.new(self)
|
755
|
+
end
|
756
|
+
|
757
|
+
def build_statement_pool
|
758
|
+
end
|
503
759
|
end
|
504
760
|
end
|
505
761
|
end
|