morningman commented on code in PR #69488:
URL: https://github.com/apache/doris/pull/69488#discussion_r4376106072
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java:
##########
@@ -477,15 +490,62 @@ 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
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 table.getBaseSchema(full);
+ 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.
+ */
+ private static Plan resolveSelectDefaultReferences(Plan query,
Optional<List<Column>> writeOnlyDefaultColumns,
+ TableIf table, List<String> targetNameParts) {
+ return query.rewriteUp(plan -> {
Review Comment:
Fixed in 724071d42a8. `resolveSelectDefaultReferences` no longer walks into
a `LogicalSubQueryAlias`: a derived table in FROM is a query of its own, so
`DEFAULT(column)` in it is left to binding and names a column of that table's
own FROM clause, qualified (`DEFAULT(src.c)`) or not, as on master. The rest of
the walk is unchanged and still bottom-up, so the INSERT's own select lists,
set operation branches included, still resolve against the pinned writer schema.
`InsertUtilsTest#writeOnlyDefaultInDerivedTableNamesItsOwnSource` covers an
unqualified and a qualified `DEFAULT(score)` inside a derived table while the
outer `DEFAULT(name)` resolves to the pinned default, and a UNION whose first
branch resolves and whose second branch reads a derived table. With the
previous `rewriteUp` walk it fails on the first case: the inner reference
became the target's default 9. branch-4.2's
`InsertUtils#resolveIcebergSelectDefaultReferences` walks the plan the same
way, so it has the same problem; I'll pass that on.
--
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]