datamapper 0.3.2 → 0.9.3
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/History.txt +0 -0
- data/Manifest.txt +5 -0
- data/README.txt +11 -0
- data/Rakefile +70 -0
- data/lib/datamapper.rb +8 -0
- metadata +152 -319
- data/CHANGELOG +0 -145
- data/FAQ +0 -96
- data/MIT-LICENSE +0 -22
- data/QUICKLINKS +0 -12
- data/README +0 -105
- data/environment.rb +0 -62
- data/example.rb +0 -156
- data/lib/data_mapper.rb +0 -88
- data/lib/data_mapper/adapters/abstract_adapter.rb +0 -43
- data/lib/data_mapper/adapters/data_object_adapter.rb +0 -480
- data/lib/data_mapper/adapters/mysql_adapter.rb +0 -72
- data/lib/data_mapper/adapters/postgresql_adapter.rb +0 -258
- data/lib/data_mapper/adapters/sql/coersion.rb +0 -134
- data/lib/data_mapper/adapters/sql/commands/load_command.rb +0 -545
- data/lib/data_mapper/adapters/sql/mappings/associations_set.rb +0 -34
- data/lib/data_mapper/adapters/sql/mappings/column.rb +0 -279
- data/lib/data_mapper/adapters/sql/mappings/conditions.rb +0 -172
- data/lib/data_mapper/adapters/sql/mappings/schema.rb +0 -60
- data/lib/data_mapper/adapters/sql/mappings/table.rb +0 -459
- data/lib/data_mapper/adapters/sql/quoting.rb +0 -24
- data/lib/data_mapper/adapters/sqlite3_adapter.rb +0 -159
- data/lib/data_mapper/associations.rb +0 -106
- data/lib/data_mapper/associations/belongs_to_association.rb +0 -160
- data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +0 -437
- data/lib/data_mapper/associations/has_many_association.rb +0 -283
- data/lib/data_mapper/associations/has_n_association.rb +0 -143
- data/lib/data_mapper/associations/reference.rb +0 -47
- data/lib/data_mapper/attributes.rb +0 -73
- data/lib/data_mapper/auto_migrations.rb +0 -36
- data/lib/data_mapper/base.rb +0 -17
- data/lib/data_mapper/callbacks.rb +0 -107
- data/lib/data_mapper/context.rb +0 -112
- data/lib/data_mapper/database.rb +0 -234
- data/lib/data_mapper/dependency_queue.rb +0 -28
- data/lib/data_mapper/embedded_value.rb +0 -145
- data/lib/data_mapper/identity_map.rb +0 -47
- data/lib/data_mapper/is/tree.rb +0 -121
- data/lib/data_mapper/migration.rb +0 -155
- data/lib/data_mapper/persistence.rb +0 -852
- data/lib/data_mapper/property.rb +0 -310
- data/lib/data_mapper/query.rb +0 -164
- data/lib/data_mapper/support/blank.rb +0 -35
- data/lib/data_mapper/support/connection_pool.rb +0 -117
- data/lib/data_mapper/support/enumerable.rb +0 -35
- data/lib/data_mapper/support/errors.rb +0 -16
- data/lib/data_mapper/support/inflector.rb +0 -265
- data/lib/data_mapper/support/object.rb +0 -54
- data/lib/data_mapper/support/serialization.rb +0 -96
- data/lib/data_mapper/support/silence.rb +0 -10
- data/lib/data_mapper/support/string.rb +0 -72
- data/lib/data_mapper/support/struct.rb +0 -7
- data/lib/data_mapper/support/symbol.rb +0 -82
- data/lib/data_mapper/support/typed_set.rb +0 -65
- data/lib/data_mapper/types/base.rb +0 -44
- data/lib/data_mapper/types/string.rb +0 -34
- data/lib/data_mapper/validatable_extensions/errors.rb +0 -12
- data/lib/data_mapper/validatable_extensions/macros.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validatable_instance_methods.rb +0 -62
- data/lib/data_mapper/validatable_extensions/validation_base.rb +0 -18
- data/lib/data_mapper/validatable_extensions/validations/formats/email.rb +0 -43
- data/lib/data_mapper/validatable_extensions/validations/validates_acceptance_of.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validations/validates_confirmation_of.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validations/validates_each.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validations/validates_format_of.rb +0 -28
- data/lib/data_mapper/validatable_extensions/validations/validates_length_of.rb +0 -15
- data/lib/data_mapper/validatable_extensions/validations/validates_numericality_of.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validations/validates_presence_of.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validations/validates_true_for.rb +0 -7
- data/lib/data_mapper/validatable_extensions/validations/validates_uniqueness_of.rb +0 -40
- data/lib/data_mapper/validations.rb +0 -20
- data/lib/data_mapper/validations/number_validator.rb +0 -40
- data/lib/data_mapper/validations/string_validator.rb +0 -20
- data/lib/data_mapper/validations/validator.rb +0 -13
- data/performance.rb +0 -307
- data/plugins/can_has_sphinx/LICENSE +0 -23
- data/plugins/can_has_sphinx/README +0 -4
- data/plugins/can_has_sphinx/REVISION +0 -1
- data/plugins/can_has_sphinx/Rakefile +0 -22
- data/plugins/can_has_sphinx/init.rb +0 -1
- data/plugins/can_has_sphinx/install.rb +0 -1
- data/plugins/can_has_sphinx/lib/acts_as_sphinx.rb +0 -123
- data/plugins/can_has_sphinx/lib/sphinx.rb +0 -460
- data/plugins/can_has_sphinx/scripts/sphinx.sh +0 -47
- data/plugins/can_has_sphinx/tasks/acts_as_sphinx_tasks.rake +0 -41
- data/profile_data_mapper.rb +0 -40
- data/rakefile.rb +0 -159
- data/spec/acts_as_tree_spec.rb +0 -67
- data/spec/adapters/data_object_adapter_spec.rb +0 -31
- data/spec/associations/belongs_to_association_spec.rb +0 -98
- data/spec/associations/has_and_belongs_to_many_association_spec.rb +0 -377
- data/spec/associations/has_many_association_spec.rb +0 -337
- data/spec/attributes_spec.rb +0 -52
- data/spec/auto_migrations_spec.rb +0 -101
- data/spec/callbacks_spec.rb +0 -186
- data/spec/can_has_sphinx.rb +0 -5
- data/spec/coersion_spec.rb +0 -41
- data/spec/column_spec.rb +0 -114
- data/spec/count_command_spec.rb +0 -45
- data/spec/database_spec.rb +0 -18
- data/spec/dataobjects_spec.rb +0 -27
- data/spec/delete_command_spec.rb +0 -11
- data/spec/dependency_spec.rb +0 -29
- data/spec/embedded_value_spec.rb +0 -161
- data/spec/fixtures/animals.yaml +0 -33
- data/spec/fixtures/animals_exhibits.yaml +0 -2
- data/spec/fixtures/careers.yaml +0 -5
- data/spec/fixtures/comments.yaml +0 -1
- data/spec/fixtures/exhibits.yaml +0 -90
- data/spec/fixtures/fruit.yaml +0 -6
- data/spec/fixtures/people.yaml +0 -37
- data/spec/fixtures/posts.yaml +0 -3
- data/spec/fixtures/projects.yaml +0 -13
- data/spec/fixtures/sections.yaml +0 -5
- data/spec/fixtures/serializers.yaml +0 -6
- data/spec/fixtures/tasks.yaml +0 -6
- data/spec/fixtures/tasks_tasks.yaml +0 -2
- data/spec/fixtures/tomatoes.yaml +0 -1
- data/spec/fixtures/users.yaml +0 -1
- data/spec/fixtures/zoos.yaml +0 -24
- data/spec/is_a_tree_spec.rb +0 -149
- data/spec/legacy_spec.rb +0 -16
- data/spec/load_command_spec.rb +0 -322
- data/spec/magic_columns_spec.rb +0 -26
- data/spec/migration_spec.rb +0 -267
- data/spec/mock_adapter.rb +0 -20
- data/spec/models/animal.rb +0 -12
- data/spec/models/candidate.rb +0 -8
- data/spec/models/career.rb +0 -7
- data/spec/models/chain.rb +0 -8
- data/spec/models/comment.rb +0 -6
- data/spec/models/exhibit.rb +0 -14
- data/spec/models/fence.rb +0 -7
- data/spec/models/fruit.rb +0 -8
- data/spec/models/job.rb +0 -8
- data/spec/models/person.rb +0 -30
- data/spec/models/post.rb +0 -14
- data/spec/models/project.rb +0 -41
- data/spec/models/sales_person.rb +0 -5
- data/spec/models/section.rb +0 -8
- data/spec/models/serializer.rb +0 -5
- data/spec/models/task.rb +0 -9
- data/spec/models/tomato.rb +0 -27
- data/spec/models/user.rb +0 -12
- data/spec/models/zoo.rb +0 -13
- data/spec/natural_key_spec.rb +0 -36
- data/spec/paranoia_spec.rb +0 -38
- data/spec/persistence_spec.rb +0 -479
- data/spec/postgres_spec.rb +0 -96
- data/spec/property_spec.rb +0 -151
- data/spec/query_spec.rb +0 -77
- data/spec/save_command_spec.rb +0 -94
- data/spec/schema_spec.rb +0 -8
- data/spec/serialize_spec.rb +0 -19
- data/spec/single_table_inheritance_spec.rb +0 -43
- data/spec/spec_helper.rb +0 -45
- data/spec/support/blank_spec.rb +0 -8
- data/spec/support/inflector_spec.rb +0 -41
- data/spec/support/object_spec.rb +0 -9
- data/spec/support/serialization_spec.rb +0 -61
- data/spec/support/silence_spec.rb +0 -15
- data/spec/support/string_spec.rb +0 -7
- data/spec/support/struct_spec.rb +0 -12
- data/spec/support/typed_set_spec.rb +0 -66
- data/spec/symbolic_operators_spec.rb +0 -27
- data/spec/table_spec.rb +0 -79
- data/spec/types/string.rb +0 -81
- data/spec/validates_confirmation_of_spec.rb +0 -55
- data/spec/validates_format_of_spec.rb +0 -78
- data/spec/validates_length_of_spec.rb +0 -117
- data/spec/validates_uniqueness_of_spec.rb +0 -92
- data/spec/validations/number_validator.rb +0 -59
- data/spec/validations/string_validator.rb +0 -14
- data/spec/validations_spec.rb +0 -141
- data/tasks/fixtures.rb +0 -53
|
@@ -1,545 +0,0 @@
|
|
|
1
|
-
module DataMapper
|
|
2
|
-
module Adapters
|
|
3
|
-
module Sql
|
|
4
|
-
module Commands
|
|
5
|
-
|
|
6
|
-
class LoadCommand
|
|
7
|
-
|
|
8
|
-
class Loader
|
|
9
|
-
|
|
10
|
-
def initialize(load_command, klass)
|
|
11
|
-
@load_command, @klass = load_command, klass
|
|
12
|
-
@columns = {}
|
|
13
|
-
@key = nil
|
|
14
|
-
@key_index = nil
|
|
15
|
-
@type_override_present = false
|
|
16
|
-
@type_override_index = nil
|
|
17
|
-
@type_override = nil
|
|
18
|
-
@database_context = load_command.database_context
|
|
19
|
-
@reload = load_command.reload?
|
|
20
|
-
@set = []
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def add_column(column, index)
|
|
24
|
-
if column.key?
|
|
25
|
-
@key = column
|
|
26
|
-
@key_index = index
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
if column.type == :class
|
|
30
|
-
@type_override_present = true
|
|
31
|
-
@type_override_index = index
|
|
32
|
-
@type_override = column
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
@columns[index] = column
|
|
36
|
-
|
|
37
|
-
self
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def materialize(values)
|
|
41
|
-
instance_id = @key.type_cast_value(values[@key_index])
|
|
42
|
-
instance = create_instance(instance_id,
|
|
43
|
-
if @type_override_present
|
|
44
|
-
@type_override.type_cast_value(values[@type_override_index]) || @klass
|
|
45
|
-
else
|
|
46
|
-
@klass
|
|
47
|
-
end
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
@klass.callbacks.execute(:before_materialize, instance)
|
|
51
|
-
|
|
52
|
-
type_casted_values = {}
|
|
53
|
-
|
|
54
|
-
@columns.each_pair do |index, column|
|
|
55
|
-
# This may be a little confusing, but we're
|
|
56
|
-
# setting both the original_value, and the
|
|
57
|
-
# instance-variable through method chaining to avoid
|
|
58
|
-
# lots of extra short-lived local variables.
|
|
59
|
-
begin
|
|
60
|
-
type_casted_values[column.name] = instance.instance_variable_set(
|
|
61
|
-
column.instance_variable_name,
|
|
62
|
-
column.type_cast_value(values[index])
|
|
63
|
-
)
|
|
64
|
-
rescue => e
|
|
65
|
-
raise MaterializationError.new("Failed to materialize column #{column.name.inspect} with value #{values[index].inspect}\n#{e.display}")
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
instance.original_values = type_casted_values
|
|
70
|
-
instance.instance_variable_set(:@loaded_set, @set)
|
|
71
|
-
@set << instance
|
|
72
|
-
|
|
73
|
-
@klass.callbacks.execute(:after_materialize, instance)
|
|
74
|
-
|
|
75
|
-
return instance
|
|
76
|
-
|
|
77
|
-
rescue => e
|
|
78
|
-
if e.is_a?(MaterializationError)
|
|
79
|
-
raise e
|
|
80
|
-
else
|
|
81
|
-
raise MaterializationError.new("Failed to materialize row: #{values.inspect}\n#{e.display}")
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def loaded_set
|
|
86
|
-
@set
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
private
|
|
90
|
-
|
|
91
|
-
def create_instance(instance_id, instance_type)
|
|
92
|
-
instance = @database_context.identity_map.get(@klass, instance_id)
|
|
93
|
-
|
|
94
|
-
if instance.nil? || @reload
|
|
95
|
-
instance = instance_type.allocate() if instance.nil?
|
|
96
|
-
instance.instance_variable_set(:@__key, instance_id)
|
|
97
|
-
instance.instance_variable_set(:@new_record, false)
|
|
98
|
-
@database_context.identity_map.set(instance)
|
|
99
|
-
elsif instance.new_record?
|
|
100
|
-
instance.instance_variable_set(:@__key, instance_id)
|
|
101
|
-
instance.instance_variable_set(:@new_record, false)
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
instance.database_context = @database_context
|
|
105
|
-
|
|
106
|
-
return instance
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
class ConditionsError < StandardError
|
|
112
|
-
|
|
113
|
-
attr_reader :inner_error
|
|
114
|
-
|
|
115
|
-
def initialize(clause, value, inner_error)
|
|
116
|
-
@clause, @value, @inner_error = clause, value, inner_error
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def message
|
|
120
|
-
"Conditions (:clause => #{@clause.inspect}, :value => #{@value.inspect}) failed: #{@inner_error}"
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def backtrace
|
|
124
|
-
@inner_error.backtrace
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
attr_reader :conditions, :database_context, :options
|
|
130
|
-
|
|
131
|
-
def initialize(adapter, database_context, primary_class, options = {})
|
|
132
|
-
@adapter, @database_context, @primary_class = adapter, database_context, primary_class
|
|
133
|
-
|
|
134
|
-
# BEGIN: Partion out the options hash into general options,
|
|
135
|
-
# and conditions.
|
|
136
|
-
standard_find_options = @adapter.class::FIND_OPTIONS
|
|
137
|
-
conditions_hash = {}
|
|
138
|
-
@options = {}
|
|
139
|
-
|
|
140
|
-
options.each do |key,value|
|
|
141
|
-
if standard_find_options.include?(key) && key != :conditions
|
|
142
|
-
@options[key] = value
|
|
143
|
-
else
|
|
144
|
-
conditions_hash[key] = value
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
# END
|
|
148
|
-
|
|
149
|
-
@order = @options[:order]
|
|
150
|
-
@limit = @options[:limit]
|
|
151
|
-
@offset = @options[:offset]
|
|
152
|
-
@reload = @options[:reload]
|
|
153
|
-
@instance_id = conditions_hash[:id]
|
|
154
|
-
@conditions = parse_conditions(conditions_hash)
|
|
155
|
-
@loaders = Hash.new { |h,k| h[k] = Loader.new(self, k) }
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# Display an overview of load options at a glance.
|
|
159
|
-
def inspect
|
|
160
|
-
<<-EOS.compress_lines % (object_id * 2)
|
|
161
|
-
#<#{self.class.name}:0x%x
|
|
162
|
-
@database=#{@adapter.name}
|
|
163
|
-
@reload=#{@reload.inspect}
|
|
164
|
-
@order=#{@order.inspect}
|
|
165
|
-
@limit=#{@limit.inspect}
|
|
166
|
-
@offset=#{@offset.inspect}
|
|
167
|
-
@options=#{@options.inspect}>
|
|
168
|
-
EOS
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
# Access the Conditions instance
|
|
172
|
-
def conditions
|
|
173
|
-
@conditions
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
# If +true+ then force the command to reload any objects
|
|
177
|
-
# already existing in the IdentityMap when executing.
|
|
178
|
-
def reload?
|
|
179
|
-
@reload
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
# Determine if there is a limitation on the number of
|
|
183
|
-
# instances returned in the results. If +nil+, no limit
|
|
184
|
-
# is set. Can be used in conjunction with #offset for
|
|
185
|
-
# paging through a set of results.
|
|
186
|
-
def limit
|
|
187
|
-
@limit
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
# Used in conjunction with #limit to page through a set
|
|
191
|
-
# of results.
|
|
192
|
-
def offset
|
|
193
|
-
@offset
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
def call
|
|
197
|
-
|
|
198
|
-
# Check to see if the query is for a specific id and return if found
|
|
199
|
-
#
|
|
200
|
-
# NOTE: If the :id option is an Array:
|
|
201
|
-
# We could search for loaded instance ids and reject from
|
|
202
|
-
# the Array for already loaded instances, but working under the
|
|
203
|
-
# assumption that we'll probably have to issue a query to find
|
|
204
|
-
# at-least some of the instances we're looking for, it's faster to
|
|
205
|
-
# just skip that and go straight for the query.
|
|
206
|
-
unless reload? || @instance_id.blank? || @instance_id.is_a?(Array)
|
|
207
|
-
# If the id is for only a single record, attempt to find it.
|
|
208
|
-
if instance = @database_context.identity_map.get(@primary_class, @instance_id)
|
|
209
|
-
return [instance]
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
results = []
|
|
214
|
-
|
|
215
|
-
# Execute the statement and load the objects.
|
|
216
|
-
@adapter.connection do |db|
|
|
217
|
-
sql, *parameters = to_parameterized_sql
|
|
218
|
-
command = db.create_command(sql)
|
|
219
|
-
command.execute_reader(*parameters) do |reader|
|
|
220
|
-
if @options.has_key?(:intercept_load)
|
|
221
|
-
load(reader, &@options[:intercept_load])
|
|
222
|
-
else
|
|
223
|
-
load(reader)
|
|
224
|
-
end
|
|
225
|
-
end
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
results += @loaders[@primary_class].loaded_set
|
|
229
|
-
|
|
230
|
-
return results
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
def load(reader)
|
|
234
|
-
# The following blocks are identical aside from the yield.
|
|
235
|
-
# It's written this way to avoid a conditional within each
|
|
236
|
-
# iterator, and to take advantage of the performance of
|
|
237
|
-
# yield vs. Proc#call.
|
|
238
|
-
if block_given?
|
|
239
|
-
reader.each do
|
|
240
|
-
@loaders.each_pair do |klass,loader|
|
|
241
|
-
row = reader.current_row
|
|
242
|
-
yield(loader.materialize(row), @columns, row)
|
|
243
|
-
end
|
|
244
|
-
end
|
|
245
|
-
else
|
|
246
|
-
reader.each do
|
|
247
|
-
@loaders.each_pair do |klass,loader|
|
|
248
|
-
loader.materialize(reader.current_row)
|
|
249
|
-
end
|
|
250
|
-
end
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
# Are any conditions present?
|
|
255
|
-
def conditions_empty?
|
|
256
|
-
@conditions.empty?
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
# Generate a select statement based on the initialization
|
|
260
|
-
# arguments.
|
|
261
|
-
def to_parameterized_sql
|
|
262
|
-
parameters = []
|
|
263
|
-
|
|
264
|
-
sql = 'SELECT ' << columns_for_select.join(', ')
|
|
265
|
-
sql << ' FROM ' << from_table_name
|
|
266
|
-
|
|
267
|
-
included_associations.each do |association|
|
|
268
|
-
sql << ' ' << association.to_sql
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
shallow_included_associations.each do |association|
|
|
272
|
-
sql << ' ' << association.to_shallow_sql
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
unless conditions_empty?
|
|
276
|
-
sql << ' WHERE ('
|
|
277
|
-
|
|
278
|
-
last_index = @conditions.size
|
|
279
|
-
current_index = 0
|
|
280
|
-
|
|
281
|
-
@conditions.each do |condition|
|
|
282
|
-
case condition
|
|
283
|
-
when String then sql << condition
|
|
284
|
-
when Array then
|
|
285
|
-
sql << condition.shift
|
|
286
|
-
parameters += condition
|
|
287
|
-
else
|
|
288
|
-
raise "Unable to parse condition: #{condition.inspect}" if condition
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
if (current_index += 1) == last_index
|
|
292
|
-
sql << ')'
|
|
293
|
-
else
|
|
294
|
-
sql << ') AND ('
|
|
295
|
-
end
|
|
296
|
-
end
|
|
297
|
-
end # unless conditions_empty?
|
|
298
|
-
|
|
299
|
-
unless @order.nil?
|
|
300
|
-
sql << ' ORDER BY ' << @order.to_s
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
unless @limit.nil?
|
|
304
|
-
sql << ' LIMIT ' << @limit.to_s
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
unless @offset.nil?
|
|
308
|
-
sql << ' OFFSET ' << @offset.to_s
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
parameters.unshift(sql)
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
# If more than one table is involved in the query, the column definitions should
|
|
315
|
-
# be qualified by the table name. ie: people.name
|
|
316
|
-
# This method determines wether that needs to happen or not.
|
|
317
|
-
# Note: After the first call, the calculations are avoided by overwriting this
|
|
318
|
-
# method with a simple getter.
|
|
319
|
-
def qualify_columns?
|
|
320
|
-
@qualify_columns = !(included_associations.empty? && shallow_included_associations.empty?)
|
|
321
|
-
def self.qualify_columns?
|
|
322
|
-
@qualify_columns
|
|
323
|
-
end
|
|
324
|
-
@qualify_columns
|
|
325
|
-
end
|
|
326
|
-
|
|
327
|
-
# expression_to_sql takes a set of arguments, and turns them into a an
|
|
328
|
-
# Array of generated SQL, followed by optional Values to interpolate as SQL-Parameters.
|
|
329
|
-
#
|
|
330
|
-
# Parameters:
|
|
331
|
-
# +clause+ The name of the column as a Symbol, a raw-SQL String, a Mappings::Column
|
|
332
|
-
# instance, or a Symbol::Operator.
|
|
333
|
-
# +value+ The Value for the condition.
|
|
334
|
-
# +collector+ An Array representing all conditions that is appended to by expression_to_sql
|
|
335
|
-
#
|
|
336
|
-
# Returns: Undefined Output. The work performed is added to the +collector+ argument.
|
|
337
|
-
# Example:
|
|
338
|
-
# conditions = []
|
|
339
|
-
# expression_to_sql(:name, 'Bob', conditions)
|
|
340
|
-
# => +undefined return value+
|
|
341
|
-
# conditions.inspect
|
|
342
|
-
# => ["name = ?", 'Bob']
|
|
343
|
-
def expression_to_sql(clause, value, collector)
|
|
344
|
-
qualify_columns = qualify_columns?
|
|
345
|
-
|
|
346
|
-
case clause
|
|
347
|
-
when Symbol::Operator then
|
|
348
|
-
operator = case clause.type
|
|
349
|
-
when :gt then '>'
|
|
350
|
-
when :gte then '>='
|
|
351
|
-
when :lt then '<'
|
|
352
|
-
when :lte then '<='
|
|
353
|
-
when :not then inequality_operator(value)
|
|
354
|
-
when :eql then equality_operator(value)
|
|
355
|
-
when :like then equality_operator(value, 'LIKE')
|
|
356
|
-
when :in then equality_operator(value)
|
|
357
|
-
else raise ArgumentError.new('Operator type not supported')
|
|
358
|
-
end
|
|
359
|
-
collector << ["#{primary_class_table[clause].to_sql(qualify_columns)} #{operator} ?", value]
|
|
360
|
-
when Symbol then
|
|
361
|
-
collector << ["#{primary_class_table[clause].to_sql(qualify_columns)} #{equality_operator(value)} ?", value]
|
|
362
|
-
when String then
|
|
363
|
-
collector << [clause, *value]
|
|
364
|
-
when Mappings::Column then
|
|
365
|
-
collector << ["#{clause.to_sql(qualify_columns)} #{equality_operator(value)} ?", value]
|
|
366
|
-
else raise "CAN HAS CRASH? #{clause.inspect}"
|
|
367
|
-
end
|
|
368
|
-
rescue => e
|
|
369
|
-
if e.is_a?(ConditionsError)
|
|
370
|
-
raise e
|
|
371
|
-
else
|
|
372
|
-
raise ConditionsError.new(clause, value, e)
|
|
373
|
-
end
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
private
|
|
377
|
-
# Return the Sql-escaped columns names to be selected in the results.
|
|
378
|
-
def columns_for_select
|
|
379
|
-
@columns_for_select || begin
|
|
380
|
-
qualify_columns = qualify_columns?
|
|
381
|
-
@columns_for_select = []
|
|
382
|
-
|
|
383
|
-
i = 0
|
|
384
|
-
columns.each do |column|
|
|
385
|
-
class_for_loader = column.table.klass
|
|
386
|
-
@loaders[class_for_loader].add_column(column, i) if class_for_loader
|
|
387
|
-
@columns_for_select << column.to_sql(qualify_columns)
|
|
388
|
-
i += 1
|
|
389
|
-
end
|
|
390
|
-
|
|
391
|
-
@columns_for_select
|
|
392
|
-
end
|
|
393
|
-
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
# Returns the DataMapper::Adapters::Sql::Mappings::Column instances to
|
|
397
|
-
# be selected in the results.
|
|
398
|
-
def columns
|
|
399
|
-
@columns || begin
|
|
400
|
-
@columns = primary_class_columns
|
|
401
|
-
@columns += included_columns
|
|
402
|
-
|
|
403
|
-
included_associations.each do |assoc|
|
|
404
|
-
@columns += assoc.associated_columns
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
shallow_included_associations.each do |assoc|
|
|
408
|
-
@columns += assoc.join_columns
|
|
409
|
-
end
|
|
410
|
-
|
|
411
|
-
@columns
|
|
412
|
-
end
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
# Returns the default columns for the primary_class_table,
|
|
416
|
-
# or maps symbols specified in a +:select+ option to columns
|
|
417
|
-
# in the primary_class_table.
|
|
418
|
-
def primary_class_columns
|
|
419
|
-
@primary_class_columns || @primary_class_columns = begin
|
|
420
|
-
if @options.has_key?(:select)
|
|
421
|
-
case x = @options[:select]
|
|
422
|
-
when Array then x
|
|
423
|
-
when Symbol then [x]
|
|
424
|
-
else raise ':select option must be a Symbol, or an Array of Symbols'
|
|
425
|
-
end.map { |name| primary_class_table[name] }
|
|
426
|
-
else
|
|
427
|
-
primary_class_table.columns.reject { |column| column.lazy? }
|
|
428
|
-
end
|
|
429
|
-
end
|
|
430
|
-
end
|
|
431
|
-
|
|
432
|
-
def included_associations
|
|
433
|
-
@included_associations || @included_associations = begin
|
|
434
|
-
associations = primary_class_table.associations
|
|
435
|
-
include_options.map do |name|
|
|
436
|
-
associations[name]
|
|
437
|
-
end.compact
|
|
438
|
-
end
|
|
439
|
-
end
|
|
440
|
-
|
|
441
|
-
def shallow_included_associations
|
|
442
|
-
@shallow_included_associations || @shallow_included_associations = begin
|
|
443
|
-
associations = primary_class_table.associations
|
|
444
|
-
shallow_include_options.map do |name|
|
|
445
|
-
associations[name]
|
|
446
|
-
end.compact
|
|
447
|
-
end
|
|
448
|
-
end
|
|
449
|
-
|
|
450
|
-
def included_columns
|
|
451
|
-
@included_columns || @included_columns = begin
|
|
452
|
-
include_options.map do |name|
|
|
453
|
-
primary_class_table[name]
|
|
454
|
-
end.compact
|
|
455
|
-
end
|
|
456
|
-
end
|
|
457
|
-
|
|
458
|
-
def include_options
|
|
459
|
-
@include_options || @include_options = begin
|
|
460
|
-
case x = @options[:include]
|
|
461
|
-
when Array then x
|
|
462
|
-
when Symbol then [x]
|
|
463
|
-
else []
|
|
464
|
-
end
|
|
465
|
-
end
|
|
466
|
-
end
|
|
467
|
-
|
|
468
|
-
def shallow_include_options
|
|
469
|
-
@shallow_include_options || @shallow_include_options = begin
|
|
470
|
-
case x = @options[:shallow_include]
|
|
471
|
-
when Array then x
|
|
472
|
-
when Symbol then [x]
|
|
473
|
-
else []
|
|
474
|
-
end
|
|
475
|
-
end
|
|
476
|
-
end
|
|
477
|
-
|
|
478
|
-
# Determine if a Column should be included based on the
|
|
479
|
-
# value of the +:include+ option.
|
|
480
|
-
def include_column?(name)
|
|
481
|
-
!primary_class_table[name].lazy? || include_options.includes?(name)
|
|
482
|
-
end
|
|
483
|
-
|
|
484
|
-
# Return the Sql-escaped table name of the +primary_class+.
|
|
485
|
-
def from_table_name
|
|
486
|
-
@from_table_name || (@from_table_name = @adapter.table(@primary_class).to_sql)
|
|
487
|
-
end
|
|
488
|
-
|
|
489
|
-
# Returns the DataMapper::Adapters::Sql::Mappings::Table for the +primary_class+.
|
|
490
|
-
def primary_class_table
|
|
491
|
-
@primary_class_table || (@primary_class_table = @adapter.table(@primary_class))
|
|
492
|
-
end
|
|
493
|
-
|
|
494
|
-
def parse_conditions(conditions_hash)
|
|
495
|
-
collection = []
|
|
496
|
-
|
|
497
|
-
case x = conditions_hash.delete(:conditions)
|
|
498
|
-
when Array then
|
|
499
|
-
# DO NOT mutate incoming Array values!!!
|
|
500
|
-
# Otherwise the mutated version may impact all the
|
|
501
|
-
# way up to the options passed to the finders,
|
|
502
|
-
# and have unintended side-effects.
|
|
503
|
-
array_copy = x.dup
|
|
504
|
-
clause = array_copy.shift
|
|
505
|
-
expression_to_sql(clause, array_copy, collection)
|
|
506
|
-
when Hash then
|
|
507
|
-
x.each_pair do |key,value|
|
|
508
|
-
expression_to_sql(key, value, collection)
|
|
509
|
-
end
|
|
510
|
-
else
|
|
511
|
-
raise "Unable to parse conditions: #{x.inspect}" if x
|
|
512
|
-
end
|
|
513
|
-
|
|
514
|
-
if primary_class_table.paranoid?
|
|
515
|
-
conditions_hash[primary_class_table.paranoid_column.name] = nil
|
|
516
|
-
end
|
|
517
|
-
|
|
518
|
-
conditions_hash.each_pair do |key,value|
|
|
519
|
-
expression_to_sql(key, value, collection)
|
|
520
|
-
end
|
|
521
|
-
|
|
522
|
-
collection
|
|
523
|
-
end
|
|
524
|
-
|
|
525
|
-
def equality_operator(value, default = '=')
|
|
526
|
-
case value
|
|
527
|
-
when NilClass then 'IS'
|
|
528
|
-
when Array then 'IN'
|
|
529
|
-
else default
|
|
530
|
-
end
|
|
531
|
-
end
|
|
532
|
-
|
|
533
|
-
def inequality_operator(value, default = '<>')
|
|
534
|
-
case value
|
|
535
|
-
when NilClass then 'IS NOT'
|
|
536
|
-
when Array then 'NOT IN'
|
|
537
|
-
else default
|
|
538
|
-
end
|
|
539
|
-
end
|
|
540
|
-
|
|
541
|
-
end # class LoadCommand
|
|
542
|
-
end # module Commands
|
|
543
|
-
end # module Sql
|
|
544
|
-
end # module Adapters
|
|
545
|
-
end # module DataMapper
|