Skip to content

Fix multi-statement measure view batches#39

Merged
nicosuave merged 37 commits into
mainfrom
fix-multi-measure-batch
Jul 3, 2026
Merged

Fix multi-statement measure view batches#39
nicosuave merged 37 commits into
mainfrom
fix-multi-measure-batch

Conversation

@nicosuave

Copy link
Copy Markdown
Member

Fixes multi-statement SQL batches containing more than one CREATE VIEW ... AS MEASURE definition by rewriting and registering measure views statement-by-statement before DuckDB parses the cleaned batch.

Adds regression coverage for two AS MEASURE view definitions in one statement batch, then verifies both registered measures through prefixed and parser-override query paths.

Validation:

  • git diff --check
  • make test

Note: standalone cargo test is not a valid full-suite target in this checkout because many existing tests require the C++ parser FFI to be initialized by the extension runtime.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8ca592b289

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +397 to +399
if (c == ';') {
statements.push_back(sql.substr(statement_start, i - statement_start));
statement_start = i + 1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle dollar-quoted literals when splitting batches

DuckDB supports $$...$$ and $tag$...$tag$ string literals (see DuckDB's literal docs: https://duckdb.org/docs/current/sql/data_types/literal_types.html#dollar-quoted-string-literals), but this splitter does not track that state, so a batch that also contains an AS MEASURE view will split at semicolons inside those strings. For example, INSERT INTO log VALUES ($$a;b$$); CREATE VIEW v AS SELECT SUM(x) AS MEASURE m FROM t; is rejoined as $$a;\nb$$, silently changing the inserted value before the cleaned batch is parsed.

Useful? React with 👍 / 👎.

@nicosuave
nicosuave force-pushed the fix-multi-measure-batch branch from 8ca592b to a0be690 Compare July 2, 2026 15:24

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a0be690fb9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
if (measure_rewrite.had_measure_view) {
had_measure_rewrite = true;
sql_to_check = std::move(measure_rewrite.rewritten_sql);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Split aggregate expansion after measure rewrites

When a newly supported batch starts with CREATE VIEW ... AS MEASURE and then includes a later SELECT ... AGGREGATE(...), this path rewrites the views but still sends the entire multi-statement batch through yardstick_expand_aggregate. That expansion calls yardstick_parse_select, which only inspects parser.statements[0], so it reports Not a SELECT for the leading CREATE VIEW; the override then falls back and DuckDB reparses the original AS MEASURE batch, causing the script to fail. Expand aggregate-containing statements separately, or return the cleaned batch before invoking aggregate expansion for this batch shape.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d0059efa94

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +655 to +656
if (yardstick_has_as_measure(sql_to_check.c_str())) {
auto measure_rewrite = RewriteMeasureViewsStatementByStatement(sql_to_check);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Guard the AS MEASURE pre-pass to real measure views

When an aggregate query has a normal alias named measure, e.g. SELECT AGGREGATE(revenue), 1 AS measure FROM sales_v, this new pre-pass runs before the aggregate path because yardstick_has_as_measure is only a substring check. yardstick_process_create_view then treats the following FROM token as a measure name even though the statement is not a CREATE VIEW, corrupting the SQL before the aggregate expansion that previously handled this query. Gate this branch on an actual CREATE VIEW ... AS MEASURE parse, or make the detector quote/comment/context-aware before taking over the query.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a22729fb51

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +517 to +520
if (!yardstick_has_as_measure(statement.c_str()) ||
!StartsWithCreateViewStatement(statement)) {
rewritten_statements.push_back(statement);
continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clean dropped measure views inside rewritten batches

When a rewritten batch includes a dropped measure view followed by another measure view, e.g. DROP VIEW old_v; CREATE VIEW new_v AS ... AS MEASURE ..., this branch treats the DROP as an ordinary statement and never removes old_v from Yardstick's measure catalog. The earlier yardstick_drop_measure_view_from_sql call only succeeds when the whole query is a standalone DROP VIEW, so in these multi-statement migrations DuckDB drops the view but Yardstick can still resolve later measure references to the stale/non-existent view. Process DROP VIEW statements in this split pass before pushing them through unchanged.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 73a17408a4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +738 to +741
if (had_measure_rewrite && yardstick_has_aggregate(sql_to_check.c_str())) {
auto aggregate_rewrite = RewriteAggregatesStatementByStatement(sql_to_check);
if (aggregate_rewrite.had_aggregate) {
sql_to_check = std::move(aggregate_rewrite.rewritten_sql);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve batch order when expanding aggregates

When a batch creates a measure view, uses it, and then later drops or replaces it, this second pass expands aggregates only after RewriteMeasureViewsStatementByStatement has already scanned the whole batch and applied the later catalog mutation. For example, CREATE VIEW temp_v ... AS MEASURE revenue; CREATE TABLE out AS SELECT AGGREGATE(revenue) FROM temp_v; DROP VIEW temp_v; should expand the CTAS before the DROP, but this code expands it with temp_v already removed from Yardstick's catalog, so the statement can fall back to the NULL placeholder or another definition and write wrong results. Interleave measure rewrites, catalog updates, and aggregate expansion in statement execution order.

Useful? React with 👍 / 👎.

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +519 to +520
if (!yardstick_has_as_measure(statement.c_str()) ||
!StartsWithCreateViewStatement(statement)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip leading comments before processing measure views

For a measure-view statement in a batch that starts with a comment, this check succeeds because StartsWithCreateViewStatement skips comments, but the original commented SQL is then passed to yardstick_process_create_view. The Rust create-view parser only accepts whitespace before CREATE, so it emits the clean view without registering the view name in the measure catalog; later AGGREGATE() calls against that view can aggregate the NULL placeholder instead of the measure. Strip the leading comments before processing, or make the downstream create-view parser consume them consistently.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 53d25ac8e2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

pos = SkipWhitespaceAndComments(sql, pos);
}

return ConsumeKeyword(sql, pos, "VIEW");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept temporary measure views in the pre-pass

When users create a valid temporary measure view, e.g. CREATE TEMP VIEW v AS SELECT SUM(x) AS MEASURE m FROM t, this helper returns false because it requires VIEW immediately after the optional OR REPLACE. The surrounding pre-pass then skips yardstick_process_create_view, so the raw AS MEASURE syntax falls through to DuckDB and the statement fails to parse instead of being rewritten; allow TEMP/TEMPORARY before VIEW here.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6ea6de3ea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +543 to +548
if (!yardstick_has_aggregate(statement.c_str())) {
rewritten_statements.push_back(statement);
continue;
}

YardstickAggregateResult result = yardstick_expand_aggregate(statement.c_str());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid expanding AGGREGATE text inside dollar literals

When a batch contains a measure-view rewrite and a later statement stores dollar-quoted text such as INSERT INTO notes VALUES ($$AGGREGATE(order_revenue)$$), this path calls yardstick_expand_aggregate on that statement even though the only occurrence is inside the literal. The splitter now preserves dollar-quoted strings, but the Rust aggregate detector/extractor does not skip them, so the literal contents can be rewritten before DuckDB executes the insert, silently corrupting stored text in multi-statement measure batches.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d142c479f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1372 to 1373
for start in aggregate_call_starts_outside_literals(sql) {
if let Ok((remaining, (measure, modifiers))) = aggregate_with_at(&sql[start..]) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve rewrites when dollar literals remain

When a statement contains both a real measure call and dollar-quoted text with AGGREGATE, e.g. SELECT AGGREGATE(revenue), $$AGGREGATE(cost)$$ FROM sales_v, this extractor skips the literal but has_aggregate_function still sees it later in expand_aggregate_with_at. That residual check delegates to expand_aggregate, which finds no extractable calls and returns had_aggregate=false; the C++ callers only use expanded_sql when that flag is true, so the real AGGREGATE(revenue) expansion is discarded and the original statement falls through to DuckDB. Make the detector dollar-quote-aware or preserve the original had_aggregate flag when only literals remain.

Useful? React with 👍 / 👎.

Comment on lines +1406 to +1408
let (input, _) = opt(tuple((
alt((tag_no_case("TEMPORARY"), tag_no_case("TEMP"))),
multispace1,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep temporary measure views out of the global catalog

When users create a TEMP/TEMPORARY measure view, this now allows process_create_view to register it in the process-global MEASURE_VIEWS map just like a permanent view. DuckDB temp views are scoped to a connection/session and can disappear without a DROP VIEW statement reaching Yardstick, but the measure catalog has no connection key or session cleanup, so later connections can resolve AGGREGATE() against a stale temp definition and expand using the wrong base query. Keep temp measure definitions connection-scoped or avoid registering them globally.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e720efc5da

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

rewrite_result.rewritten_sql += rewritten_statements[i];
}

cleanup_temporary_measure_views();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve temporary measure metadata for the session

When the batch is just CREATE TEMP VIEW tmp_v AS ... AS MEASURE revenue ..., this cleanup removes only Yardstick's catalog entry before the parsed CREATE TEMP VIEW is executed, while DuckDB keeps the temporary view for the connection. A later same-session SELECT AGGREGATE(revenue) FROM tmp_v then has no measure definition to resolve and expands against the cleaned view's NULL AS revenue placeholder (or otherwise falls back), producing wrong results instead of the temp measure semantics; keep temp metadata connection-scoped until the temp view is dropped/session ends, or reject standalone temp measure views.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 22e4c2c5ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (had_measure_rewrite) {
try {
Parser parser;
parser.ParseQuery(sql_to_check);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Roll back measure registrations when batch parsing fails

Because RewriteMeasureViewsStatementByStatement registers permanent measure views before this parse, a syntax error anywhere later in the cleaned batch returns from this catch without undoing those side effects. For a batch with a valid CREATE VIEW ... AS MEASURE followed by malformed SQL, DuckDB executes none of the statements, but Yardstick keeps the registered measure definition and can later resolve AGGREGATE() against a nonexistent or old view.

Useful? React with 👍 / 👎.

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +563 to +564
if (is_temporary_measure_view && result.view_name) {
temporary_measure_views.emplace_back(result.view_name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore overwritten permanent measures after temp cleanup

When a temporary measure view uses the same name as an existing permanent measure view, yardstick_process_create_view has already overwritten the global catalog entry; recording only result.view_name here means cleanup_temporary_measure_views() later drops that key instead of restoring the permanent definition. The fresh evidence is that the cleanup list contains only names, so after the temp batch or standalone-temp rejection, the permanent DuckDB view can still exist while Yardstick has lost its measure metadata.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c478b2a5e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

try {
Parser parser;
parser.ParseQuery(sql_to_check);
return ParserOverrideResult(std::move(parser.statements));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip SELECT fallback for rewritten batches

When a rewritten measure batch contains a standalone SELECT after the CREATE VIEW, returning these ordinary parsed statements lets the SELECT bind fallback run later; that fallback expands context.GetCurrentQuery() in yardstick_bind (the original multi-statement CREATE VIEW ...; SELECT AGGREGATE(...) text), so the Rust parser sees the leading CREATE and raises Not a SELECT. The fresh evidence beyond the earlier parser-override issue is that this branch now expands per statement but still returns normal SELECT statements here, while the existing fallback at src/yardstick_extension.cpp:854-858 re-expands the original batch; CTAS/INSERT cases avoid this because they are not SELECT_STATEMENTs.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a25678de81

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
continue;
}

YardstickAggregateResult result = yardstick_expand_aggregate(statement.c_str());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip SEMANTIC before per-statement expansion

In batches where SEMANTIC prefixes a later statement rather than the whole query, e.g. CREATE VIEW v AS SELECT SUM(x) AS MEASURE revenue FROM t; SEMANTIC SELECT AGGREGATE(revenue) FROM v, this passes the prefixed statement into the aggregate rewriter. The expanded SQL still starts with SEMANTIC, so ParsesAsSingleSelect returns false and the final parse of the rewritten batch sees invalid SEMANTIC SELECT, making the new multi-statement flow fail; strip the prefix per statement before expansion/wrapping.

Useful? React with 👍 / 👎.

Comment thread src/yardstick_extension.cpp Outdated
}

auto statement_body = statement.substr(SkipWhitespaceAndComments(statement, 0));
yardstick_drop_measure_view_from_sql(statement_body.c_str());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Snapshot drops before speculative batch parsing

This removes Yardstick metadata during the speculative rewrite pass, but rollback only tracks CREATE snapshots. When a batch has a later parse error, e.g. DROP VIEW sales_v; CREATE VIEW other AS SELECT SUM(x) AS MEASURE m FROM t; SELEC, DuckDB rejects the whole batch while the measure catalog has already forgotten sales_v, so subsequent AGGREGATE() calls cannot resolve a view that still exists; snapshot dropped entries or defer the drop until the cleaned batch is accepted/executed.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 114be2b0b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
yardstick_free_aggregate_result(result);
}

if (!temporary_snapshots.empty() && !rewrite_result.had_aggregate) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject unused temp measure views despite other aggregates

When a batch creates a TEMP AS MEASURE view but only expands an unrelated AGGREGATE() in the same batch, this global had_aggregate flag lets the batch through. cleanup_temporary_measure_views() then removes the temp view's Yardstick metadata while DuckDB still creates the temp view, so a later same-session query like SELECT AGGREGATE(temp_measure) FROM temp_v expands against the cleaned view's NULL placeholder instead of the measure definition. Track whether each temporary measure view is actually consumed in the batch, not just whether any aggregate was present.

Useful? React with 👍 / 👎.

Comment thread src/yardstick_extension.cpp Outdated
}

auto statement_body = statement.substr(SkipWhitespaceAndComments(statement, 0));
SnapshotAndDropMeasureViewFromSql(statement_body, permanent_snapshots);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep dropped temp snapshots out of permanent rollback

When a speculative batch creates a temporary measure view and then drops it before an error or rejection, e.g. CREATE TEMP VIEW v ... AS MEASURE m; DROP VIEW v; SELEC, this unconditional drop snapshot records the temporary definition in permanent_snapshots. The temp cleanup restores the original catalog first, but the caller then restores permanent_snapshots and re-inserts the dropped temp definition, potentially overwriting an existing permanent measure even though DuckDB rejected the batch; the fresh path here is the later DROP capturing the temp definition after it was registered.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bf976e41bf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +628 to +631
if (HasTemporarySnapshot(temporary_snapshots, view_name)) {
RemoveCaseInsensitive(pending_temporary_views, view_name);
yardstick_drop_measure_view_from_sql(sql.c_str());
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore shadowed measures when dropping temps

When a temporary measure view shadows an existing permanent measure view and is dropped before a later statement in the same batch, this branch removes the temp catalog entry but leaves the permanent snapshot hidden until final cleanup. In a batch like CREATE TEMP VIEW v ... AS MEASURE temp_m; DROP VIEW v; CREATE TABLE out AS SELECT AGGREGATE(perm_m) FROM v, DuckDB resolves v back to the permanent view after the drop, while Yardstick has no permanent metadata yet and expands against the cleaned NULL placeholder or fails; restore the temp snapshot immediately when handling the temp DROP VIEW.

Useful? React with 👍 / 👎.

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +762 to +764
for (auto it = pending_temporary_views.begin(); it != pending_temporary_views.end();) {
if (ContainsIdentifier(aggregate_statement, *it)) {
it = pending_temporary_views.erase(it);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require actual temp-view use before clearing pending state

This clears a pending temporary measure view whenever the aggregate statement merely contains the view name as an identifier-like token, not when the aggregate actually reads from that temp view. If the batch creates TEMP VIEW tmp_v ... AS MEASURE ... and then runs an unrelated aggregate with AS tmp_v or a predicate/literal mentioning tmp_v, the batch is allowed, cleanup removes Yardstick's temp metadata, and DuckDB still creates the temp view for the session; later AGGREGATE() queries against that temp view then use missing/stale metadata. Check the parsed FROM sources instead of substring containment before erasing the pending temp view.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2914bae261

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +879 to +880
if (ParsesAsSingleSelect(expanded_sql)) {
rewritten_statements.push_back(WrapYardstickSelect(expanded_sql));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid wrapping temp-view reads in a new connection

When a batch creates a temporary measure view and the same batch returns a SELECT from it, e.g. CREATE TEMP VIEW tmp_v AS ... AS MEASURE m; SELECT AGGREGATE(m) FROM tmp_v, this branch wraps the expanded select in yardstick(...). YardstickQueryBind executes that string through a fresh Connection con(*context.db) at src/yardstick_extension.cpp:263, so it cannot see temp views created in the caller's session/batch; CTAS avoids this because it is not wrapped. Keep SELECTs that depend on pending temporary views in the original execution context or reject that batch shape.

Useful? React with 👍 / 👎.

Comment on lines +1095 to +1097
parser.ParseQuery(sql_to_check);
FreeMeasureViewSnapshots(permanent_snapshots);
return ParserOverrideResult(std::move(parser.statements));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Defer measure-catalog commits past batch failures

This frees the rollback snapshots immediately after the rewritten batch merely parses, but the statements have not bound or executed yet. If a later statement parses but fails at bind/execution time (for example a valid CREATE VIEW ... AS MEASURE, followed by SELECT * FROM missing_table, followed by a DROP/replacement), Yardstick has already applied all measure catalog mutations while DuckDB only executes the successful prefix or rolls the batch back, leaving stale or missing measure metadata. Keep the snapshots until execution succeeds or apply catalog mutations in statement execution order.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 08245342a1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
yardstick_free_create_view_result(result);
}

FreeMeasureViewSnapshots(permanent_snapshots);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore snapshots for false-positive AS MEASURE batches

When AS MEASURE appears only in a literal/comment, the speculative rewrite still walks the batch and processes later DROP VIEW statements, but had_measure_rewrite stays false and this cleanup frees the rollback snapshots before falling through to DuckDB. For example, SELECT * FROM missing /* AS MEASURE */; DROP VIEW sales_v; drops sales_v from Yardstick's catalog even though binding fails before DuckDB executes the DROP, leaving the real view present but its measures forgotten; restore the snapshots unless the rewritten batch is actually accepted/executed.

Useful? React with 👍 / 👎.

Comment thread test/sql/measures.test Outdated
FROM batch_temp_select_v
GROUP BY year;
----
TEMPORARY AS MEASURE views must be used in the same statement batch as AGGREGATE()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Expect the direct-temp SELECT error actually emitted

For this exact CREATE TEMP VIEW ...; SELECT ... FROM batch_temp_select_v shape, StatementReadsFromView is true and the branch at src/yardstick_extension.cpp:1126 returns TEMPORARY AS MEASURE views cannot be returned directly from a statement batch, not this expected text. The sqllogictest error matcher will not see the expected substring, so this newly added test fails even though the intended rejection path is reached.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bad1c2a9fc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +1116 to +1118
if (StatementReadsFromView(aggregate_statement, *it)) {
reads_pending_temporary_view = true;
it = pending_temporary_views.erase(it);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep temp views guarded after first batch use

When a temp measure view is consumed by an earlier non-SELECT statement, e.g. CREATE TEMP VIEW tmp...; CREATE TABLE out AS SELECT AGGREGATE(m) FROM tmp; SELECT AGGREGATE(m) FROM tmp;, this erase removes the only marker used to detect later reads from that temp view. The fresh evidence beyond the earlier direct-temp SELECT case is that after the CTAS clears pending_temporary_views, the later SELECT falls through to WrapYardstickSelect, whose table function runs in a fresh connection and cannot see the caller's temporary view, so the batch fails or resolves the wrong relation.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a30603bde6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
cleanup_temporary_measure_views();
return rewrite_result;
}
if (ExtractDropViewNameFromSql(statement_body, drop_view_name)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle DROP VIEW CASCADE in batch cleanup

When a rewritten batch uses DuckDB's valid DROP VIEW old_v CASCADE or RESTRICT form before another AS MEASURE statement, this extractor returns false because it only accepts a bare statement tail, so the drop is pushed through as ordinary SQL and Yardstick never removes old_v from the measure catalog. DuckDB documents CASCADE/RESTRICT for DROP statements (https://duckdb.org/docs/lts/sql/statements/drop.html), so DuckDB can still drop the view while later AGGREGATE() resolution can see stale measure metadata.

Useful? React with 👍 / 👎.

Comment on lines +1048 to +1049
if (yardstick_has_as_measure(statement_body.c_str()) &&
StartsWithCreateViewStatement(statement_body)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip per-statement SEMANTIC before view rewrites

When SEMANTIC prefixes a later measure-view statement in a batch, for example SELECT 1; SEMANTIC CREATE VIEW v AS SELECT SUM(x) AS MEASURE m FROM t, this guard checks the unstripped statement_body, so it skips yardstick_process_create_view and the raw SEMANTIC CREATE ... AS MEASURE is handed back to DuckDB. Top-level SEMANTIC is stripped earlier and aggregate statements strip it per statement, so batched catalog rewrites need the same treatment.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2331c6e329

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread yardstick-rs/src/ffi.rs
}
};

let snapshot: Option<MeasureView> = get_measure_view(view_name_str);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Snapshot measure views case-insensitively

When a batch speculatively drops or replaces a measure view using a different case than it was created with, this exact get_measure_view lookup records None even though drop_measure_view_from_sql later removes the catalog entry case-insensitively. For example, after CREATE VIEW Sales_V ... AS MEASURE ..., an erroring batch such as DROP VIEW sales_v; SELEC leaves the DuckDB view intact but restores a None snapshot, so Yardstick loses the measure metadata for Sales_V.

Useful? React with 👍 / 👎.

Comment thread src/yardstick_extension.cpp Outdated
cleanup_temporary_measure_views();
return rewrite_result;
}
if (ExtractDropViewNameFromSql(statement_body, drop_view_name)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not process drops during false AS MEASURE scans

When AS MEASURE appears only in a literal or comment, this speculative pass still handles later DROP VIEW statements even though no measure view is actually rewritten. The fresh evidence is that the caller now restores these snapshots before falling through to DuckDB; for a successful batch like SELECT ' AS MEASURE '; DROP VIEW sales_v;, DuckDB drops the real view while Yardstick has restored the dropped metadata, leaving stale measures that can be resolved by later AGGREGATE() calls.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39233c3acb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

static bool StatementReadsFromView(const std::string &sql, const std::string &view_name) {
std::string select_sql = SelectPortionForTableAnalysis(sql);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Detect temporary measure reads inside CTEs

When a pending temporary measure view is used inside a CTE, this narrows the analysis to the outer SELECT and drops the CTE definitions. For example, CREATE TEMP VIEW tmp_v ... AS MEASURE m; CREATE TABLE out AS WITH x AS (SELECT AGGREGATE(m) FROM tmp_v) SELECT * FROM x; actually uses the temp view in the same batch, but read_temporary_views stays empty, so the batch is later rejected as unused (and a returned WITH query can be wrapped into yardstick() without seeing the session temp view). Analyze the full WITH statement's table sources before enforcing the temporary-view checks.

Useful? React with 👍 / 👎.


pub fn restore_measure_view(view: MeasureView) {
let mut views = MEASURE_VIEWS.lock().unwrap();
views.insert(view.view_name.clone(), view);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove stale case variants when restoring measures

When rollback restores a snapshot whose saved name differs only by case from the speculative rewrite, this plain insert leaves the speculative entry in MEASURE_VIEWS. For example, after an existing Sales_V, a failing batch with CREATE OR REPLACE VIEW sales_v ... AS MEASURE new_m; SELEC inserts sales_v during the rewrite and then restores Sales_V, so the unexecuted sales_v definition remains in the catalog and later AGGREGATE() resolution can see stale measures. Remove any case-insensitive existing key before inserting the restored snapshot.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7dc425926f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
if (view_name.empty() && result.view_name) {
view_name = result.view_name;
}
apply_deferred_drop_views(view_name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply prior drops before temporary replacements

When a batch drops a permanent measure view and then creates a temporary measure view with the same name, e.g. DROP VIEW v; CREATE TEMP VIEW v AS ... AS MEASURE m; CREATE TABLE out AS SELECT AGGREGATE(m) FROM v, this call skips the deferred drop because the names match. DuckDB still drops the permanent view before creating the temp view, while Yardstick snapshots the old permanent entry for the temp create and restores it during temp cleanup, leaving stale permanent measure metadata for a view that no longer exists.

Useful? React with 👍 / 👎.

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +909 to +910
if (info->tables[i].table_name &&
TableRefMatchesView(info->tables[i].table_name, view_name)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore subquery aliases when checking temp-view use

When a pending temp measure view name is reused only as a derived-table alias, e.g. CREATE TEMP VIEW tmp_v ... AS MEASURE m; CREATE TABLE out AS SELECT AGGREGATE(revenue) FROM sales_v JOIN (SELECT 1) tmp_v ON true, yardstick_parse_select reports that alias with is_subquery=true, but this condition ignores that flag and marks the temp view as consumed. That bypasses the unused-temp rejection, cleanup removes Yardstick's temp metadata while DuckDB still creates the session temp view, and later AGGREGATE(m) FROM tmp_v expands without its measure definition.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 51a4ea168f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +603 to +607
for (auto it = snapshots.begin(); it != snapshots.end(); ++it) {
if (EqualsCaseInsensitive(it->view_name, view_name)) {
yardstick_restore_measure_view_snapshot(it->view_name.c_str(), it->snapshot);
snapshots.erase(it);
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Discard all temp snapshots when dropping a replaced temp

When the same temporary measure view is replaced and then dropped in one batch, e.g. CREATE TEMP VIEW v ... AS MEASURE m1; CREATE OR REPLACE TEMP VIEW v ... AS MEASURE m2; DROP VIEW v;, this restores and erases only the first same-name snapshot and leaves the later snapshot in temporary_snapshots. The final temp cleanup then restores that stale temp definition even though DuckDB has dropped the temp view, so Yardstick's catalog can point at a non-existent/shadowing measure view after the batch or after the unused-temp error path. Remove all same-name temp snapshots (restoring only the base snapshot) and pending entries when handling the temp drop.

Useful? React with 👍 / 👎.

@nicosuave
nicosuave force-pushed the fix-multi-measure-batch branch from 275700b to dcda97a Compare July 3, 2026 01:04

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dcda97a887

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +984 to +988
if (HasMeasureSnapshot(temporary_snapshots, view_name)) {
RemoveCaseInsensitive(pending_temporary_views, view_name);
RemoveCaseInsensitive(used_temporary_views, view_name);
yardstick_drop_measure_view_from_sql(sql.c_str());
RestoreAndRemoveTemporarySnapshot(temporary_snapshots, view_name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Distinguish qualified permanent drops from temp drops

When a temp measure view v shadows a permanent measure view and the batch contains DROP VIEW main.v, view_name has already been reduced to v, so this branch treats the qualified permanent drop as a temp-view drop. DuckDB drops main.v while the temp view remains, but Yardstick removes the temp metadata and restores the permanent snapshot; a following CREATE TABLE ... SELECT AGGREGATE(temp_m) FROM v expands against the wrong definition (or the NULL placeholder) and returns incorrect results. Keep the qualifier so only unqualified/temp-schema drops take the temporary-snapshot path.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 87728e15ba

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +651 to +654
if (table_name.size() > view_name.size()) {
idx_t suffix_start = table_name.size() - view_name.size();
return table_name[suffix_start - 1] == '.' &&
EqualsCaseInsensitive(table_name.substr(suffix_start), view_name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require temp-schema match for qualified temp reads

When a pending temporary measure view v shadows a permanent measure view, this suffix match makes StatementReadsFromView treat FROM main.v as a read of the temp view. DuckDB resolves that qualified reference to the permanent view, but Yardstick has registered the temp definition globally, so a same-batch CTAS using AGGREGATE() from main.v can be marked as consuming the temp view and expanded with the temp measure metadata instead of the permanent view's metadata, producing wrong results. Limit this match to unqualified names or explicit temp schemas for pending temporary views.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: be4e010436

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
}

YardstickAggregateResult result = yardstick_expand_aggregate(aggregate_statement.c_str());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid rewriting AT shorthand inside dollar literals

In a batch that first registers a measure and later stores dollar-quoted text containing shorthand such as revenue AT (ALL), this call is reached because yardstick_has_aggregate also consults has_measure_at_refs; rewrite_measure_at_refs skips single/double quotes and comments but not dollar-quoted strings, so yardstick_expand_aggregate returns had_aggregate=true with the literal changed to AGGREGATE(revenue) AT (ALL). Since the expanded non-SELECT is pushed back into the batch, an INSERT stores corrupted text even though no measure expression was present; make the AT detector/rewrite dollar-quote-aware before expanding batch statements.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e088720bc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
apply_deferred_drop_views();
if (has_snapshot) {
yardstick_free_measure_view_snapshot(snapshot.snapshot);
has_snapshot = false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep temp replacements tracked after deferred drops

When the batch is DROP VIEW v; CREATE TEMP VIEW v AS ... AS MEASURE m; SELECT/CREATE TABLE ... AGGREGATE(m) FROM v, this branch pre-applies the deferred drop and then clears has_snapshot. Because the later temporary-view block only pushes pending_temporary_views when has_snapshot is still true, the new temp measure view is never tracked: direct SELECTs from it bypass the temp guard and cleanup never removes its process-global metadata. Fresh evidence is that the current code now pre-applies the deferred drop before disabling the only snapshot path that records the temp view.

Useful? React with 👍 / 👎.

Comment thread src/yardstick_extension.cpp Outdated
deferred_drop_views.push_back(drop_view);
}
executable_since_catalog_mutation = false;
rewritten_statements.push_back(statement);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Append stripped SEMANTIC drops to rewritten batches

When a batch contains a real measure rewrite and a later SEMANTIC DROP VIEW v, the statement is stripped into statement_body for catalog handling but this appends the original statement back into the rewritten SQL. The final parser.ParseQuery(sql_to_check) then sees SEMANTIC DROP VIEW in the middle of the batch, since only the leading query-level prefix is stripped, so an otherwise valid per-statement semantic drop fails to parse after the measure rewrite.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 635b5fc58d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
}

yardstick_free_select_info(info);
return found || StatementTextReadsFromView(select_sql, view_name, qualified_permanent);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid lexical temp-view reads after parser success

When a pending temp measure view name appears in non-relation SQL such as EXTRACT(year FROM tmp_v), the parser result above correctly reports only real table sources, but this unconditional || StatementTextReadsFromView(...) still treats the scalar FROM tmp_v as a table read. Fresh evidence is that the current code runs the lexical fallback even after yardstick_parse_select succeeds. In a batch that creates TEMP VIEW tmp_v ... AS MEASURE ... and then does a CTAS over another measure view with a column expression EXTRACT(... FROM tmp_v), used_temporary_views is set, the unused-temp rejection is bypassed, and cleanup removes Yardstick metadata while DuckDB keeps the temp view for the session.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1b34bbd151

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated
Comment on lines +997 to +998
return found || ((qualified_permanent || starts_with_with) &&
StatementTextReadsFromView(select_sql, view_name, qualified_permanent));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid lexical CTE temp-view matches

When the aggregate statement starts with WITH, this falls back to scanning the raw SQL text even after the parser path did not find the pending temp view. In a batch such as CREATE TEMP VIEW tmp_v ... AS MEASURE m; CREATE TABLE out AS WITH x AS (SELECT EXTRACT(year FROM tmp_v) FROM dates) SELECT AGGREGATE(revenue) FROM sales_v, the FROM tmp_v inside EXTRACT is a column expression, not a table read, but it marks the temp view as used; the unused-temp rejection is bypassed, cleanup removes Yardstick metadata while DuckDB keeps the session temp view, and later AGGREGATE(m) FROM tmp_v expands without the temp measure definition.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5f015116da

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/yardstick_extension.cpp Outdated

bool found = false;
for (idx_t i = 0; i < info->table_count; i++) {
if (!info->tables[i].is_subquery &&

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Detect temp-view reads inside derived subqueries

When a pending temporary measure view is read inside a derived table, e.g. CREATE TEMP VIEW tmp_v ...; CREATE TABLE out AS SELECT * FROM (SELECT AGGREGATE(m) FROM tmp_v) s, the parser reports the outer table as a subquery rather than walking the inner FROM (CollectTablesFromTableRef records is_subquery=true). This filter skips that entry and the fallback below does not run for ordinary SELECTs, so read_temporary_views stays empty and the valid same-batch use is rejected as an unused temporary measure view.

Useful? React with 👍 / 👎.

@nicosuave
nicosuave merged commit bf12b00 into main Jul 3, 2026
26 checks passed
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.

1 participant