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,29 @@
1
+ .TH Eq
2
+ .PP
3
+ Equals to
4
+ .SH Signature
5
+ .PP
6
+ .RS
7
+ .nf
8
+ eq(left: Alpha|AttrName, right: Alpha|AttrName) -> Predicate
9
+ .fi
10
+ .RE
11
+ .SH Examples
12
+ .PP
13
+ .RS
14
+ .nf
15
+ eq(:city, 'London')
16
+ .fi
17
+ .RE
18
+ .PP
19
+ .RS
20
+ .nf
21
+ eq(:supplier_city, :part_city)
22
+ .fi
23
+ .RE
24
+ .SH Description
25
+ .PP
26
+ This predicates checks whether two values are equal.
27
+ .SH Implementation notes
28
+ .PP
29
+ This predicate is equivalent to \fB\fC->(t){ _left_ == _right_ }\fR\&.
@@ -0,0 +1,33 @@
1
+ .TH Extend
2
+ .PP
3
+ Extends input tuples with derived/computed attributes
4
+ .SH Signature
5
+ .PP
6
+ .RS
7
+ .nf
8
+ extend(operand: Relation, ext: TupleComputation) -> Relation
9
+ .fi
10
+ .RE
11
+ .SH Examples
12
+ .PP
13
+ .RS
14
+ .nf
15
+ extend(suppliers,
16
+ big: ->(t){ t.name.upcase },
17
+ small: ->(t){ t.name.downcase })
18
+ .fi
19
+ .RE
20
+ .SH Description
21
+ .PP
22
+ Computes a relation which is the same as \fB\fCoperand\fR, except that each of
23
+ its tuples has new attributes whose value is the result of evaluating the
24
+ tuple expressions specified in \fB\fCext\fR\&.
25
+ .SH Implementation notes
26
+ .PP
27
+ As of current Alf version, this operator cannot be translated to SQL code.
28
+ In other words, all computations are done in ruby, which may seriously
29
+ hurt performance.
30
+ .PP
31
+ Similarly, as \fB\fCextend\fR tends to be a showstopper during compilation, it is
32
+ strongly recommanded to use it as high as possible in query expressions
33
+ trees so as to delegate the largest possible query parts to data engines.
@@ -0,0 +1,60 @@
1
+ .TH Frame
2
+ .PP
3
+ Aka limit/offset
4
+ .SH Signature
5
+ .PP
6
+ .RS
7
+ .nf
8
+ frame(operand: Relation, order: Ordering, offset: Integer, limit: Integer) -> Relation
9
+ .fi
10
+ .RE
11
+ .SH Examples
12
+ .PP
13
+ .RS
14
+ .nf
15
+ frame(suppliers, [:status, :sid], 0, 3)
16
+ .fi
17
+ .RE
18
+ .PP
19
+ .RS
20
+ .nf
21
+ frame(suppliers, [[:status, :asc], [:sid, :desc]], 1, 2)
22
+ .fi
23
+ .RE
24
+ .SH Description
25
+ .PP
26
+ Computes a relation by restricting the tuples of \fB\fCoperand\fR to a particular
27
+ frame. This frame can be easily remembered through the "skip \fB\fCoffset\fR,
28
+ take \fB\fClimit\fR" mnemonic mean, provided \fB\fCorder\fR is a total order.
29
+ .PP
30
+ Formally, the frame is defined by those tuples whose ranking according to
31
+ \fB\fCorder\fR is such that \fB\fCoffset <= rank < limit\fR\&. In other words, this
32
+ operator is actually equivalent to the following definition:
33
+ .PP
34
+ .RS
35
+ .nf
36
+ def frame(operand, order, offset, limit)
37
+ allbut(
38
+ restrict(
39
+ rank(operand, order, :rank),
40
+ lte(offset, :rank) & lt(:rank, offset+limit)),
41
+ [:rank])
42
+ end
43
+ frame(suppliers, [:city, :sid], 2, 3)
44
+ .fi
45
+ .RE
46
+ .PP
47
+ As of current Alf version, for this operator to be semantically sound and
48
+ deterministic, \fB\fCorder\fR MUST be a total order, that is, it must at least
49
+ cover a candidate key. As of current Alf version, no error is raised if
50
+ this is not the case but that might change in future versions.
51
+ .SH Implementation notes
52
+ .PP
53
+ Contrary to the longer expression shown above, this operator compiles to
54
+ \&'efficient' SQL (rank does not, so far) at the cost of having to provide a
55
+ total order.
56
+ .PP
57
+ As the result is a relation and relations are not ordered by definition,
58
+ the order in which tuples can be observed in the result (e.g. through
59
+ explicit tuple iteration, casting to an array, json encoding) is NOT
60
+ guaranteed to follow \fB\fCorder\fR\&.
@@ -0,0 +1,51 @@
1
+ .TH Group
2
+ .PP
3
+ Relation\-valued attribute
4
+ .SH Signature
5
+ .PP
6
+ .RS
7
+ .nf
8
+ group(operand: Relation, attributes: AttrList, as: AttrName) -> Relation
9
+ .fi
10
+ .RE
11
+ .SH Examples
12
+ .PP
13
+ .RS
14
+ .nf
15
+ group(suppliers, [:sid, :name, :status], :suppliers)
16
+ .fi
17
+ .RE
18
+ .PP
19
+ .RS
20
+ .nf
21
+ group(suppliers, [:city], :suppliers, allbut: true)
22
+ .fi
23
+ .RE
24
+ .SH Description
25
+ .PP
26
+ Summarizes \fB\fCoperand\fR by all but the specified \fB\fCattributes\fR and groups the
27
+ latter under a relation\-value attribute \fB\fCas\fR\&.
28
+ .PP
29
+ This operator could be formally defined as the following shortcut:
30
+ .PP
31
+ .RS
32
+ .nf
33
+ def group(operand, attributes, as)
34
+ extend(
35
+ allbut(operand, attributes),
36
+ as: ->(t){ project(matching(operand,
37
+ .BR Relation (t)),
38
+ attributes) })
39
+ end
40
+ group(suppliers, [:sid, :name, :status], :suppliers)
41
+ .fi
42
+ .RE
43
+ .PP
44
+ This operators supports an ALL BUT variant, through the \fB\fCallbut\fR option.
45
+ When set to true, the operator keeps specified attributes and groups all
46
+ remaining ones as a relation\-valued attribute.
47
+ .SH Implementation notes
48
+ .PP
49
+ This operator does not compile to SQL so far. Contributions are welcome
50
+ to provide it with a SQL compilation for SQL DBMSs that support this kind
51
+ of feature (e.g. PostgreSQL with JSON data type)
@@ -0,0 +1,30 @@
1
+ .TH Gt
2
+ .PP
3
+ Greater than
4
+ .SH Signature
5
+ .PP
6
+ .RS
7
+ .nf
8
+ gt(left: Alpha|AttrName, right: Alpha|AttrName) -> Predicate
9
+ .fi
10
+ .RE
11
+ .SH Examples
12
+ .PP
13
+ .RS
14
+ .nf
15
+ gt(:status, 20)
16
+ .fi
17
+ .RE
18
+ .PP
19
+ .RS
20
+ .nf
21
+ gt(:status, 30)
22
+ .fi
23
+ .RE
24
+ .SH Description
25
+ .PP
26
+ This predicates checks whether a value (\fB\fCleft\fR) is greater than another
27
+ one (\fB\fCright\fR).
28
+ .SH Implementation notes
29
+ .PP
30
+ This predicate is equivalent to \fB\fC->(t){ _left_ > _right_ }\fR\&.
@@ -0,0 +1,30 @@
1
+ .TH Gte
2
+ .PP
3
+ Greater than or equal to
4
+ .SH Signature
5
+ .PP
6
+ .RS
7
+ .nf
8
+ gte(left: Alpha|AttrName, right: Alpha|AttrName) -> Predicate
9
+ .fi
10
+ .RE
11
+ .SH Examples
12
+ .PP
13
+ .RS
14
+ .nf
15
+ gte(:status, 20)
16
+ .fi
17
+ .RE
18
+ .PP
19
+ .RS
20
+ .nf
21
+ gte(:status, 30)
22
+ .fi
23
+ .RE
24
+ .SH Description
25
+ .PP
26
+ This predicates checks whether a value (\fB\fCleft\fR) is greater than or equal
27
+ to another one (\fB\fCright\fR).
28
+ .SH Implementation notes
29
+ .PP
30
+ This predicate is equivalent to \fB\fC->(t){ _left_ >= _right_ }\fR\&.
@@ -0,0 +1,54 @@
1
+ .TH Intersect
2
+ .PP
3
+ Logical AND
4
+ .SH Signature
5
+ .PP
6
+ .RS
7
+ .nf
8
+ intersect(left: Relation, right: Relation) -> Relation
9
+ .fi
10
+ .RE
11
+ .SH Examples
12
+ .PP
13
+ .RS
14
+ .nf
15
+ intersect(
16
+ restrict(suppliers, eq(:city, 'Paris')),
17
+ restrict(suppliers, gt(:status, 10)))
18
+ .fi
19
+ .RE
20
+ .SH Description
21
+ .PP
22
+ Computes the relation as the set intersection of \fB\fCleft\fR and \fB\fCright\fR\&.
23
+ .PP
24
+ The \fB\fCleft\fR and \fB\fCright\fR relations must be intersect\-compatible, meaning that
25
+ they must have same heading (type inheritance is partly supported through
26
+ ruby's own type system, so that the actual behavior is slighlty more
27
+ permissive).
28
+ .SH Implementation notes
29
+ .PP
30
+ Unlike SQL, this operator ALWAYS remove duplicates. There is no way, in
31
+ Alf, to compute \fIbags\fP of tuples and therefore no way to express something
32
+ such as SQL's INTERSECT ALL.
33
+ .PP
34
+ It is sometimes idiomatic in Alf to use \fB\fCintersect\fR as a logical AND, as
35
+ illustrated below. So far, the optimizer/compiler is not smart enough to
36
+ translate the former into the latter (which is likely to have a better query
37
+ when using faithful SQL compilation and available SQL DBMSs). Any patch is
38
+ welcome here too!
39
+ .PP
40
+ .RS
41
+ .nf
42
+ intersect(
43
+ restrict(suppliers, eq(:city, 'Paris')),
44
+ restrict(suppliers, gt(:status, 10)))
45
+ .fi
46
+ .RE
47
+ .PP
48
+ is equivalent to
49
+ .PP
50
+ .RS
51
+ .nf
52
+ restrict(suppliers, eq(:city, 'Paris') & gt(:status, 10))
53
+ .fi
54
+ .RE
@@ -0,0 +1,84 @@
1
+ .TH Join
2
+ .PP
3
+ Natural join
4
+ .SH Signature
5
+ .PP
6
+ .RS
7
+ .nf
8
+ join(left: Relation, right: Relation) -> Relation
9
+ .fi
10
+ .RE
11
+ .SH Examples
12
+ .PP
13
+ .RS
14
+ .nf
15
+ join(suppliers, supplies)
16
+ .fi
17
+ .RE
18
+ .SH Description
19
+ .PP
20
+ Computes the relation resuting from joining tuples from \fB\fCleft\fR and \fB\fCright\fR
21
+ whose respective projections on common attributes are equal.
22
+ .SH Implementation notes
23
+ .PP
24
+ Alf only support natural join for now. Other kinds of join can generally
25
+ be computed through longer expressions. For instance, joining on attributes
26
+ with different names requires some renaming first:
27
+ .PP
28
+ .RS
29
+ .nf
30
+ # suppose preferences has type Relation[supplier_id: String, ...]
31
+ # suppose we want to join on suppliers.sid == preferences.supplier_id
32
+ join(suppliers, rename(preferences, :supplier_id => :sid))
33
+ .fi
34
+ .RE
35
+ .PP
36
+ Cross joins can be computed through operands having no attribute in common.
37
+ For instance, all pairs of supplier and part identifiers can be computed
38
+ as follows:
39
+ .PP
40
+ .RS
41
+ .nf
42
+ pairs = join(project(suppliers, [:sid]), project(parts, [:pid]))
43
+ .fi
44
+ .RE
45
+ .PP
46
+ Non equi\-joins can be computed through a latter restriction. For instance,
47
+ the (supplier, part) pairs not located in the same city:
48
+ .PP
49
+ .RS
50
+ .nf
51
+ ps = project(rename(parts, :city => :part_city), [:pid, :part_city])
52
+ ss = project(rename(suppliers, :city => :supplier_city), [:sid, :supplier_city])
53
+ pairs = join(ps, ss)
54
+ project(restrict(pairs, neq(:part_city, :supplier_city)), [:sid, :pid])
55
+ .fi
56
+ .RE
57
+ .PP
58
+ As obviously demonstrated by the example above, such query is rather
59
+ cumbersome to write and verbous. Future versions of Alf will come with
60
+ useful shortcuts and new operators. In the mean time, don't forget that
61
+ defining your own shortcuts and operators is easy! Don't hesitate to
62
+ contribute them if of general purpose.
63
+ .PP
64
+ Last, natural join tends to be error prone; in particular, you must take
65
+ care of common attributes of your design on which you do not want to join
66
+ (such as \fB\fClatest_change\fR and \fB\fCdeleted\fR fields and the like). Renamings and
67
+ projections are worth having at hand when joining.
68
+ .PP
69
+ Alternatively, shortcuts can be considered. A (advanced) example below:
70
+ .PP
71
+ .RS
72
+ .nf
73
+ # The following shortcut joins `left` and `right` on `wish` attributes
74
+ # only. Other common attributes are simply projected away from `right`
75
+ # before joining.
76
+ def join_on(left, right, wish)
77
+ commons = left.attr_list & right.attr_list
78
+ join(left, allbut(right, commons - wish))
79
+ end
80
+ # observe here how part names have been discarded to avoid joining them
81
+ # with supplier names (empty result guaranteed)
82
+ join_on(suppliers, parts, [:city])
83
+ .fi
84
+ .RE
@@ -0,0 +1,30 @@
1
+ .TH Lt
2
+ .PP
3
+ Less than
4
+ .SH Signature
5
+ .PP
6
+ .RS
7
+ .nf
8
+ lt(left: Alpha|AttrName, right: Alpha|AttrName) -> Predicate
9
+ .fi
10
+ .RE
11
+ .SH Examples
12
+ .PP
13
+ .RS
14
+ .nf
15
+ lt(:status, 20)
16
+ .fi
17
+ .RE
18
+ .PP
19
+ .RS
20
+ .nf
21
+ lt(:status, 30)
22
+ .fi
23
+ .RE
24
+ .SH Description
25
+ .PP
26
+ This predicates checks whether a value (\fB\fCleft\fR) is less than another one
27
+ (\fB\fCright\fR).
28
+ .SH Implementation notes
29
+ .PP
30
+ This predicate is equivalent to \fB\fC->(t){ _left_ < _right_ }\fR\&.
@@ -0,0 +1,30 @@
1
+ .TH Lte
2
+ .PP
3
+ Less than or equal to
4
+ .SH Signature
5
+ .PP
6
+ .RS
7
+ .nf
8
+ lte(left: Alpha|AttrName, right: Alpha|AttrName) -> Predicate
9
+ .fi
10
+ .RE
11
+ .SH Examples
12
+ .PP
13
+ .RS
14
+ .nf
15
+ lte(:status, 20)
16
+ .fi
17
+ .RE
18
+ .PP
19
+ .RS
20
+ .nf
21
+ lte(:status, 30)
22
+ .fi
23
+ .RE
24
+ .SH Description
25
+ .PP
26
+ This predicates checks whether a value (\fB\fCleft\fR) is less than or equal to
27
+ another one (\fB\fCright\fR).
28
+ .SH Implementation notes
29
+ .PP
30
+ This predicate is equivalent to \fB\fC->(t){ _left_ <= _right_ }\fR\&.
@@ -0,0 +1,73 @@
1
+ .TH Matching
2
+ .PP
3
+ Aka 'where exists'
4
+ .SH Signature
5
+ .PP
6
+ .RS
7
+ .nf
8
+ matching(left: Relation, right: Relation) -> Relation
9
+ .fi
10
+ .RE
11
+ .SH Examples
12
+ .PP
13
+ .RS
14
+ .nf
15
+ matching(suppliers, supplies)
16
+ .fi
17
+ .RE
18
+ .SH Description
19
+ .PP
20
+ Computes a relation as a subset of \fB\fCleft\fR tuples for which at least one
21
+ \fB\fCright\fR tuple would join on common attributes.
22
+ .PP
23
+ This operator, also known as semi\-join, can be explained through the
24
+ definition below. As shown, it consists in joining \fB\fCleft\fR and \fB\fCright\fR
25
+ relations and projecting the result back on \fB\fCleft\fR attributes.
26
+ .PP
27
+ .RS
28
+ .nf
29
+ def matching(left, right)
30
+ project(join(left, right), left.attr_list)
31
+ end
32
+ matching(suppliers, supplies)
33
+ .fi
34
+ .RE
35
+ .PP
36
+ Or, in SQL terms:
37
+ .PP
38
+ .RS
39
+ .nf
40
+ SELECT left.* FROM left NATURAL JOIN right
41
+ .fi
42
+ .RE
43
+ .PP
44
+ The synonym 'where exists' comes from the fact that, since right attributes
45
+ are projected away, it may seem more intuitive to think about this operator
46
+ as filtering tuples from left where \fIthere exists\fP some tuple at right that
47
+ \fIwould\fP join. In SQL terms:
48
+ .PP
49
+ .RS
50
+ .nf
51
+ SELECT * FROM left WHERE EXISTS (SELECT * FROM right WHERE [join condition])
52
+ .fi
53
+ .RE
54
+ .SH Implementation notes
55
+ .PP
56
+ As for (natural) \fB\fCjoin\fR, you must take care of ensuring that the list of
57
+ common attributes on which the matching applies corresponds to what you
58
+ want. Renamings and projections are worth having at hand when using
59
+ matching. Alternatively, shortcuts can be considered. A (advanced) example
60
+ below:
61
+ .PP
62
+ .RS
63
+ .nf
64
+ # Same as matching(left, right) except that only attributes in `wish`
65
+ # are take into account in matching.
66
+ def matching_on(left, right, wish)
67
+ matching(left, project(right, wish))
68
+ end
69
+ # observe here how part names have been discarded to avoid matching them
70
+ # with supplier names (empty result guaranteed)
71
+ matching_on(suppliers, parts, [:city])
72
+ .fi
73
+ .RE