You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/09/13 08:06:45 UTC

[01/12] ignite git commit: IGNITE-6326: JDBC thin driver: as of now error is thrown before query execution in case of type mismatch (executeQuery, executeUpdate). This closes #2631.

Repository: ignite
Updated Branches:
  refs/heads/ignite-6149 072322f90 -> 16e52541e


IGNITE-6326: JDBC thin driver: as of now error is thrown before query execution in case of type mismatch (executeQuery, executeUpdate). This closes #2631.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/acd78616
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/acd78616
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/acd78616

Branch: refs/heads/ignite-6149
Commit: acd786160f612e300b82ac95d5470cd50a431622
Parents: 25f8c57
Author: tledkov-gridgain <tl...@gridgain.com>
Authored: Tue Sep 12 10:52:04 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Tue Sep 12 10:52:04 2017 +0300

----------------------------------------------------------------------
 .../ignite/jdbc/thin/JdbcThinBatchSelfTest.java |  2 +-
 .../jdbc/thin/JdbcThinStatementSelfTest.java    | 41 ++++++++++++++++++++
 .../jdbc/thin/JdbcThinPreparedStatement.java    | 12 +++---
 .../internal/jdbc/thin/JdbcThinStatement.java   | 12 +++---
 .../internal/jdbc/thin/JdbcThinTcpIo.java       |  6 ++-
 .../internal/jdbc2/JdbcSqlFieldsQuery.java      |  2 +-
 .../odbc/jdbc/JdbcQueryExecuteRequest.java      | 29 +++++++++++++-
 .../odbc/jdbc/JdbcRequestHandler.java           | 27 ++++++++++---
 .../processors/odbc/jdbc/JdbcStatementType.java | 32 +++++++++++++++
 9 files changed, 141 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/acd78616/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinBatchSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinBatchSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinBatchSelfTest.java
index 5781e00..5e2e39e 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinBatchSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinBatchSelfTest.java
@@ -173,7 +173,7 @@ public class JdbcThinBatchSelfTest extends JdbcThinAbstractDmlStatementSelfTest
             for (int i = 0; i < BATCH_SIZE; ++i)
                 assertEquals("Invalid update count",i + 1, updCnts[i]);
 
-            if (!e.getMessage().contains("Query produced result set [qry=select * from Person, args=[]]")) {
+            if (!e.getMessage().contains("Given statement type does not match that declared by JDBC driver")) {
                 log.error("Invalid exception: ", e);
 
                 fail();

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd78616/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
index 97e3300..234a319 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinStatementSelfTest.java
@@ -1013,6 +1013,47 @@ public class JdbcThinStatementSelfTest extends JdbcThinAbstractSelfTest {
             "Statement is closed");
     }
 
+    /**
+     * @throws Exception If failed.
+     */
+    public void testStatementTypeMismatchSelect() throws Exception {
+        GridTestUtils.assertThrows(log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    stmt.executeUpdate("select 1;");
+
+                    return null;
+                }
+            },
+            SQLException.class,
+            "Given statement type does not match that declared by JDBC driver");
+
+        assert stmt.getResultSet() == null : "Not results expected. Last statement is executed with exception";
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testStatementTypeMismatchUpdate() throws Exception {
+        GridTestUtils.assertThrows(log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    stmt.executeQuery("update test set val=28 where _key=1");
+
+                    return null;
+                }
+            },
+            SQLException.class,
+            "Given statement type does not match that declared by JDBC driver");
+
+        ResultSet rs = stmt.executeQuery("select val from test where _key=1");
+
+        assert rs.next();
+        assert rs.getInt(1) == 1 : "The data must not be updated. " +
+            "Because update statement is executed via 'executeQuery' method." +
+            " Data [val=" + rs.getInt(1) + ']';
+    }
+
     /** */
     private void fillCache() {
         IgniteCache<String, Person> cachePerson = grid(0).cache(DEFAULT_CACHE_NAME);

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd78616/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
index 49a1029..5aa503c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java
@@ -44,6 +44,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.processors.odbc.SqlListenerUtils;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaParamsResult;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType;
 
 /**
  * JDBC prepared statement implementation.
@@ -73,7 +74,7 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
 
     /** {@inheritDoc} */
     @Override public ResultSet executeQuery() throws SQLException {
-        executeWithArguments();
+        executeWithArguments(JdbcStatementType.SELECT_STATEMENT_TYPE);
 
         ResultSet rs = getResultSet();
 
@@ -90,7 +91,7 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
 
     /** {@inheritDoc} */
     @Override public int executeUpdate() throws SQLException {
-        executeWithArguments();
+        executeWithArguments(JdbcStatementType.UPDATE_STMT_TYPE);
 
         int res = getUpdateCount();
 
@@ -230,7 +231,7 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
 
     /** {@inheritDoc} */
     @Override public boolean execute() throws SQLException {
-        executeWithArguments();
+        executeWithArguments(JdbcStatementType.ANY_STATEMENT_TYPE);
 
         return rs.isQuery();
     }
@@ -238,10 +239,11 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep
     /**
      * Execute query with arguments and nullify them afterwards.
      *
+     * @param stmtType Expected statement type.
      * @throws SQLException If failed.
      */
-    private void executeWithArguments() throws SQLException {
-        execute0(sql, args);
+    private void executeWithArguments(JdbcStatementType stmtType) throws SQLException {
+        execute0(stmtType, sql, args);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd78616/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
index df77261..44477cd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java
@@ -33,6 +33,7 @@ import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteResult;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteResult;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType;
 
 import static java.sql.ResultSet.CONCUR_READ_ONLY;
 import static java.sql.ResultSet.FETCH_FORWARD;
@@ -90,7 +91,7 @@ public class JdbcThinStatement implements Statement {
 
     /** {@inheritDoc} */
     @Override public ResultSet executeQuery(String sql) throws SQLException {
-        execute0(sql, null);
+        execute0(JdbcStatementType.SELECT_STATEMENT_TYPE, sql, null);
 
         ResultSet rs = getResultSet();
 
@@ -101,12 +102,13 @@ public class JdbcThinStatement implements Statement {
     }
 
     /**
+     * @param stmtType Expected statement type.
      * @param sql Sql query.
      * @param args Query parameters.
      *
      * @throws SQLException Onj error.
      */
-    protected void execute0(String sql, List<Object> args) throws SQLException {
+    protected void execute0(JdbcStatementType stmtType, String sql, List<Object> args) throws SQLException {
         ensureNotClosed();
 
         if (rs != null) {
@@ -121,7 +123,7 @@ public class JdbcThinStatement implements Statement {
             throw new SQLException("SQL query is empty.");
 
         try {
-            JdbcQueryExecuteResult res = conn.io().queryExecute(conn.getSchema(), pageSize, maxRows,
+            JdbcQueryExecuteResult res = conn.io().queryExecute(stmtType, conn.getSchema(), pageSize, maxRows,
                 sql, args);
 
             assert res != null;
@@ -141,7 +143,7 @@ public class JdbcThinStatement implements Statement {
 
     /** {@inheritDoc} */
     @Override public int executeUpdate(String sql) throws SQLException {
-        execute0(sql, null);
+        execute0(JdbcStatementType.UPDATE_STMT_TYPE, sql, null);
 
         int res = getUpdateCount();
 
@@ -246,7 +248,7 @@ public class JdbcThinStatement implements Statement {
     @Override public boolean execute(String sql) throws SQLException {
         ensureNotClosed();
 
-        execute0(sql, null);
+        execute0(JdbcStatementType.ANY_STATEMENT_TYPE, sql, null);
 
         return rs.isQuery();
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd78616/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
index f29f8b1..9775254 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
@@ -57,6 +57,7 @@ import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataResult;
 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.util.ipc.loopback.IpcClientTcpEndpoint;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteProductVersion;
@@ -315,6 +316,7 @@ public class JdbcThinTcpIo {
     }
 
     /**
+     * @param stmtType Expected statement type.
      * @param cache Cache name.
      * @param fetchSize Fetch size.
      * @param maxRows Max rows.
@@ -324,10 +326,10 @@ public class JdbcThinTcpIo {
      * @throws IOException On error.
      * @throws IgniteCheckedException On error.
      */
-    public JdbcQueryExecuteResult queryExecute(String cache, int fetchSize, int maxRows,
+    public JdbcQueryExecuteResult queryExecute(JdbcStatementType stmtType, String cache, int fetchSize, int maxRows,
         String sql, List<Object> args)
         throws IOException, IgniteCheckedException {
-        return sendRequest(new JdbcQueryExecuteRequest(cache, fetchSize, maxRows, sql,
+        return sendRequest(new JdbcQueryExecuteRequest(stmtType, cache, fetchSize, maxRows, sql,
             args == null ? null : args.toArray(new Object[args.size()])), DYNAMIC_SIZE_MSG_CAP);
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd78616/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcSqlFieldsQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcSqlFieldsQuery.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcSqlFieldsQuery.java
index 3d4eaba..d8b9a26 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcSqlFieldsQuery.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcSqlFieldsQuery.java
@@ -35,7 +35,7 @@ public final class JdbcSqlFieldsQuery extends SqlFieldsQuery {
      * @param sql SQL query.
      * @param isQry Flag indicating whether this object denotes a query or an update operation.
      */
-    JdbcSqlFieldsQuery(String sql, boolean isQry) {
+    public JdbcSqlFieldsQuery(String sql, boolean isQry) {
         super(sql);
         this.isQry = isQry;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd78616/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
index 0b26dce..1c6262e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.processors.odbc.jdbc;
 
+import java.io.IOException;
 import org.apache.ignite.binary.BinaryObjectException;
 import org.apache.ignite.internal.binary.BinaryReaderExImpl;
 import org.apache.ignite.internal.binary.BinaryWriterExImpl;
@@ -47,6 +48,9 @@ public class JdbcQueryExecuteRequest extends JdbcRequest {
     @GridToStringInclude(sensitive = true)
     private Object[] args;
 
+    /** Expected statement type. */
+    private JdbcStatementType stmtType;
+
     /**
      */
     JdbcQueryExecuteRequest() {
@@ -54,14 +58,15 @@ public class JdbcQueryExecuteRequest extends JdbcRequest {
     }
 
     /**
+     * @param stmtType Expected statement type.
      * @param schemaName Cache name.
      * @param pageSize Fetch size.
      * @param maxRows Max rows.
      * @param sqlQry SQL query.
      * @param args Arguments list.
      */
-    public JdbcQueryExecuteRequest(String schemaName, int pageSize, int maxRows, String sqlQry,
-        Object[] args) {
+    public JdbcQueryExecuteRequest(JdbcStatementType stmtType, String schemaName, int pageSize, int maxRows,
+        String sqlQry, Object[] args) {
         super(QRY_EXEC);
 
         this.schemaName = F.isEmpty(schemaName) ? null : schemaName;
@@ -69,6 +74,7 @@ public class JdbcQueryExecuteRequest extends JdbcRequest {
         this.maxRows = maxRows;
         this.sqlQry = sqlQry;
         this.args = args;
+        this.stmtType = stmtType;
     }
 
     /**
@@ -106,6 +112,13 @@ public class JdbcQueryExecuteRequest extends JdbcRequest {
         return schemaName;
     }
 
+    /**
+     * @return Expected statement type.
+     */
+    public JdbcStatementType expectedStatementType() {
+        return stmtType;
+    }
+
     /** {@inheritDoc} */
     @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
         super.writeBinary(writer);
@@ -121,6 +134,8 @@ public class JdbcQueryExecuteRequest extends JdbcRequest {
             for (Object arg : args)
                 SqlListenerUtils.writeObject(writer, arg, false);
         }
+
+        writer.writeByte((byte)stmtType.ordinal());
     }
 
     /** {@inheritDoc} */
@@ -138,6 +153,16 @@ public class JdbcQueryExecuteRequest extends JdbcRequest {
 
         for (int i = 0; i < argsNum; ++i)
             args[i] = SqlListenerUtils.readObject(reader, false);
+
+        try {
+            if (reader.available() > 0)
+                stmtType = JdbcStatementType.values()[reader.readByte()];
+            else
+                stmtType = JdbcStatementType.ANY_STATEMENT_TYPE;
+        }
+        catch (IOException e) {
+            throw new BinaryObjectException(e);
+        }
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd78616/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
index d2508a6..3ccc195 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
@@ -28,13 +28,13 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
-import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.cache.query.FieldsQueryCursor;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.IgniteVersionUtils;
 import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.jdbc2.JdbcSqlFieldsQuery;
 import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
 import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
 import org.apache.ignite.internal.processors.odbc.SqlListenerRequestHandler;
@@ -223,7 +223,24 @@ public class JdbcRequestHandler implements SqlListenerRequestHandler {
         try {
             String sql = req.sqlQuery();
 
-            SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+            SqlFieldsQuery qry;
+
+            switch(req.expectedStatementType()) {
+                case ANY_STATEMENT_TYPE:
+                    qry = new SqlFieldsQuery(sql);
+
+                    break;
+
+                case SELECT_STATEMENT_TYPE:
+                    qry = new JdbcSqlFieldsQuery(sql, true);
+
+                    break;
+
+                default:
+                    assert req.expectedStatementType() == JdbcStatementType.UPDATE_STMT_TYPE;
+
+                    qry = new JdbcSqlFieldsQuery(sql, false);
+            }
 
             qry.setArgs(req.arguments());
 
@@ -389,7 +406,7 @@ public class JdbcRequestHandler implements SqlListenerRequestHandler {
                 if (q.sql() != null)
                     sql = q.sql();
 
-                SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+                SqlFieldsQuery qry = new JdbcSqlFieldsQuery(sql, false);
 
                 qry.setArgs(q.args());
 
@@ -404,9 +421,7 @@ public class JdbcRequestHandler implements SqlListenerRequestHandler {
                 QueryCursorImpl<List<?>> qryCur = (QueryCursorImpl<List<?>>)ctx.query()
                     .querySqlFieldsNoCache(qry, true);
 
-                if (qryCur.isQuery())
-                    throw new IgniteCheckedException("Query produced result set [qry=" + q.sql() + ", args=" +
-                        Arrays.toString(q.args()) + ']');
+                assert !qryCur.isQuery();
 
                 List<List<?>> items = qryCur.getAll();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/acd78616/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcStatementType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcStatementType.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcStatementType.java
new file mode 100644
index 0000000..aec2d12
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcStatementType.java
@@ -0,0 +1,32 @@
+/*
+ * 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.odbc.jdbc;
+
+/**
+ * JDBC statement type.
+ */
+public enum JdbcStatementType {
+    /** Any statement type. */
+    ANY_STATEMENT_TYPE,
+
+    /** Select statement type. */
+    SELECT_STATEMENT_TYPE,
+
+    /** DML / DDL statement type. */
+    UPDATE_STMT_TYPE;
+}


[12/12] ignite git commit: ignite-6149

Posted by sb...@apache.org.
ignite-6149


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/16e52541
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/16e52541
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/16e52541

Branch: refs/heads/ignite-6149
Commit: 16e52541ef799f1e135576636a69d89591a1fee2
Parents: b5cac1c
Author: sboikov <sb...@gridgain.com>
Authored: Wed Sep 13 11:06:37 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Wed Sep 13 11:06:37 2017 +0300

----------------------------------------------------------------------
 .../cache/query/GridCacheQueryAdapter.java      |  7 ++++
 .../cache/query/GridCacheQueryManager.java      | 40 +++++++++++++++++---
 2 files changed, 42 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/16e52541/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryAdapter.java
index 27b05c7..47e7e54 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryAdapter.java
@@ -261,6 +261,13 @@ public class GridCacheQueryAdapter<T> implements CacheQuery<T> {
     }
 
     /**
+     * @param mvccVer Mvcc version.
+     */
+    void mvccVersion(MvccCoordinatorVersion mvccVer) {
+        this.mvccVer = mvccVer;
+    }
+
+    /**
      * @return Mvcc version.
      */
     @Nullable MvccCoordinatorVersion mvccVersion() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/16e52541/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
index 069c863..075e492 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
@@ -76,6 +76,7 @@ import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheAdapter;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtUnreservedPartitionException;
+import org.apache.ignite.internal.processors.cache.mvcc.MvccCoordinatorVersion;
 import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.datastructures.DataStructuresProcessor;
@@ -613,7 +614,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
                             taskName));
                     }
 
-                    iter = scanIterator(qry, false);
+                    iter = scanIterator(qry, false, null);
 
                     break;
 
@@ -819,11 +820,12 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
     /**
      * @param qry Query.
      * @param locNode Local node.
+     * @param mvccCrd Non null mvcc coordinator node if need ack mvcc query as finished on iterator close.
      * @return Full-scan row iterator.
      * @throws IgniteCheckedException If failed to get iterator.
      */
     @SuppressWarnings({"unchecked"})
-    private GridCloseableIterator scanIterator(final GridCacheQueryAdapter<?> qry, boolean locNode)
+    private GridCloseableIterator scanIterator(final GridCacheQueryAdapter<?> qry, boolean locNode, ClusterNode mvccCrd)
         throws IgniteCheckedException {
         final IgniteBiPredicate<K, V> keyValFilter = qry.scanFilter();
 
@@ -870,7 +872,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
                 it = cctx.offheap().cacheIterator(cctx.cacheId(), true, backups, topVer, qry.mvccVersion());
             }
 
-            return new ScanQueryIterator(it, qry, topVer, locPart, keyValFilter, locNode, cctx, log);
+            return new ScanQueryIterator(it, qry, topVer, locPart, keyValFilter, locNode, cctx, mvccCrd, log);
         }
         catch (IgniteCheckedException | RuntimeException e) {
             closeScanFilter(keyValFilter);
@@ -1459,7 +1461,20 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
                     taskName));
             }
 
-            GridCloseableIterator it = scanIterator(qry, true);
+            final ClusterNode mvccCrd;
+
+            // TODO IGNITE-3478.
+            if (cctx.mvccEnabled()) {
+                mvccCrd = cctx.shared().coordinators().coordinator(cctx.shared().exchange().readyAffinityVersion());
+
+                IgniteInternalFuture<MvccCoordinatorVersion> fut0 = cctx.shared().coordinators().requestQueryCounter(mvccCrd);
+
+                qry.mvccVersion(fut0.get());
+            }
+            else
+                mvccCrd = null;
+
+            GridCloseableIterator it = scanIterator(qry, true, mvccCrd);
 
             updateStatistics = false;
 
@@ -2899,6 +2914,12 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
         /** */
         private IgniteCacheExpiryPolicy expiryPlc;
 
+        /** */
+        private ClusterNode mvccCrd;
+
+        /** */
+        private MvccCoordinatorVersion mvccVer;
+
         /**
          * @param it Iterator.
          * @param qry Query.
@@ -2917,19 +2938,25 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
             IgniteBiPredicate<K, V> scanFilter,
             boolean locNode,
             GridCacheContext cctx,
+            ClusterNode mvccCrd,
             IgniteLogger log) {
+            assert mvccCrd == null || qry.mvccVersion() != null;
+
             this.it = it;
             this.topVer = topVer;
             this.locPart = locPart;
             this.scanFilter = scanFilter;
             this.cctx = cctx;
+            this.mvccCrd = mvccCrd;
+            this.mvccVer = qry.mvccVersion();
+
             this.log = log;
 
             statsEnabled = locNode && cctx.config().isStatisticsEnabled();
 
             readEvt = locNode && cctx.gridEvents().isRecordable(EVT_CACHE_QUERY_OBJECT_READ);
 
-            if(readEvt){
+            if (readEvt){
                 taskName = cctx.kernalContext().task().resolveTaskName(qry.taskHash());
                 subjId = qry.subjectId();
             }
@@ -2976,6 +3003,9 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
 
         /** {@inheritDoc} */
         @Override protected void onClose() {
+            if (mvccCrd != null)
+                dht.context().shared().coordinators().ackQueryDone(mvccCrd, mvccVer.counter());
+
             if (expiryPlc != null && dht != null) {
                 dht.sendTtlUpdateRequest(expiryPlc);
 


[10/12] ignite git commit: IGNITE-6363 Added refresh icon.

Posted by sb...@apache.org.
IGNITE-6363 Added refresh icon.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/cc3ab699
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/cc3ab699
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/cc3ab699

Branch: refs/heads/ignite-6149
Commit: cc3ab6999a997bfe7247fc5ff8c4aaa5955c7a2e
Parents: 67d716f
Author: vsisko <vs...@gridgain.com>
Authored: Wed Sep 13 13:39:28 2017 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Wed Sep 13 13:39:28 2017 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/public/images/icons/index.js    | 1 +
 modules/web-console/frontend/public/images/icons/refresh.svg | 1 +
 2 files changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/cc3ab699/modules/web-console/frontend/public/images/icons/index.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/images/icons/index.js b/modules/web-console/frontend/public/images/icons/index.js
index 2609550..5d8ac53 100644
--- a/modules/web-console/frontend/public/images/icons/index.js
+++ b/modules/web-console/frontend/public/images/icons/index.js
@@ -23,3 +23,4 @@ export manual from './manual.svg';
 export download from './download.svg';
 export filter from './filter.svg';
 export search from './search.svg';
+export refresh from './refresh.svg';

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc3ab699/modules/web-console/frontend/public/images/icons/refresh.svg
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/images/icons/refresh.svg b/modules/web-console/frontend/public/images/icons/refresh.svg
new file mode 100644
index 0000000..4252e88
--- /dev/null
+++ b/modules/web-console/frontend/public/images/icons/refresh.svg
@@ -0,0 +1 @@
+<svg id="refresh-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 20"><path d="M7 5.1v2.6l3.5-3.5L7 .7v2.6c-3.9 0-7 3.1-7 7C0 11.7.4 13 1.1 14l1.3-1.3c-.4-.7-.6-1.6-.6-2.5C1.7 7.4 4.1 5.1 7 5.1zm5.9 1.5l-1.3 1.3c.4.7.6 1.6.6 2.5 0 2.9-2.4 5.2-5.2 5.2V13l-3.5 3.5L7 20v-2.6c3.9 0 7-3.1 7-7 0-1.4-.4-2.7-1.1-3.8z" fill="currentColor"/></svg>


[11/12] ignite git commit: Merge remote-tracking branch 'remotes/origin/master' into ignite-6149

Posted by sb...@apache.org.
Merge remote-tracking branch 'remotes/origin/master' into ignite-6149


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/b5cac1c0
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/b5cac1c0
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/b5cac1c0

Branch: refs/heads/ignite-6149
Commit: b5cac1c0d818967553c72d4699d1c66c57c1fb10
Parents: 072322f cc3ab69
Author: sboikov <sb...@gridgain.com>
Authored: Wed Sep 13 10:36:42 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Wed Sep 13 10:36:42 2017 +0300

----------------------------------------------------------------------
 assembly/release-fabric-base.xml                |    2 +-
 .../ignite/jdbc/thin/JdbcThinBatchSelfTest.java |    2 +-
 .../jdbc/thin/JdbcThinStatementSelfTest.java    |   41 +
 .../org/apache/ignite/cache/QueryEntity.java    |   32 +-
 .../jdbc/thin/JdbcThinPreparedStatement.java    |   12 +-
 .../internal/jdbc/thin/JdbcThinStatement.java   |   12 +-
 .../internal/jdbc/thin/JdbcThinTcpIo.java       |    6 +-
 .../internal/jdbc2/JdbcSqlFieldsQuery.java      |    2 +-
 .../processors/cache/GridCacheContext.java      |   26 +
 .../processors/cache/GridCacheMapEntry.java     |   23 +
 .../distributed/dht/GridDhtTxPrepareFuture.java |    3 +
 .../dht/atomic/GridDhtAtomicCache.java          |   43 +-
 .../GridNearAtomicSingleUpdateFuture.java       |    9 +-
 .../dht/atomic/GridNearAtomicUpdateFuture.java  |    9 +-
 .../near/GridNearOptimisticTxPrepareFuture.java |    2 +-
 .../cache/distributed/near/GridNearTxLocal.java |   14 +-
 .../local/atomic/GridLocalAtomicCache.java      |   21 +-
 .../transactions/IgniteTxLocalAdapter.java      |    2 +
 .../odbc/jdbc/JdbcQueryExecuteRequest.java      |   29 +-
 .../odbc/jdbc/JdbcRequestHandler.java           |   27 +-
 .../processors/odbc/jdbc/JdbcStatementType.java |   32 +
 .../processors/query/GridQueryProcessor.java    |   28 +-
 .../processors/query/GridQueryProperty.java     |    7 +
 .../query/GridQueryTypeDescriptor.java          |   10 +
 .../internal/processors/query/QueryField.java   |   14 +-
 .../internal/processors/query/QuerySchema.java  |   11 +-
 .../query/QueryTypeDescriptorImpl.java          |   30 +
 .../internal/processors/query/QueryUtils.java   |   42 +-
 .../query/property/QueryBinaryProperty.java     |   12 +-
 .../query/property/QueryClassProperty.java      |   16 +-
 .../query/h2/DmlStatementsProcessor.java        |   10 +-
 .../processors/query/h2/IgniteH2Indexing.java   |    3 +-
 .../query/h2/ddl/DdlStatementsProcessor.java    |   18 +-
 .../processors/query/h2/opt/GridH2Table.java    |    6 +-
 .../query/h2/sql/GridSqlCreateTable.java        |   18 +
 .../query/h2/sql/GridSqlQueryParser.java        |   35 +-
 .../cache/index/DynamicColumnsAbstractTest.java |   18 +-
 .../H2DynamicColumnsAbstractBasicSelfTest.java  |   28 +
 .../cache/index/H2DynamicTableSelfTest.java     |   95 +-
 .../IgnitePersistentStoreSchemaLoadTest.java    |   16 +-
 .../query/IgniteSqlNotNullConstraintTest.java   | 1060 ++++++++++++++++++
 .../h2/GridIndexingSpiAbstractSelfTest.java     |   10 +
 .../query/h2/sql/GridQueryParsingTest.java      |   25 +-
 .../IgniteCacheQuerySelfTestSuite.java          |    2 +
 modules/platforms/cpp/odbc-test/Makefile.am     |    1 +
 .../cpp/odbc-test/project/vs/odbc-test.vcxproj  |    1 +
 .../project/vs/odbc-test.vcxproj.filters        |    3 +
 .../cpp/odbc-test/src/attributes_test.cpp       |  208 ++++
 .../platforms/cpp/odbc/include/ignite/odbc.h    |   22 +-
 .../cpp/odbc/include/ignite/odbc/connection.h   |   47 +
 modules/platforms/cpp/odbc/src/connection.cpp   |  100 +-
 modules/platforms/cpp/odbc/src/entry_points.cpp |   65 +-
 modules/platforms/cpp/odbc/src/odbc.cpp         |   46 +-
 .../Cache/CacheAbstractTest.cs                  |   67 +-
 .../Dataload/DataStreamerTest.cs                |   49 +
 .../Impl/Binary/BinaryWriterExtensions.cs       |    8 +-
 .../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs  |   52 +-
 .../Impl/Compute/ComputeImpl.cs                 |    2 +-
 .../Impl/Datastream/DataStreamerBatch.cs        |   10 +-
 .../Impl/Services/ServiceProxySerializer.cs     |   10 +-
 .../frontend/public/images/icons/index.js       |    1 +
 .../frontend/public/images/icons/refresh.svg    |    1 +
 62 files changed, 2318 insertions(+), 238 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/b5cac1c0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5cac1c0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5cac1c0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5cac1c0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5cac1c0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5cac1c0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5cac1c0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/atomic/GridLocalAtomicCache.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5cac1c0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
----------------------------------------------------------------------


[06/12] ignite git commit: IGNITE-5648: SQL: Added support for NOT NULL constraint. This closes #2341.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlNotNullConstraintTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlNotNullConstraintTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlNotNullConstraintTest.java
new file mode 100644
index 0000000..dab474e
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlNotNullConstraintTest.java
@@ -0,0 +1,1060 @@
+/*
+ * 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.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import javax.cache.CacheException;
+import javax.cache.processor.EntryProcessor;
+import javax.cache.processor.EntryProcessorException;
+import javax.cache.processor.EntryProcessorResult;
+import javax.cache.processor.MutableEntry;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.cache.store.CacheStoreAdapter;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.MemoryConfiguration;
+import org.apache.ignite.configuration.NearCacheConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.lang.IgniteBiInClosure;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.transactions.Transaction;
+import org.apache.ignite.transactions.TransactionConcurrency;
+import org.apache.ignite.transactions.TransactionIsolation;
+import org.jetbrains.annotations.Nullable;
+
+/** */
+public class IgniteSqlNotNullConstraintTest extends GridCommonAbstractTest {
+    /** IP finder. */
+    private static final TcpDiscoveryVmIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** Name of client node. */
+    private static String NODE_CLIENT = "client";
+
+    /** Number of server nodes. */
+    private static int NODE_COUNT = 2;
+
+    /** Cache prefix. */
+    private static String CACHE_PREFIX = "person";
+
+    /** Transactional person cache. */
+    private static String CACHE_PERSON = "person-PARTITIONED-TRANSACTIONAL";
+
+    /** Name of SQL table. */
+    private static String TABLE_PERSON = "\"" + CACHE_PERSON +  "\".\"PERSON\"";
+
+    /** Expected error message. */
+    private static String ERR_MSG = "Null value is not allowed for field 'NAME'";
+
+    /** OK value. */
+    private final Person okValue = new Person("Name", 18);
+
+    /** Bad value, violating constraint. */
+    private final Person badValue = new Person(null, 25);
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration c = super.getConfiguration(gridName);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+        disco.setForceServerMode(true);
+
+        c.setDiscoverySpi(disco);
+
+        List<CacheConfiguration> ccfgs = new ArrayList<>();
+
+        ccfgs.addAll(cacheConfigurations());
+
+        c.setCacheConfiguration(ccfgs.toArray(new CacheConfiguration[ccfgs.size()]));
+
+        if (gridName.equals(NODE_CLIENT)) {
+            c.setClientMode(true);
+
+            // Not allowed to have local cache on client without memory config
+            c.setMemoryConfiguration(new MemoryConfiguration());
+        }
+
+        return c;
+    }
+
+    /** */
+    private List<CacheConfiguration> cacheConfigurations() {
+        List<CacheConfiguration> res = new ArrayList<>();
+
+        for (boolean wrt : new boolean[] { false, true}) {
+            res.add(buildCacheConfiguration(CacheMode.LOCAL, CacheAtomicityMode.ATOMIC, false, wrt));
+            res.add(buildCacheConfiguration(CacheMode.LOCAL, CacheAtomicityMode.TRANSACTIONAL, false, wrt));
+
+            res.add(buildCacheConfiguration(CacheMode.REPLICATED, CacheAtomicityMode.ATOMIC, false, wrt));
+            res.add(buildCacheConfiguration(CacheMode.REPLICATED, CacheAtomicityMode.TRANSACTIONAL, false, wrt));
+
+            res.add(buildCacheConfiguration(CacheMode.PARTITIONED, CacheAtomicityMode.ATOMIC, false, wrt));
+            res.add(buildCacheConfiguration(CacheMode.PARTITIONED, CacheAtomicityMode.ATOMIC, true, wrt));
+            res.add(buildCacheConfiguration(CacheMode.PARTITIONED, CacheAtomicityMode.TRANSACTIONAL, false, wrt));
+            res.add(buildCacheConfiguration(CacheMode.PARTITIONED, CacheAtomicityMode.TRANSACTIONAL, true, wrt));
+        }
+
+        return res;
+    }
+
+    /** */
+    private CacheConfiguration buildCacheConfiguration(CacheMode mode,
+        CacheAtomicityMode atomicityMode, boolean hasNear, boolean writeThrough) {
+
+        CacheConfiguration cfg = new CacheConfiguration(CACHE_PREFIX + "-" +
+            mode.name() + "-" + atomicityMode.name() + (hasNear ? "-near" : "") +
+            (writeThrough ? "-writethrough" : ""));
+
+        cfg.setCacheMode(mode);
+        cfg.setAtomicityMode(atomicityMode);
+        cfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
+
+        QueryEntity qe = new QueryEntity(Integer.class, Person.class);
+
+        qe.setNotNullFields(Collections.singleton("name"));
+
+        cfg.setQueryEntities(F.asList(qe));
+
+        if (hasNear)
+            cfg.setNearConfiguration(new NearCacheConfiguration().setNearStartSize(100));
+
+        if (writeThrough) {
+            cfg.setCacheStoreFactory(singletonFactory(new TestStore()));
+            cfg.setWriteThrough(true);
+        }
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGrids(NODE_COUNT);
+
+        startGrid(NODE_CLIENT);
+
+        awaitPartitionMapExchange();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        super.afterTestsStopped();
+
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        cleanup();
+    }
+
+    /** */
+    public void testQueryEntityGetSetNotNullFields() throws Exception {
+        QueryEntity qe = new QueryEntity();
+
+        assertNull(qe.getNotNullFields());
+
+        Set<String> val = Collections.singleton("test");
+
+        qe.setNotNullFields(val);
+
+        assertEquals(val, Collections.singleton("test"));
+
+        qe.setNotNullFields(null);
+
+        assertNull(qe.getNotNullFields());
+    }
+
+    /** */
+    public void testQueryEntityEquals() throws Exception {
+        QueryEntity a = new QueryEntity();
+
+        QueryEntity b = new QueryEntity();
+
+        assertEquals(a, b);
+
+        a.setNotNullFields(Collections.singleton("test"));
+
+        assertFalse(a.equals(b));
+
+        b.setNotNullFields(Collections.singleton("test"));
+
+        assertTrue(a.equals(b));
+    }
+
+    /** */
+    public void testAtomicOrImplicitTxPut() throws Exception {
+        executeWithAllCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                cache.put(key1, okValue);
+
+                GridTestUtils.assertThrowsAnyCause(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        cache.put(key2, badValue);
+
+                        return null;
+                    }
+                }, IgniteCheckedException.class, ERR_MSG);
+            }
+        });
+    }
+
+    /** */
+    public void testAtomicOrImplicitTxPutIfAbsent() throws Exception {
+        executeWithAllCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                GridTestUtils.assertThrowsAnyCause(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        cache.putIfAbsent(key1, badValue);
+
+                        return null;
+                    }
+                }, IgniteCheckedException.class, ERR_MSG);
+
+                assertEquals(0, cache.size());
+            }
+        });
+    }
+
+    /** */
+    public void testAtomicOrImplicitTxGetAndPut() throws Exception {
+        executeWithAllCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                GridTestUtils.assertThrowsAnyCause(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        cache.getAndPut(key1, badValue);
+
+                        return null;
+                    }
+                }, IgniteCheckedException.class, ERR_MSG);
+
+                assertEquals(0, cache.size());
+            }
+        });
+    }
+
+    /** */
+    public void testAtomicOrImplicitTxGetAndPutIfAbsent() throws Exception {
+        executeWithAllCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                assertEquals(0, cache.size());
+
+                GridTestUtils.assertThrowsAnyCause(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        return cache.getAndPutIfAbsent(key1, badValue);
+                    }
+                }, IgniteCheckedException.class, ERR_MSG);
+
+                assertEquals(0, cache.size());
+            }
+        });
+    }
+
+    /** */
+    public void testAtomicOrImplicitTxReplace() throws Exception {
+        executeWithAllCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                cache.put(key1, okValue);
+
+                GridTestUtils.assertThrowsAnyCause(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        return cache.replace(key1, badValue);
+                    }
+                }, IgniteCheckedException.class, ERR_MSG);
+
+                assertEquals(1, cache.size());
+                assertEquals(okValue, cache.get(key1));
+            }
+        });
+    }
+
+    /** */
+    public void testAtomicOrImplicitTxGetAndReplace() throws Exception {
+        executeWithAllCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                cache.put(key1, okValue);
+
+                GridTestUtils.assertThrowsAnyCause(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        return cache.getAndReplace(key1, badValue);
+                    }
+                }, IgniteCheckedException.class, ERR_MSG);
+
+                assertEquals(1, cache.size());
+                assertEquals(okValue, cache.get(key1));
+            }
+        });
+    }
+
+    /** */
+    public void testAtomicOrImplicitTxPutAll() throws Exception {
+        executeWithAllCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                Throwable t = GridTestUtils.assertThrowsWithCause(new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        cache.putAll(F.asMap(key1, okValue, key2, badValue));
+
+                        return null;
+                    }
+                }, IgniteSQLException.class);
+
+                IgniteSQLException ex = X.cause(t, IgniteSQLException.class);
+
+                assertNotNull(ex);
+
+                assertTrue(ex.getMessage().contains(ERR_MSG));
+
+                assertEquals(isLocalAtomic() ? 1 : 0, cache.size());
+            }
+        });
+    }
+
+    /** */
+    public void testAtomicOrImplicitTxInvoke() throws Exception {
+        executeWithAllCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                GridTestUtils.assertThrowsAnyCause(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        return cache.invoke(key1, new TestEntryProcessor(badValue));
+                    }
+                }, IgniteCheckedException.class, ERR_MSG);
+
+                assertEquals(0, cache.size());
+            }
+        });
+    }
+
+    /** */
+    public void testAtomicOrImplicitTxInvokeAll() throws Exception {
+        executeWithAllCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                final Map<Integer, EntryProcessorResult<Object>> r = cache.invokeAll(F.asMap(
+                    key1, new TestEntryProcessor(okValue),
+                    key2, new TestEntryProcessor(badValue)));
+
+                assertNotNull(r);
+
+                GridTestUtils.assertThrowsAnyCause(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        return r.get(key2).get();
+                    }
+                }, IgniteCheckedException.class, ERR_MSG);
+
+                assertEquals(1, cache.size());
+            }
+        });
+    }
+
+    /** */
+    public void testTxPutCreate() throws Exception {
+        executeWithAllTxCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                GridTestUtils.assertThrows(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        try (Transaction tx = ignite.transactions().txStart(concurrency, isolation)) {
+                            cache.put(key1, okValue);
+                            cache.put(key2, badValue);
+
+                            tx.commit();
+                        }
+
+                        assertEquals(0, cache.size());
+
+                        return null;
+                    }
+                }, CacheException.class, ERR_MSG);
+            }
+        });
+    }
+
+    /** */
+    public void testTxPutUpdate() throws Exception {
+        executeWithAllTxCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                GridTestUtils.assertThrows(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        try (Transaction tx = ignite.transactions().txStart(concurrency, isolation)) {
+                            cache.put(key1, okValue);
+                            cache.put(key2, okValue);
+                            cache.put(key2, badValue);
+
+                            tx.commit();
+                        }
+
+                        assertEquals(0, cache.size());
+
+                        return null;
+                    }
+                }, CacheException.class, ERR_MSG);
+            }
+        });
+    }
+
+    /** */
+    public void testTxPutIfAbsent() throws Exception {
+        executeWithAllTxCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                GridTestUtils.assertThrows(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        try (Transaction tx = ignite.transactions().txStart(concurrency, isolation)) {
+                            cache.putIfAbsent(key1, badValue);
+
+                            tx.commit();
+                        }
+
+                        assertEquals(0, cache.size());
+
+                        return null;
+                    }
+                }, CacheException.class, ERR_MSG);
+            }
+        });
+    }
+
+    /** */
+    public void testTxGetAndPut() throws Exception {
+        executeWithAllTxCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                GridTestUtils.assertThrows(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        try (Transaction tx = ignite.transactions().txStart(concurrency, isolation)) {
+                            cache.getAndPut(key1, badValue);
+
+                            tx.commit();
+                        }
+
+                        assertEquals(0, cache.size());
+
+                        return null;
+                    }
+                }, CacheException.class, ERR_MSG);
+            }
+        });
+    }
+
+    /** */
+    public void testTxGetAndPutIfAbsent() throws Exception {
+        executeWithAllTxCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                GridTestUtils.assertThrows(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        try (Transaction tx = ignite.transactions().txStart(concurrency, isolation)) {
+                            cache.getAndPutIfAbsent(key1, badValue);
+
+                            tx.commit();
+                        }
+
+                        assertEquals(0, cache.size());
+
+                        return null;
+                    }
+                }, CacheException.class, ERR_MSG);
+            }
+        });
+    }
+
+    /** */
+    public void testTxReplace() throws Exception {
+        executeWithAllTxCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                GridTestUtils.assertThrows(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        cache.put(1, okValue);
+
+                        try (Transaction tx = ignite.transactions().txStart(concurrency, isolation)) {
+                            cache.replace(key1, badValue);
+
+                            tx.commit();
+                        }
+
+                        assertEquals(1, cache.size());
+                        assertEquals(okValue, cache.get(key1));
+
+                        return null;
+                    }
+                }, CacheException.class, ERR_MSG);
+            }
+        });
+    }
+
+    /** */
+    public void testTxGetAndReplace() throws Exception {
+        executeWithAllTxCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                GridTestUtils.assertThrows(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        cache.put(key1, okValue);
+
+                        try (Transaction tx = ignite.transactions().txStart(concurrency, isolation)) {
+                            cache.getAndReplace(key1, badValue);
+
+                            tx.commit();
+                        }
+
+                        assertEquals(1, cache.size());
+                        assertEquals(okValue, cache.get(key1));
+
+                        return null;
+                    }
+                }, CacheException.class, ERR_MSG);
+            }
+        });
+    }
+
+    /** */
+    public void testTxPutAll() throws Exception {
+        executeWithAllTxCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                GridTestUtils.assertThrows(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        try (Transaction tx = ignite.transactions().txStart(concurrency, isolation)) {
+                            cache.putAll(F.asMap(key1, okValue, key2, badValue));
+
+                            tx.commit();
+                        }
+
+                        assertEquals(0, cache.size());
+
+                        return null;
+                    }
+                }, CacheException.class, ERR_MSG);
+            }
+        });
+    }
+
+    /** */
+    public void testTxInvoke() throws Exception {
+        executeWithAllTxCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+                cache.put(key1, okValue);
+
+                GridTestUtils.assertThrows(log, new Callable<Object>() {
+                    @Override public Object call() throws Exception {
+                        try (Transaction tx = ignite.transactions().txStart(concurrency, isolation)) {
+                            cache.invoke(key1, new TestEntryProcessor(badValue));
+
+                            tx.commit();
+                        }
+
+                        return null;
+                    }
+                }, EntryProcessorException.class, ERR_MSG);
+
+                assertEquals(1, cache.size());
+                assertEquals(okValue, cache.get(key1));
+            }
+        });
+    }
+
+    /** */
+    public void testTxInvokeAll() throws Exception {
+        executeWithAllTxCaches(new TestClosure() {
+            @Override public void run() throws Exception {
+
+                try (Transaction tx = ignite.transactions().txStart(concurrency, isolation)) {
+                    final Map<Integer, EntryProcessorResult<Object>> r = cache.invokeAll(F.asMap(
+                        key1, new TestEntryProcessor(okValue),
+                        key2, new TestEntryProcessor(badValue)));
+
+                    assertNotNull(r);
+
+                    GridTestUtils.assertThrows(log, new Callable<Object>() {
+                        @Override public Object call() throws Exception {
+                            return r.get(key2).get();
+                        }
+                    }, EntryProcessorException.class, ERR_MSG);
+
+                    tx.rollback();
+                }
+
+                assertEquals(0, cache.size());
+            }
+        });
+    }
+
+    /** */
+    public void testDynamicTableCreateNotNullFieldsAllowed() throws Exception {
+        executeSql("CREATE TABLE test(id INT PRIMARY KEY, field INT NOT NULL)");
+
+        String cacheName = QueryUtils.createTableCacheName("PUBLIC", "TEST");
+
+        IgniteEx client = grid(NODE_CLIENT);
+
+        CacheConfiguration ccfg = client.context().cache().cache(cacheName).configuration();
+
+        QueryEntity qe = (QueryEntity)F.first(ccfg.getQueryEntities());
+
+        assertEquals(Collections.singleton("FIELD"), qe.getNotNullFields());
+
+        checkState("PUBLIC", "TEST", "FIELD");
+    }
+
+    /** */
+    public void testAlterTableAddColumnNotNullFieldAllowed() throws Exception {
+        executeSql("CREATE TABLE test(id INT PRIMARY KEY, age INT)");
+
+        executeSql("ALTER TABLE test ADD COLUMN name CHAR NOT NULL");
+
+        checkState("PUBLIC", "TEST", "NAME");
+    }
+
+    /** */
+    public void testAtomicNotNullCheckDmlInsertValues() throws Exception {
+        checkNotNullCheckDmlInsertValues(CacheAtomicityMode.ATOMIC);
+    }
+
+    /** */
+    public void testTransactionalNotNullCheckDmlInsertValues() throws Exception {
+        checkNotNullCheckDmlInsertValues(CacheAtomicityMode.TRANSACTIONAL);
+    }
+
+    /** */
+    private void checkNotNullCheckDmlInsertValues(CacheAtomicityMode atomicityMode) throws Exception {
+        executeSql("CREATE TABLE test(id INT PRIMARY KEY, name VARCHAR NOT NULL) WITH \"atomicity="
+                + atomicityMode.name() + "\"");
+
+        GridTestUtils.assertThrows(log(), new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                executeSql("INSERT INTO test(id, name) " +
+                    "VALUES (1, 'ok'), (2, NULLIF('a', 'a')), (3, 'ok')");
+
+                return null;
+            }
+        }, IgniteSQLException.class, ERR_MSG);
+
+        List<List<?>> result = executeSql("SELECT id, name FROM test ORDER BY id");
+
+        assertEquals(0, result.size());
+
+        executeSql("INSERT INTO test(id, name) VALUES (1, 'ok'), (2, 'ok2'), (3, 'ok3')");
+
+        result = executeSql("SELECT id, name FROM test ORDER BY id");
+
+        assertEquals(3, result.size());
+    }
+
+    /** */
+    public void testAtomicAddColumnNotNullCheckDmlInsertValues() throws Exception {
+        checkAddColumnNotNullCheckDmlInsertValues(CacheAtomicityMode.ATOMIC);
+    }
+
+    /** */
+    public void testTransactionalAddColumnNotNullCheckDmlInsertValues() throws Exception {
+        checkAddColumnNotNullCheckDmlInsertValues(CacheAtomicityMode.TRANSACTIONAL);
+    }
+
+    /** */
+    private void checkAddColumnNotNullCheckDmlInsertValues(CacheAtomicityMode atomicityMode) throws Exception {
+        executeSql("CREATE TABLE test(id INT PRIMARY KEY, age INT) WITH \"atomicity="
+            + atomicityMode.name() + "\"");
+
+        executeSql("ALTER TABLE test ADD COLUMN name VARCHAR NOT NULL");
+
+        GridTestUtils.assertThrows(log(), new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                executeSql("INSERT INTO test(id, name, age) " +
+                    "VALUES (1, 'ok', 1), (2, NULLIF('a', 'a'), 2), (3, 'ok', 3)");
+
+                return null;
+            }
+        }, IgniteSQLException.class, ERR_MSG);
+
+        List<List<?>> result = executeSql("SELECT id, name, age FROM test ORDER BY id");
+
+        assertEquals(0, result.size());
+
+        executeSql("INSERT INTO test(id, name) VALUES (1, 'ok'), (2, 'ok2'), (3, 'ok3')");
+
+        result = executeSql("SELECT id, name FROM test ORDER BY id");
+
+        assertEquals(3, result.size());
+    }
+
+    /** */
+    public void testNotNullCheckDmlInsertFromSelect() throws Exception {
+        executeSql("CREATE TABLE test(id INT PRIMARY KEY, name VARCHAR, age INT)");
+
+        executeSql("INSERT INTO test(id, name, age) VALUES (1, 'Macy', 25), (2, null, 25), (3, 'John', 30)");
+
+        GridTestUtils.assertThrows(log(), new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                return executeSql("INSERT INTO " + TABLE_PERSON +
+                    "(_key, name, age) " +
+                    "SELECT id, name, age FROM test");
+            }
+        }, IgniteSQLException.class, ERR_MSG);
+
+        List<List<?>> result = executeSql("SELECT _key, name FROM " + TABLE_PERSON + " ORDER BY _key");
+
+        assertEquals(0, result.size());
+
+        executeSql("DELETE FROM test WHERE id = 2");
+
+        result = executeSql("INSERT INTO " + TABLE_PERSON + "(_key, name, age) " + "SELECT id, name, age FROM test");
+
+        assertEquals(2L, result.get(0).get(0));
+    }
+
+    /** */
+    public void testNotNullCheckDmlUpdateValues() throws Exception {
+        executeSql("CREATE TABLE test(id INT PRIMARY KEY, name VARCHAR NOT NULL)");
+
+        executeSql("INSERT INTO test(id, name) VALUES (1, 'John')");
+
+        GridTestUtils.assertThrows(log(), new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                return executeSql("UPDATE test SET name = NULLIF(id, 1) WHERE id = 1");
+            }
+        }, IgniteSQLException.class, ERR_MSG);
+
+        List<List<?>> result = executeSql("SELECT id, name FROM test");
+
+        assertEquals(1, result.size());
+        assertEquals(1, result.get(0).get(0));
+        assertEquals("John", result.get(0).get(1));
+
+        executeSql("UPDATE test SET name = 'James' WHERE id = 1");
+
+        result = executeSql("SELECT id, name FROM test");
+
+        assertEquals(1, result.get(0).get(0));
+        assertEquals("James", result.get(0).get(1));
+    }
+
+    /** */
+    public void testNotNullCheckDmlUpdateFromSelect() throws Exception {
+        executeSql("CREATE TABLE src(id INT PRIMARY KEY, name VARCHAR)");
+        executeSql("CREATE TABLE dest(id INT PRIMARY KEY, name VARCHAR NOT NULL)");
+
+        executeSql("INSERT INTO dest(id, name) VALUES (1, 'William'), (2, 'Warren'), (3, 'Robert')");
+        executeSql("INSERT INTO src(id, name) VALUES (1, 'Bill'), (2, null), (3, 'Bob')");
+
+        GridTestUtils.assertThrows(log(), new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                return executeSql("UPDATE dest" +
+                    " p SET (name) = " +
+                    "(SELECT name FROM src t WHERE p.id = t.id)");
+            }
+        }, IgniteSQLException.class, ERR_MSG);
+
+        List<List<?>> result = executeSql("SELECT id, name FROM dest ORDER BY id");
+
+        assertEquals(3, result.size());
+
+        assertEquals(1, result.get(0).get(0));
+        assertEquals("William", result.get(0).get(1));
+
+        assertEquals(2, result.get(1).get(0));
+        assertEquals("Warren", result.get(1).get(1));
+
+        assertEquals(3, result.get(2).get(0));
+        assertEquals("Robert", result.get(2).get(1));
+
+        executeSql("UPDATE src SET name = 'Ren' WHERE id = 2");
+
+        executeSql("UPDATE dest p SET (name) = (SELECT name FROM src t WHERE p.id = t.id)");
+
+        result = executeSql("SELECT id, name FROM dest ORDER BY id");
+
+        assertEquals(3, result.size());
+
+        assertEquals(1, result.get(0).get(0));
+        assertEquals("Bill", result.get(0).get(1));
+
+        assertEquals(2, result.get(1).get(0));
+        assertEquals("Ren", result.get(1).get(1));
+
+        assertEquals(3, result.get(2).get(0));
+        assertEquals("Bob", result.get(2).get(1));
+    }
+
+    /** */
+    private void executeWithAllCaches(TestClosure clo) throws Exception {
+        for (CacheConfiguration ccfg : cacheConfigurations())
+            executeForCache(ccfg, clo, TransactionConcurrency.OPTIMISTIC, TransactionIsolation.READ_COMMITTED);
+    }
+
+    /** */
+    private void executeWithAllTxCaches(final TestClosure clo) throws Exception {
+        for (CacheConfiguration ccfg : cacheConfigurations()) {
+            if (ccfg.getAtomicityMode() == CacheAtomicityMode.TRANSACTIONAL) {
+                for (TransactionConcurrency con : TransactionConcurrency.values()) {
+                    for (TransactionIsolation iso : TransactionIsolation.values())
+                        executeForCache(ccfg, clo, con, iso);
+                }
+            }
+        }
+    }
+
+    /** */
+    private void executeForCache(CacheConfiguration ccfg, TestClosure clo, TransactionConcurrency concurrency,
+        TransactionIsolation isolation) throws Exception {
+
+        Ignite ignite = grid(NODE_CLIENT);
+        executeForNodeAndCache(ccfg, ignite, clo, concurrency, isolation);
+
+        for (int node = 0; node < NODE_COUNT; node++) {
+            ignite = grid(node);
+
+            executeForNodeAndCache(ccfg, ignite, clo, concurrency, isolation);
+        }
+    }
+
+    /** */
+    private void executeForNodeAndCache(CacheConfiguration ccfg, Ignite ignite, TestClosure clo,
+        TransactionConcurrency concurrency, TransactionIsolation isolation) throws Exception {
+        String cacheName = ccfg.getName();
+
+        IgniteCache cache;
+
+        if (ignite.configuration().isClientMode() &&
+            ccfg.getCacheMode() == CacheMode.PARTITIONED &&
+            ccfg.getNearConfiguration() != null)
+            cache = ignite.getOrCreateNearCache(ccfg.getName(), ccfg.getNearConfiguration());
+        else
+            cache = ignite.cache(ccfg.getName());
+
+        cache.removeAll();
+
+        assertEquals(0, cache.size());
+
+        clo.configure(ignite, cache, concurrency, isolation);
+
+        log.info("Running test with node " + ignite.name() + ", cache " + cacheName);
+
+        clo.key1 = 1;
+        clo.key2 = 4;
+
+        clo.run();
+    }
+
+    /** */
+    private List<List<?>> executeSql(String sqlText) throws Exception {
+        GridQueryProcessor qryProc = grid(NODE_CLIENT).context().query();
+
+        return qryProc.querySqlFieldsNoCache(new SqlFieldsQuery(sqlText), true).getAll();
+    }
+
+    /** */
+    private void cleanup() throws Exception {
+        for (CacheConfiguration ccfg: cacheConfigurations()) {
+            String cacheName = ccfg.getName();
+
+            if (ccfg.getCacheMode() == CacheMode.LOCAL) {
+                grid(NODE_CLIENT).cache(cacheName).clear();
+
+                for (int node = 0; node < NODE_COUNT; node++)
+                    grid(node).cache(cacheName).clear();
+            }
+            else {
+                if (ccfg.getCacheMode() == CacheMode.PARTITIONED && ccfg.getNearConfiguration() != null) {
+                    IgniteCache cache = grid(NODE_CLIENT).getOrCreateNearCache(cacheName, ccfg.getNearConfiguration());
+
+                    cache.clear();
+                }
+
+                grid(NODE_CLIENT).cache(cacheName).clear();
+            }
+        }
+
+        executeSql("DROP TABLE test IF EXISTS");
+    }
+
+    /** */
+    private void checkState(String schemaName, String tableName, String fieldName) {
+        IgniteEx client = grid(NODE_CLIENT);
+
+        checkNodeState(client, schemaName, tableName, fieldName);
+
+        for (int i = 0; i < NODE_COUNT; i++)
+            checkNodeState(grid(i), schemaName, tableName, fieldName);
+    }
+
+    /** */
+    private void checkNodeState(IgniteEx node, String schemaName, String tableName, String fieldName) {
+        String cacheName = F.eq(schemaName, QueryUtils.DFLT_SCHEMA) ?
+            QueryUtils.createTableCacheName(schemaName, tableName) : schemaName;
+
+        DynamicCacheDescriptor desc = node.context().cache().cacheDescriptor(cacheName);
+
+        assertNotNull("Cache descriptor not found", desc);
+
+        QuerySchema schema = desc.schema();
+
+        assertNotNull(schema);
+
+        QueryEntity entity = null;
+
+        for (QueryEntity e : schema.entities()) {
+            if (F.eq(tableName, e.getTableName())) {
+                entity = e;
+
+                break;
+            }
+        }
+
+        assertNotNull(entity);
+
+        assertNotNull(entity.getNotNullFields());
+
+        assertTrue(entity.getNotNullFields().contains(fieldName));
+    }
+
+    /** */
+    public static class Person {
+        /** */
+        @QuerySqlField
+        private String name;
+
+        /** */
+        @QuerySqlField
+        private int age;
+
+        /** */
+        public Person(String name, int age) {
+            this.name = name;
+            this.age = age;
+        }
+
+        /** */
+        @Override public int hashCode() {
+            return (name == null ? 0 : name.hashCode()) ^ age;
+        }
+
+        /** */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+
+            if (!(o instanceof Person))
+                return false;
+
+            Person other = (Person)o;
+
+            return F.eq(other.name, name) && other.age == age;
+        }
+    }
+
+    /** */
+    public class TestEntryProcessor implements EntryProcessor<Integer, Person, Object> {
+        /** Value to set. */
+        private Person value;
+
+        /** */
+        public TestEntryProcessor(Person value) {
+            this.value = value;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object process(MutableEntry<Integer, Person> entry,
+            Object... objects) throws EntryProcessorException {
+
+            entry.setValue(value);
+
+            return null;
+        }
+    }
+
+    /** */
+    public abstract class TestClosure {
+        /** */
+        protected Ignite ignite;
+
+        /** */
+        protected IgniteCache<Integer, Person> cache;
+
+        /** */
+        protected TransactionConcurrency concurrency;
+
+        /** */
+        protected TransactionIsolation isolation;
+
+        /** */
+        public int key1;
+
+        /** */
+        public int key2;
+
+        /** */
+        public void configure(Ignite ignite, IgniteCache<Integer, Person> cache, TransactionConcurrency concurrency,
+            TransactionIsolation isolation) {
+            this.ignite = ignite;
+            this.cache = cache;
+            this.concurrency = concurrency;
+            this.isolation = isolation;
+        }
+
+        /** */
+        protected boolean isLocalAtomic() {
+            CacheConfiguration cfg = cache.getConfiguration(CacheConfiguration.class);
+
+            return cfg.getCacheMode() == CacheMode.LOCAL && cfg.getAtomicityMode() == CacheAtomicityMode.ATOMIC;
+        }
+
+        /** */
+        public abstract void run() throws Exception;
+    }
+
+    /**
+     * Test store.
+     */
+    private static class TestStore extends CacheStoreAdapter<Integer, Person> {
+        /** {@inheritDoc} */
+        @Override public void loadCache(IgniteBiInClosure<Integer, Person> clo, @Nullable Object... args) {
+            // No-op
+        }
+
+        /** {@inheritDoc} */
+        @Override public Person load(Integer key) {
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void write(javax.cache.Cache.Entry<? extends Integer, ? extends Person> e) {
+            // No-op
+        }
+
+        /** {@inheritDoc} */
+        @Override public void delete(Object key) {
+            // No-op
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
index e1ab8e6..1ee8a84 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
@@ -554,6 +554,11 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
                 @Override public GridQueryProperty parent() {
                     return null;
                 }
+
+                /** */
+                @Override public boolean notNull() {
+                    return false;
+                }
             };
         }
 
@@ -643,6 +648,11 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
         @Nullable @Override public String valueFieldAlias() {
             return null;
         }
+
+        /** {@inheritDoc} */
+        @Override public void validateKeyAndValue(Object key, Object value) throws IgniteCheckedException {
+            // No-op.
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
index 770a375..6a78df3 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
@@ -584,9 +584,9 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
         assertCreateTableEquals(
             buildCreateTable("sch1", "Person", "cache", F.asList("id"),
                 false, c("id", Value.INT), c("city", Value.STRING), c("name", Value.STRING),
-                c("surname", Value.STRING), c("age", Value.INT)),
+                c("surname", Value.STRING), cn("age", Value.INT)),
             "CREATE TABLE sch1.\"Person\" (\"id\" integer PRIMARY KEY, \"city\" varchar," +
-                " \"name\" varchar, \"surname\" varchar, \"age\" integer) WITH " +
+                " \"name\" varchar, \"surname\" varchar, \"age\" integer NOT NULL) WITH " +
                 "\"template=cache\"");
 
         assertParseThrows("create table Person (id int)",
@@ -598,9 +598,6 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
         assertParseThrows("create table Person (id int primary key)",
             IgniteSQLException.class, "No cache value related columns found");
 
-        assertParseThrows("create table Person (id int primary key, age int not null) WITH \"cacheTemplate=cache\"",
-            IgniteSQLException.class, "Non nullable columns are not supported [colName=AGE]");
-
         assertParseThrows("create table Person (id int primary key, age int unique) WITH \"template=cache\"",
             IgniteSQLException.class, "Too many constraints - only PRIMARY KEY is supported for CREATE TABLE");
 
@@ -635,6 +632,9 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
         assertAlterTableAddColumnEquals(buildAlterTableAddColumn("SCH2", "City", false, true,
             c("POPULATION", Value.INT)), "ALTER TABLE IF EXISTS SCH2.\"City\" ADD (population int)");
 
+        assertAlterTableAddColumnEquals(buildAlterTableAddColumn("SCH2", "City", false, true,
+            cn("POPULATION", Value.INT)), "ALTER TABLE IF EXISTS SCH2.\"City\" ADD (population int NOT NULL)");
+
         // There's no table with such name, but H2 parsing does not fail just yet.
         assertAlterTableAddColumnEquals(buildAlterTableAddColumn("SCH2", "City", false, false,
             c("POPULATION", Value.INT)), "ALTER TABLE SCH2.\"City\" ADD (population int)");
@@ -846,6 +846,21 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
     }
 
     /**
+     * Constructs non-nullable column.
+     *
+     * @param name Column name.
+     * @param type Column data type.
+     * @return {@link GridSqlColumn} with given name and type.
+     */
+    private static GridSqlColumn cn(String name, int type) {
+        Column col = new Column(name, type);
+
+        col.setNullable(false);
+
+        return new GridSqlColumn(col, null, name);
+    }
+
+    /**
      * Parse SQL and compare it to expected instance of DROP TABLE.
      */
     private void assertDropTableEquals(GridSqlDropTable exp, String sql) throws Exception {

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/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 040d0af..e5e37cc 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
@@ -126,6 +126,7 @@ import org.apache.ignite.internal.processors.query.h2.IgniteSqlBigIntegerKeyTest
 import org.apache.ignite.internal.processors.query.IgniteQueryDedicatedPoolTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlEntryCacheModeAgnosticTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlKeyValueFieldsTest;
+import org.apache.ignite.internal.processors.query.IgniteSqlNotNullConstraintTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlRoutingTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSchemaIndexingTest;
 import org.apache.ignite.internal.processors.query.IgniteSqlSegmentedIndexMultiNodeSelfTest;
@@ -329,6 +330,7 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
         suite.addTestSuite(IgniteCacheDistributedPartitionQueryConfigurationSelfTest.class);
         suite.addTestSuite(IgniteSqlKeyValueFieldsTest.class);
         suite.addTestSuite(IgniteSqlRoutingTest.class);
+        suite.addTestSuite(IgniteSqlNotNullConstraintTest.class);
         suite.addTestSuite(LongIndexNameTest.class);
 
         suite.addTestSuite(GridCacheQuerySqlFieldInlineSizeSelfTest.class);


[07/12] ignite git commit: IGNITE-5648: SQL: Added support for NOT NULL constraint. This closes #2341.

Posted by sb...@apache.org.
IGNITE-5648: SQL: Added support for NOT NULL constraint. This closes #2341.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/43be051c
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/43be051c
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/43be051c

Branch: refs/heads/ignite-6149
Commit: 43be051cd33f0e35a5bf05fa3dbe73660d2dcdd2
Parents: 8c23805
Author: Sergey Kalashnikov <sk...@gridgain.com>
Authored: Tue Sep 12 16:53:50 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Tue Sep 12 16:53:50 2017 +0300

----------------------------------------------------------------------
 .../org/apache/ignite/cache/QueryEntity.java    |   32 +-
 .../processors/cache/GridCacheContext.java      |   26 +
 .../processors/cache/GridCacheMapEntry.java     |   23 +
 .../distributed/dht/GridDhtTxPrepareFuture.java |    3 +
 .../dht/atomic/GridDhtAtomicCache.java          |   43 +-
 .../GridNearAtomicSingleUpdateFuture.java       |    9 +-
 .../dht/atomic/GridNearAtomicUpdateFuture.java  |    9 +-
 .../near/GridNearOptimisticTxPrepareFuture.java |    2 +-
 .../cache/distributed/near/GridNearTxLocal.java |   14 +-
 .../local/atomic/GridLocalAtomicCache.java      |   21 +-
 .../transactions/IgniteTxLocalAdapter.java      |    2 +
 .../processors/query/GridQueryProcessor.java    |   21 +-
 .../processors/query/GridQueryProperty.java     |    7 +
 .../query/GridQueryTypeDescriptor.java          |   10 +
 .../internal/processors/query/QueryField.java   |   14 +-
 .../internal/processors/query/QuerySchema.java  |   11 +-
 .../query/QueryTypeDescriptorImpl.java          |   30 +
 .../internal/processors/query/QueryUtils.java   |   42 +-
 .../query/property/QueryBinaryProperty.java     |   12 +-
 .../query/property/QueryClassProperty.java      |   16 +-
 .../query/h2/DmlStatementsProcessor.java        |   10 +-
 .../processors/query/h2/IgniteH2Indexing.java   |    3 +-
 .../query/h2/ddl/DdlStatementsProcessor.java    |   15 +-
 .../processors/query/h2/opt/GridH2Table.java    |    6 +-
 .../query/h2/sql/GridSqlQueryParser.java        |    4 -
 .../cache/index/DynamicColumnsAbstractTest.java |   14 +-
 .../H2DynamicColumnsAbstractBasicSelfTest.java  |   28 +
 .../query/IgniteSqlNotNullConstraintTest.java   | 1060 ++++++++++++++++++
 .../h2/GridIndexingSpiAbstractSelfTest.java     |   10 +
 .../query/h2/sql/GridQueryParsingTest.java      |   25 +-
 .../IgniteCacheQuerySelfTestSuite.java          |    2 +
 31 files changed, 1475 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java b/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java
index 6440b48..fe54670 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java
@@ -83,6 +83,9 @@ public class QueryEntity implements Serializable {
     /** Table name. */
     private String tableName;
 
+    /** Fields that must have non-null value. */
+    private Set<String> notNullFields;
+
     /**
      * Creates an empty query entity.
      */
@@ -109,6 +112,8 @@ public class QueryEntity implements Serializable {
         idxs = other.idxs != null ? new ArrayList<>(other.idxs) : null;
 
         tableName = other.tableName;
+
+        notNullFields = other.notNullFields != null ? new HashSet<>(other.notNullFields) : null;
     }
 
     /**
@@ -355,6 +360,27 @@ public class QueryEntity implements Serializable {
     }
 
     /**
+     * Gets names of fields that must be checked for null.
+     *
+     * @return Set of names of fields that must have non-null values.
+     */
+    @Nullable public Set<String> getNotNullFields() {
+        return notNullFields;
+    }
+
+    /**
+     * Sets names of fields that must checked for null.
+     *
+     * @param notNullFields Set of names of fields that must have non-null values.
+     * @return {@code this} for chaining.
+     */
+    public QueryEntity setNotNullFields(@Nullable Set<String> notNullFields) {
+        this.notNullFields = notNullFields;
+
+        return this;
+    }
+
+    /**
      * Utility method for building query entities programmatically.
      * @param fullName Full name of the field.
      * @param type Type of the field.
@@ -604,12 +630,14 @@ public class QueryEntity implements Serializable {
             F.eq(keyFields, entity.keyFields) &&
             F.eq(aliases, entity.aliases) &&
             F.eqNotOrdered(idxs, entity.idxs) &&
-            F.eq(tableName, entity.tableName);
+            F.eq(tableName, entity.tableName) &&
+            F.eq(notNullFields, entity.notNullFields);
     }
 
     /** {@inheritDoc} */
     @Override public int hashCode() {
-        return Objects.hash(keyType, valType, keyFieldName, valueFieldName, fields, keyFields, aliases, idxs, tableName);
+        return Objects.hash(keyType, valType, keyFieldName, valueFieldName, fields, keyFields, aliases, idxs,
+            tableName, notNullFields);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
index b6faf47..120007f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
@@ -630,6 +630,13 @@ public class GridCacheContext<K, V> implements Externalizable {
     }
 
     /**
+     * @return {@code True} in case cache supports query.
+     */
+    public boolean isQueryEnabled() {
+        return !F.isEmpty(cacheCfg.getQueryEntities());
+    }
+
+    /**
      * @return {@code True} if entries should not be deleted from cache immediately.
      */
     public boolean deferredDelete() {
@@ -1804,6 +1811,25 @@ public class GridCacheContext<K, V> implements Externalizable {
     }
 
     /**
+     * Performs validation of provided key and value against configured constraints.
+     *
+     * @param key Key.
+     * @param val Value.
+     * @throws IgniteCheckedException, If validation fails.
+     */
+    public void validateKeyAndValue(KeyCacheObject key, CacheObject val) throws IgniteCheckedException {
+        if (!isQueryEnabled())
+            return;
+
+        try {
+            ctx.query().validateKeyAndValue(cacheObjCtx, key, val);
+        }
+        catch (RuntimeException e) {
+            throw U.cast(e);
+        }
+    }
+
+    /**
      * @param map Map.
      * @param key Key.
      * @param val Value.

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
index 61f6fb4..958f156 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
@@ -1419,6 +1419,9 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                         updated0 = cctx.unwrapTemporary(entry.getValue());
 
                         updated = cctx.toCacheObject(updated0);
+
+                        if (updated != null) // no validation for remove case
+                            cctx.validateKeyAndValue(key, updated);
                     }
                     else
                         updated = old;
@@ -4165,6 +4168,26 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
 
                     return;
                 }
+                else if ((invokeRes == null || invokeRes.getValue() == null) && writeObj != null) {
+                    try {
+                        cctx.validateKeyAndValue(entry.key, (CacheObject)writeObj);
+                    }
+                    catch (Exception e) {
+                        initResultOnCancelUpdate(null, true);
+
+                        updateRes = new GridCacheUpdateAtomicResult(UpdateOutcome.INVOKE_NO_OP,
+                            oldVal,
+                            null,
+                            new IgniteBiTuple<>(null, e),
+                            CU.TTL_ETERNAL,
+                            CU.EXPIRE_TIME_ETERNAL,
+                            null,
+                            null,
+                            0);
+
+                        return;
+                    }
+                }
 
                 op = writeObj == null ? DELETE : UPDATE;
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
index 47dcefc..e048696 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
@@ -419,6 +419,9 @@ public final class GridDhtTxPrepareFuture extends GridCacheCompoundFuture<Ignite
                                     procRes = processor.process(invokeEntry, t.get2());
 
                                     val = cacheCtx.toCacheObject(invokeEntry.getValue(true));
+
+                                    if (val != null) // no validation for remove case
+                                        cacheCtx.validateKeyAndValue(key, val);
                                 }
                                 catch (Exception e) {
                                     err = e;

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
index 7d0f747..a50a707 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
@@ -2105,35 +2105,52 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                     CacheInvokeEntry<Object, Object> invokeEntry = new CacheInvokeEntry(entry.key(), old,
                         entry.version(), req.keepBinary(), entry);
 
-                    CacheObject updated;
+                    CacheObject updated = null;
+
+                    if (invokeRes == null)
+                        invokeRes = new GridCacheReturn(node.isLocal());
+
+                    CacheInvokeResult curInvokeRes = null;
+
+                    boolean validation = false;
 
                     try {
                         Object computed = entryProcessor.process(invokeEntry, req.invokeArguments());
 
                         if (computed != null) {
-                            if (invokeRes == null)
-                                invokeRes = new GridCacheReturn(node.isLocal());
-
                             computed = ctx.unwrapTemporary(computed);
 
-                            invokeRes.addEntryProcessResult(ctx, entry.key(), invokeEntry.key(), computed, null,
-                                req.keepBinary());
+                            curInvokeRes = CacheInvokeResult.fromResult(computed);
                         }
 
                         if (!invokeEntry.modified())
                             continue;
+                        else {
+                            updatedVal = ctx.unwrapTemporary(invokeEntry.getValue());
+
+                            updated = ctx.toCacheObject(updatedVal);
 
-                        updatedVal = ctx.unwrapTemporary(invokeEntry.getValue());
+                            validation = true;
 
-                        updated = ctx.toCacheObject(updatedVal);
+                            ctx.validateKeyAndValue(entry.key(), updated);
+                        }
                     }
                     catch (Exception e) {
-                        if (invokeRes == null)
-                            invokeRes = new GridCacheReturn(node.isLocal());
-
-                        invokeRes.addEntryProcessResult(ctx, entry.key(), invokeEntry.key(), null, e, req.keepBinary());
+                        curInvokeRes = CacheInvokeResult.fromError(e);
 
                         updated = old;
+
+                        if (validation) {
+                            res.addSkippedIndex(i);
+
+                            continue;
+                        }
+                    }
+                    finally {
+                        if (curInvokeRes != null) {
+                            invokeRes.addEntryProcessResult(ctx, entry.key(), invokeEntry.key(), curInvokeRes.result(),
+                                curInvokeRes.error(), req.keepBinary());
+                        }
                     }
 
                     if (updated == null) {
@@ -2272,6 +2289,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
 
                     assert updated != null;
 
+                    ctx.validateKeyAndValue(entry.key(), updated);
+
                     if (putMap == null) {
                         putMap = new LinkedHashMap<>(size, 1.0f);
                         writeVals = new ArrayList<>(size);

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicSingleUpdateFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicSingleUpdateFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicSingleUpdateFuture.java
index 67542ca..b2f9218 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicSingleUpdateFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicSingleUpdateFuture.java
@@ -30,6 +30,7 @@ import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
 import org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheEntryPredicate;
+import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.CachePartialUpdateCheckedException;
 import org.apache.ignite.internal.processors.cache.CacheStoppedException;
 import org.apache.ignite.internal.processors.cache.EntryProcessorResourceInjectorProxy;
@@ -48,7 +49,9 @@ import org.apache.ignite.internal.util.typedef.internal.S;
 import org.jetbrains.annotations.Nullable;
 
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_ASYNC;
+import static org.apache.ignite.internal.processors.cache.GridCacheOperation.CREATE;
 import static org.apache.ignite.internal.processors.cache.GridCacheOperation.TRANSFORM;
+import static org.apache.ignite.internal.processors.cache.GridCacheOperation.UPDATE;
 
 /**
  * DHT atomic cache near update future.
@@ -542,8 +545,12 @@ public class GridNearAtomicSingleUpdateFuture extends GridNearAtomicAbstractUpda
 
         KeyCacheObject cacheKey = cctx.toCacheKeyObject(key);
 
-        if (op != TRANSFORM)
+        if (op != TRANSFORM) {
             val = cctx.toCacheObject(val);
+
+            if (op == CREATE || op == UPDATE)
+                cctx.validateKeyAndValue(cacheKey, (CacheObject)val);
+        }
         else
             val = EntryProcessorResourceInjectorProxy.wrap(cctx.kernalContext(), (EntryProcessor)val);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
index 930012a..e516a99 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
@@ -34,6 +34,7 @@ import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
 import org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheEntryPredicate;
+import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.CachePartialUpdateCheckedException;
 import org.apache.ignite.internal.processors.cache.CacheStoppedException;
 import org.apache.ignite.internal.processors.cache.EntryProcessorResourceInjectorProxy;
@@ -57,7 +58,9 @@ import org.jetbrains.annotations.Nullable;
 
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_ASYNC;
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+import static org.apache.ignite.internal.processors.cache.GridCacheOperation.CREATE;
 import static org.apache.ignite.internal.processors.cache.GridCacheOperation.TRANSFORM;
+import static org.apache.ignite.internal.processors.cache.GridCacheOperation.UPDATE;
 
 /**
  * DHT atomic cache near update future.
@@ -983,8 +986,12 @@ public class GridNearAtomicUpdateFuture extends GridNearAtomicAbstractUpdateFutu
             if (remapKeys != null && !remapKeys.contains(cacheKey))
                 continue;
 
-            if (op != TRANSFORM)
+            if (op != TRANSFORM) {
                 val = cctx.toCacheObject(val);
+
+                if (op == CREATE || op == UPDATE)
+                    cctx.validateKeyAndValue(cacheKey, (CacheObject)val);
+            }
             else
                 val = EntryProcessorResourceInjectorProxy.wrap(cctx.kernalContext(), (EntryProcessor)val);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
index c978848..77c68bd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
@@ -445,7 +445,7 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
 
                 ClusterNode primary = updated.primary();
 
-                assert !primary.isLocal() || !cctx.kernalContext().clientNode();
+                assert !primary.isLocal() || !cctx.kernalContext().clientNode() || write.context().isLocal();
 
                 // Minor optimization to not create MappingKey: on client node can not have mapping for local node.
                 Object key =  cctx.kernalContext().clientNode() ? primary.id() :

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
index a894097..c55276c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
@@ -1252,8 +1252,13 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter implements AutoClosea
                         break; // While.
                     }
 
+                    CacheObject cVal = cacheCtx.toCacheObject(val);
+
+                    if (op == CREATE || op == UPDATE)
+                        cacheCtx.validateKeyAndValue(cacheKey, cVal);
+
                     txEntry = addEntry(op,
-                        cacheCtx.toCacheObject(val),
+                        cVal,
                         entryProcessor,
                         invokeArgs,
                         entry,
@@ -1356,8 +1361,13 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter implements AutoClosea
                 GridCacheOperation op = rmv ? DELETE : entryProcessor != null ? TRANSFORM :
                     v != null ? UPDATE : CREATE;
 
+                CacheObject cVal = cacheCtx.toCacheObject(val);
+
+                if (op == CREATE || op == UPDATE)
+                    cacheCtx.validateKeyAndValue(cacheKey, cVal);
+
                 txEntry = addEntry(op,
-                    cacheCtx.toCacheObject(val),
+                    cVal,
                     entryProcessor,
                     invokeArgs,
                     entry,

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/atomic/GridLocalAtomicCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/atomic/GridLocalAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/atomic/GridLocalAtomicCache.java
index e99c9e8..1be264d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/atomic/GridLocalAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/atomic/GridLocalAtomicCache.java
@@ -866,8 +866,11 @@ public class GridLocalAtomicCache<K, V> extends GridLocalCache<K, V> {
 
             KeyCacheObject cacheKey = ctx.toCacheKeyObject(key);
 
-            if (op == UPDATE)
+            if (op == UPDATE) {
                 val = ctx.toCacheObject(val);
+
+                ctx.validateKeyAndValue(cacheKey, (CacheObject)val);
+            }
             else if (op == TRANSFORM)
                 ctx.kernalContext().resource().inject(val, GridResourceIoc.AnnotationSet.ENTRY_PROCESSOR, ctx.name());
 
@@ -1055,6 +1058,8 @@ public class GridLocalAtomicCache<K, V> extends GridLocalCache<K, V> {
                         Object updatedVal = null;
                         CacheInvokeResult invokeRes = null;
 
+                        boolean validation = false;
+
                         try {
                             Object computed = entryProcessor.process(invokeEntry, invokeArgs);
 
@@ -1064,11 +1069,23 @@ public class GridLocalAtomicCache<K, V> extends GridLocalCache<K, V> {
 
                             if (computed != null)
                                 invokeRes = CacheInvokeResult.fromResult(ctx.unwrapTemporary(computed));
+
+                            if (invokeEntry.modified()) {
+                                validation = true;
+
+                                ctx.validateKeyAndValue(entry.key(), updated);
+                            }
                         }
                         catch (Exception e) {
                             invokeRes = CacheInvokeResult.fromError(e);
 
                             updated = old;
+
+                            if (validation) {
+                                invokeResMap.put((K)entry.key().value(ctx.cacheObjectContext(), false), invokeRes);
+
+                                continue;
+                            }
                         }
 
                         if (invokeRes != null)
@@ -1175,6 +1192,8 @@ public class GridLocalAtomicCache<K, V> extends GridLocalCache<K, V> {
                             cacheVal = ctx.toCacheObject(ctx.unwrapTemporary(interceptorVal));
                         }
 
+                        ctx.validateKeyAndValue(entry.key(), cacheVal);
+
                         if (putMap == null) {
                             putMap = new LinkedHashMap<>(size, 1.0f);
                             writeVals = new ArrayList<>(size);

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
index e7ebaae..7ab921c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
@@ -1203,6 +1203,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter implements Ig
                 key0 = invokeEntry.key();
             }
 
+            ctx.validateKeyAndValue(txEntry.key(), ctx.toCacheObject(val0));
+
             if (res != null)
                 ret.addEntryProcessResult(ctx, txEntry.key(), key0, res, null, txEntry.keepBinary());
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
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 323bae6..593a3b2 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
@@ -2241,7 +2241,7 @@ private IgniteInternalFuture<Object> rebuildIndexesFromHash(@Nullable final Stri
         for (QueryField col : cols) {
             try {
                 props.add(new QueryBinaryProperty(ctx, col.name(), null, Class.forName(col.typeName()),
-                    false, null));
+                    false, null, !col.isNullable()));
             }
             catch (ClassNotFoundException e) {
                 throw new SchemaOperationException("Class not found for new property: " + col.typeName());
@@ -2593,6 +2593,25 @@ private IgniteInternalFuture<Object> rebuildIndexesFromHash(@Nullable final Stri
     }
 
     /**
+     * Performs validation of provided key and value against configured constraints.
+     * Throws runtime exception if validation fails.
+     *
+     * @param coctx Cache object context.
+     * @param key Key.
+     * @param val Value.
+     * @throws IgniteCheckedException, If error happens.
+     */
+    public void validateKeyAndValue(CacheObjectContext coctx, KeyCacheObject key, CacheObject val)
+        throws IgniteCheckedException {
+        QueryTypeDescriptorImpl desc = typeByValue(coctx.cacheName(), coctx, key, val, false);
+
+        if (desc == null)
+            return;
+
+        desc.validateKeyAndValue(key, val);
+    }
+
+    /**
      * @param ver Version.
      */
     public static void setRequestAffinityTopologyVersion(AffinityTopologyVersion ver) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java
index fb4c037..c8ae212 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java
@@ -63,4 +63,11 @@ public interface GridQueryProperty {
      * @return Parent property or {@code null} if this property is not nested.
      */
     public GridQueryProperty parent();
+
+    /**
+     * Gets the flag restricting {@code null} value for this property.
+     *
+     * @return {@code true} if property does not allow {@code null} value.
+     */
+    public boolean notNull();
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryTypeDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryTypeDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryTypeDescriptor.java
index c149335..dcf850c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryTypeDescriptor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryTypeDescriptor.java
@@ -167,4 +167,14 @@ public interface GridQueryTypeDescriptor {
      * @return value field alias.
      */
     @Nullable public String valueFieldAlias();
+
+    /**
+     * Performs validation of given key and value against configured constraints.
+     * Throws runtime exception if validation fails.
+     *
+     * @param key Key.
+     * @param val Value.
+     * @throws IgniteCheckedException, If failure happens.
+     */
+    public void validateKeyAndValue(Object key, Object val) throws IgniteCheckedException;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryField.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryField.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryField.java
index 968c287..8c7d367 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryField.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryField.java
@@ -34,13 +34,18 @@ public class QueryField implements Serializable {
     /** Class name for this field's values. */
     private final String typeName;
 
+    /** Nullable flag. */
+    private final boolean nullable;
+
     /**
      * @param name Field name.
      * @param typeName Class name for this field's values.
+     * @param nullable Nullable flag.
      */
-    public QueryField(String name, String typeName) {
+    public QueryField(String name, String typeName, boolean nullable) {
         this.name = name;
         this.typeName = typeName;
+        this.nullable = nullable;
     }
 
     /**
@@ -57,6 +62,13 @@ public class QueryField implements Serializable {
         return typeName;
     }
 
+    /**
+     * @return {@code true}, if field is nullable.
+     */
+    public boolean isNullable() {
+        return nullable;
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(QueryField.class, this);

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QuerySchema.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QuerySchema.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QuerySchema.java
index ccbba93..40da780 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QuerySchema.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QuerySchema.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.query;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import org.apache.ignite.cache.QueryEntity;
@@ -163,8 +164,16 @@ public class QuerySchema implements Serializable {
                 if (target == null)
                     return;
 
-                for (QueryField field : op0.columns())
+                for (QueryField field : op0.columns()) {
                     target.getFields().put(field.name(), field.typeName());
+
+                    if (!field.isNullable()) {
+                        if (target.getNotNullFields() == null)
+                            target.setNotNullFields(new HashSet<String>());
+
+                        target.getNotNullFields().add(field.name());
+                    }
+                }
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
index 0b77c4c..e12476a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
@@ -22,9 +22,12 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
+
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cache.QueryIndexType;
+import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.internal.A;
@@ -101,6 +104,9 @@ public class QueryTypeDescriptorImpl implements GridQueryTypeDescriptor {
     /** Obsolete. */
     private volatile boolean obsolete;
 
+    /** */
+    private List<GridQueryProperty> validateProps;
+
     /**
      * Constructor.
      *
@@ -367,6 +373,13 @@ public class QueryTypeDescriptorImpl implements GridQueryTypeDescriptor {
         if (uppercaseProps.put(name.toUpperCase(), prop) != null && failOnDuplicate)
             throw new IgniteCheckedException("Property with upper cased name '" + name + "' already exists.");
 
+        if (prop.notNull()) {
+            if (validateProps == null)
+                validateProps = new ArrayList<>();
+
+            validateProps.add(prop);
+        }
+
         fields.put(name, prop.type());
     }
 
@@ -470,4 +483,21 @@ public class QueryTypeDescriptorImpl implements GridQueryTypeDescriptor {
     @Nullable @Override public String valueFieldAlias() {
         return valFieldName != null ? aliases.get(valFieldName) : null;
     }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("ForLoopReplaceableByForEach")
+    @Override public void validateKeyAndValue(Object key, Object val) throws IgniteCheckedException {
+        if (validateProps == null)
+            return;
+
+        final int size = validateProps.size();
+
+        for (int idx = 0; idx < size; ++idx) {
+            GridQueryProperty prop = validateProps.get(idx);
+
+            if (prop.value(key, val) == null)
+                throw new IgniteSQLException("Null value is not allowed for field '" + prop.name() + "'",
+                    IgniteQueryErrorCode.NULL_VALUE);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
index 26fc776..76efb71 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
@@ -222,6 +222,7 @@ public class QueryUtils {
         normalEntity.setKeyFields(entity.getKeyFields());
         normalEntity.setKeyFieldName(entity.getKeyFieldName());
         normalEntity.setValueFieldName(entity.getValueFieldName());
+        normalEntity.setNotNullFields(entity.getNotNullFields());
 
         // Normalize table name.
         String normalTblName = entity.getTableName();
@@ -495,6 +496,7 @@ public class QueryUtils {
     public static void processBinaryMeta(GridKernalContext ctx, QueryEntity qryEntity, QueryTypeDescriptorImpl d)
         throws IgniteCheckedException {
         Set<String> keyFields = qryEntity.getKeyFields();
+        Set<String> notNulls = qryEntity.getNotNullFields();
 
         // We have to distinguish between empty and null keyFields when the key is not of SQL type -
         // when a key is not of SQL type, absence of a field in nonnull keyFields tell us that this field
@@ -521,8 +523,11 @@ public class QueryUtils {
             else
                 isKeyField = (hasKeyFields ? keyFields.contains(entry.getKey()) : null);
 
+            boolean notNull = notNulls != null && notNulls.contains(entry.getKey());
+
             QueryBinaryProperty prop = buildBinaryProperty(ctx, entry.getKey(),
-                U.classForName(entry.getValue(), Object.class, true), d.aliases(), isKeyField);
+                U.classForName(entry.getValue(), Object.class, true),
+                d.aliases(), isKeyField, notNull);
 
             d.addProperty(prop, false);
         }
@@ -539,6 +544,8 @@ public class QueryUtils {
      */
     public static void processClassMeta(QueryEntity qryEntity, QueryTypeDescriptorImpl d, CacheObjectContext coCtx)
         throws IgniteCheckedException {
+        Set<String> notNulls = qryEntity.getNotNullFields();
+
         for (Map.Entry<String, String> entry : qryEntity.getFields().entrySet()) {
             GridQueryProperty prop = buildProperty(
                 d.keyClass(),
@@ -548,6 +555,7 @@ public class QueryUtils {
                 entry.getKey(),
                 U.classForName(entry.getValue(), Object.class),
                 d.aliases(),
+                notNulls != null && notNulls.contains(entry.getKey()),
                 coCtx);
 
             d.addProperty(prop, false);
@@ -661,10 +669,11 @@ public class QueryUtils {
      * @param aliases Aliases.
      * @param isKeyField Key ownership flag, as defined in {@link QueryEntity#keyFields}: {@code true} if field belongs
      *      to key, {@code false} if it belongs to value, {@code null} if QueryEntity#keyFields is null.
+     * @param notNull {@code true} if {@code null} value is not allowed.
      * @return Binary property.
      */
     public static QueryBinaryProperty buildBinaryProperty(GridKernalContext ctx, String pathStr, Class<?> resType,
-                                     Map<String, String> aliases, @Nullable Boolean isKeyField) throws IgniteCheckedException {
+        Map<String, String> aliases, @Nullable Boolean isKeyField, boolean notNull) throws IgniteCheckedException {
         String[] path = pathStr.split("\\.");
 
         QueryBinaryProperty res = null;
@@ -680,7 +689,7 @@ public class QueryUtils {
             String alias = aliases.get(fullName.toString());
 
             // The key flag that we've found out is valid for the whole path.
-            res = new QueryBinaryProperty(ctx, prop, res, resType, isKeyField, alias);
+            res = new QueryBinaryProperty(ctx, prop, res, resType, isKeyField, alias, notNull);
         }
 
         return res;
@@ -692,21 +701,25 @@ public class QueryUtils {
      * @param pathStr Path string.
      * @param resType Result type.
      * @param aliases Aliases.
+     * @param notNull {@code true} if {@code null} value is not allowed.
+     * @param coCtx Cache object context.
      * @return Class property.
      * @throws IgniteCheckedException If failed.
      */
     public static QueryClassProperty buildClassProperty(Class<?> keyCls, Class<?> valCls, String pathStr,
-        Class<?> resType, Map<String,String> aliases, CacheObjectContext coCtx) throws IgniteCheckedException {
+        Class<?> resType, Map<String,String> aliases, boolean notNull, CacheObjectContext coCtx)
+        throws IgniteCheckedException {
         QueryClassProperty res = buildClassProperty(
             true,
             keyCls,
             pathStr,
             resType,
             aliases,
+            notNull,
             coCtx);
 
         if (res == null) // We check key before value consistently with BinaryProperty.
-            res = buildClassProperty(false, valCls, pathStr, resType, aliases, coCtx);
+            res = buildClassProperty(false, valCls, pathStr, resType, aliases, notNull, coCtx);
 
         if (res == null)
             throw new IgniteCheckedException(propertyInitializationExceptionMessage(keyCls, valCls, pathStr, resType));
@@ -722,11 +735,14 @@ public class QueryUtils {
      * @param pathStr Path string.
      * @param resType Result type.
      * @param aliases Aliases.
+     * @param notNull {@code true} if {@code null} value is not allowed.
+     * @param coCtx Cache object context.
      * @return Class property.
      * @throws IgniteCheckedException If failed.
      */
-    public static GridQueryProperty buildProperty(Class<?> keyCls, Class<?> valCls, String keyFieldName, String valueFieldName, String pathStr,
-                                                  Class<?> resType, Map<String,String> aliases, CacheObjectContext coCtx) throws IgniteCheckedException {
+    public static GridQueryProperty buildProperty(Class<?> keyCls, Class<?> valCls, String keyFieldName,
+        String valueFieldName, String pathStr, Class<?> resType, Map<String,String> aliases, boolean notNull,
+        CacheObjectContext coCtx) throws IgniteCheckedException {
         if (pathStr.equals(keyFieldName))
             return new KeyOrValProperty(true, pathStr, keyCls);
 
@@ -738,6 +754,7 @@ public class QueryUtils {
                 pathStr,
                 resType,
                 aliases,
+                notNull,
                 coCtx);
     }
 
@@ -763,11 +780,13 @@ public class QueryUtils {
      * @param pathStr String representing path to the property. May contains dots '.' to identify nested fields.
      * @param resType Expected result type.
      * @param aliases Aliases.
+     * @param notNull {@code true} if {@code null} value is not allowed.
+     * @param coCtx Cache object context.
      * @return Property instance corresponding to the given path.
      */
     @SuppressWarnings("ConstantConditions")
     public static QueryClassProperty buildClassProperty(boolean key, Class<?> cls, String pathStr, Class<?> resType,
-        Map<String,String> aliases, CacheObjectContext coCtx) {
+        Map<String,String> aliases, boolean notNull, CacheObjectContext coCtx) {
         String[] path = pathStr.split("\\.");
 
         QueryClassProperty res = null;
@@ -787,7 +806,7 @@ public class QueryUtils {
             if (accessor == null)
                 return null;
 
-            QueryClassProperty tmp = new QueryClassProperty(accessor, key, alias, coCtx);
+            QueryClassProperty tmp = new QueryClassProperty(accessor, key, alias, notNull, coCtx);
 
             tmp.parent(res);
 
@@ -1221,5 +1240,10 @@ public class QueryUtils {
         @Override public GridQueryProperty parent() {
             return null;
         }
+
+        /** {@inheritDoc} */
+        @Override public boolean notNull() {
+            return true;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryBinaryProperty.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryBinaryProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryBinaryProperty.java
index d8b907e..5d90a43 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryBinaryProperty.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryBinaryProperty.java
@@ -65,6 +65,9 @@ public class QueryBinaryProperty implements GridQueryProperty {
     /** Whether user was warned about missing property. */
     private volatile boolean warned;
 
+    /** */
+    private final boolean notNull;
+
     /**
      * Constructor.
      *
@@ -74,9 +77,10 @@ public class QueryBinaryProperty implements GridQueryProperty {
      * @param type Result type.
      * @param key {@code true} if key property, {@code false} otherwise, {@code null}  if unknown.
      * @param alias Field alias.
+     * @param notNull {@code true} if null value is not allowed.
      */
     public QueryBinaryProperty(GridKernalContext ctx, String propName, QueryBinaryProperty parent,
-        Class<?> type, @Nullable Boolean key, String alias) {
+        Class<?> type, @Nullable Boolean key, String alias, boolean notNull) {
 
         this.ctx = ctx;
 
@@ -86,6 +90,7 @@ public class QueryBinaryProperty implements GridQueryProperty {
         this.alias = F.isEmpty(alias) ? propName : alias;
         this.parent = parent;
         this.type = type;
+        this.notNull = notNull;
 
         if (key != null)
             this.isKeyProp = key ? 1 : -1;
@@ -266,4 +271,9 @@ public class QueryBinaryProperty implements GridQueryProperty {
     @Override public GridQueryProperty parent() {
         return parent;
     }
+
+    /** {@inheritDoc} */
+    @Override public boolean notNull() {
+        return notNull;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryClassProperty.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryClassProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryClassProperty.java
index 80b9c87..076a769 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryClassProperty.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/property/QueryClassProperty.java
@@ -44,19 +44,28 @@ public class QueryClassProperty implements GridQueryProperty {
     /** */
     private final CacheObjectContext coCtx;
 
+    /** */
+    private final boolean notNull;
+
     /**
      * Constructor.
      *
      * @param accessor Way of accessing the property.
+     * @param key {@code true} if key property, {@code false} otherwise.
+     * @param name Property name.
+     * @param notNull {@code true} if null value is not allowed.
+     * @param coCtx Cache Object Context.
      */
     public QueryClassProperty(QueryPropertyAccessor accessor, boolean key, String name,
-        @Nullable CacheObjectContext coCtx) {
+        boolean notNull, @Nullable CacheObjectContext coCtx) {
         this.accessor = accessor;
 
         this.key = key;
 
         this.name = !F.isEmpty(name) ? name : accessor.getPropertyName();
 
+        this.notNull = notNull;
+
         this.coCtx = coCtx;
     }
 
@@ -127,4 +136,9 @@ public class QueryClassProperty implements GridQueryProperty {
     @Override public GridQueryProperty parent() {
         return parent;
     }
+
+    /** {@inheritDoc} */
+    @Override public boolean notNull() {
+        return notNull;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java
index 0ff9cfe..0634a52 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java
@@ -611,6 +611,8 @@ public class DmlStatementsProcessor {
                 newVal = ((BinaryObjectBuilder) newVal).build();
             }
 
+            desc.type().validateKeyAndValue(key, newVal);
+
             Object srcVal = row.get(1);
 
             if (bin && !(srcVal instanceof BinaryObject))
@@ -764,14 +766,15 @@ public class DmlStatementsProcessor {
 
         // If we have just one item to put, just do so
         if (plan.rowsNum == 1) {
-            IgniteBiTuple t = rowToKeyValue(cctx, cursor.iterator().next(),
-                plan);
+            IgniteBiTuple t = rowToKeyValue(cctx, cursor.iterator().next(), plan);
 
             cctx.cache().put(t.getKey(), t.getValue());
+
             return 1;
         }
         else {
             int resCnt = 0;
+
             Map<Object, Object> rows = new LinkedHashMap<>();
 
             for (Iterator<List<?>> it = cursor.iterator(); it.hasNext();) {
@@ -783,6 +786,7 @@ public class DmlStatementsProcessor {
 
                 if ((pageSize > 0 && rows.size() == pageSize) || !it.hasNext()) {
                     cctx.cache().putAll(rows);
+
                     resCnt += rows.size();
 
                     if (it.hasNext())
@@ -952,6 +956,8 @@ public class DmlStatementsProcessor {
                 val = ((BinaryObjectBuilder) val).build();
         }
 
+        desc.validateKeyAndValue(key, val);
+
         return new IgniteBiTuple<>(key, val);
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/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 3d3ed84..a07d48e 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
@@ -1644,7 +1644,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
         sql.a(',').a(VER_FIELD_NAME).a(" OTHER INVISIBLE");
 
         for (Map.Entry<String, Class<?>> e : tbl.type().fields().entrySet())
-            sql.a(',').a(H2Utils.withQuotes(e.getKey())).a(' ').a(dbTypeFromClass(e.getValue()));
+            sql.a(',').a(H2Utils.withQuotes(e.getKey())).a(' ').a(dbTypeFromClass(e.getValue()))
+            .a(tbl.type().property(e.getKey()).notNull()? " NOT NULL" : "");
 
         sql.a(')');
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/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 6f3c3ba..03f4e1f 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
@@ -20,9 +20,11 @@ package org.apache.ignite.internal.processors.query.h2.ddl;
 import java.sql.PreparedStatement;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.QueryIndex;
@@ -241,7 +243,8 @@ public class DdlStatementsProcessor {
                         }
 
                         cols.add(new QueryField(col.columnName(),
-                            DataType.getTypeClassName(col.column().getType())));
+                            DataType.getTypeClassName(col.column().getType()),
+                            col.column().isNullable()));
                     }
 
                     if (cols != null) {
@@ -335,12 +338,21 @@ public class DdlStatementsProcessor {
 
         res.setTableName(createTbl.tableName());
 
+        Set<String> notNullFields = null;
+
         for (Map.Entry<String, GridSqlColumn> e : createTbl.columns().entrySet()) {
             GridSqlColumn gridCol = e.getValue();
 
             Column col = gridCol.column();
 
             res.addQueryField(e.getKey(), DataType.getTypeClassName(col.getType()), null);
+
+            if (!col.isNullable()) {
+                if (notNullFields == null)
+                    notNullFields = new HashSet<>();
+
+                notNullFields.add(e.getKey());
+            }
         }
 
         String valTypeName = QueryUtils.createTableValueTypeName(createTbl.schemaName(), createTbl.tableName());
@@ -350,6 +362,7 @@ public class DdlStatementsProcessor {
         res.setKeyType(keyTypeName);
 
         res.setKeyFields(createTbl.primaryKeyColumns());
+        res.setNotNullFields(notNullFields);
 
         return res;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
index 694346c..45bb9c7 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
@@ -985,7 +985,11 @@ public class GridH2Table extends TableBase {
                 }
 
                 try {
-                    newCols[pos++] = new Column(col.name(), DataType.getTypeFromClass(Class.forName(col.typeName())));
+                    Column c = new Column(col.name(), DataType.getTypeFromClass(Class.forName(col.typeName())));
+
+                    c.setNullable(col.isNullable());
+
+                    newCols[pos++] = c;
                 }
                 catch (ClassNotFoundException e) {
                     throw new IgniteSQLException("H2 data type not found for class: " + col.typeName(), e);

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
index d19e66f..a2de62b 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
@@ -1029,10 +1029,6 @@ public class GridSqlQueryParser {
             throw new IgniteSQLException("AUTO_INCREMENT columns are not supported [colName=" + col.getName() + ']',
                 IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
 
-        if (!col.isNullable())
-            throw new IgniteSQLException("Non nullable columns are not supported [colName=" + col.getName() + ']',
-                IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
-
         if (COLUMN_IS_COMPUTED.get(col))
             throw new IgniteSQLException("Computed columns are not supported [colName=" + col.getName() + ']',
                 IgniteQueryErrorCode.UNSUPPORTED_OPERATION);

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
index 75b9a30..978c504 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
@@ -116,6 +116,14 @@ public abstract class DynamicColumnsAbstractTest extends GridCommonAbstractTest
                 assertEquals(col.name(), e.getKey());
 
                 assertEquals(col.typeName(), e.getValue());
+
+                if (!col.isNullable()) {
+                    assertNotNull(entity.getNotNullFields());
+
+                    assertTrue(entity.getNotNullFields().contains(col.name()));
+                }
+                else if (entity.getNotNullFields() != null)
+                    assertFalse(entity.getNotNullFields().contains(col.name()));
             }
         }
 
@@ -151,6 +159,8 @@ public abstract class DynamicColumnsAbstractTest extends GridCommonAbstractTest
                 assertEquals(col.name(), e.getKey());
 
                 assertEquals(col.typeName(), e.getValue().getName());
+
+                assertTrue(col.isNullable() || desc.property(col.name()).notNull());
             }
         }
 
@@ -183,6 +193,8 @@ public abstract class DynamicColumnsAbstractTest extends GridCommonAbstractTest
 
                 assertFalse(rowDesc.isKeyValueOrVersionColumn(i));
 
+                assertEquals(col.isNullable(), c.isNullable());
+
                 try {
                     assertEquals(DataType.getTypeFromClass(Class.forName(col.typeName())),
                         rowDesc.fieldType(i - GridH2AbstractKeyValueRow.DEFAULT_COLUMNS_COUNT));
@@ -213,7 +225,7 @@ public abstract class DynamicColumnsAbstractTest extends GridCommonAbstractTest
      * @return New column with given name and type.
      */
     protected static QueryField c(String name, String typeName) {
-        return new QueryField(name, typeName);
+        return new QueryField(name, typeName, true);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/43be051c/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java
index 651a3f7..6455cad 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java
@@ -266,6 +266,34 @@ public abstract class H2DynamicColumnsAbstractBasicSelfTest extends DynamicColum
     }
 
     /**
+     * Test addition of column with not null constraint.
+     */
+    public void testAddNotNullColumn() {
+        run("ALTER TABLE Person ADD COLUMN age int NOT NULL");
+
+        doSleep(500);
+
+        QueryField c = new QueryField("AGE", Integer.class.getName(), false);
+
+        for (Ignite node : Ignition.allGrids())
+            checkNodeState((IgniteEx)node, QueryUtils.DFLT_SCHEMA, "PERSON", c);
+    }
+
+    /**
+     * Test addition of column explicitly defined as nullable.
+     */
+    public void testAddNullColumn() {
+        run("ALTER TABLE Person ADD COLUMN age int NULL");
+
+        doSleep(500);
+
+        QueryField c = new QueryField("AGE", Integer.class.getName(), true);
+
+        for (Ignite node : Ignition.allGrids())
+            checkNodeState((IgniteEx)node, QueryUtils.DFLT_SCHEMA, "PERSON", c);
+    }
+
+    /**
      * @return Node index to run queries on.
      */
     protected abstract int nodeIndex();


[05/12] ignite git commit: IGNITE-6151: Review fixes

Posted by sb...@apache.org.
IGNITE-6151: Review fixes


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/8c238056
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/8c238056
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/8c238056

Branch: refs/heads/ignite-6149
Commit: 8c2380568093ed6566c983d4cb11e10c1d7a68c1
Parents: 0bc1d84
Author: Igor Sapego <is...@gridgain.com>
Authored: Tue Sep 12 16:10:51 2017 +0300
Committer: Igor Sapego <is...@gridgain.com>
Committed: Tue Sep 12 16:10:51 2017 +0300

----------------------------------------------------------------------
 modules/platforms/cpp/odbc-test/src/attributes_test.cpp | 4 ++--
 modules/platforms/cpp/odbc/src/connection.cpp           | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/8c238056/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/attributes_test.cpp b/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
index 3ac46cb..f8cb5ac 100644
--- a/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
@@ -180,7 +180,7 @@ BOOST_AUTO_TEST_CASE(ConnectionAttributeConnectionDeadGet)
 {
     Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
-    SQLINTEGER dead = SQL_CD_TRUE;
+    SQLUINTEGER dead = SQL_CD_TRUE;
     SQLRETURN ret;
 
     ret = SQLGetConnectAttr(dbc, SQL_ATTR_CONNECTION_DEAD, &dead, 0, 0);
@@ -194,7 +194,7 @@ BOOST_AUTO_TEST_CASE(ConnectionAttributeConnectionDeadSet)
 {
     Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
-    SQLINTEGER dead = SQL_CD_TRUE;
+    SQLUINTEGER dead = SQL_CD_TRUE;
     SQLRETURN ret;
 
     ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_DEAD, &dead, 0);

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c238056/modules/platforms/cpp/odbc/src/connection.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp
index 53626d1..472eb75 100644
--- a/modules/platforms/cpp/odbc/src/connection.cpp
+++ b/modules/platforms/cpp/odbc/src/connection.cpp
@@ -351,9 +351,9 @@ namespace ignite
             {
                 case SQL_ATTR_CONNECTION_DEAD:
                 {
-                    SQLINTEGER *val = reinterpret_cast<SQLINTEGER*>(buf);
+                    SQLUINTEGER *val = reinterpret_cast<SQLUINTEGER*>(buf);
 
-                    *val = static_cast<SQLINTEGER>(connected ? SQL_CD_FALSE : SQL_CD_TRUE);
+                    *val = connected ? SQL_CD_FALSE : SQL_CD_TRUE;
 
                     if (valueLen)
                         *valueLen = SQL_IS_INTEGER;
@@ -384,7 +384,7 @@ namespace ignite
             {
                 case SQL_ATTR_CONNECTION_DEAD:
                 {
-                    AddStatusRecord(SqlState::SHY092_OPTION_TYPE_OUT_OF_RANGE, "Attribute can not be retrieved.");
+                    AddStatusRecord(SqlState::SHY092_OPTION_TYPE_OUT_OF_RANGE, "Attribute is read only.");
 
                     return SqlResult::AI_ERROR;
                 }


[02/12] ignite git commit: IGNITE-5703: SQL: Added WRITE_SYNCHRONIZATION_MODE parameter to CREATE TABLE command. This closes #2591.

Posted by sb...@apache.org.
IGNITE-5703: SQL: Added WRITE_SYNCHRONIZATION_MODE parameter to CREATE TABLE command. This closes #2591.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/c61f134e
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/c61f134e
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/c61f134e

Branch: refs/heads/ignite-6149
Commit: c61f134e21d8b8e17057b40c53e757eff6e8490d
Parents: acd7861
Author: Alexander Paschenko <al...@gmail.com>
Authored: Tue Sep 12 11:40:47 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Tue Sep 12 11:40:47 2017 +0300

----------------------------------------------------------------------
 .../processors/query/GridQueryProcessor.java    |  7 +-
 .../query/h2/ddl/DdlStatementsProcessor.java    |  3 +-
 .../query/h2/sql/GridSqlCreateTable.java        | 18 ++++
 .../query/h2/sql/GridSqlQueryParser.java        | 31 ++++++-
 .../cache/index/H2DynamicTableSelfTest.java     | 95 ++++++++++++++++----
 .../IgnitePersistentStoreSchemaLoadTest.java    | 16 +---
 6 files changed, 137 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c61f134e/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
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 ea4c576..323bae6 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
@@ -1362,13 +1362,15 @@ public class GridQueryProcessor extends GridProcessorAdapter {
      * @param cacheGroup Cache group name.
      * @param affinityKey Affinity key column name.
      * @param atomicityMode Atomicity mode.
+     * @param writeSyncMode Write synchronization mode.
      * @param backups Backups.
      * @param ifNotExists Quietly ignore this command if table already exists.
      * @throws IgniteCheckedException If failed.
      */
     @SuppressWarnings("unchecked")
     public void dynamicTableCreate(String schemaName, QueryEntity entity, String templateName, String cacheGroup,
-        String affinityKey, @Nullable CacheAtomicityMode atomicityMode, int backups, boolean ifNotExists)
+        String affinityKey, @Nullable CacheAtomicityMode atomicityMode,
+        @Nullable CacheWriteSynchronizationMode writeSyncMode, int backups, boolean ifNotExists)
         throws IgniteCheckedException {
         assert !F.isEmpty(templateName);
         assert backups >= 0;
@@ -1398,6 +1400,9 @@ public class GridQueryProcessor extends GridProcessorAdapter {
         if (atomicityMode != null)
             ccfg.setAtomicityMode(atomicityMode);
 
+        if (writeSyncMode != null)
+            ccfg.setWriteSynchronizationMode(writeSyncMode);
+
         ccfg.setBackups(backups);
 
         ccfg.setSqlSchema(schemaName);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c61f134e/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 f322010..6f3c3ba 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
@@ -181,7 +181,8 @@ public class DdlStatementsProcessor {
                         throw err;
 
                     ctx.query().dynamicTableCreate(cmd.schemaName(), e, cmd.templateName(), cmd.cacheGroup(),
-                        cmd.affinityKey(), cmd.atomicityMode(), cmd.backups(), cmd.ifNotExists());
+                        cmd.affinityKey(), cmd.atomicityMode(), cmd.writeSynchronizationMode(), cmd.backups(),
+                        cmd.ifNotExists());
                 }
             }
             else if (stmt0 instanceof GridSqlDropTable) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c61f134e/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
index fa76123..d28ee7a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
@@ -21,6 +21,7 @@ import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 
 /**
  * CREATE TABLE statement.
@@ -43,6 +44,9 @@ public class GridSqlCreateTable extends GridSqlStatement {
     /** Atomicity mode for new cache. */
     private CacheAtomicityMode atomicityMode;
 
+    /** Write sync mode. */
+    private CacheWriteSynchronizationMode writeSyncMode;
+
     /** Backups number for new cache. */
     private int backups;
 
@@ -104,6 +108,20 @@ public class GridSqlCreateTable extends GridSqlStatement {
     }
 
     /**
+     * @return Write sync mode for new cache.
+     */
+    public CacheWriteSynchronizationMode writeSynchronizationMode() {
+        return writeSyncMode;
+    }
+
+    /**
+     * @param writeSyncMode Write sync mode for new cache.
+     */
+    public void writeSynchronizationMode(CacheWriteSynchronizationMode writeSyncMode) {
+        this.writeSyncMode = writeSyncMode;
+    }
+
+    /**
      * @return Backups number for new cache.
      */
     public int backups() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c61f134e/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
index 97e9d5d..d19e66f 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
@@ -30,6 +30,7 @@ import java.util.Map;
 import javax.cache.CacheException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.cache.QueryIndexType;
 import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
@@ -437,6 +438,9 @@ public class GridSqlQueryParser {
     private static final String PARAM_AFFINITY_KEY = "AFFINITYKEY";
 
     /** */
+    private static final String PARAM_WRITE_SYNC = "WRITE_SYNCHRONIZATION_MODE";
+
+    /** */
     private final IdentityHashMap<Object, Object> h2ObjToGridObj = new IdentityHashMap<>();
 
     /** */
@@ -1125,17 +1129,17 @@ public class GridSqlQueryParser {
             case PARAM_ATOMICITY:
                 ensureNotEmpty(name, val);
 
-                CacheAtomicityMode mode;
+                CacheAtomicityMode atomicityMode;
 
                 if (CacheAtomicityMode.TRANSACTIONAL.name().equalsIgnoreCase(val))
-                    mode = CacheAtomicityMode.TRANSACTIONAL;
+                    atomicityMode = CacheAtomicityMode.TRANSACTIONAL;
                 else if (CacheAtomicityMode.ATOMIC.name().equalsIgnoreCase(val))
-                    mode = CacheAtomicityMode.ATOMIC;
+                    atomicityMode = CacheAtomicityMode.ATOMIC;
                 else
                     throw new IgniteSQLException("Invalid value of \"" + PARAM_ATOMICITY + "\" parameter " +
                         "(should be either TRANSACTIONAL or ATOMIC): " + val, IgniteQueryErrorCode.PARSING);
 
-                res.atomicityMode(mode);
+                res.atomicityMode(atomicityMode);
 
                 break;
 
@@ -1187,6 +1191,25 @@ public class GridSqlQueryParser {
 
                 break;
 
+            case PARAM_WRITE_SYNC:
+                ensureNotEmpty(name, val);
+
+                CacheWriteSynchronizationMode writeSyncMode;
+
+                if (CacheWriteSynchronizationMode.FULL_ASYNC.name().equalsIgnoreCase(val))
+                    writeSyncMode = CacheWriteSynchronizationMode.FULL_ASYNC;
+                else if (CacheWriteSynchronizationMode.FULL_SYNC.name().equalsIgnoreCase(val))
+                    writeSyncMode = CacheWriteSynchronizationMode.FULL_SYNC;
+                else if (CacheWriteSynchronizationMode.PRIMARY_SYNC.name().equalsIgnoreCase(val))
+                    writeSyncMode = CacheWriteSynchronizationMode.PRIMARY_SYNC;
+                else
+                    throw new IgniteSQLException("Invalid value of \"" + PARAM_WRITE_SYNC + "\" parameter " +
+                        "(should be FULL_SYNC, FULL_ASYNC, or PRIMARY_SYNC): " + val, IgniteQueryErrorCode.PARSING);
+
+                res.writeSynchronizationMode(writeSyncMode);
+
+                break;
+
             default:
                 throw new IgniteSQLException("Unsupported parameter: " + name, IgniteQueryErrorCode.PARSING);
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/c61f134e/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 d737a0f..0be6c70 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
@@ -77,6 +77,8 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
             Ignition.start(cfg);
 
         client().addCacheConfiguration(cacheConfiguration());
+        client().addCacheConfiguration(cacheConfiguration().setName(CACHE_NAME + "_async")
+            .setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_ASYNC));
     }
 
     /** {@inheritDoc} */
@@ -107,7 +109,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * @throws Exception if failed.
      */
     public void testCreateTable() throws Exception {
-        doTestCreateTable(CACHE_NAME, null, null);
+        doTestCreateTable(CACHE_NAME, null, null, null);
     }
 
     /**
@@ -115,7 +117,15 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * @throws Exception if failed.
      */
     public void testCreateTableWithCacheGroup() throws Exception {
-        doTestCreateTable(CACHE_NAME, "MyGroup", null);
+        doTestCreateTable(CACHE_NAME, "MyGroup", null, null);
+    }
+
+    /**
+     * Test that {@code CREATE TABLE} actually creates new cache from template, H2 table and type descriptor on all nodes.
+     * @throws Exception if failed.
+     */
+    public void testCreateTableWithWriteSyncMode() throws Exception {
+        doTestCreateTable(CACHE_NAME + "_async", null, null, CacheWriteSynchronizationMode.FULL_ASYNC);
     }
 
     /**
@@ -124,7 +134,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * @throws Exception if failed.
      */
     public void testCreateTableReplicated() throws Exception {
-        doTestCreateTable("REPLICATED", null, CacheMode.REPLICATED);
+        doTestCreateTable("REPLICATED", null, CacheMode.REPLICATED, CacheWriteSynchronizationMode.FULL_SYNC);
     }
 
     /**
@@ -133,7 +143,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * @throws Exception if failed.
      */
     public void testCreateTablePartitioned() throws Exception {
-        doTestCreateTable("PARTITIONED", null, CacheMode.PARTITIONED);
+        doTestCreateTable("PARTITIONED", null, CacheMode.PARTITIONED, CacheWriteSynchronizationMode.FULL_SYNC);
     }
 
     /**
@@ -142,7 +152,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * @throws Exception if failed.
      */
     public void testCreateTableReplicatedCaseInsensitive() throws Exception {
-        doTestCreateTable("replicated", null, CacheMode.REPLICATED);
+        doTestCreateTable("replicated", null, CacheMode.REPLICATED, CacheWriteSynchronizationMode.FULL_SYNC);
     }
 
     /**
@@ -151,7 +161,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * @throws Exception if failed.
      */
     public void testCreateTablePartitionedCaseInsensitive() throws Exception {
-        doTestCreateTable("partitioned", null, CacheMode.PARTITIONED);
+        doTestCreateTable("partitioned", null, CacheMode.PARTITIONED, CacheWriteSynchronizationMode.FULL_SYNC);
     }
 
     /**
@@ -160,7 +170,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * @throws Exception if failed.
      */
     public void testCreateTableNoTemplate() throws Exception {
-        doTestCreateTable(null, null, CacheMode.PARTITIONED);
+        doTestCreateTable(null, null, CacheMode.PARTITIONED, CacheWriteSynchronizationMode.FULL_SYNC);
     }
 
     /**
@@ -173,6 +183,33 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     }
 
     /**
+     * Test that {@code CREATE TABLE} with given write sync mode actually creates new cache as needed.
+     * @throws Exception if failed.
+     */
+    public void testFullSyncWriteMode() throws Exception {
+        doTestCreateTable(null, null, null, CacheWriteSynchronizationMode.FULL_SYNC,
+            "write_synchronization_mode=full_sync");
+    }
+
+    /**
+     * Test that {@code CREATE TABLE} with given write sync mode actually creates new cache as needed.
+     * @throws Exception if failed.
+     */
+    public void testPrimarySyncWriteMode() throws Exception {
+        doTestCreateTable(null, null, null, CacheWriteSynchronizationMode.PRIMARY_SYNC,
+            "write_synchronization_mode=primary_sync");
+    }
+
+    /**
+     * Test that {@code CREATE TABLE} with given write sync mode actually creates new cache as needed.
+     * @throws Exception if failed.
+     */
+    public void testFullAsyncWriteMode() throws Exception {
+        doTestCreateTable(null, null, null, CacheWriteSynchronizationMode.FULL_ASYNC,
+            "write_synchronization_mode=full_async");
+    }
+
+    /**
      * Perform a check on given table name considering case sensitivity.
      * @param tblName Table name to check.
      * @param sensitive Whether table should be created w/case sensitive name or not.
@@ -277,13 +314,21 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * H2 table and type descriptor on all nodes, optionally with cache type check.
      * @param tplCacheName Template cache name.
      * @param cacheGrp Cache group name, or {@code null} if no group is set.
-     * @param mode Expected cache mode, or {@code null} if no check is needed.
+     * @param cacheMode Expected cache mode, or {@code null} if no check is needed.
+     * @param writeSyncMode Expected write sync mode, or {@code null} if no check is needed.
+     * @param additionalParams Supplemental parameters to append to {@code CREATE TABLE} SQL.
      */
-    private void doTestCreateTable(String tplCacheName, String cacheGrp, CacheMode mode) {
-        execute("CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
+    private void doTestCreateTable(String tplCacheName, String cacheGrp, CacheMode cacheMode,
+        CacheWriteSynchronizationMode writeSyncMode, String... additionalParams) {
+        String sql = "CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
             (F.isEmpty(tplCacheName) ? "" : "\"template=" + tplCacheName + "\",") + "\"backups=10,atomicity=atomic\"" +
-            (F.isEmpty(cacheGrp) ? "" : ",\"cacheGroup=" + cacheGrp + '"'));
+            (F.isEmpty(cacheGrp) ? "" : ",\"cacheGroup=" + cacheGrp + '"');
+
+        for (String p : additionalParams)
+            sql += ",\"" + p + "\"";
+
+        execute(sql);
 
         String cacheName = cacheName("Person");
 
@@ -296,7 +341,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
 
             assertNotNull(cacheDesc);
 
-            if (mode == CacheMode.REPLICATED)
+            if (cacheMode == CacheMode.REPLICATED)
                 assertEquals(Integer.MAX_VALUE, cacheDesc.cacheConfiguration().getBackups());
             else
                 assertEquals(10, cacheDesc.cacheConfiguration().getBackups());
@@ -307,8 +352,11 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
 
             assertEquals(cacheGrp, cacheDesc.groupDescriptor().groupName());
 
-            if (mode != null)
-                assertEquals(mode, cacheDesc.cacheConfiguration().getCacheMode());
+            if (cacheMode != null)
+                assertEquals(cacheMode, cacheDesc.cacheConfiguration().getCacheMode());
+
+            if (writeSyncMode != null)
+                assertEquals(writeSyncMode, cacheDesc.cacheConfiguration().getWriteSynchronizationMode());
 
             QueryTypeDescriptorImpl desc = typeExisting(node, cacheName, "Person");
 
@@ -374,6 +422,23 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     }
 
     /**
+     * Test that attempting to omit mandatory value of WRITE_SYNCHRONIZATION_MODE parameter yields an error.
+     */
+    public void testEmptyWriteSyncMode() {
+        assertCreateTableWithParamsThrows("write_synchronization_mode=",
+            "Parameter value cannot be empty: WRITE_SYNCHRONIZATION_MODE");
+    }
+
+    /**
+     * Test that attempting to provide invalid value of WRITE_SYNCHRONIZATION_MODE parameter yields an error.
+     */
+    public void testInvalidWriteSyncMode() {
+        assertCreateTableWithParamsThrows("write_synchronization_mode=invalid",
+            "Invalid value of \"WRITE_SYNCHRONIZATION_MODE\" parameter " +
+                "(should be FULL_SYNC, FULL_ASYNC, or PRIMARY_SYNC): invalid");
+    }
+
+    /**
      * Test that attempting to {@code CREATE TABLE} that already exists does not yield an error if the statement
      *     contains {@code IF NOT EXISTS} clause.
      * @throws Exception if failed.
@@ -536,7 +601,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
                 e.setValueType("City");
 
                 queryProcessor(client()).dynamicTableCreate("PUBLIC", e, CacheMode.PARTITIONED.name(), null,
-                    null, CacheAtomicityMode.ATOMIC, 10, false);
+                    null, CacheAtomicityMode.ATOMIC, null, 10, false);
 
                 return null;
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/c61f134e/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/IgnitePersistentStoreSchemaLoadTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/IgnitePersistentStoreSchemaLoadTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/IgnitePersistentStoreSchemaLoadTest.java
index 927de07..349f062 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/IgnitePersistentStoreSchemaLoadTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/IgnitePersistentStoreSchemaLoadTest.java
@@ -36,7 +36,6 @@ import org.apache.ignite.internal.IgniteInterruptedCheckedException;
 import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
 import org.apache.ignite.internal.processors.cache.persistence.DbCheckpointListener;
 import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
-import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
 import org.apache.ignite.internal.util.lang.GridAbsPredicate;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
@@ -151,7 +150,8 @@ public class IgnitePersistentStoreSchemaLoadTest extends GridCommonAbstractTest
 
         idx.setName(IDX_NAME);
 
-        ig0.context().query().dynamicTableCreate(SCHEMA_NAME, getEntity(), TMPL_NAME, null, null, null, 1, true);
+        ig0.context().query().dynamicTableCreate(SCHEMA_NAME, getEntity(), TMPL_NAME, null, null, null,
+            null, 1, true);
 
         assert indexCnt(ig0, CACHE_NAME) == 0;
 
@@ -183,7 +183,7 @@ public class IgnitePersistentStoreSchemaLoadTest extends GridCommonAbstractTest
             }
         });
 
-        ig0.context().query().dynamicTableCreate(SCHEMA_NAME, getEntity(), TMPL_NAME, null, null, null, 1, true);
+        ig0.context().query().dynamicTableCreate(SCHEMA_NAME, getEntity(), TMPL_NAME, null, null, null, null, 1, true);
 
         assert indexCnt(ig0, CACHE_NAME) == 0;
 
@@ -222,21 +222,13 @@ public class IgnitePersistentStoreSchemaLoadTest extends GridCommonAbstractTest
 
         int cnt = 0;
 
-        for (QueryEntity entity : desc.schema().entities()) {
+        for (QueryEntity entity : desc.schema().entities())
             cnt += entity.getIndexes().size();
-        }
 
         return cnt;
     }
 
     /**
-     * @return Indexing.
-     */
-    private IgniteH2Indexing getIndexing(IgniteEx ignite) {
-        return U.field(ignite.context().query(), "idx");
-    }
-
-    /**
      *
      */
     private void deleteWorkFiles() throws IgniteCheckedException {


[04/12] ignite git commit: IGNITE-6151: Impemented getting and setting of the SQL_ATTR_CONNECTION_DEAD

Posted by sb...@apache.org.
IGNITE-6151: Impemented getting and setting of the SQL_ATTR_CONNECTION_DEAD


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/0bc1d847
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/0bc1d847
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/0bc1d847

Branch: refs/heads/ignite-6149
Commit: 0bc1d8477c0f0783cc046cabed9a0bb7d3518b0f
Parents: f5bbc70
Author: Igor Sapego <is...@gridgain.com>
Authored: Tue Sep 12 14:44:07 2017 +0300
Committer: Igor Sapego <is...@gridgain.com>
Committed: Tue Sep 12 14:44:07 2017 +0300

----------------------------------------------------------------------
 modules/platforms/cpp/odbc-test/Makefile.am     |   1 +
 .../cpp/odbc-test/project/vs/odbc-test.vcxproj  |   1 +
 .../project/vs/odbc-test.vcxproj.filters        |   3 +
 .../cpp/odbc-test/src/attributes_test.cpp       | 208 +++++++++++++++++++
 .../platforms/cpp/odbc/include/ignite/odbc.h    |  22 +-
 .../cpp/odbc/include/ignite/odbc/connection.h   |  47 +++++
 modules/platforms/cpp/odbc/src/connection.cpp   | 100 ++++++++-
 modules/platforms/cpp/odbc/src/entry_points.cpp |  65 +++---
 modules/platforms/cpp/odbc/src/odbc.cpp         |  46 +++-
 9 files changed, 440 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/0bc1d847/modules/platforms/cpp/odbc-test/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/Makefile.am b/modules/platforms/cpp/odbc-test/Makefile.am
index 7756181..69b62f9 100644
--- a/modules/platforms/cpp/odbc-test/Makefile.am
+++ b/modules/platforms/cpp/odbc-test/Makefile.am
@@ -78,6 +78,7 @@ ignite_odbc_tests_SOURCES = \
     src/sql_date_time_functions_test.cpp \
     src/sql_outer_join_test.cpp \
     src/api_robustness_test.cpp \
+    src/attributes_test.cpp \
     ../odbc/src/cursor.cpp \
     ../odbc/src/config/connection_info.cpp \
     ../odbc/src/app/application_data_buffer.cpp \

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bc1d847/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
index d06064b..3977a24 100644
--- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
+++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
@@ -164,6 +164,7 @@
     <ClCompile Include="..\..\..\odbc\src\utility.cpp" />
     <ClCompile Include="..\..\src\api_robustness_test.cpp" />
     <ClCompile Include="..\..\src\application_data_buffer_test.cpp" />
+    <ClCompile Include="..\..\src\attributes_test.cpp" />
     <ClCompile Include="..\..\src\column_test.cpp" />
     <ClCompile Include="..\..\src\configuration_test.cpp" />
     <ClCompile Include="..\..\src\connection_info_test.cpp" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bc1d847/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
index 91c029e..2a0c7b4 100644
--- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
+++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
@@ -124,6 +124,9 @@
     <ClCompile Include="..\..\src\meta_queries_test.cpp">
       <Filter>Code</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\attributes_test.cpp">
+      <Filter>Code</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\include\test_type.h">

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bc1d847/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/attributes_test.cpp b/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
new file mode 100644
index 0000000..3ac46cb
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ */
+
+#ifdef _WIN32
+#   include <windows.h>
+#endif
+
+#include <sql.h>
+#include <sqlext.h>
+
+#include <vector>
+#include <string>
+
+#ifndef _MSC_VER
+#   define BOOST_TEST_DYN_LINK
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+#include "ignite/ignite.h"
+#include "ignite/ignition.h"
+#include "ignite/impl/binary/binary_utils.h"
+
+#include "test_type.h"
+#include "test_utils.h"
+
+using namespace ignite;
+using namespace ignite::cache;
+using namespace ignite::cache::query;
+using namespace ignite::common;
+using namespace ignite_test;
+
+using namespace boost::unit_test;
+
+using ignite::impl::binary::BinaryUtils;
+
+/**
+ * Test setup fixture.
+ */
+struct AttributesTestSuiteFixture
+{
+    void Prepare()
+    {
+        // Allocate an environment handle
+        SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
+
+        BOOST_REQUIRE(env != NULL);
+
+        // We want ODBC 3 support
+        SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*>(SQL_OV_ODBC3), 0);
+
+        // Allocate a connection handle
+        SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
+
+        BOOST_REQUIRE(dbc != NULL);
+    }
+
+    /**
+     * Establish connection to node.
+     *
+     * @param connectStr Connection string.
+     */
+    void Connect(const std::string& connectStr)
+    {
+        Prepare();
+
+        // Connect string
+        std::vector<SQLCHAR> connectStr0;
+
+        connectStr0.reserve(connectStr.size() + 1);
+        std::copy(connectStr.begin(), connectStr.end(), std::back_inserter(connectStr0));
+
+        SQLCHAR outstr[ODBC_BUFFER_SIZE];
+        SQLSMALLINT outstrlen;
+
+        // Connecting to ODBC server.
+        SQLRETURN ret = SQLDriverConnect(dbc, NULL, &connectStr0[0], static_cast<SQLSMALLINT>(connectStr0.size()),
+            outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE);
+
+        ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+
+        // Allocate a statement handle
+        SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
+
+        BOOST_REQUIRE(stmt != NULL);
+    }
+
+    void Disconnect()
+    {
+        // Releasing statement handle.
+        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+
+        // Disconneting from the server.
+        SQLDisconnect(dbc);
+
+        // Releasing allocated handles.
+        SQLFreeHandle(SQL_HANDLE_DBC, dbc);
+        SQLFreeHandle(SQL_HANDLE_ENV, env);
+    }
+
+    /**
+     * Constructor.
+     */
+    AttributesTestSuiteFixture() :
+        env(NULL),
+        dbc(NULL),
+        stmt(NULL)
+    {
+        const char* config = NULL;
+
+#ifdef IGNITE_TESTS_32
+          config = "queries-test-32.xml";
+#else
+          config = "queries-test.xml";
+#endif
+
+        grid = StartNode(config, "NodeMain");
+    }
+
+    void CheckSQLDiagnosticError(int16_t handleType, SQLHANDLE handle, const std::string& expectSqlState)
+    {
+        SQLCHAR state[ODBC_BUFFER_SIZE];
+        SQLINTEGER nativeError = 0;
+        SQLCHAR message[ODBC_BUFFER_SIZE];
+        SQLSMALLINT messageLen = 0;
+
+        SQLRETURN ret = SQLGetDiagRec(handleType, handle, 1, state, &nativeError, message, sizeof(message), &messageLen);
+
+        const std::string sqlState = reinterpret_cast<char*>(state);
+        BOOST_REQUIRE_EQUAL(ret, SQL_SUCCESS);
+        BOOST_REQUIRE_EQUAL(sqlState, expectSqlState);
+        BOOST_REQUIRE(messageLen > 0);
+    }
+
+    void CheckSQLConnectionDiagnosticError(const std::string& expectSqlState)
+    {
+        CheckSQLDiagnosticError(SQL_HANDLE_DBC, dbc, expectSqlState);
+    }
+
+    /**
+     * Destructor.
+     */
+    ~AttributesTestSuiteFixture()
+    {
+        Disconnect();
+
+        Ignition::StopAll(true);
+    }
+
+    /** Node started during the test. */
+    Ignite grid;
+
+    /** ODBC Environment. */
+    SQLHENV env;
+
+    /** ODBC Connect. */
+    SQLHDBC dbc;
+
+    /** ODBC Statement. */
+    SQLHSTMT stmt;
+};
+
+BOOST_FIXTURE_TEST_SUITE(AttributesTestSuite, AttributesTestSuiteFixture)
+
+BOOST_AUTO_TEST_CASE(ConnectionAttributeConnectionDeadGet)
+{
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
+
+    SQLINTEGER dead = SQL_CD_TRUE;
+    SQLRETURN ret;
+
+    ret = SQLGetConnectAttr(dbc, SQL_ATTR_CONNECTION_DEAD, &dead, 0, 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+
+    BOOST_REQUIRE_EQUAL(dead, SQL_CD_FALSE);
+}
+
+BOOST_AUTO_TEST_CASE(ConnectionAttributeConnectionDeadSet)
+{
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
+
+    SQLINTEGER dead = SQL_CD_TRUE;
+    SQLRETURN ret;
+
+    ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_DEAD, &dead, 0);
+
+    BOOST_REQUIRE_EQUAL(ret, SQL_ERROR);
+
+    // According to https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlsetconnectattr-function#diagnostics
+    CheckSQLConnectionDiagnosticError("HY092");
+}
+
+BOOST_AUTO_TEST_SUITE_END()

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bc1d847/modules/platforms/cpp/odbc/include/ignite/odbc.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc.h b/modules/platforms/cpp/odbc/include/ignite/odbc.h
index 639a02a..402d737 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc.h
@@ -251,6 +251,13 @@ namespace ignite
 
     SQLRETURN SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN strLengthOrIndicator);
 
+    SQLRETURN SQLDescribeParam(SQLHSTMT     stmt,
+                               SQLUSMALLINT paramNum,
+                               SQLSMALLINT* dataType,
+                               SQLULEN*     paramSize,
+                               SQLSMALLINT* decimalDigits,
+                               SQLSMALLINT* nullable);
+
     SQLRETURN SQLError(SQLHENV      env,
                        SQLHDBC      conn,
                        SQLHSTMT     stmt,
@@ -260,13 +267,16 @@ namespace ignite
                        SQLSMALLINT  msgBufLen,
                        SQLSMALLINT* msgResLen);
 
-    SQLRETURN SQLDescribeParam(SQLHSTMT     stmt,
-                               SQLUSMALLINT paramNum,
-                               SQLSMALLINT* dataType,
-                               SQLULEN*     paramSize,
-                               SQLSMALLINT* decimalDigits,
-                               SQLSMALLINT* nullable);
+    SQLRETURN SQL_API SQLGetConnectAttr(SQLHDBC    conn,
+                                        SQLINTEGER attr,
+                                        SQLPOINTER valueBuf,
+                                        SQLINTEGER valueBufLen,
+                                        SQLINTEGER* valueResLen);
 
+    SQLRETURN SQL_API SQLSetConnectAttr(SQLHDBC    conn,
+                                        SQLINTEGER attr,
+                                        SQLPOINTER value,
+                                        SQLINTEGER valueLen);
 } // namespace ignite
 
 #endif //_IGNITE_ODBC

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bc1d847/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
index da19e1b..fa80a01 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
@@ -162,6 +162,25 @@ namespace ignite
              */
             void TransactionRollback();
 
+            /**
+             * Get connection attribute.
+             *
+             * @param attr Attribute type.
+             * @param buf Buffer for value.
+             * @param bufLen Buffer length.
+             * @param valueLen Resulting value length.
+             */
+            void GetAttribute(int attr, void* buf, SQLINTEGER bufLen, SQLINTEGER *valueLen);
+
+            /**
+             * Set connection attribute.
+             *
+             * @param attr Attribute type.
+             * @param value Value pointer.
+             * @param valueLen Value length.
+             */
+            void SetAttribute(int attr, void* value, SQLINTEGER valueLen);
+
         private:
             IGNITE_NO_COPY_ASSIGNMENT(Connection);
 
@@ -192,6 +211,11 @@ namespace ignite
             SqlResult::Type InternalRelease();
 
             /**
+             * Close connection.
+             */
+            void Close();
+
+            /**
              * Get info of any type.
              * Internal call.
              *
@@ -229,6 +253,29 @@ namespace ignite
             SqlResult::Type InternalTransactionRollback();
 
             /**
+             * Get connection attribute.
+             * Internal call.
+             *
+             * @param attr Attribute type.
+             * @param buf Buffer for value.
+             * @param bufLen Buffer length.
+             * @param valueLen Resulting value length.
+             * @return Operation result.
+             */
+            SqlResult::Type InternalGetAttribute(int attr, void* buf, SQLINTEGER bufLen, SQLINTEGER* valueLen);
+
+            /**
+             * Set connection attribute.
+             * Internal call.
+             *
+             * @param attr Attribute type.
+             * @param value Value pointer.
+             * @param valueLen Value length.
+             * @return Operation result.
+             */
+            SqlResult::Type InternalSetAttribute(int attr, void* value, SQLINTEGER valueLen);
+
+            /**
              * Receive specified number of bytes.
              *
              * @param dst Buffer for data.

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bc1d847/modules/platforms/cpp/odbc/src/connection.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp
index 80d1695..53626d1 100644
--- a/modules/platforms/cpp/odbc/src/connection.cpp
+++ b/modules/platforms/cpp/odbc/src/connection.cpp
@@ -136,7 +136,12 @@ namespace ignite
                 return SqlResult::AI_ERROR;
             }
 
-            return MakeRequestHandshake();
+            SqlResult::Type res = MakeRequestHandshake();
+
+            if (res == SqlResult::AI_ERROR)
+                Close();
+
+            return res;
         }
 
         void Connection::Release()
@@ -153,11 +158,16 @@ namespace ignite
                 return SqlResult::AI_ERROR;
             }
 
+            Close();
+
+            return SqlResult::AI_SUCCESS;
+        }
+
+        void Connection::Close()
+        {
             socket.Close();
 
             connected = false;
-
-            return SqlResult::AI_SUCCESS;
         }
 
         Statement* Connection::CreateStatement()
@@ -217,7 +227,11 @@ namespace ignite
                 LOG_MSG("Sent: " << res);
 
                 if (res <= 0)
+                {
+                    Close();
+
                     return sent;
+                }
 
                 sent += res;
             }
@@ -240,7 +254,11 @@ namespace ignite
                 IGNITE_ERROR_1(IgniteError::IGNITE_ERR_GENERIC, "Can not receive message header");
 
             if (hdr.len < 0)
-                IGNITE_ERROR_1(IgniteError::IGNITE_ERR_GENERIC, "Message lenght is negative");
+            {
+                Close();
+
+                IGNITE_ERROR_1(IgniteError::IGNITE_ERR_GENERIC, "Message length is negative");
+            }
 
             if (hdr.len == 0)
                 return;
@@ -272,7 +290,11 @@ namespace ignite
                 LOG_MSG("Receive res: " << res << " remain: " << remain);
 
                 if (res <= 0)
+                {
+                    Close();
+
                     return received;
+                }
 
                 remain -= static_cast<size_t>(res);
             }
@@ -311,6 +333,74 @@ namespace ignite
             IGNITE_ODBC_API_CALL(InternalTransactionRollback());
         }
 
+        void Connection::GetAttribute(int attr, void* buf, SQLINTEGER bufLen, SQLINTEGER* valueLen)
+        {
+            IGNITE_ODBC_API_CALL(InternalGetAttribute(attr, buf, bufLen, valueLen));
+        }
+
+        SqlResult::Type Connection::InternalGetAttribute(int attr, void* buf, SQLINTEGER bufLen, SQLINTEGER* valueLen)
+        {
+            if (!buf)
+            {
+                AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Data buffer is NULL.");
+
+                return SqlResult::AI_ERROR;
+            }
+
+            switch (attr)
+            {
+                case SQL_ATTR_CONNECTION_DEAD:
+                {
+                    SQLINTEGER *val = reinterpret_cast<SQLINTEGER*>(buf);
+
+                    *val = static_cast<SQLINTEGER>(connected ? SQL_CD_FALSE : SQL_CD_TRUE);
+
+                    if (valueLen)
+                        *valueLen = SQL_IS_INTEGER;
+
+                    break;
+                }
+
+                default:
+                {
+                    AddStatusRecord(SqlState::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED,
+                        "Specified attribute is not supported.");
+
+                    return SqlResult::AI_ERROR;
+                }
+            }
+
+            return SqlResult::AI_SUCCESS;
+        }
+
+        void Connection::SetAttribute(int attr, void* value, SQLINTEGER valueLen)
+        {
+            IGNITE_ODBC_API_CALL(InternalSetAttribute(attr, value, valueLen));
+        }
+
+        SqlResult::Type Connection::InternalSetAttribute(int attr, void* value, SQLINTEGER valueLen)
+        {
+            switch (attr)
+            {
+                case SQL_ATTR_CONNECTION_DEAD:
+                {
+                    AddStatusRecord(SqlState::SHY092_OPTION_TYPE_OUT_OF_RANGE, "Attribute can not be retrieved.");
+
+                    return SqlResult::AI_ERROR;
+                }
+
+                default:
+                {
+                    AddStatusRecord(SqlState::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED,
+                        "Specified attribute is not supported.");
+
+                    return SqlResult::AI_ERROR;
+                }
+            }
+
+            return SqlResult::AI_SUCCESS;
+        }
+
         SqlResult::Type Connection::InternalTransactionRollback()
         {
             AddStatusRecord(SqlState::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED,
@@ -383,8 +473,6 @@ namespace ignite
 
                 AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, constructor.str());
 
-                InternalRelease();
-
                 return SqlResult::AI_ERROR;
             }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bc1d847/modules/platforms/cpp/odbc/src/entry_points.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/entry_points.cpp b/modules/platforms/cpp/odbc/src/entry_points.cpp
index e241a9f..d3c9e26 100644
--- a/modules/platforms/cpp/odbc/src/entry_points.cpp
+++ b/modules/platforms/cpp/odbc/src/entry_points.cpp
@@ -216,8 +216,7 @@ SQLRETURN SQL_API SQLNativeSql(SQLHDBC      conn,
                                SQLINTEGER   outQueryBufferLen,
                                SQLINTEGER*  outQueryLen)
 {
-    return ignite::SQLNativeSql(conn, inQuery, inQueryLen,
-        outQueryBuffer, outQueryBufferLen, outQueryLen);
+    return ignite::SQLNativeSql(conn, inQuery, inQueryLen, outQueryBuffer, outQueryBufferLen, outQueryLen);
 }
 
 
@@ -239,8 +238,7 @@ SQLRETURN SQL_API SQLColAttribute(SQLHSTMT       stmt,
                                   SQLPOINTER     numericAttr)
 #endif
 {
-    return ignite::SQLColAttribute(stmt, columnNum, fieldId,
-        strAttr, bufferLen, strAttrLen, (SQLLEN*)numericAttr);
+    return ignite::SQLColAttribute(stmt, columnNum, fieldId, strAttr, bufferLen, strAttrLen, (SQLLEN*)numericAttr);
 }
 
 SQLRETURN SQL_API SQLDescribeCol(SQLHSTMT       stmt,
@@ -327,8 +325,7 @@ SQLRETURN SQL_API SQLGetDiagField(SQLSMALLINT   handleType,
                                   SQLSMALLINT   bufferLen,
                                   SQLSMALLINT*  resLen)
 {
-    return ignite::SQLGetDiagField(handleType, handle,
-        recNum, diagId, buffer, bufferLen, resLen);
+    return ignite::SQLGetDiagField(handleType, handle, recNum, diagId, buffer, bufferLen, resLen);
 }
 
 SQLRETURN SQL_API SQLGetDiagRec(SQLSMALLINT     handleType,
@@ -340,8 +337,7 @@ SQLRETURN SQL_API SQLGetDiagRec(SQLSMALLINT     handleType,
                                 SQLSMALLINT     msgBufferLen,
                                 SQLSMALLINT*    msgLen)
 {
-    return ignite::SQLGetDiagRec(handleType, handle, recNum,
-        sqlState, nativeError, msgBuffer, msgBufferLen, msgLen);
+    return ignite::SQLGetDiagRec(handleType, handle, recNum, sqlState, nativeError, msgBuffer, msgBufferLen, msgLen);
 }
 
 SQLRETURN SQL_API SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT type)
@@ -349,9 +345,7 @@ SQLRETURN SQL_API SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT type)
     return ignite::SQLGetTypeInfo(stmt, type);
 }
 
-SQLRETURN SQL_API SQLEndTran(SQLSMALLINT    handleType,
-                             SQLHANDLE      handle,
-                             SQLSMALLINT    completionType)
+SQLRETURN SQL_API SQLEndTran(SQLSMALLINT handleType, SQLHANDLE handle, SQLSMALLINT completionType)
 {
     return ignite::SQLEndTran(handleType, handle, completionType);
 }
@@ -381,8 +375,7 @@ SQLRETURN SQL_API SQLGetEnvAttr(SQLHENV     env,
                                 SQLINTEGER  valueBufLen,
                                 SQLINTEGER* valueResLen)
 {
-    return ignite::SQLGetEnvAttr(env, attr,
-        valueBuf, valueBufLen, valueResLen);
+    return ignite::SQLGetEnvAttr(env, attr, valueBuf, valueBufLen, valueResLen);
 }
 
 SQLRETURN SQL_API SQLSpecialColumns(SQLHSTMT    stmt,
@@ -405,9 +398,7 @@ SQLRETURN SQL_API SQLParamData(SQLHSTMT stmt, SQLPOINTER* value)
     return ignite::SQLParamData(stmt, value);
 }
 
-SQLRETURN SQL_API SQLPutData(SQLHSTMT     stmt,
-                             SQLPOINTER   data,
-                             SQLLEN       strLengthOrIndicator)
+SQLRETURN SQL_API SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN strLengthOrIndicator)
 {
     return ignite::SQLPutData(stmt, data, strLengthOrIndicator);
 }
@@ -419,8 +410,7 @@ SQLRETURN SQL_API SQLDescribeParam(SQLHSTMT     stmt,
                                    SQLSMALLINT* decimalDigits,
                                    SQLSMALLINT* nullable)
 {
-    return ignite::SQLDescribeParam(stmt, paramNum, dataType,
-     paramSize, decimalDigits, nullable);
+    return ignite::SQLDescribeParam(stmt, paramNum, dataType, paramSize, decimalDigits, nullable);
 }
 
 SQLRETURN SQL_API SQLError(SQLHENV      env,
@@ -432,8 +422,24 @@ SQLRETURN SQL_API SQLError(SQLHENV      env,
                            SQLSMALLINT  msgBufLen,
                            SQLSMALLINT* msgResLen)
 {
-    return ignite::SQLError(env, conn, stmt, state,
-        error, msgBuf, msgBufLen, msgResLen);
+    return ignite::SQLError(env, conn, stmt, state, error, msgBuf, msgBufLen, msgResLen);
+}
+
+SQLRETURN SQL_API SQLGetConnectAttr(SQLHDBC     conn,
+                                    SQLINTEGER  attr,
+                                    SQLPOINTER  valueBuf,
+                                    SQLINTEGER  valueBufLen,
+                                    SQLINTEGER* valueResLen)
+{
+    return ignite::SQLGetConnectAttr(conn, attr, valueBuf, valueBufLen, valueResLen);
+}
+
+SQLRETURN SQL_API SQLSetConnectAttr(SQLHDBC     conn,
+                                    SQLINTEGER  attr,
+                                    SQLPOINTER  value,
+                                    SQLINTEGER  valueLen)
+{
+    return ignite::SQLSetConnectAttr(conn, attr, value, valueLen);
 }
 
 //
@@ -564,25 +570,6 @@ SQLRETURN SQL_API SQLSetScrollOptions(SQLHSTMT      stmt,
     return SQL_SUCCESS;
 }
 
-SQLRETURN SQL_API SQLGetConnectAttr(SQLHDBC     conn,
-                                    SQLINTEGER  attr,
-                                    SQLPOINTER  valueBuf,
-                                    SQLINTEGER  valueBufLen,
-                                    SQLINTEGER* valueResLen)
-{
-    LOG_MSG("SQLGetConnectAttr called");
-    return SQL_SUCCESS;
-}
-
-SQLRETURN SQL_API SQLSetConnectAttr(SQLHDBC     conn,
-                                    SQLINTEGER  attr,
-                                    SQLPOINTER  value,
-                                    SQLINTEGER  valueLen)
-{
-    LOG_MSG("SQLSetConnectAttr called");
-    return SQL_SUCCESS;
-}
-
 SQLRETURN SQL_API SQLBulkOperations(SQLHSTMT       stmt,
                                     SQLUSMALLINT   operation)
 {

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bc1d847/modules/platforms/cpp/odbc/src/odbc.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/odbc.cpp b/modules/platforms/cpp/odbc/src/odbc.cpp
index 1862465..baa276a 100644
--- a/modules/platforms/cpp/odbc/src/odbc.cpp
+++ b/modules/platforms/cpp/odbc/src/odbc.cpp
@@ -1140,9 +1140,9 @@ namespace ignite
                             SQLINTEGER* valueResLen)
     {
         using namespace odbc;
-        using namespace odbc::type_traits;
+        using namespace type_traits;
 
-        using odbc::app::ApplicationDataBuffer;
+        using app::ApplicationDataBuffer;
 
         LOG_MSG("SQLGetEnvAttr called");
 
@@ -1310,4 +1310,46 @@ namespace ignite
         return SQL_SUCCESS;
     }
 
+    SQLRETURN SQL_API SQLGetConnectAttr(SQLHDBC    conn,
+                                        SQLINTEGER attr,
+                                        SQLPOINTER valueBuf,
+                                        SQLINTEGER valueBufLen,
+                                        SQLINTEGER* valueResLen)
+    {
+        using namespace odbc;
+        using namespace type_traits;
+
+        using app::ApplicationDataBuffer;
+
+        LOG_MSG("SQLGetConnectAttr called");
+
+        Connection *connection = reinterpret_cast<Connection*>(conn);
+
+        if (!connection)
+            return SQL_INVALID_HANDLE;
+
+        connection->GetAttribute(attr, valueBuf, valueBufLen, valueResLen);
+
+        return connection->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQL_API SQLSetConnectAttr(SQLHDBC    conn,
+                                        SQLINTEGER attr,
+                                        SQLPOINTER value,
+                                        SQLINTEGER valueLen)
+    {
+        using odbc::Connection;
+
+        LOG_MSG("SQLSetConnectAttr called");
+
+        Connection *connection = reinterpret_cast<Connection*>(conn);
+
+        if (!connection)
+            return SQL_INVALID_HANDLE;
+
+        connection->SetAttribute(attr, value, valueLen);
+
+        return connection->GetDiagnosticRecords().GetReturnCode();
+    }
+
 } // namespace ignite;


[09/12] ignite git commit: IGNITE-6354 .NET: Fix DataStreamer with complex object graphs

Posted by sb...@apache.org.
IGNITE-6354 .NET: Fix DataStreamer with complex object graphs

This closes #2645


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/67d716f0
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/67d716f0
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/67d716f0

Branch: refs/heads/ignite-6149
Commit: 67d716f00806c8d69f8339b090e0ddd877b225e3
Parents: ed3d2a5
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Sep 12 17:41:38 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Sep 12 17:41:38 2017 +0300

----------------------------------------------------------------------
 .../Cache/CacheAbstractTest.cs                  | 67 ++++++++------------
 .../Dataload/DataStreamerTest.cs                | 49 ++++++++++++++
 .../Impl/Binary/BinaryWriterExtensions.cs       |  8 +--
 .../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs  | 52 ++++++++-------
 .../Impl/Compute/ComputeImpl.cs                 |  2 +-
 .../Impl/Datastream/DataStreamerBatch.cs        | 10 +--
 .../Impl/Services/ServiceProxySerializer.cs     | 10 ++-
 7 files changed, 120 insertions(+), 78 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/67d716f0/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs
index 27ac3f4..39a18fe 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs
@@ -128,14 +128,18 @@ namespace Apache.Ignite.Core.Tests.Cache
             return GetIgnite(idx).GetCache<TK, TV>(CacheName());
         }
 
-        protected ICache<int, int> Cache()
+        protected ICache<int, int> Cache(bool async = false)
         {
-            return Cache<int, int>(0);
+            var cache = Cache<int, int>(0);
+
+            return async ? cache.WrapAsync() : cache;
         }
 
-        private ICache<TK, TV> Cache<TK, TV>()
+        private ICache<TK, TV> Cache<TK, TV>(bool async = false)
         {
-            return Cache<TK, TV>(0);
+            var cache = Cache<TK, TV>(0);
+
+            return async ? cache : cache.WrapAsync();
         }
 
         private ICacheAffinity Affinity()
@@ -404,39 +408,26 @@ namespace Apache.Ignite.Core.Tests.Cache
         }
 
         [Test]
-        public void TestPut()
+        public void TestPut([Values(true, false)] bool async)
         {
-            var cache = Cache();
+            var cache = Cache(async);
 
             cache.Put(1, 1);
 
             Assert.AreEqual(1, cache.Get(1));
-        }
-
-        [Test]
-        public void TestPutxAsync()
-        {
-            var cache = Cache().WrapAsync();
-
-            cache.Put(1, 1);
-
-            Assert.AreEqual(1, cache.Get(1));
-        }
-
-        [Test]
-        public void TestPutIfAbsent()
-        {
-            var cache = Cache();
 
-            Assert.IsFalse(cache.ContainsKey(1));
+            // Objects.
+            var cache2 = Cache<Container, Container>(async);
 
-            Assert.AreEqual(true, cache.PutIfAbsent(1, 1));
+            var obj1 = new Container {Id = 1};
+            var obj2 = new Container {Id = 2};
 
-            Assert.AreEqual(1, cache.Get(1));
+            obj1.Inner = obj2;
+            obj2.Inner = obj1;
 
-            Assert.AreEqual(false, cache.PutIfAbsent(1, 2));
+            cache2[obj1] = obj2;
 
-            Assert.AreEqual(1, cache.Get(1));
+            Assert.AreEqual(2, cache2[obj1].Id);
         }
 
         [Test]
@@ -458,7 +449,7 @@ namespace Apache.Ignite.Core.Tests.Cache
         [Test]
         public void TestGetAndPutIfAbsentAsync()
         {
-            var cache = Cache().WrapAsync();
+            var cache = Cache(true);
 
             Assert.IsFalse(cache.ContainsKey(1));
 
@@ -476,9 +467,9 @@ namespace Apache.Ignite.Core.Tests.Cache
         }
 
         [Test]
-        public void TestPutIfAbsentAsync()
+        public void TestPutIfAbsent([Values(true, false)] bool async)
         {
-            var cache = Cache().WrapAsync();
+            var cache = Cache(async);
 
             Assert.Throws<KeyNotFoundException>(() => cache.Get(1));
             Assert.IsFalse(cache.ContainsKey(1));
@@ -599,12 +590,7 @@ namespace Apache.Ignite.Core.Tests.Cache
         [Test]
         public void TestPutAll([Values(true, false)] bool async)
         {
-            var cache = Cache();
-
-            if (async)
-            {
-                cache = cache.WrapAsync();
-            }
+            var cache = Cache(async);
 
             // Primitives.
             cache.PutAll(new Dictionary<int, int> { { 1, 1 }, { 2, 2 }, { 3, 3 } });
@@ -614,12 +600,7 @@ namespace Apache.Ignite.Core.Tests.Cache
             Assert.AreEqual(3, cache.Get(3));
 
             // Objects.
-            var cache2 = Cache<int, Container>();
-
-            if (async)
-            {
-                cache2 = cache2.WrapAsync();
-            }
+            var cache2 = Cache<int, Container>(async);
 
             var obj1 = new Container();
             var obj2 = new Container();
@@ -2565,6 +2546,8 @@ namespace Apache.Ignite.Core.Tests.Cache
 
         private class Container
         {
+            public int Id;
+
             public Container Inner;
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/67d716f0/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Dataload/DataStreamerTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Dataload/DataStreamerTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Dataload/DataStreamerTest.cs
index 85ee976..fe5955f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Dataload/DataStreamerTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Dataload/DataStreamerTest.cs
@@ -168,6 +168,46 @@ namespace Apache.Ignite.Core.Tests.Dataload
         }
 
         /// <summary>
+        /// Tests object graphs with loops.
+        /// </summary>
+        [Test]
+        public void TestObjectGraphs()
+        {
+            var obj1 = new Container();
+            var obj2 = new Container();
+            var obj3 = new Container();
+            var obj4 = new Container();
+
+            obj1.Inner = obj2;
+            obj2.Inner = obj1;
+            obj3.Inner = obj1;
+            obj4.Inner = new Container();
+
+            using (var ldr = _grid.GetDataStreamer<int, Container>(CacheName))
+            {
+                ldr.AllowOverwrite = true;
+
+                ldr.AddData(1, obj1);
+                ldr.AddData(2, obj2);
+                ldr.AddData(3, obj3);
+                ldr.AddData(4, obj4);
+            }
+
+            var cache = _grid.GetCache<int, Container>(CacheName);
+
+            var res = cache[1];
+            Assert.AreEqual(res, res.Inner.Inner);
+
+            Assert.IsNotNull(cache[2].Inner);
+            Assert.IsNotNull(cache[2].Inner.Inner);
+            Assert.IsNotNull(cache[3].Inner);
+            Assert.IsNotNull(cache[3].Inner.Inner);
+            
+            Assert.IsNotNull(cache[4].Inner);
+            Assert.IsNull(cache[4].Inner.Inner);
+        }
+
+        /// <summary>
         /// Test "tryFlush".
         /// </summary>
         [Test]
@@ -572,5 +612,14 @@ namespace Apache.Ignite.Core.Tests.Dataload
         {
             public int Val { get; set; }
         }
+
+        /// <summary>
+        /// Container class.
+        /// </summary>
+        private class Container
+        {
+            public Container Inner;
+        }
+
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/67d716f0/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriterExtensions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriterExtensions.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriterExtensions.cs
index 02b5dec..f75fcf8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriterExtensions.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriterExtensions.cs
@@ -92,12 +92,12 @@ namespace Apache.Ignite.Core.Impl.Binary
             if (selector == null)
             {
                 foreach (var val in vals)
-                    writer.Write(val);
+                    writer.WriteObjectDetached(val);
             }
             else
             {
                 foreach (var val in vals)
-                    writer.Write(selector(val));
+                    writer.WriteObjectDetached(selector(val));
             }
         }
 
@@ -142,7 +142,7 @@ namespace Apache.Ignite.Core.Impl.Binary
             {
                 foreach (var val in vals)
                 {
-                    writer.Write(val);
+                    writer.WriteObjectDetached(val);
 
                     size++;
                 }
@@ -151,7 +151,7 @@ namespace Apache.Ignite.Core.Impl.Binary
             {
                 foreach (var val in vals)
                 {
-                    writer.Write(selector(val));
+                    writer.WriteObjectDetached(selector(val));
 
                     size++;
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/67d716f0/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
index 64eee8d..05644cd 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
@@ -250,17 +250,21 @@ namespace Apache.Ignite.Core.Impl.Cache
                 var p0 = new CacheEntryFilterHolder(p, (k, v) => p.Invoke(new CacheEntry<TK, TV>((TK) k, (TV) v)),
                     Marshaller, IsKeepBinary);
 
-                writer.WriteObject(p0);
+                writer.WriteObjectDetached(p0);
             }
             else
-                writer.WriteObject<CacheEntryFilterHolder>(null);
+            {
+                writer.WriteObjectDetached<CacheEntryFilterHolder>(null);
+            }
 
             if (args != null && args.Length > 0)
             {
                 writer.WriteInt(args.Length);
 
                 foreach (var o in args)
-                    writer.WriteObject(o);
+                {
+                    writer.WriteObjectDetached(o);
+                }
             }
             else
             {
@@ -337,7 +341,7 @@ namespace Apache.Ignite.Core.Impl.Cache
             var res = DoOutInOpX((int)CacheOp.Peek,
                 w =>
                 {
-                    w.Write(key);
+                    w.WriteObjectDetached(key);
                     w.WriteInt(EncodePeekModes(modes));
                 },
                 (s, r) => r == True ? new CacheResult<TV>(Unmarshal<TV>(s)) : new CacheResult<TV>(),
@@ -473,8 +477,8 @@ namespace Apache.Ignite.Core.Impl.Cache
 
             return DoOutOpAsync(CacheOp.GetAndPutAsync, w =>
             {
-                w.WriteObject(key);
-                w.WriteObject(val);
+                w.WriteObjectDetached(key);
+                w.WriteObjectDetached(val);
             }, r => GetCacheResult(r));
         }
 
@@ -499,8 +503,8 @@ namespace Apache.Ignite.Core.Impl.Cache
 
             return DoOutOpAsync(CacheOp.GetAndReplaceAsync, w =>
             {
-                w.WriteObject(key);
-                w.WriteObject(val);
+                w.WriteObjectDetached(key);
+                w.WriteObjectDetached(val);
             }, r => GetCacheResult(r));
         }
 
@@ -567,8 +571,8 @@ namespace Apache.Ignite.Core.Impl.Cache
 
             return DoOutOpAsync(CacheOp.GetAndPutIfAbsentAsync, w =>
             {
-                w.WriteObject(key);
-                w.WriteObject(val);
+                w.WriteObjectDetached(key);
+                w.WriteObjectDetached(val);
             }, r => GetCacheResult(r));
         }
 
@@ -617,9 +621,9 @@ namespace Apache.Ignite.Core.Impl.Cache
 
             return DoOutOpAsync<bool>(CacheOp.Replace3Async, w =>
             {
-                w.WriteObject(key);
-                w.WriteObject(oldVal);
-                w.WriteObject(newVal);
+                w.WriteObjectDetached(key);
+                w.WriteObjectDetached(oldVal);
+                w.WriteObjectDetached(newVal);
             });
         }
 
@@ -838,8 +842,8 @@ namespace Apache.Ignite.Core.Impl.Cache
             return DoOutInOpX((int) CacheOp.Invoke,
                 writer =>
                 {
-                    writer.Write(key);
-                    writer.Write(holder);
+                    writer.WriteObjectDetached(key);
+                    writer.WriteObjectDetached(holder);
                 },
                 (input, res) => res == True ? Unmarshal<TRes>(input) : default(TRes),
                 _readException);
@@ -858,8 +862,8 @@ namespace Apache.Ignite.Core.Impl.Cache
 
             return DoOutOpAsync(CacheOp.InvokeAsync, writer =>
                 {
-                    writer.Write(key);
-                    writer.Write(holder);
+                    writer.WriteObjectDetached(key);
+                    writer.WriteObjectDetached(holder);
                 },
                 r =>
                 {
@@ -1319,8 +1323,8 @@ namespace Apache.Ignite.Core.Impl.Cache
         {
             return DoOutInOpX((int) op, w =>
             {
-                w.Write(x);
-                w.Write(y);
+                w.WriteObjectDetached(x);
+                w.WriteObjectDetached(y);
             }, _readException);
         }
 
@@ -1331,9 +1335,9 @@ namespace Apache.Ignite.Core.Impl.Cache
         {
             return DoOutInOpX((int) op, w =>
             {
-                w.Write(x);
-                w.Write(y);
-                w.Write(z);
+                w.WriteObjectDetached(x);
+                w.WriteObjectDetached(y);
+                w.WriteObjectDetached(z);
             }, _readException);
         }
 
@@ -1364,8 +1368,8 @@ namespace Apache.Ignite.Core.Impl.Cache
             return DoOutInOpX((int)cacheOp,
                 w =>
                 {
-                    w.Write(x);
-                    w.Write(y);
+                    w.WriteObjectDetached(x);
+                    w.WriteObjectDetached(y);
                 },
                 (stream, res) => res == True ? new CacheResult<TV>(Unmarshal<TV>(stream)) : new CacheResult<TV>(),
                 _readException);

http://git-wip-us.apache.org/repos/asf/ignite/blob/67d716f0/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs
index 06f9ad4..3c684ae 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs
@@ -590,7 +590,7 @@ namespace Apache.Ignite.Core.Impl.Compute
 
             try
             {
-                writer.WriteObject(jobHolder);
+                writer.WriteObjectDetached(jobHolder);
             }
             catch (Exception)
             {

http://git-wip-us.apache.org/repos/asf/ignite/blob/67d716f0/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Datastream/DataStreamerBatch.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Datastream/DataStreamerBatch.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Datastream/DataStreamerBatch.cs
index 66ee695..38a8ea8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Datastream/DataStreamerBatch.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Datastream/DataStreamerBatch.cs
@@ -221,8 +221,8 @@ namespace Apache.Ignite.Core.Impl.Datastream
                 {
                     foreach (KeyValuePair<TK, TV> item in entries)
                     {
-                        writer.Write(item.Key);
-                        writer.Write(item.Value);
+                        writer.WriteObjectDetached(item.Key);
+                        writer.WriteObjectDetached(item.Value);
                     }
 
                     continue;
@@ -232,8 +232,8 @@ namespace Apache.Ignite.Core.Impl.Datastream
                 DataStreamerEntry<TK, TV> entry = val as DataStreamerEntry<TK, TV>;
 
                 if (entry != null) {
-                    writer.Write(entry.Key);
-                    writer.Write(entry.Value);
+                    writer.WriteObjectDetached(entry.Key);
+                    writer.WriteObjectDetached(entry.Value);
 
                     continue;
                 }
@@ -243,7 +243,7 @@ namespace Apache.Ignite.Core.Impl.Datastream
 
                 if (rmvEntry != null)
                 {
-                    writer.Write(rmvEntry.Key);
+                    writer.WriteObjectDetached(rmvEntry.Key);
                     writer.Write<object>(null);
                 }
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/67d716f0/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs
index b4273b1..fc6009a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs
@@ -56,7 +56,9 @@ namespace Apache.Ignite.Core.Impl.Services
                 {
                     // Write as is
                     foreach (var arg in arguments)
-                        writer.WriteObject(arg);
+                    {
+                        writer.WriteObjectDetached(arg);
+                    }
                 }
                 else
                 {
@@ -200,9 +202,13 @@ namespace Apache.Ignite.Core.Impl.Services
             var hnd = GetPlatformArgWriter(param, arg);
 
             if (hnd != null)
+            {
                 hnd(writer, arg);
+            }
             else
-                writer.WriteObject(arg);
+            {
+                writer.WriteObjectDetached(arg);
+            }
         }
 
         /// <summary>


[03/12] ignite git commit: IGNITE-6253 .NET: Use DocFX for API documentation

Posted by sb...@apache.org.
IGNITE-6253 .NET: Use DocFX for API documentation


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/f5bbc709
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/f5bbc709
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/f5bbc709

Branch: refs/heads/ignite-6149
Commit: f5bbc709fb79eb00e4044adc7aaf03abf9508fa6
Parents: c61f134
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Sep 12 11:29:15 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Sep 12 12:40:07 2017 +0300

----------------------------------------------------------------------
 assembly/release-fabric-base.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/f5bbc709/assembly/release-fabric-base.xml
----------------------------------------------------------------------
diff --git a/assembly/release-fabric-base.xml b/assembly/release-fabric-base.xml
index 7484dfa..a16d996 100644
--- a/assembly/release-fabric-base.xml
+++ b/assembly/release-fabric-base.xml
@@ -88,7 +88,7 @@
 
         <!-- Move .Net docs. -->
         <fileSet>
-            <directory>modules/clients/target/dotnetdoc/html</directory>
+            <directory>modules/clients/target/dotnetdoc</directory>
             <outputDirectory>/platforms/dotnet/docs</outputDirectory>
         </fileSet>
 


[08/12] ignite git commit: Added more memory to DynamicColumnsAbstractTest.

Posted by sb...@apache.org.
Added more memory to DynamicColumnsAbstractTest.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/ed3d2a5e
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/ed3d2a5e
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/ed3d2a5e

Branch: refs/heads/ignite-6149
Commit: ed3d2a5edbe9b4b20dd02eeedc7636abdc0548c5
Parents: 43be051
Author: devozerov <vo...@gridgain.com>
Authored: Tue Sep 12 17:33:23 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Tue Sep 12 17:33:23 2017 +0300

----------------------------------------------------------------------
 .../processors/cache/index/DynamicColumnsAbstractTest.java       | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ed3d2a5e/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
index 978c504..00f345e 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
@@ -264,8 +264,8 @@ public abstract class DynamicColumnsAbstractTest extends GridCommonAbstractTest
             .setMemoryPolicies(
                 new MemoryPolicyConfiguration()
                     .setName("default")
-                    .setMaxSize(32 * 1024 * 1024L)
-                    .setInitialSize(32 * 1024 * 1024L)
+                    .setMaxSize(128 * 1024 * 1024L)
+                    .setInitialSize(128 * 1024 * 1024L)
             );
 
         cfg.setMemoryConfiguration(memCfg);