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;