AbstractAdapter
DataObjectsAdapter is the base class for all adapers for relational databases. If you want to add support for a new RDBMS, it makes sense to make your adapter class inherit from this class.
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.
@api public
# File lib/dm-do-adapter/adapter.rb, line 265 265: def initialize(name, uri_or_options) 266: super 267: 268: # Default the driver-specific logger to DataMapper's logger 269: if driver_module = DataObjects.const_get(normalized_uri.scheme.capitalize) 270: driver_module.logger = DataMapper.logger if driver_module.respond_to?(:logger=) 271: end 272: end
For each model instance in resources, issues an SQL INSERT (or equivalent) statement to create a new record in the data store for the instance
Note that this method does not update the identity map. If a plugin needs to use an adapter directly, it is up to plugin developer to keep the identity map up to date.
@param [Enumerable(Resource)] resources
The list of resources (model instances) to create
@return [Integer]
The number of records that were actually saved into the database
@api semipublic
# File lib/dm-do-adapter/adapter.rb, line 82 82: def create(resources) 83: name = self.name 84: 85: resources.each do |resource| 86: model = resource.model 87: serial = model.serial(name) 88: attributes = resource.dirty_attributes 89: 90: properties = [] 91: bind_values = [] 92: 93: # make the order of the properties consistent 94: model.properties(name).each do |property| 95: next unless attributes.key?(property) 96: 97: bind_value = attributes[property] 98: 99: # skip insering NULL for columns that are serial or without a default 100: next if bind_value.nil? && (property.serial? || !property.default?) 101: 102: # if serial is being set explicitly, do not set it again 103: if property.equal?(serial) 104: serial = nil 105: end 106: 107: properties << property 108: bind_values << bind_value 109: end 110: 111: statement = insert_statement(model, properties, serial) 112: 113: result = with_connection do |connection| 114: connection.create_command(statement).execute_non_query(*bind_values) 115: end 116: 117: if result.affected_rows == 1 && serial 118: serial.set!(resource, result.insert_id) 119: end 120: end 121: end
Constructs and executes DELETE statement for given query
@param [Collection] collection
collection of records to be deleted
@return [Integer]
the number of records deleted
@api semipublic
# File lib/dm-do-adapter/adapter.rb, line 207 207: def delete(collection) 208: query = collection.query 209: statement, bind_values = delete_statement(query) 210: 211: with_connection do |connection| 212: connection.create_command(statement).execute_non_query(*bind_values) 213: end.affected_rows 214: end
Execute non-SELECT SQL query
@param [String] statement
the SQL statement
@param [Array] *bind_values
optional bind values to merge into the statement
@return [DataObjects::Result]
result with number of affected rows, and insert id if any
@api public
# File lib/dm-do-adapter/adapter.rb, line 60 60: def execute(statement, *bind_values) 61: with_connection do |connection| 62: command = connection.create_command(statement) 63: command.execute_non_query(*bind_values) 64: end 65: end
Constructs and executes SELECT query, then instantiates one or many object from result set.
@param [Query] query
composition of the query to perform
@return [Array]
result set of the query
@api semipublic
# File lib/dm-do-adapter/adapter.rb, line 133 133: def read(query) 134: fields = query.fields 135: types = fields.map { |property| property.primitive } 136: 137: statement, bind_values = select_statement(query) 138: 139: records = [] 140: 141: with_connection do |connection| 142: command = connection.create_command(statement) 143: command.set_types(types) 144: 145: # Handle different splat semantics for nil on 1.8 and 1.9 146: reader = if bind_values 147: command.execute_reader(*bind_values) 148: else 149: command.execute_reader 150: end 151: 152: begin 153: while reader.next! 154: records << Hash[ fields.zip(reader.values) ] 155: end 156: ensure 157: reader.close 158: end 159: end 160: 161: records 162: end
Retrieve results using an SQL SELECT statement
@param [String] statement
the SQL SELECT statement
@param [Array] *bind_values
optional bind values to merge into the statement
@return [Array]
if fields > 1, return an Array of Struct objects if fields == 1, return an Array of objects
@api public
# File lib/dm-do-adapter/adapter.rb, line 32 32: def select(statement, *bind_values) 33: with_connection do |connection| 34: reader = connection.create_command(statement).execute_reader(*bind_values) 35: fields = reader.fields 36: 37: begin 38: if fields.size > 1 39: select_fields(reader, fields) 40: else 41: select_field(reader) 42: end 43: ensure 44: reader.close 45: end 46: end 47: end
Constructs and executes UPDATE statement for given attributes and a query
@param [Hash(Property => Object)] attributes
hash of attribute values to set, keyed by Property
@param [Collection] collection
collection of records to be updated
@return [Integer]
the number of records updated
@api semipublic
# File lib/dm-do-adapter/adapter.rb, line 176 176: def update(attributes, collection) 177: query = collection.query 178: 179: properties = [] 180: bind_values = [] 181: 182: # make the order of the properties consistent 183: query.model.properties(name).each do |property| 184: next unless attributes.key?(property) 185: properties << property 186: bind_values << attributes[property] 187: end 188: 189: statement, conditions_bind_values = update_statement(properties, query) 190: 191: bind_values.concat(conditions_bind_values) 192: 193: with_connection do |connection| 194: connection.create_command(statement).execute_non_query(*bind_values) 195: end.affected_rows 196: end
Takes connection and closes it
@api semipublic
# File lib/dm-do-adapter/adapter.rb, line 257 257: def close_connection(connection) 258: connection.close if connection.respond_to?(:close) 259: end
@api private
# File lib/dm-do-adapter/adapter.rb, line 219 219: def normalized_uri 220: @normalized_uri ||= 221: begin 222: keys = [ 223: :adapter, :user, :password, :host, :port, :path, :fragment, 224: :scheme, :query, :username, :database ] 225: query = DataMapper::Ext::Hash.except(@options, keys) 226: query = nil if query.empty? 227: 228: # Better error message in case port is no Numeric value 229: port = @options[:port].nil? ? nil : @options[:port].to_int 230: 231: DataObjects::URI.new( 232: :scheme => @options[:adapter], 233: :user => @options[:user] || @options[:username], 234: :password => @options[:password], 235: :host => @options[:host], 236: :port => port, 237: :path => @options[:path] || @options[:database], 238: :query => query, 239: :fragment => @options[:fragment] 240: ).freeze 241: end 242: end
@api private
# File lib/dm-do-adapter/adapter.rb, line 299 299: def select_field(reader) 300: results = [] 301: 302: while reader.next! 303: results << reader.values.at(0) 304: end 305: 306: results 307: end
@api private
# File lib/dm-do-adapter/adapter.rb, line 285 285: def select_fields(reader, fields) 286: fields = fields.map { |field| DataMapper::Inflector.underscore(field).to_sym } 287: struct = Struct.new(*fields) 288: 289: results = [] 290: 291: while reader.next! 292: results << struct.new(*reader.values) 293: end 294: 295: results 296: end
@api private
# File lib/dm-do-adapter/adapter.rb, line 275 275: def with_connection 276: yield connection = open_connection 277: rescue Exception => exception 278: DataMapper.logger.error(exception.to_s) if DataMapper.logger 279: raise 280: ensure 281: close_connection(connection) 282: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.