questdb / questdb/questdb

Support numeric scalar subqueries in BETWEEN predicates

Open
#7,407 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

New feature SQL
Dominant language
Java
Stars
17.3k
Forks
1.6k
Avg merge
5d 10h
Merged PRs (30d)
28

Description

Problem

QuestDB supports comparisons between numeric expressions and scalar subqueries since #7377, including the derived <=, >=, !=, and <> forms. BETWEEN does not provide the equivalent numeric scalar-subquery support.

PR #7388 adds scalar-subquery BETWEEN syntax and implements timestamp bounds. On that branch, the numeric form reaches generic function resolution but has no matching overload:

CREATE TABLE trades (price DOUBLE);
INSERT INTO trades VALUES (10.0), (20.0), (30.0);

CREATE TABLE limits (min_price DOUBLE, max_price DOUBLE);
INSERT INTO limits VALUES (15.0, 25.0);

SELECT price
FROM trades
WHERE price BETWEEN (SELECT min_price FROM limits)
                AND (SELECT max_price FROM limits);

Actual result on #7388:

[37] there is no matching operator `between` with the argument type: DOUBLE

Expected result:

price
20.0

Requested behavior

Support numeric expressions with scalar-subquery bounds in all three forms:

value BETWEEN (SELECT lo) AND hi
value BETWEEN lo AND (SELECT hi)
value BETWEEN (SELECT lo) AND (SELECT hi)

The feature should cover the numeric families already supported by #7377 (DOUBLE, FLOAT, LONG, INT, SHORT, and BYTE) and preserve existing numeric BETWEEN behavior:

  • evaluate each scalar subquery once per query execution;
  • zero rows or a NULL bound produce no match;
  • more than one row raises scalar sub-query returned more than one row at the offending bound;
  • reject multi-column and non-numeric scalar results at the offending bound;
  • avoid narrowing integer values through double, including values beyond 2^53;
  • preserve inclusive and reversed-bound semantics;
  • close cursor resources on success and all error paths;
  • work in filters, projections, and CASE expressions.

Tests should cover mixed and dual subquery bounds, numeric-width combinations, NULL/empty/multi-row results, reversed bounds, large integers, error positions, query reinitialization, parallel filtering, and resource cleanup.

Workaround

For non-NULL bounds already ordered from low to high, the equivalent comparisons work after #7377:

WHERE price >= (SELECT min_price FROM limits)
  AND price <= (SELECT max_price FROM limits)

This is not a full replacement because QuestDB's BETWEEN also tolerates reversed bounds.

Related work

  • #7377 added numeric scalar-subquery comparisons.
  • #7388 adds scalar-subquery BETWEEN parsing and timestamp-bound support.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Compare the numeric scalar-subquery comparison support from #7377 with the scalar-subquery BETWEEN implementation and timestamp-bound support from #7388. Trace generic function resolution for BETWEEN, then cover the requested numeric-bound cases and edge conditions with tests. Done means all three bound forms work without changing existing numeric or reversed-bound semantics, and resources are cleaned up on success and errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, sql
Domain
database
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.