You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@flink.apache.org by "raminqaf (via GitHub)" <gi...@apache.org> on 2026/06/12 07:53:30 UTC
[PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
raminqaf opened a new pull request, #28403:
URL: https://github.com/apache/flink/pull/28403
### What is the purpose of the change
A foreground query (a bare `SELECT` collected through the anonymous result sink, which has no primary key) over a relation that emits an upsert changelog fails with an unhelpful error: Can't generate a valid execution plan for the given query followed by the optimized plan. A common trigger is `FROM_CHANGELOG` with `PARTITION BY` and an `op_mapping` without `UPDATE_BEFORE`. This change appends actionable guidance to that error. Behavior is unchanged; only the message is improved.
### Brief change log
- `FlinkChangelogModeInferenceProgram`: when the rejected plan involves updates, append guidance explaining the upsert-vs-retract mismatch and the two fixes (declare a `PRIMARY KEY` on the sink, or make the upstream emit `UPDATE_BEFORE`). Gated on `ModifyKind.UPDATE` so unrelated planning failures keep the original message.
### Verifiying the output
Locally setup a test and verified the exception message. The plan now includes the changelog mode of the operators. Before, it was all set to `NONE`.
```
Can't generate a valid execution plan for the given query:
This usually means an upsert changelog (UPDATE_AFTER without UPDATE_BEFORE) reaches an operator or sink that requires a retract changelog (UPDATE_BEFORE and UPDATE_AFTER), for example a sink without a primary key. To resolve it, declare a PRIMARY KEY on the sink, or make the input produce UPDATE_BEFORE.
Sink(table=[*anonymous_collect$1*], fields=[customer_id, name], changelogMode=[NONE])
+- ProcessTableFunction(invocation=[FROM_CHANGELOG(TABLE(#0) PARTITION BY($0), DESCRIPTOR(_UTF-16LE'operation'), MAP(_UTF-16LE'Created', _UTF-16LE'INSERT':VARCHAR(12) CHARACTER SET "UTF-16LE", _UTF-16LE'Updated', _UTF-16LE'UPDATE_AFTER':VARCHAR(12) CHARACTER SET "UTF-16LE", _UTF-16LE'Deleted', _UTF-16LE'DELETE':VARCHAR(12) CHARACTER SET "UTF-16LE"), DEFAULT(), DEFAULT(), DEFAULT())], uid=[FROM_CHANGELOG], select=[customer_id,name], rowType=[RecordType(VARCHAR(2147483647) customer_id, VARCHAR(2147483647) name)], changelogMode=[I,UA,D])
+- Exchange(distribution=[hash[customer_id]], changelogMode=[I])
+- TableSourceScan(table=[[default_catalog, default_database, customer_events]], fields=[customer_id, name, operation], changelogMode=[I])
```
### Does this pull request potentially affect one of the following parts:
- Dependencies: no
- `@Public(Evolving)` API: no
- Serializers: no
- Runtime per-record code paths: no
- Deployment / recovery: no
- S3 connector: no
### Documentation
- New feature: no
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "twalthr (via GitHub)" <gi...@apache.org>.
twalthr commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3412673435
##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/stream/sql/ProcessTableFunctionTest.java:
##########
@@ -513,6 +517,11 @@ private static Stream<ErrorSpec> errorSpecs() {
"SELECT * FROM f(r => TABLE t_watermarked PARTITION BY name, on_time => DESCRIPTOR(ts))",
"Time operations using the `on_time` argument are currently not supported for "
+ "PTFs that consume or produce updates."),
+ ErrorSpec.ofInsertInto(
+ "upsert output into sink without primary key",
+ UpdatingUpsertFunction.class,
+ "INSERT INTO t_no_pk_sink SELECT * FROM f(r => TABLE t_updating PARTITION BY name)",
+ "declare a PRIMARY KEY on the sink"),
Review Comment:
Please add the full error message to the spec. Otherwise reviewers can't see the resulting message after this PR.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "raminqaf (via GitHub)" <gi...@apache.org>.
raminqaf commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3413455699
##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/stream/sql/ProcessTableFunctionTest.java:
##########
@@ -513,6 +517,11 @@ private static Stream<ErrorSpec> errorSpecs() {
"SELECT * FROM f(r => TABLE t_watermarked PARTITION BY name, on_time => DESCRIPTOR(ts))",
Review Comment:
Good catch. The OVER case did reach the new message, but at a non-sink root where both displayed nodes had the same mode. So it read as a mismatch with nothing mismatched.
Updated the if statement so it fires on the root being the sink. Intermediate-operator conflicts now fall back to the old path showing the full plan.
Added two tests: a buried conflict under a Calc (sink boundary, friendly message) and your OVER case (now the plan-dump fallback).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "twalthr (via GitHub)" <gi...@apache.org>.
twalthr merged PR #28403:
URL: https://github.com/apache/flink/pull/28403
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "raminqaf (via GitHub)" <gi...@apache.org>.
raminqaf commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3413270488
##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -1604,6 +1619,21 @@ class FlinkChangelogModeInferenceProgram extends FlinkOptimizeProgram[StreamOpti
modifyKindSetTrait.modifyKindSet
}
+ /** Whether the node or any node in its input subtree produces UPDATE changes. */
+ private def containsUpdates(rel: RelNode): Boolean =
+ getModifyKindSet(rel).contains(ModifyKind.UPDATE) ||
+ rel.getInputs.exists(input => containsUpdates(input))
+
+ /** Renders a node's type and changelog mode, for example "Sink(changelogMode=[NONE])". */
Review Comment:
Now the sink contains the changelogMode
```
Sink(ExpectedChangelogMode=[I,UB,UA,D])
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "raminqaf (via GitHub)" <gi...@apache.org>.
raminqaf commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3413465657
##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -114,9 +114,24 @@ class FlinkChangelogModeInferenceProgram extends FlinkOptimizeProgram[StreamOpti
// step4: sanity check and return non-empty root
if (finalRoot.isEmpty) {
- val plan = FlinkRelOptUtil.toString(root, withChangelogTraits = true)
- throw new TableException(
- "Can't generate a valid execution plan for the given query:\n" + plan)
+ val errorMessage =
+ if (containsUpdates(rootWithModifyKindSet)) {
+ // Point at the failing node and its inputs instead of dumping the whole plan.
+ val conflict = new StringBuilder(describeChangelog(rootWithModifyKindSet))
+ rootWithModifyKindSet.getInputs.foreach(
+ input => conflict.append("\n +- ").append(describeChangelog(input)))
+ "Can't generate a valid execution plan for the given query.\n\n" +
+ "There is a changelog mismatch between two operators. One produces an upsert " +
+ "changelog (UPDATE_AFTER without UPDATE_BEFORE). The other requires a retract " +
+ "changelog (UPDATE_BEFORE and UPDATE_AFTER), for example a sink without a primary " +
+ "key. To resolve it, declare a PRIMARY KEY on the sink, or make the input produce " +
+ "UPDATE_BEFORE.\n\n" +
+ "The conflict is at:\n" + conflict
+ } else {
+ val plan = FlinkRelOptUtil.toString(rootWithModifyKindSet, withChangelogTraits = true)
Review Comment:
Test added. I didn't paste the entire plan for the test. Hope it is fine.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "gustavodemorais (via GitHub)" <gi...@apache.org>.
gustavodemorais commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3412558585
##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -114,9 +114,24 @@ class FlinkChangelogModeInferenceProgram extends FlinkOptimizeProgram[StreamOpti
// step4: sanity check and return non-empty root
if (finalRoot.isEmpty) {
- val plan = FlinkRelOptUtil.toString(root, withChangelogTraits = true)
- throw new TableException(
- "Can't generate a valid execution plan for the given query:\n" + plan)
+ val errorMessage =
+ if (containsUpdates(rootWithModifyKindSet)) {
+ // Point at the failing node and its inputs instead of dumping the whole plan.
+ val conflict = new StringBuilder(describeChangelog(rootWithModifyKindSet))
+ rootWithModifyKindSet.getInputs.foreach(
+ input => conflict.append("\n +- ").append(describeChangelog(input)))
+ "Can't generate a valid execution plan for the given query.\n\n" +
+ "There is a changelog mismatch between two operators. One produces an upsert " +
+ "changelog (UPDATE_AFTER without UPDATE_BEFORE). The other requires a retract " +
+ "changelog (UPDATE_BEFORE and UPDATE_AFTER), for example a sink without a primary " +
+ "key. To resolve it, declare a PRIMARY KEY on the sink, or make the input produce " +
Review Comment:
Otherwise it sounds imperative and like it's a certain fix
```suggestion
"key. In such cases, declare a PRIMARY KEY on the sink, or make the input produce " +
```
##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/stream/sql/ProcessTableFunctionTest.java:
##########
@@ -513,6 +517,11 @@ private static Stream<ErrorSpec> errorSpecs() {
"SELECT * FROM f(r => TABLE t_watermarked PARTITION BY name, on_time => DESCRIPTOR(ts))",
Review Comment:
Try a test like "SELECT name, SUM(count) OVER (PARTITION BY name ORDER BY name) FROM f(...)" and check if the error message makes sense. I think it output no changelog mismatch
##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -114,9 +114,24 @@ class FlinkChangelogModeInferenceProgram extends FlinkOptimizeProgram[StreamOpti
// step4: sanity check and return non-empty root
if (finalRoot.isEmpty) {
- val plan = FlinkRelOptUtil.toString(root, withChangelogTraits = true)
- throw new TableException(
- "Can't generate a valid execution plan for the given query:\n" + plan)
+ val errorMessage =
+ if (containsUpdates(rootWithModifyKindSet)) {
+ // Point at the failing node and its inputs instead of dumping the whole plan.
Review Comment:
I find it hard to grasp that all the error here are related to upsert vs retract mismatches. It first reads like, were there any errors? See if there was an update in the plan and say that's the issue. Not related to the PR but the code itself. Maybe we can add a comment since the code is not super intuitive
##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/stream/sql/ProcessTableFunctionTest.java:
##########
@@ -513,6 +517,11 @@ private static Stream<ErrorSpec> errorSpecs() {
"SELECT * FROM f(r => TABLE t_watermarked PARTITION BY name, on_time => DESCRIPTOR(ts))",
"Time operations using the `on_time` argument are currently not supported for "
+ "PTFs that consume or produce updates."),
+ ErrorSpec.ofInsertInto(
+ "upsert output into sink without primary key",
+ UpdatingUpsertFunction.class,
+ "INSERT INTO t_no_pk_sink SELECT * FROM f(r => TABLE t_updating PARTITION BY name)",
+ "declare a PRIMARY KEY on the sink"),
Review Comment:
Can you assert the rendered conflict block, not just one substring? "The conflict is at:\n..."
##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/stream/sql/ProcessTableFunctionTest.java:
##########
@@ -513,6 +517,11 @@ private static Stream<ErrorSpec> errorSpecs() {
"SELECT * FROM f(r => TABLE t_watermarked PARTITION BY name, on_time => DESCRIPTOR(ts))",
"Time operations using the `on_time` argument are currently not supported for "
+ "PTFs that consume or produce updates."),
+ ErrorSpec.ofInsertInto(
Review Comment:
Can you add a more complex test to see if things make sense? Add a case with the conflict ≥2 levels down (e.g. over-aggregate buried under a projection/filter/join)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "raminqaf (via GitHub)" <gi...@apache.org>.
raminqaf commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3429062187
##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/stream/sql/ProcessTableFunctionTest.java:
##########
@@ -513,6 +517,35 @@ private static Stream<ErrorSpec> errorSpecs() {
"SELECT * FROM f(r => TABLE t_watermarked PARTITION BY name, on_time => DESCRIPTOR(ts))",
"Time operations using the `on_time` argument are currently not supported for "
+ "PTFs that consume or produce updates."),
+ ErrorSpec.ofInsertInto(
+ "upsert output into sink without primary key",
+ UpdatingUpsertFunction.class,
+ "INSERT INTO t_no_pk_sink SELECT * FROM f(r => TABLE t_updating PARTITION BY name)",
+ "There is a changelog mismatch between two operators. "
+ + "One produces an upsert changelog (UPDATE_AFTER without UPDATE_BEFORE). "
+ + "The other requires a retract changelog (UPDATE_BEFORE and UPDATE_AFTER), for example a sink without a primary key. "
+ + "In such cases, ensure that the sink is able to digest upserts where the PRIMARY KEY serves as the upsert key, or make the input produce UPDATE_BEFORE.\n\n"
+ + "The conflict is at:\n"
+ + "Sink(ExpectedChangelogMode=[I,UB,UA,D])\n"
+ + " +- ProcessTableFunction(changelogMode=[I,UA,D])"),
+ ErrorSpec.ofSelect(
+ "upsert conflict that does not surface at a sink",
+ UpdatingUpsertFunction.class,
+ "SELECT name, SUM(`count`) OVER (PARTITION BY name ORDER BY name) "
+ + "FROM f(r => TABLE t_updating PARTITION BY name)",
+ "Can't generate a valid execution plan for the given query:\n"),
+ ErrorSpec.ofInsertInto(
+ "upsert conflict buried below a calc",
+ UpdatingUpsertFunction.class,
+ "INSERT INTO t_no_pk_sink SELECT name, name0, `count`, mode "
+ + "FROM f(r => TABLE t_updating PARTITION BY name) WHERE name0 <> ''",
+ "There is a changelog mismatch between two operators. "
+ + "One produces an upsert changelog (UPDATE_AFTER without UPDATE_BEFORE). "
+ + "The other requires a retract changelog (UPDATE_BEFORE and UPDATE_AFTER), for example a sink without a primary key. "
+ + "In such cases, ensure that the sink is able to digest upserts where the PRIMARY KEY serves as the upsert key, or make the input produce UPDATE_BEFORE.\n\n"
+ + "The conflict is at:\n"
+ + "Sink(ExpectedChangelogMode=[I,UB,UA,D])\n"
Review Comment:
Thanks! Addressed
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "twalthr (via GitHub)" <gi...@apache.org>.
twalthr commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3412663375
##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -114,9 +114,24 @@ class FlinkChangelogModeInferenceProgram extends FlinkOptimizeProgram[StreamOpti
// step4: sanity check and return non-empty root
if (finalRoot.isEmpty) {
- val plan = FlinkRelOptUtil.toString(root, withChangelogTraits = true)
- throw new TableException(
- "Can't generate a valid execution plan for the given query:\n" + plan)
+ val errorMessage =
+ if (containsUpdates(rootWithModifyKindSet)) {
+ // Point at the failing node and its inputs instead of dumping the whole plan.
+ val conflict = new StringBuilder(describeChangelog(rootWithModifyKindSet))
+ rootWithModifyKindSet.getInputs.foreach(
+ input => conflict.append("\n +- ").append(describeChangelog(input)))
+ "Can't generate a valid execution plan for the given query.\n\n" +
+ "There is a changelog mismatch between two operators. One produces an upsert " +
+ "changelog (UPDATE_AFTER without UPDATE_BEFORE). The other requires a retract " +
+ "changelog (UPDATE_BEFORE and UPDATE_AFTER), for example a sink without a primary " +
Review Comment:
Just declaring a PRIMARY KEY won't always solve the problem. I would generalize the message to something like:
```
In such cases, ensure that the sink is able to digest upserts where the PRIMARY KEY serves as the upsert key, or make the input produce UPDATE_BEFORE.
```
##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -1604,6 +1619,21 @@ class FlinkChangelogModeInferenceProgram extends FlinkOptimizeProgram[StreamOpti
modifyKindSetTrait.modifyKindSet
}
+ /** Whether the node or any node in its input subtree produces UPDATE changes. */
+ private def containsUpdates(rel: RelNode): Boolean =
+ getModifyKindSet(rel).contains(ModifyKind.UPDATE) ||
+ rel.getInputs.exists(input => containsUpdates(input))
+
+ /** Renders a node's type and changelog mode, for example "Sink(changelogMode=[NONE])". */
Review Comment:
> Sink(changelogMode=[NONE])
I always found this `NONE` very confusing. For this error message, could we instead print the expected mode by the sink?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "raminqaf (via GitHub)" <gi...@apache.org>.
raminqaf commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3413459361
##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/stream/sql/ProcessTableFunctionTest.java:
##########
@@ -513,6 +517,11 @@ private static Stream<ErrorSpec> errorSpecs() {
"SELECT * FROM f(r => TABLE t_watermarked PARTITION BY name, on_time => DESCRIPTOR(ts))",
"Time operations using the `on_time` argument are currently not supported for "
+ "PTFs that consume or produce updates."),
+ ErrorSpec.ofInsertInto(
Review Comment:
Added a more complex test case
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "raminqaf (via GitHub)" <gi...@apache.org>.
raminqaf commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3413199099
##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/stream/sql/ProcessTableFunctionTest.java:
##########
@@ -513,6 +517,11 @@ private static Stream<ErrorSpec> errorSpecs() {
"SELECT * FROM f(r => TABLE t_watermarked PARTITION BY name, on_time => DESCRIPTOR(ts))",
"Time operations using the `on_time` argument are currently not supported for "
+ "PTFs that consume or produce updates."),
+ ErrorSpec.ofInsertInto(
+ "upsert output into sink without primary key",
+ UpdatingUpsertFunction.class,
+ "INSERT INTO t_no_pk_sink SELECT * FROM f(r => TABLE t_updating PARTITION BY name)",
+ "declare a PRIMARY KEY on the sink"),
Review Comment:
Added the full message to the test
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "flinkbot (via GitHub)" <gi...@apache.org>.
flinkbot commented on PR #28403:
URL: https://github.com/apache/flink/pull/28403#issuecomment-4688943197
<!--
Meta data
{
"version" : 1,
"metaDataEntries" : [ {
"hash" : "cfa459dd4f2548329081592af6b18f9a35e5421f",
"status" : "UNKNOWN",
"url" : "TBD",
"triggerID" : "cfa459dd4f2548329081592af6b18f9a35e5421f",
"triggerType" : "PUSH"
} ]
}-->
## CI report:
* cfa459dd4f2548329081592af6b18f9a35e5421f UNKNOWN
<details>
<summary>Bot commands</summary>
The @flinkbot bot supports the following commands:
- `@flinkbot run azure` re-run the last Azure build
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "raminqaf (via GitHub)" <gi...@apache.org>.
raminqaf commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3413458431
##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -114,9 +114,24 @@ class FlinkChangelogModeInferenceProgram extends FlinkOptimizeProgram[StreamOpti
// step4: sanity check and return non-empty root
if (finalRoot.isEmpty) {
- val plan = FlinkRelOptUtil.toString(root, withChangelogTraits = true)
- throw new TableException(
- "Can't generate a valid execution plan for the given query:\n" + plan)
+ val errorMessage =
+ if (containsUpdates(rootWithModifyKindSet)) {
+ // Point at the failing node and its inputs instead of dumping the whole plan.
Review Comment:
Added a clarifying comment
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "raminqaf (via GitHub)" <gi...@apache.org>.
raminqaf commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3413455699
##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/stream/sql/ProcessTableFunctionTest.java:
##########
@@ -513,6 +517,11 @@ private static Stream<ErrorSpec> errorSpecs() {
"SELECT * FROM f(r => TABLE t_watermarked PARTITION BY name, on_time => DESCRIPTOR(ts))",
Review Comment:
Good catch. The OVER case did reach the new message, but at a non-sink root where both displayed nodes had the same mode — so it read as a mismatch with nothing mismatched.
Updated the if statement so it fires on the root being the sink. Intermediate-operator conflicts now fall back to the old path showing the full plan.
Added two tests: a buried conflict under a Calc (sink boundary, friendly message) and your OVER case (now the plan-dump fallback).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "raminqaf (via GitHub)" <gi...@apache.org>.
raminqaf commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3413277563
##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -114,9 +114,24 @@ class FlinkChangelogModeInferenceProgram extends FlinkOptimizeProgram[StreamOpti
// step4: sanity check and return non-empty root
if (finalRoot.isEmpty) {
- val plan = FlinkRelOptUtil.toString(root, withChangelogTraits = true)
- throw new TableException(
- "Can't generate a valid execution plan for the given query:\n" + plan)
+ val errorMessage =
+ if (containsUpdates(rootWithModifyKindSet)) {
+ // Point at the failing node and its inputs instead of dumping the whole plan.
+ val conflict = new StringBuilder(describeChangelog(rootWithModifyKindSet))
+ rootWithModifyKindSet.getInputs.foreach(
+ input => conflict.append("\n +- ").append(describeChangelog(input)))
+ "Can't generate a valid execution plan for the given query.\n\n" +
+ "There is a changelog mismatch between two operators. One produces an upsert " +
+ "changelog (UPDATE_AFTER without UPDATE_BEFORE). The other requires a retract " +
+ "changelog (UPDATE_BEFORE and UPDATE_AFTER), for example a sink without a primary " +
+ "key. To resolve it, declare a PRIMARY KEY on the sink, or make the input produce " +
Review Comment:
Addressed Timo's feedback on this section
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "raminqaf (via GitHub)" <gi...@apache.org>.
raminqaf commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3413198022
##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -114,9 +114,24 @@ class FlinkChangelogModeInferenceProgram extends FlinkOptimizeProgram[StreamOpti
// step4: sanity check and return non-empty root
if (finalRoot.isEmpty) {
- val plan = FlinkRelOptUtil.toString(root, withChangelogTraits = true)
- throw new TableException(
- "Can't generate a valid execution plan for the given query:\n" + plan)
+ val errorMessage =
+ if (containsUpdates(rootWithModifyKindSet)) {
+ // Point at the failing node and its inputs instead of dumping the whole plan.
+ val conflict = new StringBuilder(describeChangelog(rootWithModifyKindSet))
+ rootWithModifyKindSet.getInputs.foreach(
+ input => conflict.append("\n +- ").append(describeChangelog(input)))
+ "Can't generate a valid execution plan for the given query.\n\n" +
+ "There is a changelog mismatch between two operators. One produces an upsert " +
+ "changelog (UPDATE_AFTER without UPDATE_BEFORE). The other requires a retract " +
+ "changelog (UPDATE_BEFORE and UPDATE_AFTER), for example a sink without a primary " +
Review Comment:
Thanks for the correction. Applied
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "gustavodemorais (via GitHub)" <gi...@apache.org>.
gustavodemorais commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3412982997
##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -114,9 +114,24 @@ class FlinkChangelogModeInferenceProgram extends FlinkOptimizeProgram[StreamOpti
// step4: sanity check and return non-empty root
if (finalRoot.isEmpty) {
- val plan = FlinkRelOptUtil.toString(root, withChangelogTraits = true)
- throw new TableException(
- "Can't generate a valid execution plan for the given query:\n" + plan)
+ val errorMessage =
+ if (containsUpdates(rootWithModifyKindSet)) {
+ // Point at the failing node and its inputs instead of dumping the whole plan.
Review Comment:
Maybe add smth like this as a comment
```
// An empty result means no consistent UpdateKind/DeleteKind assignment exists. When the
// plan carries updates, the only way this happens is an upsert producer (UPDATE_AFTER only)
// feeding a consumer that needs a retract changelog (UPDATE_BEFORE and UPDATE_AFTER), so we
// can point at that mismatch. Otherwise we fall back to dumping the whole plan.
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "raminqaf (via GitHub)" <gi...@apache.org>.
raminqaf commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3413270488
##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -1604,6 +1619,21 @@ class FlinkChangelogModeInferenceProgram extends FlinkOptimizeProgram[StreamOpti
modifyKindSetTrait.modifyKindSet
}
+ /** Whether the node or any node in its input subtree produces UPDATE changes. */
+ private def containsUpdates(rel: RelNode): Boolean =
+ getModifyKindSet(rel).contains(ModifyKind.UPDATE) ||
+ rel.getInputs.exists(input => containsUpdates(input))
+
+ /** Renders a node's type and changelog mode, for example "Sink(changelogMode=[NONE])". */
Review Comment:
Now the sink contains the changelogMode
```
Sink(ChangelogMode=[I,UB,UA,D])
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "gustavodemorais (via GitHub)" <gi...@apache.org>.
gustavodemorais commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3412711930
##########
flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/optimize/program/FlinkChangelogModeInferenceProgram.scala:
##########
@@ -114,9 +114,24 @@ class FlinkChangelogModeInferenceProgram extends FlinkOptimizeProgram[StreamOpti
// step4: sanity check and return non-empty root
if (finalRoot.isEmpty) {
- val plan = FlinkRelOptUtil.toString(root, withChangelogTraits = true)
- throw new TableException(
- "Can't generate a valid execution plan for the given query:\n" + plan)
+ val errorMessage =
+ if (containsUpdates(rootWithModifyKindSet)) {
+ // Point at the failing node and its inputs instead of dumping the whole plan.
+ val conflict = new StringBuilder(describeChangelog(rootWithModifyKindSet))
+ rootWithModifyKindSet.getInputs.foreach(
+ input => conflict.append("\n +- ").append(describeChangelog(input)))
+ "Can't generate a valid execution plan for the given query.\n\n" +
+ "There is a changelog mismatch between two operators. One produces an upsert " +
+ "changelog (UPDATE_AFTER without UPDATE_BEFORE). The other requires a retract " +
+ "changelog (UPDATE_BEFORE and UPDATE_AFTER), for example a sink without a primary " +
+ "key. To resolve it, declare a PRIMARY KEY on the sink, or make the input produce " +
+ "UPDATE_BEFORE.\n\n" +
+ "The conflict is at:\n" + conflict
+ } else {
+ val plan = FlinkRelOptUtil.toString(rootWithModifyKindSet, withChangelogTraits = true)
Review Comment:
Do we have existing tests for this path?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [FLINK-39913][table] Improve the error message when a foreground query emits an upsert changelog [flink]
Posted by "twalthr (via GitHub)" <gi...@apache.org>.
twalthr commented on code in PR #28403:
URL: https://github.com/apache/flink/pull/28403#discussion_r3427502871
##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/plan/stream/sql/ProcessTableFunctionTest.java:
##########
@@ -513,6 +517,35 @@ private static Stream<ErrorSpec> errorSpecs() {
"SELECT * FROM f(r => TABLE t_watermarked PARTITION BY name, on_time => DESCRIPTOR(ts))",
"Time operations using the `on_time` argument are currently not supported for "
+ "PTFs that consume or produce updates."),
+ ErrorSpec.ofInsertInto(
+ "upsert output into sink without primary key",
+ UpdatingUpsertFunction.class,
+ "INSERT INTO t_no_pk_sink SELECT * FROM f(r => TABLE t_updating PARTITION BY name)",
+ "There is a changelog mismatch between two operators. "
+ + "One produces an upsert changelog (UPDATE_AFTER without UPDATE_BEFORE). "
+ + "The other requires a retract changelog (UPDATE_BEFORE and UPDATE_AFTER), for example a sink without a primary key. "
+ + "In such cases, ensure that the sink is able to digest upserts where the PRIMARY KEY serves as the upsert key, or make the input produce UPDATE_BEFORE.\n\n"
+ + "The conflict is at:\n"
+ + "Sink(ExpectedChangelogMode=[I,UB,UA,D])\n"
+ + " +- ProcessTableFunction(changelogMode=[I,UA,D])"),
+ ErrorSpec.ofSelect(
+ "upsert conflict that does not surface at a sink",
+ UpdatingUpsertFunction.class,
+ "SELECT name, SUM(`count`) OVER (PARTITION BY name ORDER BY name) "
+ + "FROM f(r => TABLE t_updating PARTITION BY name)",
+ "Can't generate a valid execution plan for the given query:\n"),
+ ErrorSpec.ofInsertInto(
+ "upsert conflict buried below a calc",
+ UpdatingUpsertFunction.class,
+ "INSERT INTO t_no_pk_sink SELECT name, name0, `count`, mode "
+ + "FROM f(r => TABLE t_updating PARTITION BY name) WHERE name0 <> ''",
+ "There is a changelog mismatch between two operators. "
+ + "One produces an upsert changelog (UPDATE_AFTER without UPDATE_BEFORE). "
+ + "The other requires a retract changelog (UPDATE_BEFORE and UPDATE_AFTER), for example a sink without a primary key. "
+ + "In such cases, ensure that the sink is able to digest upserts where the PRIMARY KEY serves as the upsert key, or make the input produce UPDATE_BEFORE.\n\n"
+ + "The conflict is at:\n"
+ + "Sink(ExpectedChangelogMode=[I,UB,UA,D])\n"
Review Comment:
```suggestion
+ "Sink(expectedChangelogMode=[I,UB,UA,D])\n"
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@flink.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org