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.
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