Skip to content

Commit 2ffba9f

Browse files
committed
remove old "foreach" syntax and update documentation
1 parent f95146d commit 2ffba9f

File tree

5 files changed

+185
-306
lines changed

5 files changed

+185
-306
lines changed

doc/antora/modules/howto/pages/installation/upgrade.adoc

Lines changed: 61 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -304,40 +304,6 @@ here is to allow a common pre-processing of accounting packets in the
304304
in `accounting %{Acct-Status-Type}`. See sites-available/default for
305305
examples and more information.
306306

307-
=== update sections
308-
309-
A major difference between v3 and v4 is that `update` sections are no
310-
longer necessary. It is now possible to just edit attributes "in
311-
place", as with:
312-
313-
See the xref:reference:unlang/update.adoc[update] documentation for a
314-
description of what has changed, and how to use the attribute new
315-
xref:reference:unlang/edit.adoc[edit] functionality.
316-
317-
For example, instead of doing this:
318-
319-
[source,unlang]
320-
----
321-
if (User-Name == "bob") {
322-
update reply {
323-
Reply-Message := "Hello, %{User-Name}"
324-
}
325-
}
326-
----
327-
328-
You can now do this:
329-
330-
[source,unlang]
331-
----
332-
if (User-Name == "bob") {
333-
reply.Reply-Message := "Hello, %{User-Name}"
334-
}
335-
----
336-
337-
As with any upgrade across major version numbers, there are caveats.
338-
See the full xref:reference:unlang/update.adoc[update] documentation
339-
and xref:reference:unlang/edit.adoc[edit] documentation for details.
340-
341307
== Proxying
342308

343309
Proxying has undergone massive changes. The `proxy.conf` file no
@@ -589,14 +555,6 @@ Many lists have been removed. e.g._`proxy`, `proxy-reply`, `coa`,
589555
functionality still exists, but it has been moved to different
590556
keywords, such as `subrequest`.
591557

592-
== Update sections
593-
594-
The `update` sections are deprecated. See the new way to
595-
xref:reference:unlang/edit.adoc[edit attributes].
596-
597-
The server has limited support for "auto-conversion" of `update`
598-
sections to the new syntax.
599-
600558
=== Recommendations
601559

602560
We recommend manually converting the `update` sections to the new
@@ -701,6 +659,67 @@ Many new xref:reference:unlang/index.adoc[unlang] keywords have been added.
701659

702660
Data type casts have changed from `<ipaddr> ...` to `(ipaddr) ...`
703661

662+
== Keyword Changes
663+
664+
=== foreach
665+
666+
The xref:reference:unlang/foreach.adoc[foreach] keyword has changed syntax.
667+
668+
Instead of
669+
670+
----
671+
foreach &reply.Filter-Id {
672+
if ("%{Foreach-Variable-0}" == ...) {
673+
}
674+
----
675+
676+
You can define a xref:reference:unlang/local.adoc[local variable] via
677+
the following syntax:
678+
679+
----
680+
foreach thing (reply.Filter-Id[*]) {
681+
if (thing == ...) {
682+
}
683+
----
684+
685+
The result is much simpler and clearer.
686+
687+
=== update
688+
689+
The `update` sections are deprecated. The new way to
690+
xref:reference:unlang/edit.adoc[edit] is much simpler.
691+
See the xref:reference:unlang/update.adoc[update] documentation for a
692+
description of what has changed, and how to use the attribute new
693+
xref:reference:unlang/edit.adoc[edit] functionality.
694+
695+
The server has limited support for "auto-conversion" of `update`
696+
sections to the new syntax. Documentation is TBD.
697+
698+
It is now possible to just edit attributes "in place". For example,
699+
instead of doing this:
700+
701+
[source,unlang]
702+
----
703+
if (User-Name == "bob") {
704+
update reply {
705+
Reply-Message := "Hello, %{User-Name}"
706+
}
707+
}
708+
----
709+
710+
You can now do this:
711+
712+
[source,unlang]
713+
----
714+
if (User-Name == "bob") {
715+
reply.Reply-Message := "Hello, %{User-Name}"
716+
}
717+
----
718+
719+
As with any upgrade across major version numbers, there are caveats.
720+
See the full xref:reference:unlang/update.adoc[update] documentation
721+
for further information.
722+
704723
== Xlat expansions
705724

706725
xref:reference:xlat/index.adoc[xlat] expansions have been changed from syntax like `%{md5:...}` to `%md5(...)`.

doc/antora/modules/reference/pages/unlang/foreach.adoc

Lines changed: 87 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,61 +8,94 @@ foreach [<key-type> <key-name>,] [<value-type>] <value-name> (<reference>) {
88
}
99
----
1010

11-
The `foreach` statement loops over a set of attributes as given by
12-
`<attribute-reference>`. The loop can be exited early by using the
11+
The `foreach` statement loops over values given in `<reference>`.
12+
Each value is assigned to the given loop variable. If the loop is
13+
done over attributes, it is also possible to get a reference to the
14+
current attribute, either as a string reference, or an integer index.
15+
16+
The loop can be exited early by using the
1317
xref:unlang/break.adoc[break] keyword.
1418

1519
There is no limit to how many `foreach` statements can be nested.
1620

1721
<key-type>::
1822

19-
In conjunction with `<key-name>`, an optional data type for the key or index variable. The data type should be numeric (e.g. `uint32`) for a `<reference>` which is a dynamic expansion. The data type should be `string` for a `<reference>` which is an attribute reference.
23+
The `<key-type>` and `<key-name>` fields are optional. But if used,
24+
both must be specified.
25+
26+
The `<key-type>` is the data type for the key or index variable. The data type can be numeric (e.g. `uint32`) for a `<reference>` which is a dynamic expansion or attribute reference. The data type can be `string` for an attribute reference.
2027

2128
<key-name>::
2229

23-
The name of the local variable which is used as the name of key when iterating over the attributes.
30+
The local variable where the key refereence is placed.
2431

25-
For numerical data types, the key value starts off at zero (0), and increases by one every round through the loop. For `string` data types the key value is the full path to the current attribute.
32+
For numerical data types, the key value starts off at zero (0), and
33+
increases by one every round through the loop. For `string` data
34+
types the key value is the full path to the current attribute.
2635

2736
The `<key-type>` and `<key-name>` are optional, and can be omitted.
2837

38+
A `<key-name>` must not be an `unlang` keyword, a module name, or
39+
the name of an existing attribute.
40+
2941
<value-type>::
3042

31-
An optional data type for the `<value-name>` local variable. When looping over attributes, the data type can be omitted. The data type of the local variable is then taken from the attribute reference.
43+
An optional data type for the `<value-name>` local variable. It must be a 'leaf' data type like `uint32`, or `string`, or `ipv4addr`. Structural data types like `group` or `tlv` are not allowed.
44+
45+
When looping over attributes, the `<value-type>` can be omitted. The
46+
data type of the local variable is then taken automatically from the
47+
attribute reference.
48+
49+
When looping over data returned from a dynamic expansion, the
50+
`<value-type>` can sometimes be determined from the expansion.
51+
e.g. `%range(...)` returns a `uint32`. However, if the `<value-type>`
52+
cannot be automatically determined, then an error will be produced.
53+
54+
If the `<value-type>` is specified, it has to be compatible with the
55+
data type produced by the `<reference>`. That is, the data types can
56+
be different, but it must be possible to cast one data type to another.
3257

3358
<value-name>::
3459

35-
The name of the local variable which is used as the name of value when iterating over the attributes.
60+
The name of the local variable which is used to store the current value when iterating over the attributes.
3661

37-
The local variable is created automatically when the `foreach` loop is entered, and is deleted automatically when the `foreach` loop exits.
62+
The local variable is created automatically when the `foreach` loop is
63+
entered, and is deleted automatically when the `foreach` loop exits.
3864

39-
The `<value-name>` can be modified during the course of the `foreach` loop. Modifications to the variable are copied back to the referenced attribute when the loop is done. See below for an example.
65+
The `<value-name>` can be modified during the course of the `foreach`
66+
loop. Modifications to the variable do not result in immediate
67+
changes being made to any attribute being looped over. Instead, the
68+
value is copied back to the attribute at the end of each loop
69+
iteration.
4070

41-
The only limitation on the `<value-name>` is that it must be unique.
71+
A `<value-name>` must not be an `unlang` keyword, a module name, or
72+
the name of an existing attribute. A `<value-name>` can be reused in
73+
different sections.
4274

4375
<reference>::
4476

4577
An xref:unlang/attr.adoc[attribute reference] which will will be looped
4678
over. The reference can be to one attribute, to an array, a child, or
4779
be a subset of attributes.
4880

49-
Alternatively, the `<reference>` can be a xref:reference:xlat/index.adoc[dynamic expansion function],
50-
such as `%sql("SELECT ...")`. When the reference is a dynamic
51-
expansion function, a `<value-type>` must be specified.
81+
Alternatively, the `<reference>` can be a
82+
xref:reference:xlat/index.adoc[dynamic expansion function], such as
83+
`%sql("SELECT ...")`. When the reference is a dynamic expansion
84+
function, a `<value-type>` usually needs to be specified.
5285

53-
== Modifying Loop variables
86+
There is currently no way to assign _sets_ of results to a value.
87+
That is, an SQL query can return a list of strings or IP addresses,
88+
but it cannot return a series of rows, each of which contains a number
89+
of columns.
5490

55-
When the `<reference>` is an attribute, the attribute being looped
56-
over can sometimes be modified. When the `<reference>` is a dynamic
57-
expansion, the results cannot be modified, and are discarded when the
58-
`foreach` loop is finished. If it is necessary to save the results,
59-
they should be placed into another attribute.
91+
== Attributes Being Looped over
6092

61-
An attribute which is a "leaf" data type (e.g. `uint32`, and not
62-
`tlv`) will be automatically copied back to the original attribute at
63-
the end of each iteration of the `foreach` loop. That is, the
64-
original attribute will still exist, and will be unmodified, during
65-
the execution of the loop.
93+
While it is technically possible to modify the attributes being looped
94+
over, any modifications are over-written at the end of each loop.
95+
96+
Instead, any modifications should be done to the loop variable.
97+
98+
It is not possible to delete the attributes being looped over.
6699

67100
.Example of modifying values
68101
[source,unlang]
@@ -74,7 +107,8 @@ foreach self (Tmp-Integer-0) {
74107
}
75108
----
76109

77-
Once the loop has finished , the `Tmp-Integer-0` attribute will have the following set of values.
110+
Once the loop has finished , the `Tmp-Integer-0` attribute will have
111+
the following set of values.
78112

79113
[source,unlang]
80114
----
@@ -84,19 +118,28 @@ Tmp-Integer-0 := { 20, 22, 24, 30 }
84118
.Pseudocode for variable modification
85119
----
86120
loop over each i in attribute[0..n]
87-
copy attribute[i] to the key variable, or cast the attribute to the destination type
121+
copy / cast attribute[i] to <value-name>
88122
89123
run loop body
90124
91-
if data type of attribute matches the data type of the key
92-
copy the key variable back to attribute[i]
125+
copy / cast <value-name> back to attribute[i]
93126
----
94127

95128
=== Keys
96129

97-
Using a key variable allows the loop to determine exactly which attribute is being modified. Or for dynamic expansions, which of `0..n` values are being examined.
130+
Using a key variable allows the loop to determine exactly which
131+
attribute is being modified. Or else, which of `0..n` values are
132+
being examined.
133+
134+
For attributes, the `<key-type>` must be `string` or `uint32`. When
135+
the `string` data type is used, a reference to the attribute is placed
136+
into the string value. e.g. `reply.Reply-Message[3]` When the
137+
`uint32` data type is used, the index to the current loop iteration is
138+
placed into the value, e.g. `3`.
98139

99-
For attributes, the `<key-type>` must be `string` or `uint32`. For dynamic expansions, it must be a numerical type such as `uint32`.
140+
For dynamic expansions, The `<key-type> must be a numerical type such
141+
as `uint32`. The index to the current loop iteration is placed into
142+
the value at the beginning of each loop iteration.
100143

101144
.Key variable with attribute reference
102145
[source,unlang]
@@ -108,7 +151,7 @@ foreach string ref, uint32 self (Tmp-Integer-0) {
108151
total += ref
109152
total += " = "
110153
total += (string) self
111-
ttoal += ", "
154+
total += ", "
112155
}
113156
----
114157

@@ -130,7 +173,9 @@ foreach uint32 index, uint32 self (Tmp-Integer-0) {
130173
----
131174

132175

133-
A dynamic expansion can use a keyed index. If the `SELECT` statement below returns a list of `"a", "b", "c", "d"`. then we have the following example:
176+
A dynamic expansion can use a keyed index. If the `SELECT` statement
177+
below returns a list of `"a", "b", "c", "d"`. then we have the
178+
following example:
134179

135180
.Key variable with expansion
136181
[source,unlang]
@@ -153,9 +198,14 @@ When the loop is finished, the `total` variable will have the following value:
153198

154199
=== Structural Data Types
155200

156-
It is possible to loop over the children of a structural data type, as given in the example below. Since the loop is over the child (i.e. leaf) attributes, the values are copied back.
201+
It is possible to loop over the children of a structural data type, as
202+
given in the example below. Since the loop is over the child
203+
(i.e. leaf) attributes, the values are copied back as described above.
157204

158-
In this example, we have to explicitly give a data type `string`. The data type is needed because there may be multiple children of the `TLV-Thing` attribute, and the children may not all have the same data type.
205+
In this example, we have to explicitly give a data type of `string`. The
206+
data type is needed because there may be multiple children of the
207+
`TLV-Thing` attribute, and the children may not all have the same data
208+
type.
159209

160210
.Example of Looping over children of a structural type.
161211
[source,unlang]
@@ -166,9 +216,9 @@ foreach string child (TLV-Thing.[*]) {
166216
}
167217
----
168218

169-
170-
When using `foreach` to loop over multiple structural data types, the values can be
171-
examined, but cannot be changed. This is a limitation of the current interpreter, and may be changed in the future.
219+
When using `foreach` to loop over differnet data types, the values can
220+
be examined, but cannot be changed. This is a limitation of the
221+
current interpreter, and may be changed in the future.
172222

173223
.Example of Looping over children of a structural type.
174224
[source,unlang]

src/lib/unlang/base.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ static int _unlang_global_init(UNUSED void *uctx)
107107
*/
108108
unlang_compile_init(unlang_ctx);
109109
unlang_condition_init();
110-
unlang_foreach_init(unlang_ctx);
110+
unlang_foreach_init();
111111
unlang_function_init();
112112
unlang_group_init();
113113
unlang_load_balance_init();

0 commit comments

Comments
 (0)