github-actions[bot] commented on code in PR #69488:
URL: https://github.com/apache/doris/pull/69488#discussion_r4376629863
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java:
##########
@@ -477,15 +491,67 @@ private static Plan normalizePlanWithoutLock(LogicalPlan
plan, TableIf table,
}
static List<Column> connectorWriteSchema(TableIf table, boolean full) {
+ return pinnedConnectorWriteSchema(table).orElseGet(() ->
table.getBaseSchema(full));
+ }
+
+ private static Optional<List<Column>> pinnedConnectorWriteSchema(TableIf
table) {
ConnectContext context = ConnectContext.get();
- if (context != null && context.getStatementContext() != null) {
- Optional<List<Column>> pinned =
-
context.getStatementContext().getConnectorWriteSchema(table.getId());
- if (pinned.isPresent()) {
- return pinned.get();
- }
+ if (context == null || context.getStatementContext() == null) {
+ return Optional.empty();
}
- return table.getBaseSchema(full);
+ return
context.getStatementContext().getConnectorWriteSchema(table.getId());
+ }
+
+ /**
+ * The pinned writer schema of a target whose column defaults apply to
writes only. The read schema of such a
+ * table carries no defaults, so DEFAULT(column) in an INSERT into it must
resolve against this schema.
+ */
+ private static Optional<List<Column>> writeOnlyDefaultColumns(TableIf
table) {
+ if (!(table instanceof PluginDrivenExternalTable)
+ || !((PluginDrivenExternalTable)
table).hasWriteOnlyDefaults()) {
+ return Optional.empty();
+ }
+ return pinnedConnectorWriteSchema(table);
+ }
+
+ /** Resolve DEFAULT(column) in one inserted value by name against the
target's pinned writer schema. */
+ private static NamedExpression resolveDefaultReferences(NamedExpression
value,
+ Optional<List<Column>> writeOnlyDefaultColumns, TableIf table,
List<String> targetNameParts) {
+ if (!writeOnlyDefaultColumns.isPresent()) {
+ return value;
+ }
+ return (NamedExpression)
ConnectorWriteSchemaUtils.resolveDefaultReferences(value,
+ writeOnlyDefaultColumns.get(), (ExternalTable) table,
ConnectContext.get(), targetNameParts, null);
+ }
+
+ /**
+ * Resolve DEFAULT(column) in the select lists of an INSERT ... SELECT by
name against the target's pinned
+ * writer schema, before the source relations are bound, so it names a
target column whatever the source is.
+ * A derived table in FROM is a query of its own: DEFAULT(column) in it
names a column of its own FROM clause,
+ * as without this resolution, so it is left alone.
+ */
+ private static Plan resolveSelectDefaultReferences(Plan query,
Optional<List<Column>> writeOnlyDefaultColumns,
+ TableIf table, List<String> targetNameParts) {
+ if (query instanceof LogicalSubQueryAlias) {
+ return query;
+ }
+ Plan plan = query.withChildren(child -> resolveSelectDefaultReferences(
+ child, writeOnlyDefaultColumns, table, targetNameParts));
+ if (plan instanceof LogicalProject) {
+ LogicalProject<?> project = (LogicalProject<?>) plan;
+ return project.withProjects(project.getProjects().stream()
+ .map(projection -> resolveDefaultReferences(
Review Comment:
[P2] Resolve defaults inside SELECT star replacements
Let OLAP `src(c INT DEFAULT 7)` contain one row and Iceberg target `t(c
INT)` have pinned write-default `9`:
```sql
INSERT INTO t(c) SELECT * REPLACE(DEFAULT(c) AS c) FROM src;
```
The reduced parsed plan is `Sink(t.c) ->
Project(UnboundStar{replacedAlias=[DEFAULT(c) AS c]}) -> Scan(src.c)`.
`UnboundStar` is a leaf and stores replacement aliases outside its expression
children, so `resolveDefaultReferences` never visits this DEFAULT.
`BindExpression.bindProject` later binds the replacement against `src`, and
`RewriteDefaultExpression` produces `Project(7 AS c)`, silently writing 7; the
equivalent direct `SELECT DEFAULT(c) FROM src` now writes the target's 9.
Normalize `getReplacedAlias()` against the pinned target before binding and add
coverage with different source/target defaults. This is distinct from the
existing aggregate/CTE/subquery omission: the outer LogicalProject is visited,
but its star-replacement payload is skipped.
--
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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]