It works.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/8a2a8610 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/8a2a8610 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/8a2a8610 Branch: refs/heads/ignite-10291 Commit: 8a2a8610a8439b8fedc3271153379d0d57058128 Parents: 4860158 Author: devozerov <[email protected]> Authored: Wed Nov 28 16:55:52 2018 +0300 Committer: devozerov <[email protected]> Committed: Wed Nov 28 16:55:52 2018 +0300 ---------------------------------------------------------------------- .../java/org/apache/ignite/jdbc/Reproducer.java | 164 +++++++++++++++++++ .../processors/query/h2/IgniteH2Indexing.java | 9 +- .../processors/query/h2/database/H2Tree.java | 14 ++ .../query/h2/database/H2TreeIndex.java | 4 +- 4 files changed, 188 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/8a2a8610/modules/clients/src/test/java/org/apache/ignite/jdbc/Reproducer.java ---------------------------------------------------------------------- diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/Reproducer.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/Reproducer.java new file mode 100644 index 0000000..1899a45 --- /dev/null +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/Reproducer.java @@ -0,0 +1,164 @@ +package org.apache.ignite.jdbc; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import javax.cache.Cache; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.IgniteJdbcThinDriver; +import org.apache.ignite.Ignition; +import org.apache.ignite.binary.BinaryObject; +import org.apache.ignite.configuration.DataRegionConfiguration; +import org.apache.ignite.configuration.DataStorageConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; +import org.apache.ignite.testframework.GridTestUtils; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +public class Reproducer extends GridCommonAbstractTest { + + static final String NODE_1 = "node1"; + static final String NODE_2 = "node2"; + + public static final String CREATE_TABLE = "CREATE TABLE PERSON (\n" + + " FIRST_NAME VARCHAR,\n" + + " LAST_NAME VARCHAR,\n" + + " ADDRESS VARCHAR,\n" + + " LANG VARCHAR,\n" + + " BIRTH_DATE TIMESTAMP,\n" + + " CONSTRAINT PK_PESON PRIMARY KEY (FIRST_NAME,LAST_NAME,ADDRESS,LANG)\n" + + ") WITH \"key_type=PersonKeyType, CACHE_NAME=PersonCache, value_type=PersonValueType, AFFINITY_KEY=FIRST_NAME,template=PARTITIONED,backups=1\""; + + public static final String CREATE_INDEX = "create index PERSON_FIRST_NAME_IDX on PERSON(FIRST_NAME)"; + + public static final String QUERY = "select * from PERSON use index(PERSON_FIRST_NAME_IDX) \n" + + "where \n" + + "FIRST_NAME=?\n" + + "and LAST_NAME=?\n" + + "and ADDRESS=?\n" + + "and LANG = ? "; + + public static void main(String[] args) throws Exception { + cleanPersistenceDir(); // TODO: Enable + + System.out.println(CREATE_TABLE); + System.out.println(CREATE_INDEX); + System.out.println(QUERY); + + Ignite server1 = Ignition.start(getCfg(NODE_1)); + Ignite server2 = Ignition.start(getCfg(NODE_2)); + Ignite client = Ignition.start(getCfg("client").setClientMode(true)); + client.cluster().active(true); + + createTable(); + fill(); + + server2.close(); + + createIndex(); + + server2 = Ignition.start(getCfg(NODE_2)); + + findRows(client); + } + + static IgniteConfiguration getCfg(String id) { + IgniteConfiguration cfg = new IgniteConfiguration(); + TcpDiscoverySpi discovery = new TcpDiscoverySpi(); + TcpDiscoveryVmIpFinder finder = new TcpDiscoveryVmIpFinder(); + + cfg.setConsistentId(id); + cfg.setIgniteInstanceName(id); + + cfg.setDataStorageConfiguration(new DataStorageConfiguration().setDefaultDataRegionConfiguration(new DataRegionConfiguration().setPersistenceEnabled(true))); + + finder.setAddresses(Arrays.asList("127.0.0.1:47500..47509")); + discovery.setIpFinder(finder); + cfg.setDiscoverySpi(discovery); + + return cfg; + } + + private static void createTable() throws SQLException { + try (Connection conn = new IgniteJdbcThinDriver().connect("jdbc:ignite:thin://localhost", new Properties())) { + conn.createStatement().execute(CREATE_TABLE); + } + } + + private static void createIndex() throws SQLException { + try (Connection conn = new IgniteJdbcThinDriver().connect("jdbc:ignite:thin://localhost", new Properties())) { + conn.createStatement().execute(CREATE_INDEX); + } + } + + private static void fill() throws SQLException { + try (Connection conn = new IgniteJdbcThinDriver().connect("jdbc:ignite:thin://localhost", new Properties())) { + + PreparedStatement st = conn.prepareStatement("insert into Person(LANG,FIRST_NAME,ADDRESS,LAST_NAME,BIRTH_DATE)\n" + + "values(?,?,?,?,?)"); + + for (int i = 0; i < 1; i++) { + try { + String s = String.valueOf(i); + st.setString(1, s); + st.setString(2, s); + st.setString(3, s); + st.setString(4, s); + st.setTimestamp(6, new Timestamp(System.currentTimeMillis())); + st.executeUpdate(); + } + catch (Exception e) { + System.out.println(e.getMessage()); + } + } + } + System.out.println("Tables with data are created."); + } + + static void findRows(Ignite ignite) throws SQLException { + AtomicInteger total = new AtomicInteger(); + AtomicInteger fails = new AtomicInteger(); + try (Connection conn = new IgniteJdbcThinDriver().connect("jdbc:ignite:thin://localhost", new Properties())) { + PreparedStatement st = conn.prepareStatement(QUERY); + + IgniteCache<BinaryObject, BinaryObject> cache = ignite.cache("PersonCache").withKeepBinary(); + cache.forEach(new Consumer<Cache.Entry<BinaryObject, BinaryObject>>() { + @Override public void accept(Cache.Entry<BinaryObject, BinaryObject> entry) { + BinaryObject key = entry.getKey(); + try { + st.setString(1, key.field("FIRST_NAME")); + st.setString(2, key.field("LAST_NAME")); + st.setString(3, key.field("ADDRESS")); + st.setString(4, key.field("LANG")); + ResultSet rs = st.executeQuery(); + if (!rs.next()) { + System.out.println("!!!Unable to find row by key:" + key); + fails.incrementAndGet(); + } + + total.incrementAndGet(); + rs.close(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + }); + + st.close(); + + } + System.out.println("Finished"); + System.out.println("Total:"+total.get()+" fails:"+fails.get()); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/8a2a8610/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java index 9dc15e6..6e87655 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java @@ -2705,13 +2705,18 @@ public class IgniteH2Indexing implements GridQueryIndexing { } else { // Otherwise iterate over tables looking for missing indexes. - clo = new IndexRebuildPartialClosure(); + IndexRebuildPartialClosure clo0 = new IndexRebuildPartialClosure(); for (H2TableDescriptor tblDesc : tables(cctx.name())) { assert tblDesc.table() != null; - tblDesc.table().collectIndexesForPartialRebuild((IndexRebuildPartialClosure)clo); + tblDesc.table().collectIndexesForPartialRebuild(clo0); } + + if (clo0.hasIndexes()) + clo = clo0; + else + return null; } // Closure prepared, do rebuild. http://git-wip-us.apache.org/repos/asf/ignite/blob/8a2a8610/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java index 71cea7e..f2a69bb 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2Tree.java @@ -108,8 +108,12 @@ public abstract class H2Tree extends BPlusTree<GridH2SearchRow, GridH2Row> { /** */ private final IgniteLogger log; + /** Whether PK is stored in unwrapped form. */ private boolean unwrappedPk; + /** Whether index was created from scratch during owning node lifecycle. */ + private final boolean created; + /** * Constructor. * @@ -200,6 +204,8 @@ public abstract class H2Tree extends BPlusTree<GridH2SearchRow, GridH2Row> { this.log = log; initTree(initNew, inlineSize); + + this.created = initNew; } /** @@ -556,6 +562,14 @@ public abstract class H2Tree extends BPlusTree<GridH2SearchRow, GridH2Row> { */ public abstract int compareValues(Value v1, Value v2); + /** + * @return {@code True} if index was created during curren node's lifetime, {@code False} if it was restored from + * disk. + */ + public boolean created() { + return created; + } + /** {@inheritDoc} */ @Override public String toString() { return S.toString(H2Tree.class, this, "super", super.toString()); http://git-wip-us.apache.org/repos/asf/ignite/blob/8a2a8610/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java index 48d4cc4..25a5c61 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/H2TreeIndex.java @@ -224,8 +224,9 @@ public class H2TreeIndex extends GridH2IndexBase { for (int i = 0; i < segments.length; i++) { try { + H2Tree segment = segments[i]; - if (!metaPageExists(i)) + if (segment.created()) return true; } catch (Exception e) { @@ -572,6 +573,7 @@ public class H2TreeIndex extends GridH2IndexBase { * @return {@code True} if exists. * @throws IgniteCheckedException If failed. */ + // TODO: Remove? private boolean metaPageExists(int segIdx) throws IgniteCheckedException { return cctx.offheap().rootPageForIndexExists(cctx.cacheId(), treeName, segIdx); }
