You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by tl...@apache.org on 2021/04/05 11:46:54 UTC

[ignite] branch master updated: IGNITE-14451 fix corrupt PK index tree caused fields order (closes #8951)

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

tledkov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 55e5717  IGNITE-14451 fix corrupt PK index tree caused fields order (closes #8951)
55e5717 is described below

commit 55e57173adc5fa2a891fb6a9d8d8fefdaab87ba9
Author: tledkov <tl...@gridgain.com>
AuthorDate: Mon Apr 5 14:46:37 2021 +0300

    IGNITE-14451 fix corrupt PK index tree caused fields order (closes #8951)
---
 .../internal/processors/query/QueryEntityEx.java   | 26 ++++++++++-
 .../internal/processors/query/QueryUtils.java      |  2 +-
 .../processors/query/h2/CommandProcessor.java      | 17 ++++---
 .../processors/query/h2/H2TableDescriptor.java     |  4 +-
 .../processors/cache/index/BasicIndexTest.java     | 54 ++++++++++++++++++++++
 5 files changed, 89 insertions(+), 14 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryEntityEx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryEntityEx.java
index 655cf52..dde4b4e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryEntityEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryEntityEx.java
@@ -34,6 +34,9 @@ public class QueryEntityEx extends QueryEntity {
     /** Fields that must have non-null value. */
     private Set<String> notNullFields;
 
+    /** Whether to preserve order specified by {@link #getKeyFields()} or not. */
+    private boolean preserveKeysOrder;
+
     /**
      * Default constructor.
      */
@@ -53,6 +56,8 @@ public class QueryEntityEx extends QueryEntity {
             QueryEntityEx other0 = (QueryEntityEx)other;
 
             notNullFields = other0.notNullFields != null ? new HashSet<>(other0.notNullFields) : null;
+
+            preserveKeysOrder = other0.preserveKeysOrder;
         }
     }
 
@@ -68,6 +73,23 @@ public class QueryEntityEx extends QueryEntity {
         return this;
     }
 
+    /**
+     * @return {@code true} if order should be preserved, {@code false} otherwise.
+     */
+    public boolean isPreserveKeysOrder() {
+        return preserveKeysOrder;
+    }
+
+    /**
+     * @param preserveKeysOrder Whether the order should be preserved or not.
+     * @return {@code this} for chaining.
+     */
+    public QueryEntity setPreserveKeysOrder(boolean preserveKeysOrder) {
+        this.preserveKeysOrder = preserveKeysOrder;
+
+        return this;
+    }
+
     /** {@inheritDoc} */
     @Override public boolean equals(Object o) {
         if (this == o)
@@ -78,7 +100,8 @@ public class QueryEntityEx extends QueryEntity {
 
         QueryEntityEx entity = (QueryEntityEx)o;
 
-        return super.equals(entity) && F.eq(notNullFields, entity.notNullFields);
+        return super.equals(entity) && F.eq(notNullFields, entity.notNullFields)
+            && preserveKeysOrder == entity.preserveKeysOrder;
     }
 
     /** {@inheritDoc} */
@@ -86,6 +109,7 @@ public class QueryEntityEx extends QueryEntity {
         int res = super.hashCode();
 
         res = 31 * res + (notNullFields != null ? notNullFields.hashCode() : 0);
+        res = 31 * res + (preserveKeysOrder ? 1 : 0);
 
         return res;
     }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
index 1577932..9b4449e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
@@ -655,7 +655,7 @@ public class QueryUtils {
             d.addProperty(prop, false);
         }
 
-        if (!isKeyClsSqlType)
+        if (!isKeyClsSqlType && qryEntity instanceof QueryEntityEx && ((QueryEntityEx)qryEntity).isPreserveKeysOrder())
             d.primaryKeyFields(keyFields);
 
         // Sql-typed key/value doesn't have field property, but they may have precision and scale constraints.
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/CommandProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/CommandProcessor.java
index fb314e6..f81e7f6 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/CommandProcessor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/CommandProcessor.java
@@ -32,6 +32,7 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
+
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteCluster;
 import org.apache.ignite.IgniteDataStreamer;
@@ -1059,7 +1060,7 @@ public class CommandProcessor {
      * @return Query entity mimicking this SQL statement.
      */
     private static QueryEntity toQueryEntity(GridSqlCreateTable createTbl) {
-        QueryEntity res = new QueryEntity();
+        QueryEntityEx res = new QueryEntityEx();
 
         res.setTableName(createTbl.tableName());
 
@@ -1132,9 +1133,12 @@ public class CommandProcessor {
 
             res.setKeyFieldName(pkCol.columnName());
         }
-        else
+        else {
             res.setKeyFields(createTbl.primaryKeyColumns());
 
+            res.setPreserveKeysOrder(true);
+        }
+
         if (!createTbl.wrapValue()) {
             GridSqlColumn valCol = null;
 
@@ -1156,13 +1160,8 @@ public class CommandProcessor {
         res.setValueType(valTypeName);
         res.setKeyType(keyTypeName);
 
-        if (!F.isEmpty(notNullFields)) {
-            QueryEntityEx res0 = new QueryEntityEx(res);
-
-            res0.setNotNullFields(notNullFields);
-
-            res = res0;
-        }
+        if (!F.isEmpty(notNullFields))
+            res.setNotNullFields(notNullFields);
 
         return res;
     }
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableDescriptor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableDescriptor.java
index f592341..6e181ce 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableDescriptor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2TableDescriptor.java
@@ -331,9 +331,7 @@ public class H2TableDescriptor {
             if (QueryUtils.isSqlType(type.keyClass()))
                 keyCols.add(keyCol);
             else {
-                // SPECIFIED_SEQ_PK_KEYS check guarantee that request running on heterogeneous (RU) cluster can
-                // perform equally on all nodes.
-                if (!idx.kernalContext().recoveryMode()) {
+                if (!type.primaryKeyFields().isEmpty()) {
                     for (String keyName : type.primaryKeyFields()) {
                         GridQueryProperty prop = type.property(keyName);
 
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/BasicIndexTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/BasicIndexTest.java
index 9eefbc1..8c0c67b 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/BasicIndexTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/BasicIndexTest.java
@@ -27,6 +27,7 @@ import java.util.List;
 import java.util.Objects;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
+
 import javax.cache.CacheException;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
@@ -316,6 +317,59 @@ public class BasicIndexTest extends AbstractIndexingCommonTest {
     }
 
     /**
+     * Checks that fields in primary index have correct order after node restart.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCorrectPkFieldsSequenceAfterRestart() throws Exception {
+        inlineSize = 10;
+
+        IgniteEx ig0 = startGrid(getConfiguration("0").setDataStorageConfiguration(
+            new DataStorageConfiguration().setDefaultDataRegionConfiguration(
+                new DataRegionConfiguration().setPersistenceEnabled(true)
+            )
+        ));
+
+        ig0.cluster().state(ClusterState.ACTIVE);
+
+        {
+            GridQueryProcessor qryProc = ig0.context().query();
+
+            IgniteH2Indexing idx = (IgniteH2Indexing)(ig0).context().query().getIndexing();
+
+            String tblName = "T1";
+
+            qryProc.querySqlFields(new SqlFieldsQuery("CREATE TABLE PUBLIC." + tblName + " (F1 VARCHAR, F2 VARCHAR, F3 VARCHAR, " +
+                "CONSTRAINT PK PRIMARY KEY (F2, F1))"), true).getAll();
+
+            List<String> expect = Arrays.asList("F2", "F1");
+
+            checkPkFldSequence(tblName, expect, idx);
+        }
+
+        stopAllGrids();
+
+        ig0 = startGrid(getConfiguration("0").setDataStorageConfiguration(
+            new DataStorageConfiguration().setDefaultDataRegionConfiguration(
+                new DataRegionConfiguration().setPersistenceEnabled(true)
+            )
+        ));
+
+        ig0.cluster().state(ClusterState.ACTIVE);
+
+        {
+            IgniteH2Indexing idx = (IgniteH2Indexing)(ig0).context().query().getIndexing();
+
+            String tblName = "T1";
+
+            List<String> expect = Arrays.asList("F2", "F1");
+
+            checkPkFldSequence(tblName, expect, idx);
+        }
+    }
+
+    /**
      * Fields correctness checker.
      *
      * @param tblName Table name.