Class: DataMapper::Adapters::DataObjectsAdapter

You must inherit from the DoAdapter, and implement the required methods to adapt a database library for use with the DataMapper.

NOTE: By inheriting from DataObjectsAdapter, you get a copy of all the standard sub-modules (Quoting, Coersion and Queries) in your own Adapter. You can extend and overwrite these copies without affecting the originals.

Constructor Summary

private initialize(name, uri_or_options)
[View source]


340
341
342
343
344
345
346
347
348
349
350
351
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 340

def initialize(name, uri_or_options)
  super

  # Default the driver-specifc logger to DataMapper's logger
  if driver_module = DataObjects.const_get(@uri.scheme.capitalize) rescue nil




    driver_module.logger = DataMapper.logger if driver_module.respond_to?(:logger=)
  end
end

Public Visibility

Public Class Method Summary

type_map

Default TypeMap for all data object based adapters.

Returns:

Public Instance Method Summary

#avg(respository, property, query)
#count(repository, property, query)
#create(repository, resource)

all of our CRUD Methods dealing with a single resource object.

#create_model_storage(repository, model)

TODO: move to dm-more/dm-migrations.

#delete(repository, resource)
#destroy_model_storage(repository, model)

TODO: move to dm-more/dm-migrations.

#execute(statement, *args)

Database-specific method.

#max(respository, property, query)
#min(respository, property, query)
#query(statement, *args)
#read_set(repository, query)

Methods dealing with finding stuff by some query parameters.

#sum(respository, property, query)
#transaction_primitive

TODO: move to dm-more/dm-transactions.

#update(repository, resource)

def read(repository, model, bind_values)

 properties = model.
#upgrade_model_storage(repository, model)

TODO: move to dm-more/dm-migrations.

Public Class Method Details

type_map

public type_map

Default TypeMap for all data object based adapters.

Meta Tags

Returns:

<DataMapper::TypeMap> default TypeMap for data objects adapters.

[View source]


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 109

def self.type_map



  @type_map ||= TypeMap.new(super) do |tm|
    tm.map(Integer).to('INT')
    tm.map(String).to('VARCHAR').with(:size => Property::DEFAULT_LENGTH)
    tm.map(Class).to('VARCHAR').with(:size => Property::DEFAULT_LENGTH)
    tm.map(DM::Discriminator).to('VARCHAR').with(:size => Property::DEFAULT_LENGTH)
    tm.map(BigDecimal).to('DECIMAL').with(:scale => Property::DEFAULT_SCALE, :precision => Property::DEFAULT_PRECISION)
    tm.map(Float).to('FLOAT').with(:scale => Property::DEFAULT_SCALE, :precision => Property::DEFAULT_PRECISION)
    tm.map(DateTime).to('DATETIME')
    tm.map(Date).to('DATE')
    tm.map(Time).to('TIMESTAMP')
    tm.map(TrueClass).to('BOOLEAN')
    tm.map(Object).to('TEXT')
    tm.map(DM::Text).to('TEXT')
  end
end

Public Instance Method Details

avg

public avg(respository, property, query)
[View source]


21
22
23
24
25
# File 'dm-more/dm-aggregates/lib/dm-aggregates/adapters/data_objects_adapter.rb', line 21

def avg(respository, property, query)
  parameters = query.parameters
  avg = query(aggregate_value_statement(:avg, property, query), *parameters).first
  property.type == Integer ? avg.to_f : property.typecast(avg)
end

count

public count(repository, property, query)
[View source]


4
5
6
7
# File 'dm-more/dm-aggregates/lib/dm-aggregates/adapters/data_objects_adapter.rb', line 4

def count(repository, property, query)
  parameters = query.parameters
  query(aggregate_value_statement(:count, property, query), *parameters).first
end

create

public create(repository, resource)

all of our CRUD Methods dealing with a single resource object

[View source]


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 128

def create(repository, resource)
  dirty_attributes = resource.dirty_attributes

  identity_field = begin
    key = resource.class.key(name)
    key.first if key.size == 1 && key.first.serial?
  end

  statement = create_statement(resource.class, dirty_attributes, identity_field)
  bind_values = dirty_attributes.map { |p| resource.instance_variable_get(p.instance_variable_name) }

  result = execute(statement, *bind_values)

  return false if result.to_i != 1

  if identity_field




    resource.instance_variable_set(identity_field.instance_variable_name, result.insert_id)
  end

  true
end

create_model_storage

public create_model_storage(repository, model)

TODO: move to dm-more/dm-migrations

[View source]


275
276
277
278
279
280
281
282
283
284
285
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 275

def create_model_storage(repository, model)
  return false if storage_exists?(model.storage_name(name))

  execute(create_table_statement(model))

  (create_index_statements(model) + create_unique_index_statements(model)).each do |sql|
    execute(sql)
  end

  true
end

delete

public delete(repository, resource)
[View source]


193
194
195
196
197
198
199
200
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 193

def delete(repository, resource)
  key = resource.class.key(name)

  statement = delete_statement(resource.class, key)
  bind_values = key.map { |p| resource.instance_variable_get(p.instance_variable_name) }

  execute(statement, *bind_values).to_i == 1
end

destroy_model_storage

public destroy_model_storage(repository, model)

TODO: move to dm-more/dm-migrations

[View source]


288
289
290
291
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 288

def destroy_model_storage(repository, model)
  execute(drop_table_statement(model))
  true
end

execute

public execute(statement, *args)

Database-specific method

[View source]


225
226
227
228
229
230
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 225

def execute(statement, *args)
  with_connection do |connection|
    command = connection.create_command(statement)
    command.execute_non_query(*args)
  end
end

max

public max(respository, property, query)
[View source]


15
16
17
18
19
# File 'dm-more/dm-aggregates/lib/dm-aggregates/adapters/data_objects_adapter.rb', line 15

def max(respository, property, query)
  parameters = query.parameters
  max = query(aggregate_value_statement(:max, property, query), *parameters).first
  property.typecast(max)
end

min

public min(respository, property, query)
[View source]


9
10
11
12
13
# File 'dm-more/dm-aggregates/lib/dm-aggregates/adapters/data_objects_adapter.rb', line 9

def min(respository, property, query)
  parameters = query.parameters
  min = query(aggregate_value_statement(:min, property, query), *parameters).first
  property.typecast(min)
end

query

public query(statement, *args)
[View source]


232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 232

def query(statement, *args)
  with_reader(statement, *args) do |reader|
    results = []

    if (fields = reader.fields).size > 1




      fields = fields.map { |field| Extlib::Inflection.underscore(field).to_sym }
      struct = Struct.new(*fields)

      while(reader.next!) do
        results << struct.new(*reader.values)
      end
    else
      while(reader.next!) do
        results << reader.values.at(0)
      end
    end

    results
  end
end

read_set

public read_set(repository, query)

Methods dealing with finding stuff by some query parameters

[View source]


203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 203

def read_set(repository, query)
  Collection.new(query) do |set|
    with_connection do |connection|
      begin
        command = connection.create_command(query_read_statement(query))
        command.set_types(query.fields.map { |p| p.primitive })

        reader = command.execute_reader(*query.parameters)

        do_reload = query.reload?

        while(reader.next!)




          set.load(reader.values, do_reload)
        end
      ensure
        reader.close if reader
      end
    end
  end
end

sum

public sum(respository, property, query)
[View source]


27
28
29
30
31
# File 'dm-more/dm-aggregates/lib/dm-aggregates/adapters/data_objects_adapter.rb', line 27

def sum(respository, property, query)
  parameters = query.parameters
  sum = query(aggregate_value_statement(:sum, property, query), *parameters).first
  property.typecast(sum)
end

transaction_primitive

public transaction_primitive

TODO: move to dm-more/dm-transactions

[View source]


294
295
296
297
298
299
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 294

def transaction_primitive



  DataObjects::Transaction.create_for_uri(@uri)
end

update

public update(repository, resource)

def read(repository, model, bind_values)

 properties = model.properties(name).defaults

 key = model.key(name)

 set = Collection.new(Query.new(repository, model, model.key(name) => bind_values))

 statement = read_statement(model, properties, key)

 with_connection do |connection|
   command = connection.create_command(statement)
   command.set_types(properties.map { |p| p.primitive })

   begin
     reader = command.execute_reader(*bind_values)
     set.load(reader.values) if reader.next!
     set.first
   ensure
     reader.close if reader
   end
 end

end

[View source]


177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 177

def update(repository, resource)
  # FIXME: if the properties are in different repositories
  # won't this cause problems?
  dirty_attributes = resource.dirty_attributes

  return false if dirty_attributes.empty?

  key = resource.class.key(name)

  statement = update_statement(resource.class, dirty_attributes, key)
  bind_values = dirty_attributes.map { |p| resource.instance_variable_get(p.instance_variable_name) }
  key.each { |p| bind_values << resource.instance_variable_get(p.instance_variable_name) }

  execute(statement, *bind_values).to_i == 1
end

upgrade_model_storage

public upgrade_model_storage(repository, model)

TODO: move to dm-more/dm-migrations

[View source]


254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 254

def upgrade_model_storage(repository, model)
  table_name = model.storage_name(name)

  if success = create_model_storage(repository, model)




    return model.properties(name)
  end

  properties = []

  model.properties(name).each do |property|
    schema_hash = property_schema_hash(property, model)
    next if field_exists?(table_name, schema_hash[:name])
    statement = alter_table_add_column_statement(table_name, schema_hash)
    execute(statement)
    properties << property
  end

  properties
end

Protected Visibility

Protected Instance Method Summary

#close_connection(connection)

TODO: clean up once transaction related methods move to dm-more/dm-transactions.

#create_connection

TODO: clean up once transaction related methods move to dm-more/dm-transactions.

#normalize_uri(uri_or_options)

Protected Instance Method Details

close_connection

protected close_connection(connection)

TODO: clean up once transaction related methods move to dm-more/dm-transactions

[View source]


334
335
336
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 334

def close_connection(connection)
  connection.close unless within_transaction? && current_transaction.primitive_for(self).connection == connection
end

create_connection

protected create_connection

TODO: clean up once transaction related methods move to dm-more/dm-transactions

[View source]


323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 323

def create_connection



  if within_transaction?




    current_transaction.primitive_for(self).connection
  else
    # DataObjects::Connection.new(uri) will give you back the right
    # driver based on the Uri#scheme.
    DataObjects::Connection.new(@uri)
  end
end

normalize_uri

protected normalize_uri(uri_or_options)
[View source]


300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'dm-core/lib/dm-core/adapters/data_objects_adapter.rb', line 300

def normalize_uri(uri_or_options)
  if String === uri_or_options




    uri_or_options = Addressable::URI.parse(uri_or_options)
  end
  if Addressable::URI === uri_or_options




    return uri_or_options.normalize
  end

  adapter = uri_or_options.delete(:adapter)
  user = uri_or_options.delete(:username)
  password = uri_or_options.delete(:password)
  host = (uri_or_options.delete(:host) || "")
  port = uri_or_options.delete(:port)
  database = uri_or_options.delete(:database)
  query = uri_or_options.to_a.map { |pair| pair.join('=') }.join('&')
  query = nil if query == ""

  return Addressable::URI.new(
    adapter, user, password, host, port, database, query, nil
  )
end