activerecord 4.2.11.3 → 5.0.7.2
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.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +1638 -1132
 - data/MIT-LICENSE +2 -2
 - data/README.rdoc +7 -8
 - data/examples/performance.rb +2 -3
 - data/examples/simple.rb +0 -1
 - data/lib/active_record.rb +7 -2
 - data/lib/active_record/aggregations.rb +34 -21
 - data/lib/active_record/association_relation.rb +7 -4
 - data/lib/active_record/associations.rb +347 -218
 - data/lib/active_record/associations/alias_tracker.rb +19 -16
 - data/lib/active_record/associations/association.rb +22 -10
 - data/lib/active_record/associations/association_scope.rb +75 -104
 - data/lib/active_record/associations/belongs_to_association.rb +21 -32
 - data/lib/active_record/associations/builder/association.rb +28 -34
 - data/lib/active_record/associations/builder/belongs_to.rb +43 -18
 - data/lib/active_record/associations/builder/collection_association.rb +7 -19
 - data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +16 -11
 - data/lib/active_record/associations/builder/has_many.rb +4 -4
 - data/lib/active_record/associations/builder/has_one.rb +11 -6
 - data/lib/active_record/associations/builder/singular_association.rb +13 -11
 - data/lib/active_record/associations/collection_association.rb +85 -69
 - data/lib/active_record/associations/collection_proxy.rb +104 -46
 - data/lib/active_record/associations/foreign_association.rb +1 -1
 - data/lib/active_record/associations/has_many_association.rb +21 -78
 - data/lib/active_record/associations/has_many_through_association.rb +6 -47
 - data/lib/active_record/associations/has_one_association.rb +12 -5
 - data/lib/active_record/associations/join_dependency.rb +38 -22
 - data/lib/active_record/associations/join_dependency/join_association.rb +15 -14
 - data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
 - data/lib/active_record/associations/preloader.rb +14 -4
 - data/lib/active_record/associations/preloader/association.rb +52 -71
 - data/lib/active_record/associations/preloader/collection_association.rb +0 -7
 - data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
 - data/lib/active_record/associations/preloader/has_one.rb +0 -8
 - data/lib/active_record/associations/preloader/singular_association.rb +0 -1
 - data/lib/active_record/associations/preloader/through_association.rb +36 -17
 - data/lib/active_record/associations/singular_association.rb +13 -1
 - data/lib/active_record/associations/through_association.rb +12 -4
 - data/lib/active_record/attribute.rb +69 -19
 - data/lib/active_record/attribute/user_provided_default.rb +28 -0
 - data/lib/active_record/attribute_assignment.rb +19 -140
 - data/lib/active_record/attribute_decorators.rb +6 -5
 - data/lib/active_record/attribute_methods.rb +69 -44
 - data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
 - data/lib/active_record/attribute_methods/dirty.rb +46 -86
 - data/lib/active_record/attribute_methods/primary_key.rb +16 -3
 - data/lib/active_record/attribute_methods/query.rb +2 -2
 - data/lib/active_record/attribute_methods/read.rb +31 -59
 - data/lib/active_record/attribute_methods/serialization.rb +13 -16
 - data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
 - data/lib/active_record/attribute_methods/write.rb +13 -37
 - data/lib/active_record/attribute_mutation_tracker.rb +70 -0
 - data/lib/active_record/attribute_set.rb +32 -3
 - data/lib/active_record/attribute_set/builder.rb +42 -16
 - data/lib/active_record/attributes.rb +199 -81
 - data/lib/active_record/autosave_association.rb +54 -17
 - data/lib/active_record/base.rb +32 -23
 - data/lib/active_record/callbacks.rb +39 -43
 - data/lib/active_record/coders/json.rb +1 -1
 - data/lib/active_record/coders/yaml_column.rb +20 -8
 - data/lib/active_record/collection_cache_key.rb +50 -0
 - data/lib/active_record/connection_adapters/abstract/connection_pool.rb +467 -189
 - data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
 - data/lib/active_record/connection_adapters/abstract/database_statements.rb +66 -62
 - data/lib/active_record/connection_adapters/abstract/query_cache.rb +39 -4
 - data/lib/active_record/connection_adapters/abstract/quoting.rb +86 -13
 - data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
 - data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
 - data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -188
 - data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
 - data/lib/active_record/connection_adapters/abstract/schema_statements.rb +407 -156
 - data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
 - data/lib/active_record/connection_adapters/abstract_adapter.rb +177 -71
 - data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +433 -399
 - data/lib/active_record/connection_adapters/column.rb +28 -43
 - data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
 - data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
 - data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
 - data/lib/active_record/connection_adapters/mysql/database_statements.rb +108 -0
 - data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
 - data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
 - data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
 - data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
 - data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
 - data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
 - data/lib/active_record/connection_adapters/mysql2_adapter.rb +25 -166
 - data/lib/active_record/connection_adapters/postgresql/column.rb +33 -11
 - data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -72
 - data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
 - data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
 - data/lib/active_record/connection_adapters/postgresql/oid/array.rb +37 -57
 - data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +3 -3
 - data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
 - data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +13 -3
 - data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
 - data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
 - data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
 - data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
 - data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
 - data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/quoting.rb +56 -19
 - data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
 - data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
 - data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
 - data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +250 -154
 - data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
 - data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql_adapter.rb +264 -170
 - data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
 - data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
 - data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
 - data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
 - data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
 - data/lib/active_record/connection_adapters/sqlite3_adapter.rb +151 -194
 - data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
 - data/lib/active_record/connection_handling.rb +37 -14
 - data/lib/active_record/core.rb +92 -108
 - data/lib/active_record/counter_cache.rb +13 -24
 - data/lib/active_record/dynamic_matchers.rb +1 -20
 - data/lib/active_record/enum.rb +116 -76
 - data/lib/active_record/errors.rb +87 -48
 - data/lib/active_record/explain.rb +20 -9
 - data/lib/active_record/explain_registry.rb +1 -1
 - data/lib/active_record/explain_subscriber.rb +1 -1
 - data/lib/active_record/fixture_set/file.rb +26 -5
 - data/lib/active_record/fixtures.rb +77 -41
 - data/lib/active_record/gem_version.rb +4 -4
 - data/lib/active_record/inheritance.rb +32 -40
 - data/lib/active_record/integration.rb +17 -14
 - data/lib/active_record/internal_metadata.rb +56 -0
 - data/lib/active_record/legacy_yaml_adapter.rb +18 -2
 - data/lib/active_record/locale/en.yml +3 -2
 - data/lib/active_record/locking/optimistic.rb +15 -15
 - data/lib/active_record/locking/pessimistic.rb +1 -1
 - data/lib/active_record/log_subscriber.rb +48 -24
 - data/lib/active_record/migration.rb +362 -111
 - data/lib/active_record/migration/command_recorder.rb +59 -18
 - data/lib/active_record/migration/compatibility.rb +126 -0
 - data/lib/active_record/model_schema.rb +270 -73
 - data/lib/active_record/nested_attributes.rb +58 -29
 - data/lib/active_record/no_touching.rb +4 -0
 - data/lib/active_record/null_relation.rb +16 -8
 - data/lib/active_record/persistence.rb +152 -90
 - data/lib/active_record/query_cache.rb +18 -23
 - data/lib/active_record/querying.rb +12 -11
 - data/lib/active_record/railtie.rb +23 -16
 - data/lib/active_record/railties/controller_runtime.rb +1 -1
 - data/lib/active_record/railties/databases.rake +52 -41
 - data/lib/active_record/readonly_attributes.rb +1 -1
 - data/lib/active_record/reflection.rb +302 -115
 - data/lib/active_record/relation.rb +187 -120
 - data/lib/active_record/relation/batches.rb +141 -36
 - data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
 - data/lib/active_record/relation/calculations.rb +92 -117
 - data/lib/active_record/relation/delegation.rb +8 -20
 - data/lib/active_record/relation/finder_methods.rb +173 -89
 - data/lib/active_record/relation/from_clause.rb +32 -0
 - data/lib/active_record/relation/merger.rb +16 -42
 - data/lib/active_record/relation/predicate_builder.rb +120 -107
 - data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
 - data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
 - data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
 - data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
 - data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
 - data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
 - data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
 - data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
 - data/lib/active_record/relation/query_attribute.rb +19 -0
 - data/lib/active_record/relation/query_methods.rb +308 -244
 - data/lib/active_record/relation/record_fetch_warning.rb +49 -0
 - data/lib/active_record/relation/spawn_methods.rb +4 -7
 - data/lib/active_record/relation/where_clause.rb +174 -0
 - data/lib/active_record/relation/where_clause_factory.rb +38 -0
 - data/lib/active_record/result.rb +11 -4
 - data/lib/active_record/runtime_registry.rb +1 -1
 - data/lib/active_record/sanitization.rb +105 -66
 - data/lib/active_record/schema.rb +26 -22
 - data/lib/active_record/schema_dumper.rb +54 -37
 - data/lib/active_record/schema_migration.rb +11 -14
 - data/lib/active_record/scoping.rb +34 -16
 - data/lib/active_record/scoping/default.rb +28 -10
 - data/lib/active_record/scoping/named.rb +59 -26
 - data/lib/active_record/secure_token.rb +38 -0
 - data/lib/active_record/serialization.rb +3 -5
 - data/lib/active_record/statement_cache.rb +17 -15
 - data/lib/active_record/store.rb +8 -3
 - data/lib/active_record/suppressor.rb +58 -0
 - data/lib/active_record/table_metadata.rb +69 -0
 - data/lib/active_record/tasks/database_tasks.rb +66 -49
 - data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
 - data/lib/active_record/tasks/postgresql_database_tasks.rb +12 -3
 - data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
 - data/lib/active_record/timestamp.rb +20 -9
 - data/lib/active_record/touch_later.rb +63 -0
 - data/lib/active_record/transactions.rb +139 -57
 - data/lib/active_record/type.rb +66 -17
 - data/lib/active_record/type/adapter_specific_registry.rb +130 -0
 - data/lib/active_record/type/date.rb +2 -45
 - data/lib/active_record/type/date_time.rb +2 -49
 - data/lib/active_record/type/internal/abstract_json.rb +33 -0
 - data/lib/active_record/type/internal/timezone.rb +15 -0
 - data/lib/active_record/type/serialized.rb +15 -14
 - data/lib/active_record/type/time.rb +10 -16
 - data/lib/active_record/type/type_map.rb +4 -4
 - data/lib/active_record/type_caster.rb +7 -0
 - data/lib/active_record/type_caster/connection.rb +29 -0
 - data/lib/active_record/type_caster/map.rb +19 -0
 - data/lib/active_record/validations.rb +33 -32
 - data/lib/active_record/validations/absence.rb +23 -0
 - data/lib/active_record/validations/associated.rb +10 -3
 - data/lib/active_record/validations/length.rb +24 -0
 - data/lib/active_record/validations/presence.rb +11 -12
 - data/lib/active_record/validations/uniqueness.rb +33 -33
 - data/lib/rails/generators/active_record/migration.rb +15 -0
 - data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -5
 - data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
 - data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
 - data/lib/rails/generators/active_record/model/model_generator.rb +33 -16
 - data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
 - data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
 - metadata +58 -34
 - data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
 - data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
 - data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
 - 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/integer.rb +0 -11
 - data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
 - 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 -64
 - data/lib/active_record/type/decimal_without_scale.rb +0 -11
 - 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/text.rb +0 -11
 - data/lib/active_record/type/time_value.rb +0 -38
 - data/lib/active_record/type/unsigned_integer.rb +0 -15
 - data/lib/active_record/type/value.rb +0 -110
 
| 
         @@ -1,498 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'active_record/connection_adapters/abstract_mysql_adapter'
         
     | 
| 
       2 
     | 
    
         
            -
            require 'active_record/connection_adapters/statement_pool'
         
     | 
| 
       3 
     | 
    
         
            -
            require 'active_support/core_ext/hash/keys'
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            gem 'mysql', '~> 2.9'
         
     | 
| 
       6 
     | 
    
         
            -
            require 'mysql'
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
            class Mysql
         
     | 
| 
       9 
     | 
    
         
            -
              class Time
         
     | 
| 
       10 
     | 
    
         
            -
                def to_date
         
     | 
| 
       11 
     | 
    
         
            -
                  Date.new(year, month, day)
         
     | 
| 
       12 
     | 
    
         
            -
                end
         
     | 
| 
       13 
     | 
    
         
            -
              end
         
     | 
| 
       14 
     | 
    
         
            -
              class Stmt; include Enumerable end
         
     | 
| 
       15 
     | 
    
         
            -
              class Result; include Enumerable end
         
     | 
| 
       16 
     | 
    
         
            -
            end
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
            module ActiveRecord
         
     | 
| 
       19 
     | 
    
         
            -
              module ConnectionHandling # :nodoc:
         
     | 
| 
       20 
     | 
    
         
            -
                # Establishes a connection to the database that's used by all Active Record objects.
         
     | 
| 
       21 
     | 
    
         
            -
                def mysql_connection(config)
         
     | 
| 
       22 
     | 
    
         
            -
                  config = config.symbolize_keys
         
     | 
| 
       23 
     | 
    
         
            -
                  host     = config[:host]
         
     | 
| 
       24 
     | 
    
         
            -
                  port     = config[:port]
         
     | 
| 
       25 
     | 
    
         
            -
                  socket   = config[:socket]
         
     | 
| 
       26 
     | 
    
         
            -
                  username = config[:username] ? config[:username].to_s : 'root'
         
     | 
| 
       27 
     | 
    
         
            -
                  password = config[:password].to_s
         
     | 
| 
       28 
     | 
    
         
            -
                  database = config[:database]
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
                  mysql = Mysql.init
         
     | 
| 
       31 
     | 
    
         
            -
                  mysql.ssl_set(config[:sslkey], config[:sslcert], config[:sslca], config[:sslcapath], config[:sslcipher]) if config[:sslca] || config[:sslkey]
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                  default_flags = Mysql.const_defined?(:CLIENT_MULTI_RESULTS) ? Mysql::CLIENT_MULTI_RESULTS : 0
         
     | 
| 
       34 
     | 
    
         
            -
                  default_flags |= Mysql::CLIENT_FOUND_ROWS if Mysql.const_defined?(:CLIENT_FOUND_ROWS)
         
     | 
| 
       35 
     | 
    
         
            -
                  options = [host, username, password, database, port, socket, default_flags]
         
     | 
| 
       36 
     | 
    
         
            -
                  ConnectionAdapters::MysqlAdapter.new(mysql, logger, options, config)
         
     | 
| 
       37 
     | 
    
         
            -
                rescue Mysql::Error => error
         
     | 
| 
       38 
     | 
    
         
            -
                  if error.message.include?("Unknown database")
         
     | 
| 
       39 
     | 
    
         
            -
                    raise ActiveRecord::NoDatabaseError.new(error.message, error)
         
     | 
| 
       40 
     | 
    
         
            -
                  else
         
     | 
| 
       41 
     | 
    
         
            -
                    raise
         
     | 
| 
       42 
     | 
    
         
            -
                  end
         
     | 
| 
       43 
     | 
    
         
            -
                end
         
     | 
| 
       44 
     | 
    
         
            -
              end
         
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
              module ConnectionAdapters
         
     | 
| 
       47 
     | 
    
         
            -
                # The MySQL adapter will work with both Ruby/MySQL, which is a Ruby-based MySQL adapter that comes bundled with Active Record, and with
         
     | 
| 
       48 
     | 
    
         
            -
                # the faster C-based MySQL/Ruby adapter (available both as a gem and from http://www.tmtm.org/en/mysql/ruby/).
         
     | 
| 
       49 
     | 
    
         
            -
                #
         
     | 
| 
       50 
     | 
    
         
            -
                # Options:
         
     | 
| 
       51 
     | 
    
         
            -
                #
         
     | 
| 
       52 
     | 
    
         
            -
                # * <tt>:host</tt> - Defaults to "localhost".
         
     | 
| 
       53 
     | 
    
         
            -
                # * <tt>:port</tt> - Defaults to 3306.
         
     | 
| 
       54 
     | 
    
         
            -
                # * <tt>:socket</tt> - Defaults to "/tmp/mysql.sock".
         
     | 
| 
       55 
     | 
    
         
            -
                # * <tt>:username</tt> - Defaults to "root"
         
     | 
| 
       56 
     | 
    
         
            -
                # * <tt>:password</tt> - Defaults to nothing.
         
     | 
| 
       57 
     | 
    
         
            -
                # * <tt>:database</tt> - The name of the database. No default, must be provided.
         
     | 
| 
       58 
     | 
    
         
            -
                # * <tt>:encoding</tt> - (Optional) Sets the client encoding by executing "SET NAMES <encoding>" after connection.
         
     | 
| 
       59 
     | 
    
         
            -
                # * <tt>:reconnect</tt> - Defaults to false (See MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html).
         
     | 
| 
       60 
     | 
    
         
            -
                # * <tt>:strict</tt> - Defaults to true. Enable STRICT_ALL_TABLES. (See MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/sql-mode.html)
         
     | 
| 
       61 
     | 
    
         
            -
                # * <tt>:variables</tt> - (Optional) A hash session variables to send as <tt>SET @@SESSION.key = value</tt> on each database connection. Use the value +:default+ to set a variable to its DEFAULT value. (See MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/set-statement.html).
         
     | 
| 
       62 
     | 
    
         
            -
                # * <tt>:sslca</tt> - Necessary to use MySQL with an SSL connection.
         
     | 
| 
       63 
     | 
    
         
            -
                # * <tt>:sslkey</tt> - Necessary to use MySQL with an SSL connection.
         
     | 
| 
       64 
     | 
    
         
            -
                # * <tt>:sslcert</tt> - Necessary to use MySQL with an SSL connection.
         
     | 
| 
       65 
     | 
    
         
            -
                # * <tt>:sslcapath</tt> - Necessary to use MySQL with an SSL connection.
         
     | 
| 
       66 
     | 
    
         
            -
                # * <tt>:sslcipher</tt> - Necessary to use MySQL with an SSL connection.
         
     | 
| 
       67 
     | 
    
         
            -
                #
         
     | 
| 
       68 
     | 
    
         
            -
                class MysqlAdapter < AbstractMysqlAdapter
         
     | 
| 
       69 
     | 
    
         
            -
                  ADAPTER_NAME = 'MySQL'.freeze
         
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
                  class StatementPool < ConnectionAdapters::StatementPool
         
     | 
| 
       72 
     | 
    
         
            -
                    def initialize(connection, max = 1000)
         
     | 
| 
       73 
     | 
    
         
            -
                      super
         
     | 
| 
       74 
     | 
    
         
            -
                      @cache = Hash.new { |h,pid| h[pid] = {} }
         
     | 
| 
       75 
     | 
    
         
            -
                    end
         
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
                    def each(&block); cache.each(&block); end
         
     | 
| 
       78 
     | 
    
         
            -
                    def key?(key);    cache.key?(key); end
         
     | 
| 
       79 
     | 
    
         
            -
                    def [](key);      cache[key]; end
         
     | 
| 
       80 
     | 
    
         
            -
                    def length;       cache.length; end
         
     | 
| 
       81 
     | 
    
         
            -
                    def delete(key);  cache.delete(key); end
         
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
                    def []=(sql, key)
         
     | 
| 
       84 
     | 
    
         
            -
                      while @max <= cache.size
         
     | 
| 
       85 
     | 
    
         
            -
                        cache.shift.last[:stmt].close
         
     | 
| 
       86 
     | 
    
         
            -
                      end
         
     | 
| 
       87 
     | 
    
         
            -
                      cache[sql] = key
         
     | 
| 
       88 
     | 
    
         
            -
                    end
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                    def clear
         
     | 
| 
       91 
     | 
    
         
            -
                      cache.each_value do |hash|
         
     | 
| 
       92 
     | 
    
         
            -
                        hash[:stmt].close
         
     | 
| 
       93 
     | 
    
         
            -
                      end
         
     | 
| 
       94 
     | 
    
         
            -
                      cache.clear
         
     | 
| 
       95 
     | 
    
         
            -
                    end
         
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
                    private
         
     | 
| 
       98 
     | 
    
         
            -
                    def cache
         
     | 
| 
       99 
     | 
    
         
            -
                      @cache[Process.pid]
         
     | 
| 
       100 
     | 
    
         
            -
                    end
         
     | 
| 
       101 
     | 
    
         
            -
                  end
         
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
       103 
     | 
    
         
            -
                  def initialize(connection, logger, connection_options, config)
         
     | 
| 
       104 
     | 
    
         
            -
                    super
         
     | 
| 
       105 
     | 
    
         
            -
                    @statements = StatementPool.new(@connection,
         
     | 
| 
       106 
     | 
    
         
            -
                                                    self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }))
         
     | 
| 
       107 
     | 
    
         
            -
                    @client_encoding = nil
         
     | 
| 
       108 
     | 
    
         
            -
                    connect
         
     | 
| 
       109 
     | 
    
         
            -
                  end
         
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
                  # Returns true, since this connection adapter supports prepared statement
         
     | 
| 
       112 
     | 
    
         
            -
                  # caching.
         
     | 
| 
       113 
     | 
    
         
            -
                  def supports_statement_cache?
         
     | 
| 
       114 
     | 
    
         
            -
                    true
         
     | 
| 
       115 
     | 
    
         
            -
                  end
         
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
       117 
     | 
    
         
            -
                  # HELPER METHODS ===========================================
         
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
                  def each_hash(result) # :nodoc:
         
     | 
| 
       120 
     | 
    
         
            -
                    if block_given?
         
     | 
| 
       121 
     | 
    
         
            -
                      result.each_hash do |row|
         
     | 
| 
       122 
     | 
    
         
            -
                        row.symbolize_keys!
         
     | 
| 
       123 
     | 
    
         
            -
                        yield row
         
     | 
| 
       124 
     | 
    
         
            -
                      end
         
     | 
| 
       125 
     | 
    
         
            -
                    else
         
     | 
| 
       126 
     | 
    
         
            -
                      to_enum(:each_hash, result)
         
     | 
| 
       127 
     | 
    
         
            -
                    end
         
     | 
| 
       128 
     | 
    
         
            -
                  end
         
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
                  def error_number(exception) # :nodoc:
         
     | 
| 
       131 
     | 
    
         
            -
                    exception.errno if exception.respond_to?(:errno)
         
     | 
| 
       132 
     | 
    
         
            -
                  end
         
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
       134 
     | 
    
         
            -
                  # QUOTING ==================================================
         
     | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
       136 
     | 
    
         
            -
                  def quote_string(string) #:nodoc:
         
     | 
| 
       137 
     | 
    
         
            -
                    @connection.quote(string)
         
     | 
| 
       138 
     | 
    
         
            -
                  end
         
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
       140 
     | 
    
         
            -
                  #--
         
     | 
| 
       141 
     | 
    
         
            -
                  # CONNECTION MANAGEMENT ====================================
         
     | 
| 
       142 
     | 
    
         
            -
                  #++
         
     | 
| 
       143 
     | 
    
         
            -
             
     | 
| 
       144 
     | 
    
         
            -
                  def active?
         
     | 
| 
       145 
     | 
    
         
            -
                    if @connection.respond_to?(:stat)
         
     | 
| 
       146 
     | 
    
         
            -
                      @connection.stat
         
     | 
| 
       147 
     | 
    
         
            -
                    else
         
     | 
| 
       148 
     | 
    
         
            -
                      @connection.query 'select 1'
         
     | 
| 
       149 
     | 
    
         
            -
                    end
         
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
                    # mysql-ruby doesn't raise an exception when stat fails.
         
     | 
| 
       152 
     | 
    
         
            -
                    if @connection.respond_to?(:errno)
         
     | 
| 
       153 
     | 
    
         
            -
                      @connection.errno.zero?
         
     | 
| 
       154 
     | 
    
         
            -
                    else
         
     | 
| 
       155 
     | 
    
         
            -
                      true
         
     | 
| 
       156 
     | 
    
         
            -
                    end
         
     | 
| 
       157 
     | 
    
         
            -
                  rescue Mysql::Error
         
     | 
| 
       158 
     | 
    
         
            -
                    false
         
     | 
| 
       159 
     | 
    
         
            -
                  end
         
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
       161 
     | 
    
         
            -
                  def reconnect!
         
     | 
| 
       162 
     | 
    
         
            -
                    super
         
     | 
| 
       163 
     | 
    
         
            -
                    disconnect!
         
     | 
| 
       164 
     | 
    
         
            -
                    connect
         
     | 
| 
       165 
     | 
    
         
            -
                  end
         
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
                  # Disconnects from the database if already connected. Otherwise, this
         
     | 
| 
       168 
     | 
    
         
            -
                  # method does nothing.
         
     | 
| 
       169 
     | 
    
         
            -
                  def disconnect!
         
     | 
| 
       170 
     | 
    
         
            -
                    super
         
     | 
| 
       171 
     | 
    
         
            -
                    @connection.close rescue nil
         
     | 
| 
       172 
     | 
    
         
            -
                  end
         
     | 
| 
       173 
     | 
    
         
            -
             
     | 
| 
       174 
     | 
    
         
            -
                  def reset!
         
     | 
| 
       175 
     | 
    
         
            -
                    if @connection.respond_to?(:change_user)
         
     | 
| 
       176 
     | 
    
         
            -
                      # See http://bugs.mysql.com/bug.php?id=33540 -- the workaround way to
         
     | 
| 
       177 
     | 
    
         
            -
                      # reset the connection is to change the user to the same user.
         
     | 
| 
       178 
     | 
    
         
            -
                      @connection.change_user(@config[:username], @config[:password], @config[:database])
         
     | 
| 
       179 
     | 
    
         
            -
                      configure_connection
         
     | 
| 
       180 
     | 
    
         
            -
                    end
         
     | 
| 
       181 
     | 
    
         
            -
                  end
         
     | 
| 
       182 
     | 
    
         
            -
             
     | 
| 
       183 
     | 
    
         
            -
                  #--
         
     | 
| 
       184 
     | 
    
         
            -
                  # DATABASE STATEMENTS ======================================
         
     | 
| 
       185 
     | 
    
         
            -
                  #++
         
     | 
| 
       186 
     | 
    
         
            -
             
     | 
| 
       187 
     | 
    
         
            -
                  def select_rows(sql, name = nil, binds = [])
         
     | 
| 
       188 
     | 
    
         
            -
                    @connection.query_with_result = true
         
     | 
| 
       189 
     | 
    
         
            -
                    rows = exec_query(sql, name, binds).rows
         
     | 
| 
       190 
     | 
    
         
            -
                    @connection.more_results && @connection.next_result    # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
         
     | 
| 
       191 
     | 
    
         
            -
                    rows
         
     | 
| 
       192 
     | 
    
         
            -
                  end
         
     | 
| 
       193 
     | 
    
         
            -
             
     | 
| 
       194 
     | 
    
         
            -
                  # Clears the prepared statements cache.
         
     | 
| 
       195 
     | 
    
         
            -
                  def clear_cache!
         
     | 
| 
       196 
     | 
    
         
            -
                    super
         
     | 
| 
       197 
     | 
    
         
            -
                    @statements.clear
         
     | 
| 
       198 
     | 
    
         
            -
                  end
         
     | 
| 
       199 
     | 
    
         
            -
             
     | 
| 
       200 
     | 
    
         
            -
                  # Taken from here:
         
     | 
| 
       201 
     | 
    
         
            -
                  #   https://github.com/tmtm/ruby-mysql/blob/master/lib/mysql/charset.rb
         
     | 
| 
       202 
     | 
    
         
            -
                  # Author: TOMITA Masahiro <tommy@tmtm.org>
         
     | 
| 
       203 
     | 
    
         
            -
                  ENCODINGS = {
         
     | 
| 
       204 
     | 
    
         
            -
                    "armscii8" => nil,
         
     | 
| 
       205 
     | 
    
         
            -
                    "ascii"    => Encoding::US_ASCII,
         
     | 
| 
       206 
     | 
    
         
            -
                    "big5"     => Encoding::Big5,
         
     | 
| 
       207 
     | 
    
         
            -
                    "binary"   => Encoding::ASCII_8BIT,
         
     | 
| 
       208 
     | 
    
         
            -
                    "cp1250"   => Encoding::Windows_1250,
         
     | 
| 
       209 
     | 
    
         
            -
                    "cp1251"   => Encoding::Windows_1251,
         
     | 
| 
       210 
     | 
    
         
            -
                    "cp1256"   => Encoding::Windows_1256,
         
     | 
| 
       211 
     | 
    
         
            -
                    "cp1257"   => Encoding::Windows_1257,
         
     | 
| 
       212 
     | 
    
         
            -
                    "cp850"    => Encoding::CP850,
         
     | 
| 
       213 
     | 
    
         
            -
                    "cp852"    => Encoding::CP852,
         
     | 
| 
       214 
     | 
    
         
            -
                    "cp866"    => Encoding::IBM866,
         
     | 
| 
       215 
     | 
    
         
            -
                    "cp932"    => Encoding::Windows_31J,
         
     | 
| 
       216 
     | 
    
         
            -
                    "dec8"     => nil,
         
     | 
| 
       217 
     | 
    
         
            -
                    "eucjpms"  => Encoding::EucJP_ms,
         
     | 
| 
       218 
     | 
    
         
            -
                    "euckr"    => Encoding::EUC_KR,
         
     | 
| 
       219 
     | 
    
         
            -
                    "gb2312"   => Encoding::EUC_CN,
         
     | 
| 
       220 
     | 
    
         
            -
                    "gbk"      => Encoding::GBK,
         
     | 
| 
       221 
     | 
    
         
            -
                    "geostd8"  => nil,
         
     | 
| 
       222 
     | 
    
         
            -
                    "greek"    => Encoding::ISO_8859_7,
         
     | 
| 
       223 
     | 
    
         
            -
                    "hebrew"   => Encoding::ISO_8859_8,
         
     | 
| 
       224 
     | 
    
         
            -
                    "hp8"      => nil,
         
     | 
| 
       225 
     | 
    
         
            -
                    "keybcs2"  => nil,
         
     | 
| 
       226 
     | 
    
         
            -
                    "koi8r"    => Encoding::KOI8_R,
         
     | 
| 
       227 
     | 
    
         
            -
                    "koi8u"    => Encoding::KOI8_U,
         
     | 
| 
       228 
     | 
    
         
            -
                    "latin1"   => Encoding::ISO_8859_1,
         
     | 
| 
       229 
     | 
    
         
            -
                    "latin2"   => Encoding::ISO_8859_2,
         
     | 
| 
       230 
     | 
    
         
            -
                    "latin5"   => Encoding::ISO_8859_9,
         
     | 
| 
       231 
     | 
    
         
            -
                    "latin7"   => Encoding::ISO_8859_13,
         
     | 
| 
       232 
     | 
    
         
            -
                    "macce"    => Encoding::MacCentEuro,
         
     | 
| 
       233 
     | 
    
         
            -
                    "macroman" => Encoding::MacRoman,
         
     | 
| 
       234 
     | 
    
         
            -
                    "sjis"     => Encoding::SHIFT_JIS,
         
     | 
| 
       235 
     | 
    
         
            -
                    "swe7"     => nil,
         
     | 
| 
       236 
     | 
    
         
            -
                    "tis620"   => Encoding::TIS_620,
         
     | 
| 
       237 
     | 
    
         
            -
                    "ucs2"     => Encoding::UTF_16BE,
         
     | 
| 
       238 
     | 
    
         
            -
                    "ujis"     => Encoding::EucJP_ms,
         
     | 
| 
       239 
     | 
    
         
            -
                    "utf8"     => Encoding::UTF_8,
         
     | 
| 
       240 
     | 
    
         
            -
                    "utf8mb4"  => Encoding::UTF_8,
         
     | 
| 
       241 
     | 
    
         
            -
                  }
         
     | 
| 
       242 
     | 
    
         
            -
             
     | 
| 
       243 
     | 
    
         
            -
                  # Get the client encoding for this database
         
     | 
| 
       244 
     | 
    
         
            -
                  def client_encoding
         
     | 
| 
       245 
     | 
    
         
            -
                    return @client_encoding if @client_encoding
         
     | 
| 
       246 
     | 
    
         
            -
             
     | 
| 
       247 
     | 
    
         
            -
                    result = exec_query(
         
     | 
| 
       248 
     | 
    
         
            -
                      "select @@character_set_client",
         
     | 
| 
       249 
     | 
    
         
            -
                      'SCHEMA')
         
     | 
| 
       250 
     | 
    
         
            -
                    @client_encoding = ENCODINGS[result.rows.last.last]
         
     | 
| 
       251 
     | 
    
         
            -
                  end
         
     | 
| 
       252 
     | 
    
         
            -
             
     | 
| 
       253 
     | 
    
         
            -
                  def exec_query(sql, name = 'SQL', binds = [])
         
     | 
| 
       254 
     | 
    
         
            -
                    if without_prepared_statement?(binds)
         
     | 
| 
       255 
     | 
    
         
            -
                      result_set, affected_rows = exec_without_stmt(sql, name)
         
     | 
| 
       256 
     | 
    
         
            -
                    else
         
     | 
| 
       257 
     | 
    
         
            -
                      result_set, affected_rows = exec_stmt(sql, name, binds)
         
     | 
| 
       258 
     | 
    
         
            -
                    end
         
     | 
| 
       259 
     | 
    
         
            -
             
     | 
| 
       260 
     | 
    
         
            -
                    yield affected_rows if block_given?
         
     | 
| 
       261 
     | 
    
         
            -
             
     | 
| 
       262 
     | 
    
         
            -
                    result_set
         
     | 
| 
       263 
     | 
    
         
            -
                  end
         
     | 
| 
       264 
     | 
    
         
            -
             
     | 
| 
       265 
     | 
    
         
            -
                  def last_inserted_id(result)
         
     | 
| 
       266 
     | 
    
         
            -
                    @connection.insert_id
         
     | 
| 
       267 
     | 
    
         
            -
                  end
         
     | 
| 
       268 
     | 
    
         
            -
             
     | 
| 
       269 
     | 
    
         
            -
                  module Fields # :nodoc:
         
     | 
| 
       270 
     | 
    
         
            -
                    class DateTime < Type::DateTime # :nodoc:
         
     | 
| 
       271 
     | 
    
         
            -
                      def cast_value(value)
         
     | 
| 
       272 
     | 
    
         
            -
                        if Mysql::Time === value
         
     | 
| 
       273 
     | 
    
         
            -
                          new_time(
         
     | 
| 
       274 
     | 
    
         
            -
                            value.year,
         
     | 
| 
       275 
     | 
    
         
            -
                            value.month,
         
     | 
| 
       276 
     | 
    
         
            -
                            value.day,
         
     | 
| 
       277 
     | 
    
         
            -
                            value.hour,
         
     | 
| 
       278 
     | 
    
         
            -
                            value.minute,
         
     | 
| 
       279 
     | 
    
         
            -
                            value.second,
         
     | 
| 
       280 
     | 
    
         
            -
                            value.second_part)
         
     | 
| 
       281 
     | 
    
         
            -
                        else
         
     | 
| 
       282 
     | 
    
         
            -
                          super
         
     | 
| 
       283 
     | 
    
         
            -
                        end
         
     | 
| 
       284 
     | 
    
         
            -
                      end
         
     | 
| 
       285 
     | 
    
         
            -
             
     | 
| 
       286 
     | 
    
         
            -
                      def has_precision?
         
     | 
| 
       287 
     | 
    
         
            -
                        precision || 0
         
     | 
| 
       288 
     | 
    
         
            -
                      end
         
     | 
| 
       289 
     | 
    
         
            -
                    end
         
     | 
| 
       290 
     | 
    
         
            -
             
     | 
| 
       291 
     | 
    
         
            -
                    class Time < Type::Time # :nodoc:
         
     | 
| 
       292 
     | 
    
         
            -
                      def cast_value(value)
         
     | 
| 
       293 
     | 
    
         
            -
                        if Mysql::Time === value
         
     | 
| 
       294 
     | 
    
         
            -
                          new_time(
         
     | 
| 
       295 
     | 
    
         
            -
                            2000,
         
     | 
| 
       296 
     | 
    
         
            -
                            01,
         
     | 
| 
       297 
     | 
    
         
            -
                            01,
         
     | 
| 
       298 
     | 
    
         
            -
                            value.hour,
         
     | 
| 
       299 
     | 
    
         
            -
                            value.minute,
         
     | 
| 
       300 
     | 
    
         
            -
                            value.second,
         
     | 
| 
       301 
     | 
    
         
            -
                            value.second_part)
         
     | 
| 
       302 
     | 
    
         
            -
                        else
         
     | 
| 
       303 
     | 
    
         
            -
                          super
         
     | 
| 
       304 
     | 
    
         
            -
                        end
         
     | 
| 
       305 
     | 
    
         
            -
                      end
         
     | 
| 
       306 
     | 
    
         
            -
                    end
         
     | 
| 
       307 
     | 
    
         
            -
             
     | 
| 
       308 
     | 
    
         
            -
                    class << self
         
     | 
| 
       309 
     | 
    
         
            -
                      TYPES = Type::HashLookupTypeMap.new # :nodoc:
         
     | 
| 
       310 
     | 
    
         
            -
             
     | 
| 
       311 
     | 
    
         
            -
                      delegate :register_type, :alias_type, to: :TYPES
         
     | 
| 
       312 
     | 
    
         
            -
             
     | 
| 
       313 
     | 
    
         
            -
                      def find_type(field)
         
     | 
| 
       314 
     | 
    
         
            -
                        if field.type == Mysql::Field::TYPE_TINY && field.length > 1
         
     | 
| 
       315 
     | 
    
         
            -
                          TYPES.lookup(Mysql::Field::TYPE_LONG)
         
     | 
| 
       316 
     | 
    
         
            -
                        else
         
     | 
| 
       317 
     | 
    
         
            -
                          TYPES.lookup(field.type)
         
     | 
| 
       318 
     | 
    
         
            -
                        end
         
     | 
| 
       319 
     | 
    
         
            -
                      end
         
     | 
| 
       320 
     | 
    
         
            -
                    end
         
     | 
| 
       321 
     | 
    
         
            -
             
     | 
| 
       322 
     | 
    
         
            -
                    register_type Mysql::Field::TYPE_TINY,    Type::Boolean.new
         
     | 
| 
       323 
     | 
    
         
            -
                    register_type Mysql::Field::TYPE_LONG,    Type::Integer.new
         
     | 
| 
       324 
     | 
    
         
            -
                    alias_type Mysql::Field::TYPE_LONGLONG,   Mysql::Field::TYPE_LONG
         
     | 
| 
       325 
     | 
    
         
            -
                    alias_type Mysql::Field::TYPE_NEWDECIMAL, Mysql::Field::TYPE_LONG
         
     | 
| 
       326 
     | 
    
         
            -
             
     | 
| 
       327 
     | 
    
         
            -
                    register_type Mysql::Field::TYPE_DATE, Type::Date.new
         
     | 
| 
       328 
     | 
    
         
            -
                    register_type Mysql::Field::TYPE_DATETIME, Fields::DateTime.new
         
     | 
| 
       329 
     | 
    
         
            -
                    register_type Mysql::Field::TYPE_TIME, Fields::Time.new
         
     | 
| 
       330 
     | 
    
         
            -
                    register_type Mysql::Field::TYPE_FLOAT, Type::Float.new
         
     | 
| 
       331 
     | 
    
         
            -
                  end
         
     | 
| 
       332 
     | 
    
         
            -
             
     | 
| 
       333 
     | 
    
         
            -
                  def initialize_type_map(m) # :nodoc:
         
     | 
| 
       334 
     | 
    
         
            -
                    super
         
     | 
| 
       335 
     | 
    
         
            -
                    m.register_type %r(time)i,     Fields::Time.new
         
     | 
| 
       336 
     | 
    
         
            -
                    m.register_type(%r(datetime)i) do |sql_type|
         
     | 
| 
       337 
     | 
    
         
            -
                      precision = extract_precision(sql_type)
         
     | 
| 
       338 
     | 
    
         
            -
                      Fields::DateTime.new(precision: precision)
         
     | 
| 
       339 
     | 
    
         
            -
                    end
         
     | 
| 
       340 
     | 
    
         
            -
                  end
         
     | 
| 
       341 
     | 
    
         
            -
             
     | 
| 
       342 
     | 
    
         
            -
                  def exec_without_stmt(sql, name = 'SQL') # :nodoc:
         
     | 
| 
       343 
     | 
    
         
            -
                    # Some queries, like SHOW CREATE TABLE don't work through the prepared
         
     | 
| 
       344 
     | 
    
         
            -
                    # statement API. For those queries, we need to use this method. :'(
         
     | 
| 
       345 
     | 
    
         
            -
                    log(sql, name) do
         
     | 
| 
       346 
     | 
    
         
            -
                      result = @connection.query(sql)
         
     | 
| 
       347 
     | 
    
         
            -
                      affected_rows = @connection.affected_rows
         
     | 
| 
       348 
     | 
    
         
            -
             
     | 
| 
       349 
     | 
    
         
            -
                      if result
         
     | 
| 
       350 
     | 
    
         
            -
                        types = {}
         
     | 
| 
       351 
     | 
    
         
            -
                        fields = []
         
     | 
| 
       352 
     | 
    
         
            -
                        result.fetch_fields.each { |field|
         
     | 
| 
       353 
     | 
    
         
            -
                          field_name = field.name
         
     | 
| 
       354 
     | 
    
         
            -
                          fields << field_name
         
     | 
| 
       355 
     | 
    
         
            -
             
     | 
| 
       356 
     | 
    
         
            -
                          if field.decimals > 0
         
     | 
| 
       357 
     | 
    
         
            -
                            types[field_name] = Type::Decimal.new
         
     | 
| 
       358 
     | 
    
         
            -
                          else
         
     | 
| 
       359 
     | 
    
         
            -
                            types[field_name] = Fields.find_type field
         
     | 
| 
       360 
     | 
    
         
            -
                          end
         
     | 
| 
       361 
     | 
    
         
            -
                        }
         
     | 
| 
       362 
     | 
    
         
            -
             
     | 
| 
       363 
     | 
    
         
            -
                        result_set = ActiveRecord::Result.new(fields, result.to_a, types)
         
     | 
| 
       364 
     | 
    
         
            -
                        result.free
         
     | 
| 
       365 
     | 
    
         
            -
                      else
         
     | 
| 
       366 
     | 
    
         
            -
                        result_set = ActiveRecord::Result.new([], [])
         
     | 
| 
       367 
     | 
    
         
            -
                      end
         
     | 
| 
       368 
     | 
    
         
            -
             
     | 
| 
       369 
     | 
    
         
            -
                      [result_set, affected_rows]
         
     | 
| 
       370 
     | 
    
         
            -
                    end
         
     | 
| 
       371 
     | 
    
         
            -
                  end
         
     | 
| 
       372 
     | 
    
         
            -
             
     | 
| 
       373 
     | 
    
         
            -
                  def execute_and_free(sql, name = nil) # :nodoc:
         
     | 
| 
       374 
     | 
    
         
            -
                    result = execute(sql, name)
         
     | 
| 
       375 
     | 
    
         
            -
                    ret = yield result
         
     | 
| 
       376 
     | 
    
         
            -
                    result.free
         
     | 
| 
       377 
     | 
    
         
            -
                    ret
         
     | 
| 
       378 
     | 
    
         
            -
                  end
         
     | 
| 
       379 
     | 
    
         
            -
             
     | 
| 
       380 
     | 
    
         
            -
                  def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
         
     | 
| 
       381 
     | 
    
         
            -
                    super sql, name
         
     | 
| 
       382 
     | 
    
         
            -
                    id_value || @connection.insert_id
         
     | 
| 
       383 
     | 
    
         
            -
                  end
         
     | 
| 
       384 
     | 
    
         
            -
                  alias :create :insert_sql
         
     | 
| 
       385 
     | 
    
         
            -
             
     | 
| 
       386 
     | 
    
         
            -
                  def exec_delete(sql, name, binds) # :nodoc:
         
     | 
| 
       387 
     | 
    
         
            -
                    affected_rows = 0
         
     | 
| 
       388 
     | 
    
         
            -
             
     | 
| 
       389 
     | 
    
         
            -
                    exec_query(sql, name, binds) do |n|
         
     | 
| 
       390 
     | 
    
         
            -
                      affected_rows = n
         
     | 
| 
       391 
     | 
    
         
            -
                    end
         
     | 
| 
       392 
     | 
    
         
            -
             
     | 
| 
       393 
     | 
    
         
            -
                    affected_rows
         
     | 
| 
       394 
     | 
    
         
            -
                  end
         
     | 
| 
       395 
     | 
    
         
            -
                  alias :exec_update :exec_delete
         
     | 
| 
       396 
     | 
    
         
            -
             
     | 
| 
       397 
     | 
    
         
            -
                  def begin_db_transaction #:nodoc:
         
     | 
| 
       398 
     | 
    
         
            -
                    exec_query "BEGIN"
         
     | 
| 
       399 
     | 
    
         
            -
                  end
         
     | 
| 
       400 
     | 
    
         
            -
             
     | 
| 
       401 
     | 
    
         
            -
                  private
         
     | 
| 
       402 
     | 
    
         
            -
             
     | 
| 
       403 
     | 
    
         
            -
                  def exec_stmt(sql, name, binds)
         
     | 
| 
       404 
     | 
    
         
            -
                    cache = {}
         
     | 
| 
       405 
     | 
    
         
            -
                    type_casted_binds = binds.map { |col, val|
         
     | 
| 
       406 
     | 
    
         
            -
                      [col, type_cast(val, col)]
         
     | 
| 
       407 
     | 
    
         
            -
                    }
         
     | 
| 
       408 
     | 
    
         
            -
             
     | 
| 
       409 
     | 
    
         
            -
                    log(sql, name, type_casted_binds) do
         
     | 
| 
       410 
     | 
    
         
            -
                      if binds.empty?
         
     | 
| 
       411 
     | 
    
         
            -
                        stmt = @connection.prepare(sql)
         
     | 
| 
       412 
     | 
    
         
            -
                      else
         
     | 
| 
       413 
     | 
    
         
            -
                        cache = @statements[sql] ||= {
         
     | 
| 
       414 
     | 
    
         
            -
                          :stmt => @connection.prepare(sql)
         
     | 
| 
       415 
     | 
    
         
            -
                        }
         
     | 
| 
       416 
     | 
    
         
            -
                        stmt = cache[:stmt]
         
     | 
| 
       417 
     | 
    
         
            -
                      end
         
     | 
| 
       418 
     | 
    
         
            -
             
     | 
| 
       419 
     | 
    
         
            -
                      begin
         
     | 
| 
       420 
     | 
    
         
            -
                        stmt.execute(*type_casted_binds.map { |_, val| val })
         
     | 
| 
       421 
     | 
    
         
            -
                      rescue Mysql::Error => e
         
     | 
| 
       422 
     | 
    
         
            -
                        # Older versions of MySQL leave the prepared statement in a bad
         
     | 
| 
       423 
     | 
    
         
            -
                        # place when an error occurs. To support older MySQL versions, we
         
     | 
| 
       424 
     | 
    
         
            -
                        # need to close the statement and delete the statement from the
         
     | 
| 
       425 
     | 
    
         
            -
                        # cache.
         
     | 
| 
       426 
     | 
    
         
            -
                        stmt.close
         
     | 
| 
       427 
     | 
    
         
            -
                        @statements.delete sql
         
     | 
| 
       428 
     | 
    
         
            -
                        raise e
         
     | 
| 
       429 
     | 
    
         
            -
                      end
         
     | 
| 
       430 
     | 
    
         
            -
             
     | 
| 
       431 
     | 
    
         
            -
                      cols = nil
         
     | 
| 
       432 
     | 
    
         
            -
                      if metadata = stmt.result_metadata
         
     | 
| 
       433 
     | 
    
         
            -
                        cols = cache[:cols] ||= metadata.fetch_fields.map { |field|
         
     | 
| 
       434 
     | 
    
         
            -
                          field.name
         
     | 
| 
       435 
     | 
    
         
            -
                        }
         
     | 
| 
       436 
     | 
    
         
            -
                        metadata.free
         
     | 
| 
       437 
     | 
    
         
            -
                      end
         
     | 
| 
       438 
     | 
    
         
            -
             
     | 
| 
       439 
     | 
    
         
            -
                      result_set = ActiveRecord::Result.new(cols, stmt.to_a) if cols
         
     | 
| 
       440 
     | 
    
         
            -
                      affected_rows = stmt.affected_rows
         
     | 
| 
       441 
     | 
    
         
            -
             
     | 
| 
       442 
     | 
    
         
            -
                      stmt.free_result
         
     | 
| 
       443 
     | 
    
         
            -
                      stmt.close if binds.empty?
         
     | 
| 
       444 
     | 
    
         
            -
             
     | 
| 
       445 
     | 
    
         
            -
                      [result_set, affected_rows]
         
     | 
| 
       446 
     | 
    
         
            -
                    end
         
     | 
| 
       447 
     | 
    
         
            -
                  end
         
     | 
| 
       448 
     | 
    
         
            -
             
     | 
| 
       449 
     | 
    
         
            -
                  def connect
         
     | 
| 
       450 
     | 
    
         
            -
                    encoding = @config[:encoding]
         
     | 
| 
       451 
     | 
    
         
            -
                    if encoding
         
     | 
| 
       452 
     | 
    
         
            -
                      @connection.options(Mysql::SET_CHARSET_NAME, encoding) rescue nil
         
     | 
| 
       453 
     | 
    
         
            -
                    end
         
     | 
| 
       454 
     | 
    
         
            -
             
     | 
| 
       455 
     | 
    
         
            -
                    if @config[:sslca] || @config[:sslkey]
         
     | 
| 
       456 
     | 
    
         
            -
                      @connection.ssl_set(@config[:sslkey], @config[:sslcert], @config[:sslca], @config[:sslcapath], @config[:sslcipher])
         
     | 
| 
       457 
     | 
    
         
            -
                    end
         
     | 
| 
       458 
     | 
    
         
            -
             
     | 
| 
       459 
     | 
    
         
            -
                    @connection.options(Mysql::OPT_CONNECT_TIMEOUT, @config[:connect_timeout]) if @config[:connect_timeout]
         
     | 
| 
       460 
     | 
    
         
            -
                    @connection.options(Mysql::OPT_READ_TIMEOUT, @config[:read_timeout]) if @config[:read_timeout]
         
     | 
| 
       461 
     | 
    
         
            -
                    @connection.options(Mysql::OPT_WRITE_TIMEOUT, @config[:write_timeout]) if @config[:write_timeout]
         
     | 
| 
       462 
     | 
    
         
            -
             
     | 
| 
       463 
     | 
    
         
            -
                    @connection.real_connect(*@connection_options)
         
     | 
| 
       464 
     | 
    
         
            -
             
     | 
| 
       465 
     | 
    
         
            -
                    # reconnect must be set after real_connect is called, because real_connect sets it to false internally
         
     | 
| 
       466 
     | 
    
         
            -
                    @connection.reconnect = !!@config[:reconnect] if @connection.respond_to?(:reconnect=)
         
     | 
| 
       467 
     | 
    
         
            -
             
     | 
| 
       468 
     | 
    
         
            -
                    configure_connection
         
     | 
| 
       469 
     | 
    
         
            -
                  end
         
     | 
| 
       470 
     | 
    
         
            -
             
     | 
| 
       471 
     | 
    
         
            -
                  # Many Rails applications monkey-patch a replacement of the configure_connection method
         
     | 
| 
       472 
     | 
    
         
            -
                  # and don't call 'super', so leave this here even though it looks superfluous.
         
     | 
| 
       473 
     | 
    
         
            -
                  def configure_connection
         
     | 
| 
       474 
     | 
    
         
            -
                    super
         
     | 
| 
       475 
     | 
    
         
            -
                  end
         
     | 
| 
       476 
     | 
    
         
            -
             
     | 
| 
       477 
     | 
    
         
            -
                  def select(sql, name = nil, binds = [])
         
     | 
| 
       478 
     | 
    
         
            -
                    @connection.query_with_result = true
         
     | 
| 
       479 
     | 
    
         
            -
                    rows = super
         
     | 
| 
       480 
     | 
    
         
            -
                    @connection.more_results && @connection.next_result    # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
         
     | 
| 
       481 
     | 
    
         
            -
                    rows
         
     | 
| 
       482 
     | 
    
         
            -
                  end
         
     | 
| 
       483 
     | 
    
         
            -
             
     | 
| 
       484 
     | 
    
         
            -
                  # Returns the full version of the connected MySQL server.
         
     | 
| 
       485 
     | 
    
         
            -
                  def full_version
         
     | 
| 
       486 
     | 
    
         
            -
                    @full_version ||= @connection.server_info
         
     | 
| 
       487 
     | 
    
         
            -
                  end
         
     | 
| 
       488 
     | 
    
         
            -
             
     | 
| 
       489 
     | 
    
         
            -
                  def set_field_encoding field_name
         
     | 
| 
       490 
     | 
    
         
            -
                    field_name.force_encoding(client_encoding)
         
     | 
| 
       491 
     | 
    
         
            -
                    if internal_enc = Encoding.default_internal
         
     | 
| 
       492 
     | 
    
         
            -
                      field_name = field_name.encode!(internal_enc)
         
     | 
| 
       493 
     | 
    
         
            -
                    end
         
     | 
| 
       494 
     | 
    
         
            -
                    field_name
         
     | 
| 
       495 
     | 
    
         
            -
                  end
         
     | 
| 
       496 
     | 
    
         
            -
                end
         
     | 
| 
       497 
     | 
    
         
            -
              end
         
     | 
| 
       498 
     | 
    
         
            -
            end
         
     |