activerecord 4.2.11.1 → 5.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 +1282 -1195
- 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 +8 -4
- data/lib/active_record/aggregations.rb +35 -24
- data/lib/active_record/association_relation.rb +3 -3
- data/lib/active_record/associations.rb +317 -209
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +11 -9
- data/lib/active_record/associations/association_scope.rb +73 -102
- 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 +14 -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 +3 -10
- data/lib/active_record/associations/collection_association.rb +49 -41
- data/lib/active_record/associations/collection_proxy.rb +67 -27
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +20 -71
- data/lib/active_record/associations/has_many_through_association.rb +8 -47
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency.rb +29 -19
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
- data/lib/active_record/associations/preloader.rb +14 -4
- data/lib/active_record/associations/preloader/association.rb +46 -52
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- 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/through_association.rb +27 -14
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/attribute.rb +68 -18
- 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 +76 -47
- 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 +2 -2
- 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 +30 -3
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attributes.rb +199 -81
- data/lib/active_record/autosave_association.rb +49 -16
- 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 +40 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
- 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 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +380 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
- data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
- 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 +125 -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 +29 -166
- data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -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 +27 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- 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 +3 -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 +26 -18
- 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 +234 -148
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
- 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 +149 -192
- 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 +89 -107
- data/lib/active_record/counter_cache.rb +13 -24
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +113 -76
- data/lib/active_record/errors.rb +87 -48
- 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 +76 -40
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +32 -40
- data/lib/active_record/integration.rb +4 -4
- 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 +43 -21
- data/lib/active_record/migration.rb +363 -133
- 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 +129 -41
- data/lib/active_record/nested_attributes.rb +58 -29
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +121 -80
- data/lib/active_record/query_cache.rb +15 -18
- data/lib/active_record/querying.rb +10 -9
- 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 +69 -46
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +282 -115
- data/lib/active_record/relation.rb +176 -116
- data/lib/active_record/relation/batches.rb +139 -34
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/calculations.rb +79 -108
- data/lib/active_record/relation/delegation.rb +7 -20
- data/lib/active_record/relation/finder_methods.rb +163 -81
- 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 +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +95 -66
- data/lib/active_record/schema.rb +26 -22
- data/lib/active_record/schema_dumper.rb +62 -38
- data/lib/active_record/schema_migration.rb +11 -14
- data/lib/active_record/scoping.rb +32 -15
- data/lib/active_record/scoping/default.rb +23 -9
- data/lib/active_record/scoping/named.rb +49 -28
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +16 -14
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +58 -0
- data/lib/active_record/table_metadata.rb +68 -0
- data/lib/active_record/tasks/database_tasks.rb +57 -43
- data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
- 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 +58 -0
- data/lib/active_record/transactions.rb +138 -56
- 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 +29 -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 +30 -29
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- 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 +32 -15
- 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 +59 -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
@@ -0,0 +1,51 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module MySQL
|
4
|
+
module Quoting # :nodoc:
|
5
|
+
QUOTED_TRUE, QUOTED_FALSE = '1', '0'
|
6
|
+
|
7
|
+
def quote_column_name(name)
|
8
|
+
@quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`"
|
9
|
+
end
|
10
|
+
|
11
|
+
def quote_table_name(name)
|
12
|
+
@quoted_table_names[name] ||= super.gsub('.', '`.`')
|
13
|
+
end
|
14
|
+
|
15
|
+
def quoted_true
|
16
|
+
QUOTED_TRUE
|
17
|
+
end
|
18
|
+
|
19
|
+
def unquoted_true
|
20
|
+
1
|
21
|
+
end
|
22
|
+
|
23
|
+
def quoted_false
|
24
|
+
QUOTED_FALSE
|
25
|
+
end
|
26
|
+
|
27
|
+
def unquoted_false
|
28
|
+
0
|
29
|
+
end
|
30
|
+
|
31
|
+
def quoted_date(value)
|
32
|
+
if supports_datetime_with_precision?
|
33
|
+
super
|
34
|
+
else
|
35
|
+
super.sub(/\.\d{6}\z/, '')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def _quote(value)
|
42
|
+
if value.is_a?(Type::Binary::Data)
|
43
|
+
"x'#{value.hex}'"
|
44
|
+
else
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module MySQL
|
4
|
+
class SchemaCreation < AbstractAdapter::SchemaCreation
|
5
|
+
delegate :add_sql_comment!, to: :@conn
|
6
|
+
private :add_sql_comment!
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def visit_DropForeignKey(name)
|
11
|
+
"DROP FOREIGN KEY #{name}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def visit_ColumnDefinition(o)
|
15
|
+
o.sql_type = type_to_sql(o.type, o.limit, o.precision, o.scale, o.unsigned)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def visit_AddColumnDefinition(o)
|
20
|
+
add_column_position!(super, column_options(o.column))
|
21
|
+
end
|
22
|
+
|
23
|
+
def visit_ChangeColumnDefinition(o)
|
24
|
+
change_column_sql = "CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
|
25
|
+
add_column_position!(change_column_sql, column_options(o.column))
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_table_options!(create_sql, options)
|
29
|
+
add_sql_comment!(super, options[:comment])
|
30
|
+
end
|
31
|
+
|
32
|
+
def column_options(o)
|
33
|
+
column_options = super
|
34
|
+
column_options[:charset] = o.charset
|
35
|
+
column_options
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_column_options!(sql, options)
|
39
|
+
if charset = options[:charset]
|
40
|
+
sql << " CHARACTER SET #{charset}"
|
41
|
+
end
|
42
|
+
|
43
|
+
if collation = options[:collation]
|
44
|
+
sql << " COLLATE #{collation}"
|
45
|
+
end
|
46
|
+
|
47
|
+
add_sql_comment!(super, options[:comment])
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_column_position!(sql, options)
|
51
|
+
if options[:first]
|
52
|
+
sql << " FIRST"
|
53
|
+
elsif options[:after]
|
54
|
+
sql << " AFTER #{quote_column_name(options[:after])}"
|
55
|
+
end
|
56
|
+
|
57
|
+
sql
|
58
|
+
end
|
59
|
+
|
60
|
+
def index_in_create(table_name, column_name, options)
|
61
|
+
index_name, index_type, index_columns, _, _, index_using, comment = @conn.add_index_options(table_name, column_name, options)
|
62
|
+
add_sql_comment!("#{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})", comment)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module MySQL
|
4
|
+
module ColumnMethods
|
5
|
+
def primary_key(name, type = :primary_key, **options)
|
6
|
+
options[:auto_increment] = true if type == :bigint && !options.key?(:default)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def blob(*args, **options)
|
11
|
+
args.each { |name| column(name, :blob, options) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def tinyblob(*args, **options)
|
15
|
+
args.each { |name| column(name, :tinyblob, options) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def mediumblob(*args, **options)
|
19
|
+
args.each { |name| column(name, :mediumblob, options) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def longblob(*args, **options)
|
23
|
+
args.each { |name| column(name, :longblob, options) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def tinytext(*args, **options)
|
27
|
+
args.each { |name| column(name, :tinytext, options) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def mediumtext(*args, **options)
|
31
|
+
args.each { |name| column(name, :mediumtext, options) }
|
32
|
+
end
|
33
|
+
|
34
|
+
def longtext(*args, **options)
|
35
|
+
args.each { |name| column(name, :longtext, options) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def json(*args, **options)
|
39
|
+
args.each { |name| column(name, :json, options) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def unsigned_integer(*args, **options)
|
43
|
+
args.each { |name| column(name, :unsigned_integer, options) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def unsigned_bigint(*args, **options)
|
47
|
+
args.each { |name| column(name, :unsigned_bigint, options) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def unsigned_float(*args, **options)
|
51
|
+
args.each { |name| column(name, :unsigned_float, options) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def unsigned_decimal(*args, **options)
|
55
|
+
args.each { |name| column(name, :unsigned_decimal, options) }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
|
60
|
+
attr_accessor :charset, :unsigned
|
61
|
+
end
|
62
|
+
|
63
|
+
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
64
|
+
include ColumnMethods
|
65
|
+
|
66
|
+
def new_column_definition(name, type, options) # :nodoc:
|
67
|
+
column = super
|
68
|
+
case column.type
|
69
|
+
when :primary_key
|
70
|
+
column.type = :integer
|
71
|
+
column.auto_increment = true
|
72
|
+
when /\Aunsigned_(?<type>.+)\z/
|
73
|
+
column.type = $~[:type].to_sym
|
74
|
+
column.unsigned = true
|
75
|
+
end
|
76
|
+
column.unsigned ||= options[:unsigned]
|
77
|
+
column.charset = options[:charset]
|
78
|
+
column
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def create_column_definition(name, type)
|
84
|
+
MySQL::ColumnDefinition.new(name, type)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Table < ActiveRecord::ConnectionAdapters::Table
|
89
|
+
include ColumnMethods
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module MySQL
|
4
|
+
module ColumnDumper
|
5
|
+
def column_spec_for_primary_key(column)
|
6
|
+
if column.bigint?
|
7
|
+
spec = { id: :bigint.inspect }
|
8
|
+
spec[:default] = schema_default(column) || 'nil' unless column.auto_increment?
|
9
|
+
else
|
10
|
+
spec = super
|
11
|
+
end
|
12
|
+
spec[:unsigned] = 'true' if column.unsigned?
|
13
|
+
spec
|
14
|
+
end
|
15
|
+
|
16
|
+
def prepare_column_options(column)
|
17
|
+
spec = super
|
18
|
+
spec[:unsigned] = 'true' if column.unsigned?
|
19
|
+
spec
|
20
|
+
end
|
21
|
+
|
22
|
+
def migration_keys
|
23
|
+
super + [:unsigned]
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def default_primary_key?(column)
|
29
|
+
super && column.auto_increment?
|
30
|
+
end
|
31
|
+
|
32
|
+
def schema_type(column)
|
33
|
+
if column.sql_type == 'tinyblob'
|
34
|
+
:blob
|
35
|
+
else
|
36
|
+
super
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def schema_precision(column)
|
41
|
+
super unless /time/ === column.sql_type && column.precision == 0
|
42
|
+
end
|
43
|
+
|
44
|
+
def schema_collation(column)
|
45
|
+
if column.collation && table_name = column.table_name
|
46
|
+
@table_collation_cache ||= {}
|
47
|
+
@table_collation_cache[table_name] ||= select_one("SHOW TABLE STATUS LIKE '#{table_name}'")["Collation"]
|
48
|
+
column.collation.inspect if column.collation != @table_collation_cache[table_name]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module MySQL
|
4
|
+
class TypeMetadata < DelegateClass(SqlTypeMetadata) # :nodoc:
|
5
|
+
attr_reader :extra, :strict
|
6
|
+
|
7
|
+
def initialize(type_metadata, extra: "", strict: false)
|
8
|
+
super(type_metadata)
|
9
|
+
@type_metadata = type_metadata
|
10
|
+
@extra = extra
|
11
|
+
@strict = strict
|
12
|
+
end
|
13
|
+
|
14
|
+
def ==(other)
|
15
|
+
other.is_a?(MySQL::TypeMetadata) &&
|
16
|
+
attributes_for_hash == other.attributes_for_hash
|
17
|
+
end
|
18
|
+
alias eql? ==
|
19
|
+
|
20
|
+
def hash
|
21
|
+
attributes_for_hash.hash
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def attributes_for_hash
|
27
|
+
[self.class, @type_metadata, extra, strict]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'active_record/connection_adapters/abstract_mysql_adapter'
|
2
|
+
require 'active_record/connection_adapters/mysql/database_statements'
|
2
3
|
|
3
|
-
gem 'mysql2', '>= 0.3.
|
4
|
+
gem 'mysql2', '>= 0.3.18', '< 0.5'
|
4
5
|
require 'mysql2'
|
6
|
+
raise 'mysql2 0.4.3 is not supported. Please upgrade to 0.4.4+' if Mysql2::VERSION == '0.4.3'
|
5
7
|
|
6
8
|
module ActiveRecord
|
7
9
|
module ConnectionHandling # :nodoc:
|
@@ -10,17 +12,21 @@ module ActiveRecord
|
|
10
12
|
config = config.symbolize_keys
|
11
13
|
|
12
14
|
config[:username] = 'root' if config[:username].nil?
|
15
|
+
config[:flags] ||= 0
|
13
16
|
|
14
17
|
if Mysql2::Client.const_defined? :FOUND_ROWS
|
15
|
-
config[:flags]
|
18
|
+
if config[:flags].kind_of? Array
|
19
|
+
config[:flags].push "FOUND_ROWS".freeze
|
20
|
+
else
|
21
|
+
config[:flags] |= Mysql2::Client::FOUND_ROWS
|
22
|
+
end
|
16
23
|
end
|
17
24
|
|
18
25
|
client = Mysql2::Client.new(config)
|
19
|
-
|
20
|
-
ConnectionAdapters::Mysql2Adapter.new(client, logger, options, config)
|
26
|
+
ConnectionAdapters::Mysql2Adapter.new(client, logger, nil, config)
|
21
27
|
rescue Mysql2::Error => error
|
22
28
|
if error.message.include?("Unknown database")
|
23
|
-
raise ActiveRecord::NoDatabaseError
|
29
|
+
raise ActiveRecord::NoDatabaseError
|
24
30
|
else
|
25
31
|
raise
|
26
32
|
end
|
@@ -31,22 +37,27 @@ module ActiveRecord
|
|
31
37
|
class Mysql2Adapter < AbstractMysqlAdapter
|
32
38
|
ADAPTER_NAME = 'Mysql2'.freeze
|
33
39
|
|
40
|
+
include MySQL::DatabaseStatements
|
41
|
+
|
34
42
|
def initialize(connection, logger, connection_options, config)
|
35
43
|
super
|
36
|
-
@prepared_statements = false
|
44
|
+
@prepared_statements = false unless config.key?(:prepared_statements)
|
37
45
|
configure_connection
|
38
46
|
end
|
39
47
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
48
|
+
def supports_json?
|
49
|
+
!mariadb? && version >= '5.7.8'
|
50
|
+
end
|
51
|
+
|
52
|
+
def supports_comments?
|
53
|
+
true
|
47
54
|
end
|
48
55
|
|
49
|
-
def
|
56
|
+
def supports_comments_in_create?
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
def supports_savepoints?
|
50
61
|
true
|
51
62
|
end
|
52
63
|
|
@@ -79,6 +90,7 @@ module ActiveRecord
|
|
79
90
|
#++
|
80
91
|
|
81
92
|
def active?
|
93
|
+
return false unless @connection
|
82
94
|
@connection.ping
|
83
95
|
end
|
84
96
|
|
@@ -93,155 +105,10 @@ module ActiveRecord
|
|
93
105
|
# Otherwise, this method does nothing.
|
94
106
|
def disconnect!
|
95
107
|
super
|
96
|
-
@connection.
|
97
|
-
|
98
|
-
|
99
|
-
#--
|
100
|
-
# DATABASE STATEMENTS ======================================
|
101
|
-
#++
|
102
|
-
|
103
|
-
def explain(arel, binds = [])
|
104
|
-
sql = "EXPLAIN #{to_sql(arel, binds.dup)}"
|
105
|
-
start = Time.now
|
106
|
-
result = exec_query(sql, 'EXPLAIN', binds)
|
107
|
-
elapsed = Time.now - start
|
108
|
-
|
109
|
-
ExplainPrettyPrinter.new.pp(result, elapsed)
|
110
|
-
end
|
111
|
-
|
112
|
-
class ExplainPrettyPrinter # :nodoc:
|
113
|
-
# Pretty prints the result of a EXPLAIN in a way that resembles the output of the
|
114
|
-
# MySQL shell:
|
115
|
-
#
|
116
|
-
# +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
|
117
|
-
# | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|
118
|
-
# +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
|
119
|
-
# | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |
|
120
|
-
# | 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
|
121
|
-
# +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
|
122
|
-
# 2 rows in set (0.00 sec)
|
123
|
-
#
|
124
|
-
# This is an exercise in Ruby hyperrealism :).
|
125
|
-
def pp(result, elapsed)
|
126
|
-
widths = compute_column_widths(result)
|
127
|
-
separator = build_separator(widths)
|
128
|
-
|
129
|
-
pp = []
|
130
|
-
|
131
|
-
pp << separator
|
132
|
-
pp << build_cells(result.columns, widths)
|
133
|
-
pp << separator
|
134
|
-
|
135
|
-
result.rows.each do |row|
|
136
|
-
pp << build_cells(row, widths)
|
137
|
-
end
|
138
|
-
|
139
|
-
pp << separator
|
140
|
-
pp << build_footer(result.rows.length, elapsed)
|
141
|
-
|
142
|
-
pp.join("\n") + "\n"
|
143
|
-
end
|
144
|
-
|
145
|
-
private
|
146
|
-
|
147
|
-
def compute_column_widths(result)
|
148
|
-
[].tap do |widths|
|
149
|
-
result.columns.each_with_index do |column, i|
|
150
|
-
cells_in_column = [column] + result.rows.map {|r| r[i].nil? ? 'NULL' : r[i].to_s}
|
151
|
-
widths << cells_in_column.map(&:length).max
|
152
|
-
end
|
153
|
-
end
|
108
|
+
unless @connection.nil?
|
109
|
+
@connection.close
|
110
|
+
@connection = nil
|
154
111
|
end
|
155
|
-
|
156
|
-
def build_separator(widths)
|
157
|
-
padding = 1
|
158
|
-
'+' + widths.map {|w| '-' * (w + (padding*2))}.join('+') + '+'
|
159
|
-
end
|
160
|
-
|
161
|
-
def build_cells(items, widths)
|
162
|
-
cells = []
|
163
|
-
items.each_with_index do |item, i|
|
164
|
-
item = 'NULL' if item.nil?
|
165
|
-
justifier = item.is_a?(Numeric) ? 'rjust' : 'ljust'
|
166
|
-
cells << item.to_s.send(justifier, widths[i])
|
167
|
-
end
|
168
|
-
'| ' + cells.join(' | ') + ' |'
|
169
|
-
end
|
170
|
-
|
171
|
-
def build_footer(nrows, elapsed)
|
172
|
-
rows_label = nrows == 1 ? 'row' : 'rows'
|
173
|
-
"#{nrows} #{rows_label} in set (%.2f sec)" % elapsed
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
# FIXME: re-enable the following once a "better" query_cache solution is in core
|
178
|
-
#
|
179
|
-
# The overrides below perform much better than the originals in AbstractAdapter
|
180
|
-
# because we're able to take advantage of mysql2's lazy-loading capabilities
|
181
|
-
#
|
182
|
-
# # Returns a record hash with the column names as keys and column values
|
183
|
-
# # as values.
|
184
|
-
# def select_one(sql, name = nil)
|
185
|
-
# result = execute(sql, name)
|
186
|
-
# result.each(as: :hash) do |r|
|
187
|
-
# return r
|
188
|
-
# end
|
189
|
-
# end
|
190
|
-
#
|
191
|
-
# # Returns a single value from a record
|
192
|
-
# def select_value(sql, name = nil)
|
193
|
-
# result = execute(sql, name)
|
194
|
-
# if first = result.first
|
195
|
-
# first.first
|
196
|
-
# end
|
197
|
-
# end
|
198
|
-
#
|
199
|
-
# # Returns an array of the values of the first column in a select:
|
200
|
-
# # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
|
201
|
-
# def select_values(sql, name = nil)
|
202
|
-
# execute(sql, name).map { |row| row.first }
|
203
|
-
# end
|
204
|
-
|
205
|
-
# Returns an array of arrays containing the field values.
|
206
|
-
# Order is the same as that returned by +columns+.
|
207
|
-
def select_rows(sql, name = nil, binds = [])
|
208
|
-
execute(sql, name).to_a
|
209
|
-
end
|
210
|
-
|
211
|
-
# Executes the SQL statement in the context of this connection.
|
212
|
-
def execute(sql, name = nil)
|
213
|
-
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
214
|
-
# made since we established the connection
|
215
|
-
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
216
|
-
|
217
|
-
super
|
218
|
-
end
|
219
|
-
|
220
|
-
def exec_query(sql, name = 'SQL', binds = [])
|
221
|
-
result = execute(sql, name)
|
222
|
-
ActiveRecord::Result.new(result.fields, result.to_a)
|
223
|
-
end
|
224
|
-
|
225
|
-
alias exec_without_stmt exec_query
|
226
|
-
|
227
|
-
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
228
|
-
super
|
229
|
-
id_value || @connection.last_id
|
230
|
-
end
|
231
|
-
alias :create :insert_sql
|
232
|
-
|
233
|
-
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
|
234
|
-
execute to_sql(sql, binds), name
|
235
|
-
end
|
236
|
-
|
237
|
-
def exec_delete(sql, name, binds)
|
238
|
-
execute to_sql(sql, binds), name
|
239
|
-
@connection.affected_rows
|
240
|
-
end
|
241
|
-
alias :exec_update :exec_delete
|
242
|
-
|
243
|
-
def last_inserted_id(result)
|
244
|
-
@connection.last_id
|
245
112
|
end
|
246
113
|
|
247
114
|
private
|
@@ -259,10 +126,6 @@ module ActiveRecord
|
|
259
126
|
def full_version
|
260
127
|
@full_version ||= @connection.server_info[:version]
|
261
128
|
end
|
262
|
-
|
263
|
-
def set_field_encoding field_name
|
264
|
-
field_name
|
265
|
-
end
|
266
129
|
end
|
267
130
|
end
|
268
131
|
end
|