locomotive 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/lib/locomotive.rb +6 -0
  2. data/lib/locomotive/core_extensions.rb +6 -0
  3. data/lib/locomotive/core_extensions/array.rb +22 -0
  4. data/lib/locomotive/core_extensions/class.rb +47 -0
  5. data/lib/locomotive/core_extensions/hash.rb +7 -0
  6. data/lib/locomotive/core_extensions/inflector.rb +29 -0
  7. data/lib/locomotive/core_extensions/module.rb +77 -0
  8. data/lib/locomotive/core_extensions/symbol.rb +17 -0
  9. data/lib/locomotive/misc.rb +1 -0
  10. data/lib/locomotive/misc/type_check.rb +129 -0
  11. data/lib/locomotive/relational_algebra.rb +8 -0
  12. data/lib/locomotive/relational_algebra/attributes.rb +171 -0
  13. data/lib/locomotive/relational_algebra/operators.rb +15 -0
  14. data/lib/locomotive/relational_algebra/operators/abstraction.rb +2 -0
  15. data/lib/locomotive/relational_algebra/operators/abstraction/lambda.rb +83 -0
  16. data/lib/locomotive/relational_algebra/operators/abstraction/variable.rb +65 -0
  17. data/lib/locomotive/relational_algebra/operators/aggregation.rb +2 -0
  18. data/lib/locomotive/relational_algebra/operators/aggregation/aggr_builtin.rb +26 -0
  19. data/lib/locomotive/relational_algebra/operators/aggregation/aggregation.rb +76 -0
  20. data/lib/locomotive/relational_algebra/operators/basic_operators.rb +144 -0
  21. data/lib/locomotive/relational_algebra/operators/boolean.rb +4 -0
  22. data/lib/locomotive/relational_algebra/operators/boolean/and.rb +9 -0
  23. data/lib/locomotive/relational_algebra/operators/boolean/basic_boolean.rb +66 -0
  24. data/lib/locomotive/relational_algebra/operators/boolean/not.rb +56 -0
  25. data/lib/locomotive/relational_algebra/operators/boolean/or.rb +9 -0
  26. data/lib/locomotive/relational_algebra/operators/builtins.rb +3 -0
  27. data/lib/locomotive/relational_algebra/operators/builtins/arith_builtin.rb +37 -0
  28. data/lib/locomotive/relational_algebra/operators/builtins/basic_builtin.rb +20 -0
  29. data/lib/locomotive/relational_algebra/operators/builtins/function.rb +69 -0
  30. data/lib/locomotive/relational_algebra/operators/comparisons.rb +6 -0
  31. data/lib/locomotive/relational_algebra/operators/comparisons/basic_comparison.rb +65 -0
  32. data/lib/locomotive/relational_algebra/operators/comparisons/equal.rb +13 -0
  33. data/lib/locomotive/relational_algebra/operators/comparisons/greater.rb +13 -0
  34. data/lib/locomotive/relational_algebra/operators/comparisons/greater_equal.rb +14 -0
  35. data/lib/locomotive/relational_algebra/operators/comparisons/less.rb +21 -0
  36. data/lib/locomotive/relational_algebra/operators/comparisons/less_equal.rb +13 -0
  37. data/lib/locomotive/relational_algebra/operators/error.rb +1 -0
  38. data/lib/locomotive/relational_algebra/operators/error/error.rb +52 -0
  39. data/lib/locomotive/relational_algebra/operators/filter.rb +1 -0
  40. data/lib/locomotive/relational_algebra/operators/filter/select.rb +50 -0
  41. data/lib/locomotive/relational_algebra/operators/join.rb +5 -0
  42. data/lib/locomotive/relational_algebra/operators/join/basic_join.rb +9 -0
  43. data/lib/locomotive/relational_algebra/operators/join/cross.rb +28 -0
  44. data/lib/locomotive/relational_algebra/operators/join/equi_join.rb +61 -0
  45. data/lib/locomotive/relational_algebra/operators/join/predicates.rb +95 -0
  46. data/lib/locomotive/relational_algebra/operators/join/theta_join.rb +53 -0
  47. data/lib/locomotive/relational_algebra/operators/projections.rb +2 -0
  48. data/lib/locomotive/relational_algebra/operators/projections/attach.rb +67 -0
  49. data/lib/locomotive/relational_algebra/operators/projections/projection.rb +106 -0
  50. data/lib/locomotive/relational_algebra/operators/ranking.rb +6 -0
  51. data/lib/locomotive/relational_algebra/operators/ranking/basic_ranking.rb +67 -0
  52. data/lib/locomotive/relational_algebra/operators/ranking/rank.rb +9 -0
  53. data/lib/locomotive/relational_algebra/operators/ranking/rank_lists.rb +45 -0
  54. data/lib/locomotive/relational_algebra/operators/ranking/row_id.rb +24 -0
  55. data/lib/locomotive/relational_algebra/operators/ranking/row_number.rb +55 -0
  56. data/lib/locomotive/relational_algebra/operators/ranking/row_rank.rb +9 -0
  57. data/lib/locomotive/relational_algebra/operators/serialization.rb +2 -0
  58. data/lib/locomotive/relational_algebra/operators/serialization/basic_serialize.rb +9 -0
  59. data/lib/locomotive/relational_algebra/operators/serialization/serialize_relation.rb +105 -0
  60. data/lib/locomotive/relational_algebra/operators/set.rb +4 -0
  61. data/lib/locomotive/relational_algebra/operators/set/basic_set.rb +24 -0
  62. data/lib/locomotive/relational_algebra/operators/set/difference.rb +11 -0
  63. data/lib/locomotive/relational_algebra/operators/set/distinct.rb +35 -0
  64. data/lib/locomotive/relational_algebra/operators/set/union.rb +11 -0
  65. data/lib/locomotive/relational_algebra/operators/tables.rb +3 -0
  66. data/lib/locomotive/relational_algebra/operators/tables/literal_table.rb +95 -0
  67. data/lib/locomotive/relational_algebra/operators/tables/nil.rb +13 -0
  68. data/lib/locomotive/relational_algebra/operators/tables/ref_table.rb +75 -0
  69. data/lib/locomotive/relational_algebra/operators/typeing.rb +1 -0
  70. data/lib/locomotive/relational_algebra/operators/typeing/cast.rb +59 -0
  71. data/lib/locomotive/relational_algebra/ordering.rb +30 -0
  72. data/lib/locomotive/relational_algebra/query_information.rb +666 -0
  73. data/lib/locomotive/relational_algebra/rel_alg_ast_node.rb +51 -0
  74. data/lib/locomotive/relational_algebra/rel_alg_exceptions.rb +15 -0
  75. data/lib/locomotive/relational_algebra/schema.rb +87 -0
  76. data/lib/locomotive/relational_algebra/types.rb +86 -0
  77. data/lib/locomotive/tree_helpers.rb +3 -0
  78. data/lib/locomotive/tree_helpers/annotations.rb +58 -0
  79. data/lib/locomotive/tree_helpers/ast.rb +99 -0
  80. data/lib/locomotive/tree_helpers/ast_traversal.rb +43 -0
  81. data/lib/locomotive/utils.rb +2 -0
  82. data/lib/locomotive/utils/relalg2xml.rb +239 -0
  83. data/lib/locomotive/utils/xml.rb +47 -0
  84. 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,2 @@
1
+ require 'locomotive/relational_algebra/operators/abstraction/variable'
2
+ require 'locomotive/relational_algebra/operators/abstraction/lambda'
@@ -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,2 @@
1
+ require 'locomotive/relational_algebra/operators/aggregation/aggr_builtin'
2
+ require 'locomotive/relational_algebra/operators/aggregation/aggregation'
@@ -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,4 @@
1
+ require 'locomotive/relational_algebra/operators/boolean/basic_boolean'
2
+ require 'locomotive/relational_algebra/operators/boolean/and'
3
+ require 'locomotive/relational_algebra/operators/boolean/or'
4
+ require 'locomotive/relational_algebra/operators/boolean/not'
@@ -0,0 +1,9 @@
1
+ module Locomotive
2
+
3
+ module RelationalAlgebra
4
+
5
+ class And < BinOp; end
6
+
7
+ end
8
+
9
+ 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