activerecord 1.0.0 → 4.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 +7 -0
- data/CHANGELOG.md +2102 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +213 -0
- data/examples/performance.rb +172 -0
- data/examples/simple.rb +14 -0
- data/lib/active_record/aggregations.rb +180 -84
- data/lib/active_record/associations/alias_tracker.rb +76 -0
- data/lib/active_record/associations/association.rb +248 -0
- data/lib/active_record/associations/association_scope.rb +135 -0
- data/lib/active_record/associations/belongs_to_association.rb +92 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +35 -0
- data/lib/active_record/associations/builder/association.rb +108 -0
- data/lib/active_record/associations/builder/belongs_to.rb +98 -0
- data/lib/active_record/associations/builder/collection_association.rb +89 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +39 -0
- data/lib/active_record/associations/builder/has_many.rb +15 -0
- data/lib/active_record/associations/builder/has_one.rb +25 -0
- data/lib/active_record/associations/builder/singular_association.rb +32 -0
- data/lib/active_record/associations/collection_association.rb +608 -0
- data/lib/active_record/associations/collection_proxy.rb +986 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +58 -39
- data/lib/active_record/associations/has_many_association.rb +116 -85
- data/lib/active_record/associations/has_many_through_association.rb +197 -0
- data/lib/active_record/associations/has_one_association.rb +102 -0
- data/lib/active_record/associations/has_one_through_association.rb +36 -0
- data/lib/active_record/associations/join_dependency/join_association.rb +174 -0
- data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
- data/lib/active_record/associations/join_dependency.rb +235 -0
- data/lib/active_record/associations/join_helper.rb +45 -0
- data/lib/active_record/associations/preloader/association.rb +121 -0
- data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
- data/lib/active_record/associations/preloader/collection_association.rb +24 -0
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
- data/lib/active_record/associations/preloader/has_many.rb +17 -0
- data/lib/active_record/associations/preloader/has_many_through.rb +19 -0
- data/lib/active_record/associations/preloader/has_one.rb +23 -0
- data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
- data/lib/active_record/associations/preloader/singular_association.rb +21 -0
- data/lib/active_record/associations/preloader/through_association.rb +63 -0
- data/lib/active_record/associations/preloader.rb +178 -0
- data/lib/active_record/associations/singular_association.rb +64 -0
- data/lib/active_record/associations/through_association.rb +87 -0
- data/lib/active_record/associations.rb +1437 -431
- data/lib/active_record/attribute_assignment.rb +201 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +70 -0
- data/lib/active_record/attribute_methods/dirty.rb +118 -0
- data/lib/active_record/attribute_methods/primary_key.rb +122 -0
- data/lib/active_record/attribute_methods/query.rb +40 -0
- data/lib/active_record/attribute_methods/read.rb +107 -0
- data/lib/active_record/attribute_methods/serialization.rb +162 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -0
- data/lib/active_record/attribute_methods/write.rb +63 -0
- data/lib/active_record/attribute_methods.rb +393 -0
- data/lib/active_record/autosave_association.rb +426 -0
- data/lib/active_record/base.rb +268 -930
- data/lib/active_record/callbacks.rb +203 -230
- data/lib/active_record/coders/yaml_column.rb +38 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +638 -0
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +67 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +390 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +129 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +501 -0
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +873 -0
- data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +389 -275
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +782 -0
- data/lib/active_record/connection_adapters/column.rb +318 -0
- data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +273 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +517 -90
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
- data/lib/active_record/connection_adapters/postgresql/cast.rb +152 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +366 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +489 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +911 -138
- data/lib/active_record/connection_adapters/schema_cache.rb +129 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +624 -0
- data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
- data/lib/active_record/connection_handling.rb +98 -0
- data/lib/active_record/core.rb +463 -0
- data/lib/active_record/counter_cache.rb +122 -0
- data/lib/active_record/dynamic_matchers.rb +131 -0
- data/lib/active_record/errors.rb +213 -0
- data/lib/active_record/explain.rb +38 -0
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +29 -0
- data/lib/active_record/fixture_set/file.rb +55 -0
- data/lib/active_record/fixtures.rb +892 -138
- data/lib/active_record/inheritance.rb +200 -0
- data/lib/active_record/integration.rb +60 -0
- data/lib/active_record/locale/en.yml +47 -0
- data/lib/active_record/locking/optimistic.rb +181 -0
- data/lib/active_record/locking/pessimistic.rb +77 -0
- data/lib/active_record/log_subscriber.rb +82 -0
- data/lib/active_record/migration/command_recorder.rb +164 -0
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/migration.rb +1015 -0
- data/lib/active_record/model_schema.rb +345 -0
- data/lib/active_record/nested_attributes.rb +546 -0
- data/lib/active_record/null_relation.rb +65 -0
- data/lib/active_record/persistence.rb +509 -0
- data/lib/active_record/query_cache.rb +56 -0
- data/lib/active_record/querying.rb +62 -0
- data/lib/active_record/railtie.rb +205 -0
- data/lib/active_record/railties/console_sandbox.rb +5 -0
- data/lib/active_record/railties/controller_runtime.rb +50 -0
- data/lib/active_record/railties/databases.rake +402 -0
- data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
- data/lib/active_record/readonly_attributes.rb +30 -0
- data/lib/active_record/reflection.rb +544 -87
- data/lib/active_record/relation/batches.rb +93 -0
- data/lib/active_record/relation/calculations.rb +399 -0
- data/lib/active_record/relation/delegation.rb +125 -0
- data/lib/active_record/relation/finder_methods.rb +349 -0
- data/lib/active_record/relation/merger.rb +161 -0
- data/lib/active_record/relation/predicate_builder.rb +106 -0
- data/lib/active_record/relation/query_methods.rb +1044 -0
- data/lib/active_record/relation/spawn_methods.rb +73 -0
- data/lib/active_record/relation.rb +655 -0
- data/lib/active_record/result.rb +67 -0
- data/lib/active_record/runtime_registry.rb +17 -0
- data/lib/active_record/sanitization.rb +168 -0
- data/lib/active_record/schema.rb +65 -0
- data/lib/active_record/schema_dumper.rb +204 -0
- data/lib/active_record/schema_migration.rb +39 -0
- data/lib/active_record/scoping/default.rb +146 -0
- data/lib/active_record/scoping/named.rb +175 -0
- data/lib/active_record/scoping.rb +82 -0
- data/lib/active_record/serialization.rb +22 -0
- data/lib/active_record/serializers/xml_serializer.rb +197 -0
- data/lib/active_record/statement_cache.rb +26 -0
- data/lib/active_record/store.rb +156 -0
- data/lib/active_record/tasks/database_tasks.rb +203 -0
- data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +143 -0
- data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
- data/lib/active_record/test_case.rb +96 -0
- data/lib/active_record/timestamp.rb +119 -0
- data/lib/active_record/transactions.rb +366 -69
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/validations/associated.rb +49 -0
- data/lib/active_record/validations/presence.rb +65 -0
- data/lib/active_record/validations/uniqueness.rb +225 -0
- data/lib/active_record/validations.rb +64 -185
- data/lib/active_record/version.rb +11 -0
- data/lib/active_record.rb +149 -24
- data/lib/rails/generators/active_record/migration/migration_generator.rb +62 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +39 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +48 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +10 -0
- data/lib/rails/generators/active_record/model/templates/module.rb +7 -0
- data/lib/rails/generators/active_record.rb +23 -0
- metadata +261 -161
- data/CHANGELOG +0 -581
- data/README +0 -361
- data/RUNNING_UNIT_TESTS +0 -36
- data/dev-utils/eval_debugger.rb +0 -9
- data/examples/associations.png +0 -0
- data/examples/associations.rb +0 -87
- data/examples/shared_setup.rb +0 -15
- data/examples/validation.rb +0 -88
- data/install.rb +0 -60
- data/lib/active_record/associations/association_collection.rb +0 -70
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -107
- data/lib/active_record/deprecated_associations.rb +0 -70
- data/lib/active_record/observer.rb +0 -71
- data/lib/active_record/support/class_attribute_accessors.rb +0 -43
- data/lib/active_record/support/class_inheritable_attributes.rb +0 -37
- data/lib/active_record/support/clean_logger.rb +0 -10
- data/lib/active_record/support/inflector.rb +0 -70
- data/lib/active_record/vendor/mysql.rb +0 -1117
- data/lib/active_record/vendor/simple.rb +0 -702
- data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
- data/lib/active_record/wrappings.rb +0 -59
- data/rakefile +0 -122
- data/test/abstract_unit.rb +0 -16
- data/test/aggregations_test.rb +0 -34
- data/test/all.sh +0 -8
- data/test/associations_test.rb +0 -477
- data/test/base_test.rb +0 -513
- data/test/class_inheritable_attributes_test.rb +0 -33
- data/test/connections/native_mysql/connection.rb +0 -24
- data/test/connections/native_postgresql/connection.rb +0 -24
- data/test/connections/native_sqlite/connection.rb +0 -24
- data/test/deprecated_associations_test.rb +0 -336
- data/test/finder_test.rb +0 -67
- data/test/fixtures/accounts/signals37 +0 -3
- data/test/fixtures/accounts/unknown +0 -2
- data/test/fixtures/auto_id.rb +0 -4
- data/test/fixtures/column_name.rb +0 -3
- data/test/fixtures/companies/first_client +0 -6
- data/test/fixtures/companies/first_firm +0 -4
- data/test/fixtures/companies/second_client +0 -6
- data/test/fixtures/company.rb +0 -37
- data/test/fixtures/company_in_module.rb +0 -33
- data/test/fixtures/course.rb +0 -3
- data/test/fixtures/courses/java +0 -2
- data/test/fixtures/courses/ruby +0 -2
- data/test/fixtures/customer.rb +0 -30
- data/test/fixtures/customers/david +0 -6
- data/test/fixtures/db_definitions/mysql.sql +0 -96
- data/test/fixtures/db_definitions/mysql2.sql +0 -4
- data/test/fixtures/db_definitions/postgresql.sql +0 -113
- data/test/fixtures/db_definitions/postgresql2.sql +0 -4
- data/test/fixtures/db_definitions/sqlite.sql +0 -85
- data/test/fixtures/db_definitions/sqlite2.sql +0 -4
- data/test/fixtures/default.rb +0 -2
- data/test/fixtures/developer.rb +0 -8
- data/test/fixtures/developers/david +0 -2
- data/test/fixtures/developers/jamis +0 -2
- data/test/fixtures/developers_projects/david_action_controller +0 -2
- data/test/fixtures/developers_projects/david_active_record +0 -2
- data/test/fixtures/developers_projects/jamis_active_record +0 -2
- data/test/fixtures/entrant.rb +0 -3
- data/test/fixtures/entrants/first +0 -3
- data/test/fixtures/entrants/second +0 -3
- data/test/fixtures/entrants/third +0 -3
- data/test/fixtures/fixture_database.sqlite +0 -0
- data/test/fixtures/fixture_database_2.sqlite +0 -0
- data/test/fixtures/movie.rb +0 -5
- data/test/fixtures/movies/first +0 -2
- data/test/fixtures/movies/second +0 -2
- data/test/fixtures/project.rb +0 -3
- data/test/fixtures/projects/action_controller +0 -2
- data/test/fixtures/projects/active_record +0 -2
- data/test/fixtures/reply.rb +0 -21
- data/test/fixtures/subscriber.rb +0 -5
- data/test/fixtures/subscribers/first +0 -2
- data/test/fixtures/subscribers/second +0 -2
- data/test/fixtures/topic.rb +0 -20
- data/test/fixtures/topics/first +0 -9
- data/test/fixtures/topics/second +0 -8
- data/test/fixtures_test.rb +0 -20
- data/test/inflector_test.rb +0 -104
- data/test/inheritance_test.rb +0 -125
- data/test/lifecycle_test.rb +0 -110
- data/test/modules_test.rb +0 -21
- data/test/multiple_db_test.rb +0 -46
- data/test/pk_test.rb +0 -57
- data/test/reflection_test.rb +0 -78
- data/test/thread_safety_test.rb +0 -33
- data/test/transactions_test.rb +0 -83
- data/test/unconnected_test.rb +0 -24
- data/test/validations_test.rb +0 -126
@@ -1,326 +1,440 @@
|
|
1
|
-
require 'benchmark'
|
2
1
|
require 'date'
|
2
|
+
require 'bigdecimal'
|
3
|
+
require 'bigdecimal/util'
|
4
|
+
require 'active_support/core_ext/benchmark'
|
5
|
+
require 'active_record/connection_adapters/schema_cache'
|
6
|
+
require 'active_record/connection_adapters/abstract/schema_dumper'
|
7
|
+
require 'monitor'
|
3
8
|
|
4
9
|
module ActiveRecord
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
module ConnectionAdapters # :nodoc:
|
11
|
+
extend ActiveSupport::Autoload
|
12
|
+
|
13
|
+
autoload :Column
|
14
|
+
autoload :ConnectionSpecification
|
15
|
+
|
16
|
+
autoload_at 'active_record/connection_adapters/abstract/schema_definitions' do
|
17
|
+
autoload :IndexDefinition
|
18
|
+
autoload :ColumnDefinition
|
19
|
+
autoload :TableDefinition
|
20
|
+
autoload :Table
|
21
|
+
autoload :AlterTable
|
11
22
|
end
|
12
23
|
|
13
|
-
|
14
|
-
|
24
|
+
autoload_at 'active_record/connection_adapters/abstract/connection_pool' do
|
25
|
+
autoload :ConnectionHandler
|
26
|
+
autoload :ConnectionManagement
|
27
|
+
end
|
15
28
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
# "adapter" => "sqlite",
|
38
|
-
# "dbfile" => "path/to/dbfile"
|
39
|
-
# )
|
40
|
-
#
|
41
|
-
# The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
|
42
|
-
# may be returned on an error.
|
43
|
-
#
|
44
|
-
# == Connecting to another database for a single model
|
45
|
-
#
|
46
|
-
# To support different connections for different classes, you can
|
47
|
-
# simply call establish_connection with the classes you wish to have
|
48
|
-
# different connections for:
|
29
|
+
autoload_under 'abstract' do
|
30
|
+
autoload :SchemaStatements
|
31
|
+
autoload :DatabaseStatements
|
32
|
+
autoload :DatabaseLimits
|
33
|
+
autoload :Quoting
|
34
|
+
autoload :ConnectionPool
|
35
|
+
autoload :QueryCache
|
36
|
+
end
|
37
|
+
|
38
|
+
autoload_at 'active_record/connection_adapters/abstract/transaction' do
|
39
|
+
autoload :ClosedTransaction
|
40
|
+
autoload :RealTransaction
|
41
|
+
autoload :SavepointTransaction
|
42
|
+
end
|
43
|
+
|
44
|
+
# Active Record supports multiple database systems. AbstractAdapter and
|
45
|
+
# related classes form the abstraction layer which makes this possible.
|
46
|
+
# An AbstractAdapter represents a connection to a database, and provides an
|
47
|
+
# abstract interface for database-specific functionality such as establishing
|
48
|
+
# a connection, escaping values, building the right SQL fragments for ':offset'
|
49
|
+
# and ':limit' options, etc.
|
49
50
|
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
51
|
+
# All the concrete database adapters follow the interface laid down in this class.
|
52
|
+
# ActiveRecord::Base.connection returns an AbstractAdapter object, which
|
53
|
+
# you can use.
|
53
54
|
#
|
54
|
-
#
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
Thread.current['active_connections'] ||= {}
|
78
|
-
if Thread.current['active_connections'][klass]
|
79
|
-
return Thread.current['active_connections'][klass]
|
80
|
-
elsif @@defined_connections[klass]
|
81
|
-
klass.connection = @@defined_connections[klass]
|
82
|
-
return self.connection
|
55
|
+
# Most of the methods in the adapter are useful during migrations. Most
|
56
|
+
# notably, the instance methods provided by SchemaStatement are very useful.
|
57
|
+
class AbstractAdapter
|
58
|
+
include Quoting, DatabaseStatements, SchemaStatements
|
59
|
+
include DatabaseLimits
|
60
|
+
include QueryCache
|
61
|
+
include ActiveSupport::Callbacks
|
62
|
+
include MonitorMixin
|
63
|
+
include ColumnDumper
|
64
|
+
|
65
|
+
SIMPLE_INT = /\A\d+\z/
|
66
|
+
|
67
|
+
define_callbacks :checkout, :checkin
|
68
|
+
|
69
|
+
attr_accessor :visitor, :pool
|
70
|
+
attr_reader :schema_cache, :last_use, :in_use, :logger
|
71
|
+
alias :in_use? :in_use
|
72
|
+
|
73
|
+
def self.type_cast_config_to_integer(config)
|
74
|
+
if config =~ SIMPLE_INT
|
75
|
+
config.to_i
|
76
|
+
else
|
77
|
+
config
|
83
78
|
end
|
84
|
-
klass = klass.superclass
|
85
79
|
end
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
def self.connected?
|
91
|
-
klass = self
|
92
|
-
until klass == ActiveRecord::Base.superclass
|
93
|
-
if Thread.current['active_connections'].is_a?(Hash) && Thread.current['active_connections'][klass]
|
94
|
-
return true
|
80
|
+
|
81
|
+
def self.type_cast_config_to_boolean(config)
|
82
|
+
if config == "false"
|
83
|
+
false
|
95
84
|
else
|
96
|
-
|
85
|
+
config
|
97
86
|
end
|
98
87
|
end
|
99
|
-
return false
|
100
|
-
end
|
101
|
-
|
102
|
-
# Remove the connection for this class. This will close the active
|
103
|
-
# connection and the defined connection (if they exist). The result
|
104
|
-
# can be used as argument for establish_connection, for easy
|
105
|
-
# re-establishing of the connection.
|
106
|
-
def self.remove_connection(klass=self)
|
107
|
-
conn = @@defined_connections[klass]
|
108
|
-
@@defined_connections.delete(klass)
|
109
|
-
Thread.current['active_connections'] ||= {}
|
110
|
-
Thread.current['active_connections'][klass] = nil
|
111
|
-
conn.config if conn
|
112
|
-
end
|
113
|
-
|
114
|
-
# Set the connection for the class.
|
115
|
-
def self.connection=(spec)
|
116
|
-
raise ConnectionNotEstablished unless spec
|
117
|
-
conn = self.send(spec.adapter_method, spec.config)
|
118
|
-
Thread.current['active_connections'] ||= {}
|
119
|
-
Thread.current['active_connections'][self] = conn
|
120
|
-
end
|
121
88
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
89
|
+
def initialize(connection, logger = nil, pool = nil) #:nodoc:
|
90
|
+
super()
|
91
|
+
|
92
|
+
@connection = connection
|
93
|
+
@in_use = false
|
94
|
+
@instrumenter = ActiveSupport::Notifications.instrumenter
|
95
|
+
@last_use = false
|
96
|
+
@logger = logger
|
97
|
+
@pool = pool
|
98
|
+
@query_cache = Hash.new { |h,sql| h[sql] = {} }
|
99
|
+
@query_cache_enabled = false
|
100
|
+
@schema_cache = SchemaCache.new self
|
101
|
+
@visitor = nil
|
129
102
|
end
|
130
|
-
end
|
131
|
-
end
|
132
103
|
|
133
|
-
|
134
|
-
|
135
|
-
attr_reader :name, :default, :type, :limit
|
136
|
-
# The name should contain the name of the column, such as "name" in "name varchar(250)"
|
137
|
-
# The default should contain the type-casted default of the column, such as 1 in "count int(11) DEFAULT 1"
|
138
|
-
# The type parameter should either contain :integer, :float, :datetime, :date, :text, or :string
|
139
|
-
# The sql_type is just used for extracting the limit, such as 10 in "varchar(10)"
|
140
|
-
def initialize(name, default, sql_type = nil)
|
141
|
-
@name, @default, @type = name, default, simplified_type(sql_type)
|
142
|
-
@limit = extract_limit(sql_type) unless sql_type.nil?
|
143
|
-
end
|
144
|
-
|
145
|
-
def default
|
146
|
-
type_cast(@default)
|
147
|
-
end
|
148
|
-
|
149
|
-
def klass
|
150
|
-
case type
|
151
|
-
when :integer then Fixnum
|
152
|
-
when :float then Float
|
153
|
-
when :datetime then Time
|
154
|
-
when :date then Date
|
155
|
-
when :text, :string then String
|
156
|
-
when :boolean then Object
|
157
|
-
end
|
104
|
+
def valid_type?(type)
|
105
|
+
true
|
158
106
|
end
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
107
|
+
|
108
|
+
class SchemaCreation
|
109
|
+
def initialize(conn)
|
110
|
+
@conn = conn
|
111
|
+
@cache = {}
|
112
|
+
end
|
113
|
+
|
114
|
+
def accept(o)
|
115
|
+
m = @cache[o.class] ||= "visit_#{o.class.name.split('::').last}"
|
116
|
+
send m, o
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def visit_AlterTable(o)
|
122
|
+
sql = "ALTER TABLE #{quote_table_name(o.name)} "
|
123
|
+
sql << o.adds.map { |col| visit_AddColumn col }.join(' ')
|
124
|
+
end
|
125
|
+
|
126
|
+
def visit_AddColumn(o)
|
127
|
+
sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
|
128
|
+
sql = "ADD #{quote_column_name(o.name)} #{sql_type}"
|
129
|
+
add_column_options!(sql, column_options(o))
|
130
|
+
end
|
131
|
+
|
132
|
+
def visit_ColumnDefinition(o)
|
133
|
+
sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
|
134
|
+
column_sql = "#{quote_column_name(o.name)} #{sql_type}"
|
135
|
+
add_column_options!(column_sql, column_options(o)) unless o.primary_key?
|
136
|
+
column_sql
|
137
|
+
end
|
138
|
+
|
139
|
+
def visit_TableDefinition(o)
|
140
|
+
create_sql = "CREATE#{' TEMPORARY' if o.temporary} TABLE "
|
141
|
+
create_sql << "#{quote_table_name(o.name)} ("
|
142
|
+
create_sql << o.columns.map { |c| accept c }.join(', ')
|
143
|
+
create_sql << ") #{o.options}"
|
144
|
+
create_sql
|
145
|
+
end
|
146
|
+
|
147
|
+
def column_options(o)
|
148
|
+
column_options = {}
|
149
|
+
column_options[:null] = o.null unless o.null.nil?
|
150
|
+
column_options[:default] = o.default unless o.default.nil?
|
151
|
+
column_options[:column] = o
|
152
|
+
column_options
|
171
153
|
end
|
172
|
-
end
|
173
|
-
|
174
|
-
def human_name
|
175
|
-
Base.human_attribute_name(@name)
|
176
|
-
end
|
177
154
|
|
178
|
-
|
179
|
-
|
180
|
-
return string if Date === string
|
181
|
-
date_array = ParseDate.parsedate(string)
|
182
|
-
# treat 0000-00-00 as nil
|
183
|
-
Date.new(date_array[0], date_array[1], date_array[2]) rescue nil
|
155
|
+
def quote_column_name(name)
|
156
|
+
@conn.quote_column_name name
|
184
157
|
end
|
185
|
-
|
186
|
-
def
|
187
|
-
|
188
|
-
time_array = ParseDate.parsedate(string).compact
|
189
|
-
# treat 0000-00-00 00:00:00 as nil
|
190
|
-
Time.local(*time_array) rescue nil
|
158
|
+
|
159
|
+
def quote_table_name(name)
|
160
|
+
@conn.quote_table_name name
|
191
161
|
end
|
192
162
|
|
193
|
-
def
|
194
|
-
|
163
|
+
def type_to_sql(type, limit, precision, scale)
|
164
|
+
@conn.type_to_sql type.to_sym, limit, precision, scale
|
195
165
|
end
|
196
166
|
|
197
|
-
def
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
:boolean
|
167
|
+
def add_column_options!(column_sql, column_options)
|
168
|
+
@conn.add_column_options! column_sql, column_options
|
169
|
+
column_sql
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def schema_creation
|
174
|
+
SchemaCreation.new self
|
175
|
+
end
|
176
|
+
|
177
|
+
def lease
|
178
|
+
synchronize do
|
179
|
+
unless in_use
|
180
|
+
@in_use = true
|
181
|
+
@last_use = Time.now
|
213
182
|
end
|
214
183
|
end
|
215
|
-
|
184
|
+
end
|
216
185
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
186
|
+
def schema_cache=(cache)
|
187
|
+
cache.connection = self
|
188
|
+
@schema_cache = cache
|
189
|
+
end
|
190
|
+
|
191
|
+
def expire
|
192
|
+
@in_use = false
|
193
|
+
end
|
194
|
+
|
195
|
+
def unprepared_visitor
|
196
|
+
self.class::BindSubstitution.new self
|
197
|
+
end
|
198
|
+
|
199
|
+
def unprepared_statement
|
200
|
+
old, @visitor = @visitor, unprepared_visitor
|
201
|
+
yield
|
202
|
+
ensure
|
203
|
+
@visitor = old
|
204
|
+
end
|
222
205
|
|
223
|
-
|
206
|
+
# Returns the human-readable name of the adapter. Use mixed case - one
|
207
|
+
# can always use downcase if needed.
|
208
|
+
def adapter_name
|
209
|
+
'Abstract'
|
210
|
+
end
|
224
211
|
|
225
|
-
|
226
|
-
|
227
|
-
|
212
|
+
# Does this adapter support migrations? Backend specific, as the
|
213
|
+
# abstract adapter always returns +false+.
|
214
|
+
def supports_migrations?
|
215
|
+
false
|
228
216
|
end
|
229
217
|
|
230
|
-
#
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
218
|
+
# Can this adapter determine the primary key for tables not attached
|
219
|
+
# to an Active Record class, such as join tables? Backend specific, as
|
220
|
+
# the abstract adapter always returns +false+.
|
221
|
+
def supports_primary_key?
|
222
|
+
false
|
223
|
+
end
|
235
224
|
|
236
|
-
#
|
237
|
-
|
225
|
+
# Does this adapter support using DISTINCT within COUNT? This is +true+
|
226
|
+
# for all adapters except sqlite.
|
227
|
+
def supports_count_distinct?
|
228
|
+
true
|
229
|
+
end
|
238
230
|
|
239
|
-
#
|
240
|
-
|
231
|
+
# Does this adapter support DDL rollbacks in transactions? That is, would
|
232
|
+
# CREATE TABLE or ALTER TABLE get rolled back by a transaction? PostgreSQL,
|
233
|
+
# SQL Server, and others support this. MySQL and others do not.
|
234
|
+
def supports_ddl_transactions?
|
235
|
+
false
|
236
|
+
end
|
241
237
|
|
242
|
-
|
243
|
-
|
238
|
+
def supports_bulk_alter?
|
239
|
+
false
|
240
|
+
end
|
244
241
|
|
245
|
-
#
|
246
|
-
|
242
|
+
# Does this adapter support savepoints? PostgreSQL and MySQL do,
|
243
|
+
# SQLite < 3.6.8 does not.
|
244
|
+
def supports_savepoints?
|
245
|
+
false
|
246
|
+
end
|
247
247
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
248
|
+
# Should primary key values be selected from their corresponding
|
249
|
+
# sequence before the insert statement? If true, next_sequence_value
|
250
|
+
# is called before each insert to set the record's primary key.
|
251
|
+
# This is false for all adapters but Firebird.
|
252
|
+
def prefetch_primary_key?(table_name = nil)
|
253
|
+
false
|
252
254
|
end
|
253
255
|
|
254
|
-
#
|
255
|
-
def
|
256
|
-
|
257
|
-
|
258
|
-
def commit_db_transaction() end
|
256
|
+
# Does this adapter support index sort order?
|
257
|
+
def supports_index_sort_order?
|
258
|
+
false
|
259
|
+
end
|
259
260
|
|
260
|
-
#
|
261
|
-
|
262
|
-
|
261
|
+
# Does this adapter support partial indices?
|
262
|
+
def supports_partial_index?
|
263
|
+
false
|
264
|
+
end
|
263
265
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
when TrueClass then (column && column.type == :boolean ? "'t'" : "1")
|
269
|
-
when FalseClass then (column && column.type == :boolean ? "'f'" : "0")
|
270
|
-
when Float, Fixnum, Bignum, Date then "'#{value.to_s}'"
|
271
|
-
when Time, DateTime then "'#{value.strftime("%Y-%m-%d %H:%M:%S")}'"
|
272
|
-
else "'#{value.to_yaml.gsub(/'/, "''")}'"
|
273
|
-
end
|
266
|
+
# Does this adapter support explain? As of this writing sqlite3,
|
267
|
+
# mysql2, and postgresql are the only ones that do.
|
268
|
+
def supports_explain?
|
269
|
+
false
|
274
270
|
end
|
275
271
|
|
276
|
-
|
277
|
-
|
272
|
+
# Does this adapter support setting the isolation level for a transaction?
|
273
|
+
def supports_transaction_isolation?
|
274
|
+
false
|
278
275
|
end
|
279
276
|
|
280
|
-
#
|
281
|
-
|
277
|
+
# Does this adapter support database extensions? As of this writing only
|
278
|
+
# postgresql does.
|
279
|
+
def supports_extensions?
|
280
|
+
false
|
281
|
+
end
|
282
282
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
else
|
289
|
-
result = nil
|
290
|
-
bm = measure { result = action.call(connection) }
|
291
|
-
@runtime += bm.real
|
292
|
-
log_info(sql, name, bm.real)
|
293
|
-
result
|
294
|
-
end
|
295
|
-
rescue => e
|
296
|
-
log_info("#{e.message}: #{sql}", name, 0)
|
297
|
-
raise ActiveRecord::StatementInvalid, "#{e.message}: #{sql}"
|
298
|
-
end
|
299
|
-
end
|
283
|
+
# A list of extensions, to be filled in by adapters that support them. At
|
284
|
+
# the moment only postgresql does.
|
285
|
+
def extensions
|
286
|
+
[]
|
287
|
+
end
|
300
288
|
|
301
|
-
|
302
|
-
|
289
|
+
# A list of index algorithms, to be filled by adapters that support them.
|
290
|
+
# MySQL and PostgreSQL have support for them right now.
|
291
|
+
def index_algorithms
|
292
|
+
{}
|
293
|
+
end
|
303
294
|
|
304
|
-
|
305
|
-
format_log_entry(
|
306
|
-
"#{name.nil? ? "SQL" : name} (#{sprintf("%f", runtime)})",
|
307
|
-
sql.gsub(/ +/, " ")
|
308
|
-
)
|
309
|
-
)
|
310
|
-
end
|
295
|
+
# QUOTING ==================================================
|
311
296
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
297
|
+
# Returns a bind substitution value given a +column+ and list of current
|
298
|
+
# +binds+.
|
299
|
+
def substitute_at(column, index)
|
300
|
+
Arel::Nodes::BindParam.new '?'
|
301
|
+
end
|
302
|
+
|
303
|
+
# REFERENTIAL INTEGRITY ====================================
|
304
|
+
|
305
|
+
# Override to turn off referential integrity while executing <tt>&block</tt>.
|
306
|
+
def disable_referential_integrity
|
307
|
+
yield
|
308
|
+
end
|
309
|
+
|
310
|
+
# CONNECTION MANAGEMENT ====================================
|
311
|
+
|
312
|
+
# Checks whether the connection to the database is still active. This includes
|
313
|
+
# checking whether the database is actually capable of responding, i.e. whether
|
314
|
+
# the connection isn't stale.
|
315
|
+
def active?
|
316
|
+
end
|
317
|
+
|
318
|
+
# Disconnects from the database if already connected, and establishes a
|
319
|
+
# new connection with the database. Implementors should call super if they
|
320
|
+
# override the default implementation.
|
321
|
+
def reconnect!
|
322
|
+
clear_cache!
|
323
|
+
reset_transaction
|
324
|
+
end
|
325
|
+
|
326
|
+
# Disconnects from the database if already connected. Otherwise, this
|
327
|
+
# method does nothing.
|
328
|
+
def disconnect!
|
329
|
+
clear_cache!
|
330
|
+
reset_transaction
|
331
|
+
end
|
332
|
+
|
333
|
+
# Reset the state of this connection, directing the DBMS to clear
|
334
|
+
# transactions and other connection-related server-side state. Usually a
|
335
|
+
# database-dependent operation.
|
336
|
+
#
|
337
|
+
# The default implementation does nothing; the implementation should be
|
338
|
+
# overridden by concrete adapters.
|
339
|
+
def reset!
|
340
|
+
# this should be overridden by concrete adapters
|
341
|
+
end
|
342
|
+
|
343
|
+
###
|
344
|
+
# Clear any caching the database adapter may be doing, for example
|
345
|
+
# clearing the prepared statement cache. This is database specific.
|
346
|
+
def clear_cache!
|
347
|
+
# this should be overridden by concrete adapters
|
348
|
+
end
|
349
|
+
|
350
|
+
# Returns true if its required to reload the connection between requests for development mode.
|
351
|
+
# This is not the case for Ruby/MySQL and it's not necessary for any adapters except SQLite.
|
352
|
+
def requires_reloading?
|
353
|
+
false
|
354
|
+
end
|
355
|
+
|
356
|
+
# Checks whether the connection to the database is still active (i.e. not stale).
|
357
|
+
# This is done under the hood by calling <tt>active?</tt>. If the connection
|
358
|
+
# is no longer active, then this method will reconnect to the database.
|
359
|
+
def verify!(*ignored)
|
360
|
+
reconnect! unless active?
|
361
|
+
end
|
362
|
+
|
363
|
+
# Provides access to the underlying database driver for this adapter. For
|
364
|
+
# example, this method returns a Mysql object in case of MysqlAdapter,
|
365
|
+
# and a PGconn object in case of PostgreSQLAdapter.
|
366
|
+
#
|
367
|
+
# This is useful for when you need to call a proprietary method such as
|
368
|
+
# PostgreSQL's lo_* methods.
|
369
|
+
def raw_connection
|
370
|
+
@connection
|
371
|
+
end
|
372
|
+
|
373
|
+
def open_transactions
|
374
|
+
@transaction.number
|
375
|
+
end
|
376
|
+
|
377
|
+
def increment_open_transactions
|
378
|
+
ActiveSupport::Deprecation.warn "#increment_open_transactions is deprecated and has no effect"
|
379
|
+
end
|
380
|
+
|
381
|
+
def decrement_open_transactions
|
382
|
+
ActiveSupport::Deprecation.warn "#decrement_open_transactions is deprecated and has no effect"
|
383
|
+
end
|
384
|
+
|
385
|
+
def transaction_joinable=(joinable)
|
386
|
+
message = "#transaction_joinable= is deprecated. Please pass the :joinable option to #begin_transaction instead."
|
387
|
+
ActiveSupport::Deprecation.warn message
|
388
|
+
@transaction.joinable = joinable
|
389
|
+
end
|
390
|
+
|
391
|
+
def create_savepoint
|
392
|
+
end
|
393
|
+
|
394
|
+
def rollback_to_savepoint
|
395
|
+
end
|
396
|
+
|
397
|
+
def release_savepoint
|
398
|
+
end
|
399
|
+
|
400
|
+
def case_sensitive_modifier(node)
|
401
|
+
node
|
402
|
+
end
|
403
|
+
|
404
|
+
def case_insensitive_comparison(table, attribute, column, value)
|
405
|
+
table[attribute].lower.eq(table.lower(value))
|
406
|
+
end
|
407
|
+
|
408
|
+
def current_savepoint_name
|
409
|
+
"active_record_#{open_transactions}"
|
410
|
+
end
|
411
|
+
|
412
|
+
# Check the connection back in to the connection pool
|
413
|
+
def close
|
414
|
+
pool.checkin self
|
415
|
+
end
|
416
|
+
|
417
|
+
protected
|
418
|
+
|
419
|
+
def log(sql, name = "SQL", binds = [])
|
420
|
+
@instrumenter.instrument(
|
421
|
+
"sql.active_record",
|
422
|
+
:sql => sql,
|
423
|
+
:name => name,
|
424
|
+
:connection_id => object_id,
|
425
|
+
:binds => binds) { yield }
|
426
|
+
rescue => e
|
427
|
+
message = "#{e.class.name}: #{e.message}: #{sql}"
|
428
|
+
@logger.error message if @logger
|
429
|
+
exception = translate_exception(e, message)
|
430
|
+
exception.set_backtrace e.backtrace
|
431
|
+
raise exception
|
432
|
+
end
|
433
|
+
|
434
|
+
def translate_exception(exception, message)
|
435
|
+
# override in derived class
|
436
|
+
ActiveRecord::StatementInvalid.new(message, exception)
|
437
|
+
end
|
324
438
|
end
|
325
439
|
end
|
326
440
|
end
|