locomotive 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/locomotive.rb +6 -0
- data/lib/locomotive/core_extensions.rb +6 -0
- data/lib/locomotive/core_extensions/array.rb +22 -0
- data/lib/locomotive/core_extensions/class.rb +47 -0
- data/lib/locomotive/core_extensions/hash.rb +7 -0
- data/lib/locomotive/core_extensions/inflector.rb +29 -0
- data/lib/locomotive/core_extensions/module.rb +77 -0
- data/lib/locomotive/core_extensions/symbol.rb +17 -0
- data/lib/locomotive/misc.rb +1 -0
- data/lib/locomotive/misc/type_check.rb +129 -0
- data/lib/locomotive/relational_algebra.rb +8 -0
- data/lib/locomotive/relational_algebra/attributes.rb +171 -0
- data/lib/locomotive/relational_algebra/operators.rb +15 -0
- data/lib/locomotive/relational_algebra/operators/abstraction.rb +2 -0
- data/lib/locomotive/relational_algebra/operators/abstraction/lambda.rb +83 -0
- data/lib/locomotive/relational_algebra/operators/abstraction/variable.rb +65 -0
- data/lib/locomotive/relational_algebra/operators/aggregation.rb +2 -0
- data/lib/locomotive/relational_algebra/operators/aggregation/aggr_builtin.rb +26 -0
- data/lib/locomotive/relational_algebra/operators/aggregation/aggregation.rb +76 -0
- data/lib/locomotive/relational_algebra/operators/basic_operators.rb +144 -0
- data/lib/locomotive/relational_algebra/operators/boolean.rb +4 -0
- data/lib/locomotive/relational_algebra/operators/boolean/and.rb +9 -0
- data/lib/locomotive/relational_algebra/operators/boolean/basic_boolean.rb +66 -0
- data/lib/locomotive/relational_algebra/operators/boolean/not.rb +56 -0
- data/lib/locomotive/relational_algebra/operators/boolean/or.rb +9 -0
- data/lib/locomotive/relational_algebra/operators/builtins.rb +3 -0
- data/lib/locomotive/relational_algebra/operators/builtins/arith_builtin.rb +37 -0
- data/lib/locomotive/relational_algebra/operators/builtins/basic_builtin.rb +20 -0
- data/lib/locomotive/relational_algebra/operators/builtins/function.rb +69 -0
- data/lib/locomotive/relational_algebra/operators/comparisons.rb +6 -0
- data/lib/locomotive/relational_algebra/operators/comparisons/basic_comparison.rb +65 -0
- data/lib/locomotive/relational_algebra/operators/comparisons/equal.rb +13 -0
- data/lib/locomotive/relational_algebra/operators/comparisons/greater.rb +13 -0
- data/lib/locomotive/relational_algebra/operators/comparisons/greater_equal.rb +14 -0
- data/lib/locomotive/relational_algebra/operators/comparisons/less.rb +21 -0
- data/lib/locomotive/relational_algebra/operators/comparisons/less_equal.rb +13 -0
- data/lib/locomotive/relational_algebra/operators/error.rb +1 -0
- data/lib/locomotive/relational_algebra/operators/error/error.rb +52 -0
- data/lib/locomotive/relational_algebra/operators/filter.rb +1 -0
- data/lib/locomotive/relational_algebra/operators/filter/select.rb +50 -0
- data/lib/locomotive/relational_algebra/operators/join.rb +5 -0
- data/lib/locomotive/relational_algebra/operators/join/basic_join.rb +9 -0
- data/lib/locomotive/relational_algebra/operators/join/cross.rb +28 -0
- data/lib/locomotive/relational_algebra/operators/join/equi_join.rb +61 -0
- data/lib/locomotive/relational_algebra/operators/join/predicates.rb +95 -0
- data/lib/locomotive/relational_algebra/operators/join/theta_join.rb +53 -0
- data/lib/locomotive/relational_algebra/operators/projections.rb +2 -0
- data/lib/locomotive/relational_algebra/operators/projections/attach.rb +67 -0
- data/lib/locomotive/relational_algebra/operators/projections/projection.rb +106 -0
- data/lib/locomotive/relational_algebra/operators/ranking.rb +6 -0
- data/lib/locomotive/relational_algebra/operators/ranking/basic_ranking.rb +67 -0
- data/lib/locomotive/relational_algebra/operators/ranking/rank.rb +9 -0
- data/lib/locomotive/relational_algebra/operators/ranking/rank_lists.rb +45 -0
- data/lib/locomotive/relational_algebra/operators/ranking/row_id.rb +24 -0
- data/lib/locomotive/relational_algebra/operators/ranking/row_number.rb +55 -0
- data/lib/locomotive/relational_algebra/operators/ranking/row_rank.rb +9 -0
- data/lib/locomotive/relational_algebra/operators/serialization.rb +2 -0
- data/lib/locomotive/relational_algebra/operators/serialization/basic_serialize.rb +9 -0
- data/lib/locomotive/relational_algebra/operators/serialization/serialize_relation.rb +105 -0
- data/lib/locomotive/relational_algebra/operators/set.rb +4 -0
- data/lib/locomotive/relational_algebra/operators/set/basic_set.rb +24 -0
- data/lib/locomotive/relational_algebra/operators/set/difference.rb +11 -0
- data/lib/locomotive/relational_algebra/operators/set/distinct.rb +35 -0
- data/lib/locomotive/relational_algebra/operators/set/union.rb +11 -0
- data/lib/locomotive/relational_algebra/operators/tables.rb +3 -0
- data/lib/locomotive/relational_algebra/operators/tables/literal_table.rb +95 -0
- data/lib/locomotive/relational_algebra/operators/tables/nil.rb +13 -0
- data/lib/locomotive/relational_algebra/operators/tables/ref_table.rb +75 -0
- data/lib/locomotive/relational_algebra/operators/typeing.rb +1 -0
- data/lib/locomotive/relational_algebra/operators/typeing/cast.rb +59 -0
- data/lib/locomotive/relational_algebra/ordering.rb +30 -0
- data/lib/locomotive/relational_algebra/query_information.rb +666 -0
- data/lib/locomotive/relational_algebra/rel_alg_ast_node.rb +51 -0
- data/lib/locomotive/relational_algebra/rel_alg_exceptions.rb +15 -0
- data/lib/locomotive/relational_algebra/schema.rb +87 -0
- data/lib/locomotive/relational_algebra/types.rb +86 -0
- data/lib/locomotive/tree_helpers.rb +3 -0
- data/lib/locomotive/tree_helpers/annotations.rb +58 -0
- data/lib/locomotive/tree_helpers/ast.rb +99 -0
- data/lib/locomotive/tree_helpers/ast_traversal.rb +43 -0
- data/lib/locomotive/utils.rb +2 -0
- data/lib/locomotive/utils/relalg2xml.rb +239 -0
- data/lib/locomotive/utils/xml.rb +47 -0
- metadata +157 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'locomotive/relational_algebra/operators/basic_operators.rb'
|
|
2
|
+
require 'locomotive/relational_algebra/operators/abstraction'
|
|
3
|
+
require 'locomotive/relational_algebra/operators/aggregation'
|
|
4
|
+
require 'locomotive/relational_algebra/operators/boolean'
|
|
5
|
+
require 'locomotive/relational_algebra/operators/builtins'
|
|
6
|
+
require 'locomotive/relational_algebra/operators/comparisons'
|
|
7
|
+
require 'locomotive/relational_algebra/operators/filter'
|
|
8
|
+
require 'locomotive/relational_algebra/operators/join'
|
|
9
|
+
require 'locomotive/relational_algebra/operators/projections'
|
|
10
|
+
require 'locomotive/relational_algebra/operators/ranking'
|
|
11
|
+
require 'locomotive/relational_algebra/operators/serialization'
|
|
12
|
+
require 'locomotive/relational_algebra/operators/set'
|
|
13
|
+
require 'locomotive/relational_algebra/operators/tables'
|
|
14
|
+
require 'locomotive/relational_algebra/operators/typeing'
|
|
15
|
+
require 'locomotive/relational_algebra/operators/error'
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module Locomotive
|
|
2
|
+
|
|
3
|
+
module RelationalAlgebra
|
|
4
|
+
|
|
5
|
+
class RelLambda < Binary
|
|
6
|
+
def_node :parametrized_plan
|
|
7
|
+
def initialize(op1, op2)
|
|
8
|
+
super(op1,op2)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def left_and_right(op1,op2)
|
|
12
|
+
self.schema = Schema.new( { Iter.new(1) => [RNat.type],
|
|
13
|
+
Pos.new(1) => [RNat.type],
|
|
14
|
+
# this is a dummy node
|
|
15
|
+
Item.new(1) => [RNat.type] } )
|
|
16
|
+
super(op1,op2)
|
|
17
|
+
end
|
|
18
|
+
def_sig :left_and_right, Variable, Operator
|
|
19
|
+
|
|
20
|
+
def serialize
|
|
21
|
+
xml_id = 0
|
|
22
|
+
self.traverse do |op|
|
|
23
|
+
op.ann_xml_id = xml_id += 1
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
xml_list = []
|
|
27
|
+
|
|
28
|
+
self.traverse_strategy = Locomotive::AstHelpers::PostOrderTraverse
|
|
29
|
+
self.traverse do |op|
|
|
30
|
+
xml_list << op.to_xml
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
parametrized_plan :comment => "not mentioned for execution" do
|
|
34
|
+
xml_list.join
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# performs a beta reduction on the right
|
|
39
|
+
# plan side
|
|
40
|
+
def apply(arg)
|
|
41
|
+
right.set(left, arg)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def clone
|
|
45
|
+
RelLambda.new(op1.clone,
|
|
46
|
+
op2.clone)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def set(var,plan)
|
|
50
|
+
if var == self.left
|
|
51
|
+
right.clone
|
|
52
|
+
else
|
|
53
|
+
if !right.free.member?(var) or
|
|
54
|
+
!plan.free.member?(left)
|
|
55
|
+
RelLambda.new(
|
|
56
|
+
left.clone,
|
|
57
|
+
right.set(var, plan))
|
|
58
|
+
else
|
|
59
|
+
# alpha reduction
|
|
60
|
+
new_var = Variable.new_variable
|
|
61
|
+
RelLambda.new(
|
|
62
|
+
new_var,
|
|
63
|
+
right.set(left,new_var)).set(var,plan)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def free
|
|
69
|
+
# the variable in the left branch
|
|
70
|
+
# is not a free variable anymore
|
|
71
|
+
right.free - [left]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def bound
|
|
75
|
+
# the variable in the right branch
|
|
76
|
+
# is now a bound variable
|
|
77
|
+
[left.clone] + right.bound
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module Locomotive
|
|
2
|
+
|
|
3
|
+
module RelationalAlgebra
|
|
4
|
+
|
|
5
|
+
class Variable < Leaf
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
attr_accessor :id_pool
|
|
9
|
+
|
|
10
|
+
def new_variable(*items)
|
|
11
|
+
Variable.id_pool ||= [0]
|
|
12
|
+
new_id = Variable.id_pool.max + 1
|
|
13
|
+
Variable.id_pool << new_id
|
|
14
|
+
Variable.new(new_id, *items)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
attr_accessor :id, :items
|
|
19
|
+
def_sig :id=, Integer
|
|
20
|
+
def_sig :items=, [GenericAttribute]
|
|
21
|
+
def_node :variable
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def initialize(id, *items)
|
|
25
|
+
self.id,
|
|
26
|
+
self.items = id, items
|
|
27
|
+
Variable.id_pool << self.id
|
|
28
|
+
self.schema = Schema.new({ Iter.new(1) => [RNat.type],
|
|
29
|
+
Pos.new(1) => [RNat.type] }.merge(
|
|
30
|
+
Hash[*items.collect do |it|
|
|
31
|
+
[it, [RNat.instance]]
|
|
32
|
+
end.flatten_once]) )
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def clone
|
|
36
|
+
Variable.new(id, *items.clone)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def xml_content
|
|
40
|
+
content do
|
|
41
|
+
variable :name => id
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def ==(other)
|
|
46
|
+
other.class == Variable and
|
|
47
|
+
other.id == self.id
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def set(var,plan)
|
|
51
|
+
if var == self
|
|
52
|
+
plan.clone
|
|
53
|
+
else
|
|
54
|
+
self.clone
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def free
|
|
59
|
+
[ self.clone ]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Locomotive
|
|
2
|
+
|
|
3
|
+
module RelationalAlgebra
|
|
4
|
+
|
|
5
|
+
class AggrFun
|
|
6
|
+
include Singleton
|
|
7
|
+
|
|
8
|
+
def to_xml
|
|
9
|
+
self.class.to_s.split("::").last.downcase.to_sym
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def clone
|
|
13
|
+
self
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class Count < AggrFun; end
|
|
18
|
+
class Max < AggrFun; end
|
|
19
|
+
class Min < AggrFun; end
|
|
20
|
+
class Sum < AggrFun; end
|
|
21
|
+
class Avg < AggrFun; end
|
|
22
|
+
class All < AggrFun; end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Locomotive
|
|
2
|
+
|
|
3
|
+
module RelationalAlgebra
|
|
4
|
+
|
|
5
|
+
class Aggr < Unary
|
|
6
|
+
def_node :column, :aggregate
|
|
7
|
+
|
|
8
|
+
attr_accessor :item, :over, :part_list, :aggr_kind
|
|
9
|
+
def_sig :aggr_kind=, AggrFun
|
|
10
|
+
def_sig :part_list=, [ConstAttribute]
|
|
11
|
+
def_sig :item=, ConstAttribute
|
|
12
|
+
def_sig :over=, [ConstAttribute]
|
|
13
|
+
|
|
14
|
+
def initialize(op, aggr_kind, item, over, part)
|
|
15
|
+
self.item = item
|
|
16
|
+
self.aggr_kind = aggr_kind
|
|
17
|
+
self.over = over
|
|
18
|
+
self.part_list = part
|
|
19
|
+
super(op)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def child=(op)
|
|
23
|
+
unless op.schema.attributes?(part_list)
|
|
24
|
+
raise CorruptedSchema,
|
|
25
|
+
"Schema #{op.schema.attributes} does not " \
|
|
26
|
+
"contain all attributes of #{part_list}."
|
|
27
|
+
end
|
|
28
|
+
unless op.schema.attributes?(over)
|
|
29
|
+
raise CorruptedSchema,
|
|
30
|
+
"Schema #{op.schema.attributes} does not " \
|
|
31
|
+
"contain all attributes of #{item}."
|
|
32
|
+
end
|
|
33
|
+
self.schema = Schema.new( { self.item => [RNat.instance] }.merge(
|
|
34
|
+
Hash[*part_list.collect do |p|
|
|
35
|
+
[p, op.schema[p]]
|
|
36
|
+
end.flatten_once]))
|
|
37
|
+
|
|
38
|
+
super(op)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def xml_content
|
|
42
|
+
content do
|
|
43
|
+
part_list.collect do |part|
|
|
44
|
+
column :name => part.to_xml, :function => :partition, :new => false
|
|
45
|
+
end.join +
|
|
46
|
+
(aggregate :kind => aggr_kind.to_xml do
|
|
47
|
+
([column(:name => item.to_xml, :new => true)] +
|
|
48
|
+
over.map do |c|
|
|
49
|
+
column(:name => c.to_xml, :new => false, :function => :item)
|
|
50
|
+
end).join
|
|
51
|
+
end)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def clone
|
|
56
|
+
Aggr.new(
|
|
57
|
+
child.clone,
|
|
58
|
+
aggr_kind.clone,
|
|
59
|
+
over.clone,
|
|
60
|
+
item.clone,
|
|
61
|
+
part_list.clone)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def set(var,plan)
|
|
65
|
+
Aggr.new(
|
|
66
|
+
child.set(var,plan),
|
|
67
|
+
aggr_kind.clone,
|
|
68
|
+
item.clone,
|
|
69
|
+
over.clone,
|
|
70
|
+
part_list.clone)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
module Locomotive
|
|
2
|
+
|
|
3
|
+
module RelationalAlgebra
|
|
4
|
+
|
|
5
|
+
# represents a variant operator of the
|
|
6
|
+
# relational algebra
|
|
7
|
+
class Operator < RelAlgAstNode
|
|
8
|
+
include Locomotive::XML
|
|
9
|
+
def_node :node, :content, :column, :edge
|
|
10
|
+
|
|
11
|
+
attr_accessor :schema
|
|
12
|
+
def_sig :schema=, Schema
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
raise AbstractClassError,
|
|
16
|
+
"#{self.class} is an abstract class" if self.class == Operator
|
|
17
|
+
self.schema = Schema.new({})
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def xml_schema
|
|
21
|
+
self.schema.to_xml
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def xml_content
|
|
25
|
+
content()
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def xml_kind
|
|
29
|
+
self.class.to_s.split("::").last.downcase.to_sym
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def to_xml
|
|
33
|
+
cont_list = [ xml_schema,
|
|
34
|
+
xml_content ]
|
|
35
|
+
cont_list << edge(:to => left_child.ann_xml_id) if has_left_child? and
|
|
36
|
+
left_child.respond_to? :ann_xml_id
|
|
37
|
+
cont_list << edge(:to => right_child.ann_xml_id) if has_right_child? and
|
|
38
|
+
right_child.respond_to? :ann_xml_id
|
|
39
|
+
node :id => ann_xml_id,
|
|
40
|
+
:kind => xml_kind do
|
|
41
|
+
cont_list.join
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# returns all free variables in this plan
|
|
46
|
+
def free
|
|
47
|
+
# attention: for convenience we use
|
|
48
|
+
# the underlying ast framework
|
|
49
|
+
fv = []
|
|
50
|
+
fv += left_child.free if has_left_child?
|
|
51
|
+
fv += right_child.free if has_right_child?
|
|
52
|
+
fv
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# returns all bound variables in this plan
|
|
56
|
+
def bound
|
|
57
|
+
# attention: for convenience we use
|
|
58
|
+
# the underlying ast framework
|
|
59
|
+
bv = []
|
|
60
|
+
bv += left_child.bound if has_left_child?
|
|
61
|
+
bv += right_child.bound if has_right_child?
|
|
62
|
+
bv
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
#
|
|
67
|
+
# A leaf doesn't have any child
|
|
68
|
+
#
|
|
69
|
+
class Leaf < Operator
|
|
70
|
+
# undef left_child=
|
|
71
|
+
# undef left_child
|
|
72
|
+
# undef has_left_child?
|
|
73
|
+
# undef right_child=
|
|
74
|
+
# undef right_child
|
|
75
|
+
# undef has_right_child?
|
|
76
|
+
def initialize()
|
|
77
|
+
raise AbstractClassError,
|
|
78
|
+
"#{self.class} is an abstract class" if self.class == Leaf
|
|
79
|
+
super()
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def set(var,plan)
|
|
83
|
+
self.clone
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
#
|
|
88
|
+
# An unary Operator has exactly one child
|
|
89
|
+
#
|
|
90
|
+
class Unary < Operator
|
|
91
|
+
# undefine all methods to access
|
|
92
|
+
# the right child
|
|
93
|
+
# undef right_child=
|
|
94
|
+
# undef right_child
|
|
95
|
+
# undef has_right_child?
|
|
96
|
+
|
|
97
|
+
# since we have only one child for this
|
|
98
|
+
# type of operators, we define a shortcut
|
|
99
|
+
alias :child :left_child
|
|
100
|
+
alias :child= :left_child=
|
|
101
|
+
def_sig :child=, Operator
|
|
102
|
+
|
|
103
|
+
alias :child? :has_left_child?
|
|
104
|
+
|
|
105
|
+
def initialize(op)
|
|
106
|
+
raise AbstractClassError,
|
|
107
|
+
"#{self.class} is an abstract class" if self.class == Unary
|
|
108
|
+
super()
|
|
109
|
+
self.child = op
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
#
|
|
114
|
+
# A binary operator has exactly two children
|
|
115
|
+
#
|
|
116
|
+
class Binary < Operator
|
|
117
|
+
# getter and setters for left and
|
|
118
|
+
# right children by defining shortcuts
|
|
119
|
+
alias :left :left_child
|
|
120
|
+
alias :right :right_child
|
|
121
|
+
alias :left? :has_left_child?
|
|
122
|
+
alias :right? :has_right_child?
|
|
123
|
+
|
|
124
|
+
#alias :left= :left_child=
|
|
125
|
+
#def_sig :left=, Operator
|
|
126
|
+
#alias :right= :right_child=
|
|
127
|
+
#def_sig :right=, Operator
|
|
128
|
+
|
|
129
|
+
def left_and_right(op1, op2)
|
|
130
|
+
self.left_child = op1
|
|
131
|
+
self.right_child = op2
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def initialize(op1, op2)
|
|
135
|
+
raise AbstractClassError,
|
|
136
|
+
"#{self.class} is an abstract class" if self.class == Binary
|
|
137
|
+
super()
|
|
138
|
+
left_and_right(op1,op2)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module Locomotive
|
|
2
|
+
|
|
3
|
+
module RelationalAlgebra
|
|
4
|
+
|
|
5
|
+
class BinOp < Unary
|
|
6
|
+
attr_accessor :res, :item1, :item2
|
|
7
|
+
def_sig :res=, ConstAttribute
|
|
8
|
+
def_sig :item1=, ConstAttribute
|
|
9
|
+
def_sig :item2=, ConstAttribute
|
|
10
|
+
|
|
11
|
+
def initialize(op, res, items)
|
|
12
|
+
self.res,
|
|
13
|
+
self.item1,
|
|
14
|
+
self.item2 = res, items[0], items[1]
|
|
15
|
+
super(op)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def child=(op)
|
|
19
|
+
unless op.schema.attributes?([item1])
|
|
20
|
+
raise CorruptedSchema,
|
|
21
|
+
"Schema #{op.schema.attributes} does not " \
|
|
22
|
+
"contain all attributes of #{item1}."
|
|
23
|
+
end
|
|
24
|
+
unless op.schema.attributes?([item2])
|
|
25
|
+
raise CorruptedSchema,
|
|
26
|
+
"Schema #{op.schema.attributes} does not " \
|
|
27
|
+
"contain all attributes of #{item2}."
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
self.schema = op.schema +
|
|
31
|
+
Schema.new({ res => [RBool.instance] })
|
|
32
|
+
|
|
33
|
+
super(op)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def xml_content
|
|
37
|
+
content do
|
|
38
|
+
[column(:name => res.to_xml, :new => true),
|
|
39
|
+
column(:name => item1.to_xml, :new => false, :position => 1),
|
|
40
|
+
column(:name => item2.to_xml, :new => false, :position => 2)].join
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def xml_kind
|
|
45
|
+
self.class.to_s.split('::').last.downcase.to_sym
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def clone
|
|
49
|
+
self.class.new(child.clone,
|
|
50
|
+
res.clone,
|
|
51
|
+
item1.clone,
|
|
52
|
+
item2.clone)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def set(var, plan)
|
|
56
|
+
self.class.new(
|
|
57
|
+
child.set(var,plan),
|
|
58
|
+
res.clone,
|
|
59
|
+
item1.clone,
|
|
60
|
+
item2.clone)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|