Skip to content

Conversation

@tjgreen42
Copy link
Contributor

@tjgreen42 tjgreen42 commented Jan 14, 2026

Summary

Adds offset and origin parameters to time_bucket_gapfill() using named parameters with defaults.

Fixes #1304

Function Signatures

All existing parameters remain in place. New optional parameters are added at the end with NULL defaults.

Integer Variants (5 args)

time_bucket_gapfill(
    bucket_width SMALLINT,
    ts SMALLINT,
    start SMALLINT = NULL,
    finish SMALLINT = NULL,
    "offset" SMALLINT = NULL
) RETURNS SMALLINT

-- Same pattern for INT and BIGINT

Timestamp Variants (6 args)

time_bucket_gapfill(
    bucket_width INTERVAL,
    ts TIMESTAMPTZ,
    start TIMESTAMPTZ = NULL,
    finish TIMESTAMPTZ = NULL,
    origin TIMESTAMPTZ = NULL,
    "offset" INTERVAL = NULL
) RETURNS TIMESTAMPTZ

-- Same pattern for DATE and TIMESTAMP

Timezone Variant (7 args)

time_bucket_gapfill(
    bucket_width INTERVAL,
    ts TIMESTAMPTZ,
    timezone TEXT,
    start TIMESTAMPTZ = NULL,
    finish TIMESTAMPTZ = NULL,
    origin TIMESTAMPTZ = NULL,
    "offset" INTERVAL = NULL
) RETURNS TIMESTAMPTZ

Examples

Offset: Business Day at 6 AM

SELECT time_bucket_gapfill('1 day'::interval, sale_time,
           start => '2024-01-01 06:00'::timestamptz,
           finish => '2024-01-10 06:00'::timestamptz,
           "offset" => '6 hours'::interval) AS business_day,
       coalesce(sum(amount), 0) AS total
FROM sales
GROUP BY 1 ORDER BY 1;

Origin: Fiscal Months Starting April 1st

SELECT time_bucket_gapfill('1 month'::interval, event_time,
           start => '2024-01-01'::timestamptz,
           finish => '2024-12-01'::timestamptz,
           origin => '2024-04-01'::timestamptz) AS fiscal_month,
       count(*) AS events
FROM events
GROUP BY 1 ORDER BY 1;

Timezone with Offset

SELECT time_bucket_gapfill('1 day'::interval, event_time,
           'America/New_York',
           start => '2024-01-01'::timestamptz,
           finish => '2024-01-05'::timestamptz,
           "offset" => '6 hours'::interval) AS day,
       count(*)
FROM events
GROUP BY 1 ORDER BY 1;

Constraints

  • offset and origin are mutually exclusive (same as time_bucket)
  • All existing function calls remain unchanged (full backward compatibility)

Testing

  • Added tests for offset/origin variants in tsl/test/shared/sql/gapfill.sql.in
  • Verified all variants work correctly with locf() and interpolate()

Disable-check: commit-count

@tjgreen42 tjgreen42 force-pushed the feat/gapfill-offset-origin branch 5 times, most recently from a26a3c4 to 69ffd96 Compare January 14, 2026 02:58
@codecov
Copy link

codecov bot commented Jan 14, 2026

Codecov Report

❌ Patch coverage is 42.37288% with 68 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.14%. Comparing base (1236a1a) to head (8f5bcaf).

Files with missing lines Patch % Lines
tsl/src/nodes/gapfill/gapfill_exec.c 54.21% 35 Missing and 3 partials ⚠️
tsl/src/nodes/gapfill/gapfill_functions.c 0.00% 19 Missing and 6 partials ⚠️
src/func_cache.c 28.57% 1 Missing and 4 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9123      +/-   ##
==========================================
- Coverage   82.42%   82.14%   -0.29%     
==========================================
  Files         243      243              
  Lines       47911    46914     -997     
  Branches    12228    12241      +13     
==========================================
- Hits        39492    38536     -956     
- Misses       3550     3564      +14     
+ Partials     4869     4814      -55     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tjgreen42 tjgreen42 force-pushed the feat/gapfill-offset-origin branch 5 times, most recently from 54038c3 to 7c07eec Compare January 14, 2026 18:51
…amed parameters

This implements offset and origin support for time_bucket_gapfill() using
named parameters with defaults, following the same pattern as time_bucket().

Changes:
- Updated SQL function signatures to include optional origin and offset parameters
- Integer variants: 5 args (bucket_width, ts, start, finish, offset)
- Timestamp variants: 6 args (bucket_width, ts, start, finish, origin, offset)
- Timezone variant: 7 args (bucket_width, ts, timezone, start, finish, origin, offset)
- Updated C wrapper functions to pass origin/offset to underlying time_bucket
- Updated func_cache.c with new function signatures
- Added tests for all new parameter combinations
- origin and offset are mutually exclusive - specifying both raises an error

Fixes #1304
@tjgreen42 tjgreen42 force-pushed the feat/gapfill-offset-origin branch from ec12969 to fe69d32 Compare January 14, 2026 22:57
- Apply clang-format to func_cache.c
- Update extension.out expected output for new time_bucket_gapfill signatures
- Add CHANGELOG entry for issue #1304
The assertion incorrectly expected 4 or 5 arguments, but with the new
offset/origin parameters, the function now has 5, 6, or 7 arguments:
- 5 args: integer variants
- 6 args: timestamp variants (with origin and offset)
- 7 args: timezone variant (with origin and offset)

Also update the timezone check to look for 7 args instead of 5.
The EXPLAIN output now shows the expanded function call with the
new optional origin and offset parameters (as NULLs when not specified).
Adds expected test output for the new offset and origin parameter
tests in time_bucket_gapfill.
Keep both old 4/5-arg functions and add new 5/6/7-arg functions
for offset/origin support. This ensures backward compatibility
with existing code while adding the new feature.

- Old 4-arg functions (bucket_width, ts, start, finish) preserved
- New functions add offset parameter for integers (5 args)
- New functions add origin and offset for timestamps (6 args)
- New functions add origin and offset for timezone variant (7 args)
- C code handles both old and new argument counts via PG_NARGS()
- func_cache.c updated to handle all argument count variants
The get_origin_arg and get_offset_arg functions didn't handle the old
4-argument case, causing a list access out of bounds error. This fix
adds proper handling for 4-arg variants by returning NULL for origin
and offset.

Also fixes have_timezone detection to distinguish between old 5-arg
timezone variant and new 5-arg integer-with-offset by checking the
type of the third argument.
Add the new time_bucket_gapfill variants with offset and origin
parameters to latest-dev.sql so they are created during upgrade.

Add DROP statements to reverse-dev.sql so the functions are removed
during downgrade to maintain schema compatibility.
@tjgreen42 tjgreen42 force-pushed the feat/gapfill-offset-origin branch 2 times, most recently from 6f8d85a to ee4cb11 Compare January 15, 2026 05:51
The func_cache needs entries for both old 4-arg and new 5/6/7-arg
gapfill variants for the sort transform optimization to work.
Without these entries, the planner cannot use indexed scans
for queries using the old gapfill function signatures.
@tjgreen42 tjgreen42 force-pushed the feat/gapfill-offset-origin branch from ee4cb11 to f384eaf Compare January 15, 2026 06:04
The 5-arg integer functions with offset conflicted with the
5-arg timezone variant during PostgreSQL function resolution
when arguments were passed as untyped literals.

Integer variants now stay at 4 args (bucket_width, ts, start, finish)
without offset support. Timestamp and timezone variants keep their
origin/offset parameters (6 and 7 args respectively).

This maintains backward compatibility while avoiding the function
resolution ambiguity error.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add offset and origin options to time_bucket_gapfill

2 participants