class Graffiti::SquishAssert

Attributes

insert[R]
update[R]

Public Class Methods

new(config, query) click to toggle source
Calls superclass method Graffiti::SquishQuery::new
# File lib/graffiti/squish.rb, line 316
def initialize(config, query)
  @config = config
  super(@config, query)

  if 'UPDATE' == @key
    @insert = ''
    @update = @nodes

  elsif 'INSERT' == @key and @nodes =~ /\A\s*(.*?)\s*(?:\bUPDATE\b\s*(.*?))?\s*\z/
    @insert, @update = $1, $2.to_s

  else
    raise ProgrammingError,
      "Wrong query type: INSERT or UPDATE expected instead of " + @key
  end

  @insert = @insert.split(/\s*,\s*/).each {|s|
    s =~ BN or raise ProgrammingError,
      "Blank node expected in INSERT section instead of '#{s}'"
  }

  @update = @update.empty? ? {} : Hash[*@update.split(/\s*,\s*/).collect {|s|
    s.split(/\s*=\s*/)
  }.each {|node, value|
    node =~ BN or raise ProgrammingError,
      "Blank node expected on the left side of UPDATE assignment instead of '#{bn}'"
    validate_expression(value)
  }.flatten!]
end

Public Instance Methods

run(db, params={}) click to toggle source
# File lib/graffiti/squish.rb, line 346
def run(db, params={})
  values = resource_values(db, params)

  statements = []
  alias_positions.each do |alias_, clauses|
    statement = SquishAssertStatement.new(clauses, values)
    statements.push(statement) if statement.action
  end
  SquishAssertStatement.run_ordered_statements(db, statements)

  return @insert.collect {|node| values[node].value }
end

Private Instance Methods

alias_positions() click to toggle source
# File lib/graffiti/squish.rb, line 429
def alias_positions
  a = {}
  @sql_mapper.clauses.each_with_index do |clause, i|
    a[ clause[:alias] ] ||= []
    a[ clause[:alias] ].push(clause)
  end
  a
end
resource_values(db, params) click to toggle source
# File lib/graffiti/squish.rb, line 363
def resource_values(db, params)
  values = {}
  @sql_mapper.nodes.each do |node, n|
    new = false

    if node =~ INTERNAL   # internal resource
      value = $1.to_i   # resource id

    elsif node =~ PARAMETER
      value = get_parameter_value($1, params)

    elsif node =~ LITERAL
      value = @strings[$1.to_i]

    elsif node =~ BN
      subject_position = n[:positions].select {|p| :subject == p[:role] }.first

      if subject_position.nil?   # blank node occuring only in object position
        value = @update[node] or raise ProgrammingError,
          %{Blank node #{node} is undefined (drop it or set its value in UPDATE section)}
        value = expression_value(value, params)

      else   # resource blank node
        unless @insert.include?(node)
          s = SquishSelect.new(
            @config, {
              :nodes => [node],
              :pattern => subgraph(node),
              :strings => @strings
            }
          )
          debug { 'resource_values ' + db[s.to_sql, params].select_sql }
          found = db.fetch(s.to_sql, params).first
        end

        if found
          value = found.values.first

        else
          table = @sql_mapper.clauses[ subject_position[:clause] ][:map].table
          value = db[:resource].insert(:label => table)
          debug { 'resource_values ' + db[:resource].insert_sql(:label => table) }
          new = true unless 'resource' == table
        end
      end

    else   # external resource
      uriref = { :uriref  => true, :label   => node }
      found = db[:resource].filter(uriref).first
      if found
        value = found[:id]
      else
        value = db[:resource].insert(uriref)
        debug { 'resource_values ' + db[:resource].insert_sql(uriref) }
      end
    end

    debug { 'resource_values ' + node + ' = ' + value.inspect }
    v = SquishAssertValue.new(value, new, @update.has_key?(node))
    values[node] = v
  end

  debug { 'resource_values ' + 'resource_values ' + values.inspect }
  values
end
subgraph(node) click to toggle source

calculate subgraph of query pattern that is reachable from node

fixme: make it work with optional sub-patterns

# File lib/graffiti/squish.rb, line 442
def subgraph(node)
  subgraph = [node]
  w = []
  begin
    stop = true
    @pattern.each do |triple|
      if subgraph.include? triple[1] and not w.include? triple
        subgraph.push triple[2]
        w.push triple
        stop = false
      end
    end
  end until stop
  return w
end