This is an automated email from the ASF dual-hosted git repository.
vozerov 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 3e80ca4 IGNITE-10414: SQL: Fixed schema resolution for JDBC drivers.
This closes #6088.
3e80ca4 is described below
commit 3e80ca44e4f6818eeb6f69980e5a5afb22b698e6
Author: Pavel Kuznetsov <[email protected]>
AuthorDate: Mon Mar 11 12:01:06 2019 +0300
IGNITE-10414: SQL: Fixed schema resolution for JDBC drivers. This closes
#6088.
---
.../internal/jdbc2/JdbcAbstractSchemaCaseTest.java | 228 +++++++++++++++++++++
.../internal/jdbc2/JdbcMetadataSelfTest.java | 2 +-
.../internal/jdbc2/JdbcSchemaCaseSelfTest.java | 41 ++++
.../jdbc/suite/IgniteJdbcDriverTestSuite.java | 6 +-
.../jdbc/thin/JdbcThinSchemaCaseSelfTest.java | 33 +++
.../ignite/jdbc/thin/JdbcThinSchemaCaseTest.java | 114 -----------
.../internal/jdbc/thin/JdbcThinConnection.java | 26 +--
.../ignite/internal/jdbc2/JdbcConnection.java | 2 +-
.../apache/ignite/internal/jdbc2/JdbcUtils.java | 22 ++
.../processors/query/GridQueryProcessor.java | 4 +-
.../cache/index/H2DynamicTableSelfTest.java | 36 +++-
.../processors/query/RunningQueriesTest.java | 78 ++++---
.../processors/query/SqlSystemViewsSelfTest.java | 14 +-
13 files changed, 429 insertions(+), 177 deletions(-)
diff --git
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractSchemaCaseTest.java
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractSchemaCaseTest.java
new file mode 100644
index 0000000..5995010
--- /dev/null
+++
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcAbstractSchemaCaseTest.java
@@ -0,0 +1,228 @@
+/*
+ * 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.jdbc2;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Base (for v2 and thin drivers) test for the case (in)sensitivity of schema
name.
+ */
+public abstract class JdbcAbstractSchemaCaseTest extends
GridCommonAbstractTest {
+ /** Grid count. */
+ private static final int GRID_CNT = 2;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String
igniteInstanceName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+ cfg.setCacheConfiguration(
+ cacheConfiguration("test0", "test0"),
+ cacheConfiguration("test1", "tEst1"),
+ cacheConfiguration("test2", "\"TestCase\""));
+
+ return cfg;
+ }
+
+ /**
+ * Set up connection with specified schema as default JDBC connection
schema.
+ */
+ protected abstract Connection connect(String schema) throws SQLException;
+
+ /**
+ * @param name Cache name.
+ * @param schema Schema name.
+ * @return Cache configuration.
+ * @throws Exception In case of error.
+ */
+ @SuppressWarnings("unchecked")
+ private CacheConfiguration cacheConfiguration(@NotNull String name,
@NotNull String schema) throws Exception {
+ CacheConfiguration cfg = defaultCacheConfiguration();
+
+ cfg.setIndexedTypes(Integer.class, Integer.class);
+
+ cfg.setName(name);
+
+ cfg.setSqlSchema(schema);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ startGridsMultiThreaded(GRID_CNT);
+ }
+
+ /**
+ * Cleanup.
+ */
+ @Before
+ public void dropTables() throws Exception {
+ List<String> schemas = getSchemasWithTestTable();
+
+ try (Connection conn = connect("PUBLIC")) {
+ Statement stmt = conn.createStatement();
+
+ for (String schema : schemas)
+ stmt.executeUpdate("DROP TABLE IF EXISTS \"" + schema +
"\".TAB");
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @SuppressWarnings({"unused"})
+ @Test
+ public void testSchemaName() throws Exception {
+ checkSchemaConnection("test0");
+ checkSchemaConnection("test1");
+ checkSchemaConnection("\"TestCase\"");
+ checkSchemaConnection("\"TEST0\"");
+ checkSchemaConnection("\"TEST1\"");
+
+ GridTestUtils.assertThrows(log, new Callable<Object>() {
+ @Override public Object call() throws Exception {
+ checkSchemaConnection("TestCase");
+
+ return null;
+ }
+ }, SQLException.class, null);
+ }
+
+ /**
+ * Check case (in)sensitivity of schema name that is specified in the
connection url.
+ */
+ @Test
+ public void testSchemaNameWithCreateTableIfNotExists() throws Exception {
+ createTableWithImplicitSchema("test0");
+
+ assertTablesInSchemasPresented("TEST0"); // due to its normalized.
+
+ createTableWithImplicitSchema("test1");
+
+ assertTablesInSchemasPresented("TEST0", "TEST1");
+
+ createTableWithImplicitSchema("\"TestCase\"");
+
+ assertTablesInSchemasPresented("TEST0", "TEST1", "TestCase");
+
+ createTableWithImplicitSchema("\"TEST0\"");
+
+ assertTablesInSchemasPresented("TEST0", "TEST1", "TestCase");
+
+ createTableWithImplicitSchema("\"TEST1\"");
+
+ assertTablesInSchemasPresented("TEST0", "TEST1", "TestCase");
+
+ GridTestUtils.assertThrows(log, new Callable<Object>() {
+ @Override public Object call() throws Exception {
+ createTableWithImplicitSchema("TestCase"); // due to
normalization it is converted to "TESTCASE".
+
+ return null;
+ }
+ }, SQLException.class, null);
+ }
+
+ /**
+ * @param schema Schema name.
+ * @throws SQLException If failed.
+ */
+ private void checkSchemaConnection(String schema) throws SQLException {
+ try (Connection conn = connect(schema)) {
+ Statement stmt = conn.createStatement();
+
+ assertNotNull(stmt);
+ assertFalse(stmt.isClosed());
+
+ stmt.execute("select t._key, t._val from Integer t");
+ }
+ }
+
+ /**
+ * Create table with schema that is specified in connection properties.
+ *
+ * @param schema Schema.
+ */
+ private void createTableWithImplicitSchema(String schema) throws
SQLException {
+ try (Connection conn = connect(schema)) {
+ execute(conn, "CREATE TABLE IF NOT EXISTS TAB (id INT PRIMARY KEY,
val INT);");
+ execute(conn, "CREATE TABLE IF NOT EXISTS TAB (id INT PRIMARY KEY,
val INT);");
+ execute(conn, "CREATE TABLE IF NOT EXISTS TAB (newId VARCHAR
PRIMARY KEY, val VARCHAR);");
+ execute(conn, "CREATE TABLE IF NOT EXISTS TAB (newId VARCHAR
PRIMARY KEY, val VARCHAR);");
+ }
+ }
+
+ /**
+ * Shortcut to execute prepared statement.
+ */
+ private void execute(Connection conn, String sql) throws SQLException {
+ try (PreparedStatement stmt = conn.prepareStatement(sql)) {
+ stmt.execute();
+ }
+ }
+
+ /**
+ * Retrieves list of schemas, each schema contain test table "TAB".
+ */
+ List<String> getSchemasWithTestTable() throws SQLException {
+ try (Connection conn = connect("PUBLIC")) {
+ Statement stmt = conn.createStatement();
+
+ ArrayList<String> schemasWithTab = new ArrayList<>();
+
+ try (ResultSet tabs = stmt.executeQuery(
+ "SELECT SCHEMA_NAME, TABLE_NAME FROM IGNITE.TABLES " +
+ "WHERE TABLE_NAME = 'TAB' ORDER BY SCHEMA_NAME;")) {
+ while (tabs.next())
+ schemasWithTab.add(tabs.getString("SCHEMA_NAME"));
+ }
+
+ return schemasWithTab;
+ }
+ }
+
+ /**
+ * Assert that table with name "TAB" is presented exactly in specified
schemas. Order of specified schemas is
+ * ignored.
+ *
+ * @param schemas Schemas.
+ */
+ void assertTablesInSchemasPresented(String... schemas) throws SQLException
{
+ Arrays.sort(schemas);
+
+ List<String> exp = Arrays.asList(schemas);
+
+ assertEqualsCollections(exp, getSchemasWithTestTable());
+ }
+}
diff --git
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
index ad21e6a..5172cf7 100755
---
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
@@ -495,7 +495,7 @@ public class JdbcMetadataSelfTest extends
GridCommonAbstractTest {
@Test
public void testParametersMetadata() throws Exception {
try (Connection conn = DriverManager.getConnection(BASE_URL)) {
- conn.setSchema("pers");
+ conn.setSchema("\"pers\"");
PreparedStatement stmt = conn.prepareStatement("select orgId from
Person p where p.name > ? and p.orgId > ?");
diff --git
a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcSchemaCaseSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcSchemaCaseSelfTest.java
new file mode 100644
index 0000000..49fb9cd
--- /dev/null
+++
b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcSchemaCaseSelfTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.jdbc2;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+import static org.apache.ignite.IgniteJdbcDriver.CFG_URL_PREFIX;
+
+/**
+ * Jdbc v2 test for schema name case (in)sensitivity.
+ */
+public class JdbcSchemaCaseSelfTest extends JdbcAbstractSchemaCaseTest {
+ /** JDBC URL. */
+ private static final String BASE_URL = CFG_URL_PREFIX +
"cache=test0@modules/clients/src/test/config/jdbc-config.xml";
+
+ /** {@inheritDoc} */
+ @Override protected Connection connect(String schema) throws SQLException {
+ Connection conn = DriverManager.getConnection(BASE_URL);
+
+ conn.setSchema(schema);
+
+ return conn;
+ }
+}
diff --git
a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
index bdd3700..2aae34e 100644
---
a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
+++
b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
@@ -21,6 +21,7 @@ import org.apache.ignite.internal.jdbc2.JdbcBlobTest;
import org.apache.ignite.internal.jdbc2.JdbcBulkLoadSelfTest;
import org.apache.ignite.internal.jdbc2.JdbcConnectionReopenTest;
import org.apache.ignite.internal.jdbc2.JdbcDistributedJoinsQueryTest;
+import org.apache.ignite.internal.jdbc2.JdbcSchemaCaseSelfTest;
import org.apache.ignite.jdbc.JdbcComplexQuerySelfTest;
import org.apache.ignite.jdbc.JdbcConnectionSelfTest;
import org.apache.ignite.jdbc.JdbcDefaultNoOpCacheTest;
@@ -75,7 +76,7 @@ import
org.apache.ignite.jdbc.thin.JdbcThinMultiStatementSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinNoDefaultSchemaTest;
import org.apache.ignite.jdbc.thin.JdbcThinPreparedStatementSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinResultSetSelfTest;
-import org.apache.ignite.jdbc.thin.JdbcThinSchemaCaseTest;
+import org.apache.ignite.jdbc.thin.JdbcThinSchemaCaseSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinSelectAfterAlterTable;
import org.apache.ignite.jdbc.thin.JdbcThinStatementCancelSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinStatementSelfTest;
@@ -137,6 +138,7 @@ import org.junit.runners.Suite;
org.apache.ignite.internal.jdbc2.JdbcStreamingToPublicCacheTest.class,
org.apache.ignite.internal.jdbc2.JdbcNoCacheStreamingSelfTest.class,
JdbcBulkLoadSelfTest.class,
+ JdbcSchemaCaseSelfTest.class,
JdbcBlobTest.class,
org.apache.ignite.internal.jdbc2.JdbcStreamingSelfTest.class,
@@ -165,7 +167,7 @@ import org.junit.runners.Suite;
JdbcThinStatementSelfTest.class,
JdbcThinComplexQuerySelfTest.class,
JdbcThinNoDefaultSchemaTest.class,
- JdbcThinSchemaCaseTest.class,
+ JdbcThinSchemaCaseSelfTest.class,
JdbcThinEmptyCacheSelfTest.class,
JdbcThinMetadataSelfTest.class,
JdbcThinMetadataPrimaryKeysSelfTest.class,
diff --git
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinSchemaCaseSelfTest.java
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinSchemaCaseSelfTest.java
new file mode 100644
index 0000000..5606c11
--- /dev/null
+++
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinSchemaCaseSelfTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import org.apache.ignite.internal.jdbc2.JdbcAbstractSchemaCaseTest;
+
+/**
+ * Jdbc thin test for schema name case (in)sensitivity.
+ */
+public class JdbcThinSchemaCaseSelfTest extends JdbcAbstractSchemaCaseTest {
+ /** {@inheritDoc} */
+ @Override protected Connection connect(String schema) throws SQLException {
+ return DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1/" +
schema);
+ }
+}
diff --git
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinSchemaCaseTest.java
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinSchemaCaseTest.java
deleted file mode 100644
index c73b0d1..0000000
---
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinSchemaCaseTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.jdbc.thin;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.concurrent.Callable;
-import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.testframework.GridTestUtils;
-import org.jetbrains.annotations.NotNull;
-import org.junit.Test;
-
-/**
- *
- */
-public class JdbcThinSchemaCaseTest extends JdbcThinAbstractSelfTest {
- /** URL. */
- private static final String URL = "jdbc:ignite:thin://127.0.0.1";
-
- /** Grid count. */
- private static final int GRID_CNT = 2;
-
- /** {@inheritDoc} */
- @Override protected IgniteConfiguration getConfiguration(String
igniteInstanceName) throws Exception {
- IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
-
- cfg.setCacheConfiguration(
- cacheConfiguration("test0", "test0"),
- cacheConfiguration("test1", "tEst1"),
- cacheConfiguration("test2", "\"TestCase\""));
-
- return cfg;
- }
-
- /**
- * @param name Cache name.
- * @param schema Schema name.
- * @return Cache configuration.
- * @throws Exception In case of error.
- */
- @SuppressWarnings("unchecked")
- private CacheConfiguration cacheConfiguration(@NotNull String name,
@NotNull String schema) throws Exception {
- CacheConfiguration cfg = defaultCacheConfiguration();
-
- cfg.setIndexedTypes(Integer.class, Integer.class);
-
- cfg.setName(name);
-
- cfg.setSqlSchema(schema);
-
- return cfg;
- }
-
- /** {@inheritDoc} */
- @Override protected void beforeTestsStarted() throws Exception {
- super.beforeTestsStarted();
-
- startGridsMultiThreaded(GRID_CNT);
- }
-
- /**
- * @throws Exception If failed.
- */
- @SuppressWarnings({"unused"})
- @Test
- public void testSchemaName() throws Exception {
- checkSchemaConnection("test0");
- checkSchemaConnection("test1");
- checkSchemaConnection("\"TestCase\"");
- checkSchemaConnection("\"TEST0\"");
- checkSchemaConnection("\"TEST1\"");
-
- GridTestUtils.assertThrows(log, new Callable<Object>() {
- @Override public Object call() throws Exception {
- checkSchemaConnection("TestCase");
-
- return null;
- }
- }, SQLException.class, null);
- }
-
- /**
- * @param schema Schema name.
- * @throws SQLException If failed.
- */
- void checkSchemaConnection(String schema) throws SQLException {
- try (Connection conn = DriverManager.getConnection(URL + '/' +
schema)) {
- Statement stmt = conn.createStatement();
-
- assertNotNull(stmt);
- assertFalse(stmt.isClosed());
-
- stmt.execute("select t._key, t._val from Integer t");
- }
- }
-}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
index c4f0652..113be2b 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
@@ -50,6 +50,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cache.query.QueryCancelledException;
+import org.apache.ignite.internal.jdbc2.JdbcUtils;
import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
import org.apache.ignite.internal.processors.odbc.SqlStateCode;
@@ -63,7 +64,6 @@ import
org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType;
-import org.apache.ignite.internal.processors.query.QueryUtils;
import org.apache.ignite.internal.sql.command.SqlCommand;
import org.apache.ignite.internal.sql.command.SqlSetStreamingCommand;
import org.apache.ignite.internal.util.future.GridFutureAdapter;
@@ -148,7 +148,7 @@ public class JdbcThinConnection implements Connection {
autoCommit = true;
txIsolation = Connection.TRANSACTION_NONE;
- schema = normalizeSchema(connProps.getSchema());
+ schema = JdbcUtils.normalizeSchema(connProps.getSchema());
cliIo = new JdbcThinTcpIo(connProps);
@@ -689,7 +689,7 @@ public class JdbcThinConnection implements Connection {
@Override public void setSchema(String schema) throws SQLException {
ensureNotClosed();
- this.schema = normalizeSchema(schema);
+ this.schema = JdbcUtils.normalizeSchema(schema);
}
/** {@inheritDoc} */
@@ -890,26 +890,6 @@ public class JdbcThinConnection implements Connection {
}
/**
- * Normalize schema name. If it is quoted - unquote and leave as is,
otherwise - convert to upper case.
- *
- * @param schemaName Schema name.
- * @return Normalized schema name.
- */
- private static String normalizeSchema(String schemaName) {
- if (F.isEmpty(schemaName))
- return QueryUtils.DFLT_SCHEMA;
-
- String res;
-
- if (schemaName.startsWith("\"") && schemaName.endsWith("\""))
- res = schemaName.substring(1, schemaName.length() - 1);
- else
- res = schemaName.toUpperCase();
-
- return res;
- }
-
- /**
* Streamer state and
*/
private class StreamState {
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
index 0409c94..e63f426 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
@@ -782,7 +782,7 @@ public class JdbcConnection implements Connection {
/** {@inheritDoc} */
@Override public void setSchema(String schemaName) throws SQLException {
- this.schemaName = schemaName;
+ this.schemaName = JdbcUtils.normalizeSchema(schemaName);
}
/** {@inheritDoc} */
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java
b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java
index 6f7d3a4..9c3b5a1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java
@@ -33,6 +33,7 @@ import
org.apache.ignite.internal.processors.odbc.jdbc.JdbcPrimaryKeyMeta;
import org.apache.ignite.internal.processors.odbc.jdbc.JdbcTableMeta;
import org.apache.ignite.internal.processors.query.IgniteSQLException;
import org.apache.ignite.internal.processors.query.QueryUtils;
+import org.apache.ignite.internal.util.typedef.F;
import static java.sql.DatabaseMetaData.columnNullable;
import static java.sql.DatabaseMetaData.tableIndexOther;
@@ -309,4 +310,25 @@ public class JdbcUtils {
return row;
}
+
+
+ /**
+ * Normalize schema name. If it is quoted - unquote and leave as is,
otherwise - convert to upper case.
+ *
+ * @param schemaName Schema name.
+ * @return Normalized schema name.
+ */
+ public static String normalizeSchema(String schemaName) {
+ if (F.isEmpty(schemaName))
+ return QueryUtils.DFLT_SCHEMA;
+
+ String res;
+
+ if (schemaName.startsWith("\"") && schemaName.endsWith("\""))
+ res = schemaName.substring(1, schemaName.length() - 1);
+ else
+ res = schemaName.toUpperCase();
+
+ return res;
+ }
}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index c3d0b88..bac148d 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -1501,7 +1501,7 @@ public class GridQueryProcessor extends
GridProcessorAdapter {
/**
* Create cache and table from given query entity.
*
- * @param schemaName Schema name to create table in.
+ * @param schemaName Schema name to create table in. Case sensitive, must
not be \"quoted\".
* @param entity Entity to create table from.
* @param templateName Template name.
* @param cacheName Cache name.
@@ -1579,7 +1579,7 @@ public class GridQueryProcessor extends
GridProcessorAdapter {
ccfg.setQueryParallelism(qryParallelism);
ccfg.setEncryptionEnabled(encrypted);
- ccfg.setSqlSchema(schemaName);
+ ccfg.setSqlSchema("\"" + schemaName + "\"");
ccfg.setSqlEscapeAll(true);
ccfg.setQueryEntities(Collections.singleton(entity));
diff --git
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
index b2774d8..701ceda 100644
---
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
+++
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
@@ -35,6 +35,7 @@ import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteException;
import org.apache.ignite.Ignition;
import org.apache.ignite.binary.BinaryObject;
@@ -131,7 +132,7 @@ public class H2DynamicTableSelfTest extends
AbstractSchemaSelfTest {
execute("DROP TABLE IF EXISTS PUBLIC.\"City\"");
execute("DROP TABLE IF EXISTS PUBLIC.\"NameTest\"");
execute("DROP TABLE IF EXISTS PUBLIC.\"BackupTest\"");
-
+
execute("DROP TABLE IF EXISTS PUBLIC.QP_CUSTOM");
execute("DROP TABLE IF EXISTS PUBLIC.QP_DEFAULT");
execute("DROP TABLE IF EXISTS PUBLIC.QP_DEFAULT_EXPLICIT");
@@ -802,6 +803,39 @@ public class H2DynamicTableSelfTest extends
AbstractSchemaSelfTest {
}
/**
+ * Regression test for "if not exists" in case custom schema is used.
Creates the same "schema.table" specifying sql
+ * schema implicitly and explicitly.
+ */
+ @Test
+ public void testCreateTableIfNotExistsCustomSchema() {
+ Ignite ignite = grid(0);
+
+ IgniteCache<Object, Object> cache = ignite.getOrCreateCache("test");
+
+ String createTblNoSchema = "CREATE TABLE IF NOT EXISTS City(id LONG
PRIMARY KEY, name VARCHAR)";
+
+ String createTblExplicitSchema = "CREATE TABLE IF NOT EXISTS
\"test\".City(id LONG PRIMARY KEY, name1 VARCHAR);";
+
+ // Schema is "test" due to cache name implicitly:
+ cache.query(new SqlFieldsQuery(createTblNoSchema));
+ cache.query(new SqlFieldsQuery(createTblNoSchema));
+
+ // Schema is "test" because it is specified in the text of the sql
query.
+ cache.query(new SqlFieldsQuery(createTblExplicitSchema));
+ cache.query(new SqlFieldsQuery(createTblExplicitSchema));
+
+ // Schema is "test", because it is specified in SqlFieldsQuery field.
+ cache.query(new SqlFieldsQuery(createTblNoSchema).setSchema("test"));
+ cache.query(new SqlFieldsQuery(createTblNoSchema).setSchema("test"));
+
+ //only one City table should be created.
+ List<List<?>> cityTabs = cache.query(new SqlFieldsQuery(
+ "SELECT SCHEMA_NAME, TABLE_NAME FROM IGNITE.TABLES WHERE
TABLE_NAME = 'CITY';")).getAll();
+
+
assertEqualsCollections(Collections.singletonList(Arrays.asList("test",
"CITY")), cityTabs);
+ }
+
+ /**
* Test that attempting to {@code CREATE TABLE} that already exists yields
an error.
* @throws Exception if failed.
*/
diff --git
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/RunningQueriesTest.java
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/RunningQueriesTest.java
index be90a5d..ff8fd11 100644
---
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/RunningQueriesTest.java
+++
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/RunningQueriesTest.java
@@ -64,8 +64,11 @@ import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.testframework.GridTestUtils;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
+import org.junit.Rule;
import org.junit.Ignore;
import org.junit.Test;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
import static org.apache.ignite.internal.util.IgniteUtils.resolveIgnitePath;
@@ -80,7 +83,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
private static final long TIMEOUT_IN_MS = TIMEOUT_IN_SEC * 1000;
/** Barrier. */
- private static CyclicBarrier barrier;
+ private static volatile CyclicBarrier barrier;
/** Ignite. */
private static IgniteEx ignite;
@@ -88,6 +91,32 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
/** Node count. */
private static final int NODE_CNT = 2;
+ /** Restarts the grid if if the last test failed. */
+ @Rule public final TestWatcher restarter = new TestWatcher() {
+ /** {@inheritDoc} */
+ @Override protected void failed(Throwable e, Description lastTest) {
+ try {
+ log().error("Last test failed [name=" +
lastTest.getMethodName() +
+ ", reason=" + e.getMessage() + "]. Restarting the grid.");
+
+ // Release the indexing.
+ if (barrier != null)
+ barrier.reset();
+
+ stopAllGrids();
+
+ beforeTestsStarted();
+
+ log().error("Grid restarted.");
+ }
+ catch (Exception restartFailure) {
+ throw new RuntimeException("Failed to recover after test
failure [test=" + lastTest.getMethodName() +
+ ", reason=" + e.getMessage() + "]. Subsequent test results
of this test class are incorrect.",
+ restartFailure);
+ }
+ }
+ };
+
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
super.beforeTestsStarted();
@@ -148,7 +177,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
.findAny()
.ifPresent((c) -> {
try {
- awaitTimeouted();
+ awaitTimeout();
}
catch (Exception e) {
e.printStackTrace();
@@ -157,7 +186,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
}
else if
(SchemaProposeDiscoveryMessage.class.isAssignableFrom(delegate.getClass())) {
try {
- awaitTimeouted();
+ awaitTimeout();
}
catch (Exception e) {
e.printStackTrace();
@@ -179,7 +208,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
||
GridNearAtomicFullUpdateRequest.class.isAssignableFrom(gridMsg.getClass())
) {
try {
- awaitTimeouted();
+ awaitTimeout();
}
catch (Exception ignore) {
}
@@ -222,10 +251,9 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
}
/**
- * Check auto clenup running queries on fully readed iterator.
- *
- * @throws Exception Exception in case of failure.
+ * Check auto cleanup running queries on fully read iterator.
*/
+ @SuppressWarnings("CodeBlock2Expr")
@Test
public void testAutoCloseQueryAfterIteratorIsExhausted(){
IgniteCache<Object, Object> cache = ignite.cache(DEFAULT_CACHE_NAME);
@@ -246,11 +274,9 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
/**
* Check cluster wide query id generation.
- *
- * @throws Exception Exception in case of failure.
*/
@Test
- public void testClusterWideQueryIdGeneration() throws Exception {
+ public void testClusterWideQueryIdGeneration() {
newBarrier(1);
IgniteCache<Object, Object> cache = ignite.cache(DEFAULT_CACHE_NAME);
@@ -300,7 +326,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
assertNoRunningQueries(ignite);
- awaitTimeouted();
+ awaitTimeout();
fut1.get(TIMEOUT_IN_MS);
@@ -367,7 +393,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
IgniteInternalFuture<Integer> fut1 = GridTestUtils.runAsync(() ->
barrier.await());
- awaitTimeouted();
+ awaitTimeout();
fut1.get(TIMEOUT_IN_MS);
@@ -385,9 +411,9 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
ignite.cache(DEFAULT_CACHE_NAME).query(new SqlFieldsQuery("CREATE
TABLE tst_idx_drop(id long PRIMARY KEY, cnt integer)"));
- ignite.cache(DEFAULT_CACHE_NAME).query(new SqlFieldsQuery("CREATE
INDEX tst_idx_drop_idx ON default.tst_idx_drop(cnt)"));
+ ignite.cache(DEFAULT_CACHE_NAME).query(new SqlFieldsQuery("CREATE
INDEX tst_idx_drop_idx ON tst_idx_drop(cnt)"));
- testQueryDDL("DROP INDEX default.tst_idx_drop_idx");
+ testQueryDDL("DROP INDEX tst_idx_drop_idx");
}
/**
@@ -401,7 +427,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
ignite.cache(DEFAULT_CACHE_NAME).query(new SqlFieldsQuery("CREATE
TABLE tst_idx_create(id long PRIMARY KEY, cnt integer)"));
- testQueryDDL("CREATE INDEX tst_idx_create_idx ON
default.tst_idx_create(cnt)");
+ testQueryDDL("CREATE INDEX tst_idx_create_idx ON tst_idx_create(cnt)");
}
/**
@@ -415,7 +441,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
ignite.cache(DEFAULT_CACHE_NAME).query(new SqlFieldsQuery("CREATE
TABLE tst_drop(id long PRIMARY KEY, cnt integer)"));
- testQueryDDL("DROP TABLE default.tst_drop");
+ testQueryDDL("DROP TABLE tst_drop");
}
/**
@@ -452,9 +478,9 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
runningQueries.forEach((info) -> Assert.assertEquals(qry.getSql(),
info.query()));
- awaitTimeouted();
+ awaitTimeout();
- awaitTimeouted();
+ awaitTimeout();
fut.get(TIMEOUT_IN_MS);
}
@@ -493,11 +519,11 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
assertEquals(1, runningQueries.size());
- awaitTimeouted();
+ awaitTimeout();
assertWaitingOnBarrier();
- awaitTimeouted();
+ awaitTimeout();
}
fut.get(TIMEOUT_IN_MS);
@@ -505,7 +531,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
}
/**
- * Check tracking running queries for multistatements.
+ * Check tracking running queries for multi-statements.
*
* @throws Exception Exception in case of failure.
*/
@@ -548,7 +574,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
assertEquals(query, runningQueries.get(0).query());
- awaitTimeouted();
+ awaitTimeout();
}
fut.get(TIMEOUT_IN_MS);
@@ -589,7 +615,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
assertEquals(sql, runningQueries.get(0).query());
- awaitTimeouted();
+ awaitTimeout();
fut.get(TIMEOUT_IN_MS);
}
@@ -608,7 +634,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
/**
* Check all nodes except passed as parameter on no any running queries.
*
- * @param excludeNodes Nodes shich will be excluded from check.
+ * @param excludeNodes Nodes which will be excluded from check.
*/
private void assertNoRunningQueries(IgniteEx... excludeNodes) {
Set<UUID> excludeIds = Stream.of(excludeNodes).map((ignite) ->
ignite.localNode().id()).collect(Collectors.toSet());
@@ -638,7 +664,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
* @throws TimeoutException In case of failure.
* @throws BrokenBarrierException In case of failure.
*/
- private static void awaitTimeouted() throws InterruptedException,
TimeoutException, BrokenBarrierException {
+ private static void awaitTimeout() throws InterruptedException,
TimeoutException, BrokenBarrierException {
barrier.await(TIMEOUT_IN_MS, TimeUnit.SECONDS);
}
@@ -665,7 +691,7 @@ public class RunningQueriesTest extends
AbstractIndexingCommonTest {
);
try {
- awaitTimeouted();
+ awaitTimeout();
}
catch (Exception e) {
throw new IgniteException(e);
diff --git
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSystemViewsSelfTest.java
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSystemViewsSelfTest.java
index 456838c..6e3c505 100644
---
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSystemViewsSelfTest.java
+++
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlSystemViewsSelfTest.java
@@ -185,7 +185,7 @@ public class SqlSystemViewsSelfTest extends
AbstractIndexingCommonTest {
execSql("CREATE TABLE CACHE_SQL (ID INT PRIMARY KEY, MY_VAL VARCHAR)");
- execSql("CREATE INDEX IDX_2 ON DEFAULT.CACHE_SQL(ID DESC) INLINE_SIZE
13");
+ execSql("CREATE INDEX IDX_2 ON \"default\".CACHE_SQL(ID DESC)
INLINE_SIZE 13");
execSql("CREATE TABLE PUBLIC.DFLT_CACHE (ID1 INT, ID2 INT, MY_VAL
VARCHAR, PRIMARY KEY (ID1 DESC, ID2))");
@@ -213,10 +213,10 @@ public class SqlSystemViewsSelfTest extends
AbstractIndexingCommonTest {
{"PUBLIC", "AFF_CACHE", "_key_PK", "\"ID1\" ASC, \"ID2\" ASC",
"BTREE", "true", "true", "-825022849", "SQL_PUBLIC_AFF_CACHE", "-825022849",
"SQL_PUBLIC_AFF_CACHE", "10"},
{"PUBLIC", "AFF_CACHE", "_key_PK_hash", "\"ID1\" ASC, \"ID2\" ASC,
\"ID2\" ASC", "HASH", "false", "true", "-825022849", "SQL_PUBLIC_AFF_CACHE",
"-825022849", "SQL_PUBLIC_AFF_CACHE", "null"},
- {"DEFAULT", "CACHE_SQL", "IDX_2", "\"ID\" DESC, \"ID\" ASC",
"BTREE", "false", "false", "683914882", "SQL_default_CACHE_SQL", "683914882",
"SQL_default_CACHE_SQL", "13"},
- {"DEFAULT", "CACHE_SQL", "__SCAN_", "null", "SCAN", "false",
"false", "683914882", "SQL_default_CACHE_SQL", "683914882",
"SQL_default_CACHE_SQL", "null"},
- {"DEFAULT", "CACHE_SQL", "_key_PK", "\"ID\" ASC", "BTREE", "true",
"true", "683914882", "SQL_default_CACHE_SQL", "683914882",
"SQL_default_CACHE_SQL", "5"},
- {"DEFAULT", "CACHE_SQL", "_key_PK_hash", "\"ID\" ASC", "HASH",
"false", "true", "683914882", "SQL_default_CACHE_SQL", "683914882",
"SQL_default_CACHE_SQL", "null"},
+ {"default", "CACHE_SQL", "IDX_2", "\"ID\" DESC, \"ID\" ASC",
"BTREE", "false", "false", "683914882", "SQL_default_CACHE_SQL", "683914882",
"SQL_default_CACHE_SQL", "13"},
+ {"default", "CACHE_SQL", "__SCAN_", "null", "SCAN", "false",
"false", "683914882", "SQL_default_CACHE_SQL", "683914882",
"SQL_default_CACHE_SQL", "null"},
+ {"default", "CACHE_SQL", "_key_PK", "\"ID\" ASC", "BTREE", "true",
"true", "683914882", "SQL_default_CACHE_SQL", "683914882",
"SQL_default_CACHE_SQL", "5"},
+ {"default", "CACHE_SQL", "_key_PK_hash", "\"ID\" ASC", "HASH",
"false", "true", "683914882", "SQL_default_CACHE_SQL", "683914882",
"SQL_default_CACHE_SQL", "null"},
{"PUBLIC", "DFLT_AFF_CACHE", "AFFINITY_KEY", "\"ID1\" ASC, \"ID2\"
ASC", "BTREE", "false", "false", "1374144180", "SQL_PUBLIC_DFLT_AFF_CACHE",
"1374144180", "SQL_PUBLIC_DFLT_AFF_CACHE", "10"},
{"PUBLIC", "DFLT_AFF_CACHE", "IDX_AFF_1", "\"ID2\" DESC, \"ID1\"
ASC, \"MY_VAL\" DESC", "BTREE", "false", "false", "1374144180",
"SQL_PUBLIC_DFLT_AFF_CACHE", "1374144180", "SQL_PUBLIC_DFLT_AFF_CACHE", "10"},
@@ -759,7 +759,7 @@ public class SqlSystemViewsSelfTest extends
AbstractIndexingCommonTest {
execSql("CREATE TABLE TST(id INTEGER PRIMARY KEY, name VARCHAR, age
integer)");
for (int i = 0; i < 500; i++)
- execSql("INSERT INTO DEFAULT.TST(id, name, age) VALUES (" + i +
",'name-" + i + "'," + i + 1 + ")");
+ execSql("INSERT INTO \"default\".TST(id, name, age) VALUES (" + i
+ ",'name-" + i + "'," + i + 1 + ")");
String sql1 = "SELECT GROUP_ID, GROUP_NAME, PHYSICAL_READS,
LOGICAL_READS FROM IGNITE.LOCAL_CACHE_GROUPS_IO";
@@ -802,7 +802,7 @@ public class SqlSystemViewsSelfTest extends
AbstractIndexingCommonTest {
List<List<?>> cacheSqlInfos = execSql("SELECT * FROM IGNITE.TABLES
WHERE TABLE_NAME = 'CACHE_SQL'");
List<?> expRow = asList(
- "DEFAULT", // SCHEMA_NAME
+ "default", // SCHEMA_NAME
"CACHE_SQL", // TABLE_NAME
"cache_sql", // CACHE_NAME
cacheSqlId, // CACHE_ID