datamapper-dm-core 0.9.11 → 0.10.0
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.
- data/.autotest +17 -14
- data/.gitignore +3 -1
- data/FAQ +6 -5
- data/History.txt +5 -39
- data/Manifest.txt +67 -76
- data/QUICKLINKS +1 -1
- data/README.txt +21 -15
- data/Rakefile +16 -15
- data/SPECS +2 -29
- data/TODO +1 -1
- data/dm-core.gemspec +11 -15
- data/lib/dm-core/adapters/abstract_adapter.rb +182 -185
- data/lib/dm-core/adapters/data_objects_adapter.rb +482 -534
- data/lib/dm-core/adapters/in_memory_adapter.rb +90 -69
- data/lib/dm-core/adapters/mysql_adapter.rb +22 -115
- data/lib/dm-core/adapters/oracle_adapter.rb +249 -0
- data/lib/dm-core/adapters/postgres_adapter.rb +7 -173
- data/lib/dm-core/adapters/sqlite3_adapter.rb +4 -97
- data/lib/dm-core/adapters/yaml_adapter.rb +116 -0
- data/lib/dm-core/adapters.rb +135 -16
- data/lib/dm-core/associations/many_to_many.rb +372 -90
- data/lib/dm-core/associations/many_to_one.rb +220 -73
- data/lib/dm-core/associations/one_to_many.rb +319 -255
- data/lib/dm-core/associations/one_to_one.rb +66 -53
- data/lib/dm-core/associations/relationship.rb +560 -158
- data/lib/dm-core/collection.rb +1104 -381
- data/lib/dm-core/core_ext/kernel.rb +12 -0
- data/lib/dm-core/core_ext/symbol.rb +10 -0
- data/lib/dm-core/identity_map.rb +4 -34
- data/lib/dm-core/migrations.rb +1283 -0
- data/lib/dm-core/model/descendant_set.rb +81 -0
- data/lib/dm-core/model/hook.rb +45 -0
- data/lib/dm-core/model/is.rb +32 -0
- data/lib/dm-core/model/property.rb +248 -0
- data/lib/dm-core/model/relationship.rb +335 -0
- data/lib/dm-core/model/scope.rb +90 -0
- data/lib/dm-core/model.rb +570 -369
- data/lib/dm-core/property.rb +753 -280
- data/lib/dm-core/property_set.rb +141 -98
- data/lib/dm-core/query/conditions/comparison.rb +814 -0
- data/lib/dm-core/query/conditions/operation.rb +247 -0
- data/lib/dm-core/query/direction.rb +43 -0
- data/lib/dm-core/query/operator.rb +42 -0
- data/lib/dm-core/query/path.rb +102 -0
- data/lib/dm-core/query/sort.rb +45 -0
- data/lib/dm-core/query.rb +974 -492
- data/lib/dm-core/repository.rb +147 -107
- data/lib/dm-core/resource.rb +644 -429
- data/lib/dm-core/spec/adapter_shared_spec.rb +294 -0
- data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +106 -0
- data/lib/dm-core/support/chainable.rb +20 -0
- data/lib/dm-core/support/deprecate.rb +12 -0
- data/lib/dm-core/support/equalizer.rb +23 -0
- data/lib/dm-core/support/logger.rb +13 -0
- data/lib/dm-core/{naming_conventions.rb → support/naming_conventions.rb} +6 -6
- data/lib/dm-core/transaction.rb +333 -92
- data/lib/dm-core/type.rb +98 -60
- data/lib/dm-core/types/boolean.rb +1 -1
- data/lib/dm-core/types/discriminator.rb +34 -20
- data/lib/dm-core/types/object.rb +7 -4
- data/lib/dm-core/types/paranoid_boolean.rb +11 -9
- data/lib/dm-core/types/paranoid_datetime.rb +11 -9
- data/lib/dm-core/types/serial.rb +3 -3
- data/lib/dm-core/types/text.rb +3 -4
- data/lib/dm-core/version.rb +1 -1
- data/lib/dm-core.rb +106 -110
- data/script/performance.rb +102 -109
- data/script/profile.rb +169 -38
- data/spec/lib/adapter_helpers.rb +105 -0
- data/spec/lib/collection_helpers.rb +18 -0
- data/spec/lib/counter_adapter.rb +34 -0
- data/spec/lib/pending_helpers.rb +27 -0
- data/spec/lib/rspec_immediate_feedback_formatter.rb +53 -0
- data/spec/public/associations/many_to_many_spec.rb +193 -0
- data/spec/public/associations/many_to_one_spec.rb +73 -0
- data/spec/public/associations/one_to_many_spec.rb +77 -0
- data/spec/public/associations/one_to_one_spec.rb +156 -0
- data/spec/public/collection_spec.rb +65 -0
- data/spec/public/model/relationship_spec.rb +924 -0
- data/spec/public/model_spec.rb +159 -0
- data/spec/public/property_spec.rb +829 -0
- data/spec/public/resource_spec.rb +71 -0
- data/spec/public/sel_spec.rb +44 -0
- data/spec/public/setup_spec.rb +145 -0
- data/spec/public/shared/association_collection_shared_spec.rb +317 -0
- data/spec/public/shared/collection_shared_spec.rb +1723 -0
- data/spec/public/shared/finder_shared_spec.rb +1619 -0
- data/spec/public/shared/resource_shared_spec.rb +924 -0
- data/spec/public/shared/sel_shared_spec.rb +112 -0
- data/spec/public/transaction_spec.rb +129 -0
- data/spec/public/types/discriminator_spec.rb +130 -0
- data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
- data/spec/semipublic/adapters/in_memory_adapter_spec.rb +12 -0
- data/spec/semipublic/adapters/mysql_adapter_spec.rb +17 -0
- data/spec/semipublic/adapters/oracle_adapter_spec.rb +194 -0
- data/spec/semipublic/adapters/postgres_adapter_spec.rb +17 -0
- data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +17 -0
- data/spec/semipublic/adapters/yaml_adapter_spec.rb +12 -0
- data/spec/semipublic/associations/many_to_one_spec.rb +53 -0
- data/spec/semipublic/associations/relationship_spec.rb +194 -0
- data/spec/semipublic/associations_spec.rb +177 -0
- data/spec/semipublic/collection_spec.rb +142 -0
- data/spec/semipublic/property_spec.rb +61 -0
- data/spec/semipublic/query/conditions_spec.rb +528 -0
- data/spec/semipublic/query/path_spec.rb +443 -0
- data/spec/semipublic/query_spec.rb +2626 -0
- data/spec/semipublic/resource_spec.rb +47 -0
- data/spec/semipublic/shared/resource_shared_spec.rb +126 -0
- data/spec/spec.opts +3 -1
- data/spec/spec_helper.rb +80 -57
- data/tasks/ci.rb +19 -31
- data/tasks/dm.rb +43 -48
- data/tasks/doc.rb +8 -11
- data/tasks/gemspec.rb +5 -5
- data/tasks/hoe.rb +15 -16
- data/tasks/install.rb +8 -10
- metadata +72 -93
- data/lib/dm-core/associations/relationship_chain.rb +0 -81
- data/lib/dm-core/associations.rb +0 -207
- data/lib/dm-core/auto_migrations.rb +0 -105
- data/lib/dm-core/dependency_queue.rb +0 -32
- data/lib/dm-core/hook.rb +0 -11
- data/lib/dm-core/is.rb +0 -16
- data/lib/dm-core/logger.rb +0 -232
- data/lib/dm-core/migrations/destructive_migrations.rb +0 -17
- data/lib/dm-core/migrator.rb +0 -29
- data/lib/dm-core/scope.rb +0 -58
- data/lib/dm-core/support/array.rb +0 -13
- data/lib/dm-core/support/assertions.rb +0 -8
- data/lib/dm-core/support/errors.rb +0 -23
- data/lib/dm-core/support/kernel.rb +0 -11
- data/lib/dm-core/support/symbol.rb +0 -41
- data/lib/dm-core/support.rb +0 -7
- data/lib/dm-core/type_map.rb +0 -80
- data/lib/dm-core/types.rb +0 -19
- data/script/all +0 -4
- data/spec/integration/association_spec.rb +0 -1382
- data/spec/integration/association_through_spec.rb +0 -203
- data/spec/integration/associations/many_to_many_spec.rb +0 -449
- data/spec/integration/associations/many_to_one_spec.rb +0 -163
- data/spec/integration/associations/one_to_many_spec.rb +0 -188
- data/spec/integration/auto_migrations_spec.rb +0 -413
- data/spec/integration/collection_spec.rb +0 -1073
- data/spec/integration/data_objects_adapter_spec.rb +0 -32
- data/spec/integration/dependency_queue_spec.rb +0 -46
- data/spec/integration/model_spec.rb +0 -197
- data/spec/integration/mysql_adapter_spec.rb +0 -85
- data/spec/integration/postgres_adapter_spec.rb +0 -731
- data/spec/integration/property_spec.rb +0 -253
- data/spec/integration/query_spec.rb +0 -514
- data/spec/integration/repository_spec.rb +0 -61
- data/spec/integration/resource_spec.rb +0 -513
- data/spec/integration/sqlite3_adapter_spec.rb +0 -352
- data/spec/integration/sti_spec.rb +0 -273
- data/spec/integration/strategic_eager_loading_spec.rb +0 -156
- data/spec/integration/transaction_spec.rb +0 -75
- data/spec/integration/type_spec.rb +0 -275
- data/spec/lib/logging_helper.rb +0 -18
- data/spec/lib/mock_adapter.rb +0 -27
- data/spec/lib/model_loader.rb +0 -100
- data/spec/lib/publicize_methods.rb +0 -28
- data/spec/models/content.rb +0 -16
- data/spec/models/vehicles.rb +0 -34
- data/spec/models/zoo.rb +0 -48
- data/spec/unit/adapters/abstract_adapter_spec.rb +0 -133
- data/spec/unit/adapters/adapter_shared_spec.rb +0 -15
- data/spec/unit/adapters/data_objects_adapter_spec.rb +0 -632
- data/spec/unit/adapters/in_memory_adapter_spec.rb +0 -98
- data/spec/unit/adapters/postgres_adapter_spec.rb +0 -133
- data/spec/unit/associations/many_to_many_spec.rb +0 -32
- data/spec/unit/associations/many_to_one_spec.rb +0 -159
- data/spec/unit/associations/one_to_many_spec.rb +0 -393
- data/spec/unit/associations/one_to_one_spec.rb +0 -7
- data/spec/unit/associations/relationship_spec.rb +0 -71
- data/spec/unit/associations_spec.rb +0 -242
- data/spec/unit/auto_migrations_spec.rb +0 -111
- data/spec/unit/collection_spec.rb +0 -182
- data/spec/unit/data_mapper_spec.rb +0 -35
- data/spec/unit/identity_map_spec.rb +0 -126
- data/spec/unit/is_spec.rb +0 -80
- data/spec/unit/migrator_spec.rb +0 -33
- data/spec/unit/model_spec.rb +0 -321
- data/spec/unit/naming_conventions_spec.rb +0 -36
- data/spec/unit/property_set_spec.rb +0 -90
- data/spec/unit/property_spec.rb +0 -753
- data/spec/unit/query_spec.rb +0 -571
- data/spec/unit/repository_spec.rb +0 -93
- data/spec/unit/resource_spec.rb +0 -649
- data/spec/unit/scope_spec.rb +0 -142
- data/spec/unit/transaction_spec.rb +0 -493
- data/spec/unit/type_map_spec.rb +0 -114
- data/spec/unit/type_spec.rb +0 -119
data/lib/dm-core.rb
CHANGED
|
@@ -4,27 +4,20 @@
|
|
|
4
4
|
# * Requires fastthread, support libs, and base.
|
|
5
5
|
# * Sets the application root and environment for compatibility with frameworks
|
|
6
6
|
# such as Rails or Merb.
|
|
7
|
-
# * Checks for the database.yml and loads it if it exists.
|
|
8
|
-
# * Sets up the database using the config from the Yaml file or from the
|
|
9
|
-
# environment.
|
|
10
7
|
#
|
|
11
8
|
|
|
9
|
+
require 'addressable/uri'
|
|
10
|
+
require 'base64'
|
|
11
|
+
require 'bigdecimal'
|
|
12
|
+
require 'bigdecimal/util'
|
|
12
13
|
require 'date'
|
|
14
|
+
require 'extlib'
|
|
13
15
|
require 'pathname'
|
|
14
|
-
require 'rubygems'
|
|
15
16
|
require 'set'
|
|
16
17
|
require 'time'
|
|
17
18
|
require 'yaml'
|
|
18
19
|
|
|
19
|
-
gem 'addressable', '~>2.0.1'
|
|
20
|
-
require 'addressable/uri'
|
|
21
|
-
|
|
22
|
-
gem 'extlib', '~>0.9.11'
|
|
23
|
-
require 'extlib'
|
|
24
|
-
require 'extlib/inflection'
|
|
25
|
-
|
|
26
20
|
begin
|
|
27
|
-
gem 'fastthread', '~>1.0.1'
|
|
28
21
|
require 'fastthread'
|
|
29
22
|
rescue LoadError
|
|
30
23
|
# fastthread not installed
|
|
@@ -32,30 +25,58 @@ end
|
|
|
32
25
|
|
|
33
26
|
dir = Pathname(__FILE__).dirname.expand_path / 'dm-core'
|
|
34
27
|
|
|
35
|
-
require dir / 'support'
|
|
36
|
-
require dir / '
|
|
28
|
+
require dir / 'support' / 'chainable'
|
|
29
|
+
require dir / 'support' / 'deprecate'
|
|
30
|
+
require dir / 'support' / 'equalizer'
|
|
31
|
+
|
|
37
32
|
require dir / 'model'
|
|
33
|
+
require dir / 'model' / 'descendant_set'
|
|
34
|
+
require dir / 'model' / 'hook'
|
|
35
|
+
require dir / 'model' / 'is'
|
|
36
|
+
require dir / 'model' / 'scope'
|
|
37
|
+
require dir / 'model' / 'relationship'
|
|
38
|
+
require dir / 'model' / 'property'
|
|
38
39
|
|
|
39
|
-
require dir / '
|
|
40
|
-
|
|
41
|
-
require dir / '
|
|
42
|
-
require dir / '
|
|
43
|
-
require dir / '
|
|
44
|
-
require dir / 'associations'
|
|
45
|
-
require dir / '
|
|
40
|
+
require dir / 'collection'
|
|
41
|
+
|
|
42
|
+
require dir / 'adapters'
|
|
43
|
+
require dir / 'adapters' / 'abstract_adapter'
|
|
44
|
+
require dir / 'associations' / 'relationship'
|
|
45
|
+
require dir / 'associations' / 'one_to_many'
|
|
46
|
+
require dir / 'associations' / 'one_to_one'
|
|
47
|
+
require dir / 'associations' / 'many_to_one'
|
|
48
|
+
require dir / 'associations' / 'many_to_many'
|
|
46
49
|
require dir / 'identity_map'
|
|
47
|
-
require dir / '
|
|
48
|
-
require dir / '
|
|
49
|
-
require dir / 'naming_conventions'
|
|
50
|
+
require dir / 'migrations' # TODO: move to dm-more
|
|
51
|
+
require dir / 'property'
|
|
50
52
|
require dir / 'property_set'
|
|
51
53
|
require dir / 'query'
|
|
52
|
-
require dir / '
|
|
54
|
+
require dir / 'query' / 'conditions' / 'operation'
|
|
55
|
+
require dir / 'query' / 'conditions' / 'comparison'
|
|
56
|
+
require dir / 'query' / 'operator'
|
|
57
|
+
require dir / 'query' / 'direction'
|
|
58
|
+
require dir / 'query' / 'path'
|
|
59
|
+
require dir / 'query' / 'sort'
|
|
53
60
|
require dir / 'repository'
|
|
54
|
-
require dir / '
|
|
55
|
-
require dir / '
|
|
56
|
-
require dir / '
|
|
57
|
-
require dir / '
|
|
58
|
-
require dir / '
|
|
61
|
+
require dir / 'resource'
|
|
62
|
+
require dir / 'support' / 'logger'
|
|
63
|
+
require dir / 'support' / 'naming_conventions'
|
|
64
|
+
require dir / 'transaction' # TODO: move to dm-more
|
|
65
|
+
require dir / 'type'
|
|
66
|
+
require dir / 'types' / 'boolean'
|
|
67
|
+
require dir / 'types' / 'discriminator'
|
|
68
|
+
require dir / 'types' / 'text'
|
|
69
|
+
require dir / 'types' / 'paranoid_datetime' # TODO: move to dm-more
|
|
70
|
+
require dir / 'types' / 'paranoid_boolean' # TODO: move to dm-more
|
|
71
|
+
require dir / 'types' / 'object'
|
|
72
|
+
require dir / 'types' / 'serial'
|
|
73
|
+
require dir / 'version'
|
|
74
|
+
|
|
75
|
+
require dir / 'core_ext' / 'kernel' # TODO: do not load automatically
|
|
76
|
+
require dir / 'core_ext' / 'symbol' # TODO: do not load automatically
|
|
77
|
+
|
|
78
|
+
# A logger should always be present. Lets be consistent with DO
|
|
79
|
+
DataMapper::Logger.new(StringIO.new, :fatal)
|
|
59
80
|
|
|
60
81
|
# == Setup and Configuration
|
|
61
82
|
# DataMapper uses URIs or a connection hash to connect to your data-store.
|
|
@@ -76,10 +97,10 @@ require dir / 'is'
|
|
|
76
97
|
# address the data-store on the server.
|
|
77
98
|
#
|
|
78
99
|
# Here's some examples
|
|
79
|
-
# DataMapper.setup(:default,
|
|
80
|
-
# DataMapper.setup(:default,
|
|
100
|
+
# DataMapper.setup(:default, 'sqlite3://path/to/your/project/db/development.db')
|
|
101
|
+
# DataMapper.setup(:default, 'mysql://localhost/dm_core_test')
|
|
81
102
|
# # no auth-info
|
|
82
|
-
# DataMapper.setup(:default,
|
|
103
|
+
# DataMapper.setup(:default, 'postgres://root:supahsekret@127.0.0.1/dm_core_test')
|
|
83
104
|
# # with auth-info
|
|
84
105
|
#
|
|
85
106
|
#
|
|
@@ -88,7 +109,7 @@ require dir / 'is'
|
|
|
88
109
|
#
|
|
89
110
|
# DataMapper.setup(:default, {
|
|
90
111
|
# :adapter => 'adapter_name_here',
|
|
91
|
-
# :database =>
|
|
112
|
+
# :database => 'path/to/repo',
|
|
92
113
|
# :username => 'username',
|
|
93
114
|
# :password => 'password',
|
|
94
115
|
# :host => 'hostname'
|
|
@@ -97,67 +118,71 @@ require dir / 'is'
|
|
|
97
118
|
# === Logging
|
|
98
119
|
# To turn on error logging to STDOUT, issue:
|
|
99
120
|
#
|
|
100
|
-
# DataMapper::Logger.new(STDOUT,
|
|
121
|
+
# DataMapper::Logger.new(STDOUT, :debug)
|
|
101
122
|
#
|
|
102
123
|
# You can pass a file location ("/path/to/log/file.log") in place of STDOUT.
|
|
103
124
|
# see DataMapper::Logger for more information.
|
|
104
125
|
#
|
|
105
126
|
module DataMapper
|
|
106
|
-
extend Assertions
|
|
127
|
+
extend Extlib::Assertions
|
|
128
|
+
|
|
129
|
+
# TODO: move to dm-validations
|
|
130
|
+
class ValidationError < StandardError; end
|
|
131
|
+
|
|
132
|
+
class ObjectNotFoundError < StandardError; end
|
|
133
|
+
|
|
134
|
+
class RepositoryNotSetupError < StandardError; end
|
|
135
|
+
|
|
136
|
+
class IncompleteModelError < StandardError; end
|
|
107
137
|
|
|
138
|
+
class PluginNotFoundError < StandardError; end
|
|
139
|
+
|
|
140
|
+
class UpdateConflictError < StandardError; end
|
|
141
|
+
|
|
142
|
+
class UnknownRelationshipError < StandardError; end
|
|
143
|
+
|
|
144
|
+
# Raised on attempt to operate on collection of child objects
|
|
145
|
+
# when parent object is not yet saved.
|
|
146
|
+
# For instance, if your article object is not saved,
|
|
147
|
+
# but you try to fetch or scope down comments (1:n case), or
|
|
148
|
+
# publications (n:m case), operation cannot be completed
|
|
149
|
+
# because parent object's keys are not yet persisted,
|
|
150
|
+
# and thus there is no FK value to use in the query.
|
|
151
|
+
class UnsavedParentError < RuntimeError; end
|
|
152
|
+
|
|
153
|
+
# TODO: document
|
|
154
|
+
# @api private
|
|
108
155
|
def self.root
|
|
109
|
-
@root ||= Pathname(__FILE__).dirname.parent.expand_path
|
|
156
|
+
@root ||= Pathname(__FILE__).dirname.parent.expand_path.freeze
|
|
110
157
|
end
|
|
111
158
|
|
|
112
|
-
##
|
|
113
159
|
# Setups up a connection to a data-store
|
|
114
160
|
#
|
|
115
|
-
# @param Symbol name
|
|
116
|
-
#
|
|
161
|
+
# @param [Symbol] name
|
|
162
|
+
# a name for the context, defaults to :default
|
|
163
|
+
# @param [Hash(Symbol => String), Addressable::URI, String] uri_or_options
|
|
117
164
|
# connection information
|
|
118
165
|
#
|
|
119
|
-
# @return
|
|
166
|
+
# @return [DataMapper::Adapters::AbstractAdapter]
|
|
167
|
+
# the resulting setup adapter
|
|
120
168
|
#
|
|
121
|
-
# @raise ArgumentError "+name+ must be a Symbol, but was..."
|
|
122
|
-
# an invalid argument was passed for name[Symbol]
|
|
123
|
-
# @raise [ArgumentError] "+uri_or_options+ must be a Hash, URI or String,
|
|
124
|
-
#
|
|
125
|
-
#
|
|
169
|
+
# @raise [ArgumentError] "+name+ must be a Symbol, but was..."
|
|
170
|
+
# indicates that an invalid argument was passed for name[Symbol]
|
|
171
|
+
# @raise [ArgumentError] "+uri_or_options+ must be a Hash, URI or String, but was..."
|
|
172
|
+
# indicates that connection information could not be gleaned from
|
|
173
|
+
# the given uri_or_options[Hash, Addressable::URI, String]
|
|
126
174
|
#
|
|
127
|
-
# -
|
|
128
175
|
# @api public
|
|
129
|
-
def self.setup(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
when Hash
|
|
135
|
-
adapter_name = uri_or_options[:adapter].to_s
|
|
136
|
-
when String, DataObjects::URI, Addressable::URI
|
|
137
|
-
uri_or_options = DataObjects::URI.parse(uri_or_options) if uri_or_options.kind_of?(String)
|
|
138
|
-
adapter_name = uri_or_options.scheme
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
class_name = Extlib::Inflection.classify(adapter_name) + 'Adapter'
|
|
142
|
-
|
|
143
|
-
unless Adapters::const_defined?(class_name)
|
|
144
|
-
lib_name = "#{Extlib::Inflection.underscore(adapter_name)}_adapter"
|
|
145
|
-
begin
|
|
146
|
-
require root / 'lib' / 'dm-core' / 'adapters' / lib_name
|
|
147
|
-
rescue LoadError => e
|
|
148
|
-
begin
|
|
149
|
-
require lib_name
|
|
150
|
-
rescue Exception
|
|
151
|
-
# library not found, raise the original error
|
|
152
|
-
raise e
|
|
153
|
-
end
|
|
154
|
-
end
|
|
176
|
+
def self.setup(*args)
|
|
177
|
+
adapter = if args.first.kind_of?(Adapters::AbstractAdapter)
|
|
178
|
+
args.first
|
|
179
|
+
else
|
|
180
|
+
DataMapper::Adapters.new(*args)
|
|
155
181
|
end
|
|
156
182
|
|
|
157
|
-
Repository.adapters[name] =
|
|
183
|
+
Repository.adapters[adapter.name] = adapter
|
|
158
184
|
end
|
|
159
185
|
|
|
160
|
-
##
|
|
161
186
|
# Block Syntax
|
|
162
187
|
# Pushes the named repository onto the context-stack,
|
|
163
188
|
# yields a new session, and pops the context-stack.
|
|
@@ -167,12 +192,14 @@ module DataMapper
|
|
|
167
192
|
# a new Session.
|
|
168
193
|
#
|
|
169
194
|
# @param [Symbol] args the name of a repository to act within or return, :default is default
|
|
195
|
+
#
|
|
170
196
|
# @yield [Proc] (optional) block to execute within the context of the named repository
|
|
171
|
-
#
|
|
172
|
-
|
|
197
|
+
#
|
|
198
|
+
# @api public
|
|
199
|
+
def self.repository(name = nil)
|
|
173
200
|
current_repository = if name
|
|
174
|
-
|
|
175
|
-
Repository.context.detect { |
|
|
201
|
+
assert_kind_of 'name', name, Symbol
|
|
202
|
+
Repository.context.detect { |repository| repository.name == name } || Repository.new(name)
|
|
176
203
|
else
|
|
177
204
|
Repository.context.last || Repository.new(Repository.default_name)
|
|
178
205
|
end
|
|
@@ -183,35 +210,4 @@ module DataMapper
|
|
|
183
210
|
current_repository
|
|
184
211
|
end
|
|
185
212
|
end
|
|
186
|
-
|
|
187
|
-
# A logger should always be present. Lets be consistent with DO
|
|
188
|
-
Logger.new(nil, :off)
|
|
189
|
-
|
|
190
|
-
##
|
|
191
|
-
# destructively migrates the repository upwards to match model definitions
|
|
192
|
-
#
|
|
193
|
-
# @param [Symbol] name repository to act on, :default is the default
|
|
194
|
-
def self.migrate!(name = Repository.default_name)
|
|
195
|
-
repository(name).migrate!
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
##
|
|
199
|
-
# drops and recreates the repository upwards to match model definitions
|
|
200
|
-
#
|
|
201
|
-
# @param [Symbol] name repository to act on, :default is the default
|
|
202
|
-
def self.auto_migrate!(repository_name = nil)
|
|
203
|
-
AutoMigrator.auto_migrate(repository_name)
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
def self.auto_upgrade!(repository_name = nil)
|
|
207
|
-
AutoMigrator.auto_upgrade(repository_name)
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
def self.prepare(*args, &blk)
|
|
211
|
-
yield repository(*args)
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
def self.dependency_queue
|
|
215
|
-
@dependency_queue ||= DependencyQueue.new
|
|
216
|
-
end
|
|
217
213
|
end
|
data/script/performance.rb
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
require File.join(File.dirname(__FILE__), '..', 'lib', 'dm-core')
|
|
4
|
-
require File.join(File.dirname(__FILE__), '..', 'lib', 'dm-core', 'version')
|
|
1
|
+
#!/usr/bin/env ruby -KU
|
|
5
2
|
|
|
6
3
|
require 'ftools'
|
|
7
4
|
require 'rubygems'
|
|
8
5
|
|
|
9
|
-
gem '
|
|
10
|
-
|
|
6
|
+
gem 'activerecord', '~>2.3.2'
|
|
7
|
+
gem 'addressable', '~>2.0'
|
|
8
|
+
gem 'faker', '~>0.3.1'
|
|
9
|
+
gem 'rbench', '~>0.2.3'
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
require 'active_record'
|
|
12
|
+
require 'addressable/uri'
|
|
13
13
|
require 'faker'
|
|
14
|
+
require 'rbench'
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
require 'active_record'
|
|
16
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'dm-core'))
|
|
17
17
|
|
|
18
18
|
socket_file = Pathname.glob(%w[
|
|
19
19
|
/opt/local/var/run/mysql5/mysqld.sock
|
|
@@ -29,7 +29,7 @@ configuration_options = {
|
|
|
29
29
|
:adapter => 'mysql',
|
|
30
30
|
:username => 'root',
|
|
31
31
|
:password => '',
|
|
32
|
-
:database => '
|
|
32
|
+
:database => 'dm_core_test',
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
configuration_options[:socket] = socket_file unless socket_file.nil?
|
|
@@ -38,12 +38,12 @@ log_dir = DataMapper.root / 'log'
|
|
|
38
38
|
log_dir.mkdir unless log_dir.directory?
|
|
39
39
|
|
|
40
40
|
DataMapper::Logger.new(log_dir / 'dm.log', :off)
|
|
41
|
-
adapter = DataMapper.setup(:default, "mysql://root@localhost/
|
|
41
|
+
adapter = DataMapper.setup(:default, "mysql://root@localhost/dm_core_test?socket=#{socket_file}")
|
|
42
42
|
|
|
43
43
|
if configuration_options[:adapter]
|
|
44
|
-
sqlfile
|
|
45
|
-
mysql_bin
|
|
46
|
-
mysqldump_bin = %w[mysqldump mysqldump5].select{|bin| `which #{bin}`.length > 0 }
|
|
44
|
+
sqlfile = File.join(File.dirname(__FILE__), '..', 'tmp', 'performance.sql')
|
|
45
|
+
mysql_bin = %w[ mysql mysql5 ].select { |bin| `which #{bin}`.length > 0 }
|
|
46
|
+
mysqldump_bin = %w[ mysqldump mysqldump5 ].select { |bin| `which #{bin}`.length > 0 }
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
ActiveRecord::Base.logger = Logger.new(log_dir / 'ar.log')
|
|
@@ -61,46 +61,45 @@ class ARUser < ActiveRecord::Base #:nodoc:
|
|
|
61
61
|
set_table_name 'users'
|
|
62
62
|
|
|
63
63
|
has_many :exhibits, :foreign_key => 'user_id'
|
|
64
|
-
|
|
65
64
|
end
|
|
66
65
|
|
|
67
66
|
ARExhibit.find_by_sql('SELECT 1')
|
|
68
67
|
|
|
69
|
-
class
|
|
68
|
+
class User
|
|
70
69
|
include DataMapper::Resource
|
|
71
70
|
|
|
72
71
|
property :id, Serial
|
|
73
72
|
property :name, String
|
|
74
|
-
property :
|
|
75
|
-
property :
|
|
76
|
-
property :notes, Text, :lazy => true
|
|
73
|
+
property :email, String
|
|
74
|
+
property :about, Text, :lazy => false
|
|
77
75
|
property :created_on, Date
|
|
78
|
-
|
|
79
|
-
belongs_to :user
|
|
80
|
-
# property :updated_at, DateTime
|
|
81
76
|
end
|
|
82
77
|
|
|
83
|
-
class
|
|
78
|
+
class Exhibit
|
|
84
79
|
include DataMapper::Resource
|
|
85
80
|
|
|
86
|
-
property :id,
|
|
87
|
-
property :name,
|
|
88
|
-
property :
|
|
89
|
-
property :
|
|
81
|
+
property :id, Serial
|
|
82
|
+
property :name, String
|
|
83
|
+
property :zoo_id, Integer
|
|
84
|
+
property :user_id, Integer
|
|
85
|
+
property :notes, Text, :lazy => false
|
|
90
86
|
property :created_on, Date
|
|
91
87
|
|
|
88
|
+
belongs_to :user
|
|
92
89
|
end
|
|
93
90
|
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
DataMapper.auto_migrate!
|
|
92
|
+
|
|
93
|
+
def touch_attributes(*exhibits)
|
|
94
|
+
exhibits.flatten.each do |exhibit|
|
|
96
95
|
exhibit.id
|
|
97
96
|
exhibit.name
|
|
98
97
|
exhibit.created_on
|
|
99
98
|
end
|
|
100
99
|
end
|
|
101
100
|
|
|
102
|
-
touch_relationships
|
|
103
|
-
|
|
101
|
+
def touch_relationships(*exhibits)
|
|
102
|
+
exhibits.flatten.each do |exhibit|
|
|
104
103
|
exhibit.id
|
|
105
104
|
exhibit.name
|
|
106
105
|
exhibit.created_on
|
|
@@ -108,7 +107,6 @@ touch_relationships = lambda do |exhibits|
|
|
|
108
107
|
end
|
|
109
108
|
end
|
|
110
109
|
|
|
111
|
-
|
|
112
110
|
c = configuration_options
|
|
113
111
|
|
|
114
112
|
if sqlfile && File.exists?(sqlfile)
|
|
@@ -116,14 +114,7 @@ if sqlfile && File.exists?(sqlfile)
|
|
|
116
114
|
#adapter.execute("LOAD DATA LOCAL INFILE '#{sqlfile}' INTO TABLE exhibits")
|
|
117
115
|
`#{mysql_bin} -u #{c[:username]} #{"-p#{c[:password]}" unless c[:password].blank?} #{c[:database]} < #{sqlfile}`
|
|
118
116
|
else
|
|
119
|
-
|
|
120
|
-
puts "Generating data for benchmarking..."
|
|
121
|
-
|
|
122
|
-
User.auto_migrate!
|
|
123
|
-
Exhibit.auto_migrate!
|
|
124
|
-
|
|
125
|
-
users = []
|
|
126
|
-
exhibits = []
|
|
117
|
+
puts 'Generating data for benchmarking...'
|
|
127
118
|
|
|
128
119
|
# pre-compute the insert statements and fake data compilation,
|
|
129
120
|
# so the benchmarks below show the actual runtime for the execute
|
|
@@ -131,35 +122,30 @@ else
|
|
|
131
122
|
|
|
132
123
|
# Using the same paragraph for all exhibits because it is very slow
|
|
133
124
|
# to generate unique paragraphs for all exhibits.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
125
|
+
notes = Faker::Lorem.paragraphs.join($/)
|
|
126
|
+
today = Date.today
|
|
127
|
+
|
|
128
|
+
puts 'Inserting 10,000 users and exhibits...'
|
|
129
|
+
10_000.times do
|
|
130
|
+
user = User.create(
|
|
131
|
+
:created_on => today,
|
|
132
|
+
:name => Faker::Name.name,
|
|
133
|
+
:email => Faker::Internet.email
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
Exhibit.create(
|
|
137
|
+
:created_on => today,
|
|
138
|
+
:name => Faker::Company.name,
|
|
139
|
+
:user => user,
|
|
140
|
+
:notes => notes,
|
|
141
|
+
:zoo_id => rand(10).ceil
|
|
142
|
+
)
|
|
152
143
|
end
|
|
153
144
|
|
|
154
|
-
puts "Inserting 10,000 users..."
|
|
155
|
-
10_000.times { |i| adapter.execute(*users.at(i)) }
|
|
156
|
-
puts "Inserting 10,000 exhibits..."
|
|
157
|
-
10_000.times { |i| adapter.execute(*exhibits.at(i)) }
|
|
158
|
-
|
|
159
145
|
if sqlfile
|
|
160
146
|
answer = nil
|
|
161
147
|
until answer && answer[/^$|y|yes|n|no/]
|
|
162
|
-
print(
|
|
148
|
+
print('Would you like to dump data into tmp/performance.sql (for faster setup)? [Yn]');
|
|
163
149
|
STDOUT.flush
|
|
164
150
|
answer = gets
|
|
165
151
|
end
|
|
@@ -171,13 +157,12 @@ else
|
|
|
171
157
|
puts "File saved\n"
|
|
172
158
|
end
|
|
173
159
|
end
|
|
174
|
-
|
|
175
160
|
end
|
|
176
161
|
|
|
177
|
-
TIMES = ENV
|
|
162
|
+
TIMES = ENV.key?('x') ? ENV['x'].to_i : 10_000
|
|
178
163
|
|
|
179
|
-
puts
|
|
180
|
-
puts
|
|
164
|
+
puts 'You can specify how many times you want to run the benchmarks with rake:perf x=(number)'
|
|
165
|
+
puts 'Some tasks will be run 10 and 1000 times less than (number)'
|
|
181
166
|
puts "Benchmarks will now run #{TIMES} times"
|
|
182
167
|
# Inform about slow benchmark
|
|
183
168
|
# answer = nil
|
|
@@ -193,90 +178,98 @@ puts "Benchmarks will now run #{TIMES} times"
|
|
|
193
178
|
RBench.run(TIMES) do
|
|
194
179
|
|
|
195
180
|
column :times
|
|
196
|
-
column :ar, :title =>
|
|
181
|
+
column :ar, :title => 'AR 2.3.2'
|
|
197
182
|
column :dm, :title => "DM #{DataMapper::VERSION}"
|
|
198
|
-
column :diff, :compare => [:ar
|
|
183
|
+
column :diff, :compare => [:ar, :dm]
|
|
184
|
+
|
|
185
|
+
report 'Model#id', (TIMES * 100).ceil do
|
|
186
|
+
ar_obj = ARExhibit.find(1)
|
|
187
|
+
dm_obj = Exhibit.get(1)
|
|
188
|
+
|
|
189
|
+
ar { ar_obj.id }
|
|
190
|
+
dm { dm_obj.id }
|
|
191
|
+
end
|
|
199
192
|
|
|
200
|
-
report
|
|
193
|
+
report 'Model.new (instantiation)' do
|
|
201
194
|
ar { ARExhibit.new }
|
|
202
195
|
dm { Exhibit.new }
|
|
203
196
|
end
|
|
204
197
|
|
|
205
|
-
report
|
|
206
|
-
attrs = {:name => 'sam', :zoo_id => 1}
|
|
198
|
+
report 'Model.new (setting attributes)' do
|
|
199
|
+
attrs = { :name => 'sam', :zoo_id => 1 }
|
|
207
200
|
ar { ARExhibit.new(attrs) }
|
|
208
201
|
dm { Exhibit.new(attrs) }
|
|
209
202
|
end
|
|
210
203
|
|
|
211
|
-
report
|
|
212
|
-
ActiveRecord::Base.uncached { ar { touch_attributes
|
|
213
|
-
dm { touch_attributes
|
|
204
|
+
report 'Model.get specific (not cached)' do
|
|
205
|
+
ActiveRecord::Base.uncached { ar { touch_attributes(ARExhibit.find(1)) } }
|
|
206
|
+
dm { touch_attributes(Exhibit.get(1)) }
|
|
214
207
|
end
|
|
215
208
|
|
|
216
|
-
report
|
|
217
|
-
ActiveRecord::Base.cache
|
|
218
|
-
Exhibit.repository(:default) { dm { touch_attributes
|
|
209
|
+
report 'Model.get specific (cached)' do
|
|
210
|
+
ActiveRecord::Base.cache { ar { touch_attributes(ARExhibit.find(1)) } }
|
|
211
|
+
Exhibit.repository(:default) { dm { touch_attributes(Exhibit.get(1)) } }
|
|
219
212
|
end
|
|
220
213
|
|
|
221
|
-
report
|
|
222
|
-
ar { touch_attributes
|
|
223
|
-
dm { touch_attributes
|
|
214
|
+
report 'Model.first' do
|
|
215
|
+
ar { touch_attributes(ARExhibit.first) }
|
|
216
|
+
dm { touch_attributes(Exhibit.first) }
|
|
224
217
|
end
|
|
225
218
|
|
|
226
|
-
report
|
|
227
|
-
ar { touch_attributes
|
|
228
|
-
dm { touch_attributes
|
|
219
|
+
report 'Model.all limit(100)', (TIMES / 10).ceil do
|
|
220
|
+
ar { touch_attributes(ARExhibit.find(:all, :limit => 100)) }
|
|
221
|
+
dm { touch_attributes(Exhibit.all(:limit => 100)) }
|
|
229
222
|
end
|
|
230
223
|
|
|
231
|
-
report
|
|
232
|
-
ar { touch_relationships
|
|
233
|
-
dm { touch_relationships
|
|
224
|
+
report 'Model.all limit(100) with relationship', (TIMES / 10).ceil do
|
|
225
|
+
ar { touch_relationships(ARExhibit.all(:limit => 100, :include => [ :user ])) }
|
|
226
|
+
dm { touch_relationships(Exhibit.all(:limit => 100)) }
|
|
234
227
|
end
|
|
235
228
|
|
|
236
|
-
report
|
|
237
|
-
ar { touch_attributes
|
|
238
|
-
dm { touch_attributes
|
|
229
|
+
report 'Model.all limit(10,000)', (TIMES / 1000).ceil do
|
|
230
|
+
ar { touch_attributes(ARExhibit.find(:all, :limit => 10_000)) }
|
|
231
|
+
dm { touch_attributes(Exhibit.all(:limit => 10_000)) }
|
|
239
232
|
end
|
|
240
233
|
|
|
241
|
-
|
|
234
|
+
exhibit = {
|
|
242
235
|
:name => Faker::Company.name,
|
|
243
236
|
:zoo_id => rand(10).ceil,
|
|
244
237
|
:notes => Faker::Lorem.paragraphs.join($/),
|
|
245
238
|
:created_on => Date.today
|
|
246
239
|
}
|
|
247
240
|
|
|
248
|
-
report
|
|
249
|
-
ar { ARExhibit.create(
|
|
250
|
-
dm { Exhibit.create(
|
|
241
|
+
report 'Model.create' do
|
|
242
|
+
ar { ARExhibit.create(exhibit) }
|
|
243
|
+
dm { Exhibit.create(exhibit) }
|
|
251
244
|
end
|
|
252
245
|
|
|
253
|
-
report
|
|
254
|
-
attrs_first = {:name => 'sam', :zoo_id => 1}
|
|
255
|
-
attrs_second = {:name => 'tom', :zoo_id => 1}
|
|
256
|
-
ar {
|
|
257
|
-
dm {
|
|
246
|
+
report 'Resource#attributes=' do
|
|
247
|
+
attrs_first = { :name => 'sam', :zoo_id => 1 }
|
|
248
|
+
attrs_second = { :name => 'tom', :zoo_id => 1 }
|
|
249
|
+
ar { exhibit = ARExhibit.new(attrs_first); exhibit.attributes = attrs_second }
|
|
250
|
+
dm { exhibit = Exhibit.new(attrs_first); exhibit.attributes = attrs_second }
|
|
258
251
|
end
|
|
259
252
|
|
|
260
|
-
report
|
|
261
|
-
ar {
|
|
262
|
-
dm {
|
|
253
|
+
report 'Resource#update' do
|
|
254
|
+
ar { ARExhibit.find(1).update_attributes(:name => 'bob') }
|
|
255
|
+
dm { Exhibit.get(1).update(:name => 'bob') }
|
|
263
256
|
end
|
|
264
257
|
|
|
265
|
-
report
|
|
258
|
+
report 'Resource#destroy' do
|
|
266
259
|
ar { ARExhibit.first.destroy }
|
|
267
260
|
dm { Exhibit.first.destroy }
|
|
268
261
|
end
|
|
269
262
|
|
|
270
|
-
report
|
|
263
|
+
report 'Model.transaction' do
|
|
271
264
|
ar { ARExhibit.transaction { ARExhibit.new } }
|
|
272
265
|
dm { Exhibit.transaction { Exhibit.new } }
|
|
273
266
|
end
|
|
274
267
|
|
|
275
|
-
summary
|
|
268
|
+
summary 'Total'
|
|
276
269
|
end
|
|
277
270
|
|
|
278
|
-
connection = adapter.send(:
|
|
279
|
-
command = connection.create_command(
|
|
280
|
-
command = connection.create_command(
|
|
271
|
+
connection = adapter.send(:open_connection)
|
|
272
|
+
command = connection.create_command('DROP TABLE exhibits')
|
|
273
|
+
command = connection.create_command('DROP TABLE users')
|
|
281
274
|
command.execute_non_query rescue nil
|
|
282
275
|
connection.close
|