alf-shell 0.14.0 → 0.15.0

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 (276) hide show
  1. data/Gemfile +5 -2
  2. data/Gemfile.lock +29 -10
  3. data/bin/alf +2 -0
  4. data/doc/man/alf-explain.man +22 -0
  5. data/doc/man/alf-metadata.man +13 -0
  6. data/doc/man/alf-show.man +16 -0
  7. data/doc/man/alf.man +77 -0
  8. data/doc/man/allbut.man +39 -0
  9. data/doc/man/among.man +25 -0
  10. data/doc/man/avg.man +37 -0
  11. data/doc/man/between.man +24 -0
  12. data/doc/man/concat.man +55 -0
  13. data/doc/man/contradiction.man +26 -0
  14. data/doc/man/count.man +20 -0
  15. data/doc/man/eq.man +29 -0
  16. data/doc/man/extend.man +33 -0
  17. data/doc/man/frame.man +60 -0
  18. data/doc/man/group.man +51 -0
  19. data/doc/man/gt.man +30 -0
  20. data/doc/man/gte.man +30 -0
  21. data/doc/man/intersect.man +54 -0
  22. data/doc/man/join.man +84 -0
  23. data/doc/man/lt.man +30 -0
  24. data/doc/man/lte.man +30 -0
  25. data/doc/man/matching.man +73 -0
  26. data/doc/man/max.man +36 -0
  27. data/doc/man/min.man +36 -0
  28. data/doc/man/minus.man +54 -0
  29. data/doc/man/native.man +32 -0
  30. data/doc/man/neq.man +29 -0
  31. data/doc/man/not_matching.man +51 -0
  32. data/doc/man/page.man +60 -0
  33. data/doc/man/project.man +36 -0
  34. data/doc/man/rank.man +42 -0
  35. data/doc/man/rename.man +29 -0
  36. data/doc/man/restrict.man +38 -0
  37. data/doc/man/stddev.man +37 -0
  38. data/doc/man/sum.man +37 -0
  39. data/doc/man/summarize.man +45 -0
  40. data/doc/man/tautology.man +26 -0
  41. data/doc/man/ungroup.man +30 -0
  42. data/doc/man/union.man +55 -0
  43. data/doc/man/unwrap.man +37 -0
  44. data/doc/man/variance.man +37 -0
  45. data/doc/man/wrap.man +37 -0
  46. data/doc/txt/alf-explain.man +22 -0
  47. data/doc/txt/alf-metadata.man +16 -0
  48. data/doc/txt/alf-show.man +19 -0
  49. data/doc/txt/alf.man +80 -0
  50. data/doc/txt/allbut.txt +31 -0
  51. data/doc/txt/among.txt +20 -0
  52. data/doc/txt/avg.txt +22 -0
  53. data/doc/txt/between.txt +19 -0
  54. data/doc/txt/concat.txt +31 -0
  55. data/doc/txt/contradiction.txt +15 -0
  56. data/doc/txt/count.txt +14 -0
  57. data/doc/txt/eq.txt +19 -0
  58. data/doc/txt/extend.txt +29 -0
  59. data/doc/txt/frame.txt +48 -0
  60. data/doc/txt/group.txt +37 -0
  61. data/doc/txt/gt.txt +20 -0
  62. data/doc/txt/gte.txt +20 -0
  63. data/doc/txt/intersect.txt +42 -0
  64. data/doc/txt/join.txt +65 -0
  65. data/doc/txt/lt.txt +20 -0
  66. data/doc/txt/lte.txt +20 -0
  67. data/doc/txt/matching.txt +54 -0
  68. data/doc/txt/max.txt +21 -0
  69. data/doc/txt/min.txt +21 -0
  70. data/doc/txt/minus.txt +42 -0
  71. data/doc/txt/native.txt +27 -0
  72. data/doc/txt/neq.txt +19 -0
  73. data/doc/txt/not_matching.txt +39 -0
  74. data/doc/txt/page.txt +48 -0
  75. data/doc/txt/project.txt +28 -0
  76. data/doc/txt/rank.txt +34 -0
  77. data/doc/txt/rename.txt +25 -0
  78. data/doc/txt/restrict.txt +26 -0
  79. data/doc/txt/stddev.txt +22 -0
  80. data/doc/txt/sum.txt +22 -0
  81. data/doc/txt/summarize.txt +33 -0
  82. data/doc/txt/tautology.txt +15 -0
  83. data/doc/txt/ungroup.txt +26 -0
  84. data/doc/txt/union.txt +43 -0
  85. data/doc/txt/unwrap.txt +29 -0
  86. data/doc/txt/variance.txt +22 -0
  87. data/doc/txt/wrap.txt +29 -0
  88. data/lib/alf/shell.rb +2 -32
  89. data/lib/alf/shell/alfrc.rb +3 -0
  90. data/lib/alf/shell/command.rb +2 -18
  91. data/lib/alf/shell/command/explain.rb +37 -0
  92. data/lib/alf/shell/command/help.rb +3 -21
  93. data/lib/alf/shell/command/main.rb +20 -78
  94. data/lib/alf/shell/command/metadata.rb +32 -0
  95. data/lib/alf/shell/command/show.rb +17 -5
  96. data/lib/alf/shell/support.rb +21 -13
  97. data/lib/alf/shell/version.rb +1 -1
  98. data/spec/integration/explain/explain.cmd +1 -0
  99. data/spec/integration/explain/explain.stdout +11 -0
  100. data/spec/integration/show/group.alf +2 -0
  101. data/spec/integration/show/show_alf.cmd +1 -0
  102. data/spec/integration/{group/group_0.stdout → show/show_alf.stdout} +0 -0
  103. data/tasks/doc.rake +4 -0
  104. metadata +116 -178
  105. data/doc/commands/exec.md +0 -16
  106. data/doc/commands/help.md +0 -11
  107. data/doc/commands/main.md +0 -33
  108. data/doc/commands/show.md +0 -12
  109. data/doc/operators/non_relational/autonum.md +0 -23
  110. data/doc/operators/non_relational/clip.md +0 -31
  111. data/doc/operators/non_relational/coerce.md +0 -15
  112. data/doc/operators/non_relational/compact.md +0 -20
  113. data/doc/operators/non_relational/defaults.md +0 -32
  114. data/doc/operators/non_relational/generator.md +0 -20
  115. data/doc/operators/non_relational/sort.md +0 -24
  116. data/doc/operators/non_relational/type-safe.md +0 -20
  117. data/doc/operators/relational/extend.md +0 -18
  118. data/doc/operators/relational/frame.md +0 -26
  119. data/doc/operators/relational/group.md +0 -27
  120. data/doc/operators/relational/hierarchize.md +0 -14
  121. data/doc/operators/relational/infer-heading.md +0 -20
  122. data/doc/operators/relational/intersect.md +0 -13
  123. data/doc/operators/relational/join.md +0 -28
  124. data/doc/operators/relational/matching.md +0 -24
  125. data/doc/operators/relational/minus.md +0 -12
  126. data/doc/operators/relational/not-matching.md +0 -20
  127. data/doc/operators/relational/page.md +0 -31
  128. data/doc/operators/relational/project.md +0 -28
  129. data/doc/operators/relational/quota.md +0 -21
  130. data/doc/operators/relational/rank.md +0 -27
  131. data/doc/operators/relational/rename.md +0 -17
  132. data/doc/operators/relational/restrict.md +0 -25
  133. data/doc/operators/relational/summarize.md +0 -25
  134. data/doc/operators/relational/ungroup.md +0 -20
  135. data/doc/operators/relational/union.md +0 -14
  136. data/doc/operators/relational/unwrap.md +0 -20
  137. data/doc/operators/relational/wrap.md +0 -24
  138. data/lib/alf/shell/command/exec.rb +0 -16
  139. data/lib/alf/shell/doc_manager.rb +0 -84
  140. data/lib/alf/shell/ext/signature.rb +0 -45
  141. data/lib/alf/shell/from_argv.rb +0 -84
  142. data/lib/alf/shell/operator.rb +0 -63
  143. data/spec/integration/__database__/group.alf +0 -3
  144. data/spec/integration/alf/alf_e.cmd +0 -1
  145. data/spec/integration/alf/alf_e.stdout +0 -4
  146. data/spec/integration/alf/alf_help.cmd +0 -1
  147. data/spec/integration/alf/alf_help.stdout +0 -76
  148. data/spec/integration/alf/alf_r.cmd +0 -1
  149. data/spec/integration/alf/alf_r.stdout +0 -5
  150. data/spec/integration/autonum/autonum_0.cmd +0 -1
  151. data/spec/integration/autonum/autonum_0.stdout +0 -9
  152. data/spec/integration/autonum/autonum_1.cmd +0 -1
  153. data/spec/integration/autonum/autonum_1.stdout +0 -9
  154. data/spec/integration/clip/clip_0.cmd +0 -1
  155. data/spec/integration/clip/clip_0.stdout +0 -9
  156. data/spec/integration/clip/clip_1.cmd +0 -1
  157. data/spec/integration/clip/clip_1.stdout +0 -9
  158. data/spec/integration/coerce/coerce_1.cmd +0 -1
  159. data/spec/integration/coerce/coerce_1.stdout +0 -5
  160. data/spec/integration/compact/compact_0.cmd +0 -1
  161. data/spec/integration/compact/compact_0.stdout +0 -9
  162. data/spec/integration/defaults/defaults_0.cmd +0 -1
  163. data/spec/integration/defaults/defaults_0.stdout +0 -9
  164. data/spec/integration/defaults/defaults_1.cmd +0 -1
  165. data/spec/integration/defaults/defaults_1.stdout +0 -9
  166. data/spec/integration/defaults/defaults_2.cmd +0 -1
  167. data/spec/integration/defaults/defaults_2.stdout +0 -9
  168. data/spec/integration/extend/extend_0.cmd +0 -1
  169. data/spec/integration/extend/extend_0.stdout +0 -16
  170. data/spec/integration/frame/frame_0.cmd +0 -1
  171. data/spec/integration/frame/frame_0.stdout +0 -6
  172. data/spec/integration/generator/generator_1.cmd +0 -1
  173. data/spec/integration/generator/generator_1.stdout +0 -10
  174. data/spec/integration/generator/generator_2.cmd +0 -1
  175. data/spec/integration/generator/generator_2.stdout +0 -5
  176. data/spec/integration/generator/generator_3.cmd +0 -1
  177. data/spec/integration/generator/generator_3.stdout +0 -5
  178. data/spec/integration/group/group_0.cmd +0 -1
  179. data/spec/integration/group/group_1.cmd +0 -1
  180. data/spec/integration/group/group_1.stdout +0 -32
  181. data/spec/integration/help/help_1.cmd +0 -1
  182. data/spec/integration/help/help_1.stdout +0 -12
  183. data/spec/integration/intersect/intersect_0.cmd +0 -1
  184. data/spec/integration/intersect/intersect_0.stdout +0 -9
  185. data/spec/integration/join/join_0.cmd +0 -1
  186. data/spec/integration/join/join_0.stdout +0 -16
  187. data/spec/integration/matching/matching_0.cmd +0 -1
  188. data/spec/integration/matching/matching_0.stdout +0 -8
  189. data/spec/integration/minus/minus_0.cmd +0 -1
  190. data/spec/integration/minus/minus_0.stdout +0 -4
  191. data/spec/integration/not-matching/not-matching_0.cmd +0 -1
  192. data/spec/integration/not-matching/not-matching_0.stdout +0 -5
  193. data/spec/integration/page/page_0.cmd +0 -1
  194. data/spec/integration/page/page_0.stdout +0 -6
  195. data/spec/integration/project/project_0.cmd +0 -1
  196. data/spec/integration/project/project_0.stdout +0 -9
  197. data/spec/integration/project/project_1.cmd +0 -1
  198. data/spec/integration/project/project_1.stdout +0 -9
  199. data/spec/integration/quota/quota_0.cmd +0 -1
  200. data/spec/integration/quota/quota_0.stdout +0 -16
  201. data/spec/integration/rank/rank_1.cmd +0 -1
  202. data/spec/integration/rank/rank_1.stdout +0 -10
  203. data/spec/integration/rank/rank_2.cmd +0 -1
  204. data/spec/integration/rank/rank_2.stdout +0 -10
  205. data/spec/integration/rank/rank_3.cmd +0 -1
  206. data/spec/integration/rank/rank_3.stdout +0 -10
  207. data/spec/integration/rank/rank_4.cmd +0 -1
  208. data/spec/integration/rank/rank_4.stdout +0 -6
  209. data/spec/integration/rank/rank_5.cmd +0 -1
  210. data/spec/integration/rank/rank_5.stdout +0 -6
  211. data/spec/integration/rename/rename_0.cmd +0 -1
  212. data/spec/integration/rename/rename_0.stdout +0 -9
  213. data/spec/integration/restrict/restrict_0.cmd +0 -1
  214. data/spec/integration/restrict/restrict_0.stdout +0 -6
  215. data/spec/integration/restrict/restrict_1.cmd +0 -1
  216. data/spec/integration/restrict/restrict_1.stdout +0 -6
  217. data/spec/integration/sort/sort_0.cmd +0 -1
  218. data/spec/integration/sort/sort_0.stdout +0 -9
  219. data/spec/integration/sort/sort_1.cmd +0 -1
  220. data/spec/integration/sort/sort_1.stdout +0 -9
  221. data/spec/integration/sort/sort_2.cmd +0 -1
  222. data/spec/integration/sort/sort_2.stdout +0 -9
  223. data/spec/integration/sort/sort_3.cmd +0 -1
  224. data/spec/integration/sort/sort_3.stdout +0 -9
  225. data/spec/integration/summarize/summarize_0.cmd +0 -1
  226. data/spec/integration/summarize/summarize_0.stdout +0 -8
  227. data/spec/integration/union/union_0.cmd +0 -1
  228. data/spec/integration/union/union_0.stdout +0 -9
  229. data/spec/integration/unwrap/unwrap_0.cmd +0 -1
  230. data/spec/integration/unwrap/unwrap_0.stdout +0 -9
  231. data/spec/integration/wrap/wrap_0.cmd +0 -1
  232. data/spec/integration/wrap/wrap_0.stdout +0 -9
  233. data/spec/unit/doc_manager/dynamic.md +0 -1
  234. data/spec/unit/doc_manager/example.md +0 -1
  235. data/spec/unit/doc_manager/example_1.txt +0 -11
  236. data/spec/unit/doc_manager/static.md +0 -1
  237. data/spec/unit/doc_manager/test_call.rb +0 -41
  238. data/spec/unit/ext/signature/test_argv2args.rb +0 -82
  239. data/spec/unit/ext/signature/test_to_shell.rb +0 -103
  240. data/spec/unit/from_argv/test_to_attr_list.rb +0 -30
  241. data/spec/unit/from_argv/test_to_attr_name.rb +0 -27
  242. data/spec/unit/from_argv/test_to_boolean.rb +0 -32
  243. data/spec/unit/from_argv/test_to_heading.rb +0 -37
  244. data/spec/unit/from_argv/test_to_ordering.rb +0 -28
  245. data/spec/unit/from_argv/test_to_predicate.rb +0 -26
  246. data/spec/unit/from_argv/test_to_renaming.rb +0 -23
  247. data/spec/unit/from_argv/test_to_size.rb +0 -32
  248. data/spec/unit/from_argv/test_to_summarization.rb +0 -19
  249. data/spec/unit/from_argv/test_to_tuple_computation.rb +0 -18
  250. data/spec/unit/from_argv/test_to_tuple_expression.rb +0 -38
  251. data/spec/unit/main/test_class_methods.rb +0 -44
  252. data/spec/unit/operator/test_autonum.rb +0 -28
  253. data/spec/unit/operator/test_clip.rb +0 -29
  254. data/spec/unit/operator/test_coerce.rb +0 -22
  255. data/spec/unit/operator/test_compact.rb +0 -16
  256. data/spec/unit/operator/test_defaults.rb +0 -29
  257. data/spec/unit/operator/test_extend.rb +0 -21
  258. data/spec/unit/operator/test_generator.rb +0 -37
  259. data/spec/unit/operator/test_group.rb +0 -32
  260. data/spec/unit/operator/test_infer_heading.rb +0 -16
  261. data/spec/unit/operator/test_intersect.rb +0 -18
  262. data/spec/unit/operator/test_join.rb +0 -18
  263. data/spec/unit/operator/test_matching.rb +0 -18
  264. data/spec/unit/operator/test_minus.rb +0 -18
  265. data/spec/unit/operator/test_not_matching.rb +0 -18
  266. data/spec/unit/operator/test_project.rb +0 -38
  267. data/spec/unit/operator/test_quota.rb +0 -23
  268. data/spec/unit/operator/test_rank.rb +0 -30
  269. data/spec/unit/operator/test_rename.rb +0 -21
  270. data/spec/unit/operator/test_restrict.rb +0 -36
  271. data/spec/unit/operator/test_sort.rb +0 -49
  272. data/spec/unit/operator/test_summarize.rb +0 -30
  273. data/spec/unit/operator/test_ungroup.rb +0 -28
  274. data/spec/unit/operator/test_union.rb +0 -18
  275. data/spec/unit/operator/test_unwrap.rb +0 -28
  276. data/spec/unit/operator/test_wrap.rb +0 -30
@@ -0,0 +1,20 @@
1
+ # Lt
2
+
3
+ Less than
4
+
5
+ ## Signature
6
+
7
+ lt(left: Alpha|AttrName, right: Alpha|AttrName) -> Predicate
8
+
9
+ ## Examples
10
+ lt(:status, 20)
11
+ lt(:status, 30)
12
+
13
+ ## Description
14
+
15
+ This predicates checks whether a value (`left`) is less than another one
16
+ (`right`).
17
+
18
+ ## Implementation notes
19
+
20
+ This predicate is equivalent to `->(t){ _left_ < _right_ }`.
@@ -0,0 +1,20 @@
1
+ # Lte
2
+
3
+ Less than or equal to
4
+
5
+ ## Signature
6
+
7
+ lte(left: Alpha|AttrName, right: Alpha|AttrName) -> Predicate
8
+
9
+ ## Examples
10
+ lte(:status, 20)
11
+ lte(:status, 30)
12
+
13
+ ## Description
14
+
15
+ This predicates checks whether a value (`left`) is less than or equal to
16
+ another one (`right`).
17
+
18
+ ## Implementation notes
19
+
20
+ This predicate is equivalent to `->(t){ _left_ <= _right_ }`.
@@ -0,0 +1,54 @@
1
+ # Matching
2
+
3
+ Aka 'where exists'
4
+
5
+ ## Signature
6
+
7
+ matching(left: Relation, right: Relation) -> Relation
8
+
9
+ ## Examples
10
+
11
+ matching(suppliers, supplies)
12
+
13
+ ## Description
14
+
15
+ Computes a relation as a subset of `left` tuples for which at least one
16
+ `right` tuple would join on common attributes.
17
+
18
+ This operator, also known as semi-join, can be explained through the
19
+ definition below. As shown, it consists in joining `left` and `right`
20
+ relations and projecting the result back on `left` attributes.
21
+
22
+ def matching(left, right)
23
+ project(join(left, right), left.attr_list)
24
+ end
25
+ matching(suppliers, supplies)
26
+
27
+ Or, in SQL terms:
28
+
29
+ SELECT left.* FROM left NATURAL JOIN right
30
+
31
+ The synonym 'where exists' comes from the fact that, since right attributes
32
+ are projected away, it may seem more intuitive to think about this operator
33
+ as filtering tuples from left where _there exists_ some tuple at right that
34
+ _would_ join. In SQL terms:
35
+
36
+ SELECT * FROM left WHERE EXISTS (SELECT * FROM right WHERE [join condition])
37
+
38
+ ## Implementation notes
39
+
40
+ As for (natural) `join`, you must take care of ensuring that the list of
41
+ common attributes on which the matching applies corresponds to what you
42
+ want. Renamings and projections are worth having at hand when using
43
+ matching. Alternatively, shortcuts can be considered. A (advanced) example
44
+ below:
45
+
46
+ # Same as matching(left, right) except that only attributes in `wish`
47
+ # are take into account in matching.
48
+ def matching_on(left, right, wish)
49
+ matching(left, project(right, wish))
50
+ end
51
+
52
+ # observe here how part names have been discarded to avoid matching them
53
+ # with supplier names (empty result guaranteed)
54
+ matching_on(suppliers, parts, [:city])
@@ -0,0 +1,21 @@
1
+ # Max
2
+
3
+ Maximal value
4
+
5
+ ## Signature
6
+
7
+ max(expr: AttrName|(Tuple->Numeric)) -> Aggregator
8
+
9
+ ## Examples
10
+ max(:qty)
11
+ max{|t| t.qty * t.price }
12
+ max(->(t){ t.qty * t.price })
13
+
14
+ ## Description
15
+
16
+ Returns the greatest of input values.
17
+
18
+ ## Implementation notes
19
+
20
+ This aggregate function must only be used with comparable types. As of
21
+ current Alf version, it does not aggregate empty sets correctly.
@@ -0,0 +1,21 @@
1
+ # Min
2
+
3
+ Minimal value
4
+
5
+ ## Signature
6
+
7
+ min(expr: AttrName|(Tuple->Numeric)) -> Aggregator
8
+
9
+ ## Examples
10
+ min(:qty)
11
+ min{|t| t.qty * t.price }
12
+ min(->(t){ t.qty * t.price })
13
+
14
+ ## Description
15
+
16
+ Returns the smallest of input values.
17
+
18
+ ## Implementation notes
19
+
20
+ This aggregate function must only be used with comparable types. As of
21
+ current Alf version, it does not aggregate empty sets correctly.
@@ -0,0 +1,42 @@
1
+ # Minus
2
+
3
+ Logical AND NOT
4
+
5
+ ## Signature
6
+
7
+ minus(left: Relation, right: Relation) -> Relation
8
+
9
+ ## Examples
10
+
11
+ minus(
12
+ restrict(suppliers, eq(:city, 'Paris')),
13
+ restrict(suppliers, gt(:status, 10)))
14
+
15
+ ## Description
16
+
17
+ Computes the relation as the set difference of `left` and `right`.
18
+
19
+ The `left` and `right` relations must be minus-compatible, which meaning
20
+ that they must have same heading (type inheritance is partly supported
21
+ through ruby's own type system, so that the actual behavior is slighlty more
22
+ permissive).
23
+
24
+ ## Implementation notes
25
+
26
+ Unlike SQL, this operator ALWAYS remove duplicates. There is no way, in
27
+ Alf, to compute _bags_ of tuples and therefore no way to express something
28
+ such as SQL's EXCEPT ALL.
29
+
30
+ It is sometimes idiomatic in Alf to use `intersect` as a logical AND NOT, as
31
+ illustrated below. So far, the optimizer/compiler is not smart enough to
32
+ translate the former into the latter (which is likely to have a better query
33
+ plan when using faithful SQL compilation and available SQL DBMSs). Any patch
34
+ is welcome here too!
35
+
36
+ minus(
37
+ restrict(suppliers, eq(:city, 'Paris')),
38
+ restrict(suppliers, gt(:status, 10)))
39
+
40
+ is equivalent to
41
+
42
+ restrict(suppliers, eq(:city, 'Paris') & !gt(:status, 10))
@@ -0,0 +1,27 @@
1
+ # Native
2
+
3
+ User-defined tuple predicate
4
+
5
+ ## Signature
6
+
7
+ native(predicate: (Tuple -> Boolean)) -> Predicate
8
+
9
+ ## Examples
10
+ ->(t){ t.city == 'London' }
11
+
12
+ ## Description
13
+
14
+ So called 'native' predicates are functions computing truth values from
15
+ tuples.
16
+
17
+ ## Implementation notes
18
+
19
+ Native predicates can be any ruby Proc object of arity 1. The argument
20
+ will be a Tuple instance. the Proc SHOULD return true or false, but ruby
21
+ patterns for boolean expressions are supported to (such a nil evaluating
22
+ to false, etc.).
23
+
24
+ Note that, as of current Alf version, native predicates cannot be delegated
25
+ to an underlying data engine, and are not compiled to SQL in particular.
26
+ Please always use predicate factories such as `eq(:city, 'London')` if
27
+ possible, as they do not hurt logical optimizations and compilation.
@@ -0,0 +1,19 @@
1
+ # Neq
2
+
3
+ Not equal to
4
+
5
+ ## Signature
6
+
7
+ neq(left: Alpha|AttrName, right: Alpha|AttrName) -> Predicate
8
+
9
+ ## Examples
10
+ neq(:city, 'London')
11
+ neq(:supplier_city, :part_city)
12
+
13
+ ## Description
14
+
15
+ This predicates checks whether two values are different.
16
+
17
+ ## Implementation notes
18
+
19
+ This predicate is equivalent to `->(t){ _left_ != _right_ }`.
@@ -0,0 +1,39 @@
1
+ # Not_matching
2
+
3
+ Aka 'where not exists'
4
+
5
+ ## Signature
6
+
7
+ not_matching(left: Relation, right: Relation) -> Relation
8
+
9
+ ## Examples
10
+
11
+ not_matching(suppliers, supplies)
12
+
13
+ ## Description
14
+
15
+ Computes a relation as a subset of `left` tuples for which no tuple from
16
+ `right` would join on common attributes.
17
+
18
+ This operator is the inverse of `matching`, as shown by the definition
19
+ below. It keeps all tuples from `left` but those that match a tuple from
20
+ `right`.
21
+
22
+ def not_matching(left, right)
23
+ minus(left, matching(left, right))
24
+ end
25
+ not_matching(suppliers, supplies)
26
+
27
+ The synonym 'where not exists' comes from the fact that, since right
28
+ attributes do not appear in the result, it may seem more intuitive to think
29
+ about this operator as filtering tuples from left where _there does not
30
+ exist_ any tuple from right that _would_ join. In SQL terms:
31
+
32
+ SELECT * FROM left WHERE NOT EXISTS (SELECT * FROM right WHERE [join condition])
33
+
34
+ ## Implementation notes
35
+
36
+ As for join and matching, you must take care of ensuring that the list of
37
+ common attributes on which the (not) matching applies corresponds to what
38
+ you want. Renamings and projections are worth having at hand.
39
+ Alternatively, shortcuts can be considered (see `matching` and `join`).
@@ -0,0 +1,48 @@
1
+ # Page
2
+
3
+ Pagination
4
+
5
+ ## Signature
6
+
7
+ page(operand: Relation, ordering: Ordering, nth: Integer) -> Relation
8
+
9
+ ## Examples
10
+
11
+ page(suppliers, [:status, :sid], 1, page_size: 3)
12
+
13
+ page(suppliers, [:status, :sid], -1, page_size: 3)
14
+
15
+ ## Description
16
+
17
+ Computes a relation by restricting the tuples of `operand` to those
18
+ belonging to the `nth` page (starting at 1). When `nth` is negative, returns
19
+ tuples that belong to the `nth` page from the end (e.g., -1 is last page).
20
+
21
+ Formally, the page is defined by those tuples whose ranking according to
22
+ `order` is such that `(nth-1)*page_size <= rank < nth*page_size`. In other
23
+ words, this operator is almost equivalent to the following definition
24
+ (ignoring negative page indexes for simplicity):
25
+
26
+ def page(operand, order, nth, page_size)
27
+ allbut(
28
+ restrict(
29
+ rank(operand, order, :rank),
30
+ lte((nth-1)*page_size, :rank) & lt(:rank, nth*page_size)),
31
+ [:rank])
32
+ end
33
+
34
+ As of current Alf version, for this operator to be semantically sound and
35
+ deterministic, `order` MUST be a total order, that is, it must at least
36
+ cover a candidate key. As of current Alf version, no error is raised if
37
+ this is not the case but that might change in future versions.
38
+
39
+ ## Implementation notes
40
+
41
+ Contrary to the longer expression shown above, this operator compiles to
42
+ SQL (rank does not, so far) at the cost of having to provide a total
43
+ order.
44
+
45
+ As the result is a relation and relations are not ordered by definition,
46
+ the order in which tuples can be observed in the result (e.g. through
47
+ explicit tuple iteration, casting to an array, json encoding) is NOT
48
+ guaranteed to follow `order`.
@@ -0,0 +1,28 @@
1
+ # Project
2
+
3
+ Keeps only a subset of attributes.
4
+
5
+ ## Signature
6
+
7
+ project(operand: Relation, attributes: AttrList) -> Relation
8
+
9
+ ## Examples
10
+
11
+ project(suppliers, [:city])
12
+
13
+ project(suppliers, [:city], allbut: true)
14
+
15
+ ## Description
16
+
17
+ Computes the relation obtained by projecting tuples from `operand` on a
18
+ subset of their attributes.
19
+
20
+ This operator supports an ALL BUT variant, through the `allbut` option.
21
+ When set to true, the operator _removes_ specified attributes instead of
22
+ keeping them. An `allbut` operator is also provided that has the same
23
+ effect.
24
+
25
+ ## Implementation notes
26
+
27
+ Unlike SQL, this operator ALWAYS remove duplicates. There is no way, in
28
+ Alf, to compute _bags_ of tuples.
@@ -0,0 +1,34 @@
1
+ # Rank
2
+
3
+ Tuple ranking
4
+
5
+ ## Signature
6
+
7
+ rank(operand: Relation, order: Ordering, as: AttrName) -> Relation
8
+
9
+ ## Examples
10
+
11
+ rank(suppliers, [:status], :ranking)
12
+
13
+ rank(suppliers, [:status, :sid], :ranking)
14
+
15
+ ## Description
16
+
17
+ Extends tuples from `operand` with a new attribute (`as`) capturing the
18
+ tuple position with respect to `order`.
19
+
20
+ The ranking of a tuple `t` is more precisely defined as the number of tuples
21
+ from `operand` that would come strictly before `t` if they were all ordered
22
+ according to `order`. 'Equal' tuples with respect to `order` are not counted
23
+ in this ranking.
24
+
25
+ This means that, unless `order` is a total order, duplicate ranking may be
26
+ observed. In contrast, if `order` covers a candidate key then the ranking
27
+ attribute (`as`) is unique, and therefore defines an additional candidate
28
+ key for the resulting relation.
29
+
30
+ ## Implementation notes
31
+
32
+ Note that this operator does not compile to SQL so far. The `page` and
33
+ `frame` operators provide useful alternatives when the aim is to compute
34
+ a subset of tuples based on a ranking.
@@ -0,0 +1,25 @@
1
+ # Rename
2
+
3
+ Rename attributes
4
+
5
+ ## Signature
6
+
7
+ rename(operand: Relation, renaming: Renaming) -> Relation
8
+
9
+ ## Examples
10
+
11
+ rename(suppliers, :sid => :supplier_id, :city => :lives_in)
12
+
13
+ ## Description
14
+
15
+ Computes the same relation as `operand` expect that some attributes have
16
+ been renamed.
17
+
18
+ ## Implementation notes
19
+
20
+ As of current version, renamings can only be expressed through a Hash
21
+ mapping input to output attribute names.
22
+
23
+ Other ways of specifying renamining will be added in future versions, such
24
+ as prefixing, postfixing, renaming through a Proc, etc. Any patch towards
25
+ these improvements is welcome.
@@ -0,0 +1,26 @@
1
+ # Restrict
2
+
3
+ Predicate-based filtering
4
+
5
+ ## Signature
6
+
7
+ restrict(operand: Relation, predicate: Predicate) -> Relation
8
+
9
+ ## Examples
10
+
11
+ restrict(suppliers, city: 'Paris', status: 20)
12
+
13
+ restrict(suppliers, eq(city: 'Paris') & gt(:status, 20))
14
+
15
+ restrict(suppliers, ->(t){ t.city == 'Paris' and t.status > 20 })
16
+
17
+ ## Description
18
+
19
+ Computes a relation as a subset of `operand` tuples for which a tuple
20
+ predicate evaluates to TRUE.
21
+
22
+ ## Implementation notes
23
+
24
+ As of current Alf version, native predicates (through ruby `Proc` objects)
25
+ cannot be optimized nor compiled to SQL. The use of predicate factories
26
+ (`eq`, `gt`, etc.) is strongly recommanded.
@@ -0,0 +1,22 @@
1
+ # Stddev
2
+
3
+ Standard deviation
4
+
5
+ ## Signature
6
+
7
+ stddev(expr: AttrName|(Tuple->Numeric)) -> Aggregator
8
+
9
+ ## Examples
10
+ stddev(:qty)
11
+ stddev{|t| t.qty * t.price }
12
+ stddev(->(t){ t.qty * t.price })
13
+
14
+ ## Description
15
+
16
+ Computes how much variation from the average exists.
17
+
18
+ ## Implementation notes
19
+
20
+ This aggregate function should only be used with numeric types. As of
21
+ current Alf version, it does not aggregate empty sets correctly on
22
+ non-numeric data types.