Skip to content

Commit 9f443f7

Browse files
acarpente-denodoDavid Stryker
andcommitted
Add SQL Support for MERGE INTO In Presto #20578 (engine-tests)
Automated tests. Cherry-pick of trinodb/trino@cee96c3 Co-authored-by: David Stryker <[email protected]>
1 parent eb3dcb5 commit 9f443f7

File tree

6 files changed

+173
-0
lines changed

6 files changed

+173
-0
lines changed

presto-main-base/src/test/java/com/facebook/presto/metadata/AbstractMockMetadata.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.facebook.presto.spi.ConnectorTableMetadata;
2727
import com.facebook.presto.spi.Constraint;
2828
import com.facebook.presto.spi.MaterializedViewDefinition;
29+
import com.facebook.presto.spi.MergeHandle;
2930
import com.facebook.presto.spi.NewTableLayout;
3031
import com.facebook.presto.spi.SystemTable;
3132
import com.facebook.presto.spi.TableHandle;
@@ -35,6 +36,7 @@
3536
import com.facebook.presto.spi.connector.ConnectorCapabilities;
3637
import com.facebook.presto.spi.connector.ConnectorOutputMetadata;
3738
import com.facebook.presto.spi.connector.ConnectorTableVersion;
39+
import com.facebook.presto.spi.connector.RowChangeParadigm;
3840
import com.facebook.presto.spi.connector.TableFunctionApplicationResult;
3941
import com.facebook.presto.spi.constraints.TableConstraint;
4042
import com.facebook.presto.spi.function.SqlFunction;
@@ -460,6 +462,49 @@ public void finishUpdate(Session session, TableHandle tableHandle, Collection<Sl
460462
throw new UnsupportedOperationException();
461463
}
462464

465+
/**
466+
* Return the row update paradigm supported by the connector on the table or throw
467+
* an exception if row change is not supported.
468+
*/
469+
public RowChangeParadigm getRowChangeParadigm(Session session, TableHandle tableHandle)
470+
{
471+
throw new UnsupportedOperationException();
472+
}
473+
474+
/**
475+
* Get the column handle that will generate row IDs for the merge operation.
476+
* These IDs will be passed to the {@code storeMergedRows()} method of the
477+
* {@link com.facebook.presto.spi.ConnectorMergeSink} that created them.
478+
*/
479+
public ColumnHandle getMergeTargetTableRowIdColumnHandle(Session session, TableHandle tableHandle)
480+
{
481+
throw new UnsupportedOperationException();
482+
}
483+
484+
/**
485+
* Get the physical layout for updated or deleted rows of a MERGE operation.
486+
*/
487+
public Optional<PartitioningHandle> getMergeUpdateLayout(Session session, TableHandle tableHandle)
488+
{
489+
throw new UnsupportedOperationException();
490+
}
491+
492+
/**
493+
* Begin merge query
494+
*/
495+
public MergeHandle beginMerge(Session session, TableHandle tableHandle)
496+
{
497+
throw new UnsupportedOperationException();
498+
}
499+
500+
/**
501+
* Finish merge query
502+
*/
503+
public void finishMerge(Session session, MergeHandle tableHandle, Collection<Slice> fragments, Collection<ComputedStatistics> computedStatistics)
504+
{
505+
throw new UnsupportedOperationException();
506+
}
507+
463508
@Override
464509
public Optional<ConnectorId> getCatalogHandle(Session session, String catalogName)
465510
{

presto-main-base/src/test/java/com/facebook/presto/sql/analyzer/AbstractAnalyzerTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import com.facebook.presto.spi.ColumnMetadata;
4747
import com.facebook.presto.spi.ConnectorId;
4848
import com.facebook.presto.spi.ConnectorTableMetadata;
49+
import com.facebook.presto.spi.MaterializedViewDefinition;
4950
import com.facebook.presto.spi.SchemaTableName;
5051
import com.facebook.presto.spi.WarningCollector;
5152
import com.facebook.presto.spi.analyzer.ViewDefinition;
@@ -81,6 +82,7 @@
8182
import org.testng.annotations.BeforeClass;
8283

8384
import java.util.ArrayList;
85+
import java.util.Collections;
8486
import java.util.List;
8587
import java.util.Optional;
8688
import java.util.function.Consumer;
@@ -337,6 +339,33 @@ public void setup()
337339
ColumnMetadata.builder().setName("z").setType(BIGINT).build())),
338340
false));
339341

342+
// materialized view referencing table in same schema
343+
List<SchemaTableName> baseTables = new ArrayList<>(Collections.singletonList(table2));
344+
MaterializedViewDefinition.TableColumn baseTableColumns = new MaterializedViewDefinition.TableColumn(table2, "a", true);
345+
346+
SchemaTableName materializedTable = new SchemaTableName("s1", "mv1");
347+
MaterializedViewDefinition.TableColumn materializedViewTableColumn = new MaterializedViewDefinition.TableColumn(materializedTable, "a", true);
348+
349+
List<MaterializedViewDefinition.ColumnMapping> columnMappings = Collections.singletonList(
350+
new MaterializedViewDefinition.ColumnMapping(materializedViewTableColumn, Collections.singletonList(baseTableColumns)));
351+
352+
MaterializedViewDefinition materializedViewData1 = new MaterializedViewDefinition(
353+
"select a from t2",
354+
"s1",
355+
"mv1",
356+
baseTables,
357+
Optional.of("user"),
358+
Optional.empty(),
359+
columnMappings,
360+
new ArrayList<>(),
361+
Optional.of(new ArrayList<>(Collections.singletonList("a"))));
362+
363+
ConnectorTableMetadata materializedViewMetadata1 = new ConnectorTableMetadata(
364+
materializedTable, ImmutableList.of(ColumnMetadata.builder().setName("a").setType(BIGINT).build()));
365+
366+
inSetupTransaction(session ->
367+
metadata.createMaterializedView(session, TPCH_CATALOG, materializedViewMetadata1, materializedViewData1, false));
368+
340369
// valid view referencing table in same schema
341370
String viewData1 = JsonCodec.jsonCodec(ViewDefinition.class).toJson(
342371
new ViewDefinition(

presto-main-base/src/test/java/com/facebook/presto/sql/analyzer/TestAnalyzer.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2351,4 +2351,17 @@ public void testTableFunctionRequiredColumns()
23512351
// table s1.t5 has two columns. The second column is hidden. Table function can require a hidden column.
23522352
analyze("SELECT * FROM TABLE(system.required_columns_function(input => TABLE(s1.t5)))");
23532353
}
2354+
2355+
@Test
2356+
public void testInvalidMerge()
2357+
{
2358+
assertFails(MISSING_TABLE, "Table tpch.s1.foo does not exist",
2359+
"MERGE INTO foo USING bar ON foo.id = bar.id WHEN MATCHED THEN UPDATE SET id = bar.id + 1");
2360+
2361+
assertFails(NOT_SUPPORTED, "line 1:1: Merging into views is not supported",
2362+
"MERGE INTO v1 USING t1 ON v1.a = t1.a WHEN MATCHED THEN UPDATE SET id = bar.id + 1");
2363+
2364+
assertFails(NOT_SUPPORTED, "line 1:1: Merging into materialized views is not supported",
2365+
"MERGE INTO mv1 USING t1 ON mv1.a = t1.a WHEN MATCHED THEN UPDATE SET id = bar.id + 1");
2366+
}
23542367
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package com.facebook.presto.sql.planner.iterative.rule;
15+
16+
import com.facebook.presto.spi.SchemaTableName;
17+
import com.facebook.presto.spi.relation.VariableReferenceExpression;
18+
import com.facebook.presto.sql.planner.assertions.PlanMatchPattern;
19+
import com.facebook.presto.sql.planner.iterative.rule.test.BaseRuleTest;
20+
import com.facebook.presto.sql.planner.plan.MergeWriterNode;
21+
import com.google.common.collect.ImmutableList;
22+
import com.google.common.collect.ImmutableMap;
23+
import org.testng.annotations.Test;
24+
25+
import java.util.List;
26+
27+
import static com.facebook.presto.sql.planner.assertions.PlanMatchPattern.node;
28+
import static com.facebook.presto.sql.planner.assertions.PlanMatchPattern.strictProject;
29+
import static com.facebook.presto.sql.planner.assertions.PlanMatchPattern.values;
30+
31+
public class TestPruneMergeSourceColumns
32+
extends BaseRuleTest
33+
{
34+
@Test
35+
public void testPruneInputColumn()
36+
{
37+
tester().assertThat(new PruneMergeSourceColumns())
38+
.on(p -> {
39+
VariableReferenceExpression a = p.variable("a");
40+
VariableReferenceExpression mergeRow = p.variable("merge_row");
41+
VariableReferenceExpression rowId = p.variable("row_id");
42+
VariableReferenceExpression partialRows = p.variable("partial_rows");
43+
VariableReferenceExpression fragment = p.variable("fragment");
44+
List<VariableReferenceExpression> mergeProcessorProjectedSymbols = ImmutableList.of(mergeRow, rowId);
45+
return p.merge(
46+
new SchemaTableName("schema", "table"),
47+
p.values(a, mergeRow, rowId),
48+
mergeProcessorProjectedSymbols,
49+
ImmutableList.of(partialRows, fragment));
50+
})
51+
.matches(
52+
node(
53+
MergeWriterNode.class,
54+
strictProject(
55+
ImmutableMap.of(
56+
"row_id", PlanMatchPattern.expression("row_id"),
57+
"merge_row", PlanMatchPattern.expression("merge_row")),
58+
values("a", "merge_row", "row_id"))));
59+
}
60+
61+
@Test
62+
public void testDoNotPruneRowId()
63+
{
64+
tester().assertThat(new PruneMergeSourceColumns())
65+
.on(p -> {
66+
VariableReferenceExpression mergeRow = p.variable("merge_row");
67+
VariableReferenceExpression rowId = p.variable("row_id");
68+
VariableReferenceExpression partialRows = p.variable("partial_rows");
69+
VariableReferenceExpression fragment = p.variable("fragment");
70+
List<VariableReferenceExpression> mergeProcessorProjectedSymbols = ImmutableList.of(mergeRow, rowId);
71+
return p.merge(
72+
new SchemaTableName("schema", "table"),
73+
p.values(mergeRow, rowId),
74+
mergeProcessorProjectedSymbols,
75+
ImmutableList.of(partialRows, fragment));
76+
})
77+
.doesNotFire();
78+
}
79+
}

presto-main-base/src/test/java/com/facebook/presto/sql/planner/iterative/rule/test/PlanBuilder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.facebook.presto.spi.SchemaTableName;
2727
import com.facebook.presto.spi.TableHandle;
2828
import com.facebook.presto.spi.WarningCollector;
29+
import com.facebook.presto.spi.connector.RowChangeParadigm;
2930
import com.facebook.presto.spi.constraints.TableConstraint;
3031
import com.facebook.presto.spi.function.FunctionHandle;
3132
import com.facebook.presto.spi.plan.AggregationNode;
@@ -63,6 +64,8 @@
6364
import com.facebook.presto.spi.plan.TableFinishNode;
6465
import com.facebook.presto.spi.plan.TableScanNode;
6566
import com.facebook.presto.spi.plan.TableWriterNode;
67+
import com.facebook.presto.spi.plan.TableWriterNode.MergeParadigmAndTypes;
68+
import com.facebook.presto.spi.plan.TableWriterNode.MergeTarget;
6669
import com.facebook.presto.spi.plan.TopNNode;
6770
import com.facebook.presto.spi.plan.UnionNode;
6871
import com.facebook.presto.spi.plan.UnnestNode;
@@ -84,6 +87,7 @@
8487
import com.facebook.presto.sql.planner.plan.ExchangeNode;
8588
import com.facebook.presto.sql.planner.plan.GroupIdNode;
8689
import com.facebook.presto.sql.planner.plan.LateralJoinNode;
90+
import com.facebook.presto.sql.planner.plan.MergeWriterNode;
8791
import com.facebook.presto.sql.planner.plan.OffsetNode;
8892
import com.facebook.presto.sql.planner.plan.RemoteSourceNode;
8993
import com.facebook.presto.sql.planner.plan.RowNumberNode;
@@ -113,6 +117,7 @@
113117

114118
import static com.facebook.presto.common.block.SortOrder.ASC_NULLS_FIRST;
115119
import static com.facebook.presto.common.type.BigintType.BIGINT;
120+
import static com.facebook.presto.common.type.IntegerType.INTEGER;
116121
import static com.facebook.presto.common.type.UnknownType.UNKNOWN;
117122
import static com.facebook.presto.common.type.VarbinaryType.VARBINARY;
118123
import static com.facebook.presto.spi.plan.ExchangeEncoding.COLUMNAR;

presto-spi/src/test/java/com/facebook/presto/spi/connector/classloader/TestClassLoaderSafeWrappers.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414
package com.facebook.presto.spi.connector.classloader;
1515

16+
import com.facebook.presto.spi.ConnectorMergeSink;
1617
import com.facebook.presto.spi.ConnectorPageSink;
1718
import com.facebook.presto.spi.connector.ConnectorMetadata;
1819
import com.facebook.presto.spi.connector.ConnectorNodePartitioningProvider;
@@ -34,5 +35,6 @@ public void testAllMethodsOverridden()
3435
assertAllMethodsOverridden(ConnectorPageSourceProvider.class, ClassLoaderSafeConnectorPageSourceProvider.class);
3536
assertAllMethodsOverridden(ConnectorSplitManager.class, ClassLoaderSafeConnectorSplitManager.class);
3637
assertAllMethodsOverridden(ConnectorNodePartitioningProvider.class, ClassLoaderSafeNodePartitioningProvider.class);
38+
assertAllMethodsOverridden(ConnectorMergeSink.class, ClassLoaderSafeConnectorMergeSink.class);
3739
}
3840
}

0 commit comments

Comments
 (0)