This is an automated email from the ASF dual-hosted git repository.

junhao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/paimon-trino.git


The following commit(s) were added to refs/heads/main by this push:
     new 652d2a7  Support trino query paimon file index for map type with 
map-keys (#67)
652d2a7 is described below

commit 652d2a797141ae6b9ff0aa30eff3ed131fae808a
Author: Jason Zhang <[email protected]>
AuthorDate: Mon May 6 14:49:19 2024 +0800

    Support trino query paimon file index for map type with map-keys (#67)
    
    
    ---------
    
    Co-authored-by: yilong.zyl <[email protected]>
    Co-authored-by: yejunhao <[email protected]>
---
 .../apache/paimon/trino/TrinoFilterConverter.java  |  45 +++-
 .../apache/paimon/trino/TrinoFilterExtractor.java  | 242 +++++++++++++++++++++
 .../org/apache/paimon/trino/TrinoMetadata.java     |  41 +---
 .../apache/paimon/trino/catalog/TrinoCatalog.java  |  25 +++
 .../paimon/trino/TestTrinoFilterExtractor.java     |  96 ++++++++
 pom.xml                                            |  16 +-
 6 files changed, 428 insertions(+), 37 deletions(-)

diff --git 
a/paimon-trino-common/src/main/java/org/apache/paimon/trino/TrinoFilterConverter.java
 
b/paimon-trino-common/src/main/java/org/apache/paimon/trino/TrinoFilterConverter.java
index a690fca..50060b7 100644
--- 
a/paimon-trino-common/src/main/java/org/apache/paimon/trino/TrinoFilterConverter.java
+++ 
b/paimon-trino-common/src/main/java/org/apache/paimon/trino/TrinoFilterConverter.java
@@ -21,6 +21,9 @@ package org.apache.paimon.trino;
 import org.apache.paimon.data.BinaryString;
 import org.apache.paimon.data.Decimal;
 import org.apache.paimon.data.Timestamp;
+import org.apache.paimon.fileindex.FileIndexOptions;
+import org.apache.paimon.predicate.In;
+import org.apache.paimon.predicate.LeafPredicate;
 import org.apache.paimon.predicate.Predicate;
 import org.apache.paimon.predicate.PredicateBuilder;
 import org.apache.paimon.types.RowType;
@@ -103,10 +106,20 @@ public class TrinoFilterConverter {
             TrinoColumnHandle columnHandle = entry.getKey();
             Domain domain = entry.getValue();
             String field = columnHandle.getColumnName();
+            Optional<Integer> nestedColumn = 
FileIndexOptions.topLevelIndexOfNested(field);
+            if (nestedColumn.isPresent()) {
+                int position = nestedColumn.get();
+                field = field.substring(0, position);
+            }
             int index = fieldNames.indexOf(field);
             if (index != -1) {
                 try {
-                    conjuncts.add(toPredicate(index, 
columnHandle.getTrinoType(), domain));
+                    conjuncts.add(
+                            toPredicate(
+                                    index,
+                                    columnHandle.getColumnName(),
+                                    columnHandle.getTrinoType(),
+                                    domain));
                     acceptedDomains.put(columnHandle, domain);
                     continue;
                 } catch (UnsupportedOperationException exception) {
@@ -124,7 +137,7 @@ public class TrinoFilterConverter {
         return Optional.of(and(conjuncts));
     }
 
-    private Predicate toPredicate(int columnIndex, Type type, Domain domain) {
+    private Predicate toPredicate(int columnIndex, String field, Type type, 
Domain domain) {
         if (domain.isAll()) {
             // TODO alwaysTrue
             throw new UnsupportedOperationException();
@@ -146,13 +159,35 @@ public class TrinoFilterConverter {
         }
 
         // TODO support structural types
-        if (type instanceof ArrayType
-                || type instanceof MapType
-                || type instanceof io.trino.spi.type.RowType) {
+        if (type instanceof ArrayType || type instanceof 
io.trino.spi.type.RowType) {
             // Fail fast. Ignoring expression could lead to data loss in case 
of deletions.
             throw new UnsupportedOperationException();
         }
 
+        if (type instanceof MapType) {
+            List<Range> orderedRanges = 
domain.getValues().getRanges().getOrderedRanges();
+            List<Object> values = new ArrayList<>();
+            List<Predicate> predicates = new ArrayList<>();
+            for (Range range : orderedRanges) {
+                if (range.isSingleValue()) {
+                    values.add(
+                            getLiteralValue(
+                                    ((MapType) type).getValueType(), 
range.getLowBoundedValue()));
+                }
+            }
+            if (!values.isEmpty()) {
+                Predicate predicate =
+                        new LeafPredicate(
+                                In.INSTANCE,
+                                TrinoTypeUtils.toPaimonType(type),
+                                columnIndex,
+                                field,
+                                values);
+                predicates.add(predicate);
+            }
+            return or(predicates);
+        }
+
         if (type.isOrderable()) {
             List<Range> orderedRanges = 
domain.getValues().getRanges().getOrderedRanges();
             List<Object> values = new ArrayList<>();
diff --git 
a/paimon-trino-common/src/main/java/org/apache/paimon/trino/TrinoFilterExtractor.java
 
b/paimon-trino-common/src/main/java/org/apache/paimon/trino/TrinoFilterExtractor.java
new file mode 100644
index 0000000..95e5957
--- /dev/null
+++ 
b/paimon-trino-common/src/main/java/org/apache/paimon/trino/TrinoFilterExtractor.java
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.trino;
+
+import org.apache.paimon.shade.guava30.com.google.common.collect.ImmutableList;
+import org.apache.paimon.shade.guava30.com.google.common.collect.Maps;
+import org.apache.paimon.trino.catalog.TrinoCatalog;
+
+import io.airlift.slice.Slice;
+import io.trino.spi.connector.ColumnHandle;
+import io.trino.spi.connector.Constraint;
+import io.trino.spi.expression.Call;
+import io.trino.spi.expression.Constant;
+import io.trino.spi.expression.Variable;
+import io.trino.spi.predicate.Domain;
+import io.trino.spi.predicate.Range;
+import io.trino.spi.predicate.SortedRangeSet;
+import io.trino.spi.predicate.TupleDomain;
+import io.trino.spi.type.ArrayType;
+import io.trino.spi.type.MapType;
+import io.trino.spi.type.Type;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import static io.trino.spi.expression.StandardFunctions.AND_FUNCTION_NAME;
+import static 
io.trino.spi.expression.StandardFunctions.EQUAL_OPERATOR_FUNCTION_NAME;
+import static 
io.trino.spi.expression.StandardFunctions.IN_PREDICATE_FUNCTION_NAME;
+import static org.apache.paimon.fileindex.FileIndexCommon.toMapKey;
+
+/** Extract filter from trino. */
+public class TrinoFilterExtractor {
+
+    public static final String TRINO_MAP_ELEMENT_AT_FUNCTION_NAME = 
"element_at";
+
+    /** Extract filter from trino , include ExpressionFilter. */
+    public static Optional<TrinoFilter> extract(
+            TrinoCatalog catalog, TrinoTableHandle trinoTableHandle, 
Constraint constraint) {
+
+        TupleDomain<TrinoColumnHandle> oldFilter = 
trinoTableHandle.getFilter();
+        TupleDomain<TrinoColumnHandle> newFilter =
+                constraint
+                        .getSummary()
+                        .transformKeys(TrinoColumnHandle.class::cast)
+                        .intersect(oldFilter);
+
+        if (oldFilter.equals(newFilter)) {
+            return Optional.empty();
+        }
+
+        Map<TrinoColumnHandle, Domain> trinoColumnHandleForExpressionFilter =
+                extractTrinoColumnHandleForExpressionFilter(constraint);
+
+        LinkedHashMap<TrinoColumnHandle, Domain> acceptedDomains = new 
LinkedHashMap<>();
+        LinkedHashMap<TrinoColumnHandle, Domain> unsupportedDomains = new 
LinkedHashMap<>();
+        new TrinoFilterConverter(trinoTableHandle.table(catalog).rowType())
+                .convert(newFilter, acceptedDomains, unsupportedDomains);
+
+        List<String> partitionKeys = 
trinoTableHandle.table(catalog).partitionKeys();
+        LinkedHashMap<TrinoColumnHandle, Domain> unenforcedDomains = new 
LinkedHashMap<>();
+        acceptedDomains.forEach(
+                (columnHandle, domain) -> {
+                    if (!partitionKeys.contains(columnHandle.getColumnName())) 
{
+                        unenforcedDomains.put(columnHandle, domain);
+                    }
+                });
+
+        acceptedDomains.putAll(trinoColumnHandleForExpressionFilter);
+
+        @SuppressWarnings({"unchecked", "rawtypes"})
+        TupleDomain<ColumnHandle> remain =
+                (TupleDomain)
+                        TupleDomain.withColumnDomains(unsupportedDomains)
+                                
.intersect(TupleDomain.withColumnDomains(unenforcedDomains));
+
+        return Optional.of(new 
TrinoFilter(TupleDomain.withColumnDomains(acceptedDomains), remain));
+    }
+
+    /**
+     * Extract Expression filter from trino Constraint. Extract Trino 
Expression filter ( e.g.
+     * element_at(jsonmap, 'a') = '1' ) to TrinoColumnHandle.
+     */
+    public static Map<TrinoColumnHandle, Domain> 
extractTrinoColumnHandleForExpressionFilter(
+            Constraint constraint) {
+        Map<TrinoColumnHandle, Domain> expressionPredicates = 
Collections.emptyMap();
+
+        if (constraint.getExpression() instanceof Call) {
+            Call expression = (Call) constraint.getExpression();
+            Map<String, ColumnHandle> assignments = 
constraint.getAssignments();
+
+            if 
(expression.getFunctionName().equals(EQUAL_OPERATOR_FUNCTION_NAME)) {
+                expressionPredicates = handleExpressionEqualOrIn(assignments, 
expression, false);
+            } else if 
(expression.getFunctionName().equals(IN_PREDICATE_FUNCTION_NAME)) {
+                expressionPredicates = handleExpressionEqualOrIn(assignments, 
expression, true);
+            } else if (expression.getFunctionName().equals(AND_FUNCTION_NAME)) 
{
+                expressionPredicates = handleAndArguments(assignments, 
expression);
+            }
+            // TODO: Support "or" clause
+        }
+        return expressionPredicates;
+    }
+
+    /** Expression filter support the case of "AND" and "IN". */
+    private static Map<TrinoColumnHandle, Domain> handleAndArguments(
+            Map<String, ColumnHandle> assignments, Call expression) {
+        Map<TrinoColumnHandle, Domain> expressionPredicates = new HashMap<>();
+
+        expression.getArguments().stream()
+                .map(argument -> (Call) argument)
+                .forEach(
+                        argument -> {
+                            if 
(argument.getFunctionName().equals(EQUAL_OPERATOR_FUNCTION_NAME)) {
+                                expressionPredicates.putAll(
+                                        handleExpressionEqualOrIn(assignments, 
argument, false));
+                            } else if (argument.getFunctionName()
+                                    .equals(IN_PREDICATE_FUNCTION_NAME)) {
+                                expressionPredicates.putAll(
+                                        handleExpressionEqualOrIn(assignments, 
argument, true));
+                            }
+                        });
+
+        return expressionPredicates;
+    }
+
+    private static Map<TrinoColumnHandle, Domain> handleExpressionEqualOrIn(
+            Map<String, ColumnHandle> assignments, Call expression, boolean 
inClause) {
+
+        Call elementAtExpression = (Call) expression.getArguments().get(0);
+
+        String functionName = elementAtExpression.getFunctionName().getName();
+
+        switch (functionName) {
+            case TRINO_MAP_ELEMENT_AT_FUNCTION_NAME:
+                {
+                    Variable columnExpression =
+                            (Variable) 
elementAtExpression.getArguments().get(0);
+                    Constant columnKey = (Constant) 
elementAtExpression.getArguments().get(1);
+
+                    Constant elementAtValue = (Constant) 
expression.getArguments().get(1);
+                    List<Range> values;
+                    Type elementType;
+                    if (inClause) {
+                        elementType = ((ArrayType) 
elementAtValue.getType()).getElementType();
+                        values =
+                                elementAtValue.getChildren().stream()
+                                        .filter(a -> ((Constant) a).getValue() 
!= null)
+                                        .map(
+                                                arguemnt ->
+                                                        Range.equal(
+                                                                
arguemnt.getType(),
+                                                                ((Constant) 
arguemnt).getValue()))
+                                        .collect(Collectors.toList());
+                    } else {
+                        elementType = elementAtValue.getType();
+                        values =
+                                elementAtValue.getValue() == null
+                                        ? Collections.emptyList()
+                                        : ImmutableList.of(
+                                                Range.equal(
+                                                        
elementAtValue.getType(),
+                                                        
elementAtValue.getValue()));
+                    }
+                    if (columnKey.getValue() == null) {
+                        throw new RuntimeException("Expression pares failed: " 
+ expression);
+                    }
+
+                    return handleElementAtArguments(
+                            assignments,
+                            columnExpression.getName(),
+                            ((Slice) columnKey.getValue()).toStringUtf8(),
+                            elementType,
+                            values);
+                }
+            default:
+                {
+                    return Collections.emptyMap();
+                }
+        }
+    }
+
+    /** Using paimon, trino only supports element_at function to extract 
values from map type. */
+    private static Map<TrinoColumnHandle, Domain> handleElementAtArguments(
+            Map<String, ColumnHandle> assignments,
+            String columnName,
+            String nestedName,
+            Type elementType,
+            List<Range> ranges) {
+        Map<TrinoColumnHandle, Domain> expressionPredicates = 
Maps.newHashMap();
+        TrinoColumnHandle trinoColumnHandle = (TrinoColumnHandle) 
assignments.get(columnName);
+        Type trinoType = trinoColumnHandle.getTrinoType();
+        if (trinoType instanceof MapType) {
+            expressionPredicates.put(
+                    TrinoColumnHandle.of(
+                            toMapKey(columnName, nestedName),
+                            TrinoTypeUtils.toPaimonType(trinoType)),
+                    Domain.create(SortedRangeSet.copyOf(elementType, ranges), 
false));
+        }
+        return expressionPredicates;
+    }
+
+    /** TrinoFilter for paimon trinoMetadata applyFilter. */
+    public static class TrinoFilter {
+
+        private final TupleDomain<TrinoColumnHandle> filter;
+        private final TupleDomain<ColumnHandle> remainFilter;
+
+        public TrinoFilter(
+                TupleDomain<TrinoColumnHandle> filter, 
TupleDomain<ColumnHandle> remainFilter) {
+            this.filter = filter;
+            this.remainFilter = remainFilter;
+        }
+
+        public TupleDomain<TrinoColumnHandle> getFilter() {
+            return filter;
+        }
+
+        public TupleDomain<ColumnHandle> getRemainFilter() {
+            return remainFilter;
+        }
+    }
+}
diff --git 
a/paimon-trino-common/src/main/java/org/apache/paimon/trino/TrinoMetadata.java 
b/paimon-trino-common/src/main/java/org/apache/paimon/trino/TrinoMetadata.java
index 0d8510e..926ca64 100644
--- 
a/paimon-trino-common/src/main/java/org/apache/paimon/trino/TrinoMetadata.java
+++ 
b/paimon-trino-common/src/main/java/org/apache/paimon/trino/TrinoMetadata.java
@@ -45,7 +45,6 @@ import io.trino.spi.connector.SchemaTableName;
 import io.trino.spi.connector.SchemaTablePrefix;
 import io.trino.spi.expression.ConnectorExpression;
 import io.trino.spi.predicate.Domain;
-import io.trino.spi.predicate.TupleDomain;
 import io.trino.spi.security.TrinoPrincipal;
 import io.trino.spi.type.LongTimestampWithTimeZone;
 import io.trino.spi.type.TimestampWithTimeZoneType;
@@ -423,38 +422,18 @@ public class TrinoMetadata implements ConnectorMetadata {
             ConnectorSession session, ConnectorTableHandle handle, Constraint 
constraint) {
         catalog.initSession(session);
         TrinoTableHandle trinoTableHandle = (TrinoTableHandle) handle;
-        TupleDomain<TrinoColumnHandle> oldFilter = 
trinoTableHandle.getFilter();
-        TupleDomain<TrinoColumnHandle> newFilter =
-                constraint
-                        .getSummary()
-                        .transformKeys(TrinoColumnHandle.class::cast)
-                        .intersect(oldFilter);
-        if (oldFilter.equals(newFilter)) {
+        Optional<TrinoFilterExtractor.TrinoFilter> extract =
+                TrinoFilterExtractor.extract(catalog, trinoTableHandle, 
constraint);
+        if (extract.isPresent()) {
+            TrinoFilterExtractor.TrinoFilter trinoFilter = extract.get();
+            return Optional.of(
+                    new ConstraintApplicationResult<>(
+                            trinoTableHandle.copy(trinoFilter.getFilter()),
+                            trinoFilter.getRemainFilter(),
+                            false));
+        } else {
             return Optional.empty();
         }
-
-        LinkedHashMap<TrinoColumnHandle, Domain> acceptedDomains = new 
LinkedHashMap<>();
-        LinkedHashMap<TrinoColumnHandle, Domain> unsupportedDomains = new 
LinkedHashMap<>();
-        new TrinoFilterConverter(trinoTableHandle.table(catalog).rowType())
-                .convert(newFilter, acceptedDomains, unsupportedDomains);
-
-        List<String> partitionKeys = 
trinoTableHandle.table(catalog).partitionKeys();
-        LinkedHashMap<TrinoColumnHandle, Domain> unenforcedDomains = new 
LinkedHashMap<>();
-        acceptedDomains.forEach(
-                (columnHandle, domain) -> {
-                    if (!partitionKeys.contains(columnHandle.getColumnName())) 
{
-                        unenforcedDomains.put(columnHandle, domain);
-                    }
-                });
-
-        @SuppressWarnings({"unchecked", "rawtypes"})
-        TupleDomain<ColumnHandle> remain =
-                (TupleDomain)
-                        TupleDomain.withColumnDomains(unsupportedDomains)
-                                
.intersect(TupleDomain.withColumnDomains(unenforcedDomains));
-
-        return Optional.of(
-                new 
ConstraintApplicationResult<>(trinoTableHandle.copy(newFilter), remain, false));
     }
 
     @Override
diff --git 
a/paimon-trino-common/src/main/java/org/apache/paimon/trino/catalog/TrinoCatalog.java
 
b/paimon-trino-common/src/main/java/org/apache/paimon/trino/catalog/TrinoCatalog.java
index e02abb4..2caab17 100644
--- 
a/paimon-trino-common/src/main/java/org/apache/paimon/trino/catalog/TrinoCatalog.java
+++ 
b/paimon-trino-common/src/main/java/org/apache/paimon/trino/catalog/TrinoCatalog.java
@@ -26,6 +26,7 @@ import org.apache.paimon.catalog.CatalogFactory;
 import org.apache.paimon.catalog.CatalogLockContext;
 import org.apache.paimon.catalog.CatalogLockFactory;
 import org.apache.paimon.catalog.Identifier;
+import org.apache.paimon.fs.FileIO;
 import org.apache.paimon.metastore.MetastoreClient;
 import org.apache.paimon.options.Options;
 import org.apache.paimon.schema.Schema;
@@ -95,6 +96,30 @@ public class TrinoCatalog implements Catalog {
         }
     }
 
+    @Override
+    public String warehouse() {
+        if (!inited) {
+            throw new RuntimeException("Not inited yet.");
+        }
+        return current.warehouse();
+    }
+
+    @Override
+    public Map<String, String> options() {
+        if (!inited) {
+            throw new RuntimeException("Not inited yet.");
+        }
+        return current.options();
+    }
+
+    @Override
+    public FileIO fileIO() {
+        if (!inited) {
+            throw new RuntimeException("Not inited yet.");
+        }
+        return current.fileIO();
+    }
+
     @Override
     public Optional<CatalogLockFactory> lockFactory() {
         return current.lockFactory();
diff --git 
a/paimon-trino-common/src/test/java/org/apache/paimon/trino/TestTrinoFilterExtractor.java
 
b/paimon-trino-common/src/test/java/org/apache/paimon/trino/TestTrinoFilterExtractor.java
new file mode 100644
index 0000000..a54dbef
--- /dev/null
+++ 
b/paimon-trino-common/src/test/java/org/apache/paimon/trino/TestTrinoFilterExtractor.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.trino;
+
+import org.apache.paimon.shade.guava30.com.google.common.collect.Maps;
+import org.apache.paimon.types.DataTypes;
+
+import io.airlift.slice.Slice;
+import io.airlift.slice.Slices;
+import io.trino.spi.connector.ColumnHandle;
+import io.trino.spi.connector.Constraint;
+import io.trino.spi.expression.Call;
+import io.trino.spi.expression.ConnectorExpression;
+import io.trino.spi.expression.Constant;
+import io.trino.spi.expression.FunctionName;
+import io.trino.spi.expression.StandardFunctions;
+import io.trino.spi.expression.Variable;
+import io.trino.spi.predicate.Domain;
+import io.trino.spi.predicate.TupleDomain;
+import io.trino.spi.type.Type;
+import io.trino.spi.type.VarcharType;
+import org.testng.annotations.Test;
+
+import java.util.List;
+import java.util.Map;
+
+import static io.trino.spi.type.BooleanType.BOOLEAN;
+import static io.trino.type.InternalTypeManager.TESTING_TYPE_MANAGER;
+import static org.apache.paimon.fileindex.FileIndexCommon.toMapKey;
+import static 
org.apache.paimon.trino.TrinoFilterExtractor.TRINO_MAP_ELEMENT_AT_FUNCTION_NAME;
+import static org.assertj.core.api.Assertions.assertThat;
+
+/** The test of TestTrinoFilterExtractor. */
+public class TestTrinoFilterExtractor {
+
+    @Test
+    public void testExtractTrinoColumnHandleForExpressionFilter() {
+        TupleDomain<ColumnHandle> summary = TupleDomain.all();
+        Type mapType = 
TESTING_TYPE_MANAGER.fromSqlType("map<varchar,varchar>");
+        String columnName = "map";
+        String mapKeyName = "key";
+        String constantValue = "value";
+        Slice value = Slices.utf8Slice(constantValue);
+        Call elemetAtFuntion =
+                new Call(
+                        BOOLEAN,
+                        new FunctionName(TRINO_MAP_ELEMENT_AT_FUNCTION_NAME),
+                        List.of(
+                                new Variable(columnName, mapType),
+                                new Constant(
+                                        
io.airlift.slice.Slices.utf8Slice(mapKeyName),
+                                        
VarcharType.createUnboundedVarcharType())));
+        ConnectorExpression expression =
+                new Call(
+                        BOOLEAN,
+                        StandardFunctions.EQUAL_OPERATOR_FUNCTION_NAME,
+                        List.of(
+                                elemetAtFuntion,
+                                new Constant(value, 
VarcharType.createUnboundedVarcharType())));
+        Map<String, ColumnHandle> assignments = Maps.newHashMap();
+        assignments.put(
+                columnName,
+                TrinoColumnHandle.of(
+                        columnName, DataTypes.MAP(DataTypes.STRING(), 
DataTypes.STRING())));
+        Constraint constraint = new Constraint(summary, expression, 
assignments);
+        Map<TrinoColumnHandle, Domain> domainMap =
+                
TrinoFilterExtractor.extractTrinoColumnHandleForExpressionFilter(constraint);
+        assertThat(domainMap.entrySet().size()).isEqualTo(1);
+        Map.Entry<TrinoColumnHandle, Domain> next = 
domainMap.entrySet().iterator().next();
+        
assertThat(next.getKey().getColumnName()).isEqualTo(toMapKey(columnName, 
mapKeyName));
+        assertThat(
+                        next.getValue()
+                                .getValues()
+                                .getRanges()
+                                .getOrderedRanges()
+                                .get(0)
+                                .getLowBoundedValue())
+                .isEqualTo(value);
+    }
+}
diff --git a/pom.xml b/pom.xml
index 9cec154..4bd3084 100644
--- a/pom.xml
+++ b/pom.xml
@@ -261,6 +261,20 @@ under the License.
                 </configuration>
             </plugin>
 
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>3.2.1</version>
+                <executions>
+                    <execution>
+                        <id>attach-sources</id>
+                        <goals>
+                            <goal>jar-no-fork</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-enforcer-plugin</artifactId>
@@ -518,4 +532,4 @@ under the License.
         </pluginManagement>
     </build>
 
-</project>
\ No newline at end of file
+</project>

Reply via email to