Skip to content

Commit

Permalink
Merge #699
Browse files Browse the repository at this point in the history
699: state_agg API tweaks r=Smittyvb a=Smittyvb

- `interpolated_duration_in`/`duration_in`/`interpolated_state_periods`/`state_periods` have the first two arguments swapped: now the aggregate is first and the state is second
- `into_values`/`into_int_values` now returns a table with intervals instead of microseconds

Co-authored-by: Smitty <smitty@timescale.com>
  • Loading branch information
bors[bot] and syvb authored Feb 9, 2023
2 parents cf27d8d + c6fab48 commit f80b630
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 211 deletions.
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ This changelog should be updated as part of a PR if the work is worth noting (mo
- [#692](https://github.com/timescale/timescaledb-toolkit/pull/692): Support specifying a range to `duration_in` to specify a time range to get states in for state aggregates
- [#692](https://github.com/timescale/timescaledb-toolkit/pull/692): Removed `next` parameter from interpolated state aggregate functions
- [#692](https://github.com/timescale/timescaledb-toolkit/pull/692): Renamed `state_agg` to `compact_state_agg` and `timeline_agg` to `state_agg`
- [#699](https://github.com/timescale/timescaledb-toolkit/pull/699): `interpolated_duration_in`/`duration_in`/`interpolated_state_periods`/`state_periods` have the first two arguments swapped: now the aggregate is first and the state is second
- [#699](https://github.com/timescale/timescaledb-toolkit/pull/699): `into_values`/`into_int_values` now returns a table with intervals instead of microseconds

#### Shout-outs

Expand Down
66 changes: 33 additions & 33 deletions docs/state_agg.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ INSERT INTO states_test_5 VALUES
Compute the amount of time spent in a state as INTERVAL.

```SQL
SELECT toolkit_experimental.duration_in('ERROR', toolkit_experimental.compact_state_agg(ts, state)) FROM states_test;
SELECT toolkit_experimental.duration_in(toolkit_experimental.compact_state_agg(ts, state), 'ERROR') FROM states_test;
```
```output
interval
----------
00:00:03
```
```SQL
SELECT toolkit_experimental.duration_in(2, toolkit_experimental.compact_state_agg(ts, state)) FROM states_test_4;
SELECT toolkit_experimental.duration_in(toolkit_experimental.compact_state_agg(ts, state), 2) FROM states_test_4;
```
```output
interval
Expand All @@ -67,7 +67,7 @@ Extract as number of seconds:
```SQL
SELECT
EXTRACT(epoch FROM
toolkit_experimental.duration_in('ERROR', toolkit_experimental.compact_state_agg(ts, state))
toolkit_experimental.duration_in(toolkit_experimental.compact_state_agg(ts, state), 'ERROR')
)::INTEGER
FROM states_test;
```
Expand All @@ -79,39 +79,39 @@ FROM states_test;

#### duration_in for a range
```SQL
SELECT toolkit_experimental.duration_in('OK', toolkit_experimental.state_agg(ts, state), '2020-01-01 00:01:00+00', '2 days') FROM states_test;
SELECT toolkit_experimental.duration_in(toolkit_experimental.state_agg(ts, state), 'OK', '2020-01-01 00:01:00+00', '2 days') FROM states_test;
```
```output
duration_in
-------------
00:00:57
```
```SQL
SELECT toolkit_experimental.duration_in('OK', toolkit_experimental.state_agg(ts, state), '2020-01-01 00:01:00+00', NULL) FROM states_test;
SELECT toolkit_experimental.duration_in(toolkit_experimental.state_agg(ts, state), 'OK', '2020-01-01 00:01:00+00', NULL) FROM states_test;
```
```output
duration_in
-------------
00:00:57
```
```SQL
SELECT toolkit_experimental.duration_in('OK', toolkit_experimental.state_agg(ts, state), '2020-01-01 00:01:00+00') FROM states_test;
SELECT toolkit_experimental.duration_in(toolkit_experimental.state_agg(ts, state), 'OK', '2020-01-01 00:01:00+00') FROM states_test;
```
```output
duration_in
-------------
00:00:57
```
```SQL
SELECT toolkit_experimental.duration_in(51351, toolkit_experimental.state_agg(ts, state), '2020-01-01 00:01:00+00', '2 days') FROM states_test_4;
SELECT toolkit_experimental.duration_in(toolkit_experimental.state_agg(ts, state), 51351, '2020-01-01 00:01:00+00', '2 days') FROM states_test_4;
```
```output
duration_in
-------------
00:00:57
```
```SQL
SELECT toolkit_experimental.duration_in(51351, toolkit_experimental.state_agg(ts, state), '2020-01-01 00:01:00+00', NULL) FROM states_test_4;
SELECT toolkit_experimental.duration_in(toolkit_experimental.state_agg(ts, state), 51351, '2020-01-01 00:01:00+00', NULL) FROM states_test_4;
```
```output
duration_in
Expand All @@ -120,7 +120,7 @@ SELECT toolkit_experimental.duration_in(51351, toolkit_experimental.state_agg(ts
```

```SQL
SELECT toolkit_experimental.duration_in('OK', toolkit_experimental.state_agg(ts, state), '2020-01-01 00:00:15+00', '30 seconds') FROM states_test;
SELECT toolkit_experimental.duration_in(toolkit_experimental.state_agg(ts, state), 'OK', '2020-01-01 00:00:15+00', '30 seconds') FROM states_test;
```
```output
duration_in
Expand All @@ -129,7 +129,7 @@ SELECT toolkit_experimental.duration_in('OK', toolkit_experimental.state_agg(ts,
```

```SQL
SELECT toolkit_experimental.duration_in('OK', toolkit_experimental.state_agg(ts, state), '2020-01-01 00:00:15+00', '1 minute 1 second') FROM states_test;
SELECT toolkit_experimental.duration_in(toolkit_experimental.state_agg(ts, state), 'OK', '2020-01-01 00:00:15+00', '1 minute 1 second') FROM states_test;
```
```output
duration_in
Expand All @@ -147,23 +147,23 @@ SELECT state, duration FROM toolkit_experimental.into_values(
```output
state | duration
-------+-----------
ERROR | 3000000
OK | 106000000
START | 11000000
STOP | 0
ERROR | 00:00:03
OK | 00:01:46
START | 00:00:11
STOP | 00:00:00
```
```SQL
SELECT state, duration FROM toolkit_experimental.into_int_values(
(SELECT toolkit_experimental.compact_state_agg(ts, state) FROM states_test_4))
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test_4))
ORDER BY state, duration;
```
```output
state | duration
-------+-----------
-9 | 0
2 | 3000000
4 | 11000000
51351 | 106000000
-9 | 00:00:00
2 | 00:00:03
4 | 00:00:11
51351 | 00:01:46
```

### state_timeline
Expand Down Expand Up @@ -217,8 +217,8 @@ START | 2019-12-31 00:00:00+00 | 2019-12-31 00:00:11+00
```SQL
SELECT start_time, end_time
FROM toolkit_experimental.state_periods(
'OK',
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test)
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test),
'OK'
)
ORDER BY start_time;
```
Expand All @@ -232,8 +232,8 @@ start_time | end_time
```SQL
SELECT start_time, end_time
FROM toolkit_experimental.state_periods(
51351,
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test_4)
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test_4),
51351
)
ORDER BY start_time;
```
Expand All @@ -247,8 +247,8 @@ start_time | end_time
```SQL
SELECT start_time, end_time
FROM toolkit_experimental.state_periods(
'ANYTHING',
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test)
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test),
'ANYTHING'
)
ORDER BY start_time;
```
Expand Down Expand Up @@ -338,8 +338,8 @@ ERROR | 2020-01-01 00:01:00+00 | 2020-01-01 00:01:03+00

```SQL
SELECT start_time, end_time FROM toolkit_experimental.interpolated_state_periods(
'OK',
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test),
'OK',
'2019-12-31', '1 days',
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test_3)
)
Expand All @@ -354,8 +354,8 @@ start_time | end_time

```SQL
SELECT start_time, end_time FROM toolkit_experimental.interpolated_state_periods(
'START',
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test),
'START',
'2019-12-31', '5 days',
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test_3)
)
Expand All @@ -369,8 +369,8 @@ start_time | end_time

```SQL
SELECT start_time, end_time FROM toolkit_experimental.interpolated_state_periods(
'STOP',
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test),
'STOP',
'2019-12-31', '1 days',
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test_2)
)
Expand All @@ -385,8 +385,8 @@ start_time | end_time

```SQL
SELECT start_time, end_time FROM toolkit_experimental.interpolated_state_periods(
'STOP',
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test),
'STOP',
'2019-12-31', '5 days',
(SELECT toolkit_experimental.state_agg(ts, state) FROM states_test_2)
)
Expand All @@ -408,8 +408,8 @@ WITH buckets AS (SELECT
FROM states_test
GROUP BY date_trunc('minute', ts))
SELECT toolkit_experimental.duration_in(
'START',
toolkit_experimental.rollup(buckets.sa)
toolkit_experimental.rollup(buckets.sa),
'START'
)
FROM buckets;
```
Expand All @@ -426,8 +426,8 @@ WITH buckets AS (SELECT
FROM states_test
GROUP BY date_trunc('minute', ts))
SELECT toolkit_experimental.duration_in(
'OK',
toolkit_experimental.rollup(buckets.sa)
toolkit_experimental.rollup(buckets.sa),
'OK'
)
FROM buckets;
```
Expand Down
19 changes: 17 additions & 2 deletions extension/src/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,27 @@ impl From<i64> for Interval {
time: interval,
..Default::default()
};
unsafe {
let interval = unsafe {
let ptr =
pg_sys::palloc(std::mem::size_of::<pg_sys::Interval>()) as *mut pg_sys::Interval;
*ptr = interval;
Interval(pg_sys::Datum::from(ptr))
}
};
// Now we have a valid Interval in at least one sense. But we have the
// microseconds in the `time` field and `day` and `month` are both 0,
// which is legal. However, directly converting one of these to TEXT
// comes out quite ugly if the number of microseconds is greater than 1 day:
// 8760:02:00
// Should be:
// 365 days 00:02:00
// How does postgresql do it? It happens in src/backend/utils/adt/timestamp.c:timestamp_mi:
// result->time = dt1 - dt2;
// result = DatumGetIntervalP(DirectFunctionCall1(interval_justify_hours,
// IntervalPGetDatum(result)));
// So if we want the same behavior, we need to call interval_justify_hours too:
let function_args = vec![Some(pg_sys::Datum::from(interval))];
unsafe { pgx::direct_function_call(pg_sys::interval_justify_hours, function_args) }
.expect("interval_justify_hours does not return None")
}
}

Expand Down
Loading

0 comments on commit f80b630

Please sign in to comment.