Skip to content

Commit 8c5176f

Browse files
authored
feat(iox): add iox.sqlInterval to convert flux durations to SQL interval strings (#5356)
* feat(iox): add iox.sqlInterval to convert flux durations to SQL interval strings * chore(iox): rename and fix iox_sql_interval test * chore(iox): fixed typo
1 parent 69e2736 commit 8c5176f

File tree

4 files changed

+118
-2
lines changed

4 files changed

+118
-2
lines changed

.hugo_build.lock

Whitespace-only changes.

libflux/go/libflux/buildinfo.gen.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ var sourceHashes = map[string]string{
193193
"stdlib/experimental/http/requests/requests.flux": "579f5d578722a425f350db50dc2697a8bce7bcddc3737d094ae96126b6f96c56",
194194
"stdlib/experimental/influxdb/influxdb.flux": "503f68779c9d8a4c307d371cce8071826d0462a00e486190b3dfa681f9b620dc",
195195
"stdlib/experimental/integral_test.flux": "4c9b6c866884839027946e93793689b8b3d328e2e777f8ee2f8973ffd72be036",
196-
"stdlib/experimental/iox/iox.flux": "a543270b0163c0d23b005aa71aa7c1474b691e4845e857a514adab7e537f4621",
196+
"stdlib/experimental/iox/iox.flux": "1e7dc17722b99c26ea455c0eee4047282604ee62c69d44e066a27631d86d36e8",
197+
"stdlib/experimental/iox/iox_test.flux": "04624caf7807128826564e18bafde5ad8033eaf0f8c6edfe0c9300c03c88aac0",
197198
"stdlib/experimental/join_right_side_more_cols_test.flux": "788bd7fe3dc6d324453484bdee64f1e408c291a43ffa3744e930c7ae5e533db7",
198199
"stdlib/experimental/join_test.flux": "a48f78765b34d8011e45e0333cdc10ed578076f9a34443e50c6f7633978ea549",
199200
"stdlib/experimental/json/json.flux": "50479ced0a3ae185164cbecd5f071f849ea30b727385afec8d525ff98c7460be",

stdlib/experimental/iox/iox.flux

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
package iox
66

77

8+
import "regexp"
9+
import "strings"
10+
811
// from reads from the selected bucket and measurement in an IOx storage node.
912
//
1013
// This function creates a source that reads data from IOx. Output data is
@@ -15,6 +18,17 @@ package iox
1518
// - bucket: IOx bucket to read data from.
1619
// - measurement: Measurement to read data from.
1720
//
21+
// ## Examples
22+
//
23+
// ### Use Flux to query data from IOx
24+
// ```no_run
25+
// import "experimental/iox"
26+
//
27+
// iox.from(bucket: "example-bucket", measurement: "example-measurement")
28+
// |> range(start: -1d)
29+
// |> filter(fn: (r) => r._field == "example-field")
30+
// ```
31+
//
1832
// ## Metadata
1933
// tags: inputs
2034
builtin from : (bucket: string, measurement: string) => stream[{A with _time: time}] where A: Record
@@ -25,9 +39,79 @@ builtin from : (bucket: string, measurement: string) => stream[{A with _time: ti
2539
//
2640
// ## Parameters
2741
// - bucket: IOx bucket to read data from.
28-
// - query: Query to execute.
42+
// - query: SQL query to execute.
43+
//
44+
// ## Examples
45+
//
46+
// ### Use SQL to query data from IOx
47+
// ```no_run
48+
// import "experimental/iox"
49+
//
50+
// iox.sql(bucket: "example-bucket", query: "SELECT * FROM measurement")
51+
// ```
2952
//
3053
// ## Metadata
3154
// introduced: 0.186.0
3255
// tags: inputs
3356
builtin sql : (bucket: string, query: string) => stream[A] where A: Record
57+
58+
// sqlInterval converts a duration value to a SQL interval string.
59+
//
60+
// SQL interval strings support down to millisecond precision.
61+
// Any microsecond or nanosecond duration units are dropped from the duration value.
62+
// If the duration only consists of microseconds or nanosecond units,
63+
// `iox.sqlInterval()` returns `1 millisecond`.
64+
// Duration values must be positive to work as a SQL interval string.
65+
//
66+
// ## Parameters
67+
// - d: Duration value to convert to SQL interval string.
68+
//
69+
// ## Examples
70+
//
71+
// ### Convert a duration to a SQL interval
72+
// ```no_run
73+
// import "experimental/iox"
74+
//
75+
// iox.sqlInterval(d: 1y2mo3w4d5h6m7s8ms)
76+
// // Returns 1 years 2 months 3 weeks 4 days 5 hours 6 minutes 7 seconds 8 milliseconds
77+
// ```
78+
//
79+
// ### Use a Flux duration to define a SQL interval
80+
// ```no_run
81+
// import "experimental/iox"
82+
//
83+
// windowInterval = 1d12h
84+
// sqlQuery = "
85+
// SELECT
86+
// DATE_BIN(INTERVAL '${iox.sqlInterval(d: windowInterval)}', time, TIMESTAMP '2023-01-01T00:00:00Z')
87+
// COUNT(field1)
88+
// FROM
89+
// measurement
90+
// GROUP BY
91+
// time
92+
// "
93+
//
94+
// iox.sql(bucket: "example-bucket", query: sqlQuery)
95+
// ```
96+
//
97+
// ## Metadata
98+
// introduced: NEXT
99+
// tags: sql, type-conversions
100+
sqlInterval = (d) => {
101+
_durationString = string(v: d)
102+
_pipeRegex = (v=<-, r, t) => regexp.replaceAllString(v: v, r: r, t: t)
103+
_intervalString =
104+
_pipeRegex(v: _durationString, r: /[\d]+(us|ns)/, t: "")
105+
|> _pipeRegex(r: /([^\d]+)/, t: " $1 ")
106+
|> _pipeRegex(r: / ms /, t: " milliseconds ")
107+
|> _pipeRegex(r: / s /, t: " seconds ")
108+
|> _pipeRegex(r: / m /, t: " minutes ")
109+
|> _pipeRegex(r: / h /, t: " hours ")
110+
|> _pipeRegex(r: / d /, t: " days ")
111+
|> _pipeRegex(r: / w /, t: " weeks ")
112+
|> _pipeRegex(r: / mo /, t: " months ")
113+
|> _pipeRegex(r: / y /, t: " years ")
114+
_output = if _intervalString == "" then "1 millisecond" else _intervalString
115+
116+
return strings.trimSpace(v: _output)
117+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package iox_test
2+
3+
4+
import "array"
5+
import "testing"
6+
import "experimental/iox"
7+
8+
testcase iox_sql_interval_testcase {
9+
got =
10+
array.from(
11+
rows: [
12+
{_value: "12y3mo4w"},
13+
{_value: "12d34h5m"},
14+
{_value: "123s56ms"},
15+
{_value: "123us56ns"},
16+
],
17+
)
18+
|> map(fn: (r) => ({_value: iox.sqlInterval(d: duration(v: r._value))}))
19+
20+
want =
21+
array.from(
22+
rows: [
23+
{_value: "12 years 3 months 4 weeks"},
24+
{_value: "1 weeks 6 days 10 hours 5 minutes"},
25+
{_value: "2 minutes 3 seconds 56 milliseconds"},
26+
{_value: "1 millisecond"},
27+
],
28+
)
29+
30+
testing.diff(got: got, want: want)
31+
}

0 commit comments

Comments
 (0)