module DataMapper::Constraints::Adapters::DataObjectsAdapter

Public Instance Methods

constraint_exists?(storage_name, constraint_name) click to toggle source

Determine if a constraint exists for a table

@param storage_name [Symbol]

name of table to check constraint on

@param constraint_name [~String]

name of constraint to check for

@return [Boolean]

@api private

# File lib/data_mapper/constraints/adapters/do_adapter.rb, line 17
        def constraint_exists?(storage_name, constraint_name)
          statement = DataMapper::Ext::String.compress_lines("            SELECT COUNT(*)
            FROM #{quote_name('information_schema')}.#{quote_name('table_constraints')}
            WHERE #{quote_name('constraint_type')} = 'FOREIGN KEY'
            AND #{quote_name('table_schema')} = ?
            AND #{quote_name('table_name')} = ?
            AND #{quote_name('constraint_name')} = ?
")

          select(statement, schema_name, storage_name, constraint_name).first > 0
        end
create_relationship_constraint(relationship) click to toggle source

Create the constraint for a relationship

@param relationship [Relationship]

the relationship to create the constraint for

@return [true, false]

true if creating the constraints was successful

@api semipublic

# File lib/data_mapper/constraints/adapters/do_adapter.rb, line 40
def create_relationship_constraint(relationship)
  return false unless valid_relationship_for_constraint?(relationship)

  source_storage_name = relationship.source_model.storage_name(name)
  target_storage_name = relationship.target_model.storage_name(name)
  constraint_name     = constraint_name(source_storage_name, relationship.name)

  return false if constraint_exists?(source_storage_name, constraint_name)

  constraint_type =
    case relationship.inverse.constraint
    when :protect            then 'NO ACTION'
    # TODO: support :cascade as an option:
    #   (destroy doesn't communicate the UPDATE constraint)
    when :destroy, :destroy! then 'CASCADE'
    when :set_nil            then 'SET NULL'
    end

  return false if constraint_type.nil?

  source_keys = relationship.source_key.map { |p| property_to_column_name(p, false) }
  target_keys = relationship.target_key.map { |p| property_to_column_name(p, false) }

  create_constraints_statement = create_constraints_statement(
    constraint_name,
    constraint_type,
    source_storage_name,
    source_keys,
    target_storage_name,
    target_keys)

  execute(create_constraints_statement)
end
destroy_relationship_constraint(relationship) click to toggle source

Remove the constraint for a relationship

@param relationship [Relationship]

the relationship to remove the constraint for

@return [true, false]

true if destroying the constraint was successful

@api semipublic

# File lib/data_mapper/constraints/adapters/do_adapter.rb, line 84
def destroy_relationship_constraint(relationship)
  return false unless valid_relationship_for_constraint?(relationship)

  storage_name    = relationship.source_model.storage_name(name)
  constraint_name = constraint_name(storage_name, relationship.name)

  return false unless constraint_exists?(storage_name, constraint_name)

  destroy_constraints_statement =
    destroy_constraints_statement(storage_name, constraint_name)

  execute(destroy_constraints_statement)
end

Private Instance Methods

valid_relationship_for_constraint?(relationship) click to toggle source

Check to see if the relationship's constraints can be used

Only one-to-one, one-to-many, and many-to-many relationships can be used for constraints. They must also be in the same repository as the adapter is connected to.

@param relationship [Relationship]

the relationship to check

@return [true, false]

true if a constraint can be established for relationship

@api private

# File lib/data_mapper/constraints/adapters/do_adapter.rb, line 114
def valid_relationship_for_constraint?(relationship)
  return false unless relationship.source_repository_name == name || relationship.source_repository_name.nil?
  return false unless relationship.target_repository_name == name || relationship.target_repository_name.nil?
  return false unless relationship.kind_of?(Associations::ManyToOne::Relationship)
  true
end