Created
August 9, 2010 18:28
-
-
Save dkubb/515866 to your computer and use it in GitHub Desktop.
Veritas w/Graphiviz
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby -Ku | |
# $LOAD_PATH.unshift '/Users/dankubb/Programming/ruby/open-source/veritas/lib' | |
# $LOAD_PATH.unshift '/Users/dankubb/Programming/ruby/open-source/veritas-optimizer/lib' | |
require 'veritas' | |
require 'veritas-optimizer' | |
require 'graphviz' | |
include Veritas | |
class String | |
def demodulize | |
self[/[^:]+\z/] | |
end | |
end | |
module Veritas | |
module Visitor | |
class Dot | |
def self.dispatch | |
@dispatch ||= {} | |
end | |
def initialize | |
@graph = GraphViz.new(:G, :type => :digraph) | |
end | |
def accept(object) | |
visit object | |
to_dot | |
end | |
private | |
def visit(object) | |
object.class.ancestors.each do |mod| | |
method = "visit_#{mod.name.gsub('::', '_')}" | |
return send(method, object) if respond_to?(method, true) | |
end | |
raise NoMethodError, "No visitor for #{object.class.name}" | |
end | |
def visit_Veritas_Operation_Unary(unary) | |
operand = unary.operand | |
node = @graph.add_node(unary.object_id.to_s, :label => unary.class.name.demodulize, :shape => 'rectangle') | |
@graph.add_edge(visit(operand), node) | |
node | |
end | |
def visit_Veritas_Operation_Binary(binary) | |
left, right = binary.left, binary.right | |
node = @graph.add_node(binary.object_id.to_s, :label => binary.class.name.demodulize, :shape => 'diamond') | |
@graph.add_edge(visit(left), node) | |
@graph.add_edge(visit(right), node) | |
node | |
end | |
def visit_Veritas_Algebra_Restriction(restriction) | |
node = visit_Veritas_Operation_Unary(restriction) | |
@graph.add_edge(visit(restriction.predicate), node) | |
node | |
end | |
def visit_Veritas_Algebra_Projection(projection) | |
node = visit_Veritas_Operation_Unary(projection) | |
node.label = "{ #{projection.class.name.demodulize} | #{projection.header.map { |attribute| "#{attribute.name}: #{attribute.class.name.demodulize}" }.join('|')} }" | |
node.shape = 'record' | |
node | |
end | |
def visit_Veritas_Algebra_Rename(rename) | |
node = visit_Veritas_Operation_Unary(rename) | |
node.label = "{ #{rename.class.name.demodulize} | #{rename.aliases.map { |k,v| "#{k.name} → #{v.name}" }.join(' | ')} }" | |
node.shape = 'record' | |
node | |
end | |
def visit_Veritas_Attribute(attribute) | |
@graph.add_node(attribute.object_id.to_s, :label => "#{attribute.name}: #{attribute.class.name.demodulize}", :shape => 'record') | |
end | |
def visit_Veritas_Relation(relation) | |
@graph.add_node( | |
relation.object_id.to_s, | |
:label => "{ #{relation.class.name.demodulize} | #{relation.header.map { |attribute| "#{attribute.name}: #{attribute.class.name.demodulize}" }.join(' | ')} }", | |
:shape => 'record' | |
) | |
end | |
def visit_Object(object) | |
@graph.add_node(object.object_id.to_s, :label => object.inspect, :shape => 'rectangle') | |
end | |
def to_dot | |
@graph.output('png' => 'visitor.png') | |
end | |
end | |
end | |
end | |
visitor = Visitor::Dot.new | |
header = Relation::Header.new([ [ :id, Integer ], [ :name, String ] ]) | |
body = [ [ 1, 'Dan Kubb' ], [ 2, 'John Doe' ], [ 3, 'Jane Doe' ] ].each | |
left = Relation.new(header, body) | |
right = Relation.new(header, body) | |
relation = left | right | |
relation = relation & left | |
relation = relation & right | |
relation = relation - Relation::Empty.new(header) | |
relation = relation | Relation::Empty.new(header) | |
relation = relation * Relation.new([ [ :age, Integer ] ], [ [ 35 ] ]) | |
relation = relation.restrict { |r| r[:name].match(/Kubb/).inverse }. | |
restrict { |r| r[:name].eq('John Doe') }. | |
project([ :name ]). | |
rename(:name => :full_name) | |
relation = relation.order(relation.header).take(2).reverse.order(relation.header) | |
#visitor.accept(relation) | |
visitor.accept(relation.optimize) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment