Skip to content

feat: [GH-74] Temporal-range key-bracket binding (foo[t1...t2])#77

Open
javierlores wants to merge 1 commit into
developfrom
feature/GH-74
Open

feat: [GH-74] Temporal-range key-bracket binding (foo[t1...t2])#77
javierlores wants to merge 1 commit into
developfrom
feature/GH-74

Conversation

@javierlores

Copy link
Copy Markdown
Contributor

Closes #74.

What

Extends the leaf key-bracket grammar so a key can bind to a half-open temporal interval [start, end) instead of a single instant, using the ... range separator. Three forms are supported on flat leaf keys:

Form Meaning
foo[t1...t2] closed range [t1, t2) (start-inclusive, end-exclusive)
foo[...t2] open start — bounded on the end (exclusive)
foo[t1...] open end — bounded on the start (inclusive)

This is grammar / AST / parse only. It defines the syntax, the AST node, and the canonical re-parseable string form. It does not decide what a range read returns — server-side evaluation (and the present-during vs. asserted-during choice) is a separate concourse change.

How

  • Refactored BracketedTimestamp() into a raw-string KeyBracketParameter() and centralized single-instant vs. range interpretation in Parsing.applyKeyBracket, leaving the single-instant and navigation-stop paths unchanged.
  • New TemporalRangeKeySymbol (sibling to TemporalKeySymbol): wraps a key plus optional start/end TimestampSymbols; rejects navigation and already-parameterized keys; requires at least one endpoint; rejects backwards ranges (start > end). isParameterized() is true, so writes and audit/chronicle/diff reject range bindings for free via the existing requireNotParameterized guard.
  • The canonical toString() renders both endpoints as resolved microseconds (key[<m1>...<m2>]), making it a re-parseable cross-repo contract.

Parse-time validation

  • foo[...] (both endpoints omitted) → rejected.
  • foo[t2...t1] with t2 > t1 → rejected.
  • foo[t1][t2...t3] (double bracket) → rejected.
  • foo[t1...t2...t3] (more than one separator) → rejected. Separator detection is quote-aware, so a quoted phrase that itself contains ... is treated as a single endpoint rather than mis-split.

Tests

  • Matrix (BracketTimestampMatrixTest): closed / open-start / open-end, quoted-date and natural-language endpoints, round-trip of resolved endpoints, and all rejection cases (fully-open, backwards, double-bracket, multiple-separator).
  • Node (TemporalRangeKeySymbolTest): constructor guards, accessors, equals/hashCode, all three toString() shapes.
  • Command (BracketTimestampCommandTest): range accepted on select/get/find; rejected on add and audit.

All parse-path and node tests pass locally, plus the existing GrammarTest / JavaCCParserTest / CompilerJavaCCTest suites (no regression). The parser regenerates cleanly from grammar.jjt.

Scope / follow-ups

  • Out of scope: range bindings on navigation stops (a[t1...t2].b) and scope prefixes; server-side evaluation.
  • Cross-repo dependency: concourse pins ccl 4.0.0. This must ship in a ccl release, after which concourse bumps its ccl pin before the matching range-evaluation change (cinchapi/concourse#789) can land — that change must teach Keys.parse to re-parse the canonical range toString() produced here.

Part of the connector data-sync locking initiative (cinchapi-server). Sibling grammar work: #75.

Extend the leaf key-bracket grammar so a key can bind to a half-open
temporal interval [start, end) instead of a single instant, using the
`...` range separator. Three forms are supported on flat leaf keys:

  foo[t1...t2]   closed range  [t1, t2)
  foo[...t2]     open start    (bounded on the end, exclusive)
  foo[t1...]     open end      (bounded on the start, inclusive)

Grammar/AST/parse only; server-side evaluation of a range read is a
separate concourse change. The canonical toString() renders both
endpoints as resolved microseconds, making it a re-parseable cross-repo
contract.

- Refactor BracketedTimestamp() into a raw-string KeyBracketParameter()
  and centralize single-instant vs. range interpretation in
  Parsing.applyKeyBracket, leaving the single-instant and navigation
  paths unchanged.
- Add TemporalRangeKeySymbol (sibling to TemporalKeySymbol): wraps a key
  plus optional start/end TimestampSymbols, rejects navigation and
  already-parameterized keys, requires at least one endpoint, and
  rejects backwards ranges (start > end).
- Parse-time validation: reject fully-open foo[...], backwards ranges,
  double brackets, and content with more than one `...` separator
  (quote-aware so a quoted phrase containing `...` is not mis-split).
- Range bindings reject on writes and audit/chronicle/diff for free via
  the existing requireNotParameterized guard.
- Tests: matrix (closed/open/quoted/natural-language/round-trip and all
  rejection cases), node unit tests, and command acceptance/rejection.
- Update CCL_REFERENCE.md section 8.4.

Range bindings on navigation stops and scope prefixes remain out of
scope. Part of the connector data-sync locking initiative; concourse
must bump its ccl pin before the matching range-evaluation change lands.
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.

Temporal range key-bracket binding: foo[t1...t2], foo[...t2], foo[t1...] (grammar/AST/parse only)

1 participant