alf 0.9.0 → 0.9.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 (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('.')