alf 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/CHANGELOG.md +64 -0
  2. data/Gemfile.lock +4 -4
  3. data/README.md +257 -171
  4. data/TODO.md +4 -4
  5. data/alf.gemspec +3 -3
  6. data/alf.noespec +11 -6
  7. data/examples/pseudo-with.alf +7 -0
  8. data/examples/runall.sh +2 -2
  9. data/examples/unwrap.alf +4 -0
  10. data/examples/wrap.alf +2 -0
  11. data/lib/alf/relation.rb +118 -0
  12. data/lib/alf/version.rb +1 -1
  13. data/lib/alf.rb +320 -169
  14. data/spec/integration/src/test_minus.alf +5 -0
  15. data/spec/integration/src/test_project.alf +9 -0
  16. data/spec/{alf_spec.rb → integration/test_alf.rb} +8 -21
  17. data/spec/integration/test_alf_specs.rb +37 -0
  18. data/spec/{examples_spec.rb → integration/test_examples.rb} +1 -1
  19. data/spec/spec_helper.rb +19 -1
  20. data/spec/unit/environment/examples/suppliers.rash +5 -0
  21. data/spec/{environment/explicit_spec.rb → unit/environment/test_explicit.rb} +0 -0
  22. data/spec/{environment/folder_spec.rb → unit/environment/test_folder.rb} +1 -1
  23. data/spec/{operator → unit/operator}/non_relational/compact/buffer_based.rb +0 -0
  24. data/spec/{operator/non_relational/compact/sort_based_spec.rb → unit/operator/non_relational/compact/test_sort_based.rb} +0 -0
  25. data/spec/{operator/non_relational/autonum_spec.rb → unit/operator/non_relational/test_autonum.rb} +0 -0
  26. data/spec/{operator/non_relational/clip_spec.rb → unit/operator/non_relational/test_clip.rb} +0 -0
  27. data/spec/{operator/non_relational/compact_spec.rb → unit/operator/non_relational/test_compact.rb} +0 -0
  28. data/spec/{operator/non_relational/defaults_spec.rb → unit/operator/non_relational/test_defaults.rb} +0 -0
  29. data/spec/{operator/non_relational/sort_spec.rb → unit/operator/non_relational/test_sort.rb} +0 -0
  30. data/spec/{operator/relational/join/hash_based_spec.rb → unit/operator/relational/join/test_hash_based.rb} +0 -0
  31. data/spec/unit/operator/relational/summarize/test_hash_based.rb +38 -0
  32. data/spec/{operator/relational/summarize/sort_based_spec.rb → unit/operator/relational/summarize/test_sort_based.rb} +0 -0
  33. data/spec/{operator/relational/extend_spec.rb → unit/operator/relational/test_extend.rb} +0 -0
  34. data/spec/{operator/relational/group_spec.rb → unit/operator/relational/test_group.rb} +3 -2
  35. data/spec/{operator/relational/intersect_spec.rb → unit/operator/relational/test_intersect.rb} +0 -0
  36. data/spec/unit/operator/relational/test_join.rb +36 -0
  37. data/spec/{operator/relational/minus_spec.rb → unit/operator/relational/test_minus.rb} +0 -0
  38. data/spec/{operator/relational/project_spec.rb → unit/operator/relational/test_project.rb} +0 -0
  39. data/spec/{operator/relational/quota_spec.rb → unit/operator/relational/test_quota.rb} +0 -0
  40. data/spec/{operator/relational/rename_spec.rb → unit/operator/relational/test_rename.rb} +0 -0
  41. data/spec/{operator/relational/restrict_spec.rb → unit/operator/relational/test_restrict.rb} +0 -0
  42. data/spec/unit/operator/relational/test_summarize.rb +64 -0
  43. data/spec/{operator/relational/ungroup_spec.rb → unit/operator/relational/test_ungroup.rb} +0 -0
  44. data/spec/{operator/relational/union_spec.rb → unit/operator/relational/test_union.rb} +0 -0
  45. data/spec/{operator/relational/unnest_spec.rb → unit/operator/relational/test_unwrap.rb} +5 -5
  46. data/spec/{operator/relational/nest_spec.rb → unit/operator/relational/test_wrap.rb} +5 -5
  47. data/spec/{operator/command_methods_spec.rb → unit/operator/test_command_methods.rb} +0 -0
  48. data/spec/unit/operator/test_non_relational.rb +18 -0
  49. data/spec/unit/operator/test_relational.rb +27 -0
  50. data/spec/{reader → unit/reader}/input.rb +0 -0
  51. data/spec/unit/reader/test_alf_file.rb +27 -0
  52. data/spec/{reader/rash_spec.rb → unit/reader/test_rash.rb} +0 -0
  53. data/spec/unit/relation/test_coerce.rb +53 -0
  54. data/spec/unit/relation/test_inspect.rb +20 -0
  55. data/spec/unit/relation/test_relops.rb +46 -0
  56. data/spec/{renderer/text/cell_spec.rb → unit/renderer/text/test_cell.rb} +0 -0
  57. data/spec/{renderer/text/row_spec.rb → unit/renderer/text/test_row.rb} +0 -0
  58. data/spec/{renderer/text/table_spec.rb → unit/renderer/text/test_table.rb} +0 -0
  59. data/spec/{aggregator_spec.rb → unit/test_aggregator.rb} +6 -6
  60. data/spec/{assumptions_spec.rb → unit/test_assumptions.rb} +0 -0
  61. data/spec/{lispy_spec.rb → unit/test_lispy.rb} +0 -0
  62. data/spec/unit/test_operator.rb +16 -0
  63. data/spec/{reader_spec.rb → unit/test_reader.rb} +4 -0
  64. data/spec/unit/test_relation.rb +40 -0
  65. data/spec/{renderer_spec.rb → unit/test_renderer.rb} +0 -0
  66. data/spec/{tools/ordering_key_spec.rb → unit/tools/test_ordering_key.rb} +0 -0
  67. data/spec/{tools/projection_key_spec.rb → unit/tools/test_projection_key.rb} +0 -0
  68. data/spec/{tools/tools_spec.rb → unit/tools/test_tools.rb} +0 -0
  69. data/spec/{tools/tuple_handle_spec.rb → unit/tools/test_tuple_handle.rb} +0 -0
  70. data/tasks/clean.rake +3 -0
  71. data/tasks/spec_test.rake +1 -1
  72. metadata +143 -114
  73. data/examples/nest.alf +0 -2
  74. data/examples/unnest.alf +0 -4
  75. data/examples/with.alf +0 -23
  76. data/spec/operator/relational/summarize_spec.rb +0 -41
  77. data/spec/reader/alf_file_spec.rb +0 -15
data/alf.noespec CHANGED
@@ -7,19 +7,22 @@ variables:
7
7
  upper:
8
8
  Alf
9
9
  version:
10
- 0.9.0
10
+ 0.9.1
11
11
  summary: |-
12
- Classy data-manipulation dressed in a DSL (+ commandline)
12
+ Relational Algebra at your fingertips
13
13
  description: |-
14
- Alf is a commandline tool and Ruby library to manipulate data with all the
15
- power of a truly relational algebra approach.
14
+ Alf brings the relational algebra both in Shell and in Ruby. In Shell, because
15
+ manipulating any relation-like data source should be as straightforward as a
16
+ one-liner. In Ruby, because I've never understood why programming languages
17
+ provide data structures like arrays, hashes, sets, trees and graphs but not
18
+ _relations_... Let's stop the segregation ;-)
16
19
  authors:
17
20
  - {name: Bernard Lambeau, email: blambeau@gmail.com}
18
21
  links:
19
22
  - http://rubydoc.info/github/blambeau/alf/master/frames
20
23
  - http://github.com/blambeau/alf
21
24
  dependencies:
22
- - {name: rake, version: "~> 0.8.7", groups: [development]}
25
+ - {name: rake, version: "~> 0.9.2", groups: [development]}
23
26
  - {name: bundler, version: "~> 1.0", groups: [development]}
24
27
  - {name: rspec, version: "~> 2.6.0", groups: [development]}
25
28
  - {name: yard, version: "~> 0.7.2", groups: [development]}
@@ -27,4 +30,6 @@ variables:
27
30
  - {name: wlang, version: "~> 0.10.1", groups: [development]}
28
31
  - {name: noe, version: "~> 1.3.0", groups: [development]}
29
32
  - {name: quickl, version: "~> 0.2.1", groups: [runtime]}
30
-
33
+ rake_tasks:
34
+ spec_test:
35
+ pattern: "spec/**/test_*.rb"
@@ -0,0 +1,7 @@
1
+ kept_suppliers = (restrict :suppliers, lambda{ status > 10 })
2
+ with_countries = (join kept_suppliers, :cities)
3
+ supplying = (join with_countries, :supplies)
4
+ (summarize supplying,
5
+ [:country],
6
+ :which => Agg::group(:pid),
7
+ :total => Agg::sum{ qty })
data/examples/runall.sh CHANGED
@@ -13,8 +13,8 @@ alf --text extend supplies -- sp 'sid + "/" + pid' big "qty > 100 ?
13
13
  alf --text rename suppliers -- name supplier_name city supplier_city
14
14
  alf --text restrict suppliers -- "status > 20"
15
15
  alf --text restrict suppliers -- city "'London'"
16
- alf --text nest suppliers -- city status loc_and_status
17
- alf --text unnest suppliers -- loc_and_status
16
+ alf --text wrap suppliers -- city status loc_and_status
17
+ alf --text unwrap suppliers -- loc_and_status
18
18
  alf --text group supplies -- pid qty supplying
19
19
  alf --text group --allbut supplies -- sid supplying
20
20
  alf --text ungroup group -- supplying
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env alf
2
+ (unwrap \
3
+ (wrap :suppliers, [:city, :status], :loc_and_status),
4
+ :loc_and_status)
data/examples/wrap.alf ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env alf
2
+ (wrap :suppliers, [:city, :status], :loc_and_status)
@@ -0,0 +1,118 @@
1
+ module Alf
2
+ #
3
+ # Defines an in-memory relation
4
+ #
5
+ class Relation
6
+ include Iterator
7
+
8
+ protected
9
+
10
+ # @return [Set] the set of tuples
11
+ attr_reader :tuples
12
+
13
+ public
14
+
15
+ #
16
+ # Creates a Relation instance.
17
+ #
18
+ # @param [Set] tuples a set of tuples
19
+ #
20
+ def initialize(tuples)
21
+ raise ArgumentError unless tuples.is_a?(Set)
22
+ @tuples = tuples
23
+ end
24
+
25
+ #
26
+ # Coerces `val` to a relation
27
+ #
28
+ def self.coerce(val)
29
+ case val
30
+ when Relation
31
+ val
32
+ when Set
33
+ Relation.new(val)
34
+ when Array
35
+ Relation.new val.to_set
36
+ when Iterator
37
+ Relation.new val.to_set
38
+ else
39
+ raise ArgumentError, "Unable to coerce #{val} to a Relation"
40
+ end
41
+ end
42
+
43
+ # (see Relation.coerce)
44
+ def self.[](*tuples)
45
+ coerce(tuples)
46
+ end
47
+
48
+ #
49
+ # (see Iterator#each)
50
+ #
51
+ def each(&block)
52
+ tuples.each(&block)
53
+ end
54
+
55
+ #
56
+ # Returns relation's cardinality (number of tuples)
57
+ #
58
+ def cardinality
59
+ tuples.size
60
+ end
61
+ alias :size :cardinality
62
+ alias :count :cardinality
63
+
64
+ #
65
+ # Install the DSL through iteration over defined operators
66
+ #
67
+ Operator::each do |op_class|
68
+ meth_name = Tools.ruby_case(Tools.class_name(op_class)).to_sym
69
+ if op_class.unary?
70
+ define_method(meth_name) do |*args|
71
+ op = op_class.new(*args).pipe(self)
72
+ Relation.coerce(op)
73
+ end
74
+ elsif op_class.binary?
75
+ define_method(meth_name) do |right, *args|
76
+ op = op_class.new(*args).pipe([self, Iterator.coerce(right)])
77
+ Relation.coerce(op)
78
+ end
79
+ else
80
+ raise "Unexpected operator #{op_class}"
81
+ end
82
+ end # Operators::each
83
+
84
+ alias :+ :union
85
+ alias :- :minus
86
+
87
+ #
88
+ # (see Object#hash)
89
+ #
90
+ def hash
91
+ @tuples.hash
92
+ end
93
+
94
+ #
95
+ # (see Object#==)
96
+ #
97
+ def ==(other)
98
+ return nil unless other.is_a?(Relation)
99
+ other.tuples == self.tuples
100
+ end
101
+ alias :eql? :==
102
+
103
+ #
104
+ # Returns a textual representation of this relation
105
+ #
106
+ def to_s
107
+ Alf::Renderer.text(self).execute("")
108
+ end
109
+
110
+ #
111
+ # Returns a literal representation of this relation
112
+ #
113
+ def inspect
114
+ "Alf::Relation[" << @tuples.collect{|t| t.inspect}.join(',') << "]"
115
+ end
116
+
117
+ end # class Relation
118
+ end # module Alf
data/lib/alf/version.rb CHANGED
@@ -3,7 +3,7 @@ module Alf
3
3
 
4
4
  MAJOR = 0
5
5
  MINOR = 9
6
- TINY = 0
6
+ TINY = 1
7
7
 
8
8
  def self.to_s
9
9
  [ MAJOR, MINOR, TINY ].join('.')