You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ip...@apache.org on 2020/01/23 12:44:30 UTC

[ignite] branch master updated: IGNITE-12565 Extend test coverage [IGNITE-9279] Support custom default SQL schema name - Fixes #7289.

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

ipavlukhin 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 6a87307  IGNITE-12565 Extend test coverage [IGNITE-9279] Support custom default SQL schema name - Fixes #7289.
6a87307 is described below

commit 6a8730754b5f1bf064ec044e7342b85c5b50627f
Author: ipavlukhin <vo...@gmail.com>
AuthorDate: Thu Jan 23 15:43:30 2020 +0300

    IGNITE-12565 Extend test coverage [IGNITE-9279] Support custom default SQL schema name - Fixes #7289.
    
    Signed-off-by: ipavlukhin <vo...@gmail.com>
---
 .../apache/ignite/testframework/GridTestUtils.java |  19 +-
 .../processors/query/AbstractCustomSchemaTest.java | 197 +++++++++++++++++++++
 .../query/AbstractDefaultSchemaTest.java           | 133 ++++++++++++++
 .../query/IgniteSqlCustomSchemaTest.java           |  51 ++++++
 .../query/IgniteSqlCustomSchemaWithPdsEnabled.java | 148 ++++++++++++++++
 .../query/IgniteSqlDefaultSchemaTest.java          |  31 ++++
 .../IgniteSqlSchemasDiffConfigurationsTest.java    |  90 ++++++++++
 .../processors/query/JdbcSqlCustomSchemaTest.java  |  85 +++++++++
 .../processors/query/JdbcSqlDefaultSchemaTest.java |  85 +++++++++
 .../IgniteBinaryCacheQueryTestSuite.java           |  13 ++
 10 files changed, 850 insertions(+), 2 deletions(-)

diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java b/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
index 23a64f0..7a26606 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
@@ -2125,11 +2125,26 @@ public final class GridTestUtils {
      * Generate random alphabetical string.
      *
      * @param rnd Random object.
-     * @param maxLen Maximal length of string
+     * @param maxLen Maximal length of string.
      * @return Random string object.
      */
     public static String randomString(Random rnd, int maxLen) {
-        int len = rnd.nextInt(maxLen);
+        return randomString(rnd, 0, maxLen);
+    }
+
+    /**
+     * Generate random alphabetical string.
+     *
+     * @param rnd Random object.
+     * @param minLen Minimum length of string.
+     * @param maxLen Maximal length of string.
+     * @return Random string object.
+     */
+    public static String randomString(Random rnd, int minLen, int maxLen) {
+        assert minLen >= 0 : "minLen >= 0";
+        assert maxLen >= minLen : "maxLen >= minLen";
+
+        int len = maxLen == minLen ? minLen : minLen + rnd.nextInt(maxLen - minLen);
 
         StringBuilder b = new StringBuilder(len);
 
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/AbstractCustomSchemaTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/AbstractCustomSchemaTest.java
new file mode 100644
index 0000000..c32dbb48
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/AbstractCustomSchemaTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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.ignite.internal.processors.query;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.cache.index.AbstractIndexingCommonTest;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+/** Abstract test to verify custom sql schema. */
+public abstract class AbstractCustomSchemaTest extends AbstractIndexingCommonTest {
+    /** */
+    protected static final String TBL_NAME = "T1";
+
+    /** */
+    protected static final String SCHEMA_NAME_1 = "SCHEMA_1";
+
+    /** */
+    protected static final String SCHEMA_NAME_2 = "SCHEMA_2";
+
+    /** */
+    private static final String SCHEMA_NAME_3 = "ScHeMa3";
+
+    /** */
+    private static final String SCHEMA_NAME_4 = "SCHEMA_4";
+
+    /** */
+    private static final String UNKNOWN_SCHEMA_NAME = "UNKNOWN_SCHEMA";
+
+    /** */
+    private static final String CACHE_NAME = "cache_4";
+
+    /** */
+    protected static String t(String schema, String tbl) {
+        return schema + "." + tbl;
+    }
+
+    /** */
+    private static String q(String str) {
+        return "\"" + str + "\"";
+    }
+
+    /** */
+    protected abstract List<List<?>> execSql(String qry);
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        return super.getConfiguration(igniteInstanceName)
+            .setSqlSchemas(SCHEMA_NAME_1, SCHEMA_NAME_2, q(SCHEMA_NAME_3))
+            .setCacheConfiguration(new CacheConfiguration(CACHE_NAME).setSqlSchema(SCHEMA_NAME_4));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        startGrid(0);
+    }
+
+    /** */
+    @After
+    public void clear() {
+        execSql("DROP TABLE IF EXISTS " + t(SCHEMA_NAME_1, TBL_NAME));
+        execSql("DROP TABLE IF EXISTS " + t(SCHEMA_NAME_2, TBL_NAME));
+        execSql("DROP TABLE IF EXISTS " + t(q(SCHEMA_NAME_3), TBL_NAME));
+        execSql("DROP TABLE IF EXISTS " + t(SCHEMA_NAME_4, TBL_NAME));
+    }
+
+    /** */
+    @Test
+    public void testBasicOpsDiffSchemas() {
+        execSql("CREATE TABLE " + t(SCHEMA_NAME_1, TBL_NAME) + " (s1_key INT PRIMARY KEY, s1_val INT)");
+        execSql("CREATE TABLE " + t(SCHEMA_NAME_2, TBL_NAME) + " (s2_key INT PRIMARY KEY, s2_val INT)");
+        execSql("CREATE TABLE " + t(q(SCHEMA_NAME_3), TBL_NAME) + " (s3_key INT PRIMARY KEY, s3_val INT)");
+        execSql("CREATE TABLE " + t(SCHEMA_NAME_4, TBL_NAME) + " (s4_key INT PRIMARY KEY, s4_val INT)");
+
+        execSql("INSERT INTO " + t(SCHEMA_NAME_1, TBL_NAME) + " (s1_key, s1_val) VALUES (1, 2)");
+        execSql("INSERT INTO " + t(SCHEMA_NAME_2, TBL_NAME) + " (s2_key, s2_val) VALUES (1, 2)");
+        execSql("INSERT INTO " + t(q(SCHEMA_NAME_3), TBL_NAME) + " (s3_key, s3_val) VALUES (1, 2)");
+        execSql("INSERT INTO " + t(SCHEMA_NAME_4, TBL_NAME) + " (s4_key, s4_val) VALUES (1, 2)");
+
+        execSql("UPDATE " + t(SCHEMA_NAME_1, TBL_NAME) + " SET s1_val = 5");
+        execSql("UPDATE " + t(SCHEMA_NAME_2, TBL_NAME) + " SET s2_val = 5");
+        execSql("UPDATE " + t(q(SCHEMA_NAME_3), TBL_NAME) + " SET s3_val = 5");
+        execSql("UPDATE " + t(SCHEMA_NAME_4, TBL_NAME) + " SET s4_val = 5");
+
+        execSql("DELETE FROM " + t(SCHEMA_NAME_1, TBL_NAME));
+        execSql("DELETE FROM " + t(SCHEMA_NAME_2, TBL_NAME));
+        execSql("DELETE FROM " + t(q(SCHEMA_NAME_3), TBL_NAME));
+        execSql("DELETE FROM " + t(SCHEMA_NAME_4, TBL_NAME));
+
+        execSql("CREATE INDEX t1_idx_1 ON " + t(SCHEMA_NAME_1, TBL_NAME) + "(s1_val)");
+        execSql("CREATE INDEX t1_idx_1 ON " + t(SCHEMA_NAME_2, TBL_NAME) + "(s2_val)");
+        execSql("CREATE INDEX t1_idx_1 ON " + t(q(SCHEMA_NAME_3), TBL_NAME) + "(s3_val)");
+        execSql("CREATE INDEX t1_idx_1 ON " + t(SCHEMA_NAME_4, TBL_NAME) + "(s4_val)");
+
+        execSql("SELECT * FROM " + t(SCHEMA_NAME_1, TBL_NAME));
+        execSql("SELECT * FROM " + t(SCHEMA_NAME_2, TBL_NAME));
+        execSql("SELECT * FROM " + t(q(SCHEMA_NAME_3), TBL_NAME));
+        execSql("SELECT * FROM " + t(SCHEMA_NAME_4, TBL_NAME));
+
+        execSql("SELECT * FROM " + t(SCHEMA_NAME_1, TBL_NAME)
+            + " JOIN " + t(SCHEMA_NAME_2, TBL_NAME)
+            + " JOIN " + t(q(SCHEMA_NAME_3), TBL_NAME)
+            + " JOIN " + t(SCHEMA_NAME_4, TBL_NAME));
+
+        verifyTbls();
+
+        execSql("DROP TABLE " + t(SCHEMA_NAME_1, TBL_NAME));
+        execSql("DROP TABLE " + t(SCHEMA_NAME_2, TBL_NAME));
+        execSql("DROP TABLE " + t(q(SCHEMA_NAME_3), TBL_NAME));
+        execSql("DROP TABLE " + t(SCHEMA_NAME_4, TBL_NAME));
+    }
+
+    /** */
+    @Test
+    public void testRecreateTableWithinSchema() {
+        grid(0).cache(CACHE_NAME).destroy();
+
+        grid(0).createCache(new CacheConfiguration<>(CACHE_NAME + "_new").setSqlSchema(SCHEMA_NAME_4));
+
+        List<List<?>> res = execSql("SELECT SQL_SCHEMA FROM " + t(QueryUtils.SCHEMA_SYS, "CACHES")
+            + " WHERE CACHE_NAME = '" + CACHE_NAME + "_new'");
+
+        Assert.assertEquals(
+            Collections.singletonList(Collections.singletonList(SCHEMA_NAME_4)),
+            res
+        );
+    }
+
+    /** */
+    @Test
+    @SuppressWarnings("ThrowableNotThrown")
+    public void testCreateTblsInDiffSchemasForSameCache() {
+        final String testCache = "cache1";
+
+        execSql("CREATE TABLE " + t(SCHEMA_NAME_1, TBL_NAME)
+            + " (s1_key INT PRIMARY KEY, s1_val INT) WITH \"cache_name=" + testCache + "\"");
+
+        GridTestUtils.assertThrowsWithCause(
+            () -> execSql("CREATE TABLE " + t(SCHEMA_NAME_2, TBL_NAME)
+                + " (s1_key INT PRIMARY KEY, s2_val INT) WITH \"cache_name=" + testCache + "\""),
+            SQLException.class
+        );
+
+        execSql("DROP TABLE " + t(SCHEMA_NAME_1, TBL_NAME));
+    }
+
+    /** */
+    @Test
+    @SuppressWarnings("ThrowableNotThrown")
+    public void testCreateDropNonExistingSchema() {
+        GridTestUtils.assertThrowsWithCause(
+            () -> execSql("CREATE TABLE " + t(UNKNOWN_SCHEMA_NAME, TBL_NAME) + "(id INT PRIMARY KEY, val INT)"),
+            SQLException.class
+        );
+
+        GridTestUtils.assertThrowsWithCause(
+            () -> execSql("DROP TABLE " + t(UNKNOWN_SCHEMA_NAME, TBL_NAME)),
+            SQLException.class
+        );
+    }
+
+    /** */
+    private void verifyTbls() {
+        List<List<?>> res = execSql("SELECT SCHEMA_NAME, KEY_ALIAS FROM " + t(QueryUtils.SCHEMA_SYS, "TABLES") + " ORDER BY SCHEMA_NAME");
+
+        List<List<?>> exp = Arrays.asList(
+            Arrays.asList(SCHEMA_NAME_1, "S1_KEY"),
+            Arrays.asList(SCHEMA_NAME_2, "S2_KEY"),
+            Arrays.asList(SCHEMA_NAME_4, "S4_KEY"),
+            Arrays.asList(SCHEMA_NAME_3, "S3_KEY")
+        );
+
+        Assert.assertEquals(exp, res);
+    }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/AbstractDefaultSchemaTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/AbstractDefaultSchemaTest.java
new file mode 100644
index 0000000..20a4854
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/AbstractDefaultSchemaTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.ignite.internal.processors.query;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import org.apache.ignite.internal.processors.cache.index.AbstractIndexingCommonTest;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Assert;
+import org.junit.Test;
+
+/** Abstract test to verify default sql schema. */
+public abstract class AbstractDefaultSchemaTest extends AbstractIndexingCommonTest {
+    /** Table name. */
+    private static final String TBL_NAME = "T1";
+
+    /**
+     * @param qry Query.
+     */
+    protected abstract List<List<?>> execSql(String qry);
+
+    /**
+     * @param withSchema Whether to specify schema or not.
+     */
+    public String tableName(boolean withSchema) {
+        String prefix = "";
+
+        if (withSchema)
+            prefix += "PUBLIC.";
+
+        return prefix + TBL_NAME;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        startGrid(0);
+    }
+
+    /** */
+    @Test
+    public void testBasicOpsExplicitPublicSchema() {
+        executeStmtsAndVerify(() -> true);
+    }
+
+    /** */
+    @Test
+    public void testBasicOpsImplicitPublicSchema() {
+        executeStmtsAndVerify(() -> false);
+    }
+
+    /** */
+    @Test
+    public void testBasicOpsMixedPublicSchema() {
+        AtomicInteger i = new AtomicInteger();
+
+        executeStmtsAndVerify(() -> (i.incrementAndGet() & 1) == 0);
+    }
+
+    /** */
+    @Test
+    @SuppressWarnings("ThrowableNotThrown")
+    public void testCreateDropNonExistingSchema() {
+        GridTestUtils.assertThrowsWithCause(
+            () -> sql("CREATE TABLE UNKNOWN_SCHEMA." + TBL_NAME + "(id INT PRIMARY KEY, val INT)"),
+            SQLException.class
+        );
+
+        GridTestUtils.assertThrowsWithCause(
+            () -> sql("DROP TABLE UNKNOWN_SCHEMA." + TBL_NAME),
+            SQLException.class
+        );
+    }
+
+    /** */
+    private void executeStmtsAndVerify(Supplier<Boolean> withSchemaDecisionSup) {
+        sql("CREATE TABLE " + tableName(withSchemaDecisionSup.get()) + " (id INT PRIMARY KEY, val INT)");
+
+        sql("CREATE INDEX t1_idx_1 ON " + tableName(withSchemaDecisionSup.get()) + "(val)");
+
+        sql("INSERT INTO " + tableName(withSchemaDecisionSup.get()) + " (id, val) VALUES(1, 2)");
+        sql("SELECT * FROM " + tableName(withSchemaDecisionSup.get()), res -> oneRowList(1, 2).equals(res));
+
+        sql("UPDATE " + tableName(withSchemaDecisionSup.get()) + " SET val = 5");
+        sql("SELECT * FROM " + tableName(withSchemaDecisionSup.get()), res -> oneRowList(1, 5).equals(res));
+
+        sql("DELETE FROM " + tableName(withSchemaDecisionSup.get()) + " WHERE id = 1");
+        sql("SELECT COUNT(*) FROM " + tableName(withSchemaDecisionSup.get()), res -> oneRowList(0L).equals(res));
+
+        sql("SELECT COUNT(*) FROM " + QueryUtils.SCHEMA_SYS + ".TABLES WHERE schema_name = 'PUBLIC' " +
+            "AND table_name = \'" + TBL_NAME + "\'", res -> oneRowList(1L).equals(res));
+
+        sql("DROP TABLE " + tableName(withSchemaDecisionSup.get()));
+    }
+
+    /** */
+    private List<List<?>> oneRowList(Object... args) {
+        return Collections.singletonList(Arrays.asList(args));
+    }
+
+    /** */
+    protected void sql(String qry) {
+        sql(qry, null);
+    }
+
+    /** */
+    protected void sql(String qry, @Nullable Predicate<List<List<?>>> validator) {
+        List<List<?>> res = execSql(qry);
+
+        if (validator != null)
+            Assert.assertTrue(validator.test(res));
+    }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlCustomSchemaTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlCustomSchemaTest.java
new file mode 100644
index 0000000..2e4ae1b
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlCustomSchemaTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.ignite.internal.processors.query;
+
+import java.util.List;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.junit.Test;
+
+/** Verifies custom sql schema through SqlFieldsQuery API. */
+public class IgniteSqlCustomSchemaTest extends AbstractCustomSchemaTest {
+    /** {@inheritDoc} */
+    @Override protected List<List<?>> execSql(String qry) {
+        return grid(0).context().query()
+            .querySqlFields(new SqlFieldsQuery(qry).setLazy(true), false)
+            .getAll();
+    }
+
+    /** {@inheritDoc} */
+    @Test
+    @SuppressWarnings("ThrowableNotThrown")
+    @Override public void testCreateTblsInDiffSchemasForSameCache() {
+        final String testCache = "cache1";
+
+        execSql("CREATE TABLE " + t(SCHEMA_NAME_1, TBL_NAME)
+            + " (s1_key INT PRIMARY KEY, s1_val INT) WITH \"cache_name=" + testCache + "\"");
+
+        GridTestUtils.assertThrowsWithCause(
+            () -> execSql("CREATE TABLE " + t(SCHEMA_NAME_2, TBL_NAME)
+                + " (s1_key INT PRIMARY KEY, s2_val INT) WITH \"cache_name=" + testCache + "\""),
+            IgniteSQLException.class
+        );
+
+        execSql("DROP TABLE " + t(SCHEMA_NAME_1, TBL_NAME));
+    }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlCustomSchemaWithPdsEnabled.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlCustomSchemaWithPdsEnabled.java
new file mode 100644
index 0000000..d04bdd2
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlCustomSchemaWithPdsEnabled.java
@@ -0,0 +1,148 @@
+/*
+ * 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.ignite.internal.processors.query;
+
+import java.util.List;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.cache.index.AbstractIndexingCommonTest;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+/** Test verifies custom sql schema behavior when PDS is enabled. */
+public class IgniteSqlCustomSchemaWithPdsEnabled extends AbstractIndexingCommonTest {
+    /** */
+    private static final String CACHE_NAME = "cache_4";
+
+    /** */
+    private static final String SCHEMA_NAME_1 = "SCHEMA_1";
+
+    /** */
+    private static final String SCHEMA_NAME_2 = "SCHEMA_2";
+
+    /** */
+    private static final String SCHEMA_NAME_3 = "ScHeMa3";
+
+    /** */
+    private static final String SCHEMA_NAME_4 = "SCHEMA_4";
+
+    /** */
+    private static final String TABLE_NAME = "T1";
+
+    /** */
+    private static final String[] ALL_SCHEMAS =
+        new String[]{SCHEMA_NAME_1, SCHEMA_NAME_2, SCHEMA_NAME_3, SCHEMA_NAME_4};
+
+    /** */
+    private static String t(String schema, String tbl) {
+        return schema + "." + tbl;
+    }
+
+    /** */
+    private static String q(String str) {
+        return "\"" + str + "\"";
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        return super.getConfiguration(igniteInstanceName)
+            .setSqlSchemas(SCHEMA_NAME_1, SCHEMA_NAME_2, q(SCHEMA_NAME_3))
+            .setDataStorageConfiguration(
+                new DataStorageConfiguration().setDefaultDataRegionConfiguration(
+                    new DataRegionConfiguration().setPersistenceEnabled(true)));
+    }
+
+    /** */
+    @After
+    public void tearDown() throws Exception {
+        stopAllGrids();
+
+        cleanPersistenceDir();
+    }
+
+    /** */
+    @Test
+    public void testSimpleRestart() throws Exception {
+        startAndActivate().createCache(new CacheConfiguration<>(CACHE_NAME).setSqlSchema(SCHEMA_NAME_4));
+
+        for (String schemaName : ALL_SCHEMAS) {
+            execSql("CREATE TABLE " + t(q(schemaName), TABLE_NAME) + "(id INT PRIMARY KEY, val VARCHAR)");
+
+            for (int i = 0; i < 10; i++)
+                execSql("INSERT INTO " + t(q(schemaName), TABLE_NAME) + "(id, val) VALUES (" + i + ", '" + schemaName + "')");
+        }
+
+        stopGrid(0);
+
+        startGrid(0).cluster().active(true);
+
+        for (String schemaName : ALL_SCHEMAS) {
+            List<List<?>> act = execSql("SELECT COUNT(*) FROM " + t(q(schemaName), TABLE_NAME)
+                + " WHERE val = '" + schemaName + "'");
+
+            Assert.assertEquals(10L, act.get(0).get(0));
+        }
+    }
+
+    /** */
+    @Test
+    public void testRecreateAfterRestart() throws Exception {
+        IgniteCache<?, ?> cache = startAndActivate().createCache(
+            new CacheConfiguration<>(CACHE_NAME).setSqlSchema(SCHEMA_NAME_4));
+
+        verifyCacheInSchema(CACHE_NAME, SCHEMA_NAME_4);
+
+        cache.destroy();
+
+        stopGrid(0);
+
+        startAndActivate().createCache(new CacheConfiguration<>(CACHE_NAME).setSqlSchema(SCHEMA_NAME_4));
+
+        verifyCacheInSchema(CACHE_NAME, SCHEMA_NAME_4);
+    }
+
+    /** */
+    private void verifyCacheInSchema(String cacheName, String expSchema) {
+        Object actSchema = execSql("SELECT SQL_SCHEMA FROM " + t(QueryUtils.SCHEMA_SYS, "CACHES")
+            + " WHERE CACHE_NAME = '" + cacheName + "'").get(0).get(0);
+
+        Assert.assertEquals(expSchema, actSchema);
+    }
+
+    /** */
+    private IgniteEx startAndActivate() throws Exception {
+        IgniteEx ignite = startGrid(0);
+
+        ignite.cluster().active(true);
+
+        return ignite;
+    }
+
+    /** */
+    private List<List<?>> execSql(String qry) {
+        return grid(0).context().query()
+            .querySqlFields(new SqlFieldsQuery(qry).setLazy(true), false)
+            .getAll();
+    }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlDefaultSchemaTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlDefaultSchemaTest.java
new file mode 100644
index 0000000..7334e4b
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlDefaultSchemaTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.ignite.internal.processors.query;
+
+import java.util.List;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+
+/** Verifies default sql schema through SqlFieldsQuery API. */
+public class IgniteSqlDefaultSchemaTest extends AbstractDefaultSchemaTest {
+    /** {@inheritDoc} */
+    @Override protected List<List<?>> execSql(String qry) {
+        return grid(0).context().query()
+            .querySqlFields(new SqlFieldsQuery(qry).setLazy(true), false)
+            .getAll();
+    }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemasDiffConfigurationsTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemasDiffConfigurationsTest.java
new file mode 100644
index 0000000..1fce5a9
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemasDiffConfigurationsTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.ignite.internal.processors.query;
+
+import java.util.Arrays;
+import java.util.List;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.cache.index.AbstractIndexingCommonTest;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+/** Verifies custom sql schema within different configurations. */
+public class IgniteSqlSchemasDiffConfigurationsTest extends AbstractIndexingCommonTest {
+    /** */
+    private static final String SCHEMA_NAME_1 = "SCHEMA_1";
+
+    /** */
+    private static final String SCHEMA_NAME_2 = "SCHEMA_2";
+
+    /** */
+    private static final String SCHEMA_NAME_3 = "SCHEMA_3";
+
+    /** */
+    private static final String SCHEMA_NAME_4 = "SCHEMA_4";
+
+    /** */
+    private static String t(String schema, String tbl) {
+        return schema + "." + tbl;
+    }
+
+    /** */
+    @After
+    public void tearDown() {
+        stopAllGrids();
+    }
+
+    /** */
+    @Test
+    public void testDiffSqlSchemasCfgProp() throws Exception {
+        startGrid(getConfiguration("ign1").setSqlSchemas(SCHEMA_NAME_1, SCHEMA_NAME_2));
+
+        startGrid(getConfiguration("ign2").setSqlSchemas(SCHEMA_NAME_3, SCHEMA_NAME_4));
+
+        List<List<String>> exp = Arrays.asList(
+            Arrays.asList(SCHEMA_NAME_1, "cache_1"),
+            Arrays.asList(SCHEMA_NAME_2, "cache_2"),
+            Arrays.asList(SCHEMA_NAME_3, "cache_3"),
+            Arrays.asList(SCHEMA_NAME_4, "cache_4")
+        );
+
+        for (List<String> row : exp)
+            grid("ign1").createCache(new CacheConfiguration<>(row.get(1)).setSqlSchema(row.get(0)));
+
+        List<List<?>> res = execSql("ign1", "SELECT SQL_SCHEMA, CACHE_NAME FROM "
+            + t(QueryUtils.SCHEMA_SYS, "CACHES") + " WHERE CACHE_NAME LIKE 'cache%' ORDER BY SQL_SCHEMA");
+
+        Assert.assertEquals(exp, res);
+    }
+
+    /** */
+    private IgniteConfiguration createTestConf(String nodeName, String schemaName, String cacheName) throws Exception {
+        return getConfiguration(nodeName)
+            .setCacheConfiguration(new CacheConfiguration(cacheName).setSqlSchema(schemaName));
+    }
+
+    /** */
+    protected List<List<?>> execSql(String ignName, String qry) {
+        return grid(ignName).context().query()
+            .querySqlFields(new SqlFieldsQuery(qry).setLazy(true), false)
+            .getAll();
+    }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/JdbcSqlCustomSchemaTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/JdbcSqlCustomSchemaTest.java
new file mode 100644
index 0000000..c48a0ac
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/JdbcSqlCustomSchemaTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.ignite.internal.processors.query;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/** Verifies custom sql schema through JDBC API. */
+public class JdbcSqlCustomSchemaTest extends AbstractCustomSchemaTest {
+    /** SELECT query pattern. */
+    private static final Pattern SELECT_QRY_PATTERN = Pattern.compile("^SELECT .*");
+
+    /** Connection. */
+    private Connection conn;
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        if (conn != null && !conn.isClosed())
+            conn.close();
+
+        super.afterTestsStopped();
+    }
+
+    /** */
+    private Connection getOrCreateConnection() throws SQLException {
+        if (conn == null)
+            conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1");
+
+        return conn;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected List<List<?>> execSql(String qry) {
+        try (Statement stmt = getOrCreateConnection().createStatement()) {
+            if (SELECT_QRY_PATTERN.matcher(qry).matches())
+                return resultSetToList(stmt.executeQuery(qry));
+            else {
+                stmt.execute(qry);
+
+                return Collections.emptyList();
+            }
+        }
+        catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /** Converts {@link ResultSet} to list of lists. */
+    private List<List<?>> resultSetToList(ResultSet rs) throws SQLException {
+        List<List<?>> res = new ArrayList<>();
+
+        while (rs.next()) {
+            List<Object> row = new ArrayList<>();
+
+            res.add(row);
+
+            for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++)
+                row.add(rs.getObject(i));
+        }
+
+        return res;
+    }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/JdbcSqlDefaultSchemaTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/JdbcSqlDefaultSchemaTest.java
new file mode 100644
index 0000000..fb2d358
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/JdbcSqlDefaultSchemaTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.ignite.internal.processors.query;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/** Verifies default sql schema through JDBC API. */
+public class JdbcSqlDefaultSchemaTest extends AbstractDefaultSchemaTest {
+    /** SELECT query pattern. */
+    private static final Pattern SELECT_QRY_PATTERN = Pattern.compile("^SELECT .*");
+
+    /** Connection. */
+    private Connection conn;
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        if (conn != null && !conn.isClosed())
+            conn.close();
+
+        super.afterTestsStopped();
+    }
+
+    /** */
+    private Connection getOrCreateConnection() throws SQLException {
+        if (conn == null)
+            conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1");
+
+        return conn;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected List<List<?>> execSql(String qry) {
+        try (Statement stmt = getOrCreateConnection().createStatement()) {
+            if (SELECT_QRY_PATTERN.matcher(qry).matches())
+                return resultSetToList(stmt.executeQuery(qry));
+            else {
+                stmt.execute(qry);
+
+                return Collections.emptyList();
+            }
+        }
+        catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /** Converts {@link ResultSet} to list of lists. */
+    private List<List<?>> resultSetToList(ResultSet rs) throws SQLException {
+        List<List<?>> res = new ArrayList<>();
+
+        while (rs.next()) {
+            List<Object> row = new ArrayList<>();
+
+            res.add(row);
+
+            for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++)
+                row.add(rs.getObject(i));
+        }
+
+        return res;
+    }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
index 53166e1..4234735 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
@@ -185,6 +185,9 @@ import org.apache.ignite.internal.processors.query.IgniteCachelessQueriesSelfTes
 import org.apache.ignite.internal.processors.query.IgniteQueryDedicatedPoolTest;
 import org.apache.ignite.internal.processors.query.IgniteQueryTableLockAndConnectionPoolLazyModeOffTest;
 import org.apache.ignite.internal.processors.query.IgniteQueryTableLockAndConnectionPoolLazyModeOnTest;
+import org.apache.ignite.internal.processors.query.IgniteSqlCustomSchemaTest;
+import org.apache.ignite.internal.processors.query.IgniteSqlCustomSchemaWithPdsEnabled;
+import org.apache.ignite.internal.processors.query.IgniteSqlDefaultSchemaTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlDefaultValueTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlDistributedJoinSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlEntryCacheModeAgnosticTest;
@@ -196,11 +199,14 @@ import org.apache.ignite.internal.processors.query.IgniteSqlParameterizedQueryTe
 import org.apache.ignite.internal.processors.query.IgniteSqlQueryParallelismTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlRoutingTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSchemaIndexingTest;
+import org.apache.ignite.internal.processors.query.IgniteSqlSchemasDiffConfigurationsTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSegmentedIndexMultiNodeSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSegmentedIndexSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSkipReducerOnUpdateDmlFlagSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSkipReducerOnUpdateDmlSelfTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSplitterSelfTest;
+import org.apache.ignite.internal.processors.query.JdbcSqlCustomSchemaTest;
+import org.apache.ignite.internal.processors.query.JdbcSqlDefaultSchemaTest;
 import org.apache.ignite.internal.processors.query.KillQueryFromClientTest;
 import org.apache.ignite.internal.processors.query.KillQueryFromNeighbourTest;
 import org.apache.ignite.internal.processors.query.KillQueryOnClientDisconnectTest;
@@ -520,6 +526,13 @@ import org.junit.runners.Suite;
     IgniteSQLColumnConstraintsTest.class,
     IgniteTransactionSQLColumnConstraintTest.class,
 
+    IgniteSqlDefaultSchemaTest.class,
+    IgniteSqlCustomSchemaTest.class,
+    JdbcSqlDefaultSchemaTest.class,
+    JdbcSqlCustomSchemaTest.class,
+    IgniteSqlCustomSchemaWithPdsEnabled.class,
+    IgniteSqlSchemasDiffConfigurationsTest.class,
+
     IgniteCachePartitionedAtomicColumnConstraintsTest.class,
     IgniteCachePartitionedTransactionalColumnConstraintsTest.class,
     IgniteCachePartitionedTransactionalSnapshotColumnConstraintTest.class,