Hi Julian, all,
Per your request, here are the requirements spelled out, followed by string-in 
→ SQL-out tests.
Language X = a tiny ACBP DSL for model definitions (equivalent to a JSON form).
Translator is stateless: (model, options, dialect) → SELECT/CASE. No separate 
runtime query language.
Requirements (ACBP → Calcite)
Contract

  *   Input: ACBP model (DSL or JSON), an entry point name, and options.
  *   Output: One deterministic SELECT ... CASE ... END AS action_id string.
  *   Determinism: Same inputs produce identical SQL.

Scope (what the SELECT may contain)

  *   Predicates: =, <>, >=, AND/OR/NOT, IN (...), BETWEEN, parentheses.
  *   Subqueries: IN (SELECT ...), EXISTS (SELECT ...)
  *   Literals: strings, integers. No UDFs in the core examples.
  *   Time window: last N days via options.windowDays; rendered per dialect.
  *   Joins: kept out of these minimal examples (staging happens upstream). 
Ref-table membership uses IN (SELECT ...) or EXISTS.

Semantics (governance & decision)

  *   Categories: finite enums enum('A','B',...) or enum(select code from 
ref_...). Used for coverage/soundness/dedup proofs; affect SQL only when 
referenced in predicates.
  *   Flags: named boolean predicates over columns/categories/ref tables.
  *   Decision: ordered rules; first-match-wins; exactly one integer action_id; 
a default is required.
  *   NULLs: models use explicit IS NULL/IS NOT NULL when needed (kept out of 
these minimal tests).

Dialects Targeted (Initial)

  *   PostgreSQL 16+: now() - interval 'N days'
  *   BigQuery StdSQL: TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL N DAY)
  *   ClickHouse: now() - INTERVAL N DAY
  *   Only the SELECT is in scope here; CTAS/REPLACE is templated outside 
Calcite.

Verification

  *   Compare expected vs actual via a simple normalize (collapse whitespace + 
lowercase),
  *   or parse both to SqlNode and compare trees if you prefer.

Sample Tests (Simple → Moderate), Plus Table-Driven Variant
Test A (Simple) — PostgreSQL (Inline Categories + Flags)

Input (ACBP DSL):
model hl7_v1 {
from hl7_messages
time_column event_ts
category message_type  := enum('ADT','ORM','ORU')
category trigger_event := enum('A01','A04','A03','O01','R01')
category patient_class := enum('E','I','O')
flag is_admission := message_type = 'ADT' and trigger_event in ('A01','A04')
flag is_emergency := patient_class = 'E'
decision action_id {
when is_admission and is_emergency -> 2
else -> 1
}
}

Options:
windowDays = 2
dialect = PostgresqlSqlDialect.DEFAULT
entryPoint = "decision_space_hl7"

Expected SQL (PostgreSQL):
SELECT
msg_id,
event_ts,
CASE
WHEN (message_type = 'ADT' AND trigger_event IN ('A01','A04') AND patient_class 
= 'E') THEN 2
ELSE 1
END AS action_id
FROM hl7_messages
WHERE event_ts >= now() - interval '2 days';
Test B (Moderate) — BigQuery (Inline Categories + Ref-Table Membership Flag)

Input (ACBP DSL):
model hl7_v1 {
from hl7_messages
time_column event_ts
category message_type := enum('ADT','ORM','ORU')
category obs_abn_flag := enum('H','L','N')
ref critical_loinc := "ref_critical_loinc"
flag abnormal_result  := message_type = 'ORU' and obs_abn_flag in ('H','L')
flag critical_analyte := loinc_code in (select code from ref_critical_loinc)
decision action_id {
when abnormal_result and critical_analyte -> 3
when abnormal_result -> 2
else -> 1
}
}

Options:
windowDays = 2
dialect = BigQuerySqlDialect.DEFAULT
entryPoint = "decision_space_hl7"

Expected SQL (BigQuery):
SELECT
msg_id,
event_ts,
CASE
WHEN (message_type = 'ORU' AND obs_abn_flag IN ('H','L')
AND loinc_code IN (SELECT code FROM ref_critical_loinc)) THEN 3
WHEN (message_type = 'ORU' AND obs_abn_flag IN ('H','L')) THEN 2
ELSE 1
END AS action_id
FROM hl7_messages
WHERE event_ts >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 2 DAY);

Test C (Moderate) — ClickHouse (Inline Categories + STAT)

Input (ACBP DSL):
model hl7_v1 {
from hl7_messages
time_column event_ts
category message_type  := enum('ADT','ORM','ORU')
category order_priority := enum('STAT','ROUTINE')
category obs_abn_flag := enum('H','L','N')
flag is_stat_order   := message_type = 'ORM' and order_priority = 'STAT'
flag abnormal_result := obs_abn_flag in ('H','L')
decision action_id {
when is_stat_order and abnormal_result -> 3
when is_stat_order -> 2
else -> 1
}
}

Options:
windowDays = 2
dialect = ClickHouseSqlDialect.DEFAULT
entryPoint = "decision_space_hl7"

Expected SQL (ClickHouse):
SELECT
msg_id,
event_ts,
CASE
WHEN (message_type = 'ORM' AND order_priority = 'STAT'
AND obs_abn_flag IN ('H','L')) THEN 3
WHEN (message_type = 'ORM' AND order_priority = 'STAT') THEN 2
ELSE 1
END AS action_id
FROM hl7_messages
WHERE event_ts >= now() - INTERVAL 2 DAY;

Test D (Table-Driven) — PostgreSQL (Categories and Flags via Reference Tables)
Here, categories and a flag are governed by reference tables.
enum(select ...) allows ACBP to prove coverage/soundness against live 
vocabularies; it only affects SQL when referenced.

Input (ACBP DSL):
model hl7_v1 {
from hl7_messages
time_column event_ts
// categories via reference tables
category message_type  := enum(select code from ref_message_type)      // e.g., 
('ADT'),('ORM'),('ORU')
category trigger_event := enum(select code from ref_trigger_event)     // e.g., 
('A01'),('A04'),('A03'),...
category patient_class := enum(select code from ref_patient_class)     // e.g., 
('E'),('I'),('O')
// flag driven by ref-table membership (governance-controlled)
ref emergency_classes := "ref_patient_class_emergency"                 // e.g., 
('E')
flag is_emergency := patient_class in (select code from 
ref_patient_class_emergency)
// admission flag inline
flag is_admission := message_type = 'ADT' and trigger_event in ('A01','A04')
decision action_id {
when is_admission and is_emergency -> 2
else -> 1
}
}

Options:
windowDays = 2
dialect = PostgresqlSqlDialect.DEFAULT
entryPoint = "decision_space_hl7"

Expected SQL (PostgreSQL):
SELECT
msg_id,
event_ts,
CASE
WHEN (message_type = 'ADT'
AND trigger_event IN ('A01','A04')
AND patient_class IN (SELECT code FROM ref_patient_class_emergency)) THEN 2
ELSE 1
END AS action_id
FROM hl7_messages
WHERE event_ts >= now() - interval '2 days';

Minimal Test Harness (Illustrative)
@Test
void test_admission_emergency_postgres() {
var dsl = """
model hl7_v1 {
from hl7_messages
time_column event_ts
category message_type  := enum('ADT','ORM','ORU')
category trigger_event := enum('A01','A04','A03','O01','R01')
category patient_class := enum('E','I','O')
flag is_admission := message_type = 'ADT' and trigger_event in ('A01','A04')
flag is_emergency := patient_class = 'E'
decision action_id { when is_admission and is_emergency -> 2 else -> 1 }
}
""";
String sql = acbpToSql(dsl, "decision_space_hl7",
PostgresqlSqlDialect.DEFAULT, Map.of("windowDays", 2));
String expected = """
SELECT msg_id, event_ts,
CASE
WHEN (message_type = 'ADT' AND trigger_event IN ('A01','A04') AND patient_class 
= 'E') THEN 2
ELSE 1
END AS action_id
FROM hl7_messages
WHERE event_ts >= now() - interval '2 days'
""";
assertEquals(normalize(expected), normalize(sql));
}
private static String normalize(String s) {
return s.replaceAll("\\s+", " ").trim().toLowerCase();
}

** If preferred, both strings can instead be parsed to SqlNode and 
tree-compared.

If this shape looks right, I'll share a tiny repo with:

  *   RelBuilder construction for these plans,
  *   Golden expected SQL for PostgreSQL, BigQuery, and ClickHouse,
  *   And a normalization helper. Any dialect edge we hit can become a Jira 
with a failing test.

Best,
Muteb (DotK)

________________________________
From: Julian Hyde <jhyde.apa...@gmail.com>
Sent: Wednesday, August 20, 2025 7:24 PM
To: dev@calcite.apache.org <dev@calcite.apache.org>
Subject: Re: [DISCUSS] ACBP × HL7: Calcite IR → multi-dialect SQL for 
deterministic policy artifacts (Why ACBP, benefits, MWE, questions)

As I said, what would be most helpful to me would be to understand the 
requirements. I’d love to see a simple or moderately complex test case - e.g. 
this tool can transform this string in language X to this SQL string - than 
read through the code that implements it.

Julian

> On Aug 19, 2025, at 17:42, Muteb Alanazi <dotk...@outlook.com> wrote:
>
> Subscribed now (dotk...@outlook.com). CC no longer needed.
>
> Happy to proceed with the HL7/ACBP test cases I shared. I can also attach:
> - a tiny repo with RelBuilder → RelToSql → SqlDialect producing the expected 
> strings, and
> - a normalization helper (compare SqlNode trees or whitespace-collapsed SQL)
> if that helps reviewers.
>
> —Muteb
>

Reply via email to