IGNITE-9279: SQL: custom predefined schemas. This closes #4550. This closes #4586.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/277010cd Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/277010cd Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/277010cd Branch: refs/heads/ignite-9340 Commit: 277010cddf184fa749f5280487015efc0a928c4b Parents: bab61f1 Author: devozerov <[email protected]> Authored: Wed Aug 22 13:41:44 2018 +0300 Committer: devozerov <[email protected]> Committed: Wed Aug 22 13:41:44 2018 +0300 ---------------------------------------------------------------------- .../jdbc/suite/IgniteJdbcDriverTestSuite.java | 2 + ...bcThinComplexDmlDdlCustomSchemaSelfTest.java | 78 ++++++++ .../thin/JdbcThinComplexDmlDdlSelfTest.java | 20 +- .../configuration/IgniteConfiguration.java | 33 ++++ .../processors/cache/GridCacheProcessor.java | 19 ++ .../utils/PlatformConfigurationUtils.java | 23 +++ .../internal/processors/query/h2/H2Schema.java | 31 ++- .../processors/query/h2/IgniteH2Indexing.java | 132 +++++++------ .../query/h2/ddl/DdlStatementsProcessor.java | 97 +++++----- .../cache/index/H2DynamicTableSelfTest.java | 29 --- .../query/SqlIllegalSchemaSelfTest.java | 187 +++++++++++++++++++ .../IgniteCacheQuerySelfTestSuite.java | 2 + .../Config/full-config.xml | 4 + .../IgniteConfigurationSerializerTest.cs | 6 + .../IgniteConfigurationTest.cs | 10 +- .../Apache.Ignite.Core/IgniteConfiguration.cs | 34 ++++ .../IgniteConfigurationSection.xsd | 10 + 17 files changed, 557 insertions(+), 160 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java ---------------------------------------------------------------------- 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 f3490aa..889a551 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 @@ -43,6 +43,7 @@ import org.apache.ignite.jdbc.thin.JdbcThinBulkLoadAtomicReplicatedSelfTest; import org.apache.ignite.jdbc.thin.JdbcThinBulkLoadTransactionalPartitionedNearSelfTest; import org.apache.ignite.jdbc.thin.JdbcThinBulkLoadTransactionalPartitionedSelfTest; import org.apache.ignite.jdbc.thin.JdbcThinBulkLoadTransactionalReplicatedSelfTest; +import org.apache.ignite.jdbc.thin.JdbcThinComplexDmlDdlCustomSchemaSelfTest; import org.apache.ignite.jdbc.thin.JdbcThinComplexDmlDdlSelfTest; import org.apache.ignite.jdbc.thin.JdbcThinComplexDmlDdlSkipReducerOnUpdateSelfTest; import org.apache.ignite.jdbc.thin.JdbcThinComplexQuerySelfTest; @@ -194,6 +195,7 @@ public class IgniteJdbcDriverTestSuite extends TestSuite { suite.addTest(new TestSuite(JdbcThinUpdateStatementSkipReducerOnUpdateSelfTest.class)); suite.addTest(new TestSuite(JdbcThinMergeStatementSkipReducerOnUpdateSelfTest.class)); suite.addTest(new TestSuite(JdbcThinComplexDmlDdlSkipReducerOnUpdateSelfTest.class)); + suite.addTest(new TestSuite(JdbcThinComplexDmlDdlCustomSchemaSelfTest.class)); suite.addTest(new TestSuite(JdbcThinLocalQueriesSelfTest.class)); http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlCustomSchemaSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlCustomSchemaSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlCustomSchemaSelfTest.java new file mode 100644 index 0000000..8fd9356 --- /dev/null +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlCustomSchemaSelfTest.java @@ -0,0 +1,78 @@ +/* + * 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 org.apache.ignite.configuration.IgniteConfiguration; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +/** + * Base class for complex SQL tests based on JDBC driver. + */ +public class JdbcThinComplexDmlDdlCustomSchemaSelfTest extends JdbcThinComplexDmlDdlSelfTest { + /** Simple schema. */ + private static final String SCHEMA_1 = "SCHEMA_1"; + + /** Complex schema. */ + private static final String SCHEMA_2 = "\"SCHEMA 2\""; + + /** Current schema. */ + private String curSchema = SCHEMA_1; + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); + + cfg.setSqlSchemas(SCHEMA_1, SCHEMA_2); + + return cfg; + } + + /** {@inheritDoc} */ + @Override protected Connection createConnection() throws SQLException { + return DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1/" + curSchema); + } + + /** + * Test create/select/drop flow on escaped schema. + * + * @throws Exception If failed. + */ + public void testCreateSelectDropEscapedSchema() throws Exception { + try { + curSchema = SCHEMA_2; + + testCreateSelectDrop(); + } + finally { + curSchema = SCHEMA_1; + } + } + + /** + * Test multiple iterations. + * + * @throws Exception If failed. + */ + public void testMultiple() throws Exception { + testCreateSelectDrop(); + testCreateSelectDrop(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlSelfTest.java index 9c40948..36ee34a 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlSelfTest.java @@ -33,12 +33,10 @@ import org.apache.ignite.cache.CacheMode; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor; -import org.apache.ignite.lang.IgniteCallable; import org.apache.ignite.lang.IgnitePredicate; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder; import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; -import org.apache.ignite.testframework.GridTestUtils; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.jetbrains.annotations.NotNull; @@ -82,9 +80,8 @@ public class JdbcThinComplexDmlDdlSelfTest extends GridCommonAbstractTest { /** * @param name Cache name. * @return Cache configuration. - * @throws Exception In case of error. */ - private CacheConfiguration cacheConfiguration(@NotNull String name) throws Exception { + private CacheConfiguration cacheConfiguration(@NotNull String name) { CacheConfiguration cfg = defaultCacheConfiguration(); cfg.setName(name); @@ -110,8 +107,6 @@ public class JdbcThinComplexDmlDdlSelfTest extends GridCommonAbstractTest { /** {@inheritDoc} */ @Override protected void beforeTest() throws Exception { super.beforeTest(); - - conn = createConnection(); } /** {@inheritDoc} */ @@ -133,14 +128,8 @@ public class JdbcThinComplexDmlDdlSelfTest extends GridCommonAbstractTest { * @throws Exception If failed. */ @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void testCreateSelect() throws Exception { - GridTestUtils.assertThrows(null, new IgniteCallable<Object>() { - @Override public Object call() throws Exception { - sql(new ResultChecker(new Object[][] {}), "SELECT * from Person"); - - return null; - } - }, SQLException.class, "Table \"PERSON\" not found"); + public void testCreateSelectDrop() throws Exception { + conn = createConnection(); sql(new UpdateChecker(0), "CREATE TABLE person (id int, name varchar, age int, company varchar, city varchar, " + @@ -228,6 +217,9 @@ public class JdbcThinComplexDmlDdlSelfTest extends GridCommonAbstractTest { assert cnt[0] == 34 : "Invalid rows count"; sql(new UpdateChecker(0), "DROP INDEX idx"); + + sql(new UpdateChecker(0), "DROP TABLE city"); + sql(new UpdateChecker(0), "DROP TABLE person"); } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java index cc3ea10..ab54709 100644 --- a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java +++ b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java @@ -496,6 +496,9 @@ public class IgniteConfiguration { /** Communication failure resolver */ private CommunicationFailureResolver commFailureRslvr; + /** SQL schemas to be created on node start. */ + private String[] sqlSchemas; + /** * Creates valid grid configuration with all default values. */ @@ -594,6 +597,7 @@ public class IgniteConfiguration { sndRetryCnt = cfg.getNetworkSendRetryCount(); sndRetryDelay = cfg.getNetworkSendRetryDelay(); sqlConnCfg = cfg.getSqlConnectorConfiguration(); + sqlSchemas = cfg.getSqlSchemas(); sslCtxFactory = cfg.getSslContextFactory(); storeSesLsnrs = cfg.getCacheStoreSessionListenerFactories(); stripedPoolSize = cfg.getStripedPoolSize(); @@ -3001,6 +3005,35 @@ public class IgniteConfiguration { return this; } + /** + * Gets SQL schemas to be created on node startup. + * <p> + * See {@link #setSqlSchemas(String...)} for more information. + * + * @return SQL schemas to be created on node startup. + */ + public String[] getSqlSchemas() { + return sqlSchemas; + } + + /** + * Sets SQL schemas to be created on node startup. Schemas are created on local node only and are not propagated + * to other cluster nodes. Created schemas cannot be dropped. + * <p> + * By default schema names are case-insensitive, i.e. {@code my_schema} and {@code My_Schema} represents the same + * object. Use quotes to enforce case sensitivity (e.g. {@code "My_Schema"}). + * <p> + * Property is ignored if {@code ignite-indexing} module is not in classpath. + * + * @param sqlSchemas SQL schemas to be created on node startup. + * @return {@code this} for chaining. + */ + public IgniteConfiguration setSqlSchemas(String... sqlSchemas) { + this.sqlSchemas = sqlSchemas; + + return this; + } + /** {@inheritDoc} */ @Override public String toString() { return S.toString(IgniteConfiguration.class, this); http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java index 6818e50..272aad4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java @@ -541,6 +541,25 @@ public class GridCacheProcessor extends GridProcessorAdapter { throw new IgniteCheckedException("Using cache group names reserved for datastructures is not allowed for " + "other cache types [cacheName=" + cc.getName() + ", groupName=" + cc.getGroupName() + ", cacheType=" + cacheType + "]"); + + // Make sure we do not use sql schema for system views. + if (ctx.query().moduleEnabled()) { + String schema = QueryUtils.normalizeSchemaName(cc.getName(), cc.getSqlSchema()); + + if (F.eq(schema, QueryUtils.SCHEMA_SYS)) { + if (cc.getSqlSchema() == null) { + // Conflict on cache name. + throw new IgniteCheckedException("SQL schema name derived from cache name is reserved (" + + "please set explicit SQL schema name through CacheConfiguration.setSqlSchema() or choose " + + "another cache name) [cacheName=" + cc.getName() + ", schemaName=" + cc.getSqlSchema() + "]"); + } + else { + // Conflict on schema name. + throw new IgniteCheckedException("SQL schema name is reserved (please choose another one) [" + + "cacheName=" + cc.getName() + ", schemaName=" + cc.getSqlSchema() + ']'); + } + } + } } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java index b4f82a4..d73e89d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java @@ -642,6 +642,19 @@ public class PlatformConfigurationUtils { if (in.readBoolean()) cfg.setAuthenticationEnabled(in.readBoolean()); + int sqlSchemasCnt = in.readInt(); + + if (sqlSchemasCnt == -1) + cfg.setSqlSchemas((String[])null); + else { + String[] sqlSchemas = new String[sqlSchemasCnt]; + + for (int i = 0; i < sqlSchemasCnt; i++) + sqlSchemas[i] = in.readString(); + + cfg.setSqlSchemas(sqlSchemas); + } + Object consId = in.readObjectDetached(); if (consId instanceof Serializable) { @@ -1167,6 +1180,16 @@ public class PlatformConfigurationUtils { w.writeBoolean(cfg.isActiveOnStart()); w.writeBoolean(true); w.writeBoolean(cfg.isAuthenticationEnabled()); + + if (cfg.getSqlSchemas() == null) + w.writeInt(-1); + else { + w.writeInt(cfg.getSqlSchemas().length); + + for (String schema : cfg.getSqlSchemas()) + w.writeString(schema); + } + w.writeObject(cfg.getConsistentId()); // Thread pools. http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Schema.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Schema.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Schema.java index 2fdf32d..ab7cb4b 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Schema.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Schema.java @@ -34,6 +34,9 @@ public class H2Schema { /** */ private final ConcurrentMap<H2TypeKey, H2TableDescriptor> typeToTbl = new ConcurrentHashMap<>(); + /** Whether schema is predefined and cannot be dorpped. */ + private final boolean predefined; + /** Usage count. */ private int usageCnt; @@ -41,9 +44,11 @@ public class H2Schema { * Constructor. * * @param schemaName Schema name. + * @param predefined Predefined flag. */ - public H2Schema(String schemaName) { + public H2Schema(String schemaName, boolean predefined) { this.schemaName = schemaName; + this.predefined = predefined; } /** @@ -55,20 +60,19 @@ public class H2Schema { /** * Increments counter for number of caches having this schema. - * - * @return New value of caches counter. */ - public int incrementUsageCount() { - return ++usageCnt; + public void incrementUsageCount() { + if (!predefined) + ++usageCnt; } /** * Increments counter for number of caches having this schema. * - * @return New value of caches counter. + * @return If schema is no longer used. */ - public int decrementUsageCount() { - return --usageCnt; + public boolean decrementUsageCount() { + return !predefined && --usageCnt == 0; } /** @@ -128,14 +132,9 @@ public class H2Schema { } /** - * Called after the schema was dropped. + * @return {@code True} if schema is predefined. */ - public void dropAll() { - for (H2TableDescriptor tbl : tbls.values()) - tbl.onDrop(); - - tbls.clear(); - - typeToTbl.clear(); + public boolean predefined() { + return predefined; } } http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/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 5f74c04..44cda44 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 @@ -579,12 +579,53 @@ public class IgniteH2Indexing implements GridQueryIndexing { } /** + * Create and register schema if needed. + * + * @param schemaName Schema name. + * @param predefined Whether this is predefined schema. + */ + private void createSchemaIfNeeded(String schemaName, boolean predefined) { + assert Thread.holdsLock(schemaMux); + + if (!predefined) + predefined = isSchemaPredefined(schemaName); + + H2Schema schema = new H2Schema(schemaName, predefined); + + H2Schema oldSchema = schemas.putIfAbsent(schemaName, schema); + + if (oldSchema == null) + createSchema0(schemaName); + else + schema = oldSchema; + + schema.incrementUsageCount(); + } + + /** + * Check if schema is predefined. + * + * @param schemaName Schema name. + * @return {@code True} if predefined. + */ + private boolean isSchemaPredefined(String schemaName) { + if (F.eq(QueryUtils.DFLT_SCHEMA, schemaName)) + return true; + + for (H2Schema schema : schemas.values()) { + if (F.eq(schema.schemaName(), schemaName) && schema.predefined()) + return true; + } + + return false; + } + + /** * Creates DB schema if it has not been created yet. * * @param schema Schema name. - * @throws IgniteCheckedException If failed to create db schema. */ - private void createSchema(String schema) throws IgniteCheckedException { + private void createSchema0(String schema) { executeSystemStatement("CREATE SCHEMA IF NOT EXISTS " + H2Utils.withQuotes(schema)); if (log.isDebugEnabled()) @@ -595,9 +636,8 @@ public class IgniteH2Indexing implements GridQueryIndexing { * Creates DB schema if it has not been created yet. * * @param schema Schema name. - * @throws IgniteCheckedException If failed to create db schema. */ - private void dropSchema(String schema) throws IgniteCheckedException { + private void dropSchema(String schema) { executeSystemStatement("DROP SCHEMA IF EXISTS " + H2Utils.withQuotes(schema)); if (log.isDebugEnabled()) @@ -1617,15 +1657,9 @@ public class IgniteH2Indexing implements GridQueryIndexing { return Collections.singletonList(H2Utils.zeroCursor()); } else { - try { - FieldsQueryCursor<List<?>> cursor = ddlProc.runDdlStatement(sql, cmd); + FieldsQueryCursor<List<?>> cursor = ddlProc.runDdlStatement(sql, cmd); - return Collections.singletonList(cursor); - } - catch (IgniteCheckedException e) { - throw new IgniteSQLException("Failed to execute DDL statement [stmt=" + sql + "]: " - + e.getMessage(), e); - } + return Collections.singletonList(cursor); } } @@ -1783,12 +1817,7 @@ public class IgniteH2Indexing implements GridQueryIndexing { throw new IgniteSQLException("DDL statements are not supported for LOCAL caches", IgniteQueryErrorCode.UNSUPPORTED_OPERATION); - try { - return Collections.singletonList(ddlProc.runDdlStatement(sqlQry, prepared)); - } - catch (IgniteCheckedException e) { - throw new IgniteSQLException("Failed to execute DDL statement [stmt=" + sqlQry + ']', e); - } + return Collections.singletonList(ddlProc.runDdlStatement(sqlQry, prepared)); } if (prepared instanceof NoOperation) { @@ -2236,6 +2265,7 @@ public class IgniteH2Indexing implements GridQueryIndexing { * @param type Type descriptor. * @throws IgniteCheckedException If validation failed. */ + @SuppressWarnings("CollectionAddAllCanBeReplacedWithConstructor") private void validateTypeDescriptor(GridQueryTypeDescriptor type) throws IgniteCheckedException { assert type != null; @@ -2567,7 +2597,24 @@ public class IgniteH2Indexing implements GridQueryIndexing { else { this.ctx = ctx; - schemas.put(QueryUtils.DFLT_SCHEMA, new H2Schema(QueryUtils.DFLT_SCHEMA)); + // Register PUBLIC schema which is always present. + schemas.put(QueryUtils.DFLT_SCHEMA, new H2Schema(QueryUtils.DFLT_SCHEMA, true)); + + // Register additional schemas. + String[] additionalSchemas = ctx.config().getSqlSchemas(); + + if (!F.isEmpty(additionalSchemas)) { + synchronized (schemaMux) { + for (String schema : additionalSchemas) { + if (F.isEmpty(schema)) + continue; + + schema = QueryUtils.normalizeSchemaName(null, schema); + + createSchemaIfNeeded(schema, true); + } + } + } valCtx = new CacheQueryObjectValueContext(ctx); @@ -2598,7 +2645,7 @@ public class IgniteH2Indexing implements GridQueryIndexing { if (sysViewsEnabled) { try { synchronized (schemaMux) { - createSchema(QueryUtils.SCHEMA_SYS); + createSchema0(QueryUtils.SCHEMA_SYS); } Connection c = connectionForSchema(QueryUtils.SCHEMA_SYS); @@ -2802,7 +2849,7 @@ public class IgniteH2Indexing implements GridQueryIndexing { } /** {@inheritDoc} */ - @Override public void stop() throws IgniteCheckedException { + @Override public void stop() { if (log.isDebugEnabled()) log.debug("Stopping cache query index..."); @@ -2843,34 +2890,13 @@ public class IgniteH2Indexing implements GridQueryIndexing { } } - /** - * Whether this is default schema. - * - * @param schemaName Schema name. - * @return {@code True} if default. - */ - private boolean isDefaultSchema(String schemaName) { - return F.eq(schemaName, QueryUtils.DFLT_SCHEMA); - } - /** {@inheritDoc} */ @Override public void registerCache(String cacheName, String schemaName, GridCacheContext<?, ?> cctx) throws IgniteCheckedException { rowCache.onCacheRegistered(cctx); - if (!isDefaultSchema(schemaName)) { - synchronized (schemaMux) { - H2Schema schema = new H2Schema(schemaName); - - H2Schema oldSchema = schemas.putIfAbsent(schemaName, schema); - - if (oldSchema == null) - createSchema(schemaName); - else - schema = oldSchema; - - schema.incrementUsageCount(); - } + synchronized (schemaMux) { + createSchemaIfNeeded(schemaName, false); } cacheName2schema.put(cacheName, schemaName); @@ -2915,17 +2941,15 @@ public class IgniteH2Indexing implements GridQueryIndexing { } } - if (!isDefaultSchema(schemaName)) { - synchronized (schemaMux) { - if (schema.decrementUsageCount() == 0) { - schemas.remove(schemaName); + synchronized (schemaMux) { + if (schema.decrementUsageCount()) { + schemas.remove(schemaName); - try { - dropSchema(schemaName); - } - catch (IgniteCheckedException e) { - U.error(log, "Failed to drop schema on cache stop (will ignore): " + cacheName, e); - } + try { + dropSchema(schemaName); + } + catch (IgniteException e) { + U.error(log, "Failed to drop schema on cache stop (will ignore): " + cacheName, e); } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java index c617d30..91ebece 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java @@ -111,10 +111,9 @@ public class DdlStatementsProcessor { * @param sql Original SQL. * @param cmd Command. * @return Result. - * @throws IgniteCheckedException On error. */ @SuppressWarnings("unchecked") - public FieldsQueryCursor<List<?>> runDdlStatement(String sql, SqlCommand cmd) throws IgniteCheckedException { + public FieldsQueryCursor<List<?>> runDdlStatement(String sql, SqlCommand cmd) { IgniteInternalFuture fut = null; try { @@ -123,7 +122,7 @@ public class DdlStatementsProcessor { if (cmd instanceof SqlCreateIndexCommand) { SqlCreateIndexCommand cmd0 = (SqlCreateIndexCommand)cmd; - GridH2Table tbl = idx.dataTable(cmd0.schemaName(), cmd0.tableName()); + GridH2Table tbl = dataTableWithRetry(cmd0.schemaName(), cmd0.tableName()); if (tbl == null) throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_NOT_FOUND, cmd0.tableName()); @@ -161,7 +160,7 @@ public class DdlStatementsProcessor { else if (cmd instanceof SqlDropIndexCommand) { SqlDropIndexCommand cmd0 = (SqlDropIndexCommand)cmd; - GridH2Table tbl = idx.dataTableForIndex(cmd0.schemaName(), cmd0.indexName()); + GridH2Table tbl = dataTableForIndexWithRetry(cmd0.schemaName(), cmd0.indexName()); if (tbl != null) { isDdlSupported(tbl); @@ -180,13 +179,7 @@ public class DdlStatementsProcessor { else if (cmd instanceof SqlAlterTableCommand) { SqlAlterTableCommand cmd0 = (SqlAlterTableCommand)cmd; - GridH2Table tbl = idx.dataTable(cmd0.schemaName(), cmd0.tableName()); - - if (tbl == null) { - ctx.cache().createMissingQueryCaches(); - - tbl = idx.dataTable(cmd0.schemaName(), cmd0.tableName()); - } + GridH2Table tbl = dataTableWithRetry(cmd0.schemaName(), cmd0.tableName()); if (tbl == null) { throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_NOT_FOUND, @@ -255,11 +248,9 @@ public class DdlStatementsProcessor { * @param sql SQL. * @param prepared Prepared. * @return Cursor on query results. - * @throws IgniteCheckedException On error. */ @SuppressWarnings({"unchecked", "ThrowableResultOfMethodCallIgnored"}) - public FieldsQueryCursor<List<?>> runDdlStatement(String sql, Prepared prepared) - throws IgniteCheckedException { + public FieldsQueryCursor<List<?>> runDdlStatement(String sql, Prepared prepared) { IgniteInternalFuture fut = null; try { @@ -270,7 +261,7 @@ public class DdlStatementsProcessor { isDdlOnSchemaSupported(cmd.schemaName()); - GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName()); + GridH2Table tbl = dataTableWithRetry(cmd.schemaName(), cmd.tableName()); if (tbl == null) throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_NOT_FOUND, cmd.tableName()); @@ -309,7 +300,7 @@ public class DdlStatementsProcessor { isDdlOnSchemaSupported(cmd.schemaName()); - GridH2Table tbl = idx.dataTableForIndex(cmd.schemaName(), cmd.indexName()); + GridH2Table tbl = dataTableForIndexWithRetry(cmd.schemaName(), cmd.indexName()); if (tbl != null) { isDdlSupported(tbl); @@ -332,11 +323,7 @@ public class DdlStatementsProcessor { isDdlOnSchemaSupported(cmd.schemaName()); - if (!F.eq(QueryUtils.DFLT_SCHEMA, cmd.schemaName())) - throw new SchemaOperationException("CREATE TABLE can only be executed on " + - QueryUtils.DFLT_SCHEMA + " schema."); - - GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName()); + GridH2Table tbl = dataTableWithRetry(cmd.schemaName(), cmd.tableName()); if (tbl != null) { if (!cmd.ifNotExists()) @@ -369,17 +356,7 @@ public class DdlStatementsProcessor { isDdlOnSchemaSupported(cmd.schemaName()); - if (!F.eq(QueryUtils.DFLT_SCHEMA, cmd.schemaName())) - throw new SchemaOperationException("DROP TABLE can only be executed on " + - QueryUtils.DFLT_SCHEMA + " schema."); - - GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName()); - - if (tbl == null && cmd.ifExists()) { - ctx.cache().createMissingQueryCaches(); - - tbl = idx.dataTable(cmd.schemaName(), cmd.tableName()); - } + GridH2Table tbl = dataTableWithRetry(cmd.schemaName(), cmd.tableName()); if (tbl == null) { if (!cmd.ifExists()) @@ -394,13 +371,7 @@ public class DdlStatementsProcessor { isDdlOnSchemaSupported(cmd.schemaName()); - GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName()); - - if (tbl == null && cmd.ifTableExists()) { - ctx.cache().createMissingQueryCaches(); - - tbl = idx.dataTable(cmd.schemaName(), cmd.tableName()); - } + GridH2Table tbl = dataTableWithRetry(cmd.schemaName(), cmd.tableName()); if (tbl == null) { if (!cmd.ifTableExists()) @@ -455,13 +426,7 @@ public class DdlStatementsProcessor { isDdlOnSchemaSupported(cmd.schemaName()); - GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName()); - - if (tbl == null && cmd.ifTableExists()) { - ctx.cache().createMissingQueryCaches(); - - tbl = idx.dataTable(cmd.schemaName(), cmd.tableName()); - } + GridH2Table tbl = dataTableWithRetry(cmd.schemaName(), cmd.tableName()); if (tbl == null) { if (!cmd.ifTableExists()) @@ -533,6 +498,46 @@ public class DdlStatementsProcessor { } /** + * Get table by name optionally creating missing query caches. + * + * @param schemaName Schema name. + * @param tableName Table name. + * @return Table or {@code null} if none found. + * @throws IgniteCheckedException If failed. + */ + private GridH2Table dataTableWithRetry(String schemaName, String tableName) throws IgniteCheckedException { + GridH2Table tbl = idx.dataTable(schemaName, tableName); + + if (tbl == null) { + ctx.cache().createMissingQueryCaches(); + + tbl = idx.dataTable(schemaName, tableName); + } + + return tbl; + } + + /** + * Get table by name optionally creating missing query caches. + * + * @param schemaName Schema name. + * @param indexName Index name. + * @return Table or {@code null} if none found. + * @throws IgniteCheckedException If failed. + */ + private GridH2Table dataTableForIndexWithRetry(String schemaName, String indexName) throws IgniteCheckedException { + GridH2Table tbl = idx.dataTableForIndex(schemaName, indexName); + + if (tbl == null) { + ctx.cache().createMissingQueryCaches(); + + tbl = idx.dataTableForIndex(schemaName, indexName); + } + + return tbl; + } + + /** * Check if schema supports DDL statement. * * @param schemaName Schema name. http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java ---------------------------------------------------------------------- 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 d132ebb..2fc69f6 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 @@ -1423,24 +1423,6 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest { } /** - * Test that {@code CREATE TABLE} in non-public schema causes an exception. - * - * @throws Exception if failed. - */ - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void testCreateTableInNonPublicSchema() throws Exception { - GridTestUtils.assertThrows(null, new Callable<Object>() { - @Override public Object call() throws Exception { - execute("CREATE TABLE \"cache_idx\".\"Person\" (\"id\" int, \"city\" varchar," + - " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " + - "\"template=cache\""); - - return null; - } - }, IgniteSQLException.class, "CREATE TABLE can only be executed on PUBLIC schema."); - } - - /** * Execute {@code CREATE TABLE} w/given params expecting a particular error. * @param params Engine parameters. * @param expErrMsg Expected error message. @@ -1473,17 +1455,6 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest { } /** - * Test that {@code DROP TABLE} on non-public schema causes an exception. - * - * @throws Exception if failed. - */ - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void testDropTableNotPublicSchema() throws Exception { - assertDdlCommandThrows("DROP TABLE \"cache_idx\".\"Person\"", - "DROP TABLE can only be executed on PUBLIC schema."); - } - - /** * Test that {@link IgniteH2Indexing#tables(String)} method * only returns tables belonging to given cache. * http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlIllegalSchemaSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlIllegalSchemaSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlIllegalSchemaSelfTest.java new file mode 100644 index 0000000..e56f8a2 --- /dev/null +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/SqlIllegalSchemaSelfTest.java @@ -0,0 +1,187 @@ +/* + * 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 org.apache.ignite.Ignite; +import org.apache.ignite.IgniteException; +import org.apache.ignite.Ignition; +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 javax.cache.CacheException; +import java.util.concurrent.Callable; + +/** + * Tests for illegal SQL schemas in node and cache configurations. + */ +@SuppressWarnings({"ThrowableNotThrown", "unchecked"}) +public class SqlIllegalSchemaSelfTest extends GridCommonAbstractTest { + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + stopAllGrids(); + } + + /** + * @throws Exception If failed. + */ + public void testBadCacheName() throws Exception { + IgniteConfiguration cfg = getConfiguration(); + + cfg.setCacheConfiguration(new CacheConfiguration().setName(QueryUtils.SCHEMA_SYS)); + + GridTestUtils.assertThrows(log, new Callable<Void>() { + @Override public Void call() throws Exception { + Ignition.start(cfg); + + return null; + } + }, IgniteException.class, "SQL schema name derived from cache name is reserved (please set explicit SQL " + + "schema name through CacheConfiguration.setSqlSchema() or choose another cache name) [cacheName=IGNITE, " + + "schemaName=null]"); + } + + /** + * @throws Exception If failed. + */ + public void testBadCacheNameDynamic() throws Exception { + Ignite node = startGrid(); + + GridTestUtils.assertThrows(log, new Callable<Void>() { + @Override public Void call() throws Exception { + node.getOrCreateCache(new CacheConfiguration().setName(QueryUtils.SCHEMA_SYS)); + + return null; + } + }, CacheException.class, "SQL schema name derived from cache name is reserved (please set explicit SQL " + + "schema name through CacheConfiguration.setSqlSchema() or choose another cache name) [" + + "cacheName=IGNITE, schemaName=null]"); + } + + /** + * @throws Exception If failed. + */ + public void testBadSchemaLower() throws Exception { + IgniteConfiguration cfg = getConfiguration(); + + cfg.setCacheConfiguration(new CacheConfiguration().setName("CACHE") + .setSqlSchema(QueryUtils.SCHEMA_SYS.toLowerCase())); + + GridTestUtils.assertThrows(log, new Callable<Void>() { + @Override public Void call() throws Exception { + Ignition.start(cfg); + + return null; + } + }, IgniteException.class, "SQL schema name is reserved (please choose another one) [cacheName=CACHE, " + + "schemaName=ignite]"); + } + + /** + * @throws Exception If failed. + */ + public void testBadSchemaLowerDynamic() throws Exception { + Ignite node = startGrid(); + + GridTestUtils.assertThrows(log, new Callable<Void>() { + @Override public Void call() throws Exception { + node.getOrCreateCache( + new CacheConfiguration().setName("CACHE").setSqlSchema(QueryUtils.SCHEMA_SYS.toLowerCase()) + ); + + return null; + } + }, CacheException.class, "SQL schema name is reserved (please choose another one) [cacheName=CACHE, schemaName=ignite]"); + } + + /** + * @throws Exception If failed. + */ + public void testBadSchemaUpper() throws Exception { + IgniteConfiguration cfg = getConfiguration(); + + cfg.setCacheConfiguration(new CacheConfiguration().setName("CACHE") + .setSqlSchema(QueryUtils.SCHEMA_SYS.toUpperCase())); + + GridTestUtils.assertThrows(log, new Callable<Void>() { + @Override public Void call() throws Exception { + Ignition.start(cfg); + + return null; + } + }, IgniteException.class, "SQL schema name is reserved (please choose another one) [cacheName=CACHE, " + + "schemaName=IGNITE]"); + } + + /** + * @throws Exception If failed. + */ + public void testBadSchemaUpperDynamic() throws Exception { + Ignite node = startGrid(); + + GridTestUtils.assertThrows(log, new Callable<Void>() { + @Override public Void call() throws Exception { + node.getOrCreateCache( + new CacheConfiguration().setName("CACHE").setSqlSchema(QueryUtils.SCHEMA_SYS.toUpperCase()) + ); + + return null; + } + }, CacheException.class, "SQL schema name is reserved (please choose another one) [cacheName=CACHE, " + + "schemaName=IGNITE]"); + } + + /** + * @throws Exception If failed. + */ + public void testBadSchemaQuoted() throws Exception { + IgniteConfiguration cfg = getConfiguration(); + + cfg.setCacheConfiguration(new CacheConfiguration().setName("CACHE") + .setSqlSchema("\"" + QueryUtils.SCHEMA_SYS.toUpperCase() + "\"")); + + GridTestUtils.assertThrows(log, new Callable<Void>() { + @Override public Void call() throws Exception { + Ignition.start(cfg); + + return null; + } + }, IgniteException.class, "SQL schema name is reserved (please choose another one) [cacheName=CACHE, " + + "schemaName=\"IGNITE\"]"); + } + + /** + * @throws Exception If failed. + */ + public void testBadSchemaQuotedDynamic() throws Exception { + Ignite node = startGrid(); + + GridTestUtils.assertThrows(log, new Callable<Void>() { + @Override public Void call() throws Exception { + node.getOrCreateCache( + new CacheConfiguration().setName("CACHE") + .setSqlSchema("\"" + QueryUtils.SCHEMA_SYS.toUpperCase() + "\"") + ); + + return null; + } + }, CacheException.class, "SQL schema name is reserved (please choose another one) [cacheName=CACHE, " + + "schemaName=\"IGNITE\"]"); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java index d70e5c3..a658caf 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java +++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java @@ -176,6 +176,7 @@ import org.apache.ignite.internal.processors.query.IgniteSqlSkipReducerOnUpdateD import org.apache.ignite.internal.processors.query.IgniteSqlSplitterSelfTest; import org.apache.ignite.internal.processors.query.LazyQuerySelfTest; import org.apache.ignite.internal.processors.query.MultipleStatementsSqlQuerySelfTest; +import org.apache.ignite.internal.processors.query.SqlIllegalSchemaSelfTest; import org.apache.ignite.internal.processors.query.SqlSystemViewsSelfTest; import org.apache.ignite.internal.processors.query.SqlPushDownFunctionTest; import org.apache.ignite.internal.processors.query.SqlSchemaSelfTest; @@ -221,6 +222,7 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite { suite.addTestSuite(ClientConnectorConfigurationValidationSelfTest.class); suite.addTestSuite(SqlSchemaSelfTest.class); + suite.addTestSuite(SqlIllegalSchemaSelfTest.class); suite.addTestSuite(MultipleStatementsSqlQuerySelfTest.class); // Misc tests. http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml index d50cf4f..b091a49 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml @@ -47,6 +47,10 @@ <string>-Xms1g</string> <string>-Xmx4g</string> </jvmOptions> + <sqlSchemas> + <string>SCHEMA_1</string> + <string>schema_2</string> + </sqlSchemas> <lifecycleHandlers> <iLifecycleHandler type='Apache.Ignite.Core.Tests.IgniteConfigurationSerializerTest+LifecycleBean' foo='15' /> </lifecycleHandlers> http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs index 226106f..e2ece20 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs @@ -99,6 +99,12 @@ namespace Apache.Ignite.Core.Tests Assert.AreEqual(new TimeSpan(1, 2, 3), cfg.LongQueryWarningTimeout); Assert.IsFalse(cfg.IsActiveOnStart); Assert.IsTrue(cfg.AuthenticationEnabled); + + Assert.IsNotNull(cfg.SqlSchemas); + Assert.AreEqual(2, cfg.SqlSchemas.Count); + Assert.IsTrue(cfg.SqlSchemas.Contains("SCHEMA_1")); + Assert.IsTrue(cfg.SqlSchemas.Contains("schema_2")); + Assert.AreEqual("someId012", cfg.ConsistentId); Assert.IsFalse(cfg.RedirectJavaConsoleOutput); http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs index 6c772f4..a03d09c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs @@ -19,6 +19,7 @@ namespace Apache.Ignite.Core.Tests { using System; + using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; @@ -240,6 +241,11 @@ namespace Apache.Ignite.Core.Tests Assert.AreEqual(sql.ThreadPoolSize, resSql.ThreadPoolSize); AssertExtensions.ReflectionEqual(cfg.DataStorageConfiguration, resCfg.DataStorageConfiguration); + + Assert.IsNotNull(resCfg.SqlSchemas); + Assert.AreEqual(2, resCfg.SqlSchemas.Count); + Assert.IsTrue(resCfg.SqlSchemas.Contains("SCHEMA_3")); + Assert.IsTrue(resCfg.SqlSchemas.Contains("schema_4")); } } @@ -829,7 +835,9 @@ namespace Apache.Ignite.Core.Tests } } }, - AuthenticationEnabled = false + AuthenticationEnabled = false, + + SqlSchemas = new List<string> { "SCHEMA_3", "schema_4" } }; } http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs index 7d8cfc7..9bcf763 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs @@ -305,6 +305,19 @@ namespace Apache.Ignite.Core writer.WriteTimeSpanAsLongNullable(_longQueryWarningTimeout); writer.WriteBooleanNullable(_isActiveOnStart); writer.WriteBooleanNullable(_authenticationEnabled); + + if (SqlSchemas == null) + writer.WriteInt(-1); + else + { + writer.WriteInt(SqlSchemas.Count); + + foreach (string sqlSchema in SqlSchemas) + { + writer.WriteString(sqlSchema); + } + } + writer.WriteObjectDetached(ConsistentId); // Thread pools @@ -657,6 +670,19 @@ namespace Apache.Ignite.Core _longQueryWarningTimeout = r.ReadTimeSpanNullable(); _isActiveOnStart = r.ReadBooleanNullable(); _authenticationEnabled = r.ReadBooleanNullable(); + + int sqlSchemasCnt = r.ReadInt(); + + if (sqlSchemasCnt == -1) + SqlSchemas = null; + else + { + SqlSchemas = new List<string>(sqlSchemasCnt); + + for (int i = 0; i < sqlSchemasCnt; i++) + SqlSchemas.Add(r.ReadString()); + } + ConsistentId = r.ReadObject<object>(); // Thread pools @@ -1529,5 +1555,13 @@ namespace Apache.Ignite.Core /// <see cref="NoOpFailureHandler"/>, <see cref="StopNodeOrHaltFailureHandler"/>, <see cref="StopNodeFailureHandler"/>. /// </summary> public IFailureHandler FailureHandler { get; set; } + + /// <summary> + /// Gets or sets SQL schemas to be created on node startup. Schemas are created on local node only and are not propagated. + /// to other cluster nodes. Created schemas cannot be dropped. + /// <para/> + /// By default schema names are case-insensitive. Use quotes to enforce case sensitivity. + /// </summary> + public ICollection<String> SqlSchemas { get; set; } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/277010cd/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd index f16ef43..8db5afa 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd +++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd @@ -2029,6 +2029,16 @@ </xs:attribute> </xs:complexType> </xs:element> + <xs:element name="sqlSchemas" minOccurs="0"> + <xs:annotation> + <xs:documentation>SQL schemas to be created on node startup. Schemas are created on local node only and are not propagated.</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:sequence> + <xs:element maxOccurs="unbounded" name="string" type="xs:string" /> + </xs:sequence> + </xs:complexType> + </xs:element> </xs:all> <xs:attribute name="igniteInstanceName" type="xs:string"> <xs:annotation>
