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

alexpl pushed a commit to branch sql-calcite
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/sql-calcite by this push:
     new 433de98  IGNITE-16077 Fix index scan on date types - Fixes #9640.
433de98 is described below

commit 433de9870afcf695a8acd2b00ed7bbe509329d81
Author: Aleksey Plekhanov <[email protected]>
AuthorDate: Mon Dec 13 17:31:02 2021 +0300

    IGNITE-16077 Fix index scan on date types - Fixes #9640.
    
    Signed-off-by: Aleksey Plekhanov <[email protected]>
---
 .../processors/query/calcite/exec/IndexScan.java   |  19 ++-
 .../CalciteBasicSecondaryIndexIntegrationTest.java | 182 ++++++++++++++++-----
 .../ignite/testsuites/IntegrationTestSuite.java    |   2 +-
 3 files changed, 162 insertions(+), 41 deletions(-)

diff --git 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexScan.java
 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexScan.java
index bc866db..60b8628 100644
--- 
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexScan.java
+++ 
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexScan.java
@@ -16,6 +16,7 @@
  */
 package org.apache.ignite.internal.processors.query.calcite.exec;
 
+import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
@@ -23,6 +24,7 @@ import java.util.List;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
+import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.ImmutableIntList;
 import org.apache.ignite.IgniteCheckedException;
@@ -46,6 +48,8 @@ import 
org.apache.ignite.internal.processors.cache.distributed.dht.topology.Grid
 import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot;
 import 
org.apache.ignite.internal.processors.query.calcite.exec.RowHandler.RowFactory;
 import 
org.apache.ignite.internal.processors.query.calcite.schema.TableDescriptor;
+import 
org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
+import org.apache.ignite.internal.processors.query.calcite.util.TypeUtils;
 import org.apache.ignite.internal.util.lang.GridCursor;
 import org.apache.ignite.spi.indexing.IndexingQueryFilter;
 import org.apache.ignite.spi.indexing.IndexingQueryFilterImpl;
@@ -91,6 +95,9 @@ public class IndexScan<Row> extends AbstractIndexScan<Row, 
IndexRow> {
     /** Mapping from index keys to row fields. */
     private final ImmutableIntList idxFieldMapping;
 
+    /** Types of key fields stored in index. */
+    private final Type[] fieldsStoreTypes;
+
     /**
      * @param ectx Execution context.
      * @param desc Table descriptor.
@@ -134,6 +141,13 @@ public class IndexScan<Row> extends AbstractIndexScan<Row, 
IndexRow> {
         mvccSnapshot = ectx.mvccSnapshot();
         this.requiredColumns = requiredColumns;
         this.idxFieldMapping = idxFieldMapping;
+
+        RelDataType srcRowType = desc.rowType(ectx.getTypeFactory(), null);
+        IgniteTypeFactory typeFactory = ectx.getTypeFactory();
+        fieldsStoreTypes = new Type[srcRowType.getFieldCount()];
+
+        for (int i = 0; i < srcRowType.getFieldCount(); i++)
+            fieldsStoreTypes[i] = 
typeFactory.getResultClass(srcRowType.getFieldList().get(i).getType());
     }
 
     /** {@inheritDoc} */
@@ -166,9 +180,12 @@ public class IndexScan<Row> extends AbstractIndexScan<Row, 
IndexRow> {
         boolean nullSearchRow = true;
 
         for (int i = 0; i < idxFieldMapping.size(); ++i) {
-            Object key = rowHnd.get(idxFieldMapping.getInt(i), bound);
+            int fieldIdx = idxFieldMapping.getInt(i);
+            Object key = rowHnd.get(fieldIdx, bound);
 
             if (key != null) {
+                key = TypeUtils.fromInternal(ectx, key, 
fieldsStoreTypes[fieldIdx]);
+
                 keys[i] = IndexKeyFactory.wrap(key, 
idxRowHnd.indexKeyDefinitions().get(i).idxType(),
                     cctx.cacheObjectContext(), 
idxRowHnd.indexKeyTypeSettings());
 
diff --git 
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/CalciteBasicSecondaryIndexIntegrationTest.java
 
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/CalciteBasicSecondaryIndexIntegrationTest.java
similarity index 88%
rename from 
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/CalciteBasicSecondaryIndexIntegrationTest.java
rename to 
modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/CalciteBasicSecondaryIndexIntegrationTest.java
index 87cf90f..5e0e948 100644
--- 
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/CalciteBasicSecondaryIndexIntegrationTest.java
+++ 
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/CalciteBasicSecondaryIndexIntegrationTest.java
@@ -14,11 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.internal.processors.query.calcite;
+package org.apache.ignite.internal.processors.query.calcite.integration;
 
+import java.sql.Date;
 import java.util.LinkedHashMap;
-
-import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.QueryEntity;
@@ -27,12 +26,9 @@ import org.apache.ignite.cache.QueryIndexType;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.processors.query.GridQueryProcessor;
-import org.apache.ignite.internal.processors.query.QueryEngine;
-import org.apache.ignite.internal.processors.query.calcite.util.Commons;
+import 
org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessorTest;
 import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.junit.Ignore;
 import org.junit.Test;
 
@@ -52,7 +48,7 @@ import static org.hamcrest.CoreMatchers.not;
 /**
  * Basic index tests.
  */
-public class CalciteBasicSecondaryIndexIntegrationTest extends 
GridCommonAbstractTest {
+public class CalciteBasicSecondaryIndexIntegrationTest extends 
AbstractBasicIntegrationTest {
     /** */
     private static final String DEPID_IDX = "DEPID_IDX";
 
@@ -62,9 +58,15 @@ public class CalciteBasicSecondaryIndexIntegrationTest 
extends GridCommonAbstrac
     /** */
     private static final String NAME_DEPID_CITY_IDX = "NAME_DEPID_CITY_IDX";
 
+    /** */
+    private static final String DATE_IDX = "DATE_IDX";
+
+    /** */
+    private static final String NAME_DATE_IDX = "NAME_DATE_IDX";
+
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
-        Ignite grid = startGridsMultiThreaded(2);
+        super.beforeTestsStarted();
 
         QueryEntity projEntity = new QueryEntity();
         projEntity.setKeyType(Integer.class.getName());
@@ -97,7 +99,7 @@ public class CalciteBasicSecondaryIndexIntegrationTest 
extends GridCommonAbstrac
 
         CacheConfiguration<Integer, Developer> projCfg = cache(projEntity);
 
-        IgniteCache<Integer, Developer> devCache = grid.createCache(projCfg);
+        IgniteCache<Integer, Developer> devCache = client.createCache(projCfg);
 
         devCache.put(1, new Developer("Mozart", 3, "Vienna", 33));
         devCache.put(2, new Developer("Beethoven", 2, "Vienna", 44));
@@ -128,20 +130,52 @@ public class CalciteBasicSecondaryIndexIntegrationTest 
extends GridCommonAbstrac
         devCache.put(22, new Developer("Prokofiev", 21, "", -1));
         devCache.put(23, new Developer("Musorgskii", 22, "", -1));
 
+        QueryEntity bdEntity = new QueryEntity();
+        bdEntity.setKeyType(Integer.class.getName());
+        bdEntity.setKeyFieldName("id");
+        bdEntity.setValueType(Birthday.class.getName());
+        bdEntity.addQueryField("id", Integer.class.getName(), null);
+        bdEntity.addQueryField("name", String.class.getName(), null);
+        bdEntity.addQueryField("birthday", Date.class.getName(), null);
+
+        QueryIndex dateIdx = new QueryIndex("birthday", true);
+        dateIdx.setName(DATE_IDX);
+
+        LinkedHashMap<String, Boolean> nameDateFields = new LinkedHashMap<>();
+        nameDateFields.put("name", false);
+        nameDateFields.put("birthday", false);
+        QueryIndex nameDateIdx = new QueryIndex(nameDateFields, 
QueryIndexType.SORTED);
+        nameDateIdx.setName(NAME_DATE_IDX);
+
+        bdEntity.setIndexes(asList(dateIdx, nameDateIdx));
+        bdEntity.setTableName("Birthday");
+
+        CacheConfiguration<Integer, Birthday> bdCfg = cache(bdEntity);
+
+        IgniteCache<Integer, Birthday> bdCache = client.createCache(bdCfg);
+
+        bdCache.put(1, new Birthday("Mozart", Date.valueOf("1756-01-27")));
+        bdCache.put(2, new Birthday("Beethoven", null));
+        bdCache.put(3, new Birthday("Bach", Date.valueOf("1685-03-31")));
+        bdCache.put(4, new Birthday("Strauss", Date.valueOf("1864-06-11")));
+        bdCache.put(5, new Birthday("Vagner", Date.valueOf("1813-05-22")));
+        bdCache.put(6, new Birthday("Chaikovsky", Date.valueOf("1840-05-07")));
+        bdCache.put(7, new Birthday("Verdy", Date.valueOf("1813-10-10")));
+
         IgniteCache<CalciteQueryProcessorTest.Key, 
CalciteQueryProcessorTest.Developer> tblWithAff =
-            grid.getOrCreateCache(new 
CacheConfiguration<CalciteQueryProcessorTest.Key, 
CalciteQueryProcessorTest.Developer>()
-            .setName("TBL_WITH_AFF_KEY")
-            .setSqlSchema("PUBLIC")
-            .setBackups(1)
-            .setQueryEntities(F.asList(new 
QueryEntity(CalciteQueryProcessorTest.Key.class, 
CalciteQueryProcessorTest.Developer.class)
-            .setTableName("TBL_WITH_AFF_KEY")))
+            client.getOrCreateCache(new 
CacheConfiguration<CalciteQueryProcessorTest.Key, 
CalciteQueryProcessorTest.Developer>()
+                .setName("TBL_WITH_AFF_KEY")
+                .setSqlSchema("PUBLIC")
+                .setBackups(1)
+                .setQueryEntities(F.asList(new 
QueryEntity(CalciteQueryProcessorTest.Key.class, 
CalciteQueryProcessorTest.Developer.class)
+                .setTableName("TBL_WITH_AFF_KEY")))
         );
 
         tblWithAff.put(new CalciteQueryProcessorTest.Key(1, 2), new 
CalciteQueryProcessorTest.Developer("Petr", 10));
         tblWithAff.put(new CalciteQueryProcessorTest.Key(2, 3), new 
CalciteQueryProcessorTest.Developer("Ivan", 11));
 
         IgniteCache<Integer, CalciteQueryProcessorTest.Developer> tblConstrPk =
-            grid.getOrCreateCache(new CacheConfiguration<Integer, 
CalciteQueryProcessorTest.Developer>()
+            client.getOrCreateCache(new CacheConfiguration<Integer, 
CalciteQueryProcessorTest.Developer>()
                 .setName("TBL_CONSTR_PK")
                 .setSqlSchema("PUBLIC")
                 .setBackups(0)
@@ -154,7 +188,7 @@ public class CalciteBasicSecondaryIndexIntegrationTest 
extends GridCommonAbstrac
         tblConstrPk.put(1, new CalciteQueryProcessorTest.Developer("Petr", 
10));
         tblConstrPk.put(2, new CalciteQueryProcessorTest.Developer("Ivan", 
11));
 
-        GridQueryProcessor qryProc = ((IgniteEx)grid).context().query();
+        GridQueryProcessor qryProc = client.context().query();
 
         qryProc.querySqlFields(new SqlFieldsQuery("CREATE TABLE 
PUBLIC.UNWRAP_PK" + " (F1 VARCHAR, F2 LONG, F3 LONG, F4 LONG, " +
             "CONSTRAINT PK PRIMARY KEY (F2, F1)) WITH \"backups=0, 
affinity_key=F1\""), true).getAll();
@@ -172,13 +206,18 @@ public class CalciteBasicSecondaryIndexIntegrationTest 
extends GridCommonAbstrac
     }
 
     /** {@inheritDoc} */
+    @Override protected void afterTest() {
+        // Skip super method to keep caches after each test.
+    }
+
+    /** {@inheritDoc} */
     @Override protected void afterTestsStopped() {
         stopAllGrids();
     }
 
     /** */
-    private CacheConfiguration cache(QueryEntity ent) {
-        return new CacheConfiguration<>(ent.getTableName())
+    private <K, V> CacheConfiguration<K, V> cache(QueryEntity ent) {
+        return new CacheConfiguration<K, V>(ent.getTableName())
             .setCacheMode(CacheMode.PARTITIONED)
             .setBackups(1)
             .setQueryEntities(singletonList(ent))
@@ -471,6 +510,65 @@ public class CalciteBasicSecondaryIndexIntegrationTest 
extends GridCommonAbstrac
 
     /** */
     @Test
+    public void testIndexedDateFieldEqualsFilter() {
+        assertQuery("SELECT * FROM Birthday WHERE birthday = DATE 
'1813-05-22'")
+            .matches(containsIndexScan("PUBLIC", "BIRTHDAY", DATE_IDX))
+            .returns(5, "Vagner", Date.valueOf("1813-05-22"))
+            .check();
+    }
+
+    /** */
+    @Test
+    public void testIndexedDateFieldEqualsParameterFilter() {
+        assertQuery("SELECT * FROM Birthday WHERE birthday = ?")
+            .withParams(Date.valueOf("1813-05-22"))
+            .returns(5, "Vagner", Date.valueOf("1813-05-22"))
+            .check();
+    }
+
+    /** */
+    @Test
+    public void testIndexedDateFieldGreaterThanFilter() {
+        assertQuery("SELECT * FROM Birthday WHERE birthday > DATE 
'1813-05-22'")
+            .matches(containsIndexScan("PUBLIC", "BIRTHDAY", DATE_IDX))
+            .returns(4, "Strauss", Date.valueOf("1864-06-11"))
+            .returns(6, "Chaikovsky", Date.valueOf("1840-05-07"))
+            .returns(7, "Verdy", Date.valueOf("1813-10-10"))
+            .check();
+    }
+
+    /** */
+    @Test
+    public void testIndexedDateFieldLessThanOrEqualFilter() {
+        assertQuery("SELECT * FROM Birthday WHERE birthday <= DATE 
'1756-01-27'")
+            .matches(containsIndexScan("PUBLIC", "BIRTHDAY", DATE_IDX))
+            .returns(1, "Mozart", Date.valueOf("1756-01-27"))
+            .returns(3, "Bach", Date.valueOf("1685-03-31"))
+            .check();
+    }
+
+    /** */
+    @Test
+    public void testIndexedDateFieldBetweenFilter() {
+        assertQuery("SELECT * FROM Birthday WHERE birthday BETWEEN DATE 
'1756-01-27' AND DATE '1813-10-10'")
+            .matches(containsIndexScan("PUBLIC", "BIRTHDAY", DATE_IDX))
+            .returns(1, "Mozart", Date.valueOf("1756-01-27"))
+            .returns(5, "Vagner", Date.valueOf("1813-05-22"))
+            .returns(7, "Verdy", Date.valueOf("1813-10-10"))
+            .check();
+    }
+
+    /** */
+    @Test
+    public void testIndexedNameDateFieldEqualsFilter() {
+        assertQuery("SELECT * FROM Birthday WHERE name = 'Vagner' AND birthday 
= DATE '1813-05-22'")
+            .matches(containsIndexScan("PUBLIC", "BIRTHDAY", NAME_DATE_IDX))
+            .returns(5, "Vagner", Date.valueOf("1813-05-22"))
+            .check();
+    }
+
+    /** */
+    @Test
     public void testIndexedFieldGreaterThanFilter() {
         assertQuery("SELECT * FROM Developer WHERE depId>21")
             .withParams(3)
@@ -958,13 +1056,13 @@ public class CalciteBasicSecondaryIndexIntegrationTest 
extends GridCommonAbstrac
     /** */
     @Test
     public void testOrderByNoIndexedColumn() {
-        assertQuery("SELECT * FROM Developer ORDER BY age DESC")
+        assertQuery("SELECT * FROM Developer ORDER BY age DESC, ID")
             .matches(containsAnyProject("PUBLIC", "DEVELOPER"))
             .matches(containsSubPlan("IgniteSort"))
             .returns(8, "Stravinsky", 7, "Spt", 89)
             .returns(7, "Verdy", 6, "Rankola", 88)
-            .returns(9, "Rahmaninov", 8, "Starorussky ud", 70)
             .returns(5, "Vagner", 4, "Leipzig", 70)
+            .returns(9, "Rahmaninov", 8, "Starorussky ud", 70)
             .returns(4, "Strauss", 2, "Munich", 66)
             .returns(3, "Bach", 1, "Leipzig", 55)
             .returns(6, "Chaikovsky", 5, "Votkinsk", 53)
@@ -972,18 +1070,18 @@ public class CalciteBasicSecondaryIndexIntegrationTest 
extends GridCommonAbstrac
             .returns(2, "Beethoven", 2, "Vienna", 44)
             .returns(1, "Mozart", 3, "Vienna", 33)
             .returns(10, "Shubert", 9, "Vienna", 31)
-            .returns(14, "Rihter", 13, "", -1)
-            .returns(13, "Glass", 12, "", -1)
             .returns(12, "Einaudi", 11, "", -1)
-            .returns(20, "O'Halloran", 19, "", -1)
-            .returns(23, "Musorgskii", 22, "", -1)
+            .returns(13, "Glass", 12, "", -1)
+            .returns(14, "Rihter", 13, "", -1)
+            .returns(15, "Marradi", 14, "", -1)
+            .returns(16, "Zimmer", 15, "", -1)
+            .returns(17, "Hasaishi", 16, "", -1)
+            .returns(18, "Arnalds", 17, "", -1)
             .returns(19, "Yiruma", 18, "", -1)
+            .returns(20, "O'Halloran", 19, "", -1)
             .returns(21, "Cacciapaglia", 20, "", -1)
             .returns(22, "Prokofiev", 21, "", -1)
-            .returns(16, "Zimmer", 15, "", -1)
-            .returns(18, "Arnalds", 17, "", -1)
-            .returns(17, "Hasaishi", 16, "", -1)
-            .returns(15, "Marradi", 14, "", -1)
+            .returns(23, "Musorgskii", 22, "", -1)
             .ordered()
             .check();
     }
@@ -1021,15 +1119,6 @@ public class CalciteBasicSecondaryIndexIntegrationTest 
extends GridCommonAbstrac
     }
 
     /** */
-    private QueryChecker assertQuery(String qry) {
-        return new QueryChecker(qry) {
-            @Override protected QueryEngine getEngine() {
-                return Commons.lookupComponent(grid(0).context(), 
QueryEngine.class);
-            }
-        };
-    }
-
-    /** */
     private static class Developer {
         /** */
         String name;
@@ -1061,6 +1150,21 @@ public class CalciteBasicSecondaryIndexIntegrationTest 
extends GridCommonAbstrac
     }
 
     /** */
+    private static class Birthday {
+        /** */
+        String name;
+
+        /** */
+        Date birthday;
+
+        /** */
+        public Birthday(String name, Date birthday) {
+            this.name = name;
+            this.birthday = birthday;
+        }
+    }
+
+    /** */
     public static class Key {
         /** */
         @QuerySqlField
diff --git 
a/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
 
b/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
index 83d6409..a859aaa 100644
--- 
a/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
+++ 
b/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.testsuites;
 
-import 
org.apache.ignite.internal.processors.query.calcite.CalciteBasicSecondaryIndexIntegrationTest;
 import 
org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessorTest;
 import org.apache.ignite.internal.processors.query.calcite.CancelTest;
 import org.apache.ignite.internal.processors.query.calcite.DataTypesTest;
@@ -28,6 +27,7 @@ import 
org.apache.ignite.internal.processors.query.calcite.SqlFieldsQueryUsageTe
 import org.apache.ignite.internal.processors.query.calcite.StdSqlOperatorsTest;
 import 
org.apache.ignite.internal.processors.query.calcite.UnstableTopologyTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.AggregatesIntegrationTest;
+import 
org.apache.ignite.internal.processors.query.calcite.integration.CalciteBasicSecondaryIndexIntegrationTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.CalciteErrorHandlilngIntegrationTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.CorrelatesIntegrationTest;
 import 
org.apache.ignite.internal.processors.query.calcite.integration.IndexDdlIntegrationTest;

Reply via email to