You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by al...@apache.org on 2021/05/27 07:31:30 UTC

[ignite] 01/01: Merge branch 'master' into sql-calcite

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

alexpl pushed a commit to branch sql-calcite
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 348276b51af77bb530a86b1008942355fdd368c0
Merge: c814ed2 b1529fb
Author: Aleksey Plekhanov <pl...@gmail.com>
AuthorDate: Thu May 27 10:23:00 2021 +0300

    Merge branch 'master' into sql-calcite
    
    # Conflicts:
    #	modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
    #	modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
    #	modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
    #	modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryEntityEx.java
    #	modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java

 .travis.yml                                        |   16 +-
 DEVNOTES.txt                                       |   17 +
 NOTICE                                             |    2 +-
 README.md                                          |    8 +-
 README.txt                                         |    3 -
 RELEASE_NOTES.txt                                  |  287 +++
 assembly/NOTICE_HADOOP                             |    2 +-
 assembly/NOTICE_IGNITE                             |    2 +-
 assembly/dependencies-apache-ignite-slim.xml       |    1 +
 assembly/libs/README.txt                           |    1 +
 assembly/release-apache-ignite-base.xml            |   76 -
 checkstyle/checkstyle-suppressions.xml             |    2 +
 checkstyle/checkstyle.xml                          |   21 +
 doap_Ignite.rdf                                    |    4 +-
 docs/Gemfile                                       |    3 +
 docs/_config.yml                                   |    7 +-
 docs/_data/toc.yaml                                |   16 +-
 docs/_docs/clustering/discovery-in-the-cloud.adoc  |   44 +-
 .../cpp/src/broadcast_jobs_to_remote_nodes.cpp     |   44 +
 .../cpp/src/predefined_cluster_groups.cpp          |   27 +
 docs/_docs/code-snippets/dotnet/ThinClient.cs      |   19 +
 docs/_docs/code-snippets/dotnet/dotnet.csproj      |    2 +-
 docs/_docs/code-snippets/java/pom.xml              |    5 +
 .../ignite/snippets/DiscoveryInTheCloud.java       |   24 +
 .../org/apache/ignite/snippets/JavaThinClient.java |   38 +-
 .../main/java/org/apache/ignite/snippets/TDE.java  |    7 +
 .../org/apache/ignite/snippets/WarmUpStrategy.java |   83 +
 .../java/org/apache/ignite/snippets/k8s/K8s.java   |   21 +
 docs/_docs/code-snippets/k8s/service.yaml          |    8 +-
 .../k8s/stateful/node-configuration.xml            |   12 +-
 .../k8s/stateless/node-configuration.xml           |    8 +-
 docs/_docs/code-snippets/xml/tde.xml               |   15 +-
 docs/_docs/code-snippets/xml/warm-up-strategy.xml  |   71 +
 .../distributed-computing/cluster-groups.adoc      |   12 +-
 docs/_docs/events/events.adoc                      |   30 +
 .../ignite-for-spark/overview.adoc                 |    2 +-
 .../performance-statistics.adoc                    |   82 +
 .../spring/spring-data.adoc                        |   79 +-
 .../spring/spring-tx.adoc                          |  466 ++++
 docs/_docs/includes/cpp-prerequisites.adoc         |    2 +-
 docs/_docs/includes/dotnet-prerequisites.adoc      |    2 +-
 docs/_docs/includes/java9.adoc                     |    6 +-
 docs/_docs/includes/partition-awareness.adoc       |    8 -
 docs/_docs/includes/prereqs.adoc                   |    2 +-
 docs/_docs/index.adoc                              |   19 +-
 docs/_docs/installation/index.adoc                 |   21 -
 .../kubernetes/generic-configuration.adoc          |   14 +-
 .../key-value-api/basic-cache-operations.adoc      |   27 +-
 docs/_docs/memory-configuration/data-regions.adoc  |  122 +
 docs/_docs/monitoring-metrics/metrics.adoc         |   36 +
 .../monitoring-metrics/new-metrics-system.adoc     |    2 -
 docs/_docs/monitoring-metrics/new-metrics.adoc     |   48 +-
 .../monitoring-metrics/performance-statistics.adoc |   97 +
 docs/_docs/monitoring-metrics/system-views.adoc    |  153 ++
 docs/_docs/monitoring-metrics/tracing.adoc         |   65 +
 docs/_docs/net-specific/net-async.adoc             |  121 +
 .../_docs/net-specific/net-deployment-options.adoc |   51 +-
 docs/_docs/net-specific/net-troubleshooting.adoc   |   19 +
 .../native-persistence-defragmentation.adoc        |   65 +
 docs/_docs/persistence/native-persistence.adoc     |    3 +
 docs/_docs/persistence/snapshot-directory.adoc     |   39 +
 docs/_docs/persistence/snapshots.adoc              |  208 --
 docs/_docs/quick-start/cpp.adoc                    |    2 +-
 docs/_docs/quick-start/dotnet.adoc                 |    4 +-
 docs/_docs/quick-start/java.adoc                   |    4 +-
 docs/_docs/quick-start/nodejs.adoc                 |    8 +-
 docs/_docs/quick-start/php.adoc                    |   19 +-
 docs/_docs/quick-start/python.adoc                 |    4 +-
 docs/_docs/quick-start/restapi.adoc                |    2 +-
 .../security/cache-encryption-key-rotation.adoc    |  145 ++
 docs/_docs/security/master-key-rotation.adoc       |    2 +-
 docs/_docs/security/tde.adoc                       |    1 -
 docs/_docs/setup.adoc                              |   62 +
 docs/_docs/snapshots/snapshots.adoc                |  208 ++
 docs/_docs/starting-nodes.adoc                     |   23 -
 docs/_docs/thin-clients/cpp-thin-client.adoc       |   57 +
 docs/_docs/thin-clients/dotnet-thin-client.adoc    |   15 +-
 docs/_docs/thin-clients/java-thin-client.adoc      |   32 +-
 docs/_docs/thin-clients/nodejs-thin-client.adoc    |    4 +-
 docs/_docs/thin-clients/php-thin-client.adoc       |   14 +-
 docs/_docs/thin-clients/python-thin-client.adoc    |    8 +-
 docs/_docs/tools/control-script.adoc               |  296 ++-
 docs/assets/css/docs.scss                          |    4 +-
 docs/assets/css/styles.scss                        |    4 +-
 examples/pom.xml                                   |    8 +-
 .../client/ClientKubernetesPutGetExample.java      |   70 +
 .../examples/encryption/EncryptedCacheExample.java |   29 +-
 .../ml/clustering/KMeansClusterizationExample.java |    3 +-
 .../dataset/AlgorithmSpecificDatasetExample.java   |   22 +-
 .../CatboostClassificationModelParserExample.java  |    3 +-
 .../KMeansClusterizationExportImportExample.java   |    3 +-
 .../modelparser/DecisionTreeFromSparkExample.java  |    9 +-
 .../DecisionTreeRegressionFromSparkExample.java    |    9 +-
 .../spark/modelparser/GBTFromSparkExample.java     |    9 +-
 .../modelparser/GBTRegressionFromSparkExample.java |    9 +-
 .../spark/modelparser/KMeansFromSparkExample.java  |    5 +-
 .../LinearRegressionFromSparkExample.java          |    8 +-
 .../spark/modelparser/LogRegFromSparkExample.java  |    9 +-
 .../modelparser/RandomForestFromSparkExample.java  |    9 +-
 .../RandomForestRegressionFromSparkExample.java    |    9 +-
 .../spark/modelparser/SVMFromSparkExample.java     |    5 +-
 .../multiclass/OneVsRestClassificationExample.java |    7 +-
 .../encoding/TargetEncoderExample.java             |    4 +-
 .../linear/BostonHousePricesPredictionExample.java |    3 +-
 ...gressionLSQRTrainerWithMinMaxScalerExample.java |    4 +-
 ...eeClassificationTrainerSQLInferenceExample.java |    4 +-
 .../RandomForestClassificationExample.java         |    4 +-
 .../hyperparametertuning/Step_13_RandomSearch.java |    6 +-
 .../Step_14_Parallel_Brute_Force_Search.java       |    6 +-
 .../Step_15_Parallel_Random_Search.java            |    6 +-
 .../Step_16_Genetic_Programming_Search.java        |    6 +-
 ...tep_17_Parallel_Genetic_Programming_Search.java |    6 +-
 .../ignite/examples/ml/util/MLSandboxDatasets.java |    9 +-
 .../spark/JavaIgniteDataFrameJoinExample.java      |    4 +-
 .../ignite/examples/spark/SharedRDDExample.java    |    2 +-
 idea/ignite_codeStyle.xml                          |    1 +
 modules/aop/pom.xml                                |   10 +-
 .../aop/aspectj/GridifySetToSetAspectJAspect.java  |    3 +-
 .../aspectj/GridifySetToValueAspectJAspect.java    |    3 +-
 .../gridify/aop/spring/GridifySpringEnhancer.java  |    3 +-
 .../org/apache/ignite/p2p/P2PGridifySelfTest.java  |    2 +
 .../ignite/testsuites/IgniteAopSelfTestSuite.java  |    5 +
 .../direct/singlesplit/SingleSplitsLoadTest.java   |    3 +
 .../gridify/GridifySingleSplitLoadTest.java        |    3 +
 modules/apache-license-gen/pom.xml                 |    2 +-
 modules/aws/pom.xml                                |   11 +-
 modules/azure/README.txt                           |   32 +
 modules/azure/pom.xml                              |  342 +++
 .../azure/TcpDiscoveryAzureBlobStoreIpFinder.java  |  382 +++
 .../spi/discovery/tcp/ipfinder/package-info.java   |   23 +
 ...TcpDiscoveryAzureBlobStoreIpFinderSelfTest.java |   91 +
 .../discovery/tcp/ipfinder/azure/package-info.java |   21 +
 .../ignite/testsuites/IgniteAzureTestSuite.java    |   61 +
 modules/benchmarks/pom.xml                         |    2 +-
 .../jmh/cache/JmhCacheAsyncListenBenchmark.java    |  162 ++
 .../GridDhtPartitionsStateValidatorBenchmark.java  |    5 +-
 .../jmh/misc/JmhSegmentedLruListBenchmark.java     |  122 +
 .../benchmarks/jmh/tree/BPlusTreeBenchmark.java    |    4 +-
 modules/calcite/pom.xml                            |    2 +-
 .../query/calcite/exec/AbstractIndexScan.java      |    6 +-
 .../query/calcite/exec/ExchangeServiceImpl.java    |    3 +-
 .../query/calcite/exec/ExecutionServiceImpl.java   |   13 +-
 .../processors/query/calcite/exec/IndexScan.java   |   14 +-
 .../query/calcite/exec/RuntimeTreeIndex.java       |    9 +-
 .../query/calcite/exec/ddl/DdlCommandHandler.java  |    5 +-
 .../calcite/exec/exp/agg/AccumulatorsFactory.java  |    4 +-
 .../query/calcite/exec/rel/MergeJoinNode.java      |    3 +-
 .../query/calcite/exec/rel/ModifyNode.java         |    4 +-
 .../query/calcite/exec/rel/NestedLoopJoinNode.java |    4 +-
 .../calcite/metadata/AffinityServiceImpl.java      |    4 +-
 .../query/calcite/metadata/ColocationGroup.java    |    9 +-
 .../calcite/metadata/IgniteMdSelectivity.java      |    3 +-
 .../query/calcite/metadata/MappingServiceImpl.java |    3 +-
 .../calcite/prepare/CalciteQueryFieldMetadata.java |   13 +-
 .../query/calcite/prepare/FieldsMetadata.java      |    3 +-
 .../processors/query/calcite/prepare/Splitter.java |    3 +-
 .../prepare/ddl/DdlSqlToCommandConverter.java      |    3 +-
 .../query/calcite/rel/AbstractIgniteJoin.java      |    3 +-
 .../rel/IgniteCorrelatedNestedLoopJoin.java        |    9 +-
 .../query/calcite/rel/IgniteNestedLoopJoin.java    |    9 +-
 .../query/calcite/rel/IgniteTableModify.java       |    3 +-
 .../calcite/rel/agg/IgniteMapHashAggregate.java    |    3 +-
 .../calcite/rel/agg/IgniteSingleHashAggregate.java |    6 +-
 .../calcite/rel/agg/IgniteSingleSortAggregate.java |    3 +-
 .../query/calcite/schema/SchemaHolderImpl.java     |    2 +-
 .../query/calcite/schema/TableDescriptorImpl.java  |   11 +-
 .../query/calcite/trait/DistributionFunction.java  |    3 +-
 .../processors/query/calcite/trait/TraitUtils.java |    5 +-
 .../processors/query/calcite/util/Commons.java     |    2 +-
 .../processors/query/calcite/util/RexUtils.java    |    3 +-
 .../CalciteBasicSecondaryIndexIntegrationTest.java |    6 +-
 .../query/calcite/CalciteQueryProcessorTest.java   |    8 +-
 .../processors/query/calcite/DateTimeTest.java     |   12 +-
 .../query/calcite/exec/rel/ExecutionTest.java      |   12 +-
 .../rel/HashAggregateSingleGroupExecutionTest.java |   36 +-
 .../calcite/exec/rel/TableSpoolExecutionTest.java  |    3 +-
 .../integration/AggregatesIntegrationTest.java     |    8 +-
 .../CalciteErrorHandlilngIntegrationTest.java      |    8 +-
 .../integration/MetadataIntegrationTest.java       |    2 +-
 .../query/calcite/jdbc/JdbcQueryTest.java          |    3 +-
 .../query/calcite/planner/AbstractPlannerTest.java |    3 +-
 .../query/calcite/planner/PlannerTest.java         |   56 +-
 .../query/calcite/planner/UnionPlannerTest.java    |    2 +
 .../ignite/testsuites/ExecutionTestSuite.java      |    4 +-
 .../ignite/testsuites/IntegrationTestSuite.java    |    2 +
 .../apache/ignite/testsuites/ScriptTestSuite.java  |    2 +
 modules/cassandra/pom.xml                          |    2 +-
 modules/cassandra/serializers/pom.xml              |   13 +-
 .../org/apache/ignite/tests/SerializerSuite.java   |   29 +
 modules/cassandra/store/pom.xml                    |   12 +-
 .../cassandra/CassandraCacheStoreFactory.java      |    5 +-
 .../persistence/KeyValuePersistenceSettings.java   |   15 +-
 .../ignite/tests/IgnitePersistentStoreTest.java    |   12 +-
 .../apache/ignite/tests/utils/CassandraHelper.java |    3 +-
 .../tests/persistence/blob/ignite-config.xml       |    6 +-
 .../tests/persistence/pojo/ignite-config.xml       |   21 +-
 .../tests/persistence/primitive/ignite-config.xml  |    6 +-
 modules/clients/pom.xml                            |   11 +-
 .../src/test/config/jdbc-security-config.xml       |   68 +
 ...eCreationDestructionWileTopologyChangeTest.java |   70 +
 .../ClientSizeCacheCreationDestructionTest.java    | 1243 ++++++++++
 .../common/RunningQueryInfoCheckInitiatorTest.java |  420 ++++
 .../client/ClientReconnectionSelfTest.java         |   23 +-
 .../internal/client/TaskSingleJobSplitAdapter.java |    3 +-
 .../client/suite/IgniteClientTestSuite.java        |    9 +-
 .../jdbc2/JdbcAbstractDmlStatementSelfTest.java    |   10 +-
 .../internal/jdbc2/JdbcBulkLoadSelfTest.java       |    2 +-
 .../internal/jdbc2/JdbcComplexQuerySelfTest.java   |    2 +-
 .../ignite/internal/jdbc2/JdbcCursorLeaksTest.java |  202 ++
 .../jdbc2/JdbcDistributedJoinsQueryTest.java       |    5 +-
 .../internal/jdbc2/JdbcMetadataSelfTest.java       |   16 +-
 .../jdbc2/JdbcNoCacheStreamingSelfTest.java        |    2 +-
 .../jdbc2/JdbcPreparedStatementSelfTest.java       |    2 +-
 .../internal/jdbc2/JdbcResultSetSelfTest.java      |    2 +-
 .../internal/jdbc2/JdbcStatementSelfTest.java      |    2 +-
 .../internal/jdbc2/JdbcStreamingSelfTest.java      |    4 +-
 .../jdbc2/JdbcStreamingToPublicCacheTest.java      |    2 +-
 ...ttyRestProcessorAuthenticationAbstractTest.java |   10 +-
 ...thenticatorUserManagementAuthorizationTest.java |  112 +
 .../ignite/jdbc/AbstractJdbcPojoQuerySelfTest.java |    2 +-
 .../apache/ignite/jdbc/JdbcAuthorizationTest.java  |   23 +-
 .../ignite/jdbc/JdbcComplexQuerySelfTest.java      |    2 +-
 .../ignite/jdbc/JdbcErrorsAbstractSelfTest.java    |    2 +-
 .../apache/ignite/jdbc/JdbcMetadataSelfTest.java   |    2 +-
 .../ignite/jdbc/JdbcPreparedStatementSelfTest.java |    2 +-
 .../apache/ignite/jdbc/JdbcStatementSelfTest.java  |    2 +-
 .../jdbc/suite/IgniteJdbcDriverTestSuite.java      |    4 +
 .../thin/JdbcThinAbstractDmlStatementSelfTest.java |    4 +-
 .../JdbcThinAuthenticateConnectionSelfTest.java    |   14 +-
 .../ignite/jdbc/thin/JdbcThinBatchSelfTest.java    |    3 +-
 .../ignite/jdbc/thin/JdbcThinBulkLoadSelfTest.java |    4 +-
 .../jdbc/thin/JdbcThinComplexQuerySelfTest.java    |    2 +-
 .../jdbc/thin/JdbcThinConnectionSelfTest.java      |    3 +-
 .../ignite/jdbc/thin/JdbcThinMetadataSelfTest.java |   80 +-
 .../thin/JdbcThinPartitionAwarenessSelfTest.java   |    4 +-
 .../thin/JdbcThinPreparedStatementSelfTest.java    |    2 +-
 .../jdbc/thin/JdbcThinResultSetSelfTest.java       |    2 +-
 .../jdbc/thin/JdbcThinStatementCancelSelfTest.java |    2 +-
 .../jdbc/thin/JdbcThinStatementSelfTest.java       |    2 +-
 .../thin/JdbcThinStatementTimeoutSelfTest.java     |    2 +-
 .../thin/JdbcThinStreamingAbstractSelfTest.java    |    4 +-
 .../client/ClientMarshallerBenchmarkTest.java      |    3 +
 .../loadtests/client/ClientTcpSslLoadTest.java     |    3 +
 .../qa/query/WarningOnBigQueryResultsBaseTest.java |    7 +-
 .../src/test/resources/jetty/rest-jetty.xml        |    2 +-
 modules/cloud/pom.xml                              |   15 +-
 modules/codegen/pom.xml                            |    2 +-
 .../SystemViewRowAttributeWalkerGenerator.java     |   18 +
 modules/compatibility/pom.xml                      |    2 +-
 .../clients/AbstractClientCompatibilityTest.java   |   25 +-
 .../clients/JavaThinCompatibilityTest.java         |   26 +
 .../persistence/FoldersReuseCompatibilityTest.java |    5 +-
 .../IgnitePKIndexesMigrationToUnwrapPkTest.java    |    2 +
 .../IndexAbstractCompatibilityTest.java            |   92 +
 .../persistence/IndexTypesCompatibilityTest.java   |  334 +++
 .../InlineJavaObjectCompatibilityTest.java         |  320 +++
 .../IgniteCompatibilityBasicTestSuite.java         |    4 +
 modules/compress/pom.xml                           |   11 +-
 .../AbstractPageCompressionIntegrationTest.java    |    2 +-
 .../compress/CompressionConfigurationTest.java     |    4 +-
 .../compress/CompressionProcessorTest.java         |    6 +-
 .../DiskPageCompressionIntegrationTest.java        |   10 +-
 .../WalPageCompressionIntegrationTest.java         |    4 +-
 modules/control-utility/pom.xml                    |   15 +-
 .../internal/commandline/CommandHandler.java       |    3 +-
 .../ignite/internal/commandline/CommandList.java   |    6 +-
 .../cache/CacheIndexesForceRebuild.java            |   11 +-
 .../commandline/cache/CacheValidateIndexes.java    |   13 +-
 .../commandline/cache/CheckIndexInlineSizes.java   |    4 +-
 .../internal/commandline/cache/IdleVerify.java     |   44 +-
 .../PerformanceStatisticsCommand.java              |  107 +
 .../PerformanceStatisticsSubCommand.java           |   80 +
 .../internal/commandline/query/KillCommand.java    |    2 +-
 .../commandline/snapshot/SnapshotCommand.java      |   51 +-
 .../commandline/snapshot/SnapshotSubcommand.java   |   25 +-
 .../commandline/CommandHandlerParsingTest.java     |   95 +-
 .../testsuites/IgniteControlUtilityTestSuite.java  |    6 +-
 .../util/GridCommandHandlerAbstractTest.java       |    7 +-
 ...idCommandHandlerCheckIndexesInlineSizeTest.java |    6 +-
 .../util/GridCommandHandlerClusterByClassTest.java |   39 +-
 .../GridCommandHandlerIndexForceRebuildTest.java   |  326 ++-
 .../GridCommandHandlerIndexRebuildStatusTest.java  |   27 +-
 .../util/GridCommandHandlerIndexingTest.java       |    2 +-
 .../GridCommandHandlerInterruptCommandTest.java    |  326 +++
 .../util/GridCommandHandlerPropertiesTest.java     |   39 +
 .../apache/ignite/util/GridCommandHandlerTest.java |   64 +-
 .../util/PerformanceStatisticsCommandTest.java     |  143 ++
 modules/core/pom.xml                               |   15 +-
 modules/core/src/main/java/META-INF/NOTICE         |    2 +-
 .../java/org/apache/ignite/DataRegionMetrics.java  |   12 +-
 .../apache/ignite/DataRegionMetricsAdapter.java    |   12 +-
 .../java/org/apache/ignite/DataStorageMetrics.java |   26 +-
 .../apache/ignite/DataStorageMetricsAdapter.java   |   12 +-
 .../src/main/java/org/apache/ignite/Ignite.java    |   46 +-
 .../main/java/org/apache/ignite/IgniteCache.java   |   11 +
 .../main/java/org/apache/ignite/IgniteCluster.java |   12 +
 .../main/java/org/apache/ignite/IgniteCompute.java |    4 +
 .../java/org/apache/ignite/IgniteSemaphore.java    |   13 +
 .../src/main/java/org/apache/ignite/IgniteSet.java |    3 +-
 .../java/org/apache/ignite/IgniteSnapshot.java     |   14 +
 .../org/apache/ignite/IgniteSystemProperties.java  |   54 +-
 .../java/org/apache/ignite/IgniteTransactions.java |    2 +
 .../main/java/org/apache/ignite/MemoryMetrics.java |    3 +-
 .../java/org/apache/ignite/PersistenceMetrics.java |    3 +-
 .../ignite/binary/BinaryBasicNameMapper.java       |   24 +
 .../org/apache/ignite/binary/BinaryIdMapper.java   |    2 +-
 .../org/apache/ignite/binary/BinaryObject.java     |    6 +
 .../apache/ignite/binary/BinaryObjectBuilder.java  |    2 +-
 .../java/org/apache/ignite/cache/QueryEntity.java  |    2 +-
 .../ClusterNodeAttributeColocatedBackupFilter.java |  125 +
 .../rendezvous/RendezvousAffinityFunction.java     |   35 +-
 .../sorted/SortedEvictionPolicyFactory.java        |    2 +-
 .../apache/ignite/cache/query/SqlFieldsQuery.java  |   53 +
 .../cache/store/jdbc/CacheJdbcPojoStore.java       |    7 +-
 .../cache/store/jdbc/dialect/BasicJdbcDialect.java |    8 +-
 .../cache/store/jdbc/dialect/DB2Dialect.java       |    7 +-
 .../cache/store/jdbc/dialect/OracleDialect.java    |    7 +-
 .../cache/store/jdbc/dialect/SQLServerDialect.java |    7 +-
 .../java/org/apache/ignite/client/ClientCache.java |  150 +-
 .../ignite/client/ClientCacheConfiguration.java    |   44 +
 .../ignite/client/ClientDisconnectListener.java    |   35 +
 .../ignite/configuration/CacheConfiguration.java   |    4 +-
 .../configuration/DataRegionConfiguration.java     |   36 +-
 .../ignite/configuration/IgniteConfiguration.java  |   37 +
 .../configuration/IgniteReflectionFactory.java     |    4 +-
 .../ignite/configuration/PageReplacementMode.java  |   87 +
 .../events/CacheConsistencyViolationEvent.java     |   11 +-
 .../ignite/events/CacheQueryExecutedEvent.java     |    7 +-
 .../apache/ignite/events/CacheQueryReadEvent.java  |    7 +-
 .../org/apache/ignite/events/CheckpointEvent.java  |    7 +-
 .../org/apache/ignite/events/DeploymentEvent.java  |    7 +-
 .../org/apache/ignite/events/DiscoveryEvent.java   |    7 +-
 .../main/java/org/apache/ignite/events/Event.java  |    4 +-
 .../java/org/apache/ignite/events/EventType.java   |   23 +-
 .../ignite/events/SqlQueryExecutionEvent.java      |    7 +-
 .../java/org/apache/ignite/events/TaskEvent.java   |    7 +-
 .../ignite/internal/GridEventConsumeHandler.java   |    7 +-
 .../ignite/internal/GridJobExecuteRequest.java     |    6 +-
 .../apache/ignite/internal/GridKernalContext.java  |   26 +-
 .../ignite/internal/GridKernalContextImpl.java     |   36 +-
 .../ignite/internal/GridMessageListenHandler.java  |    5 +
 .../org/apache/ignite/internal/IgniteFeatures.java |    5 +-
 .../org/apache/ignite/internal/IgniteKernal.java   |   43 +-
 .../ignite/internal/IgniteNodeAttributes.java      |    3 -
 .../ignite/internal/IgniteSchedulerImpl.java       |    4 +-
 .../org/apache/ignite/internal/IgnitionEx.java     |   39 +-
 .../internal/TransactionMetricsMxBeanImpl.java     |   13 +-
 .../internal/binary/BinaryEnumObjectImpl.java      |   14 +
 .../ignite/internal/binary/BinaryObjectImpl.java   |    5 +
 .../internal/binary/BinaryObjectOffheapImpl.java   |    5 +
 .../ignite/internal/binary/BinaryRawReaderEx.java  |    7 +
 .../ignite/internal/binary/BinaryReaderExImpl.java |    7 +-
 .../apache/ignite/internal/binary/BinaryUtils.java |   32 +-
 .../binary/builder/BinaryBuilderReader.java        |   89 +-
 .../binary/streams/BinaryAbstractOutputStream.java |    6 +-
 .../binary/streams/BinaryHeapOutputStream.java     |    3 +-
 .../binary/streams/BinaryMemoryAllocator.java      |    3 +-
 .../binary/streams/BinaryOffheapOutputStream.java  |    3 +-
 .../internal/cache/query/index/AbstractIndex.java  |   42 +
 .../ignite/internal/cache/query/index/Index.java   |   69 +
 .../cache/query/index/IndexDefinition.java         |   28 +
 .../internal/cache/query/index/IndexFactory.java   |   34 +
 .../internal/cache/query/index/IndexName.java      |   88 +
 .../internal/cache/query/index/IndexProcessor.java |  588 +++++
 .../internal/cache/query/index/NullsOrder.java     |   29 +
 .../ignite/internal/cache/query/index/Order.java   |   45 +
 .../internal/cache/query/index/SingleCursor.java   |   58 +
 .../internal/cache/query/index/SortOrder.java      |   29 +
 .../DurableBackgroundCleanupIndexTreeTask.java     |  351 +++
 .../query/index/sorted/IndexKeyDefinition.java     |   68 +
 .../query/index/sorted/IndexKeyTypeSettings.java   |   81 +
 .../cache/query/index/sorted/IndexKeyTypes.java    |  133 ++
 .../cache/query/index/sorted/IndexRow.java         |   86 +
 .../cache/query/index/sorted/IndexRowCache.java    |  162 ++
 .../query/index/sorted/IndexRowCacheRegistry.java  |  132 ++
 .../query/index/sorted/IndexRowComparator.java     |   46 +
 .../query/index/sorted/IndexRowCompartorImpl.java  |   71 +
 .../cache/query/index/sorted/IndexRowImpl.java     |  176 ++
 .../query/index/sorted/IndexSearchRowImpl.java     |   78 +
 .../cache/query/index/sorted/IndexValueCursor.java |   72 +
 .../query/index/sorted/InlineIndexRowHandler.java  |   69 +
 .../index/sorted/InlineIndexRowHandlerFactory.java |   34 +
 .../cache/query/index/sorted/MetaPageInfo.java     |   96 +
 .../query/index/sorted/SortedIndexDefinition.java  |   62 +
 .../query/index/sorted/SortedSegmentedIndex.java   |  102 +
 .../index/sorted/ThreadLocalRowHandlerHolder.java  |   62 +
 .../sorted/defragmentation/DefragIndexFactory.java |  324 +++
 .../defragmentation/IndexingDefragmentation.java   |  269 +++
 .../index/sorted/inline/IndexQueryContext.java     |   50 +
 .../query/index/sorted/inline/InlineIndex.java     |   41 +
 .../index/sorted/inline/InlineIndexFactory.java    |  102 +
 .../query/index/sorted/inline/InlineIndexImpl.java |  478 ++++
 .../index/sorted/inline/InlineIndexKeyType.java    |   88 +
 .../sorted/inline/InlineIndexKeyTypeRegistry.java  |  188 ++
 .../query/index/sorted/inline/InlineIndexTree.java |  658 ++++++
 .../sorted/inline/InlineObjectBytesDetector.java   |  212 ++
 .../index/sorted/inline/InlineRecommender.java     |  141 ++
 .../sorted/inline/InlineTreeFilterClosure.java     |  142 ++
 .../sorted/inline/JavaObjectKeySerializer.java     |   54 +
 .../sorted/inline/io/AbstractInlineInnerIO.java    |  166 ++
 .../sorted/inline/io/AbstractInlineLeafIO.java     |  166 ++
 .../index/sorted/inline/io/AbstractInnerIO.java    |   81 +
 .../index/sorted/inline/io/AbstractLeafIO.java     |   81 +
 .../query/index/sorted/inline/io/IORowHandler.java |   71 +
 .../query/index/sorted/inline/io/InlineIO.java     |   35 +
 .../index/sorted/inline/io/InlineInnerIO.java      |   31 +
 .../query/index/sorted/inline/io/InlineLeafIO.java |   31 +
 .../query/index/sorted/inline/io/InnerIO.java      |   39 +
 .../cache/query/index/sorted/inline/io/LeafIO.java |   37 +
 .../cache/query/index/sorted/inline/io/MvccIO.java |   56 +
 .../index/sorted/inline/io/MvccInlineInnerIO.java  |   55 +
 .../index/sorted/inline/io/MvccInlineLeafIO.java   |   54 +
 .../query/index/sorted/inline/io/MvccInnerIO.java  |   58 +
 .../query/index/sorted/inline/io/MvccLeafIO.java   |   58 +
 .../inline/types/BooleanInlineIndexKeyType.java    |   59 +
 .../inline/types/ByteInlineIndexKeyType.java       |   59 +
 .../inline/types/BytesInlineIndexKeyType.java      |  154 ++
 .../inline/types/DateInlineIndexKeyType.java       |   69 +
 .../sorted/inline/types/DateValueConstants.java    |   46 +
 .../inline/types/DoubleInlineIndexKeyType.java     |   59 +
 .../inline/types/FloatInlineIndexKeyType.java      |   59 +
 .../inline/types/IntegerInlineIndexKeyType.java    |   61 +
 .../inline/types/LongInlineIndexKeyType.java       |   61 +
 .../inline/types/NullableInlineIndexKeyType.java   |  232 ++
 .../types/ObjectByteArrayInlineIndexKeyType.java   |   69 +
 .../inline/types/ObjectHashInlineIndexKeyType.java |   64 +
 .../inline/types/ShortInlineIndexKeyType.java      |   59 +
 .../types/SignedBytesInlineIndexKeyType.java       |   33 +
 .../inline/types/StringInlineIndexKeyType.java     |  279 +++
 .../types/StringNoCompareInlineIndexKeyType.java   |   55 +
 .../inline/types/TimeInlineIndexKeyType.java       |   61 +
 .../inline/types/TimestampInlineIndexKeyType.java  |   82 +
 .../inline/types/UuidInlineIndexKeyType.java       |   74 +
 .../index/sorted/keys/AbstractDateIndexKey.java    |   37 +
 .../index/sorted/keys/AbstractTimeIndexKey.java    |   36 +
 .../sorted/keys/AbstractTimestampIndexKey.java     |   40 +
 .../query/index/sorted/keys/BooleanIndexKey.java   |   48 +
 .../query/index/sorted/keys/ByteIndexKey.java      |   48 +
 .../query/index/sorted/keys/BytesCompareUtils.java |   59 +
 .../query/index/sorted/keys/BytesIndexKey.java     |   48 +
 .../index/sorted/keys/CacheJavaObjectIndexKey.java |   85 +
 .../query/index/sorted/keys/DecimalIndexKey.java   |   49 +
 .../query/index/sorted/keys/DoubleIndexKey.java    |   48 +
 .../query/index/sorted/keys/FloatIndexKey.java     |   48 +
 .../cache/query/index/sorted/keys/IndexKey.java    |   40 +
 .../query/index/sorted/keys/IndexKeyFactory.java   |   99 +
 .../query/index/sorted/keys/IntegerIndexKey.java   |   48 +
 .../index/sorted/keys/JavaObjectIndexKey.java      |  109 +
 .../query/index/sorted/keys/LongIndexKey.java      |   48 +
 .../query/index/sorted/keys/NullIndexKey.java      |   46 +
 .../index/sorted/keys/PlainJavaObjectIndexKey.java |   64 +
 .../query/index/sorted/keys/ShortIndexKey.java     |   49 +
 .../index/sorted/keys/SignedBytesIndexKey.java     |   33 +
 .../query/index/sorted/keys/StringIndexKey.java    |   49 +
 .../query/index/sorted/keys/UuidIndexKey.java      |   53 +
 .../thin/ClientCacheEntryListenerHandler.java      |  265 +++
 .../thin/ClientCacheEntryListenersRegistry.java    |   61 +
 .../ignite/internal/client/thin/ClientChannel.java |    9 +-
 .../internal/client/thin/ClientComputeImpl.java    |  249 +-
 .../client/thin/ClientContinuousQueryCursor.java   |   61 +
 .../internal/client/thin/ClientJCacheAdapter.java  |  194 ++
 .../thin/ClientJCacheEntryListenerAdapter.java     |   70 +
 .../client/thin/ClientNotificationType.java        |   45 +
 .../internal/client/thin/ClientOperation.java      |   25 +-
 .../client/thin/IgniteClientFutureImpl.java        |   54 +-
 .../internal/client/thin/NotificationListener.java |   12 +-
 .../internal/client/thin/ReliableChannel.java      |   50 +-
 .../internal/client/thin/TcpClientCache.java       |  242 +-
 .../internal/client/thin/TcpClientChannel.java     |  115 +-
 .../internal/client/thin/TcpIgniteClient.java      |   23 +-
 .../ignite/internal/cluster/IgniteClusterImpl.java |    9 +-
 .../stream/v2/DirectByteBufferStreamImplV2.java    |   15 +-
 .../internal/jdbc/thin/JdbcThinConnection.java     |    6 +-
 .../ignite/internal/jdbc2/JdbcCloseCursorTask.java |   46 +
 .../ignite/internal/jdbc2/JdbcConnection.java      |   48 +
 .../jdbc2/JdbcQueryMultipleStatementsTask.java     |   11 +
 .../jdbc2/JdbcQueryMultipleStatementsTaskV3.java   |   72 +
 .../ignite/internal/jdbc2/JdbcResultSet.java       |   20 +-
 .../ignite/internal/jdbc2/JdbcStatement.java       |   29 +-
 .../jdbc2/JdbcStreamedPreparedStatement.java       |    2 +-
 .../internal/managers/GridManagerAdapter.java      |    8 +-
 .../communication/GridIoMessageFactory.java        |    4 -
 .../deployment/GridDeploymentLocalStore.java       |  174 +-
 .../deployment/GridDeploymentPerLoaderStore.java   |    2 +-
 .../managers/discovery/GridDiscoveryManager.java   |  111 +-
 .../managers/encryption/CacheGroupPageScanner.java |  234 +-
 .../encryption/EncryptionCacheKeyProvider.java     |   42 +
 .../managers/encryption/GridEncryptionManager.java |  110 +-
 .../managers/encryption/GroupKeyChangeProcess.java |    4 +-
 .../managers/indexing/IndexesRebuildTask.java      |  170 ++
 .../systemview/walker/AtomicLongViewWalker.java    |   52 +
 .../walker/AtomicReferenceViewWalker.java          |   52 +
 .../walker/AtomicSequenceViewWalker.java           |   54 +
 .../systemview/walker/AtomicStampedViewWalker.java |   54 +
 .../walker/CountDownLatchViewWalker.java           |   56 +
 .../systemview/walker/QueueViewWalker.java         |   61 +
 .../systemview/walker/ReentrantLockViewWalker.java |   60 +
 .../systemview/walker/SemaphoreViewWalker.java     |   60 +
 .../managers/systemview/walker/SetViewWalker.java  |   57 +
 .../systemview/walker/SqlQueryViewWalker.java      |    4 +-
 .../internal/metric/IoStatisticsHolderQuery.java   |    3 +-
 .../ignite/internal/pagemem/PageIdAllocator.java   |    6 -
 .../apache/ignite/internal/pagemem/PageUtils.java  |    2 +-
 .../pagemem/store/IgnitePageStoreManager.java      |    8 +-
 .../internal/pagemem/wal/record/DataEntry.java     |    6 +-
 .../internal/pagemem/wal/record/WALRecord.java     |    6 +-
 .../delta/MetaPageUpdatePartitionDataRecordV2.java |    9 +-
 .../internal/processors/GridProcessorAdapter.java  |    5 +-
 .../affinity/GridAffinityAssignmentCache.java      |    4 +-
 .../processors/affinity/GridAffinityProcessor.java |   29 +-
 .../authentication/AuthorizationContext.java       |   89 -
 .../IgniteAuthenticationProcessor.java             |  527 +++--
 .../cache/CacheAffinitySharedManager.java          |   49 +-
 .../processors/cache/CacheEvictableEntryImpl.java  |    2 +-
 .../processors/cache/CacheGroupContext.java        |    3 +-
 .../processors/cache/CacheGroupMetricsImpl.java    |    3 +-
 .../cache/CacheGroupMetricsMXBeanImpl.java         |   12 +-
 .../internal/processors/cache/CacheLazyEntry.java  |   19 +-
 .../cache/CacheLocalMetricsMXBeanImpl.java         |   14 +-
 .../processors/cache/CacheMetricsImpl.java         |   17 +-
 .../processors/cache/ClusterCachesInfo.java        |   67 +-
 .../cache/DynamicCacheChangeRequest.java           |    2 +-
 .../internal/processors/cache/ExchangeActions.java |   28 +-
 .../cache/GatewayProtectedCacheProxy.java          |   60 +-
 .../processors/cache/GridCacheAdapter.java         |   34 +-
 .../cache/GridCacheDeploymentManager.java          |   25 +-
 .../processors/cache/GridCacheEvictionManager.java |    2 +-
 .../processors/cache/GridCacheIoManager.java       |   38 +-
 .../processors/cache/GridCacheMapEntry.java        |   23 +-
 .../processors/cache/GridCacheMvccManager.java     |    2 +-
 .../cache/GridCachePartitionExchangeManager.java   |   47 +-
 .../processors/cache/GridCachePreloader.java       |    3 +-
 .../cache/GridCachePreloaderAdapter.java           |    2 +-
 .../processors/cache/GridCacheProcessor.java       |  231 +-
 .../processors/cache/GridCacheSharedContext.java   |   12 +-
 .../cache/GridCacheSharedTtlCleanupManager.java    |   23 +-
 .../internal/processors/cache/GridCacheUtils.java  |    3 +
 .../cache/GridDeferredAckMessageSender.java        |    3 +-
 .../processors/cache/IgniteCacheFutureImpl.java    |    8 +-
 .../cache/IgniteCacheOffheapManager.java           |   15 +-
 .../cache/IgniteCacheOffheapManagerImpl.java       |   32 +-
 .../processors/cache/IgniteCacheProxyImpl.java     |   26 +-
 .../cache/IgniteFinishedCacheFutureImpl.java       |    2 +-
 .../cache/PartitionUpdateCounterErrorWrapper.java  |  182 ++
 .../cache/PartitionUpdateCounterTrackingImpl.java  |   31 +-
 .../internal/processors/cache/QueryCursorImpl.java |   81 +-
 .../cache/ValidationOnNodeJoinUtils.java           |    4 +-
 .../internal/processors/cache/WalStateManager.java |   49 +-
 .../cache/binary/BinaryMetadataTransport.java      |    3 +-
 .../binary/CacheObjectBinaryProcessorImpl.java     |   44 +-
 .../datastructures/CacheDataStructuresManager.java |   10 +
 .../distributed/GridCacheTxRecoveryFuture.java     |    5 +-
 .../cache/distributed/dht/GridDhtCacheAdapter.java |    2 +-
 .../dht/GridDhtTxAbstractEnlistFuture.java         |    3 +-
 .../distributed/dht/GridDhtTxPrepareFuture.java    |   74 +-
 .../dht/GridPartitionedSingleGetFuture.java        |    2 +-
 .../distributed/dht/atomic/GridDhtAtomicCache.java |   86 +-
 .../atomic/GridNearAtomicSingleUpdateFuture.java   |    5 +-
 .../dht/atomic/GridNearAtomicUpdateFuture.java     |    5 +-
 .../dht/colocated/GridDhtColocatedCache.java       |    6 +-
 .../dht/colocated/GridDhtColocatedLockFuture.java  |    5 +-
 .../dht/colocated/GridDhtDetachedCacheEntry.java   |    8 +-
 .../dht/preloader/FinishPreloadingTask.java        |   21 +-
 .../dht/preloader/GridDhtPartitionDemander.java    |  155 +-
 .../dht/preloader/GridDhtPartitionFullMap.java     |    3 +-
 .../dht/preloader/GridDhtPartitionSupplier.java    |    5 +-
 .../preloader/GridDhtPartitionsExchangeFuture.java |  202 +-
 .../dht/preloader/GridDhtPreloader.java            |    8 +-
 .../dht/preloader/latch/ExchangeLatchManager.java  |    3 +-
 .../dht/topology/GridClientPartitionTopology.java  |    2 +-
 .../dht/topology/GridDhtLocalPartition.java        |    2 +-
 .../dht/topology/GridDhtPartitionTopologyImpl.java |   12 +-
 .../dht/topology/GridDhtPartitionsReservation.java |   18 +-
 .../topology/GridDhtPartitionsStateValidator.java  |  125 +-
 .../distributed/near/GridNearAtomicCache.java      |    3 +-
 .../cache/distributed/near/GridNearGetFuture.java  |    2 +-
 .../cache/distributed/near/GridNearLockFuture.java |    2 +-
 ...dNearOptimisticSerializableTxPrepareFuture.java |   18 +-
 .../near/GridNearOptimisticTxPrepareFuture.java    |    5 +-
 .../distributed/near/GridNearTxFinishFuture.java   |    2 +-
 .../cache/distributed/near/GridNearTxLocal.java    |   73 +-
 .../near/GridNearTxPrepareResponse.java            |    2 +-
 .../processors/cache/local/GridLocalCache.java     |    6 +-
 .../cache/local/atomic/GridLocalAtomicCache.java   |    9 +-
 .../processors/cache/mvcc/MvccProcessorImpl.java   |    6 +-
 .../internal/processors/cache/mvcc/MvccUtils.java  |    4 +-
 .../msg/PartitionCountersNeighborcastRequest.java  |  173 --
 .../msg/PartitionCountersNeighborcastResponse.java |  141 --
 .../internal/processors/cache/package-info.java    |    5 +-
 .../cache/persistence/CacheDataRowAdapter.java     |   77 +-
 .../cache/persistence/DataRegionMetricsImpl.java   |   10 +
 .../persistence/DataRegionMetricsMXBeanImpl.java   |   12 +-
 .../cache/persistence/DataStorageMetricsImpl.java  |  198 +-
 .../persistence/DataStorageMetricsSnapshot.java    |   30 +-
 .../GridCacheDatabaseSharedManager.java            |  166 +-
 .../cache/persistence/GridCacheOffheapManager.java |  260 +-
 .../IgniteCacheDatabaseSharedManager.java          |   59 +-
 .../processors/cache/persistence/IndexStorage.java |   12 +
 .../cache/persistence/IndexStorageImpl.java        |   13 +
 .../cache/persistence/RecoveryDebug.java           |    2 +-
 .../persistence/checkpoint/CheckpointEntry.java    |   17 +-
 .../persistence/checkpoint/CheckpointHistory.java  |   29 +-
 .../persistence/checkpoint/CheckpointManager.java  |   17 +-
 .../checkpoint/CheckpointPagesWriter.java          |    3 +-
 .../persistence/checkpoint/CheckpointWorkflow.java |    7 +-
 .../cache/persistence/checkpoint/Checkpointer.java |  114 +-
 .../checkpoint/LightweightCheckpointManager.java   |    9 +-
 .../checkpoint/PartitionDestroyQueue.java          |   18 +-
 .../CachePartitionDefragmentationManager.java      |   24 +-
 .../cache/persistence/defragmentation/LinkMap.java |   16 +-
 .../cache/persistence/file/EncryptedFileIO.java    |   98 +-
 .../cache/persistence/file/EncryptionUtil.java     |  159 ++
 .../cache/persistence/file/FilePageStore.java      |   48 +-
 .../persistence/file/FilePageStoreFactory.java     |   56 -
 .../persistence/file/FilePageStoreManager.java     |  149 +-
 .../cache/persistence/file/FilePageStoreV2.java    |   14 +-
 .../file/FileVersionCheckingFactory.java           |   67 +-
 .../cache/persistence/freelist/PagesList.java      |   41 +-
 .../cache/persistence/metastorage/MetaStorage.java |   29 +-
 .../metastorage/MetastorageRowStoreEntry.java      |    3 +-
 .../pendingtask/DurableBackgroundTask.java         |   37 +-
 .../pendingtask/DurableBackgroundTaskResult.java   |  107 +
 .../processors/cache/persistence/package-info.java |    5 +-
 .../pagemem/ClockPageReplacementFlags.java         |  154 ++
 .../pagemem/ClockPageReplacementPolicy.java        |   96 +
 .../pagemem/ClockPageReplacementPolicyFactory.java |   33 +
 .../cache/persistence/pagemem/PageMemoryImpl.java  |  545 ++---
 .../cache/persistence/pagemem/PagePool.java        |    8 +
 .../pagemem/PageReadWriteManagerImpl.java          |    8 +-
 .../persistence/pagemem/PageReplacementPolicy.java |   69 +
 .../pagemem/PageReplacementPolicyFactory.java      |   39 +
 .../pagemem/RandomLruPageReplacementPolicy.java    |  247 ++
 .../RandomLruPageReplacementPolicyFactory.java     |   33 +
 .../persistence/pagemem/SegmentedLruPageList.java  |  364 +++
 .../pagemem/SegmentedLruPageReplacementPolicy.java |  102 +
 .../SegmentedLruPageReplacementPolicyFactory.java  |   33 +
 .../cache/persistence/pagemem/package-info.java    |    5 +-
 .../snapshot/IgniteCacheSnapshotManager.java       |    3 +-
 .../snapshot/IgniteSnapshotManager.java            |  796 ++++++-
 .../snapshot/IgniteSnapshotVerifyException.java    |   48 +
 .../persistence/snapshot/SnapshotFutureTask.java   |  215 +-
 .../persistence/snapshot/SnapshotMetadata.java     |  199 ++
 .../snapshot/SnapshotMetadataCollectorTask.java    |  111 +
 .../snapshot/SnapshotOperationRequest.java         |  130 +
 .../snapshot/SnapshotPartitionsVerifyTask.java     |  327 +++
 .../snapshot/SnapshotRestoreProcess.java           |  935 ++++++++
 .../cache/persistence/tree/BPlusTree.java          |    9 +-
 .../persistence/tree/io/AbstractDataPageIO.java    |  129 +-
 .../cache/persistence/tree/io/BPlusMetaIO.java     |   31 +-
 .../cache/persistence/tree/io/PageIO.java          |    3 +-
 .../persistence/tree/io/PagePartitionMetaIO.java   |   38 +
 .../persistence/tree/io/PagePartitionMetaIOV2.java |   23 +-
 .../persistence/tree/io/PagePartitionMetaIOV3.java |   16 +-
 .../cache/persistence/tree/util/PageHandler.java   |   16 +-
 .../persistence/wal/FileWriteAheadLogManager.java  |  443 +++-
 .../cache/persistence/wal/SegmentRouter.java       |    8 +-
 .../wal/filehandle/FileHandleManagerImpl.java      |   10 +-
 .../wal/reader/StandaloneGridKernalContext.java    |   20 +-
 .../wal/reader/StandaloneWalRecordsIterator.java   |    8 +-
 .../wal/serializer/RecordDataV1Serializer.java     |    4 +-
 .../wal/serializer/RecordV1Serializer.java         |    8 +-
 .../processors/cache/query/CacheQueryEntry.java    |    2 +-
 .../query/GridCacheDistributedQueryFuture.java     |    6 +-
 .../query/GridCacheDistributedQueryManager.java    |    6 +-
 .../cache/query/GridCacheQueryManager.java         |   84 +-
 .../processors/cache/query/GridCacheSqlQuery.java  |   25 +-
 .../continuous/CacheContinuousQueryHandler.java    |   44 +-
 .../continuous/CacheContinuousQueryHandlerV3.java  |    7 +-
 .../continuous/CacheContinuousQueryManager.java    |    8 +-
 .../cache/query/jdbc/GridCacheQueryJdbcTask.java   |    6 +-
 .../cache/store/GridCacheWriteBehindStore.java     |   10 +-
 .../cache/transactions/IgniteTxAdapter.java        |   17 +-
 .../cache/transactions/IgniteTxEntry.java          |   16 +-
 .../cache/transactions/IgniteTxHandler.java        |   64 +-
 .../cache/transactions/IgniteTxLocalAdapter.java   |   11 +-
 .../cache/transactions/IgniteTxManager.java        |  133 +-
 .../PartitionCountersNeighborcastFuture.java       |  236 --
 .../cache/transactions/TxEntryValueHolder.java     |    5 +-
 .../processors/cache/tree/AbstractDataLeafIO.java  |    2 +-
 .../processors/cache/tree/CacheDataRowStore.java   |   10 +-
 .../processors/cache/tree/CacheDataTree.java       |    2 +-
 .../internal/processors/cache/tree/DataRow.java    |    7 +
 .../cache/tree/mvcc/data/MvccDataRow.java          |    2 +-
 .../cache/tree/mvcc/data/MvccUpdateDataRow.java    |    6 +-
 .../cache/verify/IdleVerifyResultV2.java           |  102 +-
 .../processors/cache/verify/IdleVerifyUtility.java |  114 +-
 .../cache/verify/PartitionHashRecordV2.java        |   10 +-
 .../verify/VerifyBackupPartitionsDumpTask.java     |    8 +-
 .../cache/verify/VerifyBackupPartitionsTask.java   |    2 +-
 .../cache/verify/VerifyBackupPartitionsTaskV2.java |  190 +-
 .../cacheobject/IgniteCacheObjectProcessor.java    |   10 +
 .../processors/closure/GridClosureProcessor.java   |    6 +-
 .../cluster/ClusterMetricsUpdateMessage.java       |    6 +-
 .../processors/cluster/ClusterProcessor.java       |   12 +-
 .../cluster/GridClusterStateProcessor.java         |   37 +-
 .../autoadjust/BaselineAutoAdjustData.java         |   11 +-
 .../autoadjust/BaselineAutoAdjustScheduler.java    |   50 +-
 .../autoadjust/BaselineTopologyUpdater.java        |  162 ++
 .../baseline/autoadjust/ChangeTopologyWatcher.java |  164 --
 .../continuous/GridContinuousProcessor.java        |   85 +-
 .../datastreamer/DataStreamProcessor.java          |    3 +-
 .../processors/datastreamer/DataStreamerImpl.java  |   48 +-
 .../datastreamer/DataStreamerRequest.java          |    6 +-
 .../datastructures/AtomicDataStructureProxy.java   |    4 +-
 .../datastructures/DataStructuresProcessor.java    |  201 +-
 .../GridCacheAtomicReferenceImpl.java              |    4 +-
 .../datastructures/GridCacheLockImpl.java          |    2 +-
 .../datastructures/GridCacheQueueProxy.java        |   10 +
 .../datastructures/GridCacheSemaphoreImpl.java     |   35 +
 .../datastructures/GridCacheSemaphoreState.java    |    4 +-
 .../datastructures/GridCacheSetProxy.java          |   10 +
 .../processors/diagnostic/DiagnosticProcessor.java |  222 +-
 .../diagnostic/PageHistoryDiagnoster.java          |  350 ---
 .../processors/failure/FailureProcessor.java       |    2 +-
 .../internal/processors/job/GridJobProcessor.java  |   15 +-
 .../internal/processors/job/GridJobWorker.java     |    5 +
 .../processors/jobmetrics/GridJobMetrics.java      |   12 +-
 .../jobmetrics/GridJobMetricsProcessor.java        |   12 +-
 .../jobmetrics/GridJobMetricsSnapshot.java         |   12 +-
 .../localtask/DurableBackgroundTaskState.java      |  147 ++
 .../localtask/DurableBackgroundTasksProcessor.java |  439 ++--
 .../marshaller/GridMarshallerMappingProcessor.java |    3 +-
 .../marshaller/MarshallerMappingTransport.java     |    5 +-
 .../persistence/DistributedMetaStorageImpl.java    |  151 +-
 .../persistence/DmsDataWriterWorker.java           |  233 +-
 .../metastorage/persistence/DmsWorkerStatus.java   |   30 -
 .../processors/metric/GridMetricManager.java       |   10 +-
 .../internal/processors/metric/MetricRegistry.java |    8 +-
 .../ClientListenerAbstractConnectionContext.java   |   80 +-
 .../odbc/ClientListenerConnectionContext.java      |    8 -
 .../processors/odbc/ClientListenerNioListener.java |   22 +-
 .../processors/odbc/ClientListenerProcessor.java   |   14 +-
 .../internal/processors/odbc/SqlListenerUtils.java |    2 +-
 .../odbc/jdbc/JdbcConnectionContext.java           |   13 +-
 .../processors/odbc/jdbc/JdbcRequestHandler.java   |   16 +-
 .../processors/odbc/odbc/OdbcColumnMeta.java       |   39 +-
 .../odbc/odbc/OdbcConnectionContext.java           |   18 +-
 .../processors/odbc/odbc/OdbcMessageParser.java    |    4 +-
 .../processors/odbc/odbc/OdbcRequestHandler.java   |   30 +-
 .../processors/odbc/odbc/OdbcResultSet.java        |    2 +-
 .../internal/processors/odbc/odbc/OdbcUtils.java   |    7 +-
 .../processors/offheap/GridOffHeapProcessor.java   |    7 +-
 .../ignite/internal/processors/package-info.java   |    4 +-
 .../FilePerformanceStatisticsReader.java           |   57 +
 .../FilePerformanceStatisticsWriter.java           |   78 +-
 .../performancestatistics/OperationType.java       |   18 +-
 .../PerformanceStatisticsHandler.java              |   44 +
 .../PerformanceStatisticsMBeanImpl.java            |    5 +
 .../PerformanceStatisticsProcessor.java            |  168 +-
 .../processors/platform/PlatformProcessorImpl.java |    6 +-
 .../platform/binary/PlatformBinaryProcessor.java   |    3 +-
 .../platform/client/ClientBitmaskFeature.java      |    7 +-
 .../platform/client/ClientConnectionContext.java   |   17 +-
 .../platform/client/ClientMessageParser.java       |    7 +
 .../platform/client/ClientRequestHandler.java      |    8 +-
 .../ClientBinaryConfigurationGetRequest.java       |   76 +
 .../ClientBinaryConfigurationGetResponse.java      |   54 +
 .../cache/ClientCacheSqlFieldsQueryRequest.java    |    4 +-
 .../platform/cluster/PlatformClusterGroup.java     |    2 +-
 .../platform/services/PlatformServices.java        |   26 +-
 .../transactions/PlatformTransactions.java         |    6 +-
 .../platform/utils/PlatformConfigurationUtils.java |   40 +
 .../processors/platform/utils/PlatformUtils.java   |    3 +
 .../internal/processors/query/GridIndex.java       |    6 +-
 .../processors/query/GridQueryFieldMetadata.java   |    9 +
 .../processors/query/GridQueryIndexing.java        |   78 +-
 .../processors/query/GridQueryProcessor.java       |  243 +-
 .../processors/query/GridQueryRowCacheCleaner.java |    2 +-
 .../processors/query/GridRunningQueryInfo.java     |   15 +-
 .../processors/query/IndexRebuildAware.java        |  145 ++
 .../internal/processors/query/NoOpQueryEngine.java |    3 +-
 .../internal/processors/query/QueryEntityEx.java   |   26 +-
 .../processors/query/QueryTypeDescriptorImpl.java  |    4 +-
 .../internal/processors/query/QueryUtils.java      |   61 +-
 .../processors/query/RunningQueryManager.java      |   16 +-
 .../schema/SchemaIndexCacheCompoundFuture.java     |   49 +
 .../query/schema/SchemaIndexCacheFuture.java       |   46 +
 .../schema/SchemaIndexCachePartitionWorker.java    |   20 +-
 .../query/schema/SchemaIndexCacheVisitorImpl.java  |    7 +-
 .../SchemaIndexOperationCancellationException.java |   36 +
 .../processors/rest/GridRestProcessor.java         |   66 +-
 .../handlers/cache/GridCacheCommandHandler.java    |   67 +-
 .../DataStructuresCommandHandler.java              |    6 +-
 .../handlers/probe/GridProbeCommandHandler.java    |    6 +-
 .../rest/handlers/query/QueryCommandHandler.java   |    8 +-
 .../handlers/user/UserActionCommandHandler.java    |   13 +-
 .../rest/protocols/tcp/GridTcpRestNioListener.java |  104 +-
 .../processors/rest/request/GridRestRequest.java   |   16 +-
 .../processors/security/GridSecurityProcessor.java |   32 +
 .../processors/security/IgniteSecurity.java        |   26 +
 .../security/IgniteSecurityProcessor.java          |   20 +
 .../security/NoOpIgniteSecurityProcessor.java      |   22 +-
 .../processors/security/SecurityUtils.java         |    2 +-
 .../processors/service/GridServiceProcessor.java   |    3 +-
 .../processors/service/GridServiceProxy.java       |   14 +-
 .../processors/service/ServiceDeploymentTask.java  |    3 +-
 .../GridInternalSubscriptionProcessor.java         |    3 +-
 .../internal/processors/task/GridTaskWorker.java   |    5 +-
 .../internal/processors/tracing/SpanTags.java      |    9 +
 .../processors/tracing/TraceableIterator.java      |   11 +-
 .../GridTracingConfigurationManager.java           |    8 +-
 .../apache/ignite/internal/sql/SqlParserUtils.java |    2 +-
 .../suggestions/JvmConfigurationSuggestions.java   |    6 -
 .../suggestions/OsConfigurationSuggestions.java    |   38 +-
 .../apache/ignite/internal/util/GridCleaner.java   |    2 +-
 .../org/apache/ignite/internal/util/GridDebug.java |    4 +-
 .../ignite/internal/util/GridJavaProcess.java      |    9 +-
 .../apache/ignite/internal/util/GridLeanSet.java   |    2 +-
 .../ignite/internal/util/GridMutableLong.java      |   64 +
 .../apache/ignite/internal/util/GridUnsafe.java    |    7 +-
 .../ignite/internal/util/HostAndPortRange.java     |  133 +-
 .../apache/ignite/internal/util/IgniteUtils.java   |   82 +-
 .../ignite/internal/util/collection/IntMap.java    |   30 +
 .../util/distributed/DistributedProcess.java       |   24 +-
 .../internal/util/future/IgniteFutureImpl.java     |   24 +-
 .../util/ipc/loopback/IpcServerTcpEndpoint.java    |    2 +-
 .../ipc/shmem/IpcSharedMemoryServerEndpoint.java   |    2 +-
 .../apache/ignite/internal/util/lang/GridFunc.java |   10 +
 .../ignite/internal/util/nio/GridNioServer.java    |   11 +
 .../internal/util/nio/GridNioSessionImpl.java      |    2 +-
 .../internal/util/nio/ssl/GridNioSslHandler.java   |   12 +
 .../util/offheap/unsafe/GridUnsafeMap.java         |    2 +-
 .../util/tostring/CircularStringBuilder.java       |    2 +-
 .../util/tostring/GridToStringBuilder.java         |    7 +-
 .../apache/ignite/internal/util/typedef/CIX1.java  |    7 +-
 .../apache/ignite/internal/util/typedef/CIX2.java  |    7 +-
 .../apache/ignite/internal/util/typedef/COX.java   |    7 +-
 .../apache/ignite/internal/util/typedef/CX1.java   |    7 +-
 .../apache/ignite/internal/util/typedef/CX2.java   |    7 +-
 .../apache/ignite/internal/util/typedef/PX1.java   |    7 +-
 .../apache/ignite/internal/util/typedef/PX2.java   |    7 +-
 .../apache/ignite/internal/util/typedef/R2.java    |    7 +-
 .../apache/ignite/internal/util/typedef/R3.java    |    7 +-
 .../apache/ignite/internal/util/typedef/RX1.java   |    7 +-
 .../apache/ignite/internal/util/typedef/RX2.java   |    7 +-
 .../apache/ignite/internal/util/typedef/RX3.java   |    7 +-
 .../ignite/internal/util/worker/CycleThread.java   |    2 +-
 .../ignite/internal/util/worker/GridWorker.java    |    4 +-
 .../visor/annotation/InterruptibleVisorTask.java   |   32 +
 ...VisorFindAndDeleteGarbageInPersistenceTask.java |   17 +-
 .../visor/cache/index/IndexForceRebuildTask.java   |  135 +-
 .../visor/cache/index/IndexRebuildStatusTask.java  |    7 +-
 .../diagnostic/VisorPageLocksTrackerArgs.java      |    2 +-
 .../node/VisorCacheRebalanceCollectorTask.java     |    3 +-
 .../VisorPerformanceStatisticsOperation.java       |   48 +
 .../VisorPerformanceStatisticsTask.java            |   93 +
 .../VisorPerformanceStatisticsTaskArg.java         |   64 +
 .../internal/visor/query/VisorQueryUtils.java      |    5 +-
 .../query/VisorRunningQueriesCollectorTask.java    |    4 +-
 .../visor/snapshot/VisorSnapshotCheckTask.java     |   60 +
 .../VisorTracingConfigurationTask.java             |    3 +-
 .../ignite/internal/visor/util/VisorMimeTypes.java |    9 +-
 .../internal/visor/verify/VisorIdleVerifyJob.java  |   13 +
 .../java/org/apache/ignite/lang/IgniteBiTuple.java |    2 +-
 .../java/org/apache/ignite/lang/IgniteFuture.java  |   10 +-
 .../org/apache/ignite/lang/IgniteProducer.java     |   34 +
 .../ignite/mxbean/CacheGroupMetricsMXBean.java     |   10 +-
 .../apache/ignite/mxbean/CacheMetricsMXBean.java   |   70 +-
 .../ignite/mxbean/DataRegionMetricsMXBean.java     |   34 +-
 .../ignite/mxbean/DataStorageMetricsMXBean.java    |   20 +-
 .../ignite/mxbean/DefragmentationMXBean.java       |    4 +-
 .../org/apache/ignite/mxbean/IgniteMXBean.java     |   74 +-
 .../ignite/mxbean/PerformanceStatisticsMBean.java  |    8 +-
 .../org/apache/ignite/mxbean/ThreadPoolMXBean.java |   20 +-
 .../ignite/mxbean/TransactionMetricsMxBean.java    |   12 +-
 .../plugin/security/AuthenticationContext.java     |   21 -
 .../ignite/plugin/security/SecurityPermission.java |    2 +-
 .../org/apache/ignite/spi/IgniteSpiContext.java    |    9 +-
 .../ignite/spi/checkpoint/CheckpointSpi.java       |    8 +-
 .../checkpoint/sharedfs/SharedFsCheckpointSpi.java |    2 +-
 .../jobstealing/JobStealingCollisionSpi.java       |    4 +-
 .../priorityqueue/PriorityQueueCollisionSpi.java   |    2 +-
 .../spi/communication/tcp/TcpCommunicationSpi.java |   29 +-
 .../tcp/internal/CommunicationTcpUtils.java        |   40 +-
 .../tcp/internal/CommunicationWorker.java          |    4 +-
 .../tcp/internal/ConnectionClientPool.java         |   93 +-
 .../tcp/internal/GridNioServerWrapper.java         |  328 +--
 .../tcp/internal/HandshakeTimeoutObject.java       |   55 +-
 .../tcp/internal/InboundConnectionHandler.java     |    2 +-
 .../TcpCommunicationConfigInitializer.java         |    3 +-
 .../TcpCommunicationConnectionCheckFuture.java     |    3 +-
 .../tcp/internal/TcpHandshakeExecutor.java         |  284 +++
 .../spi/deployment/local/LocalDeploymentSpi.java   |  100 +-
 .../ignite/spi/discovery/tcp/ClientImpl.java       |   19 +-
 .../ignite/spi/discovery/tcp/ServerImpl.java       |  116 +-
 .../ignite/spi/discovery/tcp/TcpDiscoverySpi.java  |   69 +-
 .../spi/discovery/tcp/TcpDiscoverySpiMBean.java    |   15 +-
 .../tcp/internal/TcpDiscoveryStatistics.java       |   12 +-
 .../multicast/TcpDiscoveryMulticastIpFinder.java   |    4 +-
 .../tcp/ipfinder/vm/TcpDiscoveryVmIpFinder.java    |  104 +-
 .../ignite/spi/encryption/EncryptionSpi.java       |   37 +-
 .../encryption/keystore/KeystoreEncryptionSpi.java |   94 +-
 .../spi/encryption/noop/NoopEncryptionSpi.java     |   15 +
 .../apache/ignite/spi/failover/FailoverSpi.java    |    3 +-
 .../jobstealing/JobStealingFailoverSpi.java        |    6 +-
 .../spi/indexing/IndexingQueryFilterImpl.java      |   34 +-
 .../apache/ignite/spi/indexing/IndexingSpi.java    |    2 +-
 .../ignite/spi/indexing/noop/NoopIndexingSpi.java  |    2 +-
 .../ignite/spi/metric/MetricExporterSpi.java       |   11 +-
 .../ignite/spi/metric/ReadOnlyMetricRegistry.java  |   32 +
 .../spi/metric/jmx/JmxMetricExporterSpi.java       |   55 +-
 .../spi/systemview/view/ClientConnectionView.java  |   10 +-
 .../spi/systemview/view/ContinuousQueryView.java   |   11 +-
 .../ignite/spi/systemview/view/SqlQueryView.java   |    6 +
 .../datastructures/AbstractDataStructureView.java  |   58 +
 .../view/datastructures/AtomicLongView.java        |   48 +
 .../view/datastructures/AtomicReferenceView.java   |   50 +
 .../view/datastructures/AtomicSequenceView.java    |   57 +
 .../view/datastructures/AtomicStampedView.java     |   59 +
 .../view/datastructures/CountDownLatchView.java    |   64 +
 .../systemview/view/datastructures/QueueView.java  |   89 +
 .../view/datastructures/ReentrantLockView.java     |   83 +
 .../view/datastructures/SemaphoreView.java         |   83 +
 .../systemview/view/datastructures/SetView.java    |   78 +
 .../apache/ignite/stream/StreamTransformer.java    |    2 +-
 .../java/org/jsr166/ConcurrentLinkedHashMap.java   |    8 +-
 .../main/resources/META-INF/classnames.properties  |    2 +
 modules/core/src/main/resources/ignite.properties  |    2 +-
 .../src/test/config/class_list_test_excluded.txt   |   17 +
 .../test/java/org/apache/ignite/GridTestJob.java   |    2 +-
 ...finityFunctionBackupFilterAbstractSelfTest.java |   24 +-
 ...tyFunctionExcludeNeighborsAbstractSelfTest.java |    2 +-
 ...NodeAttributeColocatedBackupFilterSelfTest.java |  250 ++
 ...usAffinityFunctionExcludeNeighborsSelfTest.java |   64 +-
 .../RendezvousAffinityFunctionSimpleBenchmark.java |    3 +
 ...nerRWThroughDisabledTransactionalCacheTest.java |    3 +-
 ...CacheStoreSessionListenerLifecycleSelfTest.java |    5 +-
 .../store/StoreResourceInjectionSelfTest.java      |    4 +-
 ...hallerStoreKeepBinaryWithSqlEscapeSelfTest.java |    3 +-
 .../cache/store/jdbc/CacheJdbcPojoStoreTest.java   |    6 +-
 ...JdbcPojoWriteBehindStoreWithCoalescingTest.java |   12 +-
 .../jdbc/JdbcTypesDefaultTransformerTest.java      |    7 +-
 .../store/jdbc/dialect/OracleDialectTest.java      |   49 +
 .../TestJdbcPojoStoreFactoryWithHangWriteAll.java  |    9 +-
 .../org/apache/ignite/client/ConnectionTest.java   |   31 +-
 .../org/apache/ignite/client/FunctionalTest.java   |   93 +-
 .../apache/ignite/client/LocalIgniteCluster.java   |   14 +-
 .../apache/ignite/client/PersonBinarylizable.java  |   31 +-
 .../org/apache/ignite/client/ReliabilityTest.java  |   14 -
 .../failure/FailureHandlerTriggeredTest.java       |    2 +-
 .../internal/ClusterNodeMetricsSelfTest.java       |    5 +-
 ...dCachePartitionExchangeManagerWarningsTest.java |  216 +-
 .../internal/GridContinuousTaskSelfTest.java       |    6 +-
 .../internal/GridJobMasterLeaveAwareSelfTest.java  |    3 +-
 .../GridMultipleVersionsDeploymentSelfTest.java    |    2 +-
 .../GridMultithreadedJobStealingSelfTest.java      |   12 +-
 .../internal/GridNodeMetricsLogPdsSelfTest.java    |   11 +-
 .../internal/GridNodeMetricsLogSelfTest.java       |   18 +-
 .../ignite/internal/GridSpiExceptionSelfTest.java  |    3 +-
 .../internal/GridStopWithCollisionSpiTest.java     |   66 +
 ...ientCheckClusterGroupLocalIdAfterReconnect.java |  142 ++
 .../ignite/internal/IgniteClientFailuresTest.java  |  100 +-
 .../IgniteExplicitImplicitDeploymentSelfTest.java  |  178 +-
 .../RaceOnDeployClassesWithSameAliases.java        |  147 --
 .../binary/BinaryBasicNameMapperSelfTest.java      |   21 +
 .../binary/BinaryClassLoaderMultiJvmTest.java      |    3 +-
 .../internal/binary/BinaryClassLoaderTest.java     |    3 +-
 .../internal/binary/BinaryEnumsSelfTest.java       |    1 +
 .../BinaryFooterOffsetsAbstractSelfTest.java       |    2 +
 .../internal/binary/BinaryMarshallerSelfTest.java  |  182 +-
 .../BinaryObjectBuilderAdditionalSelfTest.java     |   11 +-
 .../BinaryObjectBuilderDefaultMappersSelfTest.java |    3 +-
 .../AbstractBinaryStreamByteOrderSelfTest.java     |    5 +
 .../streams/BinaryAbstractOutputStreamTest.java    |    9 +
 .../inline/InlineIndexKeyTypeRegistryTest.java     |   97 +
 .../client/thin/AbstractThinClientTest.java        |   22 +
 .../internal/client/thin/CacheAsyncTest.java       |   28 +-
 .../client/thin/CacheEntryListenersTest.java       |  774 ++++++
 .../internal/client/thin/ComputeTaskTest.java      |   29 +-
 .../internal/client/thin/ReliableChannelTest.java  |   10 +-
 .../ignite/internal/client/thin/ServicesTest.java  |   29 +-
 ...ClientPartitionAwarenessStableTopologyTest.java |   12 +
 .../internal/cluster/IgniteClusterIdTagTest.java   |    2 +-
 ...ectByteBufferStreamImplV2ByteOrderSelfTest.java |   63 +-
 .../encryption/AbstractEncryptionTest.java         |   10 +-
 .../encryption/CacheGroupKeyChangeTest.java        |    2 +-
 .../encryption/CacheGroupReencryptionTest.java     |   17 +-
 .../encryption/EncryptedCacheBigEntryTest.java     |    4 +-
 .../encryption/EncryptedCacheCreateTest.java       |    2 +-
 .../encryption/EncryptedCacheDestroyTest.java      |    2 +-
 .../encryption/EncryptedCacheGroupCreateTest.java  |    4 +-
 .../encryption/EncryptedCacheRestartTest.java      |    4 +-
 .../internal/encryption/EncryptionMXBeanTest.java  |    4 +-
 ...GridManagerMxBeanIllegalArgumentHandleTest.java |    4 +-
 .../managers/IgniteDiagnosticMessagesTest.java     |    5 +-
 .../IgniteCommunicationBalanceTest.java            |    3 +-
 .../GridDeploymentManagerStopSelfTest.java         |    4 +-
 .../GridDifferentLocalDeploymentSelfTest.java      |  162 ++
 .../P2PCacheOperationIntoComputeTest.java          |    5 +-
 .../IgniteTopologyPrintFormatSelfTest.java         |  212 +-
 .../optimized/OptimizedMarshallerTest.java         |   12 +-
 .../ignite/internal/metric/MetricsSelfTest.java    |   14 +-
 .../ignite/internal/metric/SystemMetricsTest.java  |   66 +
 .../ignite/internal/metric/SystemViewSelfTest.java |  677 ++++++
 .../wal/record/WALRecordSerializationTest.java     |    3 +-
 .../Authentication1kUsersNodeRestartTest.java      |   38 +-
 .../AuthenticationConfigurationClusterTest.java    |   80 +-
 .../AuthenticationOnNotActiveClusterTest.java      |   22 +-
 .../AuthenticationProcessorNodeRestartTest.java    |   58 +-
 .../AuthenticationProcessorSelfTest.java           |  324 +--
 .../cache/CacheAsyncContinuationExecutorTest.java  |  254 ++
 ...heAsyncContinuationSynchronousExecutorTest.java |   42 +
 .../cache/CacheEntryProcessorCopySelfTest.java     |    4 +
 .../cache/CacheGroupsMetricsRebalanceTest.java     |   52 +-
 ...InterceptorPartitionCounterLocalSanityTest.java |   12 +-
 .../processors/cache/CacheMetricsManageTest.java   |    6 +-
 .../processors/cache/CacheRebalancingSelfTest.java |    2 +-
 .../cache/CacheSerializableTransactionsTest.java   |   15 +-
 .../cache/CacheStopAndDestroySelfTest.java         |   20 +-
 .../ClientFastReplyCoordinatorFailureTest.java     |  100 +
 .../processors/cache/ClusterStateTestUtils.java    |    5 +-
 .../cache/GridCacheAffinityRoutingSelfTest.java    |    3 +
 .../GridCacheAsyncOperationsLimitSelfTest.java     |    4 +-
 .../GridCacheConfigurationConsistencySelfTest.java |    3 +-
 .../cache/GridCacheEntryMemorySizeSelfTest.java    |    3 +
 .../cache/GridCacheEntryVersionSelfTest.java       |    2 +-
 .../processors/cache/GridCacheMvccSelfTest.java    |    3 +
 .../cache/GridCacheNestedTxAbstractTest.java       |    2 +-
 .../cache/GridCacheOffheapUpdateSelfTest.java      |    2 +-
 .../cache/GridCacheOnCopyFlagAtomicSelfTest.java   |    2 +
 .../cache/GridCacheOnCopyFlagLocalSelfTest.java    |    2 +
 .../GridCacheOnCopyFlagReplicatedSelfTest.java     |    2 +
 .../GridCacheOnCopyFlagTxPartitionedSelfTest.java  |    2 +
 .../cache/GridCacheP2PUndeploySelfTest.java        |    2 +
 .../cache/GridCachePartitionedWritesTest.java      |    4 +-
 .../cache/GridCacheReferenceCleanupSelfTest.java   |    7 +
 .../cache/GridCacheTtlManagerEvictionSelfTest.java |    2 +
 .../cache/GridCacheTtlManagerLoadTest.java         |    2 +-
 .../IgniteAbstractDynamicCacheStartFailTest.java   |    6 +-
 .../IgniteCacheClusterReadOnlyModeSelfTest.java    |   10 +-
 .../processors/cache/IgniteCacheGroupsTest.java    |    2 +-
 .../cache/IgniteCacheInterceptorSelfTestSuite.java |    9 +-
 .../cache/IgniteClientCacheStartFailoverTest.java  |    8 +-
 .../cache/IgniteDynamicCacheStartSelfTest.java     |    8 +-
 .../cache/IgniteOutOfMemoryPropagationTest.java    |    3 +
 .../RebalanceIteratorLargeEntriesOOMTest.java      |  137 ++
 .../cache/RestorePartitionStateTest.java           |  220 ++
 .../SetTxTimeoutOnPartitionMapExchangeTest.java    |    2 +-
 ...aryObjectsAtomicNearDisabledOnheapSelfTest.java |    6 +
 ...GridCacheBinaryObjectsAtomicOnheapSelfTest.java |    6 +
 ...jectsPartitionedNearDisabledOnheapSelfTest.java |    6 +
 ...acheBinaryObjectsPartitionedOnheapSelfTest.java |    6 +
 .../GridCacheBinaryObjectsLocalOnheapSelfTest.java |    6 +
 ...acheAbstractDataStructuresFailoverSelfTest.java |    2 +-
 .../GridCacheAtomicStampedApiSelfAbstractTest.java |    2 +-
 .../GridCacheQueueClientDisconnectTest.java        |    2 +-
 .../IgniteAtomicStampedClusterReadOnlyTest.java    |    2 +-
 .../IgniteDataStructuresNoClassOnServerTest.java   |    2 +
 ...iteExchangeLatchManagerCoordinatorFailTest.java |    4 +-
 .../datastructures/IgniteLockAbstractSelfTest.java |    2 +-
 .../IgniteSemaphoreAbstractSelfTest.java           |  101 +-
 .../SemaphoreFailoverNoWaitingAcquirerTest.java    |    2 +-
 ...chePartitionedAtomicReferenceMultiNodeTest.java |    2 +
 .../GridCachePartitionedNodeRestartTxSelfTest.java |    5 +-
 .../partitioned/IgnitePartitionedLockSelfTest.java |    2 +
 ...acheReplicatedAtomicReferenceMultiNodeTest.java |    2 +
 .../distributed/CacheBaselineTopologyTest.java     |    8 +-
 .../distributed/CacheBlockOnReadAbstractTest.java  |    2 +-
 .../CacheClientsConcurrentStartTest.java           |   32 +-
 .../cache/distributed/CacheStartOnJoinTest.java    |    7 +-
 .../GridCacheMultiNodeLockAbstractTest.java        |   12 +-
 ...GridCacheMultithreadedFailoverAbstractTest.java |  593 -----
 .../GridCacheMultithreadedFailoverTest.java        |  595 +++++
 ...PartitionEvictionDuringReadThroughSelfTest.java |    7 +-
 ...GridExchangeFreeCellularSwitchAbstractTest.java |  134 +-
 ...ngeFreeCellularSwitchComplexOperationsTest.java |   76 +-
 ...ridExchangeFreeCellularSwitchIsolationTest.java |  535 +++--
 ...changeFreeCellularSwitchTxContinuationTest.java |  264 +++
 ...idExchangeFreeCellularSwitchTxCountersTest.java |  242 ++
 .../distributed/GridExchangeFreeSwitchTest.java    |    8 +-
 .../IgniteBinaryMetadataUpdateNodeRestartTest.java |    2 +
 ...CacheClientMultiNodeUpdateTopologyLockTest.java |    2 +
 .../IgniteCacheNearRestartRollbackSelfTest.java    |    2 +
 .../IgniteCachePartitionLossPolicySelfTest.java    |    4 +-
 .../distributed/IgniteCacheSizeFailoverTest.java   |    2 +-
 .../distributed/IgniteTxTimeoutAbstractTest.java   |    2 +-
 ...sabledAtomicOnheapMultiNodeFullApiSelfTest.java |    3 +-
 .../GridCachePartitionsStateValidationTest.java    |   25 +-
 .../GridCachePartitionsStateValidatorSelfTest.java |    3 +-
 ...idCachePartitionsUpdateCountersAndSizeTest.java |  246 ++
 .../dht/GridCacheTxNodeFailureSelfTest.java        |    2 +-
 .../dht/IgniteCacheConcurrentPutGetRemove.java     |  165 --
 .../dht/IgniteCacheConcurrentPutGetRemoveTest.java |  165 ++
 .../dht/IgniteCacheMultiTxLockSelfTest.java        |    2 +-
 .../dht/IgniteCacheStartWithLoadTest.java          |    7 +-
 ...lanceIsProcessingWhenAssignmentIsEmptyTest.java |    2 +-
 .../dht/atomic/GridCacheAtomicPreloadSelfTest.java |    2 +
 .../dht/topology/BlockedEvictionsTest.java         |    7 +-
 ...MovingPartitionIsEvictedDuringClearingTest.java |    7 +-
 .../dht/topology/PartitionEvictionOrderTest.java   |  159 ++
 ...reloadingRestartWhileClearingPartitionTest.java |    7 +-
 .../GridCachePartitionedFilteredPutSelfTest.java   |    3 +-
 .../near/IgniteTxExceptionNodeFailTest.java        |  239 +-
 .../CacheRebalanceWithRemovedWalSegment.java       |  174 ++
 .../GridCacheRebalancingOrderingTest.java          |    2 +
 .../GridCacheRebalancingSyncSelfTest.java          |    2 +-
 .../rebalancing/RebalanceMetricsTest.java          |  112 +
 .../rebalancing/RebalanceStatisticsTest.java       |    3 +-
 .../GridCacheReplicatedMarshallerTxTest.java       |    2 +
 .../GridCacheReplicatedOnheapFullApiSelfTest.java  |    6 +
 ...heReplicatedOnheapMultiNodeFullApiSelfTest.java |    6 +
 .../GridCacheReplicatedTxConcurrentGetTest.java    |    2 +
 .../replicated/GridCacheReplicatedTxReadTest.java  |    2 +
 .../IgniteCacheAtomicLocalExpiryPolicyTest.java    |    3 +
 ...niteCacheAtomicLocalOnheapExpiryPolicyTest.java |    6 +
 .../IgniteCacheAtomicOnheapExpiryPolicyTest.java   |    6 +
 .../expiry/IgniteCacheExpiryPolicyTestSuite.java   |    4 +-
 ...teCacheStoreSessionWriteBehindAbstractTest.java |    4 +-
 .../GridCacheFastNodeLeftForTransactionTest.java   |    2 +-
 ...isabledAtomicOnheapMultiJvmFullApiSelfTest.java |    3 +-
 ...dNearDisabledOnheapMultiJvmFullApiSelfTest.java |    3 +-
 ...heMvccAbstractBasicCoordinatorFailoverTest.java |    7 +-
 .../cache/mvcc/CacheMvccAbstractTest.java          |    6 +-
 .../mvcc/CacheMvccConfigurationValidationTest.java |    6 +-
 .../cache/mvcc/CacheMvccTxFailoverTest.java        |    3 +-
 .../CorruptedTreeFailureHandlingTest.java          |   40 +-
 .../IgniteDataStorageMetricsSelfTest.java          |  238 +-
 ...gnitePdsBinaryMetadataOnClusterRestartTest.java |   12 +-
 ...sCacheObjectBinaryProcessorOnDiscoveryTest.java |    2 +-
 .../IgnitePdsCacheRebalancingAbstractTest.java     |    2 +-
 ...itePdsCacheStartStopWithFreqCheckpointTest.java |    2 +-
 .../persistence/IgnitePdsCorruptedStoreTest.java   |    3 +-
 .../persistence/IgnitePdsDefragmentationTest.java  |   68 +-
 .../IgnitePdsNoSpaceLeftOnDeviceTest.java          |    3 +-
 .../IgnitePdsSporadicDataRecordsOnBackupTest.java  |    2 +-
 ...IgnitePdsSpuriousRebalancingOnNodeJoinTest.java |   10 +-
 .../persistence/IgnitePdsTaskCancelingTest.java    |    2 +-
 .../persistence/MaintenanceRegistrySimpleTest.java |   14 +-
 ...hangingBaselineDownCacheRemoveFailoverTest.java |    5 +-
 ...eChangingBaselineUpCacheRemoveFailoverTest.java |    5 +-
 ...gniteStableBaselineCachePutAllFailoverTest.java |    2 +
 ...gniteStableBaselineCacheRemoveFailoverTest.java |    7 +-
 .../db/CheckpointBufferDeadlockTest.java           |   62 +-
 .../persistence/db/IgniteLogicalRecoveryTest.java  |    9 +-
 .../db/IgniteLogicalRecoveryWithParamsTest.java    |  368 +++
 .../db/IgnitePdsDataRegionMetricsTest.java         |   23 +-
 ...gnitePdsRebalancingOnNotStableTopologyTest.java |    2 +-
 .../db/IgnitePdsTransactionsHangTest.java          |    4 +-
 .../db/SlowCheckpointFileIOFactory.java            |   86 +
 .../db/checkpoint/CheckpointFreeListTest.java      |    6 +-
 .../db/checkpoint/IgniteMassLoadSandboxTest.java   |    3 +
 .../db/file/IgnitePdsCheckpointSimpleTest.java     |  144 +-
 ...CheckpointSimulationWithRealCpDisabledTest.java |    7 +-
 .../db/file/IgnitePdsDiskErrorsRecoveringTest.java |   10 +-
 .../db/file/IgnitePdsThreadInterruptionTest.java   |    2 +-
 .../persistence/db/wal/IgniteLocalWalSizeTest.java |   31 +-
 .../wal/IgniteNodeStoppedDuringDisableWALTest.java |    4 +-
 .../persistence/db/wal/IgniteWalRebalanceTest.java |  195 +-
 .../db/wal/WalArchiveSizeConfigurationTest.java    |  132 ++
 .../db/wal/WalCompactionAfterRestartTest.java      |    2 +
 .../db/wal/WalDeletionArchiveAbstractTest.java     |   98 +-
 .../db/wal/WalRecoveryTxLogicalRecordsTest.java    |   56 +-
 .../db/wal/WriteAheadLogManagerSelfTest.java       |  302 +++
 .../db/wal/crc/IgniteDataIntegrityTests.java       |    4 +-
 .../db/wal/reader/IgniteWalReaderTest.java         |    9 +-
 .../defragmentation/DefragmentationMXBeanTest.java |    1 -
 .../pagelocktracker/PageLockTrackerTestSuit.java   |    1 +
 .../pagelocktracker/log/PageLockLogTest.java       |    6 +-
 .../pagemem/BPlusTreePageMemoryImplTest.java       |    9 +-
 .../BPlusTreeReuseListPageMemoryImplTest.java      |    9 +-
 .../pagemem/ClockPageReplacementFlagsTest.java     |  119 +
 .../IgnitePageMemReplaceDelayedWriteUnitTest.java  |   12 +-
 .../pagemem/IgniteThrottlingUnitTest.java          |   10 +-
 .../pagemem/IndexStoragePageMemoryImplTest.java    |    9 +-
 .../persistence/pagemem/NoOpPageStoreManager.java  |    8 +-
 .../cache/persistence/pagemem/NoOpWALManager.java  |    5 +-
 .../pagemem/PageMemoryImplNoLoadTest.java          |    9 +-
 .../persistence/pagemem/PageMemoryImplTest.java    |   14 +-
 .../pagemem/PagesWriteThrottleSandboxTest.java     |    3 +-
 .../pagemem/PagesWriteThrottleSmokeTest.java       |   56 +-
 .../pagemem/SegmentedLruPageListTest.java          |  366 +++
 .../snapshot/AbstractSnapshotSelfTest.java         |   55 +-
 .../snapshot/IgniteClusterSnapshotCheckTest.java   |  542 +++++
 .../IgniteClusterSnapshotRestoreBaseTest.java      |  100 +
 .../IgniteClusterSnapshotRestoreSelfTest.java      |  770 ++++++
 .../snapshot/IgniteClusterSnapshotSelfTest.java    |   12 +-
 .../snapshot/IgniteSnapshotManagerSelfTest.java    |  187 +-
 .../IgniteSnapshotWithMetastorageTest.java         |  196 ++
 .../IgniteChangeGlobalStateCacheTest.java          |    4 +-
 .../IgniteChangeGlobalStateDataStructureTest.java  |    2 +
 .../IgniteChangeGlobalStateServiceTest.java        |    1 +
 .../IgniteChangeGlobalStateTest.java               |    1 +
 .../extended/GridActivateExtensionTest.java        |    2 +
 ...inActiveNodeToActiveClusterWithPersistence.java |    6 +-
 ...InActiveNodeToActiveClusterWithPersistence.java |    6 +-
 .../persistence/tree/io/TrackingPageIOTest.java    |    2 +-
 .../wal/AbstractWalDeltaConsistencyTest.java       |    2 +-
 .../wal/SegmentedRingByteBufferTest.java           |    4 +-
 .../persistence/wal/WalArchiveConsistencyTest.java |  273 +++
 .../wal/WalEnableDisableWithNodeShutdownTest.java  |  314 +++
 .../wal/WalEnableDisableWithRestartsTest.java      |  203 ++
 .../wal/memtracker/PageMemoryTracker.java          |    2 +-
 .../reader/StandaloneWalRecordsIteratorTest.java   |   38 +-
 .../cache/query/CacheDataPageScanQueryTest.java    |   10 +-
 .../cache/query/IndexingSpiQuerySelfTest.java      |    2 +-
 .../CacheContinuousQueryCounterAbstractTest.java   |    4 +-
 ...CacheContinuousQueryDeploymentToClientTest.java |  128 +
 ...cheContinuousQueryFailoverAbstractSelfTest.java |    9 +-
 .../CacheContinuousQueryRandomOperationsTest.java  |   28 +-
 ...CacheContinuousWithTransformerFailoverTest.java |   13 +-
 .../continuous/CacheKeepBinaryIterationTest.java   |    4 +-
 .../GridCacheContinuousQueryAbstractSelfTest.java  |   16 +-
 .../IgniteCacheContinuousQueryClientTest.java      |   45 +
 .../GridCacheWriteBehindStoreAbstractSelfTest.java |    2 +-
 ...iteBehindStorePartitionedMultiNodeSelfTest.java |    2 +-
 .../store/GridCacheWriteBehindStoreSelfTest.java   |    5 +-
 .../AbstractTransactionIntergrityTest.java         |   19 +-
 .../transactions/PartitionUpdateCounterTest.java   |    9 +-
 .../TxCrossCacheMapOnInvalidTopologyTest.java      |    5 +-
 .../cache/transactions/TxDeadlockCauseTest.java    |   11 +-
 .../TxDeadlockOnEntryToStringTest.java             |   24 +-
 .../cache/transactions/TxOnCachesStopTest.java     |    2 +-
 .../TxPartitionCounterStateConsistencyTest.java    |    6 +-
 ...ounterStateOnePrimaryTwoBackupsFailAllTest.java |    4 +-
 ...teOnePrimaryTwoBackupsHistoryRebalanceTest.java |  160 ++
 ...titionCounterStateOnePrimaryTwoBackupsTest.java |   21 +-
 ...titionCounterStateTwoPrimaryTwoBackupsTest.java |    7 +-
 .../TxRecoveryOnCoordniatorFailTest.java           |  116 +
 .../TxRecoveryWithConcurrentRollbackTest.java      |  140 +-
 .../cache/transactions/TxRollbackAsyncTest.java    |   14 +-
 .../TxRollbackOnTimeoutOnePhaseCommitTest.java     |    8 +-
 .../transactions/TxRollbackOnTimeoutTest.java      |  101 +-
 .../TxRollbackOnTopologyChangeTest.java            |    2 +-
 .../warmup/LoadAllWarmUpStrategySelfTest.java      |    3 +-
 .../processors/cluster/BaselineAutoAdjustTest.java |  219 +-
 .../cluster/ClusterNameBeforeActivation.java       |  106 +
 .../processors/database/BPlusTreeSelfTest.java     |   24 +-
 .../processors/database/CacheFreeListSelfTest.java |    9 +-
 .../database/DataRegionMetricsSelfTest.java        |   10 +-
 .../database/IgniteDbMemoryLeakAbstractTest.java   |    5 +-
 .../DataStreamerCommunicationSpiExceptionTest.java |  143 ++
 .../IgniteDataStreamerPerformanceTest.java         |    2 +-
 .../diagnostic/DiagnosticProcessorTest.java        |  313 ++-
 .../failure/FailureProcessorLoggingTest.java       |    4 +-
 .../DurableBackgroundTasksProcessorSelfTest.java   |  523 ++++
 .../localtask/ObservingCheckpointListener.java     |  128 +
 .../internal/processors/localtask/SimpleTask.java  |  102 +
 .../IgniteMessagingConfigVariationFullApiTest.java |    6 +-
 .../DistributedMetaStorageClassloadingTest.java    |  205 ++
 .../DistributedMetaStoragePersistentTest.java      |    2 +-
 .../metastorage/DistributedMetaStorageTest.java    |   48 +-
 .../persistence/DmsDataWriterWorkerTest.java       |   43 +-
 .../AbstractPerformanceStatisticsTest.java         |   58 +-
 .../performancestatistics/CheckpointTest.java      |  228 ++
 .../PerformanceStatisticsRotateFileTest.java       |  118 +
 .../processors/query/DummyQueryIndexing.java       |   55 +-
 .../cache/GridCacheMetadataCommandTest.java        |  113 +
 .../client/ThinClientPermissionCheckTest.java      |    9 +-
 .../client/ThinClientSslPermissionCheckTest.java   |    7 +-
 .../compute/ComputePermissionCheckTest.java        |    2 +-
 ...ridServiceDeploymentCompoundFutureSelfTest.java |    3 +-
 .../ServiceDeploymentProcessIdSelfTest.java        |    6 +-
 .../internal/sql/SqlParserCreateIndexSelfTest.java |   68 +-
 .../internal/sql/SqlParserKillQuerySelfTest.java   |    6 +-
 .../ignite/internal/util/GridArraysSelfTest.java   |   20 +-
 .../ignite/internal/util/GridMutableLongTest.java  |   61 +
 .../ignite/internal/util/HostAndPortRangeTest.java |  181 ++
 .../util/IgniteUtilsWorkDirectoryTest.java         |    3 +-
 .../internal/util/collection/IntHashMapTest.java   |   27 +
 .../util/future/IgniteCacheFutureImplTest.java     |    2 +-
 .../util/nio/impl/GridNioFilterChainSelfTest.java  |   14 +-
 .../GridOffHeapMapPerformanceAbstractTest.java     |    2 +-
 .../GridOffHeapPartitionedMapAbstractSelfTest.java |    2 -
 .../util/tostring/GridToStringBuilderSelfTest.java |    2 +-
 .../GridBoundedConcurrentOrderedMapSelfTest.java   |    4 +-
 .../loadtests/colocation/GridTestCacheStore.java   |    3 +-
 .../communication/GridIoManagerBenchmark0.java     |    3 +
 .../GridContinuousOperationsLoadTest.java          |   10 +-
 .../ignite/loadtests/job/GridJobLoadTest.java      |    3 +-
 .../lang/GridConcurrentLinkedHashMapBenchmark.java |   11 +-
 .../marshaller/GridMarshallerAbstractTest.java     |    2 +-
 .../marshaller/MarshallerContextTestImpl.java      |    7 +-
 .../ignite/messaging/GridMessagingSelfTest.java    |   12 +-
 .../messaging/IgniteMessagingSendAsyncTest.java    |    2 +-
 ...2PContinuousDeploymentClientDisconnectTest.java |  344 +++
 .../ignite/p2p/GridP2PLocalDeploymentSelfTest.java |    2 +-
 .../java/org/apache/ignite/p2p/GridP2PTestJob.java |    2 +-
 .../apache/ignite/p2p/GridP2PUndeploySelfTest.java |   41 +-
 .../java/org/apache/ignite/platform/Address.java   |   47 -
 .../org/apache/ignite/platform/Department.java     |   34 -
 .../java/org/apache/ignite/platform/Employee.java  |   47 -
 .../test/java/org/apache/ignite/platform/Key.java  |   51 -
 .../platform/PlatformComputeEchoArgTask.java       |   60 +
 .../ignite/platform/PlatformComputeEchoTask.java   |   14 +
 .../PlatformCustomBinaryBasicNameMapper.java       |   35 +
 .../platform/PlatformCustomBinaryNameMapper.java   |   35 +
 .../ignite/platform/PlatformDeployServiceTask.java |  127 +
 .../platform/PlatformEventsWriteEventTask.java     |    2 +-
 .../ignite/platform/PlatformTestExecutor.java      |   30 +
 .../ignite/platform/PlatformThreadUtils.java       |    9 +
 .../java/org/apache/ignite/platform/Value.java     |   51 -
 .../java/org/apache/ignite/platform/model/ACL.java |   23 +
 .../org/apache/ignite/platform/model/Account.java  |   71 +
 .../org/apache/ignite/platform/model/Address.java  |   47 +
 .../apache/ignite/platform/model/Department.java   |   34 +
 .../org/apache/ignite/platform/model/Employee.java |   47 +
 .../java/org/apache/ignite/platform/model/Key.java |   51 +
 .../apache/ignite/platform/model/ParamValue.java   |   43 +
 .../apache/ignite/platform/model/Parameter.java    |   43 +
 .../org/apache/ignite/platform/model/Role.java     |   39 +
 .../org/apache/ignite/platform/model/User.java     |   67 +
 .../java/org/apache/ignite/platform/model/V1.java  |   34 +
 .../java/org/apache/ignite/platform/model/V2.java  |   34 +
 .../java/org/apache/ignite/platform/model/V3.java  |   34 +
 .../java/org/apache/ignite/platform/model/V4.java  |   34 +
 .../org/apache/ignite/platform/model/Value.java    |   51 +
 .../session/GridSessionWaitAttributeSelfTest.java  |    5 +-
 ...unicationInverseConnectionEstablishingTest.java |   67 +-
 .../tcp/GridTcpCommunicationSpiConfigSelfTest.java |  158 ++
 .../tcp/GridTcpCommunicationSpiLogTest.java        |    5 +-
 ...municationSpiSkipWaitHandshakeOnClientTest.java |    2 +-
 .../IgniteTcpCommunicationConnectOnInitTest.java   |   32 +-
 .../tcp/TcpCommunicationHandshakeTimeoutTest.java  |  151 ++
 .../tcp/TcpCommunicationSpiDropNodesTest.java      |    2 +-
 ...cpCommunicationSpiHalfOpenedConnectionTest.java |   76 +-
 .../tcp/TcpCommunicationStatisticsTest.java        |    7 +-
 .../local/GridLocalDeploymentSpiSelfTest.java      |   54 +-
 .../discovery/DiscoverySpiDataExchangeTest.java    |  267 +++
 .../FilterDataForClientNodeDiscoveryTest.java      |    4 +-
 .../spi/discovery/tcp/IgniteClientConnectTest.java |    8 +-
 ...cpClientDiscoverySpiFailureTimeoutSelfTest.java |    9 +-
 .../tcp/TcpClientDiscoverySpiSelfTest.java         |   18 +-
 .../tcp/TcpClientDiscoveryUnresolvedHostTest.java  |    2 +-
 .../tcp/TcpDiscoveryCoordinatorFailureTest.java    |   11 +-
 .../tcp/TcpDiscoveryIpFinderFailureTest.java       |  399 ++++
 .../tcp/TcpDiscoveryNodeJoinAndFailureTest.java    |   10 +-
 .../TcpDiscoveryPendingMessageDeliveryTest.java    |    3 +-
 .../tcp/TcpDiscoverySslParametersTest.java         |    7 +-
 .../tcp/TcpDiscoveryWithAddressFilterTest.java     |   86 +
 .../tcp/TcpDiscoveryWithWrongServerTest.java       |   20 +-
 .../spi/discovery/tcp/TestDynamicIpFinder.java     |   55 +
 .../vm/TcpDiscoveryVmIpFinderDnsResolveTest.java   |  631 +++++
 .../GridInternalTasksLoadBalancingSelfTest.java    |    3 +-
 .../ignite/spi/metric/jmx/DummyMBeanServer.java    |    7 +-
 .../startup/servlet/GridServletLoaderTest.java     |    3 +-
 .../ignite/testframework/GridSpiTestContext.java   |   14 +
 .../apache/ignite/testframework/GridTestUtils.java |   40 +-
 .../testframework/junits/GridAbstractTest.java     |   77 +-
 .../testframework/junits/IgniteTestResources.java  |    6 +-
 .../junits/common/GridCommonAbstractTest.java      |  137 +-
 .../testframework/test/VariationsIteratorTest.java |   10 +-
 .../testframework/wal/record/RecordUtils.java      |    3 +-
 .../ignite/testsuites/IgniteBasicTestSuite.java    |   18 +
 .../IgniteBasicWithPersistenceTestSuite.java       |   18 +-
 .../testsuites/IgniteBinaryCacheTestSuite.java     |   12 +-
 .../testsuites/IgniteBinaryObjectsTestSuite.java   |   15 +-
 .../IgniteCacheDataStructuresSelfTestSuite.java    |   13 +-
 .../testsuites/IgniteCacheFailoverTestSuite2.java  |    6 +-
 .../IgniteCacheFullApiSelfTestSuite.java           |    3 +-
 .../testsuites/IgniteCacheMvccTestSuite1.java      |    2 +
 .../testsuites/IgniteCacheMvccTestSuite2.java      |    5 +-
 .../testsuites/IgniteCacheMvccTestSuite5.java      |    4 +
 .../testsuites/IgniteCacheMvccTestSuite6.java      |    6 +-
 .../testsuites/IgniteCacheMvccTestSuite7.java      |    4 +-
 .../testsuites/IgniteCacheRestartTestSuite.java    |    5 +-
 .../testsuites/IgniteCacheRestartTestSuite2.java   |    4 +-
 .../ignite/testsuites/IgniteCacheTestSuite.java    |   25 +-
 .../ignite/testsuites/IgniteCacheTestSuite2.java   |    5 +
 .../ignite/testsuites/IgniteCacheTestSuite3.java   |   15 +-
 .../ignite/testsuites/IgniteCacheTestSuite5.java   |    9 +-
 .../ignite/testsuites/IgniteCacheTestSuite6.java   |   13 +-
 .../ignite/testsuites/IgniteCacheTestSuite9.java   |    7 +
 .../testsuites/IgniteClientReconnectTestSuite.java |    2 +
 .../testsuites/IgniteKernalSelfTestSuite.java      |    4 +-
 .../ignite/testsuites/IgniteP2PSelfTestSuite.java  |    8 +-
 .../ignite/testsuites/IgnitePdsMvccTestSuite.java  |    2 +
 .../ignite/testsuites/IgnitePdsTestSuite.java      |   14 +
 .../ignite/testsuites/IgnitePdsTestSuite2.java     |   11 +-
 .../ignite/testsuites/IgnitePdsTestSuite4.java     |    4 +
 .../testsuites/IgniteRestHandlerTestSuite.java     |    2 +
 .../IgniteSpiCommunicationSelfTestSuite.java       |    2 +
 .../IgniteSpiDiscoverySelfTestSuite.java           |   13 +-
 .../testsuites/IgniteStandByClusterSuite.java      |   12 +-
 .../ignite/testsuites/IgniteUtilSelfTestSuite.java |    7 +-
 .../apache/ignite/util/GridLongListSelfTest.java   |   10 +-
 ...mandHandlerClusterByClassTest_cache_help.output |    4 +-
 ...ridCommandHandlerClusterByClassTest_help.output |   20 +-
 ...dlerClusterByClassWithSSLTest_cache_help.output |    4 +-
 ...andHandlerClusterByClassWithSSLTest_help.output |   20 +-
 modules/dev-utils/ignite-modules-test/build.gradle |    2 +-
 modules/dev-utils/pom.xml                          |    2 +-
 .../ignite/development/utils/DataEntryWrapper.java |  120 +-
 .../development/utils/IgniteWalConverter.java      |  234 +-
 .../utils/IgniteWalConverterArguments.java         |  626 +++++
 .../utils/MetastoreDataRecordWrapper.java          |   13 +-
 .../development/utils/DevUtilsTestSuite.java       |    2 +
 .../utils/IgniteWalConverterArgumentsTest.java     |  570 +++++
 .../utils/IgniteWalConverterSensitiveDataTest.java |   69 +-
 .../development/utils/IgniteWalConverterTest.java  |  606 +++++
 .../apache/ignite/development/utils/Person.java    |   65 +
 .../apache/ignite/development/utils/PersonEx.java  |   79 +
 .../apache/ignite/development/utils/PersonKey.java |   61 +
 modules/direct-io/pom.xml                          |   15 +-
 .../cache/persistence/file/IgniteNativeIoLib.java  |    3 +-
 .../testsuites/IgnitePdsNativeIoTestSuite.java     |    2 +
 modules/extdata/p2p/pom.xml                        |    2 +-
 .../ignite/tests/p2p/AlwaysTruePredicate.java      |    2 +-
 ...dP2PEventRemoteFilterWithStaticInitializer.java |   34 +
 ...MessageRemoteListenerWithStaticInitializer.java |   34 +
 .../GridP2PRemoteFilterWithStaticInitializer.java  |   36 +
 ...2PRemoteFilterWithStaticInitializerFactory.java |   31 +
 ...dP2PRemoteTransformerWithStaticInitializer.java |   34 +
 ...oteTransformerWithStaticInitializerFactory.java |   33 +
 ...ializableRemoteFilterWithStaticInitializer.java |   35 +
 .../GridP2PTestObjectWithStaticInitializer.java    |   36 +
 .../tests/p2p/compute/ExternalEntryProcessor.java  |   44 +
 modules/extdata/platform/pom.xml                   |    2 +-
 modules/extdata/uri/modules/uri-dependency/pom.xml |    2 +-
 modules/extdata/uri/pom.xml                        |    2 +-
 modules/gce/pom.xml                                |   10 +-
 modules/geospatial/pom.xml                         |    4 +-
 .../processors/query/h2/opt/GeoSpatialIndex.java   |   65 +
 .../query/h2/opt/GeoSpatialIndexDefinition.java    |   58 +
 .../query/h2/opt/GeoSpatialIndexFactory.java       |   69 +
 .../query/h2/opt/GeoSpatialIndexImpl.java          |  395 ++++
 .../processors/query/h2/opt/GeoSpatialUtils.java   |   71 +
 .../processors/query/h2/opt/GeometryIndexKey.java  |   49 +
 .../query/h2/opt/GridH2SpatialIndex.java           |  371 +--
 modules/hibernate-4.2/pom.xml                      |    3 +-
 modules/hibernate-5.1/pom.xml                      |    3 +-
 .../cache/hibernate/HibernateEntityRegion.java     |    9 +-
 modules/hibernate-5.3/pom.xml                      |    3 +-
 .../hibernate/IgniteCachedDomainDataAccess.java    |   15 +-
 .../cache/hibernate/IgniteEntityDataAccess.java    |    9 +-
 .../cache/hibernate/IgniteNaturalIdDataAccess.java |    7 +-
 .../HibernateL2CacheConfigurationSelfTest.java     |   10 +-
 .../HibernateL2CacheStrategySelfTest.java          |   10 +-
 modules/hibernate-core/pom.xml                     |   11 +-
 .../cache/hibernate/HibernateCacheProxy.java       |    4 +-
 modules/ignored-tests/pom.xml                      |    2 +-
 modules/indexing/pom.xml                           |   12 +-
 .../cache/query/GridCacheTwoStepQuery.java         |   15 +-
 .../processors/query/h2/CommandProcessor.java      |   22 +-
 .../processors/query/h2/ConnectionManager.java     |   13 +
 .../h2/DurableBackgroundCleanupIndexTreeTask.java  |  195 --
 .../query/h2/H2JavaObjectSerializer.java           |   27 +-
 .../internal/processors/query/h2/H2RowCache.java   |  163 --
 .../processors/query/h2/H2RowCacheRegistry.java    |  132 --
 .../processors/query/h2/H2SqlFieldMetadata.java    |   11 +-
 .../processors/query/h2/H2TableDescriptor.java     |   22 +-
 .../processors/query/h2/H2TableEngine.java         |   11 +-
 .../internal/processors/query/h2/H2Utils.java      |   45 +-
 .../processors/query/h2/IgniteH2Indexing.java      |  460 ++--
 .../query/h2/IndexRebuildFullClosure.java          |   49 -
 .../query/h2/IndexRebuildPartialClosure.java       |   91 -
 .../processors/query/h2/QueryDescriptor.java       |   14 +-
 .../internal/processors/query/h2/QueryParser.java  |    8 +-
 .../processors/query/h2/SchemaManager.java         |   16 +-
 .../query/h2/database/H2PkHashIndex.java           |   53 +-
 .../processors/query/h2/database/H2Tree.java       |  928 --------
 .../query/h2/database/H2TreeClientIndex.java       |   47 +-
 .../query/h2/database/H2TreeFilterClosure.java     |  141 --
 .../processors/query/h2/database/H2TreeIndex.java  |  622 +----
 .../query/h2/database/H2TreeIndexBase.java         |   92 -
 .../query/h2/database/InlineIndexColumn.java       |  101 -
 .../inlinecolumn/AbstractInlineIndexColumn.java    |  246 --
 .../inlinecolumn/BooleanInlineIndexColumn.java     |   68 -
 .../inlinecolumn/ByteInlineIndexColumn.java        |   68 -
 .../inlinecolumn/BytesInlineIndexColumn.java       |  148 --
 .../inlinecolumn/DateInlineIndexColumn.java        |   69 -
 .../inlinecolumn/DoubleInlineIndexColumn.java      |   68 -
 .../inlinecolumn/FixedStringInlineIndexColumn.java |   39 -
 .../inlinecolumn/FloatInlineIndexColumn.java       |   68 -
 .../inlinecolumn/InlineIndexColumnFactory.java     |  238 --
 .../inlinecolumn/IntegerInlineIndexColumn.java     |   68 -
 .../inlinecolumn/LongInlineIndexColumn.java        |   68 -
 .../inlinecolumn/ObjectBytesInlineIndexColumn.java |   40 -
 .../inlinecolumn/ObjectHashInlineIndexColumn.java  |  175 --
 .../inlinecolumn/ShortInlineIndexColumn.java       |   68 -
 .../StringIgnoreCaseInlineIndexColumn.java         |   39 -
 .../inlinecolumn/StringInlineIndexColumn.java      |  311 ---
 .../inlinecolumn/TimeInlineIndexColumn.java        |   69 -
 .../inlinecolumn/TimestampInlineIndexColumn.java   |   83 -
 .../inlinecolumn/UuidInlineIndexColumn.java        |   81 -
 .../h2/database/io/AbstractH2ExtrasInnerIO.java    |  169 --
 .../h2/database/io/AbstractH2ExtrasLeafIO.java     |  166 --
 .../query/h2/database/io/AbstractH2InnerIO.java    |   79 -
 .../query/h2/database/io/AbstractH2LeafIO.java     |   81 -
 .../query/h2/database/io/H2ExtrasInnerIO.java      |   33 -
 .../query/h2/database/io/H2ExtrasLeafIO.java       |   32 -
 .../processors/query/h2/database/io/H2IOUtils.java |   92 -
 .../processors/query/h2/database/io/H2InnerIO.java |   37 -
 .../processors/query/h2/database/io/H2LeafIO.java  |   37 -
 .../query/h2/database/io/H2MvccExtrasInnerIO.java  |   55 -
 .../query/h2/database/io/H2MvccExtrasLeafIO.java   |   54 -
 .../query/h2/database/io/H2MvccInnerIO.java        |   58 -
 .../query/h2/database/io/H2MvccLeafIO.java         |   58 -
 .../query/h2/database/io/H2RowLinkIO.java          |   69 -
 .../defragmentation/IndexingDefragmentation.java   |  482 ----
 .../processors/query/h2/dml/DmlAstUtils.java       |    2 +-
 .../processors/query/h2/index/H2RowComparator.java |  135 ++
 .../query/h2/index/QueryIndexDefinition.java       |  206 ++
 .../h2/index/QueryIndexKeyDefinitionProvider.java  |   80 +
 .../query/h2/index/QueryIndexRowHandler.java       |  172 ++
 .../query/h2/index/QueryRowHandlerFactory.java     |   48 +
 .../h2/index/client/ClientIndexDefinition.java     |   79 +
 .../query/h2/index/client/ClientIndexFactory.java  |   57 +
 .../query/h2/index/client/ClientInlineIndex.java   |  153 ++
 .../query/h2/index/keys/DateIndexKey.java          |   58 +
 .../query/h2/index/keys/H2ValueWrapperMixin.java   |   44 +
 .../query/h2/index/keys/TimeIndexKey.java          |   58 +
 .../query/h2/index/keys/TimestampIndexKey.java     |   63 +
 .../processors/query/h2/opt/GridH2IndexBase.java   |    5 +-
 .../processors/query/h2/opt/GridH2MetaTable.java   |    2 +-
 .../processors/query/h2/opt/GridH2ProxyIndex.java  |    9 +-
 .../processors/query/h2/opt/GridH2Table.java       |  210 +-
 .../processors/query/h2/opt/H2CacheRow.java        |    2 +-
 .../internal/processors/query/h2/opt/H2Row.java    |    3 +-
 .../query/h2/opt/join/CollocationModel.java        |    2 +-
 .../query/h2/opt/join/DistributedJoinContext.java  |    2 +-
 .../query/h2/opt/join/DistributedLookupBatch.java  |    2 +-
 .../processors/query/h2/opt/join/RangeSource.java  |   12 +-
 .../processors/query/h2/sql/GridSqlConst.java      |    5 +
 .../query/h2/sql/GridSqlCreateTable.java           |    4 +-
 .../processors/query/h2/sql/GridSqlDelete.java     |   10 +-
 .../processors/query/h2/sql/GridSqlInsert.java     |   18 +-
 .../processors/query/h2/sql/GridSqlJoin.java       |    8 +-
 .../processors/query/h2/sql/GridSqlMerge.java      |   16 +-
 .../processors/query/h2/sql/GridSqlQuery.java      |    4 +-
 .../query/h2/sql/GridSqlQuerySplitter.java         |   19 +-
 .../processors/query/h2/sql/GridSqlSelect.java     |   16 +-
 .../processors/query/h2/sql/GridSqlUnion.java      |   14 +-
 .../processors/query/h2/sql/GridSqlUpdate.java     |   12 +-
 .../processors/query/h2/sql/SplitterUtils.java     |   29 +
 .../query/h2/twostep/AbstractReducer.java          |    4 +-
 .../query/h2/twostep/GridMapQueryExecutor.java     |   60 +-
 .../query/h2/twostep/GridReduceQueryExecutor.java  |   14 +-
 .../h2/twostep/PartitionReservationManager.java    |   10 +
 .../processors/query/h2/twostep/ReduceIndex.java   |    4 +-
 .../query/h2/twostep/ReducePartitionMapper.java    |   10 +-
 .../query/h2/twostep/SortedReduceIndexAdapter.java |   36 +
 .../query/h2/twostep/UnsortedBaseReducer.java      |  108 +
 .../query/h2/twostep/UnsortedOneWayReducer.java    |  118 +
 .../query/h2/twostep/UnsortedReducer.java          |   81 +-
 .../query/h2/twostep/msg/GridH2QueryRequest.java   |   11 +-
 .../visor/verify/ValidateIndexesClosure.java       |  263 ++-
 .../visor/verify/ValidateIndexesContext.java       |   30 +
 .../visor/verify/VisorValidateIndexesTask.java     |   18 +
 .../org/apache/ignite/client/ClientTestSuite.java  |    2 +
 .../apache/ignite/client/FunctionalQueryTest.java  |    3 +-
 ...finityKeyNameAndValueFieldNameConflictTest.java |    3 +-
 .../cache/BinaryTypeMismatchLoggingTest.java       |    5 +-
 .../CacheGroupMetricsWithIndexBuildFailTest.java   |   22 +-
 .../cache/CacheGroupMetricsWithIndexTest.java      |  204 +-
 .../cache/CacheRegisterMetadataLocallyTest.java    |    4 +-
 ...eckIndexesInlineSizeOnNodeJoinMultiJvmTest.java |   13 +-
 .../cache/GridCacheCrossCacheQuerySelfTest.java    |    4 +-
 .../cache/GridCacheDynamicLoadOnClientTest.java    |    4 +-
 .../processors/cache/GridCacheOffHeapSelfTest.java |    2 +-
 .../cache/GridCacheQuerySimpleBenchmark.java       |    7 +-
 .../cache/GridIndexingWithNoopSwapSelfTest.java    |    2 +-
 .../IgniteCacheAbstractFieldsQuerySelfTest.java    |   17 +-
 .../cache/IgniteCacheAbstractQuerySelfTest.java    |    9 +-
 .../cache/IgniteCacheCollocatedQuerySelfTest.java  |    8 +-
 ...teCacheConfigurationPrimitiveTypesSelfTest.java |    3 +-
 .../cache/IgniteCacheDistributedJoinTest.java      |   12 +-
 .../IgniteCacheFieldsQueryNoDataSelfTest.java      |    2 +-
 ...gniteCacheJoinPartitionedAndReplicatedTest.java |   64 +-
 .../cache/IgniteCacheLargeResultSelfTest.java      |    2 +-
 .../cache/IgniteCacheOffheapEvictQueryTest.java    |    4 +-
 .../cache/IgniteCacheOffheapIndexScanTest.java     |    2 +-
 .../IgniteCacheParallelismQuerySortOrderTest.java  |  257 ++
 .../cache/IgniteCacheQueryLoadSelfTest.java        |    2 +-
 .../IgniteCacheQueryMultiThreadedSelfTest.java     |    2 +-
 .../IgniteCacheSqlInsertValidationSelfTest.java    |   47 +-
 .../IgniteCacheSqlQueryMultiThreadedSelfTest.java  |    2 +-
 .../cache/IgniteDynamicSqlRestoreTest.java         |    3 +-
 .../QueryJoinWithDifferentNodeFiltersTest.java     |    4 +-
 .../authentication/SqlUserCommandSelfTest.java     |   55 +-
 ...heClientQueryReplicatedNodeRestartSelfTest.java |    8 +-
 .../near/IgniteCacheQueryNodeRestartSelfTest.java  |    2 +-
 .../near/IgniteCacheQueryNodeRestartSelfTest2.java |    2 +-
 .../encryption/EncryptedSqlTemplateTableTest.java  |   79 +
 .../cache/index/AbstractIndexingCommonTest.java    |   11 +-
 .../processors/cache/index/BasicIndexTest.java     |   60 +-
 .../index/ComplexSecondaryKeyUnwrapSelfTest.java   |    2 +
 .../DynamicEnableIndexingConcurrentSelfTest.java   |   21 +-
 .../index/DynamicIndexAbstractBasicSelfTest.java   |    2 +-
 .../cache/index/ForceRebuildIndexTest.java         |  317 +++
 .../cache/index/H2ConnectionLeaksSelfTest.java     |    2 +-
 .../cache/index/H2DynamicTableSelfTest.java        |    2 +-
 .../cache/index/H2RowCachePageEvictionTest.java    |   14 +-
 .../processors/cache/index/H2RowCacheSelfTest.java |   26 +-
 .../cache/index/H2RowExpireTimeIndexSelfTest.java  |    6 +-
 .../index/H2TreeCorruptedTreeExceptionTest.java    |    5 +-
 .../cache/index/IgniteDecimalSelfTest.java         |    2 +-
 .../processors/cache/index/IndexMetricsTest.java   |   16 +-
 .../cache/index/IndexesRebuildTaskEx.java          |  207 ++
 .../cache/index/QueryEntityValidationSelfTest.java |    6 +-
 .../cache/index/SqlTransactionsSelfTest.java       |    2 +
 .../cache/index/StopRebuildIndexTest.java          |  311 +++
 ...niteCacheLocalQueryCancelOrTimeoutSelfTest.java |   77 +-
 ...acheMvccAbstractSqlCoordinatorFailoverTest.java |   10 +-
 .../cache/mvcc/CacheMvccBackupsAbstractTest.java   |    6 +-
 .../mvcc/CacheMvccBasicContinuousQueryTest.java    |    9 +-
 ...eMvccPartitionedSqlCoordinatorFailoverTest.java |   10 +-
 .../CacheMvccSqlConfigurationValidationTest.java   |    7 +-
 .../mvcc/CacheMvccSqlQueriesAbstractTest.java      |    8 +-
 .../cache/mvcc/CacheMvccSqlTxModesTest.java        |    2 +-
 .../mvcc/CacheMvccSqlTxQueriesAbstractTest.java    |    9 +-
 ...cheMvccSqlTxQueriesWithReducerAbstractTest.java |   38 +-
 .../cache/mvcc/MvccRepeatableReadBulkOpsTest.java  |    2 +-
 .../IgnitePdsIndexingDefragmentationTest.java      |   34 +-
 ...xingMultithreadedLoadContinuousRestartTest.java |    4 +-
 .../db/LongDestroyDurableBackgroundTaskTest.java   |  250 +-
 .../MultipleParallelCacheDeleteDeadlockTest.java   |  157 +-
 .../persistence/db/wal/IgniteWalRecoveryTest.java  |    3 +-
 .../IgniteClusterSnapshotCheckWithIndexesTest.java |  127 +
 ...niteClusterSnapshotRestoreWithIndexingTest.java |  211 ++
 .../IgniteClusterSnapshotWithIndexesTest.java      |    3 +-
 .../IgniteDbSingleNodeWithIndexingPutGetTest.java  |   14 +-
 .../processors/database/RebuildIndexTest.java      |    2 +-
 .../RebuildIndexWithHistoricalRebalanceTest.java   |    7 +-
 ...ngingBaselineCacheQueryNodeRestartSelfTest.java |    5 +-
 ...ableBaselineCacheQueryNodeRestartsSelfTest.java |    5 +-
 .../PerformanceStatisticsQueryTest.java            |    4 +-
 .../CleanupIndexTreeCheckpointFailoverTest.java    |  127 +
 .../query/IgniteCacheGroupsCompareQueryTest.java   |    2 +-
 .../query/IgniteSqlKeyValueFieldsTest.java         |    3 +-
 .../query/IgniteSqlParameterizedQueryTest.java     |    2 +-
 .../processors/query/IgniteSqlRoutingTest.java     |    2 +-
 .../query/IgniteSqlSplitterSelfTest.java           |   35 +-
 .../query/KillQueryOnClientDisconnectTest.java     |   11 +-
 .../processors/query/LocalQueryLazyTest.java       |    4 +-
 .../query/MemLeakOnSqlWithClientReconnectTest.java |    2 +-
 .../processors/query/ReducerRowsBufferTest.java    |  114 +
 .../query/RemoveConstantsFromQueryTest.java        |  235 ++
 .../processors/query/RunningQueriesTest.java       |    2 +-
 .../query/SqlFieldTypeValidationTypesTest.java     |   12 +-
 .../processors/query/SqlSystemViewsSelfTest.java   |   53 +-
 .../query/WrongQueryEntityFieldTypeTest.java       |    3 +
 .../query/h2/GridIndexRebuildSelfTest.java         |   31 +-
 .../h2/GridSubqueryJoinOptimizerSelfTest.java      |   54 +
 .../H2ResultSetIteratorNullifyOnEndSelfTest.java   |    5 +-
 .../query/h2/IgniteSqlQueryMinMaxTest.java         |   70 +-
 .../processors/query/h2/QueryDataPageScanTest.java |   38 +-
 .../inlinecolumn/InlineIndexColumnTest.java        |  258 +-
 .../query/h2/sql/AbstractH2CompareQueryTest.java   |    6 +-
 .../query/h2/sql/BaseH2CompareQueryTest.java       |   17 +-
 .../query/h2/sql/GridQueryParsingTest.java         |    4 +-
 .../query/h2/sql/H2CompareBigQueryTest.java        |   16 +-
 .../DisappearedCacheCauseRetryMessageSelfTest.java |    5 +-
 ...neOrSinglePartitionsQueryOptimizationsTest.java |    4 +-
 .../h2/twostep/RetryCauseMessageSelfTest.java      |    9 +-
 .../h2/twostep/TableViewSubquerySelfTest.java      |    2 +-
 .../ReplicatedSqlCustomPartitionsTest.java         |   76 +
 .../apache/ignite/sqltests/ReplicatedSqlTest.java  |   43 +-
 .../IgniteBinaryCacheQueryTestSuite.java           |   22 +-
 .../IgniteBinaryCacheQueryTestSuite2.java          |    3 +
 .../testsuites/IgniteCacheMvccSqlTestSuite.java    |    3 +-
 .../testsuites/IgniteCacheQuerySelfTestSuite6.java |    5 +-
 ...teCacheWithIndexingAndPersistenceTestSuite.java |    4 +-
 .../IgnitePdsWithIndexingCoreTestSuite.java        |    2 +
 .../testsuites/IgnitePdsWithIndexingTestSuite.java |   10 +-
 modules/jcl/pom.xml                                |   12 +-
 modules/jta/pom.xml                                |   12 +-
 modules/kubernetes/DEVNOTES.md                     |   69 +
 modules/kubernetes/DEVNOTES.txt                    |   69 -
 modules/kubernetes/{README.txt => README.md}       |    0
 modules/kubernetes/config/Dockerfile               |   18 +-
 .../config/example-kube-persistence-and-wal.xml    |    9 +-
 .../kubernetes/config/example-kube-persistence.xml |    9 +-
 modules/kubernetes/config/example-kube-rbac.xml    |   10 +-
 modules/kubernetes/config/example-kube.xml         |    5 +-
 modules/kubernetes/pom.xml                         |   14 +-
 .../ignite/client/TestClusterClientConnection.java |  157 --
 .../discovery/KubernetesDiscoveryAbstractTest.java |  151 ++
 .../discovery/TestClusterClientConnection.java     |   52 +
 .../TestKubernetesIpFinderDisconnection.java       |  123 +
 .../testsuites/IgniteKubernetesTestSuite.java      |    4 +-
 modules/log4j/pom.xml                              |   13 +-
 modules/log4j2/pom.xml                             |   12 +-
 modules/mesos/pom.xml                              |   12 +-
 modules/ml/catboost-model-parser/pom.xml           |   11 +-
 modules/ml/h2o-model-parser/pom.xml                |   11 +-
 modules/ml/pom.xml                                 |   11 +-
 modules/ml/spark-model-parser/pom.xml              |   12 +-
 .../ml/sparkmodelparser/SparkModelParser.java      |    5 +-
 .../ml/sparkmodelparser/SparkModelParserTest.java  |    5 +-
 .../ignite/ml/clustering/kmeans/KMeansModel.java   |    6 +-
 .../ignite/ml/composition/ModelsComposition.java   |    4 +-
 .../ml/composition/bagging/BaggedTrainer.java      |    4 +-
 .../apache/ignite/ml/dataset/DatasetBuilder.java   |    2 +-
 .../bootstrapping/BootstrappedDatasetBuilder.java  |    2 +-
 .../ml/dataset/impl/cache/CacheBasedDataset.java   |    3 +-
 .../impl/cache/CacheBasedDatasetBuilder.java       |   14 +-
 .../ml/dataset/impl/local/LocalDatasetBuilder.java |    5 +-
 .../ignite/ml/environment/logging/MLLogger.java    |    2 +-
 .../ignite/ml/knn/ann/ANNClassificationModel.java  |    6 +-
 .../ml/knn/ann/ANNClassificationTrainer.java       |    9 +-
 .../preprocessing/IllegalFeatureTypeException.java |    3 +-
 .../preprocessing/IllegalLabelTypeException.java   |    3 +-
 .../ignite/ml/multiclass/MultiClassModel.java      |    3 +-
 .../ignite/ml/multiclass/OneVsRestTrainer.java     |    3 +-
 .../compound/CompoundNaiveBayesTrainer.java        |   12 +-
 .../apache/ignite/ml/nn/MultilayerPerceptron.java  |    3 +-
 .../updatecalculators/SimpleGDParameterUpdate.java |    3 +-
 .../ml/preprocessing/PreprocessingTrainer.java     |    2 +-
 .../ml/preprocessing/encoding/EncoderTrainer.java  |    4 +-
 .../onehotencoder/OneHotEncoderPreprocessor.java   |    6 +-
 .../stringencoder/StringEncoderPreprocessor.java   |    3 +-
 .../preprocessing/imputing/ImputingStrategy.java   |    5 +-
 .../normalization/NormalizationPreprocessor.java   |    2 +-
 .../linear/LinearRegressionLSQRTrainer.java        |    3 +-
 .../linear/LinearRegressionSGDTrainer.java         |    3 +-
 .../logistic/LogisticRegressionSGDTrainer.java     |    3 +-
 .../ml/selection/cv/AbstractCrossValidation.java   |    3 +-
 ...assificationPointwiseMetricStatsAggregator.java |    3 +-
 .../ClassificationMetricsAggregator.java           |    3 +-
 .../RegressionMetricStatsAggregator.java           |    3 +-
 .../BinaryClassificationEvaluationContext.java     |    3 +-
 .../classification/BinaryClassificationMetric.java |    3 +-
 .../selection/split/TrainTestDatasetSplitter.java  |    2 +-
 .../split/mapper/SHA256UniformMapper.java          |    2 +-
 .../ml/svm/SVMLinearClassificationTrainer.java     |    3 +-
 .../ml/trainers/AdaptableDatasetTrainer.java       |   15 +-
 .../apache/ignite/ml/trainers/DatasetTrainer.java  |    9 +-
 .../java/org/apache/ignite/ml/tree/NodeData.java   |    8 +-
 .../ignite/ml/util/genetic/GeneticAlgorithm.java   |    3 +-
 .../test/java/org/apache/ignite/ml/TestUtils.java  |    6 +-
 .../ignite/ml/clustering/KMeansTrainerTest.java    |    3 +-
 .../apache/ignite/ml/common/LocalModelsTest.java   |    9 +-
 .../ml/composition/CompositionTestSuite.java       |    6 +-
 .../ml/composition/boosting/GDBTrainerTest.java    |    3 +-
 .../apache/ignite/ml/dataset/DatasetTestSuite.java |    6 +-
 .../impl/local/LocalDatasetBuilderTest.java        |    2 +-
 .../primitive/SimpleLabeledDatasetTest.java        |    3 +-
 .../LearningEnvironmentBuilderTest.java            |   16 +-
 .../ml/environment/LearningEnvironmentTest.java    |   11 +-
 .../ml/environment/deploy/MLDeployingTest.java     |    4 +-
 .../java/org/apache/ignite/ml/math/BlasTest.java   |    4 +-
 .../ignite/ml/math/MathImplLocalTestSuite.java     |    5 +
 .../ml/math/distances/DistancesTestSuite.java      |   35 +
 .../ignite/ml/math/isolve/lsqr/LSQROnHeapTest.java |    9 +-
 .../primitives/matrix/MatrixStorageFixtures.java   |    3 +-
 .../matrix/MatrixStorageImplementationTest.java    |    9 +-
 .../math/primitives/vector/AbstractVectorTest.java |   25 +-
 .../vector/VectorImplementationsFixtures.java      |    2 +-
 .../ml/math/primitives/vector/VectorNormTest.java  |    3 +-
 .../ignite/ml/multiclass/OneVsRestTrainerTest.java |    3 +-
 .../ignite/ml/naivebayes/NaiveBayesTestSuite.java  |   48 +
 .../discrete/DiscreteNaiveBayesModelTest.java      |    2 +-
 .../discrete/DiscreteNaiveBayesTrainerTest.java    |    2 +-
 .../gaussian/GaussianNaiveBayesTrainerTest.java    |    3 +-
 .../test/java/org/apache/ignite/ml/nn/MLPTest.java |    6 +-
 .../org/apache/ignite/ml/nn/MLPTrainerTest.java    |   12 +-
 .../ignite/ml/nn/performance/MnistMLPTestUtil.java |    7 +-
 .../ml/preprocessing/PreprocessingTestSuite.java   |   13 +-
 .../preprocessing/encoding/EncoderTrainerTest.java |   48 +-
 .../preprocessing/imputing/ImputerTrainerTest.java |   30 +-
 .../linear/LinearRegressionLSQRTrainerTest.java    |    3 +-
 .../logistic/LogisticRegressionSGDTrainerTest.java |    3 +-
 .../ignite/ml/selection/SelectionTestSuite.java    |    8 +-
 .../ml/selection/cv/CrossValidationTest.java       |   84 +-
 .../cursor/CacheBasedLabelPairCursorTest.java      |    3 +-
 .../scoring/cursor/LocalLabelPairCursorTest.java   |    3 +-
 .../apache/ignite/ml/svm/SVMBinaryTrainerTest.java |    3 +-
 .../ignite/ml/tree/DecisionTreeTestSuite.java      |    4 +-
 .../gini/GiniImpurityMeasureCalculatorTest.java    |   26 +-
 .../mse/MSEImpurityMeasureCalculatorTest.java      |   18 +-
 .../RandomForestClassifierTrainerTest.java         |    3 +-
 .../RandomForestRegressionTrainerTest.java         |    3 +-
 .../randomforest/RandomForestTreeTestSuite.java    |    4 +-
 .../data/impurity/GiniFeatureHistogramTest.java    |    4 +-
 .../data/impurity/ImpurityHistogramTest.java       |    4 +-
 .../ml/util/genetic/GeneticAlgorithmTest.java      |    3 +-
 modules/ml/xgboost-model-parser/pom.xml            |   11 +-
 modules/opencensus/pom.xml                         |   11 +-
 .../monitoring/opencensus/AbstractTracingTest.java |   57 +-
 .../opencensus/OpenCensusSqlJdbcTracingTest.java   |   62 +-
 .../opencensus/OpenCensusSqlNativeTracingTest.java |  200 +-
 .../opencensus/OpenCensusTracingSpiTest.java       |   12 +-
 modules/osgi-karaf/pom.xml                         |   11 +-
 modules/osgi-paxlogging/pom.xml                    |   12 +-
 modules/osgi/pom.xml                               |   11 +-
 modules/platforms/cpp/CMakeLists.txt               |    6 +-
 .../include/ignite/binary/binary_raw_reader.h      |    2 +-
 .../include/ignite/binary/binary_raw_writer.h      |    2 +-
 .../binary/include/ignite/binary/binary_reader.h   |    2 +-
 .../binary/include/ignite/binary/binary_writer.h   |    2 +-
 .../ignite/impl/binary/binary_reader_impl.h        |  161 +-
 .../ignite/impl/interop/interop_input_stream.h     |   27 +-
 .../include/ignite/impl/interop/interop_memory.h   |   18 +-
 .../binary/src/impl/binary/binary_reader_impl.cpp  |  284 ++-
 .../cpp/binary/src/impl/interop/interop_memory.cpp |   28 +-
 modules/platforms/cpp/core-test/CMakeLists.txt     |    3 +-
 .../cpp/core-test/config/affinity-test-32.xml      |   52 +
 .../cpp/core-test/config/affinity-test-default.xml |   79 +
 .../cpp/core-test/config/affinity-test.xml         |   34 +
 .../cpp/core-test/config/cache-test-default.xml    |    4 -
 .../cpp/core-test/include/ignite/test_utils.h      |   30 +
 .../cpp/core-test/project/vs/core-test.vcxproj     |    1 +
 .../core-test/project/vs/core-test.vcxproj.filters |    3 +
 .../platforms/cpp/core-test/src/affinity_test.cpp  |  123 +-
 .../platforms/cpp/core-test/src/compute_test.cpp   |  363 +--
 modules/platforms/cpp/core-test/src/test_utils.cpp |   36 +-
 modules/platforms/cpp/core/CMakeLists.txt          |    3 +-
 .../cpp/core/include/ignite/cache/cache.h          |    4 +-
 .../core/include/ignite/cache/query/query_cursor.h |    4 +-
 .../ignite/cache/query/query_fields_cursor.h       |    4 +-
 .../include/ignite/cache/query/query_fields_row.h  |    4 +-
 modules/platforms/cpp/core/include/ignite/ignite.h |    4 +-
 .../core/include/ignite/transactions/transaction.h |    4 +-
 .../include/ignite/transactions/transactions.h     |    4 +-
 .../cluster-compute-example/CMakeLists.txt         |    3 +-
 .../cpp/examples/compute-example/CMakeLists.txt    |    3 +-
 .../continuous-query-example/CMakeLists.txt        |    3 +-
 .../cpp/examples/include/ignite/examples/person.h  |    2 +-
 .../cpp/examples/odbc-example/CMakeLists.txt       |    3 +-
 .../cpp/examples/put-get-example/CMakeLists.txt    |    3 +-
 .../cpp/examples/query-example/CMakeLists.txt      |    3 +-
 .../examples/query-example/src/query_example.cpp   |    4 +-
 .../thin-client-put-get-example/CMakeLists.txt     |    3 +-
 modules/platforms/cpp/ignite/CMakeLists.txt        |    2 +-
 modules/platforms/cpp/jni/CMakeLists.txt           |    3 +-
 modules/platforms/cpp/odbc-test/CMakeLists.txt     |    3 +-
 .../cpp/odbc-test/src/attributes_test.cpp          |   24 +
 .../cpp/odbc-test/src/meta_queries_test.cpp        |   44 +-
 modules/platforms/cpp/odbc-test/src/test_utils.cpp |   34 +-
 modules/platforms/cpp/odbc/CMakeLists.txt          |    3 +-
 .../odbc/include/ignite/odbc/meta/column_meta.h    |   41 +-
 .../odbc/include/ignite/odbc/protocol_version.h    |    3 +
 .../cpp/odbc/install/ignite-odbc-amd64.wxs         |    2 +-
 .../platforms/cpp/odbc/install/ignite-odbc-x86.wxs |    2 +-
 .../platforms/cpp/odbc/src/meta/column_meta.cpp    |   28 +-
 .../platforms/cpp/odbc/src/protocol_version.cpp    |    6 +-
 .../platforms/cpp/thin-client-test/CMakeLists.txt  |    4 +-
 .../cpp/thin-client-test/config/log/log4j-0.xml    |   42 +
 .../config/sql-query-fields-32.xml                 |   52 +
 .../config/sql-query-fields-default.xml            |  125 +
 .../thin-client-test/config/sql-query-fields.xml   |   35 +
 .../cpp/thin-client-test/config/with-logging-0.xml |   36 +
 .../thin-client-test/config/with-logging-base.xml  |   70 +
 .../thin-client-test/include/ignite/test_type.h    |  183 ++
 .../cpp/thin-client-test/include/test_utils.h      |    8 +
 .../project/vs/thin-client-test.vcxproj            |    5 +
 .../project/vs/thin-client-test.vcxproj.filters    |   15 +
 .../thin-client-test/src/ignite_client_test.cpp    |   68 +-
 .../thin-client-test/src/sql_fields_query_test.cpp |  467 ++++
 .../cpp/thin-client-test/src/test_utils.cpp        |   51 +-
 .../platforms/cpp/thin-client-test/src/tx_test.cpp |   85 +-
 modules/platforms/cpp/thin-client/CMakeLists.txt   |    5 +-
 .../ignite/impl/thin/cache/cache_client_proxy.h    |   12 +
 .../thin/cache/query/query_fields_cursor_impl.h    |  147 ++
 .../impl/thin/cache/query/query_fields_row_impl.h  |  197 ++
 .../include/ignite/impl/thin/copyable.h            |  106 +
 .../include/ignite/impl/thin/copyable_writable.h   |  175 ++
 .../include/ignite/thin/cache/cache_client.h       |   30 +-
 .../ignite/thin/cache/query/query_fields_cursor.h  |   94 +
 .../ignite/thin/cache/query/query_fields_row.h     |  104 +
 .../ignite/thin/cache/query/query_sql_fields.h     |  465 ++++
 .../include/ignite/thin/ignite_client.h            |    6 +-
 .../ignite/thin/ignite_client_configuration.h      |   37 +-
 .../include/ignite/thin/transactions/transaction.h |    6 +-
 .../ignite/thin/transactions/transactions.h        |    6 +-
 .../cpp/thin-client/project/vs/thin-client.vcxproj |   13 +
 .../project/vs/thin-client.vcxproj.filters         |   60 +
 .../src/cache/query/query_fields_cursor.cpp        |   69 +
 .../src/cache/query/query_fields_row.cpp           |   59 +
 .../src/impl/cache/cache_client_impl.cpp           |  168 +-
 .../thin-client/src/impl/cache/cache_client_impl.h |   51 +-
 .../src/impl/cache/cache_client_proxy.cpp          |    8 +
 .../thin-client/src/impl/cache/query/cursor_page.h |  127 +
 .../impl/cache/query/query_fields_cursor_impl.h    |  229 ++
 .../src/impl/cache/query/query_fields_row_impl.h   |  129 +
 .../cpp/thin-client/src/impl/data_router.cpp       |   10 +
 .../cpp/thin-client/src/impl/data_router.h         |   25 +-
 .../platforms/cpp/thin-client/src/impl/message.cpp |   69 +
 .../platforms/cpp/thin-client/src/impl/message.h   |  221 +-
 .../src/impl/transactions/transaction_impl.cpp     |  151 ++
 .../src/impl/transactions/transaction_impl.h       |   50 +-
 .../src/impl/transactions/transactions_impl.cpp    |  135 +-
 .../src/impl/transactions/transactions_impl.h      |   48 +-
 .../Properties/AssemblyInfo.cs                     |    8 +-
 .../Apache.Ignite.AspNet.nuspec                    |    2 +-
 .../Properties/AssemblyInfo.cs                     |    8 +-
 .../Apache.Ignite.BenchmarkDotNet.csproj           |    4 +
 .../Apache.Ignite.BenchmarkDotNet.snk              |  Bin 0 -> 596 bytes
 .../Binary/BinarySystemTypeReadBenchmark.cs        |  124 +
 .../DataStreamer/DataStreamerBenchmark.cs          |  106 +
 .../Apache.Ignite.BenchmarkDotNet/Program.cs       |    4 +-
 .../Properties/AssemblyInfo.cs                     |    8 +-
 .../Properties/AssemblyInfo.cs                     |    8 +-
 .../Properties/AssemblyInfo.cs                     |    8 +-
 .../Apache.Ignite.Core.Tests.TestDll2/Account.cs   |   57 +
 .../Apache.Ignite.Core.Tests.TestDll2/Address.cs   |   57 +
 .../Apache.Ignite.Core.Tests.TestDll2.csproj       |   58 +
 .../Apache.Ignite.Core.Tests.TestDll2.snk          |  Bin 0 -> 596 bytes
 .../Properties/AssemblyInfo.cs                     |   41 +
 .../Apache.Ignite.Core.Tests.DotNetCore.csproj     |   13 +-
 .../Apache.Ignite.Core.Tests.csproj                |   32 +-
 .../Binary/BinaryDateTimeTest.cs                   |  213 +-
 .../Binary/BinaryDynamicRegistrationTest.cs        |   57 +-
 .../Binary/BinaryNameMapperTest.cs                 |  140 ++
 .../Binary/BinarySelfTest.cs                       |   69 +-
 .../Binary/JavaBinaryInteropTest.cs                |  283 ++-
 .../Binary/TypeResolverTest.cs                     |    2 +-
 .../Cache/Affinity/AffinityTest.cs                 |   40 +
 .../Cache/CacheAbstractTest.cs                     |    2 +-
 .../Cache/CacheLocalAtomicTest.cs                  |    3 +
 .../Cache/CacheLocalTest.cs                        |    3 +
 .../Cache/CacheTestAsyncAwait.cs                   |  115 +
 .../Cache/PartitionPreloadTest.cs                  |    2 +-
 .../Cache/PersistenceTest.cs                       |    1 +
 .../Cache/Platform/PlatformCacheTest.cs            |    2 +-
 .../Platform/PlatformCacheTopologyChangeTest.cs    |    1 +
 .../Cache/Query/CacheDmlQueriesTestSimpleName.cs   |    1 +
 .../Query/CacheQueriesCodeConfigurationTest.cs     |  130 +-
 .../Cache/Query/CacheQueriesTestSimpleName.cs      |    1 +
 .../Cache/Query/Continuous/ContinuousQueryTest.cs  |    1 +
 .../Cache/Query/Linq/CacheLinqTest.Base.cs         |   31 +
 .../Cache/Query/Linq/CacheLinqTest.Functions.cs    |   98 -
 .../Cache/Query/Linq/CacheLinqTest.GroupBy.cs      |  294 +++
 .../Cache/Query/Linq/CacheLinqTest.Misc.cs         |  151 ++
 .../Cache/Query/Linq/CacheLinqTest.Strings.cs      |   71 +
 .../Cache/Query/Linq/CacheLinqTestSimpleName.cs    |    1 +
 .../Cache/Query/Linq/CacheLinqTestSqlEscapeAll.cs  |    1 +
 .../Binary/BinaryConfigurationRetrievalTest.cs     |  341 +++
 .../Client/Cache/CacheTestAsync.cs                 |    1 +
 .../Client/Cache/CacheTestAsyncAwait.cs            |    2 +-
 .../Client/Cache/CacheTestNoMeta.cs                |    3 +-
 .../Client/Cache/CacheTestSsl.cs                   |    1 +
 .../Client/Cache/ContinuousQueryTest.cs            |    2 +
 .../Client/ClientFeaturesTest.cs                   |   15 +-
 .../Client/Cluster/ClientClusterDiscoveryTests.cs  |    1 +
 .../ClientClusterDiscoveryTestsBaselineTopology.cs |    1 +
 .../ClientClusterDiscoveryTestsNoLocalhost.cs      |    1 +
 .../Cluster/ClientClusterDiscoveryTestsSsl.cs      |    1 +
 .../ClientReconnectCompatibilityTest.cs            |    2 -
 .../Client/Compute/ComputeClientTests.cs           |    1 +
 .../Compute/CancellationTest.cs                    |    2 +-
 .../Compute/ComputeApiTest.JavaTask.cs             |    3 +
 .../Compute/ComputeApiTest.cs                      |   14 +-
 .../Compute/ComputeApiTestFullFooter.cs            |    1 +
 .../Compute/ComputeApiTypeAutoRegisterTest.cs      |   98 +
 .../Compute/ComputeTestAsyncAwait.cs               |   50 +
 .../Config/binary-custom-name-mapper.xml           |   56 +
 .../Config/binary-custom-name-mapper2.xml          |   56 +
 .../Config/full-config.xml                         |    2 +-
 .../Config/spring-test.xml                         |    4 +
 .../Dataload/DataStreamerTest.cs                   |  314 ++-
 .../Dataload/DataStreamerTestTopologyChange.cs     |   39 +-
 .../Deployment/GetAddressFunc.cs                   |    6 +-
 .../Deployment/PeerAssemblyLoadingAllApisTest.cs   |    4 +-
 .../Deployment/PeerAssemblyLoadingTest.cs          |    4 +-
 .../Apache.Ignite.Core.Tests/Examples/Example.cs   |  158 +-
 .../Examples/ExamplePaths.cs                       |   74 +
 .../Examples/ExamplesTest.cs                       |  264 ---
 .../Examples/ExamplesTestBase.cs                   |  172 ++
 .../Examples/ExpectedOutput/AtomicLong.txt         |   24 +
 .../ExpectedOutput/AtomicLong_ExternalNode.txt     |   44 +
 .../Examples/ExpectedOutput/AtomicReference.txt    |    1 +
 .../Examples/ExpectedOutput/AtomicSequence.txt     |   23 +
 .../ExpectedOutput/AtomicSequence_ExternalNode.txt |   44 +
 .../Examples/ExpectedOutput/BinaryMode.txt         |   21 +
 .../Examples/ExpectedOutput/BinaryModeThin.txt     |   18 +
 .../Examples/ExpectedOutput/ClientReconnect.txt    |   19 +
 .../Examples/ExpectedOutput/DataStreamer.txt       |   51 +
 .../Examples/ExpectedOutput/Ddl.txt                |    9 +
 .../Examples/ExpectedOutput/DdlThin.txt            |   13 +
 .../Examples/ExpectedOutput/Dml.txt                |   17 +
 .../Examples/ExpectedOutput/DmlThin.txt            |   17 +
 .../Examples/ExpectedOutput/EntryProcessor.txt     |   45 +
 .../Examples/ExpectedOutput/Events.txt             |   10 +
 .../ExpectedOutput/Events_ExternalNode.txt         |   10 +
 .../Examples/ExpectedOutput/Func.txt               |   15 +
 .../Examples/ExpectedOutput/Lifecycle.txt          |   17 +
 .../Examples/ExpectedOutput/Linq.txt               |   32 +
 .../Examples/ExpectedOutput/LinqThin.txt           |   32 +
 .../Examples/ExpectedOutput/Messaging.txt          |   28 +
 .../Examples/ExpectedOutput/MultiTieredCache.txt   |   34 +
 .../ExpectedOutput/OptimisticTransaction.txt       |    7 +
 .../ExpectedOutput/OptimisticTransactionThin.txt   |    7 +
 .../ExpectedOutput/PeerAssemblyLoading.txt         |    4 +
 .../Examples/ExpectedOutput/PutGet.txt             |   13 +
 .../Examples/ExpectedOutput/PutGetThin.txt         |   13 +
 .../Examples/ExpectedOutput/QueryContinuous.txt    |    6 +
 .../ExpectedOutput/QueryContinuousThin.txt         |    6 +
 .../Examples/ExpectedOutput/QueryFullText.txt      |    5 +
 .../Examples/ExpectedOutput/QueryScan.txt          |    5 +
 .../Examples/ExpectedOutput/QueryScanThin.txt      |    5 +
 .../Examples/ExpectedOutput/Services.txt           |    7 +
 .../Examples/ExpectedOutput/ServicesThin.txt       |    3 +
 .../Examples/ExpectedOutput/Sql.txt                |   15 +
 .../Examples/ExpectedOutput/SqlThin.txt            |   15 +
 .../Examples/ExpectedOutput/Store.txt              |   21 +
 .../Examples/ExpectedOutput/Task.txt               |   15 +
 .../Examples/ExpectedOutput/Task_ExternalNode.txt  |   16 +
 .../Examples/ExpectedOutput/Transaction.txt        |   26 +
 .../TransactionDeadlockDetection.txt               |   17 +
 .../Examples/ExpectedOutput/TransactionThin.txt    |   26 +
 .../Apache.Ignite.Core.Tests/Examples/PathUtil.cs  |   56 -
 .../Examples/ProjectFilesTest.cs                   |  154 +-
 .../Examples/ThickClientExamplesTest.cs            |   63 +
 .../Examples/ThickExamplesExternalNodeTest.cs      |   63 +
 .../Examples/ThickExamplesTest.cs                  |   47 +
 .../Examples/ThinExamplesTest.cs                   |  102 +
 .../Examples/ThinExamplesTwoServersTest.cs         |   37 +
 .../IgniteConfigurationSerializerTest.cs           |    5 +-
 .../IgniteConfigurationTest.cs                     |    5 +
 .../Apache.Ignite.Core.Tests/IgniteLockTests.cs    |    1 +
 .../dotnet/Apache.Ignite.Core.Tests/JavaServer.cs  |    4 +-
 .../Apache.Ignite.Core.Tests/LifecycleTest.cs      |    4 +-
 .../Log/CustomLoggerTest.cs                        |  100 +-
 .../Apache.Ignite.Core.Tests/MessagingTest.cs      |  128 +-
 .../Apache.Ignite.Core.Tests/ProjectFilesTest.cs   |   74 +-
 .../Properties/AssemblyInfo.cs                     |    8 +-
 .../Services/IJavaService.cs                       |   23 +-
 .../Services/JavaServiceDynamicProxy.cs            |   44 +-
 .../Apache.Ignite.Core.Tests/Services/Model.cs     |  106 +-
 .../Services/PlatformTestService.cs                |  620 +++++
 .../Services/ServiceProxyTest.cs                   |    6 +-
 .../Services/ServiceTypeAutoResolveTest.cs         |  193 --
 .../Services/ServicesTest.cs                       |  480 +++-
 .../Services/ServicesTestAsync.cs                  |    5 +-
 .../Services/ServicesTestFullFooter.cs             |    4 +
 .../Services/ServicesTypeAutoResolveTest.cs        |  296 +++
 .../Apache.Ignite.Core.Tests/TestUtilsJni.cs       |   21 +
 .../Apache.Ignite.Core.Schema.nuspec               |    2 +-
 .../Apache.Ignite.Core/Apache.Ignite.Core.csproj   |    5 +
 .../Apache.Ignite.Core/Apache.Ignite.Core.nuspec   |   18 +-
 .../Binary/BinaryBasicNameMapper.cs                |   61 +-
 .../Binary/BinaryConfiguration.cs                  |   12 +-
 .../Binary/BinaryReflectiveSerializer.cs           |    2 +-
 .../Binary/ITimestampConverter.cs                  |   38 +
 .../Configuration/AsyncContinuationExecutor.cs     |   60 +
 .../Apache.Ignite.Core/Datastream/IDataStreamer.cs |  150 +-
 .../IgniteClientConfigurationSection.xsd           |   12 +
 .../Apache.Ignite.Core/IgniteConfiguration.cs      |   19 +-
 .../IgniteConfigurationSection.xsd                 |   26 +-
 .../dotnet/Apache.Ignite.Core/Ignition.cs          |   42 +-
 .../Impl/Binary/BinaryProcessor.cs                 |   21 +-
 .../Impl/Binary/BinaryProcessorClient.cs           |   23 +-
 .../Apache.Ignite.Core/Impl/Binary/BinaryReader.cs |   36 +-
 .../Impl/Binary/BinarySystemHandlers.cs            |  412 ++--
 .../Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs  |  105 +-
 .../Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs |   40 +-
 .../Impl/Binary/IBinaryProcessor.cs                |    9 +-
 .../Apache.Ignite.Core/Impl/Binary/JavaTypes.cs    |    2 +-
 .../Apache.Ignite.Core/Impl/Binary/Marshaller.cs   |   73 +-
 .../Impl/Binary/TypeNameParser.cs                  |   18 +-
 .../Apache.Ignite.Core/Impl/Binary/TypeResolver.cs |    9 +-
 .../Binary/BinaryConfigurationClientInternal.cs    |   68 +
 .../Impl/Client/Binary/BinaryNameMapperMode.cs     |   42 +
 .../Impl/Client/ClientBitmaskFeature.cs            |    3 +-
 .../Impl/Client/ClientFailoverSocket.cs            |  112 +-
 .../Impl/Client/ClientFeatures.cs                  |   30 +-
 .../Apache.Ignite.Core/Impl/Client/ClientOp.cs     |    1 +
 .../Apache.Ignite.Core/Impl/Client/IgniteClient.cs |    2 +-
 .../Impl/Common/FutureConverter.cs                 |   22 +-
 .../Apache.Ignite.Core/Impl/Common/TaskRunner.cs   |   57 +-
 .../Apache.Ignite.Core/Impl/Compute/ComputeImpl.cs |   10 +
 .../Impl/Compute/ComputeTaskHolder.cs              |   20 +-
 .../Impl/Datastream/DataStreamerBatch.cs           |   58 +-
 .../Impl/Datastream/DataStreamerImpl.cs            |  212 +-
 .../Impl/IPlatformTargetInternal.cs                |    3 +-
 .../Impl/PlatformDisposableTargetAdapter.cs        |   24 +-
 .../Apache.Ignite.Core/Impl/PlatformJniTarget.cs   |    5 +-
 .../Impl/PlatformTargetAdapter.cs                  |   53 +-
 .../Impl/Plugin/PluginProcessor.cs                 |   34 +-
 .../Impl/Services/ServiceProxySerializer.cs        |   49 +-
 .../Apache.Ignite.Core/Impl/Services/Services.cs   |   26 +-
 .../Impl/Unmanaged/Jni/DllLoader.cs                |   10 +-
 .../Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs   |    2 +-
 .../Impl/Unmanaged/NativeLibraryUtils.cs           |  108 +
 .../Impl/Unmanaged/UnmanagedThread.cs              |   20 +-
 .../Apache.Ignite.Core/Properties/AssemblyInfo.cs  |    9 +-
 .../Properties/AssemblyInfo.cs                     |    6 +-
 .../Apache.Ignite.EntityFramework.nuspec           |    2 +-
 .../Properties/AssemblyInfo.cs                     |    8 +-
 .../Apache.Ignite.Linq/Apache.Ignite.Linq.nuspec   |    2 +-
 .../Apache.Ignite.Linq/Impl/AliasDictionary.cs     |   43 +-
 .../Impl/CacheQueryExpressionVisitor.cs            |    5 +-
 .../Impl/CacheQueryModelVisitor.cs                 |    2 +-
 .../Apache.Ignite.Linq/Impl/ExpressionWalker.cs    |  130 +-
 .../Apache.Ignite.Linq/Impl/MethodVisitor.cs       |   54 +
 .../Apache.Ignite.Linq/Properties/AssemblyInfo.cs  |    8 +-
 .../Apache.Ignite.Log4Net.nuspec                   |    2 +-
 .../Properties/AssemblyInfo.cs                     |    8 +-
 .../Apache.Ignite.NLog/Apache.Ignite.NLog.nuspec   |    2 +-
 .../Apache.Ignite.NLog/Properties/AssemblyInfo.cs  |    8 +-
 modules/platforms/dotnet/Apache.Ignite.sln         |   25 +-
 modules/platforms/dotnet/Apache.Ignite/App.config  |    2 +-
 .../Apache.Ignite/Properties/AssemblyInfo.cs       |    8 +-
 modules/platforms/dotnet/DEVNOTES.txt              |   14 +-
 modules/platforms/dotnet/build.ps1                 |   84 +-
 modules/platforms/dotnet/docfx/index.md            |    9 +-
 .../dotnet/examples/.template.config/template.json |   17 +
 .../platforms/dotnet/examples/.vscode/launch.json  |  445 ++++
 .../platforms/dotnet/examples/.vscode/tasks.json   |   17 +
 .../dotnet/examples/Apache.Ignite.Examples.sln     |  665 +++++-
 .../Apache.Ignite.Examples.sln.DotSettings         |   17 +
 .../Apache.Ignite.Examples.csproj                  |  107 -
 .../Apache.Ignite.Examples.snk                     |  Bin 596 -> 0 bytes
 .../examples/Apache.Ignite.Examples/App.config     |   41 -
 .../Compute/ClosureExample.cs                      |   78 -
 .../Compute/PeerAssemblyLoadingExample.cs          |   96 -
 .../Apache.Ignite.Examples/Compute/TaskExample.cs  |  134 --
 .../DataStructures/AtomicLongExample.cs            |   65 -
 .../DataStructures/AtomicReferenceExample.cs       |   65 -
 .../DataStructures/AtomicSequenceExample.cs        |   70 -
 .../Datagrid/BinaryModeExample.cs                  |  261 --
 .../Datagrid/ContinuousQueryExample.cs             |  100 -
 .../Datagrid/DataStreamerExample.cs                |   94 -
 .../Datagrid/EntryProcessorExample.cs              |   94 -
 .../Datagrid/MultiTieredCacheExample.cs            |  116 -
 .../Datagrid/NearCacheExample.cs                   |   87 -
 .../Datagrid/OptimisticTransactionExample.cs       |  110 -
 .../Datagrid/PutGetExample.cs                      |  213 --
 .../Datagrid/QueryExample.cs                       |  163 --
 .../Datagrid/StoreExample.cs                       |  119 -
 .../TransactionDeadlockDetectionExample.cs         |  121 -
 .../Datagrid/TransactionExample.cs                 |  146 --
 .../Apache.Ignite.Examples/Events/EventsExample.cs |   98 -
 .../Messaging/MessagingExample.cs                  |  110 -
 .../Misc/ClientReconnectExample.cs                 |  173 --
 .../Misc/LifecycleExample.cs                       |  115 -
 .../Properties/AssemblyInfo.cs                     |   34 -
 .../Apache.Ignite.Examples/Services/IMapService.cs |   56 -
 .../Services/ServicesExample.cs                    |   74 -
 .../Apache.Ignite.Examples/Sql/LinqExample.cs      |  345 ---
 .../Apache.Ignite.Examples/Sql/SqlDdlExample.cs    |  112 -
 .../Apache.Ignite.Examples/Sql/SqlDmlExample.cs    |  161 --
 .../Apache.Ignite.Examples/Sql/SqlExample.cs       |  281 ---
 .../ThinClient/ThinClientPutGetExample.cs          |   89 -
 .../ThinClient/ThinClientQueryExample.cs           |  144 --
 .../ThinClient/ThinClientSqlExample.cs             |  198 --
 .../Apache.Ignite.ExamplesDll.csproj               |   86 -
 .../Apache.Ignite.ExamplesDll.snk                  |  Bin 596 -> 0 bytes
 .../Apache.Ignite.ExamplesDll/Binary/Account.cs    |   59 -
 .../Apache.Ignite.ExamplesDll/Binary/Address.cs    |   82 -
 .../Apache.Ignite.ExamplesDll/Binary/Employee.cs   |  104 -
 .../Binary/Organization.cs                         |   77 -
 .../Binary/OrganizationType.cs                     |   40 -
 .../Compute/AverageSalaryJob.cs                    |   64 -
 .../Compute/AverageSalaryTask.cs                   |   84 -
 .../Compute/CharacterCountClosure.cs               |   42 -
 .../Compute/CharacterCountReducer.cs               |   51 -
 .../DataStructures/AtomicLongIncrementAction.cs    |   50 -
 .../DataStructures/AtomicReferenceModifyAction.cs  |   62 -
 .../AtomicSequenceIncrementAction.cs               |   50 -
 .../Datagrid/CacheIncrementEntryProcessor.cs       |   45 -
 .../Datagrid/CachePutEntryProcessor.cs             |   45 -
 .../Datagrid/ContinuousQueryFilter.cs              |   48 -
 .../Datagrid/EmployeeStore.cs                      |  120 -
 .../Datagrid/EmployeeStoreFactory.cs               |   38 -
 .../Datagrid/EmployeeStorePredicate.cs             |   38 -
 .../Datagrid/ScanQueryFilter.cs                    |   50 -
 .../Events/LocalListener.cs                        |   54 -
 .../Messaging/LocalListener.cs                     |   59 -
 .../Messaging/RemoteOrderedListener.cs             |   53 -
 .../Messaging/RemoteUnorderedListener.cs           |   53 -
 .../Apache.Ignite.ExamplesDll/Messaging/Topic.cs   |   28 -
 .../Properties/AssemblyInfo.cs                     |   34 -
 .../Services/MapService.cs                         |  116 -
 .../dotnet/examples/Directory.Build.props          |   42 +
 modules/platforms/dotnet/examples/README.md        |   57 +
 modules/platforms/dotnet/examples/README.txt       |    8 -
 .../dotnet/examples/ServerNode/Program.cs          |   39 +
 .../dotnet/examples/ServerNode/ServerNode.csproj   |   13 +
 .../Shared/Cache/CacheIncrementEntryProcessor.cs   |   45 +
 .../Shared/Cache/CachePutEntryProcessor.cs         |   45 +
 .../examples/Shared/Cache/ContinuousQueryFilter.cs |   48 +
 .../dotnet/examples/Shared/Cache/EmployeeStore.cs  |  116 +
 .../examples/Shared/Cache/EmployeeStoreFactory.cs  |   38 +
 .../Shared/Cache/EmployeeStorePredicate.cs         |   38 +
 .../examples/Shared/Cache/ScanQueryFilter.cs       |   50 +
 .../examples/Shared/Compute/AverageSalaryJob.cs    |   64 +
 .../examples/Shared/Compute/AverageSalaryTask.cs   |   84 +
 .../examples/Shared/Compute/CharacterCountFunc.cs  |   42 +
 .../Shared/Compute/CharacterCountReducer.cs        |   51 +
 .../DataStructures/AtomicLongIncrementAction.cs    |   50 +
 .../DataStructures/AtomicReferenceModifyAction.cs  |   62 +
 .../AtomicSequenceIncrementAction.cs               |   50 +
 .../Shared/Messaging/LocalMessageListener.cs       |   59 +
 .../Messaging/RemoteOrderedMessageListener.cs      |   52 +
 .../Messaging/RemoteUnorderedMessageListener.cs    |   52 +
 .../dotnet/examples/Shared/Messaging/Topic.cs      |   28 +
 .../dotnet/examples/Shared/Models/Account.cs       |   59 +
 .../dotnet/examples/Shared/Models/Address.cs       |   82 +
 .../dotnet/examples/Shared/Models/Employee.cs      |  104 +
 .../dotnet/examples/Shared/Models/Organization.cs  |   77 +
 .../examples/Shared/Models/OrganizationType.cs     |   40 +
 .../dotnet/examples/Shared/Services/MapService.cs  |  117 +
 .../platforms/dotnet/examples/Shared/Shared.csproj |   15 +
 modules/platforms/dotnet/examples/Shared/Utils.cs  |  191 ++
 .../Thick/Cache/BinaryMode/BinaryMode.csproj       |   13 +
 .../examples/Thick/Cache/BinaryMode/Program.cs     |  246 ++
 .../Thick/Cache/DataStreamer/DataStreamer.csproj   |   13 +
 .../examples/Thick/Cache/DataStreamer/Program.cs   |   76 +
 .../Cache/EntryProcessor/EntryProcessor.csproj     |   13 +
 .../examples/Thick/Cache/EntryProcessor/Program.cs |   74 +
 .../Cache/MultiTieredCache/MultiTieredCache.csproj |   13 +
 .../Thick/Cache/MultiTieredCache/Program.cs        |  113 +
 .../Thick/Cache/NearCache/NearCache.csproj         |   13 +
 .../examples/Thick/Cache/NearCache/Program.cs      |   78 +
 .../OptimisticTransaction.csproj                   |   13 +
 .../Thick/Cache/OptimisticTransaction/Program.cs   |  101 +
 .../dotnet/examples/Thick/Cache/PutGet/Program.cs  |  195 ++
 .../examples/Thick/Cache/PutGet/PutGet.csproj      |   13 +
 .../Thick/Cache/QueryContinuous/Program.cs         |   85 +
 .../Cache/QueryContinuous/QueryContinuous.csproj   |   13 +
 .../examples/Thick/Cache/QueryFullText/Program.cs  |   62 +
 .../Thick/Cache/QueryFullText/QueryFullText.csproj |   13 +
 .../examples/Thick/Cache/QueryScan/Program.cs      |   65 +
 .../Thick/Cache/QueryScan/QueryScan.csproj         |   13 +
 .../dotnet/examples/Thick/Cache/Store/Program.cs   |  104 +
 .../dotnet/examples/Thick/Cache/Store/Store.csproj |   13 +
 .../examples/Thick/Cache/Transaction/Program.cs    |  131 ++
 .../Thick/Cache/Transaction/Transaction.csproj     |   13 +
 .../Cache/TransactionDeadlockDetection/Program.cs  |  101 +
 .../TransactionDeadlockDetection.csproj            |   13 +
 .../dotnet/examples/Thick/Compute/Func/Func.csproj |   13 +
 .../dotnet/examples/Thick/Compute/Func/Program.cs  |   64 +
 .../PeerAssemblyLoading/PeerAssemblyLoading.csproj |   16 +
 .../Thick/Compute/PeerAssemblyLoading/Program.cs   |   87 +
 .../dotnet/examples/Thick/Compute/Task/Program.cs  |   61 +
 .../dotnet/examples/Thick/Compute/Task/Task.csproj |   13 +
 .../DataStructures/AtomicLong/AtomicLong.csproj    |   13 +
 .../Thick/DataStructures/AtomicLong/Program.cs     |   56 +
 .../AtomicReference/AtomicReference.csproj         |   13 +
 .../DataStructures/AtomicReference/Program.cs      |   57 +
 .../AtomicSequence/AtomicSequence.csproj           |   13 +
 .../Thick/DataStructures/AtomicSequence/Program.cs |   57 +
 .../Misc/ClientReconnect/ClientReconnect.csproj    |   13 +
 .../examples/Thick/Misc/ClientReconnect/Program.cs |  143 ++
 .../examples/Thick/Misc/Events/Events.csproj       |   13 +
 .../dotnet/examples/Thick/Misc/Events/Program.cs   |  114 +
 .../examples/Thick/Misc/Lifecycle/Lifecycle.csproj |   13 +
 .../examples/Thick/Misc/Lifecycle/Program.cs       |   94 +
 .../examples/Thick/Misc/Messaging/Messaging.csproj |   13 +
 .../examples/Thick/Misc/Messaging/Program.cs       |  100 +
 .../dotnet/examples/Thick/Misc/Services/Program.cs |   78 +
 .../examples/Thick/Misc/Services/Services.csproj   |   13 +
 modules/platforms/dotnet/examples/Thick/README.md  |    4 +
 .../dotnet/examples/Thick/Sql/Ddl/Ddl.csproj       |   13 +
 .../dotnet/examples/Thick/Sql/Ddl/Program.cs       |   99 +
 .../dotnet/examples/Thick/Sql/Dml/Dml.csproj       |   13 +
 .../dotnet/examples/Thick/Sql/Dml/Program.cs       |  145 ++
 .../dotnet/examples/Thick/Sql/Linq/Linq.csproj     |   13 +
 .../dotnet/examples/Thick/Sql/Linq/Program.cs      |  311 +++
 .../dotnet/examples/Thick/Sql/Sql/Program.cs       |  244 ++
 .../dotnet/examples/Thick/Sql/Sql/Sql.csproj       |   13 +
 .../Cache/BinaryModeThin/BinaryModeThin.csproj     |   13 +
 .../examples/Thin/Cache/BinaryModeThin/Program.cs  |  232 ++
 .../OptimisticTransactionThin.csproj               |   13 +
 .../Cache/OptimisticTransactionThin/Program.cs     |  108 +
 .../examples/Thin/Cache/PutGetThin/Program.cs      |  202 ++
 .../Thin/Cache/PutGetThin/PutGetThin.csproj        |   13 +
 .../Thin/Cache/QueryContinuousThin/Program.cs      |   93 +
 .../QueryContinuousThin/QueryContinuousThin.csproj |   13 +
 .../examples/Thin/Cache/QueryScanThin/Program.cs   |   71 +
 .../Thin/Cache/QueryScanThin/QueryScanThin.csproj  |   13 +
 .../examples/Thin/Cache/TransactionThin/Program.cs |  137 ++
 .../Cache/TransactionThin/TransactionThin.csproj   |   13 +
 .../examples/Thin/Misc/ServicesThin/Program.cs     |   79 +
 .../Thin/Misc/ServicesThin/ServicesThin.csproj     |   13 +
 modules/platforms/dotnet/examples/Thin/README.md   |    3 +
 .../examples/Thin/Sql/DdlThin/DdlThin.csproj       |   13 +
 .../dotnet/examples/Thin/Sql/DdlThin/Program.cs    |  104 +
 .../examples/Thin/Sql/DmlThin/DmlThin.csproj       |   13 +
 .../dotnet/examples/Thin/Sql/DmlThin/Program.cs    |  152 ++
 .../examples/Thin/Sql/LinqThin/LinqThin.csproj     |   13 +
 .../dotnet/examples/Thin/Sql/LinqThin/Program.cs   |  319 +++
 .../dotnet/examples/Thin/Sql/SqlThin/Program.cs    |  249 ++
 .../examples/Thin/Sql/SqlThin/SqlThin.csproj       |   13 +
 .../dotnetcore/Apache.Ignite.Examples.csproj       |   29 -
 .../dotnet/examples/dotnetcore/App.config          |   38 -
 .../dotnet/examples/dotnetcore/Employee.cs         |   67 -
 .../dotnet/examples/dotnetcore/LinqExample.cs      |  239 --
 .../dotnet/examples/dotnetcore/Organization.cs     |   58 -
 .../dotnet/examples/dotnetcore/Program.cs          |  109 -
 .../dotnet/examples/dotnetcore/PutGetExample.cs    |  122 -
 .../dotnet/examples/dotnetcore/README.txt          |    8 -
 .../dotnet/examples/dotnetcore/SqlExample.cs       |  191 --
 .../dotnet/examples/images/rider-sidebar.png       |  Bin 0 -> 48065 bytes
 modules/platforms/dotnet/examples/images/rider.png |  Bin 0 -> 21953 bytes
 .../platforms/dotnet/examples/images/vs-code.png   |  Bin 0 -> 29808 bytes
 modules/platforms/dotnet/examples/images/vs.png    |  Bin 0 -> 8262 bytes
 modules/platforms/dotnet/release/verify-nuget.ps1  |    2 +-
 .../platforms/dotnet/run-dotnetcore-examples.bat   |   27 -
 modules/platforms/dotnet/templates/README.md       |   32 +
 .../.template.config/template.json                 |   16 +
 .../Apache.Ignite.Example/ExampleProject.csproj    |   13 +
 .../internal/Apache.Ignite.Example/Program.cs      |   50 +
 .../.template.config/template.json                 |   16 +
 .../ExampleProjectThin.csproj                      |   13 +
 .../internal/Apache.Ignite.ExampleThin/Program.cs  |   57 +
 .../Apache.Ignite.Examples.csproj                  |   32 +
 modules/platforms/nodejs/README.md                 |   32 -
 modules/platforms/nodejs/api_spec/conf.json        |   12 -
 .../platforms/nodejs/examples/AuthTlsExample.js    |  128 -
 .../nodejs/examples/CachePutGetExample.js          |  186 --
 .../platforms/nodejs/examples/FailoverExample.js   |   59 -
 modules/platforms/nodejs/examples/SqlExample.js    |  242 --
 .../nodejs/examples/SqlQueryEntriesExample.js      |  136 --
 modules/platforms/nodejs/examples/certs/ca.crt     |   32 -
 modules/platforms/nodejs/examples/certs/client.crt |   30 -
 modules/platforms/nodejs/examples/certs/client.key |   51 -
 .../platforms/nodejs/examples/certs/keystore.jks   |  Bin 3828 -> 0 bytes
 .../platforms/nodejs/examples/certs/truststore.jks |  Bin 1477 -> 0 bytes
 modules/platforms/nodejs/index.js                  |   43 -
 modules/platforms/nodejs/lib/BinaryObject.js       |  530 -----
 modules/platforms/nodejs/lib/CacheClient.js        |  759 ------
 modules/platforms/nodejs/lib/CacheConfiguration.js | 1734 --------------
 modules/platforms/nodejs/lib/Cursor.js             |  307 ---
 modules/platforms/nodejs/lib/EnumItem.js           |  212 --
 modules/platforms/nodejs/lib/Errors.js             |  133 --
 modules/platforms/nodejs/lib/IgniteClient.js       |  290 ---
 .../nodejs/lib/IgniteClientConfiguration.js        |  112 -
 modules/platforms/nodejs/lib/ObjectType.js         |  600 -----
 modules/platforms/nodejs/lib/Query.js              |  508 ----
 modules/platforms/nodejs/lib/Timestamp.js          |   76 -
 .../nodejs/lib/internal/ArgumentChecker.js         |   83 -
 .../nodejs/lib/internal/BinaryCommunicator.js      |  409 ----
 .../platforms/nodejs/lib/internal/BinaryType.js    |  483 ----
 .../nodejs/lib/internal/BinaryTypeStorage.js       |  112 -
 .../platforms/nodejs/lib/internal/BinaryUtils.js   |  602 -----
 .../nodejs/lib/internal/ClientFailoverSocket.js    |  134 --
 .../platforms/nodejs/lib/internal/ClientSocket.js  |  454 ----
 modules/platforms/nodejs/lib/internal/Logger.js    |   45 -
 .../platforms/nodejs/lib/internal/MessageBuffer.js |  293 ---
 modules/platforms/nodejs/package.json              |   40 -
 modules/platforms/nodejs/spec/ExamplesExecutor.js  |   28 -
 modules/platforms/nodejs/spec/TestingHelper.js     |  391 ---
 .../nodejs/spec/cache/BinaryObject.spec.js         |  176 --
 modules/platforms/nodejs/spec/cache/Cache.spec.js  |  262 ---
 .../nodejs/spec/cache/CacheKeyValueOps.spec.js     | 1022 --------
 .../nodejs/spec/cache/CachePutGetDiffTypes.spec.js |  686 ------
 .../nodejs/spec/cache/ComplexObject.spec.js        |  540 -----
 modules/platforms/nodejs/spec/cache/UUID.spec.js   |  105 -
 modules/platforms/nodejs/spec/config.js            |   27 -
 .../nodejs/spec/examples/AuthExample.spec.js       |   33 -
 .../nodejs/spec/examples/Examples.spec.js          |   45 -
 .../platforms/nodejs/spec/query/ScanQuery.spec.js  |  207 --
 .../nodejs/spec/query/SqlFieldsQuery.spec.js       |  266 ---
 .../platforms/nodejs/spec/query/SqlQuery.spec.js   |  247 --
 modules/platforms/nodejs/spec/support/jasmine.json |   11 -
 modules/platforms/php/.gitignore                   |    2 -
 modules/platforms/php/README.md                    |   37 -
 modules/platforms/php/api_docs/Doxyfile            | 2487 --------------------
 modules/platforms/php/composer.json                |   27 -
 modules/platforms/php/examples/AuthTlsExample.php  |  129 -
 .../platforms/php/examples/CachePutGetExample.php  |  184 --
 modules/platforms/php/examples/FailoverExample.php |   67 -
 modules/platforms/php/examples/SqlExample.php      |  237 --
 .../php/examples/SqlQueryEntriesExample.php        |  127 -
 modules/platforms/php/examples/certs/ca.pem        |   32 -
 modules/platforms/php/examples/certs/client.pem    |   81 -
 modules/platforms/php/examples/certs/keystore.jks  |  Bin 3828 -> 0 bytes
 .../platforms/php/examples/certs/truststore.jks    |  Bin 1477 -> 0 bytes
 .../src/Apache/Ignite/Cache/CacheConfiguration.php | 1011 --------
 .../php/src/Apache/Ignite/Cache/CacheEntry.php     |   60 -
 .../php/src/Apache/Ignite/Cache/CacheInterface.php |  379 ---
 .../Apache/Ignite/Cache/CacheKeyConfiguration.php  |  107 -
 .../php/src/Apache/Ignite/Cache/QueryEntity.php    |  315 ---
 .../php/src/Apache/Ignite/Cache/QueryField.php     |  279 ---
 .../php/src/Apache/Ignite/Cache/QueryIndex.php     |  191 --
 modules/platforms/php/src/Apache/Ignite/Client.php |  243 --
 .../php/src/Apache/Ignite/ClientConfiguration.php  |  294 ---
 .../php/src/Apache/Ignite/Data/BinaryObject.php    |  469 ----
 .../platforms/php/src/Apache/Ignite/Data/Date.php  |   83 -
 .../php/src/Apache/Ignite/Data/EnumItem.php        |  155 --
 .../platforms/php/src/Apache/Ignite/Data/Time.php  |   58 -
 .../php/src/Apache/Ignite/Data/Timestamp.php       |   66 -
 .../Apache/Ignite/Exception/ClientException.php    |   35 -
 .../Ignite/Exception/NoConnectionException.php     |   35 -
 .../Apache/Ignite/Exception/OperationException.php |   35 -
 .../Exception/OperationStatusUnknownException.php  |   35 -
 .../Ignite/Internal/Binary/BinaryCommunicator.php  |  493 ----
 .../Apache/Ignite/Internal/Binary/BinaryField.php  |   78 -
 .../Ignite/Internal/Binary/BinaryObjectField.php   |  113 -
 .../Apache/Ignite/Internal/Binary/BinarySchema.php |  145 --
 .../Apache/Ignite/Internal/Binary/BinaryType.php   |  233 --
 .../Ignite/Internal/Binary/BinaryTypeBuilder.php   |  207 --
 .../Ignite/Internal/Binary/BinaryTypeStorage.php   |  123 -
 .../Apache/Ignite/Internal/Binary/BinaryUtils.php  |  450 ----
 .../Ignite/Internal/Binary/ClientOperation.php     |   64 -
 .../Ignite/Internal/Binary/MessageBuffer.php       |  307 ---
 .../src/Apache/Ignite/Internal/Binary/Request.php  |   85 -
 .../src/Apache/Ignite/Internal/Binary/TypeInfo.php |  312 ---
 .../php/src/Apache/Ignite/Internal/Cache.php       |  387 ---
 .../Internal/Connection/ClientFailoverSocket.php   |  134 --
 .../Ignite/Internal/Connection/ClientSocket.php    |  247 --
 .../Ignite/Internal/Connection/ProtocolVersion.php |   82 -
 .../src/Apache/Ignite/Internal/Query/Cursor.php    |  166 --
 .../Ignite/Internal/Query/SqlFieldsCursor.php      |   75 -
 .../Ignite/Internal/Utils/ArgumentChecker.php      |   87 -
 .../src/Apache/Ignite/Internal/Utils/Logger.php    |   62 -
 .../src/Apache/Ignite/Query/CursorInterface.php    |   56 -
 .../php/src/Apache/Ignite/Query/Query.php          |   70 -
 .../php/src/Apache/Ignite/Query/ScanQuery.php      |   88 -
 .../Ignite/Query/SqlFieldsCursorInterface.php      |   82 -
 .../php/src/Apache/Ignite/Query/SqlFieldsQuery.php |  206 --
 .../php/src/Apache/Ignite/Query/SqlQuery.php       |  225 --
 .../Apache/Ignite/Type/CollectionObjectType.php    |  142 --
 .../src/Apache/Ignite/Type/ComplexObjectType.php   |  165 --
 .../php/src/Apache/Ignite/Type/MapObjectType.php   |  123 -
 .../php/src/Apache/Ignite/Type/ObjectArrayType.php |   68 -
 .../php/src/Apache/Ignite/Type/ObjectType.php      |  442 ----
 modules/platforms/php/tests/BinaryObjectTest.php   |  196 --
 .../platforms/php/tests/CacheKeyValueOpsTest.php   |  763 ------
 modules/platforms/php/tests/CachePutGetTest.php    |  765 ------
 modules/platforms/php/tests/CacheTest.php          |  240 --
 modules/platforms/php/tests/ComplexObjectTest.php  |  428 ----
 modules/platforms/php/tests/ScanQueryTest.php      |  167 --
 modules/platforms/php/tests/SqlFieldsQueryTest.php |  224 --
 modules/platforms/php/tests/SqlQueryTest.php       |  204 --
 modules/platforms/php/tests/TestConfig.php         |   37 -
 modules/platforms/php/tests/TestingHelper.php      |  363 ---
 .../php/tests/examples/ExecuteAuthTlsExample.php   |   36 -
 .../php/tests/examples/ExecuteExamples.php         |   61 -
 modules/platforms/python/LICENSE                   |  202 --
 modules/platforms/python/README.md                 |   75 -
 modules/platforms/python/docs/Makefile             |   20 -
 modules/platforms/python/docs/conf.py              |  176 --
 .../python/docs/datatypes/cache_props.rst          |  163 --
 .../platforms/python/docs/datatypes/parsers.rst    |  175 --
 modules/platforms/python/docs/examples.rst         |  624 -----
 modules/platforms/python/docs/index.rst            |   33 -
 modules/platforms/python/docs/modules.rst          |   31 -
 modules/platforms/python/docs/readme.rst           |  202 --
 modules/platforms/python/docs/source/modules.rst   |    7 -
 .../python/docs/source/pyignite.api.binary.rst     |    7 -
 .../docs/source/pyignite.api.cache_config.rst      |    7 -
 .../python/docs/source/pyignite.api.key_value.rst  |    7 -
 .../python/docs/source/pyignite.api.result.rst     |    7 -
 .../platforms/python/docs/source/pyignite.api.rst  |   19 -
 .../python/docs/source/pyignite.api.sql.rst        |    7 -
 .../python/docs/source/pyignite.binary.rst         |    7 -
 .../python/docs/source/pyignite.cache.rst          |    7 -
 .../python/docs/source/pyignite.client.rst         |    7 -
 .../docs/source/pyignite.connection.generators.rst |    7 -
 .../docs/source/pyignite.connection.handshake.rst  |    7 -
 .../python/docs/source/pyignite.connection.rst     |   17 -
 .../python/docs/source/pyignite.connection.ssl.rst |    7 -
 .../python/docs/source/pyignite.constants.rst      |    7 -
 .../python/docs/source/pyignite.datatypes.base.rst |    7 -
 .../docs/source/pyignite.datatypes.binary.rst      |    7 -
 .../source/pyignite.datatypes.cache_config.rst     |    7 -
 .../source/pyignite.datatypes.cache_properties.rst |    7 -
 .../docs/source/pyignite.datatypes.complex.rst     |    7 -
 .../docs/source/pyignite.datatypes.internal.rst    |    7 -
 .../docs/source/pyignite.datatypes.key_value.rst   |    7 -
 .../docs/source/pyignite.datatypes.null_object.rst |    7 -
 .../docs/source/pyignite.datatypes.primitive.rst   |    7 -
 .../source/pyignite.datatypes.primitive_arrays.rst |    7 -
 .../pyignite.datatypes.primitive_objects.rst       |    7 -
 .../docs/source/pyignite.datatypes.prop_codes.rst  |    7 -
 .../python/docs/source/pyignite.datatypes.rst      |   29 -
 .../python/docs/source/pyignite.datatypes.sql.rst  |    7 -
 .../docs/source/pyignite.datatypes.standard.rst    |    7 -
 .../docs/source/pyignite.datatypes.type_codes.rst  |    7 -
 .../python/docs/source/pyignite.exceptions.rst     |    7 -
 .../docs/source/pyignite.queries.op_codes.rst      |    7 -
 .../python/docs/source/pyignite.queries.rst        |   15 -
 modules/platforms/python/docs/source/pyignite.rst  |   30 -
 .../python/docs/source/pyignite.utils.rst          |    7 -
 modules/platforms/python/examples/binary_basics.py |   53 -
 modules/platforms/python/examples/create_binary.py |  103 -
 modules/platforms/python/examples/failover.py      |   61 -
 modules/platforms/python/examples/get_and_put.py   |   41 -
 .../platforms/python/examples/migrate_binary.py    |  190 --
 modules/platforms/python/examples/read_binary.py   |  275 ---
 modules/platforms/python/examples/readme.md        |   17 -
 modules/platforms/python/examples/scans.py         |   55 -
 modules/platforms/python/examples/sql.py           |  298 ---
 modules/platforms/python/examples/type_hints.py    |   51 -
 modules/platforms/python/pyignite/__init__.py      |   17 -
 modules/platforms/python/pyignite/api/__init__.py  |   71 -
 modules/platforms/python/pyignite/api/binary.py    |  209 --
 .../platforms/python/pyignite/api/cache_config.py  |  279 ---
 modules/platforms/python/pyignite/api/key_value.py |  995 --------
 modules/platforms/python/pyignite/api/result.py    |   38 -
 modules/platforms/python/pyignite/api/sql.py       |  475 ----
 modules/platforms/python/pyignite/binary.py        |  136 --
 modules/platforms/python/pyignite/cache.py         |  595 -----
 modules/platforms/python/pyignite/client.py        |  406 ----
 .../python/pyignite/connection/__init__.py         |  333 ---
 .../python/pyignite/connection/generators.py       |   48 -
 .../python/pyignite/connection/handshake.py        |   91 -
 .../platforms/python/pyignite/connection/ssl.py    |   49 -
 modules/platforms/python/pyignite/constants.py     |   52 -
 .../python/pyignite/datatypes/__init__.py          |   27 -
 .../platforms/python/pyignite/datatypes/base.py    |   24 -
 .../platforms/python/pyignite/datatypes/binary.py  |   45 -
 .../python/pyignite/datatypes/cache_config.py      |  153 --
 .../python/pyignite/datatypes/cache_properties.py  |  287 ---
 .../platforms/python/pyignite/datatypes/complex.py |  526 -----
 .../python/pyignite/datatypes/internal.py          |  472 ----
 .../python/pyignite/datatypes/key_value.py         |   24 -
 .../python/pyignite/datatypes/null_object.py       |   64 -
 .../python/pyignite/datatypes/primitive.py         |  106 -
 .../python/pyignite/datatypes/primitive_arrays.py  |  208 --
 .../python/pyignite/datatypes/primitive_objects.py |  158 --
 .../python/pyignite/datatypes/prop_codes.py        |   51 -
 modules/platforms/python/pyignite/datatypes/sql.py |   23 -
 .../python/pyignite/datatypes/standard.py          |  739 ------
 .../python/pyignite/datatypes/type_codes.py        |   57 -
 modules/platforms/python/pyignite/exceptions.py    |   80 -
 .../platforms/python/pyignite/queries/__init__.py  |  339 ---
 .../platforms/python/pyignite/queries/op_codes.py  |   65 -
 modules/platforms/python/pyignite/utils.py         |  172 --
 modules/platforms/python/requirements/docs.txt     |    6 -
 modules/platforms/python/requirements/install.txt  |    4 -
 modules/platforms/python/requirements/setup.txt    |    3 -
 modules/platforms/python/requirements/tests.txt    |    5 -
 modules/platforms/python/setup.py                  |  104 -
 modules/platforms/python/tests/config/ssl.xml      |   58 -
 .../platforms/python/tests/config/ssl/README.txt   |    3 -
 .../python/tests/config/ssl/client_full.pem        |   52 -
 .../tests/config/ssl/client_with_pass_full.pem     |   54 -
 .../platforms/python/tests/config/ssl/server.jks   |  Bin 2380 -> 0 bytes
 .../platforms/python/tests/config/ssl/trust.jks    |  Bin 1346 -> 0 bytes
 modules/platforms/python/tests/conftest.py         |  227 --
 modules/platforms/python/tests/test_binary.py      |  280 ---
 modules/platforms/python/tests/test_cache_class.py |  221 --
 .../platforms/python/tests/test_cache_class_sql.py |  103 -
 .../platforms/python/tests/test_cache_config.py    |   75 -
 modules/platforms/python/tests/test_datatypes.py   |  176 --
 modules/platforms/python/tests/test_examples.py    |   57 -
 .../platforms/python/tests/test_generic_object.py  |   33 -
 modules/platforms/python/tests/test_get_names.py   |   30 -
 modules/platforms/python/tests/test_handshake.py   |   64 -
 modules/platforms/python/tests/test_key_value.py   |  400 ----
 modules/platforms/python/tests/test_scan.py        |   66 -
 modules/platforms/python/tests/test_sql.py         |  184 --
 modules/rest-http/pom.xml                          |   11 +-
 .../http/jetty/GridJettyObjectMapper.java          |   27 +-
 .../protocols/http/jetty/GridJettyRestHandler.java |    6 +-
 modules/scalar-2.10/pom.xml                        |   13 +-
 modules/scalar/pom.xml                             |   49 +-
 .../scalar/testsuites/ScalarSelfTestSuite.scala    |    2 -
 modules/schedule/pom.xml                           |    3 +-
 modules/slf4j/pom.xml                              |   11 +-
 modules/spark-2.4/pom.xml                          |   11 +-
 .../org/apache/ignite/spark/impl/QueryHelper.scala |    2 +-
 .../apache/ignite/spark/IgniteDataFrameSuite.scala |    6 +-
 modules/spark/pom.xml                              |   11 +-
 .../org/apache/ignite/spark/impl/QueryHelper.scala |    2 +-
 .../apache/ignite/spark/IgniteDataFrameSuite.scala |    6 +-
 modules/spring/pom.xml                             |   18 +-
 .../org/apache/ignite/IgniteClientSpringBean.java  |  258 ++
 .../java/org/apache/ignite/IgniteSpringBean.java   |    2 +
 .../apache/ignite/cache/spring/SpringCache.java    |  172 --
 .../ignite/cache/spring/SpringCacheManager.java    |  389 ---
 .../apache/ignite/cache/spring/package-info.java   |   23 -
 .../spring/IgniteTransactionHolder.java            |   97 -
 .../spring/SpringTransactionManager.java           |  561 -----
 .../ignite/transactions/spring/package-info.java   |   22 -
 .../spring-transactions-ignite-spring-bean.xml     |   67 -
 .../src/test/java/config/spring-transactions.xml   |   35 -
 .../apache/ignite/TestInjectionLifecycleBean.java  |   42 -
 .../spring/GridSpringCacheManagerAbstractTest.java |  398 ----
 .../GridSpringCacheManagerMultiJvmSelfTest.java    |  131 --
 .../spring/GridSpringCacheManagerSelfTest.java     |   64 -
 .../GridSpringCacheManagerSpringBeanSelfTest.java  |   46 -
 .../cache/spring/GridSpringCacheTestKey.java       |   61 -
 .../spring/GridSpringCacheTestKeyGenerator.java    |   40 -
 .../cache/spring/GridSpringCacheTestService.java   |  181 --
 .../spring/GridSpringDynamicCacheTestService.java  |   98 -
 .../SpringCacheManagerContextInjectionTest.java    |  128 -
 .../ignite/cache/spring/SpringCacheTest.java       |  184 --
 .../spring/spring-caching-ignite-spring-bean.xml   |   90 -
 .../apache/ignite/cache/spring/spring-caching.xml  |   57 -
 .../apache/ignite/cache/spring/spring-caching1.xml |   56 -
 .../apache/ignite/cache/spring/spring-caching2.xml |   56 -
 .../SpringEncryptedCacheRestartTest.java           |   10 +-
 .../internal/IgniteClientSpringBeanTest.java       |   61 +
 .../ignite/internal/ignite-client-spring-bean.xml  |   40 +
 .../resource/GridResourceProcessorSelfTest.java    |    3 +-
 .../GridSpringResourceInjectionSelfTest.java       |    2 +-
 .../org/apache/ignite/spring-injection-test.xml    |   43 -
 ...gniteSpringBeanSpringResourceInjectionTest.java |    6 +-
 .../apache/ignite/spring/injection/spring-bean.xml |    3 +-
 .../ignite/testsuites/IgniteSpringTestSuite.java   |   23 +-
 .../GridSpringTransactionManagerAbstractTest.java  |  142 --
 .../GridSpringTransactionManagerSelfTest.java      |   66 -
 ...SpringTransactionManagerSpringBeanSelfTest.java |   58 -
 .../spring/GridSpringTransactionService.java       |   66 -
 ...ringTransactionManagerContextInjectionTest.java |  128 -
 modules/sqlline/bin/sqlline.bat                    |    8 +-
 modules/sqlline/bin/sqlline.sh                     |    6 +-
 modules/sqlline/pom.xml                            |    2 +-
 modules/ssh/pom.xml                                |   12 +-
 modules/tools/pom.xml                              |   68 +-
 .../tools/ant/beautifier/GridJavadocAntTask.java   |    3 +-
 .../surefire/testsuites/AssertOnOrphanedTests.java |   58 +
 .../surefire/testsuites/CheckAllTestsInSuites.java |  127 +
 .../surefire/testsuites/IgniteTestsProvider.java   |  131 ++
 .../testsuites/OrphanedTestCollection.java         |  123 +
 ...che.maven.surefire.providerapi.SurefireProvider |    1 +
 modules/urideploy/pom.xml                          |   12 +-
 .../spi/deployment/uri/UriDeploymentSpi.java       |    4 +-
 .../scanners/file/UriDeploymentFileScanner.java    |    2 +-
 .../UriDeploymentAbsentProcessorClassTest.java     |  117 +
 .../testsuites/IgniteUriDeploymentTestSuite.java   |    4 +-
 modules/visor-console-2.10/pom.xml                 |   14 +-
 modules/visor-console/pom.xml                      |   13 +-
 modules/visor-plugins/pom.xml                      |   13 +-
 modules/web/ignite-appserver-test/pom.xml          |    2 +-
 modules/web/ignite-websphere-test/pom.xml          |    2 +-
 modules/web/pom.xml                                |   12 +-
 .../servlet/ServletContextListenerStartup.java     |    6 +-
 .../ignite/startup/servlet/ServletStartup.java     |    6 +-
 .../benchmark-cache-pagereplacements.properties    |  124 +
 .../benchmark-cache-pegereplacements.properties    |   83 -
 .../ignite-localhost-pagereplacement-config.xml    |   79 +
 modules/yardstick/pom.xml                          |    2 +-
 .../ignite/yardstick/IgniteBenchmarkArguments.java |   29 +-
 .../org/apache/ignite/yardstick/IgniteNode.java    |    8 +-
 .../IgniteAbstractPageReplacementBenchmark.java    |  216 ++
 .../cache/IgniteCacheAbstractBenchmark.java        |    2 +-
 .../IgniteGetWithPageReplacementBenchmark.java     |   41 +
 .../cache/IgnitePutGetWithPageReplacements.java    |  171 --
 .../IgnitePutWithPageReplacementBenchmark.java     |   43 +
 .../yardstick/cache/jdbc/RdbmsBenchmark.java       |    4 +-
 .../jdbc/NativeJavaApiPutRemoveBenchmark.java      |    2 +-
 .../jdbc/NativeSqlInsertDeleteBenchmark.java       |    2 +-
 .../jdbc/NativeSqlJoinQueryRangeBenchmark.java     |    6 +-
 modules/yarn/pom.xml                               |   12 +-
 modules/yarn/src/main/resources/ignite.properties  |    2 +-
 modules/zookeeper/pom.xml                          |   12 +-
 .../spi/discovery/zk/internal/ZkIgnitePaths.java   |    2 +-
 .../zk/internal/ZookeeperDiscoveryImpl.java        |   14 +
 .../zk/internal/ZookeeperDiscoveryStatistics.java  |   18 +-
 .../zk/ZookeeperDiscoverySpiTestSuite4.java        |    4 +-
 .../zk/ZookeeperDiscoverySpiTestUtil.java          |    4 +-
 packaging/deb/changelog                            |    6 +
 packaging/rpm/apache-ignite.spec                   |    5 +-
 parent/pom.xml                                     |   40 +-
 pom.xml                                            |   71 +-
 2632 files changed, 90536 insertions(+), 74775 deletions(-)

diff --cc modules/calcite/pom.xml
index 81171e7,0000000..5e2b3de
mode 100644,000000..100644
--- a/modules/calcite/pom.xml
+++ b/modules/calcite/pom.xml
@@@ -1,288 -1,0 +1,288 @@@
 +<?xml version="1.0" encoding="UTF-8"?>
 +
 +<!--
 +  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.
 +-->
 +
 +<!--
 +    POM file.
 +-->
 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 +         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 +    <modelVersion>4.0.0</modelVersion>
 +
 +    <!-- Module specific package versions -->
 +    <properties>
 +        <calcite.version>1.26.0</calcite.version>
 +        <janino.version>3.0.11</janino.version>
 +        <avatica.version>1.17.0</avatica.version>
 +        <jsonpath.version>2.4.0</jsonpath.version>
 +        <reflections.version>0.9.10</reflections.version>
 +        <javassist.version>3.27.0-GA</javassist.version>
 +        <esri.geometry.version>2.2.3</esri.geometry.version>
 +    </properties>
 +
 +    <parent>
 +        <groupId>org.apache.ignite</groupId>
 +        <artifactId>ignite-parent</artifactId>
 +        <version>1</version>
 +        <relativePath>../../parent</relativePath>
 +    </parent>
 +
 +    <artifactId>ignite-calcite</artifactId>
-     <version>2.10.0-SNAPSHOT</version>
++    <version>2.11.0-SNAPSHOT</version>
 +    <url>http://ignite.apache.org</url>
 +
 +    <dependencies>
 +        <dependency>
 +            <groupId>org.apache.ignite</groupId>
 +            <artifactId>ignite-core</artifactId>
 +            <version>${project.version}</version>
 +        </dependency>
 +
 +        <!--
 +            At now the new calcite engine reuses some logic
 +            and doesn't work without "old" indexing module.
 +        -->
 +        <dependency>
 +            <groupId>org.apache.ignite</groupId>
 +            <artifactId>ignite-indexing</artifactId>
 +            <version>${project.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.apache.calcite</groupId>
 +            <artifactId>calcite-core</artifactId>
 +            <version>${calcite.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.apache.calcite</groupId>
 +            <artifactId>calcite-linq4j</artifactId>
 +            <version>${calcite.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>com.google.guava</groupId>
 +            <artifactId>guava</artifactId>
 +            <version>${guava.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.codehaus.janino</groupId>
 +            <artifactId>commons-compiler</artifactId>
 +            <version>${janino.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.codehaus.janino</groupId>
 +            <artifactId>janino</artifactId>
 +            <version>${janino.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.apache.calcite.avatica</groupId>
 +            <artifactId>avatica-core</artifactId>
 +            <version>${avatica.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>com.fasterxml.jackson.core</groupId>
 +            <artifactId>jackson-core</artifactId>
 +            <version>${jackson.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>com.fasterxml.jackson.core</groupId>
 +            <artifactId>jackson-databind</artifactId>
 +            <version>${jackson.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>com.fasterxml.jackson.core</groupId>
 +            <artifactId>jackson-annotations</artifactId>
 +            <version>${jackson.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>com.jayway.jsonpath</groupId>
 +            <artifactId>json-path</artifactId>
 +            <version>${jsonpath.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.reflections</groupId>
 +            <artifactId>reflections</artifactId>
 +            <version>${reflections.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.javassist</groupId>
 +            <artifactId>javassist</artifactId>
 +            <version>${javassist.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>com.esri.geometry</groupId>
 +            <artifactId>esri-geometry-api</artifactId>
 +            <version>${esri.geometry.version}</version>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.apache.ignite</groupId>
 +            <artifactId>ignite-core</artifactId>
 +            <version>${project.version}</version>
 +            <type>test-jar</type>
 +            <scope>test</scope>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.springframework</groupId>
 +            <artifactId>spring-core</artifactId>
 +            <version>${spring.version}</version>
 +            <scope>test</scope>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>log4j</groupId>
 +            <artifactId>log4j</artifactId>
 +            <scope>test</scope>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.slf4j</groupId>
 +            <artifactId>slf4j-log4j12</artifactId>
 +            <version>${slf4j.version}</version>
 +            <scope>test</scope>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.springframework</groupId>
 +            <artifactId>spring-beans</artifactId>
 +            <version>${spring.version}</version>
 +            <scope>test</scope>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.springframework</groupId>
 +            <artifactId>spring-context</artifactId>
 +            <version>${spring.version}</version>
 +            <scope>test</scope>
 +        </dependency>
 +
 +        <dependency>
 +            <groupId>org.apache.ignite</groupId>
 +            <artifactId>ignite-clients</artifactId>
 +            <version>${project.version}</version>
 +            <scope>test</scope>
 +        </dependency>
 +    </dependencies>
 +
 +    <build>
 +        <plugins>
 +            <!-- Generate the OSGi MANIFEST.MF for this bundle. -->
 +            <plugin>
 +                <groupId>org.apache.felix</groupId>
 +                <artifactId>maven-bundle-plugin</artifactId>
 +            </plugin>
 +            <plugin>
 +                <artifactId>maven-resources-plugin</artifactId>
 +                <executions>
 +                    <execution>
 +                        <id>copy-fmpp-resources</id>
 +                        <phase>validate</phase>
 +                        <goals>
 +                            <goal>copy-resources</goal>
 +                        </goals>
 +                        <configuration>
 +                            <outputDirectory>${project.build.directory}/codegen</outputDirectory>
 +                            <resources>
 +                                <resource>
 +                                    <directory>src/main/codegen</directory>
 +                                    <filtering>false</filtering>
 +                                </resource>
 +                            </resources>
 +                        </configuration>
 +                    </execution>
 +                </executions>
 +            </plugin>
 +            <plugin>
 +                <groupId>org.apache.maven.plugins</groupId>
 +                <artifactId>maven-dependency-plugin</artifactId>
 +                <executions>
 +                    <execution>
 +                        <id>unpack-parser-template</id>
 +                        <phase>validate</phase>
 +                        <goals>
 +                            <goal>unpack</goal>
 +                        </goals>
 +                        <configuration>
 +                            <artifactItems>
 +                                <artifactItem>
 +                                    <groupId>org.apache.calcite</groupId>
 +                                    <artifactId>calcite-core</artifactId>
 +                                    <type>jar</type>
 +                                    <overWrite>true</overWrite>
 +                                    <outputDirectory>${project.build.directory}/</outputDirectory>
 +                                    <includes>codegen/templates/Parser.jj</includes>
 +                                </artifactItem>
 +                            </artifactItems>
 +                        </configuration>
 +                    </execution>
 +                </executions>
 +            </plugin>
 +            <plugin>
 +                <groupId>com.googlecode.fmpp-maven-plugin</groupId>
 +                <artifactId>fmpp-maven-plugin</artifactId>
 +                <version>1.0</version>
 +                <configuration>
 +                    <cfgFile>${project.build.directory}/codegen/config.fmpp</cfgFile>
 +                    <templateDirectory>${project.build.directory}/codegen/templates</templateDirectory>
 +                </configuration>
 +                <executions>
 +                    <execution>
 +                        <id>generate-fmpp-sources</id>
 +                        <phase>validate</phase>
 +                        <goals>
 +                            <goal>generate</goal>
 +                        </goals>
 +                    </execution>
 +                </executions>
 +            </plugin>
 +            <plugin>
 +                <groupId>org.codehaus.mojo</groupId>
 +                <artifactId>javacc-maven-plugin</artifactId>
 +                <executions>
 +                    <execution>
 +                        <id>javacc</id>
 +                        <goals>
 +                            <goal>javacc</goal>
 +                        </goals>
 +                        <configuration>
 +                            <sourceDirectory>${project.build.directory}/generated-sources/fmpp</sourceDirectory>
 +                            <outputDirectory>${project.build.directory}/generated-sources/javacc</outputDirectory>
 +                            <includes>
 +                                <include>**/Parser.jj</include>
 +                            </includes>
 +                            <lookAhead>2</lookAhead>
 +                            <isStatic>false</isStatic>
 +                        </configuration>
 +                    </execution>
 +                </executions>
 +            </plugin>
 +        </plugins>
 +    </build>
 +</project>
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/AbstractIndexScan.java
index 096e4ff,0000000..52365c2
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/AbstractIndexScan.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/AbstractIndexScan.java
@@@ -1,166 -1,0 +1,166 @@@
 +/*
 + * 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.calcite.exec;
 +
 +import java.util.Iterator;
 +import java.util.NoSuchElementException;
 +import java.util.function.Function;
 +import java.util.function.Predicate;
 +import java.util.function.Supplier;
 +
 +import org.apache.calcite.rel.type.RelDataType;
 +import org.apache.ignite.IgniteCheckedException;
- import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree;
++import org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext;
 +import org.apache.ignite.internal.processors.query.GridIndex;
 +import org.apache.ignite.internal.util.lang.GridCursor;
 +import org.apache.ignite.internal.util.lang.GridIteratorAdapter;
 +import org.jetbrains.annotations.NotNull;
 +
 +/**
 + * Abstract index scan.
 + */
 +public abstract class AbstractIndexScan<Row, IdxRow> implements Iterable<Row>, AutoCloseable {
 +    /** */
 +    private final GridIndex<IdxRow> idx;
 +
 +    /** Additional filters. */
 +    private final Predicate<Row> filters;
 +
 +    /** Lower index scan bound. */
 +    private final Supplier<Row> lowerBound;
 +
 +    /** Upper index scan bound. */
 +    private final Supplier<Row> upperBound;
 +
 +    /** */
 +    private final Function<Row, Row> rowTransformer;
 +
 +    /** */
 +    protected final ExecutionContext<Row> ectx;
 +
 +    /** */
 +    protected final RelDataType rowType;
 +
 +    /**
 +     * @param ectx Execution context.
 +     * @param idx Physical index.
 +     * @param filters Additional filters.
 +     * @param lowerBound Lower index scan bound.
 +     * @param upperBound Upper index scan bound.
 +     */
 +    protected AbstractIndexScan(
 +        ExecutionContext<Row> ectx,
 +        RelDataType rowType,
 +        GridIndex<IdxRow> idx,
 +        Predicate<Row> filters,
 +        Supplier<Row> lowerBound,
 +        Supplier<Row> upperBound,
 +        Function<Row, Row> rowTransformer
 +    ) {
 +        this.ectx = ectx;
 +        this.rowType = rowType;
 +        this.idx = idx;
 +        this.filters = filters;
 +        this.lowerBound = lowerBound;
 +        this.upperBound = upperBound;
 +        this.rowTransformer = rowTransformer;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public synchronized Iterator<Row> iterator() {
 +        IdxRow lower = lowerBound == null ? null : row2indexRow(lowerBound.get());
 +        IdxRow upper = upperBound == null ? null : row2indexRow(upperBound.get());
 +
-         return new IteratorImpl(idx.find(lower, upper, filterClosure()));
++        return new IteratorImpl(idx.find(lower, upper, indexQueryContext()));
 +    }
 +
 +    /** */
 +    protected abstract IdxRow row2indexRow(Row bound);
 +
 +    /** */
 +    protected abstract Row indexRow2Row(IdxRow idxRow) throws IgniteCheckedException;
 +
 +    /** */
-     protected abstract BPlusTree.TreeRowClosure<IdxRow, IdxRow> filterClosure();
++    protected abstract IndexQueryContext indexQueryContext();
 +
 +    /** {@inheritDoc} */
 +    @Override public void close() {
 +        // No-op.
 +    }
 +
 +    /** */
 +    private class IteratorImpl extends GridIteratorAdapter<Row> {
 +        /** */
 +        private final GridCursor<IdxRow> cursor;
 +
 +        /** Next element. */
 +        private Row next;
 +
 +        /** */
 +        private IteratorImpl(@NotNull GridCursor<IdxRow> cursor) {
 +            this.cursor = cursor;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public boolean hasNextX() throws IgniteCheckedException {
 +            advance();
 +
 +            return next != null;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public Row nextX() throws IgniteCheckedException {
 +            advance();
 +
 +            if (next == null)
 +                throw new NoSuchElementException();
 +
 +            Row res = next;
 +
 +            next = null;
 +
 +            return res;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public void removeX() {
 +            throw new UnsupportedOperationException("Remove is not supported.");
 +        }
 +
 +        /** */
 +        private void advance() throws IgniteCheckedException {
 +            assert cursor != null;
 +
 +            if (next != null)
 +                return;
 +
 +            while (next == null && cursor.next()) {
 +                IdxRow idxRow = cursor.get();
 +
 +                Row r = indexRow2Row(idxRow);
 +
 +                if (filters != null && !filters.test(r))
 +                    continue;
 +
 +                if (rowTransformer != null)
 +                    r = rowTransformer.apply(r);
 +
 +                next = r;
 +            }
 +        }
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExchangeServiceImpl.java
index 02af657,0000000..083b295
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExchangeServiceImpl.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExchangeServiceImpl.java
@@@ -1,282 -1,0 +1,283 @@@
 +/*
 + * 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.calcite.exec;
 +
 +import java.util.ArrayList;
 +import java.util.Collection;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Objects;
 +import java.util.Set;
 +import java.util.UUID;
 +import java.util.concurrent.CompletableFuture;
 +import com.google.common.collect.ImmutableMap;
 +import org.apache.ignite.IgniteCheckedException;
 +import org.apache.ignite.IgniteException;
 +import org.apache.ignite.internal.GridKernalContext;
 +import org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor;
 +import org.apache.ignite.internal.processors.query.calcite.exec.rel.Inbox;
 +import org.apache.ignite.internal.processors.query.calcite.exec.rel.Outbox;
 +import org.apache.ignite.internal.processors.query.calcite.message.ErrorMessage;
 +import org.apache.ignite.internal.processors.query.calcite.message.InboxCloseMessage;
 +import org.apache.ignite.internal.processors.query.calcite.message.MessageService;
 +import org.apache.ignite.internal.processors.query.calcite.message.MessageType;
 +import org.apache.ignite.internal.processors.query.calcite.message.OutboxCloseMessage;
 +import org.apache.ignite.internal.processors.query.calcite.message.QueryBatchAcknowledgeMessage;
 +import org.apache.ignite.internal.processors.query.calcite.message.QueryBatchMessage;
 +import org.apache.ignite.internal.processors.query.calcite.metadata.FragmentDescription;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
 +import org.apache.ignite.internal.processors.query.calcite.util.AbstractService;
 +import org.apache.ignite.internal.processors.query.calcite.util.Commons;
 +import org.apache.ignite.internal.util.typedef.F;
 +
 +/**
 + *
 + */
 +public class ExchangeServiceImpl extends AbstractService implements ExchangeService {
 +    /** */
 +    private QueryTaskExecutor taskExecutor;
 +
 +    /** */
 +    private MailboxRegistry mailboxRegistry;
 +
 +    /** */
 +    private MessageService msgSvc;
 +
 +    /**
 +     * @param ctx Kernal context.
 +     */
 +    public ExchangeServiceImpl(GridKernalContext ctx) {
 +        super(ctx);
 +    }
 +
 +    /**
 +     * @param taskExecutor Task executor.
 +     */
 +    public void taskExecutor(QueryTaskExecutor taskExecutor) {
 +        this.taskExecutor = taskExecutor;
 +    }
 +
 +    /**
 +     * @return Task executor.
 +     */
 +    public QueryTaskExecutor taskExecutor() {
 +        return taskExecutor;
 +    }
 +
 +    /**
 +     * @param mailboxRegistry Mailbox registry.
 +     */
 +    public void mailboxRegistry(MailboxRegistry mailboxRegistry) {
 +        this.mailboxRegistry = mailboxRegistry;
 +    }
 +
 +    /**
 +     * @return  Mailbox registry.
 +     */
 +    public MailboxRegistry mailboxRegistry() {
 +        return mailboxRegistry;
 +    }
 +
 +    /**
 +     * @param msgSvc Message service.
 +     */
 +    public void messageService(MessageService msgSvc) {
 +        this.msgSvc = msgSvc;
 +    }
 +
 +    /**
 +     * @return  Message service.
 +     */
 +    public MessageService messageService() {
 +        return msgSvc;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public <Row> void sendBatch(UUID nodeId, UUID qryId, long fragmentId, long exchangeId, int batchId,
 +        boolean last, List<Row> rows) throws IgniteCheckedException {
 +        messageService().send(nodeId, new QueryBatchMessage(qryId, fragmentId, exchangeId, batchId, last, Commons.cast(rows)));
 +    }
 +
 +    /** {@inheritDoc} */
-     @Override public void acknowledge(UUID nodeId, UUID qryId, long fragmentId, long exchangeId, int batchId) throws IgniteCheckedException {
++    @Override public void acknowledge(UUID nodeId, UUID qryId, long fragmentId, long exchangeId, int batchId)
++        throws IgniteCheckedException {
 +        messageService().send(nodeId, new QueryBatchAcknowledgeMessage(qryId, fragmentId, exchangeId, batchId));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void closeOutbox(UUID nodeId, UUID qryId, long fragmentId, long exchangeId) throws IgniteCheckedException {
 +        messageService().send(nodeId, new OutboxCloseMessage(qryId, fragmentId, exchangeId));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void closeInbox(UUID nodeId, UUID qryId, long fragmentId, long exchangeId) throws IgniteCheckedException {
 +        messageService().send(nodeId, new InboxCloseMessage(qryId, fragmentId, exchangeId));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void sendError(UUID nodeId, UUID qryId, long fragmentId, Throwable err) throws IgniteCheckedException {
 +        messageService().send(nodeId, new ErrorMessage(qryId, fragmentId, err));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void onStart(GridKernalContext ctx) {
 +        CalciteQueryProcessor proc =
 +            Objects.requireNonNull(Commons.lookupComponent(ctx, CalciteQueryProcessor.class));
 +
 +        taskExecutor(proc.taskExecutor());
 +        mailboxRegistry(proc.mailboxRegistry());
 +        messageService(proc.messageService());
 +
 +        init();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void init() {
 +        messageService().register((n, m) -> onMessage(n, (InboxCloseMessage) m), MessageType.QUERY_INBOX_CANCEL_MESSAGE);
 +        messageService().register((n, m) -> onMessage(n, (OutboxCloseMessage) m), MessageType.QUERY_OUTBOX_CANCEL_MESSAGE);
 +        messageService().register((n, m) -> onMessage(n, (QueryBatchAcknowledgeMessage) m), MessageType.QUERY_ACKNOWLEDGE_MESSAGE);
 +        messageService().register((n, m) -> onMessage(n, (QueryBatchMessage) m), MessageType.QUERY_BATCH_MESSAGE);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean alive(UUID nodeId) {
 +        return messageService().alive(nodeId);
 +    }
 +
 +    /** */
 +    protected void onMessage(UUID nodeId, InboxCloseMessage msg) {
 +        Collection<Inbox<?>> inboxes = mailboxRegistry().inboxes(msg.queryId(), msg.fragmentId(), msg.exchangeId());
 +
 +        if (!F.isEmpty(inboxes)) {
 +            for (Inbox<?> inbox : inboxes)
 +                inbox.context().execute(inbox::close, inbox::onError);
 +        }
 +        else if (log.isDebugEnabled()) {
 +            log.debug("Stale inbox cancel message received: [" +
 +                "nodeId=" + nodeId +
 +                ", queryId=" + msg.queryId() +
 +                ", fragmentId=" + msg.fragmentId() +
 +                ", exchangeId=" + msg.exchangeId() + "]");
 +        }
 +    }
 +
 +    /** */
 +    protected void onMessage(UUID nodeId, OutboxCloseMessage msg) {
 +        Collection<Outbox<?>> outboxes = mailboxRegistry().outboxes(msg.queryId(), msg.fragmentId(), msg.exchangeId());
 +
 +        if (!F.isEmpty(outboxes)) {
 +            List<CompletableFuture<?>> futs = new ArrayList<>(outboxes.size());
 +
 +            Set<ExecutionContext<?>> ctxs = new HashSet<>();
 +
 +            for (Outbox<?> outbox : outboxes) {
 +                CompletableFuture<?> fut = outbox.context().submit(outbox::close, outbox::onError);
 +
 +                futs.add(fut);
 +
 +                ctxs.add(outbox.context());
 +            }
 +
 +            CompletableFuture.allOf(futs.toArray(new CompletableFuture<?>[0])).thenRun(() -> ctxs.forEach(ExecutionContext::cancel));
 +        }
 +        else if (log.isDebugEnabled()) {
 +            log.debug("Stale oubox cancel message received: [" +
 +                "nodeId=" + nodeId +
 +                ", queryId=" + msg.queryId() +
 +                ", fragmentId=" + msg.fragmentId() +
 +                ", exchangeId=" + msg.exchangeId() + "]");
 +        }
 +    }
 +
 +    /** */
 +    protected void onMessage(UUID nodeId, QueryBatchAcknowledgeMessage msg) {
 +        Outbox<?> outbox = mailboxRegistry().outbox(msg.queryId(), msg.exchangeId());
 +
 +        if (outbox != null) {
 +            try {
 +                outbox.onAcknowledge(nodeId, msg.batchId());
 +            }
 +            catch (Throwable e) {
 +                outbox.onError(e);
 +
 +                throw new IgniteException("Unexpected exception", e);
 +            }
 +        }
 +        else if (log.isDebugEnabled()) {
 +            log.debug("Stale acknowledge message received: [" +
 +                "nodeId=" + nodeId + ", " +
 +                "queryId=" + msg.queryId() + ", " +
 +                "fragmentId=" + msg.fragmentId() + ", " +
 +                "exchangeId=" + msg.exchangeId() + ", " +
 +                "batchId=" + msg.batchId() + "]");
 +        }
 +    }
 +
 +    /** */
 +    protected void onMessage(UUID nodeId, QueryBatchMessage msg) {
 +        Inbox<?> inbox = mailboxRegistry().inbox(msg.queryId(), msg.exchangeId());
 +
 +        if (inbox == null && msg.batchId() == 0) {
 +            // first message sent before a fragment is built
 +            // note that an inbox source fragment id is also used as an exchange id
 +            Inbox<?> newInbox = new Inbox<>(baseInboxContext(nodeId, msg.queryId(), msg.fragmentId()),
 +                this, mailboxRegistry(), msg.exchangeId(), msg.exchangeId());
 +
 +            inbox = mailboxRegistry().register(newInbox);
 +        }
 +
 +        if (inbox != null) {
 +            try {
 +                inbox.onBatchReceived(nodeId, msg.batchId(), msg.last(), Commons.cast(msg.rows()));
 +            }
 +            catch (Throwable e) {
 +                inbox.onError(e);
 +
 +                throw new IgniteException("Unexpected exception", e);
 +            }
 +        }
 +        else if (log.isDebugEnabled()) {
 +            log.debug("Stale batch message received: [" +
 +                "nodeId=" + nodeId + ", " +
 +                "queryId=" + msg.queryId() + ", " +
 +                "fragmentId=" + msg.fragmentId() + ", " +
 +                "exchangeId=" + msg.exchangeId() + ", " +
 +                "batchId=" + msg.batchId() + "]");
 +        }
 +    }
 +
 +    /**
 +     * @return Minimal execution context to meet Inbox needs.
 +     */
 +    private ExecutionContext<?> baseInboxContext(UUID nodeId, UUID qryId, long fragmentId) {
 +        return new ExecutionContext<>(
 +            taskExecutor(),
 +            PlanningContext.builder()
 +                .originatingNodeId(nodeId)
 +                .logger(log)
 +                .build(),
 +            qryId,
 +            new FragmentDescription(
 +                fragmentId,
 +                null,
 +                null,
 +                null),
 +            null,
 +            ImmutableMap.of());
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
index 7420ed6,0000000..330e8c2
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
@@@ -1,1098 -1,0 +1,1099 @@@
 +/*
 + * 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.calcite.exec;
 +
 +import java.util.ArrayList;
 +import java.util.Collection;
 +import java.util.HashSet;
 +import java.util.Iterator;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Objects;
 +import java.util.Set;
 +import java.util.UUID;
 +import java.util.concurrent.ConcurrentHashMap;
 +
 +import com.google.common.collect.ImmutableList;
 +import org.apache.calcite.plan.Context;
 +import org.apache.calcite.plan.Contexts;
 +import org.apache.calcite.plan.ConventionTraitDef;
 +import org.apache.calcite.plan.RelOptUtil;
 +import org.apache.calcite.plan.RelTraitDef;
 +import org.apache.calcite.rel.RelCollationTraitDef;
 +import org.apache.calcite.rel.type.RelDataType;
 +import org.apache.calcite.sql.SqlDdl;
 +import org.apache.calcite.sql.SqlExplain;
 +import org.apache.calcite.sql.SqlExplainLevel;
 +import org.apache.calcite.sql.SqlNode;
 +import org.apache.calcite.sql.SqlNodeList;
 +import org.apache.calcite.sql.parser.SqlParseException;
 +import org.apache.calcite.sql.type.SqlTypeName;
 +import org.apache.calcite.tools.Frameworks;
 +import org.apache.calcite.tools.ValidationException;
 +import org.apache.ignite.IgniteCheckedException;
 +import org.apache.ignite.IgniteException;
 +import org.apache.ignite.cache.query.FieldsQueryCursor;
 +import org.apache.ignite.cache.query.QueryCancelledException;
 +import org.apache.ignite.events.EventType;
 +import org.apache.ignite.internal.GridKernalContext;
 +import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
 +import org.apache.ignite.internal.managers.eventstorage.DiscoveryEventListener;
 +import org.apache.ignite.internal.managers.eventstorage.GridEventStorageManager;
 +import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 +import org.apache.ignite.internal.processors.cache.GridCachePartitionExchangeManager;
 +import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
 +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
 +import org.apache.ignite.internal.processors.failure.FailureProcessor;
 +import org.apache.ignite.internal.processors.query.GridQueryCancel;
 +import org.apache.ignite.internal.processors.query.IgniteSQLException;
 +import org.apache.ignite.internal.processors.query.QueryCancellable;
 +import org.apache.ignite.internal.processors.query.QueryContext;
 +import org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor;
 +import org.apache.ignite.internal.processors.query.calcite.exec.ddl.DdlCommandHandler;
 +import org.apache.ignite.internal.processors.query.calcite.exec.rel.Inbox;
 +import org.apache.ignite.internal.processors.query.calcite.exec.rel.Node;
 +import org.apache.ignite.internal.processors.query.calcite.exec.rel.Outbox;
 +import org.apache.ignite.internal.processors.query.calcite.exec.rel.RootNode;
 +import org.apache.ignite.internal.processors.query.calcite.message.ErrorMessage;
 +import org.apache.ignite.internal.processors.query.calcite.message.MessageService;
 +import org.apache.ignite.internal.processors.query.calcite.message.MessageType;
 +import org.apache.ignite.internal.processors.query.calcite.message.QueryStartRequest;
 +import org.apache.ignite.internal.processors.query.calcite.message.QueryStartResponse;
 +import org.apache.ignite.internal.processors.query.calcite.metadata.AffinityService;
 +import org.apache.ignite.internal.processors.query.calcite.metadata.FragmentDescription;
 +import org.apache.ignite.internal.processors.query.calcite.metadata.FragmentMapping;
 +import org.apache.ignite.internal.processors.query.calcite.metadata.MappingService;
 +import org.apache.ignite.internal.processors.query.calcite.metadata.RemoteException;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.CacheKey;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.DdlPlan;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.ExplainPlan;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.FieldsMetadata;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.FieldsMetadataImpl;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.Fragment;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.FragmentPlan;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.IgnitePlanner;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.MultiStepDmlPlan;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.MultiStepPlan;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.MultiStepQueryPlan;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.QueryPlan;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.QueryPlanCache;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.QueryTemplate;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.Splitter;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.ValidationResult;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.ddl.DdlSqlToCommandConverter;
 +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
 +import org.apache.ignite.internal.processors.query.calcite.schema.SchemaHolder;
 +import org.apache.ignite.internal.processors.query.calcite.trait.CorrelationTraitDef;
 +import org.apache.ignite.internal.processors.query.calcite.trait.DistributionTraitDef;
 +import org.apache.ignite.internal.processors.query.calcite.trait.RewindabilityTraitDef;
 +import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
 +import org.apache.ignite.internal.processors.query.calcite.util.AbstractService;
 +import org.apache.ignite.internal.processors.query.calcite.util.Commons;
 +import org.apache.ignite.internal.processors.query.calcite.util.ListFieldsQueryCursor;
 +import org.apache.ignite.internal.processors.query.calcite.util.TypeUtils;
 +import org.apache.ignite.internal.processors.query.h2.H2Utils;
 +import org.apache.ignite.internal.util.typedef.F;
 +import org.apache.ignite.internal.util.typedef.T2;
 +import org.apache.ignite.internal.util.typedef.X;
 +import org.apache.ignite.internal.util.typedef.internal.U;
 +import org.jetbrains.annotations.NotNull;
 +import org.jetbrains.annotations.Nullable;
 +
 +import static java.util.Collections.singletonList;
 +import static org.apache.calcite.rel.type.RelDataType.PRECISION_NOT_SPECIFIED;
 +import static org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor.FRAMEWORK_CONFIG;
 +import static org.apache.ignite.internal.processors.query.calcite.exec.PlannerHelper.optimize;
 +import static org.apache.ignite.internal.processors.query.calcite.externalize.RelJsonReader.fromJson;
 +
 +/**
 + *
 + */
 +@SuppressWarnings("TypeMayBeWeakened")
 +public class ExecutionServiceImpl<Row> extends AbstractService implements ExecutionService {
 +    /** */
 +    private final DiscoveryEventListener discoLsnr;
 +
 +    /** */
 +    private UUID locNodeId;
 +
 +    /** */
 +    private GridEventStorageManager evtMgr;
 +
 +    /** */
-     private GridCachePartitionExchangeManager<?,?> exchangeMgr;
++    private GridCachePartitionExchangeManager<?, ?> exchangeMgr;
 +
 +    /** */
 +    private QueryPlanCache qryPlanCache;
 +
 +    /** */
 +    private SchemaHolder schemaHolder;
 +
 +    /** */
 +    private QueryTaskExecutor taskExecutor;
 +
 +    /** */
 +    private FailureProcessor failureProcessor;
 +
 +    /** */
 +    private AffinityService partSvc;
 +
 +    /** */
 +    private MailboxRegistry mailboxRegistry;
 +
 +    /** */
 +    private MappingService mappingSvc;
 +
 +    /** */
 +    private MessageService msgSvc;
 +
 +    /** */
 +    private ExchangeService exchangeSvc;
 +
 +    /** */
 +    private ClosableIteratorsHolder iteratorsHolder;
 +
 +    /** */
 +    private final Map<UUID, QueryInfo> running;
 +
 +    /** */
 +    private final RowHandler<Row> handler;
 +
 +    /** */
 +    private final DdlCommandHandler ddlCmdHnd;
 +
 +    /** */
 +    private final DdlSqlToCommandConverter ddlConverter;
 +
 +    /**
 +     * @param ctx Kernal.
 +     */
 +    public ExecutionServiceImpl(GridKernalContext ctx, RowHandler<Row> handler) {
 +        super(ctx);
 +        this.handler = handler;
 +
 +        discoLsnr = (e, c) -> onNodeLeft(e.eventNode().id());
 +        running = new ConcurrentHashMap<>();
 +        ddlConverter = new DdlSqlToCommandConverter();
 +
 +        ddlCmdHnd = new DdlCommandHandler(
 +            ctx::query, ctx.cache(), ctx.security(), () -> schemaHolder().schema()
 +        );
 +    }
 +
 +    /**
 +     * @param locNodeId Local node ID.
 +     */
 +    public void localNodeId(UUID locNodeId) {
 +        this.locNodeId = locNodeId;
 +    }
 +
 +    /**
 +     * @return Local node ID.
 +     */
 +    public UUID localNodeId() {
 +        return locNodeId;
 +    }
 +
 +    /**
 +     * @param qryPlanCache Query cache.
 +     */
 +    public void queryPlanCache(QueryPlanCache qryPlanCache) {
 +        this.qryPlanCache = qryPlanCache;
 +    }
 +
 +    /**
 +     * @return Query cache.
 +     */
 +    public QueryPlanCache queryPlanCache() {
 +        return qryPlanCache;
 +    }
 +
 +    /**
 +     * @param schemaHolder Schema holder.
 +     */
 +    public void schemaHolder(SchemaHolder schemaHolder) {
 +        this.schemaHolder = schemaHolder;
 +    }
 +
 +    /**
 +     * @return Schema holder.
 +     */
 +    public SchemaHolder schemaHolder() {
 +        return schemaHolder;
 +    }
 +
 +    /**
 +     * @param taskExecutor Task executor.
 +     */
 +    public void taskExecutor(QueryTaskExecutor taskExecutor) {
 +        this.taskExecutor = taskExecutor;
 +    }
 +
 +    /**
 +     * @return Task executor.
 +     */
 +    public QueryTaskExecutor taskExecutor() {
 +        return taskExecutor;
 +    }
 +
 +    /**
 +     * @param failureProcessor Failure processor.
 +     */
 +    public void failureProcessor(FailureProcessor failureProcessor) {
 +        this.failureProcessor = failureProcessor;
 +    }
 +
 +    /**
 +     * @return Failure processor.
 +     */
 +    public FailureProcessor failureProcessor() {
 +        return failureProcessor;
 +    }
 +
 +    /**
 +     * @param partSvc Partition service.
 +     */
 +    public void partitionService(AffinityService partSvc) {
 +        this.partSvc = partSvc;
 +    }
 +
 +    /**
 +     * @return Partition service.
 +     */
 +    public AffinityService partitionService() {
 +        return partSvc;
 +    }
 +
 +    /**
 +     * @param mailboxRegistry Mailbox registry.
 +     */
 +    public void mailboxRegistry(MailboxRegistry mailboxRegistry) {
 +        this.mailboxRegistry = mailboxRegistry;
 +    }
 +
 +    /**
 +     * @return Mailbox registry.
 +     */
 +    public MailboxRegistry mailboxRegistry() {
 +        return mailboxRegistry;
 +    }
 +
 +    /**
 +     * @param mappingSvc Mapping service.
 +     */
 +    public void mappingService(MappingService mappingSvc) {
 +        this.mappingSvc = mappingSvc;
 +    }
 +
 +    /**
 +     * @return Mapping service.
 +     */
 +    public MappingService mappingService() {
 +        return mappingSvc;
 +    }
 +
 +    /**
 +     * @param msgSvc Message service.
 +     */
 +    public void messageService(MessageService msgSvc) {
 +        this.msgSvc = msgSvc;
 +    }
 +
 +    /**
 +     * @return Message service.
 +     */
 +    public MessageService messageService() {
 +        return msgSvc;
 +    }
 +
 +    /**
 +     * @param exchangeSvc Exchange service.
 +     */
 +    public void exchangeService(ExchangeService exchangeSvc) {
 +        this.exchangeSvc = exchangeSvc;
 +    }
 +
 +    /**
 +     * @return Exchange service.
 +     */
 +    public ExchangeService exchangeService() {
 +        return exchangeSvc;
 +    }
 +
 +    /**
 +     * @param evtMgr Event manager.
 +     */
 +    public void eventManager(GridEventStorageManager evtMgr) {
 +        this.evtMgr = evtMgr;
 +    }
 +
 +    /**
 +     * @return Event manager.
 +     */
 +    public GridEventStorageManager eventManager() {
 +        return evtMgr;
 +    }
 +
 +    /**
 +     * @param exchangeMgr Exchange manager.
 +     */
-     public void exchangeManager(GridCachePartitionExchangeManager<?,?> exchangeMgr) {
++    public void exchangeManager(GridCachePartitionExchangeManager<?, ?> exchangeMgr) {
 +        this.exchangeMgr = exchangeMgr;
 +    }
 +
 +    /**
 +     * @return Exchange manager.
 +     */
 +    public GridCachePartitionExchangeManager<?, ?> exchangeManager() {
 +        return exchangeMgr;
 +    }
 +
 +    /**
 +     * @param iteratorsHolder Iterators holder.
 +     */
 +    public void iteratorsHolder(ClosableIteratorsHolder iteratorsHolder) {
 +        this.iteratorsHolder = iteratorsHolder;
 +    }
 +
 +    /**
 +     * @return Iterators holder.
 +     */
 +    public ClosableIteratorsHolder iteratorsHolder() {
 +        return iteratorsHolder;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public List<FieldsQueryCursor<List<?>>> executeQuery(
 +        @Nullable QueryContext ctx,
 +        String schema,
 +        String qry,
 +        Object[] params
 +    ) {
 +        PlanningContext pctx = createContext(Commons.convert(ctx), topologyVersion(), localNodeId(), schema, qry, params);
 +
 +        List<QueryPlan> qryPlans = queryPlanCache().queryPlan(pctx, new CacheKey(pctx.schemaName(), pctx.query()), this::prepareQuery);
 +
 +        return executePlans(qryPlans, pctx);
 +    }
 +
 +    /**
 +     * Executes prepared plans.
 +     * @param qryPlans Query plans.
 +     * @param pctx Query context.
 +     * @return List of query result cursors.
 +     */
 +    @NotNull public List<FieldsQueryCursor<List<?>>> executePlans(
 +        Collection<QueryPlan> qryPlans,
 +        PlanningContext pctx
 +    ) {
 +        List<FieldsQueryCursor<List<?>>> cursors = new ArrayList<>(qryPlans.size());
 +
 +        for (QueryPlan plan : qryPlans) {
 +            UUID qryId = UUID.randomUUID();
 +
 +            FieldsQueryCursor<List<?>> cur = executePlan(qryId, pctx, plan);
 +
 +            cursors.add(cur);
 +        }
 +
 +        return cursors;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void cancelQuery(UUID qryId) {
 +        QueryInfo info = running.get(qryId);
 +
 +        if (info != null)
 +            info.doCancel();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void onStart(GridKernalContext ctx) {
 +        localNodeId(ctx.localNodeId());
 +        exchangeManager(ctx.cache().context().exchange());
 +        eventManager(ctx.event());
 +        iteratorsHolder(new ClosableIteratorsHolder(log));
 +
 +        CalciteQueryProcessor proc = Objects.requireNonNull(
 +            Commons.lookupComponent(ctx, CalciteQueryProcessor.class));
 +
 +        queryPlanCache(proc.queryPlanCache());
 +        schemaHolder(proc.schemaHolder());
 +        taskExecutor(proc.taskExecutor());
 +        failureProcessor(proc.failureProcessor());
 +        partitionService(proc.affinityService());
 +        mailboxRegistry(proc.mailboxRegistry());
 +        mappingService(proc.mappingService());
 +        messageService(proc.messageService());
 +        exchangeService(proc.exchangeService());
 +
 +        init();
 +     }
 +
 +    /** {@inheritDoc} */
 +    @Override public void init() {
-         messageService().register((n,m) -> onMessage(n, (QueryStartRequest) m), MessageType.QUERY_START_REQUEST);
-         messageService().register((n,m) -> onMessage(n, (QueryStartResponse) m), MessageType.QUERY_START_RESPONSE);
-         messageService().register((n,m) -> onMessage(n, (ErrorMessage) m), MessageType.QUERY_ERROR_MESSAGE);
++        messageService().register((n, m) -> onMessage(n, (QueryStartRequest) m), MessageType.QUERY_START_REQUEST);
++        messageService().register((n, m) -> onMessage(n, (QueryStartResponse) m), MessageType.QUERY_START_RESPONSE);
++        messageService().register((n, m) -> onMessage(n, (ErrorMessage) m), MessageType.QUERY_ERROR_MESSAGE);
 +
 +        eventManager().addDiscoveryEventListener(discoLsnr, EventType.EVT_NODE_FAILED, EventType.EVT_NODE_LEFT);
 +
 +        iteratorsHolder().init();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void tearDown() {
 +        eventManager().removeDiscoveryEventListener(discoLsnr, EventType.EVT_NODE_FAILED, EventType.EVT_NODE_LEFT);
 +
 +        running.clear();
 +
 +        iteratorsHolder().tearDown();
 +    }
 +
 +    /** */
 +    protected AffinityTopologyVersion topologyVersion() {
 +        return exchangeManager().readyAffinityVersion();
 +    }
 +
 +    /** */
 +    private PlanningContext createContext(Context parent, AffinityTopologyVersion topVer, UUID originator,
 +        @Nullable String schema, String qry, Object[] params) {
 +        RelTraitDef<?>[] traitDefs = {
 +            ConventionTraitDef.INSTANCE,
 +            RelCollationTraitDef.INSTANCE,
 +            DistributionTraitDef.INSTANCE,
 +            RewindabilityTraitDef.INSTANCE,
 +            CorrelationTraitDef.INSTANCE,
 +        };
 +
 +        return PlanningContext.builder()
 +            .localNodeId(localNodeId())
 +            .originatingNodeId(originator)
 +            .parentContext(parent)
 +            .frameworkConfig(Frameworks.newConfigBuilder(FRAMEWORK_CONFIG)
 +                .defaultSchema(schema != null
 +                    ? schemaHolder().schema().getSubSchema(schema)
 +                    : schemaHolder().schema())
 +                .traitDefs(traitDefs)
 +                .build())
 +            .query(qry)
 +            .parameters(params)
 +            .topologyVersion(topVer)
 +            .logger(log)
 +            .build();
 +    }
 +
 +    /** */
 +    private List<QueryPlan> prepareQuery(PlanningContext ctx) {
 +        try {
 +            String qry = ctx.query();
 +
 +            assert qry != null;
 +
 +            // Parse query.
 +            SqlNode sqlNode = ctx.planner().parse(qry);
 +
 +            if (single(sqlNode))
 +                return singletonList(prepareSingle(sqlNode, ctx));
 +
 +            List<SqlNode> nodes = ((SqlNodeList) sqlNode).getList();
 +            List<QueryPlan> res = new ArrayList<>(nodes.size());
 +
 +            for (SqlNode node : nodes)
 +                res.add(prepareSingle(node, ctx));
 +
 +            return res;
 +        }
 +        catch (IgniteSQLException e) {
 +            throw e;
 +        }
 +        catch (SqlParseException e) {
 +            throw new IgniteSQLException("Failed to parse query.", IgniteQueryErrorCode.PARSING, e);
 +        }
 +        catch (ValidationException e) {
 +            throw new IgniteSQLException("Failed to validate query.", IgniteQueryErrorCode.PARSING, e);
 +        }
 +        catch (Exception e) {
 +            throw new IgniteSQLException("Failed to plan query.", IgniteQueryErrorCode.UNKNOWN, e);
 +        }
 +    }
 +
 +    /** */
 +    private List<QueryPlan> prepareFragment(PlanningContext ctx) {
 +        return ImmutableList.of(new FragmentPlan(fromJson(ctx, ctx.query())));
 +    }
 +
 +    /** */
 +    private QueryPlan prepareSingle(SqlNode sqlNode, PlanningContext ctx) throws ValidationException {
 +        assert single(sqlNode);
 +
 +        ctx.planner().reset();
 +
 +        switch (sqlNode.getKind()) {
 +            case SELECT:
 +            case ORDER_BY:
 +            case WITH:
 +            case VALUES:
 +            case UNION:
 +            case EXCEPT:
 +                return prepareQuery(sqlNode, ctx);
 +
 +            case INSERT:
 +            case DELETE:
 +            case UPDATE:
 +                return prepareDml(sqlNode, ctx);
 +
 +            case EXPLAIN:
 +                return prepareExplain(sqlNode, ctx);
 +
 +            case CREATE_TABLE:
 +            case DROP_TABLE:
 +                return prepareDdl(sqlNode, ctx);
 +
 +            default:
 +                throw new IgniteSQLException("Unsupported operation [" +
 +                    "sqlNodeKind=" + sqlNode.getKind() + "; " +
 +                    "querySql=\"" + ctx.query() + "\"]", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
 +        }
 +    }
 +
 +    /** */
 +    private QueryPlan prepareQuery(SqlNode sqlNode, PlanningContext ctx) {
 +        IgnitePlanner planner = ctx.planner();
 +
 +        // Validate
 +        ValidationResult validated = planner.validateAndGetTypeMetadata(sqlNode);
 +
 +        sqlNode = validated.sqlNode();
 +
 +        IgniteRel igniteRel = optimize(sqlNode, planner, log);
 +
 +        // Split query plan to query fragments.
 +        List<Fragment> fragments = new Splitter().go(igniteRel);
 +
 +        QueryTemplate template = new QueryTemplate(mappingSvc, fragments);
 +
 +        return new MultiStepQueryPlan(template, queryFieldsMetadata(ctx, validated.dataType(), validated.origins()));
 +    }
 +
 +    /** */
 +    private QueryPlan prepareDml(SqlNode sqlNode, PlanningContext ctx) throws ValidationException {
 +        IgnitePlanner planner = ctx.planner();
 +
 +        // Validate
 +        sqlNode = planner.validate(sqlNode);
 +
 +        // Convert to Relational operators graph
 +        IgniteRel igniteRel = optimize(sqlNode, planner, log);
 +
 +        // Split query plan to query fragments.
 +        List<Fragment> fragments = new Splitter().go(igniteRel);
 +
 +        QueryTemplate template = new QueryTemplate(mappingSvc, fragments);
 +
 +        return new MultiStepDmlPlan(template, queryFieldsMetadata(ctx, igniteRel.getRowType(), null));
 +    }
 +
 +    /** */
 +    private QueryPlan prepareDdl(SqlNode sqlNode, PlanningContext ctx) {
 +        assert sqlNode instanceof SqlDdl : sqlNode == null ? "null" : sqlNode.getClass().getName();
 +
 +        SqlDdl ddlNode = (SqlDdl)sqlNode;
 +
 +        return new DdlPlan(ddlConverter.convert(ddlNode, ctx));
 +    }
 +
 +    /** */
 +    private QueryPlan prepareExplain(SqlNode explain, PlanningContext ctx) throws ValidationException {
 +        IgnitePlanner planner = ctx.planner();
 +
 +        SqlNode sql = ((SqlExplain)explain).getExplicandum();
 +
 +        // Validate
 +        sql = planner.validate(sql);
 +
 +        // Convert to Relational operators graph
 +        IgniteRel igniteRel = optimize(sql, planner, log);
 +
 +        String plan = RelOptUtil.toString(igniteRel, SqlExplainLevel.ALL_ATTRIBUTES);
 +
 +        return new ExplainPlan(plan, explainFieldsMetadata(ctx));
 +    }
 +
 +    /** */
 +    private FieldsMetadata explainFieldsMetadata(PlanningContext ctx) {
 +        IgniteTypeFactory factory = ctx.typeFactory();
 +        RelDataType planStrDataType =
 +            factory.createSqlType(SqlTypeName.VARCHAR, PRECISION_NOT_SPECIFIED);
 +        T2<String, RelDataType> planField = new T2<>(ExplainPlan.PLAN_COL_NAME, planStrDataType);
 +        RelDataType planDataType = factory.createStructType(singletonList(planField));
 +
 +        return queryFieldsMetadata(ctx, planDataType, null);
 +    }
 +
 +    /** */
 +    private FieldsQueryCursor<List<?>> executePlan(UUID qryId, PlanningContext pctx, QueryPlan plan) {
 +        switch (plan.type()) {
 +            case DML:
 +                // TODO a barrier between previous operation and this one
 +            case QUERY:
 +                return executeQuery(qryId, (MultiStepPlan) plan, pctx);
 +            case EXPLAIN:
 +                return executeExplain((ExplainPlan)plan, pctx);
 +            case DDL:
 +                return executeDdl((DdlPlan)plan, pctx);
 +
 +            default:
 +                throw new AssertionError("Unexpected plan type: " + plan);
 +        }
 +    }
 +
 +    /** */
 +    private FieldsQueryCursor<List<?>> executeDdl(DdlPlan plan, PlanningContext pctx) {
 +        try {
 +            ddlCmdHnd.handle(pctx, plan.command());
 +        }
 +        catch (IgniteCheckedException e) {
 +            throw new IgniteSQLException("Failed to execute DDL statement [stmt=" + pctx.query() +
 +                ", err=" + e.getMessage() + ']', e);
 +        }
 +
 +        return H2Utils.zeroCursor();
 +    }
 +
 +    /** */
 +    private FieldsQueryCursor<List<?>> executeQuery(UUID qryId, MultiStepPlan plan, PlanningContext pctx) {
 +        plan.init(pctx);
 +
 +        List<Fragment> fragments = plan.fragments();
 +
 +        // Local execution
 +        Fragment fragment = F.first(fragments);
 +
 +        if (U.assertionsEnabled()) {
 +            assert fragment != null;
 +
 +            FragmentMapping mapping = plan.mapping(fragment);
 +
 +            assert mapping != null;
 +
 +            List<UUID> nodes = mapping.nodeIds();
 +
 +            assert nodes != null && nodes.size() == 1 && F.first(nodes).equals(pctx.localNodeId());
 +        }
 +
 +        FragmentDescription fragmentDesc = new FragmentDescription(
 +            fragment.fragmentId(),
 +            plan.mapping(fragment),
 +            plan.target(fragment),
 +            plan.remotes(fragment));
 +
 +        ExecutionContext<Row> ectx = new ExecutionContext<>(
 +            taskExecutor(),
 +            pctx,
 +            qryId,
 +            fragmentDesc,
 +            handler,
 +            Commons.parametersMap(pctx.parameters()));
 +
 +        Node<Row> node = new LogicalRelImplementor<>(ectx, partitionService(), mailboxRegistry(),
 +            exchangeService(), failureProcessor()).go(fragment.root());
 +
 +        QueryInfo info = new QueryInfo(ectx, plan, node);
 +
 +        // register query
 +        register(info);
 +
 +        // start remote execution
 +        for (int i = 1; i < fragments.size(); i++) {
 +            fragment = fragments.get(i);
 +            fragmentDesc = new FragmentDescription(
 +                fragment.fragmentId(),
 +                plan.mapping(fragment),
 +                plan.target(fragment),
 +                plan.remotes(fragment));
 +
 +            Throwable ex = null;
 +            for (UUID nodeId : fragmentDesc.nodeIds()) {
 +                if (ex != null)
 +                    info.onResponse(nodeId, fragment.fragmentId(), ex);
 +                else {
 +                    try {
 +                        QueryStartRequest req = new QueryStartRequest(
 +                            qryId,
 +                            pctx.schemaName(),
 +                            fragment.serialized(),
 +                            pctx.topologyVersion(),
 +                            fragmentDesc,
 +                            pctx.parameters());
 +
 +                        messageService().send(nodeId, req);
 +                    }
 +                    catch (Throwable e) {
 +                        info.onResponse(nodeId, fragment.fragmentId(), ex = e);
 +                    }
 +                }
 +            }
 +        }
 +
 +        return new ListFieldsQueryCursor<>(plan, info.iterator(), ectx);
 +    }
 +
 +    /** */
 +    private FieldsQueryCursor<List<?>> executeExplain(ExplainPlan plan, PlanningContext pctx) {
 +        QueryCursorImpl<List<?>> cur = new QueryCursorImpl<>(singletonList(singletonList(plan.plan())));
 +        cur.fieldsMeta(plan.fieldsMeta().queryFieldsMetadata(pctx.typeFactory()));
 +
 +        return cur;
 +    }
 +
 +    /** */
 +    private void executeFragment(UUID qryId, FragmentPlan plan, PlanningContext pctx, FragmentDescription fragmentDesc) {
 +        ExecutionContext<Row> ectx = new ExecutionContext<>(taskExecutor(), pctx, qryId,
 +            fragmentDesc, handler, Commons.parametersMap(pctx.parameters()));
 +
 +        long frId = fragmentDesc.fragmentId();
 +        UUID origNodeId = pctx.originatingNodeId();
 +
 +        Outbox<Row> node = new LogicalRelImplementor<>(
 +                ectx,
 +                partitionService(),
 +                mailboxRegistry(),
 +                exchangeService(),
 +                failureProcessor())
 +                .go(plan.root());
 +
 +        try {
 +            messageService().send(origNodeId, new QueryStartResponse(qryId, frId));
 +        }
 +        catch (IgniteCheckedException e) {
 +            IgniteException wrpEx = new IgniteException("Failed to send reply. [nodeId=" + origNodeId + ']', e);
 +
 +            throw wrpEx;
 +        }
 +
 +        node.init();
 +    }
 +
 +    /** */
 +    private void register(QueryInfo info) {
 +        UUID qryId = info.ctx.queryId();
 +        PlanningContext pctx = info.ctx.planningContext();
 +
 +        running.put(qryId, info);
 +
 +        GridQueryCancel qryCancel = pctx.queryCancel();
 +
 +        if (qryCancel == null)
 +            return;
 +
 +        try {
 +            qryCancel.add(info);
 +        }
 +        catch (QueryCancelledException e) {
 +            running.remove(qryId);
 +
 +            throw new IgniteSQLException(e.getMessage(), IgniteQueryErrorCode.QUERY_CANCELED);
 +        }
 +    }
 +
 +    /** */
 +    private FieldsMetadata queryFieldsMetadata(PlanningContext ctx, RelDataType sqlType,
 +        @Nullable List<List<String>> origins) {
 +        RelDataType resultType = TypeUtils.getResultType(
 +            ctx.typeFactory(), ctx.catalogReader(), sqlType, origins);
 +        return new FieldsMetadataImpl(resultType, origins);
 +    }
 +
 +    /** */
 +    private boolean single(SqlNode sqlNode) {
 +        return !(sqlNode instanceof SqlNodeList);
 +    }
 +
 +    /** */
 +    private void onMessage(UUID nodeId, QueryStartRequest msg) {
 +        assert nodeId != null && msg != null;
 +
 +        try {
-             PlanningContext pctx = createContext(Contexts.empty(), msg.topologyVersion(), nodeId, msg.schema(), msg.root(), msg.parameters());
++            PlanningContext pctx = createContext(Contexts.empty(), msg.topologyVersion(), nodeId, msg.schema(),
++                msg.root(), msg.parameters());
 +
 +            List<QueryPlan> qryPlans = queryPlanCache().queryPlan(
 +                pctx,
 +                new CacheKey(pctx.schemaName(), pctx.query()),
 +                this::prepareFragment
 +            );
 +
 +            assert qryPlans.size() == 1 && qryPlans.get(0).type() == QueryPlan.Type.FRAGMENT;
 +
 +            FragmentPlan plan = (FragmentPlan)qryPlans.get(0);
 +
 +            executeFragment(msg.queryId(), plan, pctx, msg.fragmentDescription());
 +        }
 +        catch (Throwable ex) {
 +            U.error(log, "Failed to start query fragment ", ex);
 +
 +            mailboxRegistry.outboxes(msg.queryId(), msg.fragmentId(), -1)
 +                .forEach(Outbox::close);
 +            mailboxRegistry.inboxes(msg.queryId(), msg.fragmentId(), -1)
 +                .forEach(Inbox::close);
 +
 +            try {
 +                messageService().send(nodeId, new QueryStartResponse(msg.queryId(), msg.fragmentId(), ex));
 +            }
 +            catch (IgniteCheckedException e) {
 +                U.error(log, "Error occurred during send error message: " + X.getFullStackTrace(e));
 +
 +                IgniteException wrpEx = new IgniteException("Error occurred during send error message", e);
 +
 +                e.addSuppressed(ex);
 +
 +                throw wrpEx;
 +            }
 +
 +            throw ex;
 +        }
 +    }
 +
 +    /** */
 +    private void onMessage(UUID nodeId, QueryStartResponse msg) {
 +        assert nodeId != null && msg != null;
 +
 +        QueryInfo info = running.get(msg.queryId());
 +
 +        if (info != null)
 +            info.onResponse(nodeId, msg.fragmentId(), msg.error());
 +    }
 +
 +    /** */
 +    private void onMessage(UUID nodeId, ErrorMessage msg) {
 +        assert nodeId != null && msg != null;
 +
 +        QueryInfo info = running.get(msg.queryId());
 +
 +        if (info != null)
 +            info.onError(new RemoteException(nodeId, msg.queryId(), msg.fragmentId(), msg.error()));
 +    }
 +
 +    /** */
 +    private void onNodeLeft(UUID nodeId) {
 +        running.forEach((uuid, queryInfo) -> queryInfo.onNodeLeft(nodeId));
 +    }
 +
 +    /** */
 +    private enum QueryState {
 +        /** */
 +        RUNNING,
 +
 +        /** */
 +        CLOSING,
 +
 +        /** */
 +        CLOSED
 +    }
 +
 +    /** */
 +    private static final class RemoteFragmentKey {
 +        /** */
 +        private final UUID nodeId;
 +
 +        /** */
 +        private final long fragmentId;
 +
 +        /** */
 +        private RemoteFragmentKey(UUID nodeId, long fragmentId) {
 +            this.nodeId = nodeId;
 +            this.fragmentId = fragmentId;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public boolean equals(Object o) {
 +            if (this == o)
 +                return true;
 +            if (o == null || getClass() != o.getClass())
 +                return false;
 +
 +            RemoteFragmentKey that = (RemoteFragmentKey) o;
 +
 +            if (fragmentId != that.fragmentId)
 +                return false;
 +            return nodeId.equals(that.nodeId);
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public int hashCode() {
 +            int res = nodeId.hashCode();
 +            res = 31 * res + (int) (fragmentId ^ (fragmentId >>> 32));
 +            return res;
 +        }
 +    }
 +
 +    /** */
 +    @SuppressWarnings("TypeMayBeWeakened")
 +    private final class QueryInfo implements QueryCancellable {
 +        /** */
 +        private final ExecutionContext<Row> ctx;
 +
 +        /** */
 +        private final RootNode<Row> root;
 +
 +        /** remote nodes */
 +        private final Set<UUID> remotes;
 +
 +        /** node to fragment */
 +        private final Set<RemoteFragmentKey> waiting;
 +
 +        /** */
 +        private volatile QueryState state;
 +
 +        /** */
 +        private QueryInfo(ExecutionContext<Row> ctx, MultiStepPlan plan, Node<Row> root) {
 +            this.ctx = ctx;
 +
 +            RootNode<Row> rootNode = new RootNode<>(ctx, plan.fieldsMetadata().rowType(), this::tryClose);
 +            rootNode.register(root);
 +
 +            this.root = rootNode;
 +
 +            remotes = new HashSet<>();
 +            waiting = new HashSet<>();
 +
 +            for (int i = 1; i < plan.fragments().size(); i++) {
 +                Fragment fragment = plan.fragments().get(i);
 +                List<UUID> nodes = plan.mapping(fragment).nodeIds();
 +
 +                remotes.addAll(nodes);
 +
 +                for (UUID node : nodes)
 +                    waiting.add(new RemoteFragmentKey(node, fragment.fragmentId()));
 +            }
 +
 +            state = QueryState.RUNNING;
 +        }
 +
 +        /** */
 +        public Iterator<Row> iterator() {
 +            return iteratorsHolder().iterator(root);
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public void doCancel() {
 +            root.close();
 +        }
 +
 +        /**
 +         * Can be called multiple times after receive each error at {@link #onResponse(RemoteFragmentKey, Throwable)}.
 +         */
 +        private void tryClose() {
 +            QueryState state0 = null;
 +
 +            synchronized (this) {
 +                if (state == QueryState.CLOSED)
 +                    return;
 +
 +                if (state == QueryState.RUNNING)
 +                    state0 = state = QueryState.CLOSING;
 +
 +                // 1) close local fragment
 +                root.closeInternal();
 +
 +                if (state == QueryState.CLOSING && waiting.isEmpty())
 +                    state0 = state = QueryState.CLOSED;
 +            }
 +
 +            if (state0 == QueryState.CLOSED) {
 +                // 2) unregister runing query
 +                running.remove(ctx.queryId());
 +
 +                // 4) close remote fragments
 +                IgniteException wrpEx = null;
 +
 +                // 3) close remote fragments
 +                for (UUID nodeId : remotes) {
 +                    try {
 +                        exchangeService().closeOutbox(nodeId, ctx.queryId(), -1, -1);
 +                    }
 +                    catch (IgniteCheckedException e) {
 +                        if (wrpEx == null)
 +                            wrpEx = new IgniteException("Failed to send cancel message. [nodeId=" + nodeId + ']', e);
 +                        else
 +                            wrpEx.addSuppressed(e);
 +                    }
 +                }
 +
 +                // 4) Cancel local fragment
 +                ctx.cancel();
 +
 +                if (wrpEx != null)
 +                    throw wrpEx;
 +            }
 +        }
 +
 +        /** */
 +        private void onNodeLeft(UUID nodeId) {
 +            List<RemoteFragmentKey> fragments = null;
 +
 +            synchronized (this) {
 +                for (RemoteFragmentKey fragment : waiting) {
 +                    if (!fragment.nodeId.equals(nodeId))
 +                        continue;
 +
 +                    if (fragments == null)
 +                        fragments = new ArrayList<>();
 +
 +                    fragments.add(fragment);
 +                }
 +            }
 +
 +            if (!F.isEmpty(fragments)) {
 +                ClusterTopologyCheckedException ex = new ClusterTopologyCheckedException(
 +                    "Failed to start query, node left. nodeId=" + nodeId);
 +
 +                for (RemoteFragmentKey fragment : fragments)
 +                    onResponse(fragment, ex);
 +            }
 +        }
 +
 +        /** */
 +        private void onResponse(UUID nodeId, long fragmentId, Throwable error) {
 +            onResponse(new RemoteFragmentKey(nodeId, fragmentId), error);
 +        }
 +
 +        /** */
 +        private void onResponse(RemoteFragmentKey fragment, Throwable error) {
 +            QueryState state;
 +            synchronized (this) {
 +                waiting.remove(fragment);
 +                state = this.state;
 +            }
 +
 +            if (error != null)
 +                onError(error);
 +            else if (state == QueryState.CLOSING)
 +                tryClose();
 +        }
 +
 +        /** */
 +        private void onError(Throwable error) {
 +            root.onError(error);
 +
 +            tryClose();
 +        }
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexScan.java
index b9d3c9d,0000000..cca3cba
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexScan.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/IndexScan.java
@@@ -1,273 -1,0 +1,265 @@@
 +/*
 + * 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.calcite.exec;
 +
 +import java.util.ArrayList;
 +import java.util.Collections;
 +import java.util.Iterator;
 +import java.util.List;
 +import java.util.function.Function;
 +import java.util.function.Predicate;
 +import java.util.function.Supplier;
- 
 +import org.apache.calcite.util.ImmutableBitSet;
 +import org.apache.ignite.IgniteCheckedException;
 +import org.apache.ignite.IgniteException;
 +import org.apache.ignite.cluster.ClusterTopologyException;
 +import org.apache.ignite.internal.GridKernalContext;
++import org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext;
 +import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 +import org.apache.ignite.internal.processors.cache.CacheObjectContext;
 +import org.apache.ignite.internal.processors.cache.CacheObjectValueContext;
 +import org.apache.ignite.internal.processors.cache.GridCacheContext;
 +import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture;
 +import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition;
 +import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState;
 +import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionTopology;
 +import org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot;
 +import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
 +import org.apache.ignite.internal.processors.query.GridIndex;
 +import org.apache.ignite.internal.processors.query.calcite.exec.RowHandler.RowFactory;
 +import org.apache.ignite.internal.processors.query.calcite.schema.TableDescriptor;
 +import org.apache.ignite.internal.processors.query.h2.H2Utils;
- import org.apache.ignite.internal.processors.query.h2.database.H2TreeFilterClosure;
 +import org.apache.ignite.internal.processors.query.h2.opt.H2PlainRow;
 +import org.apache.ignite.internal.processors.query.h2.opt.H2Row;
- import org.apache.ignite.spi.indexing.IndexingQueryCacheFilter;
 +import org.apache.ignite.spi.indexing.IndexingQueryFilter;
 +import org.apache.ignite.spi.indexing.IndexingQueryFilterImpl;
 +import org.h2.value.DataType;
 +import org.h2.value.Value;
 +import org.jetbrains.annotations.Nullable;
 +
 +/**
 + * Scan on index.
 + */
 +public class IndexScan<Row> extends AbstractIndexScan<Row, H2Row> {
 +    /** */
 +    private final GridKernalContext kctx;
 +
 +    /** */
 +    private final GridCacheContext<?, ?> cctx;
 +
 +    /** */
 +    private final CacheObjectContext coCtx;
 +
 +    /** */
 +    private final TableDescriptor desc;
 +
 +    /** */
 +    private final RowFactory<Row> factory;
 +
 +    /** */
 +    private final AffinityTopologyVersion topVer;
 +
 +    /** */
 +    private final int[] parts;
 +
 +    /** */
 +    private final MvccSnapshot mvccSnapshot;
 +
 +    /** */
 +    private volatile List<GridDhtLocalPartition> reserved;
 +
 +    /** */
 +    private final ImmutableBitSet requiredColumns;
 +
 +    /**
 +     * @param ectx Execution context.
 +     * @param desc Table descriptor.
 +     * @param idx Phisycal index.
 +     * @param filters Additional filters.
 +     * @param lowerBound Lower index scan bound.
 +     * @param upperBound Upper index scan bound.
 +     */
 +    public IndexScan(
 +        ExecutionContext<Row> ectx,
 +        TableDescriptor desc,
 +        GridIndex<H2Row> idx,
 +        int[] parts,
 +        Predicate<Row> filters,
 +        Supplier<Row> lowerBound,
 +        Supplier<Row> upperBound,
 +        Function<Row, Row> rowTransformer,
 +        @Nullable ImmutableBitSet requiredColumns
 +    ) {
 +        super(
 +            ectx,
 +            desc.rowType(ectx.getTypeFactory(), requiredColumns),
 +            idx,
 +            filters,
 +            lowerBound,
 +            upperBound,
 +            rowTransformer
 +        );
 +
 +        this.desc = desc;
 +        cctx = desc.cacheContext();
 +        kctx = cctx.kernalContext();
 +        coCtx = cctx.cacheObjectContext();
 +
 +        factory = ectx.rowHandler().factory(ectx.getTypeFactory(), rowType);
 +        topVer = ectx.planningContext().topologyVersion();
 +        this.parts = parts;
 +        mvccSnapshot = ectx.mvccSnapshot();
 +        this.requiredColumns = requiredColumns;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public synchronized Iterator<Row> iterator() {
 +        reserve();
 +
 +        try {
 +            return super.iterator();
 +        }
 +        catch (Exception e) {
 +            release();
 +
 +            throw e;
 +        }
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected H2Row row2indexRow(Row bound) {
 +        return new H2PlainRow(values(coCtx, ectx, bound));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected Row indexRow2Row(H2Row row) throws IgniteCheckedException {
 +        return desc.toRow(ectx, (CacheDataRow)row, factory, requiredColumns);
 +    }
 +
 +    /** */
 +    @Override public void close() {
 +        release();
 +    }
 +
 +    /** */
 +    private synchronized void reserve() {
 +        if (reserved != null)
 +            return;
 +
 +        GridDhtPartitionTopology top = cctx.topology();
 +        top.readLock();
 +
 +        GridDhtTopologyFuture topFut = top.topologyVersionFuture();
 +
 +        boolean done = topFut.isDone();
 +
 +        if (!done || !(topFut.topologyVersion().compareTo(topVer) >= 0
 +            && cctx.shared().exchange().lastAffinityChangedTopologyVersion(topFut.initialVersion()).compareTo(topVer) <= 0)) {
 +            top.readUnlock();
 +
 +            throw new ClusterTopologyException("Topology was changed. Please retry on stable topology.");
 +        }
 +
 +        List<GridDhtLocalPartition> toReserve;
 +
 +        if (cctx.isReplicated()) {
 +            int partsCnt = cctx.affinity().partitions();
 +            toReserve = new ArrayList<>(partsCnt);
 +            for (int i = 0; i < partsCnt; i++)
 +                toReserve.add(top.localPartition(i));
 +        }
 +        else if (cctx.isPartitioned()) {
 +            assert parts != null;
 +
 +            toReserve = new ArrayList<>(parts.length);
 +            for (int i = 0; i < parts.length; i++)
 +                toReserve.add(top.localPartition(parts[i]));
 +        }
 +        else {
 +            assert cctx.isLocal();
 +
 +            toReserve = Collections.emptyList();
 +        }
 +
 +        reserved = new ArrayList<>(toReserve.size());
 +
 +        try {
 +            for (GridDhtLocalPartition part : toReserve) {
 +                if (part == null || !part.reserve()) {
 +                    throw new ClusterTopologyException(
 +                        "Failed to reserve partition for query execution. Retry on stable topology."
 +                    );
 +                }
 +                else if (part.state() != GridDhtPartitionState.OWNING) {
 +                    part.release();
 +
 +                    throw new ClusterTopologyException(
 +                        "Failed to reserve partition for query execution. Retry on stable topology."
 +                    );
 +                }
 +
 +                reserved.add(part);
 +            }
 +        }
 +        catch (Exception e) {
 +            release();
 +
 +            throw e;
 +        }
 +        finally {
 +            top.readUnlock();
 +        }
 +    }
 +
 +    /** */
 +    private synchronized void release() {
 +        if (reserved == null)
 +            return;
 +
 +        for (GridDhtLocalPartition part : reserved)
 +            part.release();
 +
 +        reserved = null;
 +    }
 +
 +    /** {@inheritDoc} */
-     @Override protected H2TreeFilterClosure filterClosure() {
++    @Override protected IndexQueryContext indexQueryContext() {
 +        IndexingQueryFilter filter = new IndexingQueryFilterImpl(kctx, topVer, parts);
-         IndexingQueryCacheFilter f = filter.forCache(cctx.name());
-         H2TreeFilterClosure filterC = null;
- 
-         if (f != null || mvccSnapshot != null )
-             filterC = new H2TreeFilterClosure(f, mvccSnapshot, cctx, ectx.planningContext().logger());
- 
-         return filterC;
++        return new IndexQueryContext(filter, mvccSnapshot);
 +    }
 +
 +    /** */
 +    private Value[] values(CacheObjectValueContext cctx, ExecutionContext<Row> ectx, Row row) {
 +        try {
 +            RowHandler<Row> rowHnd = ectx.rowHandler();
 +            int rowLen = rowHnd.columnCount(row);
 +
 +            Value[] values = new Value[rowLen];
 +            for (int i = 0; i < rowLen; i++) {
 +                Object o = rowHnd.get(i, row);
 +
 +                if (o != null)
 +                    values[i] = H2Utils.wrap(cctx, o, DataType.getTypeFromClass(o.getClass()));
 +            }
 +
 +            return values;
 +        }
 +        catch (IgniteCheckedException e) {
 +            throw new IgniteException("Failed to wrap object into H2 Value.", e);
 +        }
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/RuntimeTreeIndex.java
index 541ba60,0000000..7f125f9
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/RuntimeTreeIndex.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/RuntimeTreeIndex.java
@@@ -1,200 -1,0 +1,199 @@@
 +/*
 + * 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.calcite.exec;
 +
 +import java.util.ArrayList;
 +import java.util.Comparator;
 +import java.util.Iterator;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Objects;
 +import java.util.SortedMap;
 +import java.util.TreeMap;
 +import java.util.function.Predicate;
 +import java.util.function.Supplier;
- 
 +import org.apache.calcite.rel.RelCollation;
 +import org.apache.calcite.rel.type.RelDataType;
 +import org.apache.ignite.IgniteCheckedException;
- import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree;
++import org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext;
 +import org.apache.ignite.internal.processors.query.GridIndex;
 +import org.apache.ignite.internal.util.lang.GridCursor;
 +import org.apache.ignite.internal.util.typedef.F;
 +
 +/**
 + * Runtime sorted index based on on-heap tree.
 + */
 +public class RuntimeTreeIndex<Row> implements RuntimeIndex<Row>, GridIndex<Row> {
 +    /** */
 +    protected final ExecutionContext<Row> ectx;
 +
 +    /** */
 +    protected final Comparator<Row> comp;
 +
 +    /** Collation. */
 +    private final RelCollation collation;
 +
 +    /** Rows. */
 +    private TreeMap<Row, List<Row>> rows;
 +
 +    /**
 +     *
 +     */
 +    public RuntimeTreeIndex(
 +        ExecutionContext<Row> ectx,
 +        RelCollation collation,
 +        Comparator<Row> comp
 +    ) {
 +        this.ectx = ectx;
 +        this.comp = comp;
 +
 +        assert Objects.nonNull(collation);
 +
 +        this.collation = collation;
 +        rows = new TreeMap<>(comp);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void push(Row r) {
 +        List<Row> newEqRows = new ArrayList<>();
 +
 +        List<Row> eqRows = rows.putIfAbsent(r, newEqRows);
 +
 +        if (eqRows != null)
 +            eqRows.add(r);
 +        else
 +            newEqRows.add(r);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void close() {
 +        rows.clear();
 +    }
 +
 +    /** {@inheritDoc} */
-     @Override public GridCursor<Row> find(Row lower, Row upper, BPlusTree.TreeRowClosure<Row, Row> filterC) {
-         assert filterC == null;
++    @Override public GridCursor<Row> find(Row lower, Row upper, IndexQueryContext qctx) {
++        assert qctx == null;
 +
 +        int firstCol = F.first(collation.getKeys());
 +
 +        if (ectx.rowHandler().get(firstCol, lower) != null && ectx.rowHandler().get(firstCol, upper) != null)
 +            return new Cursor(rows.subMap(lower, true, upper, true));
 +        else if (ectx.rowHandler().get(firstCol, lower) == null && ectx.rowHandler().get(firstCol, upper) != null)
 +            return new Cursor(rows.headMap(upper, true));
 +        else if (ectx.rowHandler().get(firstCol, lower) != null && ectx.rowHandler().get(firstCol, upper) == null)
 +            return new Cursor(rows.tailMap(lower, true));
 +        else
 +            return new Cursor(rows);
 +    }
 +
 +    /**
 +     * Creates iterable on the index.
 +     */
 +    public Iterable<Row> scan(
 +        ExecutionContext<Row> ectx,
 +        RelDataType rowType,
 +        Predicate<Row> filter,
 +        Supplier<Row> lowerBound,
 +        Supplier<Row> upperBound
 +    ) {
 +        return new IndexScan(rowType, this, filter, lowerBound, upperBound);
 +    }
 +
 +    /**
 +     *
 +     */
 +    private class Cursor implements GridCursor<Row> {
 +        /** Sub map iterator. */
 +        private final Iterator<Map.Entry<Row, List<Row>>> mapIt;
 +
 +        /** Iterator over rows with equal index keys. */
 +        private Iterator<Row> listIt;
 +
 +        /** */
 +        private Row row;
 +
 +        /** */
 +        Cursor(SortedMap<Row, List<Row>> subMap) {
 +            mapIt = subMap.entrySet().iterator();
 +            listIt = null;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public boolean next() throws IgniteCheckedException {
 +            if (!hasNext())
 +                return false;
 +
 +            next0();
 +
 +            return true;
 +        }
 +
 +        /** */
 +        private boolean hasNext() {
 +            return listIt != null && listIt.hasNext() || mapIt.hasNext();
 +        }
 +
 +        /** */
 +        private void next0() {
 +            if (listIt == null || !listIt.hasNext())
 +                listIt = mapIt.next().getValue().iterator();
 +
 +            row = listIt.next();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public Row get() throws IgniteCheckedException {
 +            return row;
 +        }
 +    }
 +
 +    /**
 +     *
 +     */
 +    private class IndexScan extends AbstractIndexScan<Row, Row> {
 +        /**
 +         * @param rowType Row type.
 +         * @param idx Physical index.
 +         * @param filter Additional filters.
 +         * @param lowerBound Lower index scan bound.
 +         * @param upperBound Upper index scan bound.
 +         */
 +        IndexScan(
 +            RelDataType rowType,
 +            GridIndex<Row> idx,
 +            Predicate<Row> filter,
 +            Supplier<Row> lowerBound,
 +            Supplier<Row> upperBound) {
 +            super(RuntimeTreeIndex.this.ectx, rowType, idx, filter, lowerBound, upperBound, null);
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected Row row2indexRow(Row bound) {
 +            return bound;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected Row indexRow2Row(Row row) {
 +            return row;
 +        }
 +
 +        /** */
-         @Override protected BPlusTree.TreeRowClosure<Row, Row> filterClosure() {
++        @Override protected IndexQueryContext indexQueryContext() {
 +            return null;
 +        }
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ddl/DdlCommandHandler.java
index d07dbcc,0000000..17949c5
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ddl/DdlCommandHandler.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ddl/DdlCommandHandler.java
@@@ -1,246 -1,0 +1,249 @@@
 +/*
 + * 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.calcite.exec.ddl;
 +
 +import java.lang.reflect.Type;
 +import java.util.Collections;
 +import java.util.HashMap;
 +import java.util.HashSet;
 +import java.util.LinkedHashSet;
 +import java.util.Map;
 +import java.util.Set;
 +import java.util.function.Supplier;
 +
 +import org.apache.calcite.schema.SchemaPlus;
 +import org.apache.calcite.schema.Table;
 +import org.apache.ignite.IgniteCheckedException;
 +import org.apache.ignite.cache.QueryEntity;
 +import org.apache.ignite.configuration.CacheConfiguration;
 +import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
 +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
 +import org.apache.ignite.internal.processors.query.GridQueryProcessor;
 +import org.apache.ignite.internal.processors.query.IgniteSQLException;
 +import org.apache.ignite.internal.processors.query.QueryEntityEx;
 +import org.apache.ignite.internal.processors.query.QueryUtils;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.ddl.ColumnDefinition;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.ddl.CreateTableCommand;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.ddl.DdlCommand;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.ddl.DropTableCommand;
 +import org.apache.ignite.internal.processors.query.calcite.schema.IgniteTable;
 +import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
 +import org.apache.ignite.internal.processors.query.schema.SchemaOperationException;
 +import org.apache.ignite.internal.processors.security.IgniteSecurity;
 +import org.apache.ignite.internal.util.typedef.F;
 +import org.apache.ignite.lang.IgniteUuid;
 +import org.apache.ignite.plugin.security.SecurityPermission;
 +
 +import static org.apache.ignite.internal.processors.query.QueryUtils.convert;
 +import static org.apache.ignite.internal.processors.query.QueryUtils.isDdlOnSchemaSupported;
 +
 +/** */
 +public class DdlCommandHandler {
 +    /** */
 +    private final Supplier<GridQueryProcessor> qryProcessorSupp;
 +
 +    /** */
 +    private final GridCacheProcessor cacheProcessor;
 +
 +    /** */
 +    private final IgniteSecurity security;
 +
 +    /** */
 +    private final Supplier<SchemaPlus> schemaSupp;
 +
 +    /** */
 +    public DdlCommandHandler(Supplier<GridQueryProcessor> qryProcessorSupp, GridCacheProcessor cacheProcessor,
 +        IgniteSecurity security, Supplier<SchemaPlus> schemaSupp) {
 +        this.qryProcessorSupp = qryProcessorSupp;
 +        this.cacheProcessor = cacheProcessor;
 +        this.security = security;
 +        this.schemaSupp = schemaSupp;
 +    }
 +
 +    /** */
 +    public void handle(PlanningContext pctx, DdlCommand cmd) throws IgniteCheckedException {
 +        if (cmd instanceof CreateTableCommand)
 +            handle0(pctx, (CreateTableCommand)cmd);
 +
 +        else if (cmd instanceof DropTableCommand)
 +            handle0(pctx, (DropTableCommand)cmd);
 +
 +        else {
 +            throw new IgniteSQLException("Unsupported DDL operation [" +
 +                "cmdName=" + (cmd == null ? null : cmd.getClass().getSimpleName()) + "; " +
 +                "querySql=\"" + pctx.query() + "\"]", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
 +        }
 +    }
 +
 +    /** */
 +    private void handle0(PlanningContext pctx, CreateTableCommand cmd) throws IgniteCheckedException {
 +        security.authorize(cmd.cacheName(), SecurityPermission.CACHE_CREATE);
 +
 +        isDdlOnSchemaSupported(cmd.schemaName());
 +
 +        if (schemaSupp.get().getSubSchema(cmd.schemaName()).getTable(cmd.tableName()) != null) {
 +            if (cmd.ifNotExists())
 +                return;
 +
 +            throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_EXISTS, cmd.tableName());
 +        }
 +
 +        CacheConfiguration<?, ?> ccfg = new CacheConfiguration<>(cmd.tableName());
 +
 +        QueryEntity e = toQueryEntity(cmd, pctx);
 +
 +        ccfg.setQueryEntities(Collections.singleton(e));
 +        ccfg.setSqlSchema(cmd.schemaName());
 +
 +        SchemaOperationException err =
 +            QueryUtils.checkQueryEntityConflicts(ccfg, cacheProcessor.cacheDescriptors().values());
 +
 +        if (err != null)
 +            throw convert(err);
 +
 +        qryProcessorSupp.get().dynamicTableCreate(
 +            cmd.schemaName(),
 +            e,
 +            cmd.templateName(),
 +            cmd.cacheName(),
 +            cmd.cacheGroup(),
 +            cmd.dataRegionName(),
 +            cmd.affinityKey(),
 +            cmd.atomicityMode(),
 +            cmd.writeSynchronizationMode(),
 +            cmd.backups(),
 +            cmd.ifNotExists(),
 +            cmd.encrypted(),
 +            null
 +        );
 +    }
 +
 +    /** */
 +    private void handle0(PlanningContext pctx, DropTableCommand cmd) throws IgniteCheckedException {
 +        isDdlOnSchemaSupported(cmd.schemaName());
 +
 +        Table tbl = schemaSupp.get().getSubSchema(cmd.schemaName()).getTable(cmd.tableName());
 +
 +        if (tbl == null) {
 +            if (!cmd.ifExists())
 +                throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_NOT_FOUND, cmd.tableName());
 +
 +            return;
 +        }
 +
 +        String cacheName = ((IgniteTable)tbl).descriptor().cacheInfo().name();
 +
 +        security.authorize(cacheName, SecurityPermission.CACHE_DESTROY);
 +
 +        qryProcessorSupp.get().dynamicTableDrop(cacheName, cmd.tableName(), cmd.ifExists());
 +    }
 +
 +    /** */
 +    private QueryEntity toQueryEntity(CreateTableCommand cmd, PlanningContext pctx) {
 +        QueryEntity res = new QueryEntity();
 +
 +        res.setTableName(cmd.tableName());
 +
 +        Set<String> notNullFields = null;
 +
 +        HashMap<String, Object> dfltValues = new HashMap<>();
 +
 +        Map<String, Integer> precision = new HashMap<>();
 +        Map<String, Integer> scale = new HashMap<>();
 +
 +        IgniteTypeFactory tf = pctx.typeFactory();
 +
 +        for (ColumnDefinition col : cmd.columns()) {
 +            String name = col.name();
 +
 +            Type javaType = tf.getJavaClass(col.type());
 +
 +            String typeName = javaType instanceof Class ? ((Class<?>)javaType).getName() : javaType.getTypeName();
 +
 +            res.addQueryField(name, typeName, null);
 +
 +            if (!col.nullable()) {
 +                if (notNullFields == null)
 +                    notNullFields = new HashSet<>();
 +
 +                notNullFields.add(name);
 +            }
 +
 +            if (col.defaultValue() != null)
 +                dfltValues.put(name, col.defaultValue());
 +
 +            if (col.precision() != null)
 +                precision.put(name, col.precision());
 +
 +            if (col.scale() != null)
 +                scale.put(name, col.scale());
 +        }
 +
 +        if (!F.isEmpty(dfltValues))
 +            res.setDefaultFieldValues(dfltValues);
 +
 +        if (!F.isEmpty(precision))
 +            res.setFieldsPrecision(precision);
 +
 +        if (!F.isEmpty(scale))
 +            res.setFieldsScale(scale);
 +
 +        String valTypeName = QueryUtils.createTableValueTypeName(cmd.schemaName(), cmd.tableName());
 +
 +        String keyTypeName;
 +        if ((!F.isEmpty(cmd.primaryKeyColumns()) && cmd.primaryKeyColumns().size() > 1) || !F.isEmpty(cmd.keyTypeName())) {
 +            keyTypeName = cmd.keyTypeName();
 +
 +            if (F.isEmpty(keyTypeName))
 +                keyTypeName = QueryUtils.createTableKeyTypeName(valTypeName);
 +
-             if (!F.isEmpty(cmd.primaryKeyColumns()))
++            if (!F.isEmpty(cmd.primaryKeyColumns())) {
 +                res.setKeyFields(new LinkedHashSet<>(cmd.primaryKeyColumns()));
++
++                res = new QueryEntityEx(res).setPreserveKeysOrder(true);
++            }
 +        }
 +        else if (!F.isEmpty(cmd.primaryKeyColumns()) && cmd.primaryKeyColumns().size() == 1) {
 +            String pkFieldName = cmd.primaryKeyColumns().get(0);
 +
 +            keyTypeName = res.getFields().get(pkFieldName);
 +
 +            res.setKeyFieldName(pkFieldName);
 +        }
 +        else {
 +            // if pk is not explicitly set, we create it ourselves
 +            keyTypeName = IgniteUuid.class.getName();
 +
 +            res = new QueryEntityEx(res).implicitPk(true);
 +        }
 +
 +        res.setValueType(F.isEmpty(cmd.valueTypeName()) ? valTypeName : cmd.valueTypeName());
 +        res.setKeyType(keyTypeName);
 +
 +        if (!F.isEmpty(notNullFields)) {
 +            QueryEntityEx res0 = new QueryEntityEx(res);
 +
 +            res0.setNotNullFields(notNullFields);
 +
 +            res = res0;
 +        }
 +
 +        return res;
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/AccumulatorsFactory.java
index 3b8e5a6,0000000..4f4789c
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/AccumulatorsFactory.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/AccumulatorsFactory.java
@@@ -1,330 -1,0 +1,330 @@@
 +/*
 + * 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.calcite.exec.exp.agg;
 +
 +import java.lang.reflect.Modifier;
 +import java.util.List;
 +import java.util.concurrent.ExecutionException;
 +import java.util.function.Function;
 +import java.util.function.Supplier;
 +
 +import com.google.common.cache.CacheBuilder;
 +import com.google.common.cache.CacheLoader;
 +import com.google.common.cache.LoadingCache;
 +import com.google.common.collect.ImmutableList;
 +import com.google.common.primitives.Primitives;
 +import org.apache.calcite.DataContext;
 +import org.apache.calcite.adapter.enumerable.EnumUtils;
 +import org.apache.calcite.adapter.enumerable.JavaRowFormat;
 +import org.apache.calcite.adapter.enumerable.PhysTypeImpl;
 +import org.apache.calcite.adapter.enumerable.RexToLixTranslator;
 +import org.apache.calcite.linq4j.tree.BlockBuilder;
 +import org.apache.calcite.linq4j.tree.Expression;
 +import org.apache.calcite.linq4j.tree.Expressions;
 +import org.apache.calcite.linq4j.tree.MethodDeclaration;
 +import org.apache.calcite.linq4j.tree.ParameterExpression;
 +import org.apache.calcite.rel.core.AggregateCall;
 +import org.apache.calcite.rel.type.RelDataType;
 +import org.apache.calcite.rex.RexBuilder;
 +import org.apache.calcite.rex.RexNode;
 +import org.apache.calcite.rex.RexProgram;
 +import org.apache.calcite.rex.RexProgramBuilder;
 +import org.apache.calcite.sql.type.SqlTypeUtil;
 +import org.apache.calcite.sql.validate.SqlConformanceEnum;
 +import org.apache.calcite.util.Pair;
 +import org.apache.ignite.IgniteException;
 +import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
 +import org.apache.ignite.internal.processors.query.calcite.exec.RowHandler;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
 +import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
 +import org.apache.ignite.internal.processors.query.calcite.util.Commons;
 +import org.apache.ignite.internal.util.typedef.F;
 +import org.jetbrains.annotations.NotNull;
 +
 +import static org.apache.ignite.internal.processors.query.calcite.util.TypeUtils.createRowType;
 +
 +/** */
 +public class AccumulatorsFactory<Row> implements Supplier<List<AccumulatorWrapper<Row>>> {
 +    /** */
-     private static final LoadingCache<Pair<RelDataType,RelDataType>, Function<Object,Object>> CACHE =
++    private static final LoadingCache<Pair<RelDataType, RelDataType>, Function<Object, Object>> CACHE =
 +        CacheBuilder.newBuilder().build(CacheLoader.from(AccumulatorsFactory::cast0));
 +
 +    /** */
 +    public static interface CastFunction extends Function<Object, Object> {
 +        @Override Object apply(Object o);
 +    }
 +
 +    /** */
 +    private static Function<Object, Object> cast(RelDataType from, RelDataType to) {
 +        assert !from.isStruct();
 +        assert !to.isStruct();
 +
 +        return cast(Pair.of(from, to));
 +    }
 +
 +    /** */
 +    private static Function<Object, Object> cast(Pair<RelDataType, RelDataType> types) {
 +        try {
 +            return CACHE.get(types);
 +        }
 +        catch (ExecutionException e) {
 +            throw new IgniteException(e);
 +        }
 +    }
 +
 +    /** */
-     private static Function<Object, Object> cast0(Pair<RelDataType,RelDataType> types) {
++    private static Function<Object, Object> cast0(Pair<RelDataType, RelDataType> types) {
 +        IgniteTypeFactory typeFactory = PlanningContext.empty().typeFactory();
 +
 +        RelDataType from = types.left;
 +        RelDataType to = types.right;
 +
 +        Class<?> fromType = Primitives.wrap((Class<?>)typeFactory.getJavaClass(from));
 +        Class<?> toType = Primitives.wrap((Class<?>)typeFactory.getJavaClass(to));
 +
 +        if (toType.isAssignableFrom(fromType))
 +            return Function.identity();
 +
 +        if (Void.class == toType)
 +            return o -> null;
 +
 +        return compileCast(typeFactory, from, to);
 +    }
 +
 +    /** */
 +    private static Function<Object, Object> compileCast(IgniteTypeFactory typeFactory, RelDataType from,
 +        RelDataType to) {
 +        RelDataType rowType = createRowType(typeFactory, from);
 +        ParameterExpression in_ = Expressions.parameter(Object.class, "in");
 +
 +        RexToLixTranslator.InputGetter getter =
 +            new RexToLixTranslator.InputGetterImpl(
 +                ImmutableList.of(
 +                    Pair.of(EnumUtils.convert(in_, Object.class, typeFactory.getJavaClass(from)),
 +                        PhysTypeImpl.of(typeFactory, rowType,
 +                            JavaRowFormat.SCALAR, false))));
 +
 +        RexBuilder builder = new RexBuilder(typeFactory);
 +        RexProgramBuilder programBuilder = new RexProgramBuilder(rowType, builder);
 +        RexNode cast = builder.makeCast(to, builder.makeInputRef(from, 0));
 +        programBuilder.addProject(cast, null);
 +        RexProgram program = programBuilder.getProgram();
 +        BlockBuilder list = new BlockBuilder();
 +        List<Expression> projects = RexToLixTranslator.translateProjects(program, typeFactory, SqlConformanceEnum.DEFAULT,
 +            list, null, DataContext.ROOT, getter, null);
 +        list.add(projects.get(0));
 +
 +        MethodDeclaration decl = Expressions.methodDecl(
 +            Modifier.PUBLIC, Object.class, "apply", ImmutableList.of(in_), list.toBlock());
 +
 +        return Commons.compile(CastFunction.class, Expressions.toString(F.asList(decl), "\n", false));
 +    }
 +
 +    /** */
 +    private final ExecutionContext<Row> ctx;
 +
 +    /** */
 +    private final AggregateType type;
 +
 +    /** */
 +    private final RelDataType inputRowType;
 +
 +    /** */
 +    private final List<WrapperPrototype> prototypes;
 +
 +    /** */
 +    public AccumulatorsFactory(
 +        ExecutionContext<Row> ctx,
 +        AggregateType type,
 +        List<AggregateCall> aggCalls,
 +        RelDataType inputRowType
 +    ) {
 +        this.ctx = ctx;
 +        this.type = type;
 +        this.inputRowType = inputRowType;
 +
 +        prototypes = Commons.transform(aggCalls, WrapperPrototype::new);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public List<AccumulatorWrapper<Row>> get() {
 +        return Commons.transform(prototypes, WrapperPrototype::get);
 +    }
 +
 +    /** */
 +    private final class WrapperPrototype implements Supplier<AccumulatorWrapper<Row>> {
 +        /** */
 +        private Supplier<Accumulator> accFactory;
 +
 +        /** */
 +        private final AggregateCall call;
 +
 +        /** */
 +        private Function<Object[], Object[]> inAdapter;
 +
 +        /** */
 +        private Function<Object, Object> outAdapter;
 +
 +        /** */
 +        private WrapperPrototype(AggregateCall call) {
 +            this.call = call;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public AccumulatorWrapper<Row> get() {
 +            Accumulator accumulator = accumulator();
 +
 +            return new AccumulatorWrapperImpl(accumulator, call, inAdapter, outAdapter);
 +        }
 +
 +        /** */
 +        @NotNull private Accumulator accumulator() {
 +            if (accFactory != null)
 +                return accFactory.get();
 +
 +            // init factory and adapters
 +            accFactory = Accumulators.accumulatorFactory(call);
 +            Accumulator accumulator = accFactory.get();
 +
 +            inAdapter = createInAdapter(accumulator);
 +            outAdapter = createOutAdapter(accumulator);
 +
 +            return accumulator;
 +        }
 +
 +        /** */
 +        @NotNull private Function<Object[], Object[]> createInAdapter(Accumulator accumulator) {
 +            if (type == AggregateType.REDUCE || F.isEmpty(call.getArgList()))
 +                return Function.identity();
 +
 +            List<RelDataType> inTypes = SqlTypeUtil.projectTypes(inputRowType, call.getArgList());
 +            List<RelDataType> outTypes = accumulator.argumentTypes(ctx.getTypeFactory());
 +
 +            if (call.ignoreNulls())
 +                inTypes = Commons.transform(inTypes, this::nonNull);
 +
 +            List<Function<Object, Object>> casts =
 +                Commons.transform(Pair.zip(inTypes, outTypes), AccumulatorsFactory::cast);
 +
 +            return new Function<Object[], Object[]>() {
 +                @Override public Object[] apply(Object[] args) {
 +                    for (int i = 0; i < args.length; i++)
 +                        args[i] = casts.get(i).apply(args[i]);
 +                    return args;
 +                }
 +            };
 +        }
 +
 +        /** */
 +        @NotNull private Function<Object, Object> createOutAdapter(Accumulator accumulator) {
 +            if (type == AggregateType.MAP)
 +                return Function.identity();
 +
 +            RelDataType inType = accumulator.returnType(ctx.getTypeFactory());
 +            RelDataType outType = call.getType();
 +
 +            return cast(inType, outType);
 +        }
 +
 +        /** */
 +        private RelDataType nonNull(RelDataType type) {
 +            return ctx.getTypeFactory().createTypeWithNullability(type, false);
 +        }
 +    }
 +
 +    /** */
 +    private final class AccumulatorWrapperImpl implements AccumulatorWrapper<Row> {
 +        /** */
 +        private final Accumulator accumulator;
 +
 +        /** */
 +        private final Function<Object[], Object[]> inAdapter;
 +
 +        /** */
 +        private final Function<Object, Object> outAdapter;
 +
 +        /** */
 +        private final List<Integer> argList;
 +
 +        /** */
 +        private final int filterArg;
 +
 +        /** */
 +        private final boolean ignoreNulls;
 +
 +        /** */
 +        private final RowHandler<Row> handler;
 +
 +        /** */
 +        AccumulatorWrapperImpl(
 +            Accumulator accumulator,
 +            AggregateCall call,
 +            Function<Object[], Object[]> inAdapter,
 +            Function<Object, Object> outAdapter
 +        ) {
 +            this.accumulator = accumulator;
 +            this.inAdapter = inAdapter;
 +            this.outAdapter = outAdapter;
 +
 +            argList = call.getArgList();
 +            ignoreNulls = call.ignoreNulls();
 +            filterArg = call.hasFilter() ? call.filterArg : -1;
 +
 +            handler = ctx.rowHandler();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public void add(Row row) {
 +            assert type != AggregateType.REDUCE;
 +
 +            if (filterArg >= 0 && Boolean.TRUE != handler.get(filterArg, row))
 +                return;
 +
 +            Object[] args = new Object[argList.size()];
 +            for (int i = 0; i < argList.size(); i++) {
 +                args[i] = handler.get(argList.get(i), row);
 +
 +                if (ignoreNulls && args[i] == null)
 +                    return;
 +            }
 +
 +            accumulator.add(inAdapter.apply(args));
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public Object end() {
 +            assert type != AggregateType.MAP;
 +
 +            return outAdapter.apply(accumulator.end());
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public void apply(Accumulator accumulator) {
 +            assert type == AggregateType.REDUCE;
 +
 +            this.accumulator.apply(accumulator);
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public Accumulator accumulator() {
 +            assert type == AggregateType.MAP;
 +
 +            return accumulator;
 +        }
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/MergeJoinNode.java
index 3d291c7,0000000..6e38925
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/MergeJoinNode.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/MergeJoinNode.java
@@@ -1,1132 -1,0 +1,1133 @@@
 +/*
 + * 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.calcite.exec.rel;
 +
 +import java.util.ArrayDeque;
 +import java.util.ArrayList;
 +import java.util.Comparator;
 +import java.util.Deque;
 +import java.util.List;
 +
 +import org.apache.calcite.rel.core.JoinRelType;
 +import org.apache.calcite.rel.type.RelDataType;
 +import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
 +import org.apache.ignite.internal.processors.query.calcite.exec.RowHandler;
 +import org.apache.ignite.internal.util.typedef.F;
 +import org.jetbrains.annotations.NotNull;
 +
 +/** */
 +public abstract class MergeJoinNode<Row> extends AbstractNode<Row> {
 +    /** Special value to highlights that all row were received and we are not waiting any more. */
 +    protected static final int NOT_WAITING = -1;
 +
 +    /** */
 +    protected final Comparator<Row> comp;
 +
 +    /** */
 +    protected final RowHandler<Row> handler;
 +
 +    /** */
 +    protected int requested;
 +
 +    /** */
 +    protected int waitingLeft;
 +
 +    /** */
 +    protected int waitingRight;
 +
 +    /** */
 +    protected final Deque<Row> rightInBuf = new ArrayDeque<>(IN_BUFFER_SIZE);
 +
 +    /** */
 +    protected final Deque<Row> leftInBuf = new ArrayDeque<>(IN_BUFFER_SIZE);
 +
 +    /** */
 +    protected boolean inLoop;
 +
 +    /**
 +     * @param ctx Execution context.
 +     * @param comp Join expression.
 +     */
 +    private MergeJoinNode(ExecutionContext<Row> ctx, RelDataType rowType, Comparator<Row> comp) {
 +        super(ctx, rowType);
 +
 +        this.comp = comp;
 +        handler = ctx.rowHandler();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void request(int rowsCnt) throws Exception {
 +        assert !F.isEmpty(sources()) && sources().size() == 2;
 +        assert rowsCnt > 0 && requested == 0;
 +
 +        checkState();
 +
 +        requested = rowsCnt;
 +
 +        if (!inLoop)
 +            context().execute(this::doJoin, this::onError);
 +    }
 +
 +    /** */
 +    private void doJoin() throws Exception {
 +        checkState();
 +
 +        join();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected void rewindInternal() {
 +        requested = 0;
 +        waitingLeft = 0;
 +        waitingRight = 0;
 +
 +        rightInBuf.clear();
 +        leftInBuf.clear();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected Downstream<Row> requestDownstream(int idx) {
 +        if (idx == 0)
 +            return new Downstream<Row>() {
 +                /** {@inheritDoc} */
 +                @Override public void push(Row row) throws Exception {
 +                    pushLeft(row);
 +                }
 +
 +                /** {@inheritDoc} */
 +                @Override public void end() throws Exception {
 +                    endLeft();
 +                }
 +
 +                /** {@inheritDoc} */
 +                @Override public void onError(Throwable e) {
 +                    MergeJoinNode.this.onError(e);
 +                }
 +            };
 +        else if (idx == 1)
 +            return new Downstream<Row>() {
 +                /** {@inheritDoc} */
 +                @Override public void push(Row row) throws Exception {
 +                    pushRight(row);
 +                }
 +
 +                /** {@inheritDoc} */
 +                @Override public void end() throws Exception {
 +                    endRight();
 +                }
 +
 +                /** {@inheritDoc} */
 +                @Override public void onError(Throwable e) {
 +                    MergeJoinNode.this.onError(e);
 +                }
 +            };
 +
 +        throw new IndexOutOfBoundsException();
 +    }
 +
 +    /** */
 +    private void pushLeft(Row row) throws Exception {
 +        assert downstream() != null;
 +        assert waitingLeft > 0;
 +
 +        checkState();
 +
 +        waitingLeft--;
 +
 +        leftInBuf.add(row);
 +
 +        join();
 +    }
 +
 +    /** */
 +    private void pushRight(Row row) throws Exception {
 +        assert downstream() != null;
 +        assert waitingRight > 0;
 +
 +        checkState();
 +
 +        waitingRight--;
 +
 +        rightInBuf.add(row);
 +
 +        join();
 +    }
 +
 +    /** */
 +    private void endLeft() throws Exception {
 +        assert downstream() != null;
 +        assert waitingLeft > 0;
 +
 +        checkState();
 +
 +        waitingLeft = NOT_WAITING;
 +
 +        join();
 +    }
 +
 +    /** */
 +    private void endRight() throws Exception {
 +        assert downstream() != null;
 +        assert waitingRight > 0;
 +
 +        checkState();
 +
 +        waitingRight = NOT_WAITING;
 +
 +        join();
 +    }
 +
 +    /** */
 +    protected Node<Row> leftSource() {
 +        return sources().get(0);
 +    }
 +
 +    /** */
 +    protected Node<Row> rightSource() {
 +        return sources().get(1);
 +    }
 +
 +    /** */
 +    protected abstract void join() throws Exception;
 +
 +    /** */
 +    @NotNull public static <Row> MergeJoinNode<Row> create(ExecutionContext<Row> ctx, RelDataType outputRowType, RelDataType leftRowType,
 +        RelDataType rightRowType, JoinRelType joinType, Comparator<Row> comp) {
 +        switch (joinType) {
 +            case INNER:
 +                return new InnerJoin<>(ctx, outputRowType, comp);
 +
 +            case LEFT: {
 +                RowHandler.RowFactory<Row> rightRowFactory = ctx.rowHandler().factory(ctx.getTypeFactory(), rightRowType);
 +
 +                return new LeftJoin<>(ctx, outputRowType, comp, rightRowFactory);
 +            }
 +
 +            case RIGHT: {
 +                RowHandler.RowFactory<Row> leftRowFactory = ctx.rowHandler().factory(ctx.getTypeFactory(), leftRowType);
 +
 +                return new RightJoin<>(ctx, outputRowType, comp, leftRowFactory);
 +            }
 +
 +            case FULL: {
 +                RowHandler.RowFactory<Row> leftRowFactory = ctx.rowHandler().factory(ctx.getTypeFactory(), leftRowType);
 +                RowHandler.RowFactory<Row> rightRowFactory = ctx.rowHandler().factory(ctx.getTypeFactory(), rightRowType);
 +
 +                return new FullOuterJoin<>(ctx, outputRowType, comp, leftRowFactory, rightRowFactory);
 +            }
 +
 +            case SEMI:
 +                return new SemiJoin<>(ctx, outputRowType, comp);
 +
 +            case ANTI:
 +                return new AntiJoin<>(ctx, outputRowType, comp);
 +
 +            default:
 +                throw new IllegalStateException("Join type \"" + joinType + "\" is not supported yet");
 +        }
 +    }
 +
 +    /** */
 +    private static class InnerJoin<Row> extends MergeJoinNode<Row> {
 +        /** */
 +        private Row left;
 +
 +        /** */
 +        private Row right;
 +
 +        /** Used to store similar rows of rights stream in many-to-many join mode. */
 +        private List<Row> rightMaterialization;
 +
 +        /** */
 +        private int rightIdx;
 +
 +        /** */
 +        private boolean drainMaterialization;
 +
 +        /**
 +         * @param ctx Execution context.
 +         * @param rowType Row type.
 +         * @param comp Join expression comparator.
 +         */
 +        public InnerJoin(ExecutionContext<Row> ctx, RelDataType rowType, Comparator<Row> comp) {
 +            super(ctx, rowType, comp);
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void rewindInternal() {
 +            left = null;
 +            right = null;
 +            rightIdx = 0;
 +            rightMaterialization = null;
 +            drainMaterialization = false;
 +
 +            super.rewindInternal();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void join() throws Exception {
 +            inLoop = true;
 +            try {
 +                while (requested > 0 && (left != null || !leftInBuf.isEmpty()) && (right != null || !rightInBuf.isEmpty()
 +                    || rightMaterialization != null)) {
 +                    checkState();
 +
 +                    if (left == null)
 +                        left = leftInBuf.remove();
 +
 +                    if (right == null) {
 +                        if (rightInBuf.isEmpty() && waitingRight != NOT_WAITING)
 +                            break;
 +
 +                        if (!rightInBuf.isEmpty())
 +                            right = rightInBuf.remove();
 +                    }
 +
 +                    if (right == null && rightMaterialization != null && !drainMaterialization) {
 +                        drainMaterialization = true;
 +                        left = null;
 +
 +                        continue;
 +                    }
 +
 +                    Row row;
 +                    if (!drainMaterialization) {
 +                        int cmp = comp.compare(left, right);
 +
 +                        if (cmp < 0) {
 +                            left = null;
 +                            rightIdx = 0;
 +
 +                            if (rightMaterialization != null)
 +                                drainMaterialization = true;
 +
 +                            continue;
 +                        }
 +                        else if (cmp > 0) {
 +                            right = null;
 +                            rightIdx = 0;
 +                            rightMaterialization = null;
 +
 +                            continue;
 +                        }
 +
 +                        if (rightMaterialization == null && (!rightInBuf.isEmpty() || waitingRight != NOT_WAITING)) {
 +                            if (rightInBuf.isEmpty())
 +                                break;
 +
 +                            if (comp.compare(left, rightInBuf.peek()) == 0)
 +                                rightMaterialization = new ArrayList<>();
 +                        }
 +
 +                        row = handler.concat(left, right);
 +
 +                        if (rightMaterialization != null) {
 +                            rightMaterialization.add(right);
 +
 +                            right = null;
 +                        }
 +                        else
 +                            left = null;
 +                    }
 +                    else {
 +                        if (rightIdx >= rightMaterialization.size()) {
 +                            rightIdx = 0;
 +                            left = null;
 +
 +                            continue;
 +                        }
 +
 +                        Row right = rightMaterialization.get(rightIdx++);
 +
 +                        int cmp = comp.compare(left, right);
 +
 +                        if (cmp > 0) {
 +                            rightIdx = 0;
 +                            rightMaterialization = null;
 +                            drainMaterialization = false;
 +
 +                            continue;
 +                        }
 +
 +                        row = handler.concat(left, right);
 +                    }
 +
 +                    requested--;
 +                    downstream().push(row);
 +                }
 +            }
 +            finally {
 +                inLoop = false;
 +            }
 +
 +            if (waitingRight == 0)
 +                rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +
 +            if (waitingLeft == 0)
 +                leftSource().request(waitingLeft = IN_BUFFER_SIZE);
 +
 +            if (requested > 0 && ((waitingLeft == NOT_WAITING && left == null && leftInBuf.isEmpty())
 +                || (waitingRight == NOT_WAITING && right == null && rightInBuf.isEmpty() && rightMaterialization == null))
 +            ) {
 +                requested = 0;
 +                downstream().end();
 +            }
 +        }
 +    }
 +
 +    /** */
 +    private static class LeftJoin<Row> extends MergeJoinNode<Row> {
 +        /** Right row factory. */
 +        private final RowHandler.RowFactory<Row> rightRowFactory;
 +
 +        /** */
 +        private Row left;
 +
 +        /** */
 +        private Row right;
 +
 +        /** Used to store similar rows of rights stream in many-to-many join mode. */
 +        private List<Row> rightMaterialization;
 +
 +        /** */
 +        private int rightIdx;
 +
 +        /** */
 +        private boolean drainMaterialization;
 +
 +        /** Whether current left row was matched (hence pushed to downstream) or not. */
 +        private boolean matched;
 +
 +        /**
 +         * @param ctx Execution context.
 +         * @param rowType Row type.
 +         * @param comp Join expression comparator.
 +         * @param rightRowFactory Right row factory.
 +         */
 +        public LeftJoin(ExecutionContext<Row> ctx, RelDataType rowType, Comparator<Row> comp, RowHandler.RowFactory<Row> rightRowFactory) {
 +            super(ctx, rowType, comp);
 +
 +            this.rightRowFactory = rightRowFactory;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void rewindInternal() {
 +            left = null;
 +            right = null;
 +            rightIdx = 0;
 +            rightMaterialization = null;
 +            drainMaterialization = false;
 +
 +            super.rewindInternal();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void join() throws Exception {
 +            inLoop = true;
 +            try {
 +                while (requested > 0 && (left != null || !leftInBuf.isEmpty())
 +                    && !(right == null && rightInBuf.isEmpty() && rightMaterialization == null && waitingRight != NOT_WAITING)) {
 +                    checkState();
 +
 +                    if (left == null) {
 +                        left = leftInBuf.remove();
 +
 +                        matched = false;
 +                    }
 +
 +                    if (right == null && !rightInBuf.isEmpty())
 +                        right = rightInBuf.remove();
 +
 +                    if (right == null && rightMaterialization != null && !drainMaterialization) {
 +                        drainMaterialization = true;
 +                        left = null;
 +
 +                        continue;
 +                    }
 +
 +                    Row row;
 +                    if (!drainMaterialization) {
 +                        if (right == null) {
 +                            row = handler.concat(left, rightRowFactory.create());
 +
 +                            requested--;
 +                            downstream().push(row);
 +
 +                            left = null;
 +
 +                            continue;
 +                        }
 +
 +                        int cmp = comp.compare(left, right);
 +
 +                        if (cmp < 0) {
 +                            if (!matched) {
 +                                row = handler.concat(left, rightRowFactory.create());
 +
 +                                requested--;
 +                                downstream().push(row);
 +                            }
 +
 +                            left = null;
 +                            rightIdx = 0;
 +
 +                            if (rightMaterialization != null)
 +                                drainMaterialization = true;
 +
 +                            continue;
 +                        }
 +                        else if (cmp > 0) {
 +                            right = null;
 +                            rightIdx = 0;
 +                            rightMaterialization = null;
 +
 +                            continue;
 +                        }
 +
 +                        matched = true;
 +
 +                        if (rightMaterialization == null && (!rightInBuf.isEmpty() || waitingRight != NOT_WAITING)) {
 +                            if (rightInBuf.isEmpty())
 +                                break;
 +
 +                            if (comp.compare(left, rightInBuf.peek()) == 0)
 +                                rightMaterialization = new ArrayList<>();
 +                        }
 +
 +                        row = handler.concat(left, right);
 +
 +                        if (rightMaterialization != null) {
 +                            rightMaterialization.add(right);
 +
 +                            right = null;
 +                        }
 +                        else
 +                            left = null;
 +                    }
 +                    else {
 +                        if (rightIdx >= rightMaterialization.size()) {
 +                            rightIdx = 0;
 +                            left = null;
 +
 +                            continue;
 +                        }
 +
 +                        Row right = rightMaterialization.get(rightIdx++);
 +
 +                        int cmp = comp.compare(left, right);
 +
 +                        if (cmp > 0) {
 +                            rightIdx = 0;
 +                            rightMaterialization = null;
 +                            drainMaterialization = false;
 +
 +                            continue;
 +                        }
 +
 +                        row = handler.concat(left, right);
 +                    }
 +
 +                    requested--;
 +                    downstream().push(row);
 +                }
 +            }
 +            finally {
 +                inLoop = false;
 +            }
 +
 +            if (waitingRight == 0)
 +                rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +
 +            if (waitingLeft == 0)
 +                leftSource().request(waitingLeft = IN_BUFFER_SIZE);
 +
 +            if (requested > 0 && waitingLeft == NOT_WAITING && left == null && leftInBuf.isEmpty()) {
 +                requested = 0;
 +                downstream().end();
 +            }
 +        }
 +    }
 +
 +    /** */
 +    private static class RightJoin<Row> extends MergeJoinNode<Row> {
 +        /** Right row factory. */
 +        private final RowHandler.RowFactory<Row> leftRowFactory;
 +
 +        /** */
 +        private Row left;
 +
 +        /** */
 +        private Row right;
 +
 +        /** Used to store similar rows of rights stream in many-to-many join mode. */
 +        private List<Row> rightMaterialization;
 +
 +        /** */
 +        private int rightIdx;
 +
 +        /** */
 +        private boolean drainMaterialization;
 +
 +        /** Whether current right row was matched (hence pushed to downstream) or not. */
 +        private boolean matched;
 +
 +        /**
 +         * @param ctx Execution context.
 +         * @param rowType Row type.
 +         * @param comp Join expression comparator.
 +         * @param leftRowFactory Left row factory.
 +         */
 +        public RightJoin(ExecutionContext<Row> ctx, RelDataType rowType, Comparator<Row> comp, RowHandler.RowFactory<Row> leftRowFactory) {
 +            super(ctx, rowType, comp);
 +
 +            this.leftRowFactory = leftRowFactory;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void rewindInternal() {
 +            left = null;
 +            right = null;
 +            rightIdx = 0;
 +            rightMaterialization = null;
 +            drainMaterialization = false;
 +
 +            super.rewindInternal();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void join() throws Exception {
 +            inLoop = true;
 +            try {
 +                while (requested > 0 && !(left == null && leftInBuf.isEmpty() && waitingLeft != NOT_WAITING)
 +                    && (right != null || !rightInBuf.isEmpty() || rightMaterialization != null)) {
 +                    checkState();
 +
 +                    if (left == null && !leftInBuf.isEmpty())
 +                        left = leftInBuf.remove();
 +
 +                    if (right == null) {
 +                        if (rightInBuf.isEmpty() && waitingRight != NOT_WAITING)
 +                            break;
 +
 +                        if (!rightInBuf.isEmpty()) {
 +                            right = rightInBuf.remove();
 +
 +                            matched = false;
 +                        }
 +                    }
 +
 +                    if (right == null && rightMaterialization != null && !drainMaterialization) {
 +                        drainMaterialization = true;
 +                        left = null;
 +
 +                        continue;
 +                    }
 +
 +                    Row row;
 +                    if (!drainMaterialization) {
 +                        if (left == null) {
 +                            if (!matched) {
 +                                row = handler.concat(leftRowFactory.create(), right);
 +
 +                                requested--;
 +                                downstream().push(row);
 +                            }
 +
 +                            right = null;
 +
 +                            continue;
 +                        }
 +
 +                        int cmp = comp.compare(left, right);
 +
 +                        if (cmp < 0) {
 +                            left = null;
 +                            rightIdx = 0;
 +
 +                            if (rightMaterialization != null)
 +                                drainMaterialization = true;
 +
 +                            continue;
 +                        }
 +                        else if (cmp > 0) {
 +                            if (!matched) {
 +                                row = handler.concat(leftRowFactory.create(), right);
 +
 +                                requested--;
 +                                downstream().push(row);
 +                            }
 +
 +                            right = null;
 +                            rightIdx = 0;
 +                            rightMaterialization = null;
 +
 +                            continue;
 +                        }
 +
 +                        if (rightMaterialization == null && (!rightInBuf.isEmpty() || waitingRight != NOT_WAITING)) {
 +                            if (rightInBuf.isEmpty())
 +                                break;
 +
 +                            if (comp.compare(left, rightInBuf.peek()) == 0)
 +                                rightMaterialization = new ArrayList<>();
 +                        }
 +
 +                        matched = true;
 +
 +                        row = handler.concat(left, right);
 +
 +                        if (rightMaterialization != null) {
 +                            rightMaterialization.add(right);
 +
 +                            right = null;
 +                        }
 +                        else
 +                            left = null;
 +                    }
 +                    else {
 +                        if (left == null) {
 +                            if (waitingLeft == NOT_WAITING)
 +                                rightMaterialization = null;
 +
 +                            break;
 +                        }
 +
 +                        if (rightIdx >= rightMaterialization.size()) {
 +                            rightIdx = 0;
 +                            left = null;
 +
 +                            continue;
 +                        }
 +
 +                        Row right = rightMaterialization.get(rightIdx++);
 +
 +                        int cmp = comp.compare(left, right);
 +
 +                        if (cmp > 0) {
 +                            rightIdx = 0;
 +                            rightMaterialization = null;
 +                            drainMaterialization = false;
 +
 +                            continue;
 +                        }
 +
 +                        row = handler.concat(left, right);
 +                    }
 +
 +                    requested--;
 +                    downstream().push(row);
 +                }
 +            }
 +            finally {
 +                inLoop = false;
 +            }
 +
 +            if (waitingRight == 0)
 +                rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +
 +            if (waitingLeft == 0)
 +                leftSource().request(waitingLeft = IN_BUFFER_SIZE);
 +
 +            if (requested > 0 && waitingRight == NOT_WAITING && right == null && rightInBuf.isEmpty() && rightMaterialization == null) {
 +                requested = 0;
 +                downstream().end();
 +            }
 +        }
 +    }
 +
 +    /** */
 +    private static class FullOuterJoin<Row> extends MergeJoinNode<Row> {
 +        /** Left row factory. */
 +        private final RowHandler.RowFactory<Row> leftRowFactory;
 +
 +        /** Right row factory. */
 +        private final RowHandler.RowFactory<Row> rightRowFactory;
 +
 +        /** */
 +        private Row left;
 +
 +        /** */
 +        private Row right;
 +
 +        /** Used to store similar rows of rights stream in many-to-many join mode. */
 +        private List<Row> rightMaterialization;
 +
 +        /** */
 +        private int rightIdx;
 +
 +        /** */
 +        private boolean drainMaterialization;
 +
 +        /** Whether current left row was matched (hence pushed to downstream) or not. */
 +        private boolean leftMatched;
 +
 +        /** Whether current right row was matched (hence pushed to downstream) or not. */
 +        private boolean rightMatched;
 +
 +        /**
 +         * @param ctx Execution context.
 +         * @param rowType Row type.
 +         * @param comp Join expression comparator.
 +         * @param leftRowFactory Left row factory.
 +         * @param rightRowFactory Right row factory.
 +         */
 +        public FullOuterJoin(ExecutionContext<Row> ctx, RelDataType rowType, Comparator<Row> comp,
 +            RowHandler.RowFactory<Row> leftRowFactory, RowHandler.RowFactory<Row> rightRowFactory) {
 +            super(ctx, rowType, comp);
 +
 +            this.leftRowFactory = leftRowFactory;
 +            this.rightRowFactory = rightRowFactory;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void rewindInternal() {
 +            left = null;
 +            right = null;
 +            rightIdx = 0;
 +            rightMaterialization = null;
 +            drainMaterialization = false;
 +
 +            super.rewindInternal();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void join() throws Exception {
 +            inLoop = true;
 +            try {
 +                while (requested > 0 && !(left == null && leftInBuf.isEmpty() && waitingLeft != NOT_WAITING)
 +                    && !(right == null && rightInBuf.isEmpty() && rightMaterialization == null && waitingRight != NOT_WAITING)) {
 +                    checkState();
 +
 +                    if (left == null && !leftInBuf.isEmpty()) {
 +                        left = leftInBuf.remove();
 +
 +                        leftMatched = false;
 +                    }
 +
 +                    if (right == null) {
 +                        if (rightInBuf.isEmpty() && waitingRight != NOT_WAITING)
 +                            break;
 +
 +                        if (!rightInBuf.isEmpty()) {
 +                            right = rightInBuf.remove();
 +
 +                            rightMatched = false;
 +                        }
 +                    }
 +
 +                    if (right == null && rightMaterialization != null && !drainMaterialization) {
 +                        drainMaterialization = true;
 +                        left = null;
 +
 +                        continue;
 +                    }
 +
 +                    Row row;
 +                    if (!drainMaterialization) {
 +                        if (left == null || right == null) {
 +                            if (left == null && right != null) {
 +                                if (!rightMatched) {
 +                                    row = handler.concat(leftRowFactory.create(), right);
 +
 +                                    requested--;
 +                                    downstream().push(row);
 +                                }
 +
 +                                right = null;
 +
 +                                continue;
 +                            }
 +
 +                            if (left != null && right == null) {
 +                                if (!leftMatched) {
 +                                    row = handler.concat(left, rightRowFactory.create());
 +
 +                                    requested--;
 +                                    downstream().push(row);
 +                                }
 +
 +                                left = null;
 +
 +                                continue;
 +                            }
 +
 +                            break;
 +                        }
 +
 +                        int cmp = comp.compare(left, right);
 +
 +                        if (cmp < 0) {
 +                            if (!leftMatched) {
 +                                row = handler.concat(left, rightRowFactory.create());
 +
 +                                requested--;
 +                                downstream().push(row);
 +                            }
 +
 +                            left = null;
 +                            rightIdx = 0;
 +
 +                            if (rightMaterialization != null)
 +                                drainMaterialization = true;
 +
 +                            continue;
 +                        }
 +                        else if (cmp > 0) {
 +                            if (!rightMatched) {
 +                                row = handler.concat(leftRowFactory.create(), right);
 +
 +                                requested--;
 +                                downstream().push(row);
 +                            }
 +
 +                            right = null;
 +                            rightIdx = 0;
 +                            rightMaterialization = null;
 +
 +                            continue;
 +                        }
 +
 +                        if (rightMaterialization == null && (!rightInBuf.isEmpty() || waitingRight != NOT_WAITING)) {
 +                            if (rightInBuf.isEmpty())
 +                                break;
 +
 +                            if (comp.compare(left, rightInBuf.peek()) == 0)
 +                                rightMaterialization = new ArrayList<>();
 +                        }
 +
 +                        leftMatched = true;
 +                        rightMatched = true;
 +
 +                        row = handler.concat(left, right);
 +
 +                        if (rightMaterialization != null) {
 +                            rightMaterialization.add(right);
 +
 +                            right = null;
 +                        }
 +                        else
 +                            left = null;
 +                    }
 +                    else {
 +                        if (left == null) {
 +                            if (waitingLeft == NOT_WAITING)
 +                                rightMaterialization = null;
 +
 +                            break;
 +                        }
 +
 +                        if (rightIdx >= rightMaterialization.size()) {
 +                            rightIdx = 0;
 +                            left = null;
 +
 +                            continue;
 +                        }
 +
 +                        Row right = rightMaterialization.get(rightIdx++);
 +
 +                        int cmp = comp.compare(left, right);
 +
 +                        if (cmp > 0) {
 +                            rightIdx = 0;
 +                            rightMaterialization = null;
 +                            drainMaterialization = false;
 +
 +                            continue;
 +                        }
 +
 +                        leftMatched = true;
 +
 +                        row = handler.concat(left, right);
 +                    }
 +
 +                    requested--;
 +                    downstream().push(row);
 +                }
 +            }
 +            finally {
 +                inLoop = false;
 +            }
 +
 +            if (waitingRight == 0)
 +                rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +
 +            if (waitingLeft == 0)
 +                leftSource().request(waitingLeft = IN_BUFFER_SIZE);
 +
 +            if (requested > 0 && waitingLeft == NOT_WAITING && left == null && leftInBuf.isEmpty()
 +                && waitingRight == NOT_WAITING && right == null && rightInBuf.isEmpty() && rightMaterialization == null
 +            ) {
 +                requested = 0;
 +                downstream().end();
 +            }
 +        }
 +    }
 +
 +    /** */
 +    private static class SemiJoin<Row> extends MergeJoinNode<Row> {
 +        /** */
 +        private Row left;
 +
 +        /** */
 +        private Row right;
 +
 +        /**
 +         * @param ctx Execution context.
 +         * @param rowType Row type.
 +         * @param comp Join expression comparator.
 +         */
 +        public SemiJoin(ExecutionContext<Row> ctx, RelDataType rowType, Comparator<Row> comp) {
 +            super(ctx, rowType, comp);
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void rewindInternal() {
 +            left = null;
 +            right = null;
 +
 +            super.rewindInternal();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void join() throws Exception {
 +            inLoop = true;
 +            try {
 +                while (requested > 0 && (left != null || !leftInBuf.isEmpty()) && (right != null || !rightInBuf.isEmpty())) {
 +                    checkState();
 +
 +                    if (left == null)
 +                        left = leftInBuf.remove();
 +
 +                    if (right == null)
 +                        right = rightInBuf.remove();
 +
 +                    int cmp = comp.compare(left, right);
 +
 +                    if (cmp < 0) {
 +                        left = null;
 +
 +                        continue;
 +                    }
 +                    else if (cmp > 0) {
 +                        right = null;
 +
 +                        continue;
 +                    }
 +
 +                    requested--;
 +                    downstream().push(left);
 +
 +                    left = null;
 +                }
 +            }
 +            finally {
 +                inLoop = false;
 +            }
 +
 +            if (waitingRight == 0)
 +                rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +
 +            if (waitingLeft == 0)
 +                leftSource().request(waitingLeft = IN_BUFFER_SIZE);
 +
 +            if (requested > 0 && ((waitingLeft == NOT_WAITING && left == null && leftInBuf.isEmpty()
 +                || (waitingRight == NOT_WAITING && right == null && rightInBuf.isEmpty())))
 +            ) {
 +                requested = 0;
 +                downstream().end();
 +            }
 +        }
 +    }
 +
 +    /** */
 +    private static class AntiJoin<Row> extends MergeJoinNode<Row> {
 +        /** */
 +        private Row left;
 +
 +        /** */
 +        private Row right;
 +
 +        /**
 +         * @param ctx Execution context.
 +         * @param rowType Row type.
 +         * @param comp Join expression comparator.
 +         */
 +        public AntiJoin(ExecutionContext<Row> ctx, RelDataType rowType, Comparator<Row> comp) {
 +            super(ctx, rowType, comp);
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void rewindInternal() {
 +            left = null;
 +            right = null;
 +
 +            super.rewindInternal();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void join() throws Exception {
 +            inLoop = true;
 +            try {
-                 while (requested > 0 && (left != null || !leftInBuf.isEmpty()) && !(right == null && rightInBuf.isEmpty() && waitingRight != NOT_WAITING)) {
++                while (requested > 0 && (left != null || !leftInBuf.isEmpty()) &&
++                    !(right == null && rightInBuf.isEmpty() && waitingRight != NOT_WAITING)) {
 +                    checkState();
 +
 +                    if (left == null)
 +                        left = leftInBuf.remove();
 +
 +                    if (right == null && !rightInBuf.isEmpty())
 +                        right = rightInBuf.remove();
 +
 +                    if (right != null) {
 +                        int cmp = comp.compare(left, right);
 +
 +                        if (cmp == 0) {
 +                            left = null;
 +
 +                            continue;
 +                        }
 +                        else if (cmp > 0) {
 +                            right = null;
 +
 +                            continue;
 +                        }
 +                    }
 +
 +                    requested--;
 +                    downstream().push(left);
 +
 +                    left = null;
 +                }
 +            }
 +            finally {
 +                inLoop = false;
 +            }
 +
 +            if (waitingRight == 0)
 +                rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +
 +            if (waitingLeft == 0)
 +                leftSource().request(waitingLeft = IN_BUFFER_SIZE);
 +
 +            if (requested > 0 && waitingLeft == NOT_WAITING && left == null && leftInBuf.isEmpty()) {
 +                requested = 0;
 +                downstream().end();
 +            }
 +        }
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java
index d1aaa38,0000000..3dc3edc
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java
@@@ -1,309 -1,0 +1,309 @@@
 +/*
 + * 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.calcite.exec.rel;
 +
 +import java.util.ArrayList;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.stream.Collectors;
 +import javax.cache.processor.EntryProcessor;
 +import javax.cache.processor.EntryProcessorException;
 +import javax.cache.processor.EntryProcessorResult;
 +import javax.cache.processor.MutableEntry;
 +import org.apache.calcite.rel.core.TableModify;
 +import org.apache.calcite.rel.type.RelDataType;
 +import org.apache.ignite.IgniteCheckedException;
 +import org.apache.ignite.internal.processors.cache.GridCacheContext;
 +import org.apache.ignite.internal.processors.query.IgniteSQLException;
 +import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
 +import org.apache.ignite.internal.processors.query.calcite.schema.TableDescriptor;
 +import org.apache.ignite.internal.util.typedef.F;
 +import org.apache.ignite.internal.util.typedef.internal.U;
 +import org.apache.ignite.lang.IgniteBiTuple;
 +
 +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.DUPLICATE_KEY;
 +
 +/**
 + *
 + */
 +public class ModifyNode<Row> extends AbstractNode<Row> implements SingleNode<Row>, Downstream<Row> {
 +    /** */
 +    protected final TableDescriptor desc;
 +
 +    /** */
 +    private final TableModify.Operation op;
 +
 +    /** */
 +    private final List<String> cols;
 +
 +    /** */
 +    private List<IgniteBiTuple<?, ?>> tuples = new ArrayList<>(MODIFY_BATCH_SIZE);
 +
 +    /** */
 +    private long updatedRows;
 +
 +    /** */
 +    private int waiting;
 +
 +    /** */
 +    private int requested;
 +
 +    /** */
 +    private boolean inLoop;
 +
 +    /** */
 +    private State state = State.UPDATING;
 +
 +    /**
 +     * @param ctx Execution context.
 +     * @param desc Table descriptor.
 +     * @param cols Update column list.
 +     */
 +    public ModifyNode(
 +        ExecutionContext<Row> ctx,
 +        RelDataType rowType,
 +        TableDescriptor desc,
 +        TableModify.Operation op,
 +        List<String> cols
 +    ) {
 +        super(ctx, rowType);
 +
 +        this.desc = desc;
 +        this.op = op;
 +        this.cols = cols;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void request(int rowsCnt) throws Exception {
 +        assert !F.isEmpty(sources()) && sources().size() == 1;
 +        assert rowsCnt > 0 && requested == 0;
 +
 +        checkState();
 +
 +        requested = rowsCnt;
 +
 +        if (!inLoop)
 +            tryEnd();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void push(Row row) throws Exception {
 +        assert downstream() != null;
 +        assert waiting > 0;
 +        assert state == State.UPDATING;
 +
 +        checkState();
 +
 +        waiting--;
 +
 +        switch (op) {
 +            case DELETE:
 +            case UPDATE:
 +            case INSERT:
 +                tuples.add(desc.toTuple(context(), row, op, cols));
 +
 +                flushTuples(false);
 +
 +                break;
 +            default:
 +                throw new UnsupportedOperationException(op.name());
 +        }
 +
 +        if (waiting == 0)
 +            source().request(waiting = MODIFY_BATCH_SIZE);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void end() throws Exception {
 +        assert downstream() != null;
 +        assert waiting > 0;
 +
 +        checkState();
 +
 +        waiting = -1;
 +        state = State.UPDATED;
 +
 +        tryEnd();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected void rewindInternal() {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected Downstream<Row> requestDownstream(int idx) {
 +        if (idx != 0)
 +            throw new IndexOutOfBoundsException();
 +
 +        return this;
 +    }
 +
 +    /** */
 +    private void tryEnd() throws Exception {
 +        assert downstream() != null;
 +
 +        if (state == State.UPDATING && waiting == 0)
 +            source().request(waiting = MODIFY_BATCH_SIZE);
 +
 +        if (state == State.UPDATED && requested > 0) {
 +            flushTuples(true);
 +
 +            state = State.END;
 +
 +            inLoop = true;
 +            try {
 +                requested--;
 +                downstream().push(context().rowHandler().factory(long.class).create(updatedRows));
 +            }
 +            finally {
 +                inLoop = false;
 +            }
 +        }
 +
 +        if (state == State.END && requested > 0) {
 +            requested = 0;
 +            downstream().end();
 +        }
 +    }
 +
 +    /** */
 +    @SuppressWarnings("unchecked")
 +    private void flushTuples(boolean force) throws IgniteCheckedException {
 +        if (F.isEmpty(tuples) || !force && tuples.size() < MODIFY_BATCH_SIZE)
 +            return;
 +
-         List<IgniteBiTuple<?,?>> tuples = this.tuples;
++        List<IgniteBiTuple<?, ?>> tuples = this.tuples;
 +        this.tuples = new ArrayList<>(MODIFY_BATCH_SIZE);
 +
 +        GridCacheContext<Object, Object> cctg = desc.cacheContext();
 +        Map<Object, EntryProcessor<Object, Object, Long>> map = invokeMap(tuples);
 +        Map<Object, EntryProcessorResult<Long>> res = cctg.cache().invokeAll(map);
 +
 +        long updated = res.values().stream().mapToLong(EntryProcessorResult::get).sum();
 +
 +        if (op == TableModify.Operation.INSERT && updated != res.size()) {
 +            List<Object> duplicates = res.entrySet().stream()
 +                .filter(e -> e.getValue().get() == 0)
 +                .map(Map.Entry::getKey)
 +                .collect(Collectors.toList());
 +
 +            throw new IgniteSQLException("Failed to INSERT some keys because they are already in cache. " +
 +                "[keys=" + duplicates + ']', DUPLICATE_KEY);
 +        }
 +
 +        updatedRows += updated;
 +    }
 +
 +    /** */
-     private Map<Object, EntryProcessor<Object, Object, Long>> invokeMap(List<IgniteBiTuple<?,?>> tuples) {
++    private Map<Object, EntryProcessor<Object, Object, Long>> invokeMap(List<IgniteBiTuple<?, ?>> tuples) {
 +        Map<Object, EntryProcessor<Object, Object, Long>> procMap = U.newLinkedHashMap(tuples.size());
 +
 +        switch (op) {
 +            case INSERT:
 +                for (IgniteBiTuple<?, ?> entry : tuples)
 +                    procMap.put(entry.getKey(), new InsertOperation<>(entry.getValue()));
 +
 +                break;
 +            case UPDATE:
 +                for (IgniteBiTuple<?, ?> entry : tuples)
 +                    procMap.put(entry.getKey(), new UpdateOperation<>(entry.getValue()));
 +
 +                break;
 +            case DELETE:
 +                for (IgniteBiTuple<?, ?> entry : tuples)
 +                    procMap.put(entry.getKey(), new DeleteOperation<>());
 +
 +                break;
 +            default:
 +                throw new AssertionError();
 +        }
 +
 +        return procMap;
 +    }
 +
 +    /** */
 +    private enum State {
 +        /** */
 +        UPDATING,
 +
 +        /** */
 +        UPDATED,
 +
 +        /** */
 +        END
 +    }
 +
 +    /** */
 +    private static class InsertOperation<K, V> implements EntryProcessor<K, V, Long> {
 +        /** */
 +        private final V val;
 +
 +        /** */
 +        private InsertOperation(V val) {
 +            this.val = val;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public Long process(MutableEntry<K, V> entry, Object... arguments) throws EntryProcessorException {
 +            if (!entry.exists()) {
 +                entry.setValue(val);
 +
 +                return 1L;
 +            }
 +
 +            return 0L;
 +        }
 +    }
 +
 +    /** */
 +    private static class UpdateOperation<K, V> implements EntryProcessor<K, V, Long> {
 +        /** */
 +        private final V val;
 +
 +        /** */
 +        private UpdateOperation(V val) {
 +            this.val = val;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override public Long process(MutableEntry<K, V> entry, Object... arguments) throws EntryProcessorException {
 +            if (entry.exists()) {
 +                entry.setValue(val);
 +
 +                return 1L;
 +            }
 +
 +            return 0L;
 +        }
 +    }
 +
 +    /** */
 +    private static class DeleteOperation<K, V> implements EntryProcessor<K, V, Long> {
 +        /** {@inheritDoc} */
 +        @Override public Long process(MutableEntry<K, V> entry, Object... arguments) throws EntryProcessorException {
 +            if (entry.exists()) {
 +                entry.remove();
 +
 +                return 1L;
 +            }
 +
 +            return 0L;
 +        }
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/NestedLoopJoinNode.java
index a27e9f2,0000000..6f3188f
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/NestedLoopJoinNode.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/NestedLoopJoinNode.java
@@@ -1,811 -1,0 +1,811 @@@
 +/*
 + * 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.calcite.exec.rel;
 +
 +import java.util.ArrayDeque;
 +import java.util.ArrayList;
 +import java.util.BitSet;
 +import java.util.Deque;
 +import java.util.List;
 +import java.util.function.Predicate;
 +
 +import org.apache.calcite.rel.core.JoinRelType;
 +import org.apache.calcite.rel.type.RelDataType;
 +import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
 +import org.apache.ignite.internal.processors.query.calcite.exec.RowHandler;
 +import org.apache.ignite.internal.util.typedef.F;
 +import org.jetbrains.annotations.NotNull;
 +
 +/** */
 +public abstract class NestedLoopJoinNode<Row> extends AbstractNode<Row> {
 +    /** Special value to highlights that all row were received and we are not waiting any more. */
 +    protected static final int NOT_WAITING = -1;
 +
 +    /** */
 +    protected final Predicate<Row> cond;
 +
 +    /** */
 +    protected final RowHandler<Row> handler;
 +
 +    /** */
 +    protected int requested;
 +
 +    /** */
 +    protected int waitingLeft;
 +
 +    /** */
 +    protected int waitingRight;
 +
 +    /** */
 +    protected final List<Row> rightMaterialized = new ArrayList<>(IN_BUFFER_SIZE);
 +
 +    /** */
 +    protected final Deque<Row> leftInBuf = new ArrayDeque<>(IN_BUFFER_SIZE);
 +
 +    /** */
 +    protected boolean inLoop;
 +
 +    /**
 +     * @param ctx Execution context.
 +     * @param cond Join expression.
 +     */
 +    private NestedLoopJoinNode(ExecutionContext<Row> ctx, RelDataType rowType, Predicate<Row> cond) {
 +        super(ctx, rowType);
 +
 +        this.cond = cond;
 +        handler = ctx.rowHandler();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void request(int rowsCnt) throws Exception {
 +        assert !F.isEmpty(sources()) && sources().size() == 2;
 +        assert rowsCnt > 0 && requested == 0;
 +
 +        checkState();
 +
 +        requested = rowsCnt;
 +
 +        if (!inLoop)
 +            context().execute(this::doJoin, this::onError);
 +    }
 +
 +    /** */
 +    private void doJoin() throws Exception {
 +        checkState();
 +
 +        join();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected void rewindInternal() {
 +        requested = 0;
 +        waitingLeft = 0;
 +        waitingRight = 0;
 +
 +        rightMaterialized.clear();
 +        leftInBuf.clear();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override protected Downstream<Row> requestDownstream(int idx) {
 +        if (idx == 0)
 +            return new Downstream<Row>() {
 +                /** {@inheritDoc} */
 +                @Override public void push(Row row) throws Exception {
 +                    pushLeft(row);
 +                }
 +
 +                /** {@inheritDoc} */
 +                @Override public void end() throws Exception {
 +                    endLeft();
 +                }
 +
 +                /** {@inheritDoc} */
 +                @Override public void onError(Throwable e) {
 +                    NestedLoopJoinNode.this.onError(e);
 +                }
 +            };
 +        else if (idx == 1)
 +            return new Downstream<Row>() {
 +                /** {@inheritDoc} */
 +                @Override public void push(Row row) throws Exception {
 +                    pushRight(row);
 +                }
 +
 +                /** {@inheritDoc} */
 +                @Override public void end() throws Exception {
 +                    endRight();
 +                }
 +
 +                /** {@inheritDoc} */
 +                @Override public void onError(Throwable e) {
 +                    NestedLoopJoinNode.this.onError(e);
 +                }
 +            };
 +
 +        throw new IndexOutOfBoundsException();
 +    }
 +
 +    /** */
 +    private void pushLeft(Row row) throws Exception {
 +        assert downstream() != null;
 +        assert waitingLeft > 0;
 +
 +        checkState();
 +
 +        waitingLeft--;
 +
 +        leftInBuf.add(row);
 +
 +        join();
 +    }
 +
 +    /** */
 +    private void pushRight(Row row) throws Exception {
 +        assert downstream() != null;
 +        assert waitingRight > 0;
 +
 +        checkState();
 +
 +        waitingRight--;
 +
 +        rightMaterialized.add(row);
 +
 +        if (waitingRight == 0)
 +            rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +    }
 +
 +    /** */
 +    private void endLeft() throws Exception {
 +        assert downstream() != null;
 +        assert waitingLeft > 0;
 +
 +        checkState();
 +
 +        waitingLeft = NOT_WAITING;
 +
 +        join();
 +    }
 +
 +    /** */
 +    private void endRight() throws Exception {
 +        assert downstream() != null;
 +        assert waitingRight > 0;
 +
 +        checkState();
 +
 +        waitingRight = NOT_WAITING;
 +
 +        join();
 +    }
 +
 +    /** */
 +    protected Node<Row> leftSource() {
 +        return sources().get(0);
 +    }
 +
 +    /** */
 +    protected Node<Row> rightSource() {
 +        return sources().get(1);
 +    }
 +
 +    /** */
 +    protected abstract void join() throws Exception;
 +
 +    /** */
-     @NotNull public static <Row> NestedLoopJoinNode<Row> create(ExecutionContext<Row> ctx, RelDataType outputRowType, RelDataType leftRowType,
-         RelDataType rightRowType, JoinRelType joinType, Predicate<Row> cond) {
++    @NotNull public static <Row> NestedLoopJoinNode<Row> create(ExecutionContext<Row> ctx, RelDataType outputRowType,
++        RelDataType leftRowType, RelDataType rightRowType, JoinRelType joinType, Predicate<Row> cond) {
 +        switch (joinType) {
 +            case INNER:
 +                return new InnerJoin<>(ctx, outputRowType, cond);
 +
 +            case LEFT: {
 +                RowHandler.RowFactory<Row> rightRowFactory = ctx.rowHandler().factory(ctx.getTypeFactory(), rightRowType);
 +
 +                return new LeftJoin<>(ctx, outputRowType, cond, rightRowFactory);
 +            }
 +
 +            case RIGHT: {
 +                RowHandler.RowFactory<Row> leftRowFactory = ctx.rowHandler().factory(ctx.getTypeFactory(), leftRowType);
 +
 +                return new RightJoin<>(ctx, outputRowType, cond, leftRowFactory);
 +            }
 +
 +            case FULL: {
 +                RowHandler.RowFactory<Row> leftRowFactory = ctx.rowHandler().factory(ctx.getTypeFactory(), leftRowType);
 +                RowHandler.RowFactory<Row> rightRowFactory = ctx.rowHandler().factory(ctx.getTypeFactory(), rightRowType);
 +
 +                return new FullOuterJoin<>(ctx, outputRowType, cond, leftRowFactory, rightRowFactory);
 +            }
 +
 +            case SEMI:
 +                return new SemiJoin<>(ctx, outputRowType, cond);
 +
 +            case ANTI:
 +                return new AntiJoin<>(ctx, outputRowType, cond);
 +
 +            default:
 +                throw new IllegalStateException("Join type \"" + joinType + "\" is not supported yet");
 +        }
 +    }
 +
 +    /** */
 +    private static class InnerJoin<Row> extends NestedLoopJoinNode<Row> {
 +        /** */
 +        private Row left;
 +
 +        /** */
 +        private int rightIdx;
 +
 +        /**
 +         * @param ctx Execution context.
 +         * @param cond Join expression.
 +         */
 +        public InnerJoin(ExecutionContext<Row> ctx, RelDataType rowType, Predicate<Row> cond) {
 +            super(ctx, rowType, cond);
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void rewindInternal() {
 +            left = null;
 +            rightIdx = 0;
 +
 +            super.rewindInternal();
 +        }
 +
 +        /** */
 +        @Override protected void join() throws Exception {
 +            if (waitingRight == NOT_WAITING) {
 +                inLoop = true;
 +                try {
 +                    while (requested > 0 && (left != null || !leftInBuf.isEmpty())) {
 +                        if (left == null)
 +                            left = leftInBuf.remove();
 +
 +                        while (requested > 0 && rightIdx < rightMaterialized.size()) {
 +                            checkState();
 +
 +                            Row row = handler.concat(left, rightMaterialized.get(rightIdx++));
 +
 +                            if (!cond.test(row))
 +                                continue;
 +
 +                            requested--;
 +                            downstream().push(row);
 +                        }
 +
 +                        if (rightIdx == rightMaterialized.size()) {
 +                            left = null;
 +                            rightIdx = 0;
 +                        }
 +                    }
 +                }
 +                finally {
 +                    inLoop = false;
 +                }
 +            }
 +
 +            if (waitingRight == 0)
 +                rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +
 +            if (waitingLeft == 0 && leftInBuf.isEmpty())
 +                leftSource().request(waitingLeft = IN_BUFFER_SIZE);
 +
 +            if (requested > 0 && waitingLeft == NOT_WAITING && waitingRight == NOT_WAITING && left == null && leftInBuf.isEmpty()) {
 +                requested = 0;
 +                downstream().end();
 +            }
 +        }
 +    }
 +
 +    /** */
 +    private static class LeftJoin<Row> extends NestedLoopJoinNode<Row> {
 +        /** Right row factory. */
 +        private final RowHandler.RowFactory<Row> rightRowFactory;
 +
 +        /** Whether current left row was matched or not. */
 +        private boolean matched;
 +
 +        /** */
 +        private Row left;
 +
 +        /** */
 +        private int rightIdx;
 +
 +        /**
 +         * @param ctx Execution context.
 +         * @param cond Join expression.
 +         */
 +        public LeftJoin(ExecutionContext<Row> ctx, RelDataType rowType, Predicate<Row> cond, RowHandler.RowFactory<Row> rightRowFactory) {
 +            super(ctx, rowType, cond);
 +
 +            this.rightRowFactory = rightRowFactory;
 +        }
 +
 +        /** */
 +        @Override protected void rewindInternal() {
 +            matched = false;
 +            left = null;
 +            rightIdx = 0;
 +
 +            super.rewindInternal();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void join() throws Exception {
 +            if (waitingRight == NOT_WAITING) {
 +                inLoop = true;
 +                try {
 +                    while (requested > 0 && (left != null || !leftInBuf.isEmpty())) {
 +                        if (left == null) {
 +                            left = leftInBuf.remove();
 +
 +                            matched = false;
 +                        }
 +
 +                        while (requested > 0 && rightIdx < rightMaterialized.size()) {
 +                            checkState();
 +
 +                            Row row = handler.concat(left, rightMaterialized.get(rightIdx++));
 +
 +                            if (!cond.test(row))
 +                                continue;
 +
 +                            requested--;
 +                            matched = true;
 +                            downstream().push(row);
 +                        }
 +
 +                        if (rightIdx == rightMaterialized.size()) {
 +                            boolean wasPushed = false;
 +
 +                            if (!matched && requested > 0) {
 +                                requested--;
 +                                wasPushed = true;
 +
 +                                downstream().push(handler.concat(left, rightRowFactory.create()));
 +                            }
 +
 +                            if (matched || wasPushed) {
 +                                left = null;
 +                                rightIdx = 0;
 +                            }
 +                        }
 +                    }
 +                }
 +                finally {
 +                    inLoop = false;
 +                }
 +            }
 +
 +            if (waitingRight == 0)
 +                rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +
 +            if (waitingLeft == 0 && leftInBuf.isEmpty())
 +                leftSource().request(waitingLeft = IN_BUFFER_SIZE);
 +
 +            if (requested > 0 && waitingLeft == NOT_WAITING && waitingRight == NOT_WAITING && left == null && leftInBuf.isEmpty()) {
 +                requested = 0;
 +                downstream().end();
 +            }
 +        }
 +    }
 +
 +    /** */
 +    private static class RightJoin<Row> extends NestedLoopJoinNode<Row> {
 +        /** Right row factory. */
 +        private final RowHandler.RowFactory<Row> leftRowFactory;
 +
 +        /** */
 +        private BitSet rightNotMatchedIndexes;
 +
 +        /** */
 +        private int lastPushedInd;
 +
 +        /** */
 +        private Row left;
 +
 +        /** */
 +        private int rightIdx;
 +
 +        /**
 +         * @param ctx Execution context.
 +         * @param cond Join expression.
 +         */
 +        public RightJoin(ExecutionContext<Row> ctx, RelDataType rowType, Predicate<Row> cond, RowHandler.RowFactory<Row> leftRowFactory) {
 +            super(ctx, rowType, cond);
 +
 +            this.leftRowFactory = leftRowFactory;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void rewindInternal() {
 +            left = null;
 +            rightNotMatchedIndexes.clear();
 +            lastPushedInd = 0;
 +            rightIdx = 0;
 +
 +            super.rewindInternal();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void join() throws Exception {
 +            if (waitingRight == NOT_WAITING) {
 +                if (rightNotMatchedIndexes == null) {
 +                    rightNotMatchedIndexes = new BitSet(rightMaterialized.size());
 +
 +                    rightNotMatchedIndexes.set(0, rightMaterialized.size());
 +                }
 +
 +                inLoop = true;
 +                try {
 +                    while (requested > 0 && (left != null || !leftInBuf.isEmpty())) {
 +                        if (left == null)
 +                            left = leftInBuf.remove();
 +
 +                        while (requested > 0 && rightIdx < rightMaterialized.size()) {
 +                            checkState();
 +
 +                            Row right = rightMaterialized.get(rightIdx++);
 +                            Row joined = handler.concat(left, right);
 +
 +                            if (!cond.test(joined))
 +                                continue;
 +
 +                            requested--;
 +                            rightNotMatchedIndexes.clear(rightIdx - 1);
 +                            downstream().push(joined);
 +                        }
 +
 +                        if (rightIdx == rightMaterialized.size()) {
 +                            left = null;
 +                            rightIdx = 0;
 +                        }
 +                    }
 +                }
 +                finally {
 +                    inLoop = false;
 +                }
 +            }
 +
 +            if (waitingLeft == NOT_WAITING && requested > 0 && (rightNotMatchedIndexes != null && !rightNotMatchedIndexes.isEmpty())) {
 +                assert lastPushedInd >= 0;
 +
 +                inLoop = true;
 +                try {
 +                    for (lastPushedInd = rightNotMatchedIndexes.nextSetBit(lastPushedInd);;
 +                        lastPushedInd = rightNotMatchedIndexes.nextSetBit(lastPushedInd + 1)
 +                    ) {
 +                        checkState();
 +
 +                        if (lastPushedInd < 0)
 +                            break;
 +
 +                        Row row = handler.concat(leftRowFactory.create(), rightMaterialized.get(lastPushedInd));
 +
 +                        rightNotMatchedIndexes.clear(lastPushedInd);
 +
 +                        requested--;
 +                        downstream().push(row);
 +
 +                        if (lastPushedInd == Integer.MAX_VALUE || requested <= 0)
 +                            break;
 +                    }
 +                }
 +                finally {
 +                    inLoop = false;
 +                }
 +            }
 +
 +            if (waitingRight == 0)
 +                rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +
 +            if (waitingLeft == 0 && leftInBuf.isEmpty())
 +                leftSource().request(waitingLeft = IN_BUFFER_SIZE);
 +
 +            if (requested > 0 && waitingLeft == NOT_WAITING && waitingRight == NOT_WAITING && left == null
 +                && leftInBuf.isEmpty() && rightNotMatchedIndexes.isEmpty()) {
 +                requested = 0;
 +                downstream().end();
 +            }
 +        }
 +    }
 +
 +    /** */
 +    private static class FullOuterJoin<Row> extends NestedLoopJoinNode<Row> {
 +        /** Left row factory. */
 +        private final RowHandler.RowFactory<Row> leftRowFactory;
 +
 +        /** Right row factory. */
 +        private final RowHandler.RowFactory<Row> rightRowFactory;
 +
 +        /** Whether current left row was matched or not. */
 +        private boolean leftMatched;
 +
 +        /** */
 +        private BitSet rightNotMatchedIndexes;
 +
 +        /** */
 +        private int lastPushedInd;
 +
 +        /** */
 +        private Row left;
 +
 +        /** */
 +        private int rightIdx;
 +
 +        /**
 +         * @param ctx Execution context.
 +         * @param cond Join expression.
 +         */
 +        public FullOuterJoin(ExecutionContext<Row> ctx, RelDataType rowType, Predicate<Row> cond, RowHandler.RowFactory<Row> leftRowFactory,
 +            RowHandler.RowFactory<Row> rightRowFactory) {
 +            super(ctx, rowType, cond);
 +
 +            this.leftRowFactory = leftRowFactory;
 +            this.rightRowFactory = rightRowFactory;
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void rewindInternal() {
 +            left = null;
 +            leftMatched = false;
 +            rightNotMatchedIndexes.clear();
 +            lastPushedInd = 0;
 +            rightIdx = 0;
 +
 +            super.rewindInternal();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void join() throws Exception {
 +            if (waitingRight == NOT_WAITING) {
 +                if (rightNotMatchedIndexes == null) {
 +                    rightNotMatchedIndexes = new BitSet(rightMaterialized.size());
 +
 +                    rightNotMatchedIndexes.set(0, rightMaterialized.size());
 +                }
 +
 +                inLoop = true;
 +                try {
 +                    while (requested > 0 && (left != null || !leftInBuf.isEmpty())) {
 +                        if (left == null) {
 +                            left = leftInBuf.remove();
 +
 +                            leftMatched = false;
 +                        }
 +
 +                        while (requested > 0 && rightIdx < rightMaterialized.size()) {
 +                            checkState();
 +
 +                            Row right = rightMaterialized.get(rightIdx++);
 +                            Row joined = handler.concat(left, right);
 +
 +                            if (!cond.test(joined))
 +                                continue;
 +
 +                            requested--;
 +                            leftMatched = true;
 +                            rightNotMatchedIndexes.clear(rightIdx - 1);
 +                            downstream().push(joined);
 +                        }
 +
 +                        if (rightIdx == rightMaterialized.size()) {
 +                            boolean wasPushed = false;
 +
 +                            if (!leftMatched && requested > 0) {
 +                                requested--;
 +                                wasPushed = true;
 +
 +                                downstream().push(handler.concat(left, rightRowFactory.create()));
 +                            }
 +
 +                            if (leftMatched || wasPushed) {
 +                                left = null;
 +                                rightIdx = 0;
 +                            }
 +                        }
 +                    }
 +                }
 +                finally {
 +                    inLoop = false;
 +                }
 +            }
 +
 +            if (waitingLeft == NOT_WAITING && requested > 0 && (rightNotMatchedIndexes != null && !rightNotMatchedIndexes.isEmpty())) {
 +                assert lastPushedInd >= 0;
 +
 +                inLoop = true;
 +                try {
 +                    for (lastPushedInd = rightNotMatchedIndexes.nextSetBit(lastPushedInd);;
 +                        lastPushedInd = rightNotMatchedIndexes.nextSetBit(lastPushedInd + 1)
 +                    ) {
 +                        checkState();
 +
 +                        if (lastPushedInd < 0)
 +                            break;
 +
 +                        Row row = handler.concat(leftRowFactory.create(), rightMaterialized.get(lastPushedInd));
 +
 +                        rightNotMatchedIndexes.clear(lastPushedInd);
 +
 +                        requested--;
 +                        downstream().push(row);
 +
 +                        if (lastPushedInd == Integer.MAX_VALUE || requested <= 0)
 +                            break;
 +                    }
 +                }
 +                finally {
 +                    inLoop = false;
 +                }
 +            }
 +
 +            if (waitingRight == 0)
 +                rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +
 +            if (waitingLeft == 0 && leftInBuf.isEmpty())
 +                leftSource().request(waitingLeft = IN_BUFFER_SIZE);
 +
 +            if (requested > 0 && waitingLeft == NOT_WAITING && waitingRight == NOT_WAITING && left == null
 +                && leftInBuf.isEmpty() && rightNotMatchedIndexes.isEmpty()) {
 +                requested = 0;
 +                downstream().end();
 +            }
 +        }
 +    }
 +
 +    /** */
 +    private static class SemiJoin<Row> extends NestedLoopJoinNode<Row> {
 +        /** */
 +        private Row left;
 +
 +        /** */
 +        private int rightIdx;
 +
 +        /**
 +         * @param ctx Execution context.
 +         * @param cond Join expression.
 +         */
 +        public SemiJoin(ExecutionContext<Row> ctx, RelDataType rowType, Predicate<Row> cond) {
 +            super(ctx, rowType, cond);
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void rewindInternal() {
 +            left = null;
 +            rightIdx = 0;
 +
 +            super.rewindInternal();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void join() throws Exception {
 +            if (waitingRight == NOT_WAITING) {
 +                while (requested > 0 && (left != null || !leftInBuf.isEmpty())) {
 +                    if (left == null)
 +                        left = leftInBuf.remove();
 +
 +                    boolean matched = false;
 +
 +                    while (!matched && requested > 0 && rightIdx < rightMaterialized.size()) {
 +                        checkState();
 +
 +                        Row row = handler.concat(left, rightMaterialized.get(rightIdx++));
 +
 +                        if (!cond.test(row))
 +                            continue;
 +
 +                        requested--;
 +                        downstream().push(left);
 +
 +                        matched = true;
 +                    }
 +
 +                    if (matched || rightIdx == rightMaterialized.size()) {
 +                        left = null;
 +                        rightIdx = 0;
 +                    }
 +                }
 +            }
 +
 +            if (waitingRight == 0)
 +                rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +
 +            if (waitingLeft == 0 && leftInBuf.isEmpty())
 +                leftSource().request(waitingLeft = IN_BUFFER_SIZE);
 +
 +            if (requested > 0 && waitingLeft == NOT_WAITING && waitingRight == NOT_WAITING && left == null
 +                && leftInBuf.isEmpty()) {
 +                downstream().end();
 +                requested = 0;
 +            }
 +        }
 +    }
 +
 +    /** */
 +    private static class AntiJoin<Row> extends NestedLoopJoinNode<Row> {
 +        /** */
 +        private Row left;
 +
 +        /** */
 +        private int rightIdx;
 +
 +        /**
 +         * @param ctx Execution context.
 +         * @param cond Join expression.
 +         */
 +        public AntiJoin(ExecutionContext<Row> ctx, RelDataType rowType, Predicate<Row> cond) {
 +            super(ctx, rowType, cond);
 +        }
 +
 +        /** */
 +        @Override protected void rewindInternal() {
 +            left = null;
 +            rightIdx = 0;
 +
 +            super.rewindInternal();
 +        }
 +
 +        /** {@inheritDoc} */
 +        @Override protected void join() throws Exception {
 +            if (waitingRight == NOT_WAITING) {
 +                inLoop = true;
 +                try {
 +                    while (requested > 0 && (left != null || !leftInBuf.isEmpty())) {
 +                        if (left == null)
 +                            left = leftInBuf.remove();
 +
 +                        boolean matched = false;
 +
 +                        while (!matched && rightIdx < rightMaterialized.size()) {
 +                            checkState();
 +
 +                            Row row = handler.concat(left, rightMaterialized.get(rightIdx++));
 +
 +                            if (cond.test(row))
 +                                matched = true;
 +                        }
 +
 +                        if (!matched) {
 +                            requested--;
 +                            downstream().push(left);
 +                        }
 +
 +                        left = null;
 +                        rightIdx = 0;
 +                    }
 +                }
 +                finally {
 +                    inLoop = false;
 +                }
 +            }
 +
 +            if (waitingRight == 0)
 +                rightSource().request(waitingRight = IN_BUFFER_SIZE);
 +
 +            if (waitingLeft == 0 && leftInBuf.isEmpty())
 +                leftSource().request(waitingLeft = IN_BUFFER_SIZE);
 +
 +            if (requested > 0 && waitingLeft == NOT_WAITING && waitingRight == NOT_WAITING && left == null && leftInBuf.isEmpty()) {
 +                requested = 0;
 +                downstream().end();
 +            }
 +        }
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/AffinityServiceImpl.java
index 4589e55,0000000..1471957
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/AffinityServiceImpl.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/AffinityServiceImpl.java
@@@ -1,63 -1,0 +1,63 @@@
 +/*
 + * 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.calcite.metadata;
 +
 +import java.util.function.ToIntFunction;
 +import org.apache.ignite.cache.affinity.AffinityFunction;
 +import org.apache.ignite.internal.GridKernalContext;
 +import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 +import org.apache.ignite.internal.processors.query.calcite.util.AbstractService;
 +import org.apache.ignite.internal.util.typedef.internal.CU;
 +import org.apache.ignite.internal.util.typedef.internal.U;
 +
 +/**
 + *
 + */
 +public class AffinityServiceImpl extends AbstractService implements AffinityService {
 +    /** */
-     private GridCacheSharedContext<?,?> cacheSharedContext;
++    private GridCacheSharedContext<?, ?> cacheSharedContext;
 +
 +    /**
 +     * @param ctx Kernal.
 +     */
 +    public AffinityServiceImpl(GridKernalContext ctx) {
 +        super(ctx);
 +    }
 +
 +    /**
 +     * @param cacheSharedContext Cache shared context.
 +     */
-     public void cacheSharedContext(GridCacheSharedContext<?,?> cacheSharedContext) {
++    public void cacheSharedContext(GridCacheSharedContext<?, ?> cacheSharedContext) {
 +        this.cacheSharedContext = cacheSharedContext;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void onStart(GridKernalContext ctx) {
 +        cacheSharedContext(ctx.cache().context());
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public ToIntFunction<Object> affinity(int cacheId) {
 +        if (cacheId == CU.UNDEFINED_CACHE_ID)
 +            return k -> k == null ? 0 : U.safeAbs(k.hashCode());
 +
 +        AffinityFunction affinity = cacheSharedContext.cacheContext(cacheId).group().affinityFunction();
 +
 +        return affinity::partition;
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/ColocationGroup.java
index f761784,0000000..ab9aed1
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/ColocationGroup.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/ColocationGroup.java
@@@ -1,351 -1,0 +1,354 @@@
 +/*
 + * 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.calcite.metadata;
 +
 +import java.nio.ByteBuffer;
 +import java.util.ArrayList;
 +import java.util.Collections;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Objects;
 +import java.util.Set;
 +import java.util.UUID;
 +import org.apache.ignite.IgniteSystemProperties;
 +import org.apache.ignite.internal.GridDirectCollection;
 +import org.apache.ignite.internal.GridDirectTransient;
 +import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState;
 +import org.apache.ignite.internal.processors.query.calcite.message.MarshalableMessage;
 +import org.apache.ignite.internal.processors.query.calcite.message.MarshallingContext;
 +import org.apache.ignite.internal.processors.query.calcite.message.MessageType;
 +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
 +import org.apache.ignite.internal.processors.query.calcite.util.Commons;
 +import org.apache.ignite.internal.util.GridIntList;
 +import org.apache.ignite.internal.util.UUIDCollectionMessage;
 +import org.apache.ignite.internal.util.typedef.F;
 +import org.apache.ignite.internal.util.typedef.internal.U;
 +import org.apache.ignite.plugin.extensions.communication.Message;
 +import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
 +import org.apache.ignite.plugin.extensions.communication.MessageReader;
 +import org.apache.ignite.plugin.extensions.communication.MessageWriter;
 +import org.jetbrains.annotations.NotNull;
 +
 +/** */
 +public class ColocationGroup implements MarshalableMessage {
 +    /** */
-     private static final int SYNTHETIC_PARTITIONS_COUNT = IgniteSystemProperties.getInteger("IGNITE_CALCITE_SYNTHETIC_PARTITIONS_COUNT", 512);
++    private static final int SYNTHETIC_PARTITIONS_COUNT =
++        IgniteSystemProperties.getInteger("IGNITE_CALCITE_SYNTHETIC_PARTITIONS_COUNT", 512);
 +
 +    /** */
 +    @GridDirectCollection(Long.class)
 +    private List<Long> sourceIds;
 +
 +    /** */
 +    @GridDirectCollection(UUID.class)
 +    private List<UUID> nodeIds;
 +
 +    /** */
 +    @GridDirectTransient
 +    private List<List<UUID>> assignments;
 +
 +    /** */
 +    @GridDirectCollection(Message.class)
 +    private List<UUIDCollectionMessage> assignments0;
 +
 +    /** */
 +    public static ColocationGroup forNodes(List<UUID> nodeIds) {
 +        return new ColocationGroup(null, nodeIds, null);
 +    }
 +
 +    /** */
 +    public static ColocationGroup forAssignments(List<List<UUID>> assignments) {
 +        return new ColocationGroup(null, null, assignments);
 +    }
 +
 +    /** */
 +    public static ColocationGroup forSourceId(long sourceId) {
 +        return new ColocationGroup(Collections.singletonList(sourceId), null, null);
 +    }
 +
 +    /** */
 +    public ColocationGroup() {
 +    }
 +
 +    /** */
 +    private ColocationGroup(List<Long> sourceIds, List<UUID> nodeIds, List<List<UUID>> assignments) {
 +        this.sourceIds = sourceIds;
 +        this.nodeIds = nodeIds;
 +        this.assignments = assignments;
 +    }
 +
 +    /**
 +     * @return Lists of colocation group sources.
 +     */
 +    public List<Long> sourceIds() {
 +        return sourceIds == null ? Collections.emptyList() : sourceIds;
 +    }
 +
 +    /**
 +     * @return Lists of nodes capable to execute a query fragment for what the mapping is calculated.
 +     */
 +    public List<UUID> nodeIds() {
 +        return nodeIds == null ? Collections.emptyList() : nodeIds;
 +    }
 +
 +    /**
 +     * @return List of partitions (index) and nodes (items) having an appropriate partition in
 +     * {@link GridDhtPartitionState#OWNING} state, calculated for distributed tables, involved in query execution.
 +     */
 +    public List<List<UUID>> assignments() {
 +        return assignments == null ? Collections.emptyList() : assignments;
 +    }
 +
 +    /**
 +     * Prunes involved partitions (hence nodes, involved in query execution) on the basis of filter,
 +     * its distribution, query parameters and original nodes mapping.
 +     * @param rel Filter.
 +     * @return Resulting nodes mapping.
 +     */
 +    public ColocationGroup prune(IgniteRel rel) {
 +        return this; // TODO https://issues.apache.org/jira/browse/IGNITE-12455
 +    }
 +
 +    /** */
 +    public boolean belongs(long sourceId) {
 +        return sourceIds != null && sourceIds.contains(sourceId);
 +    }
 +
 +    /**
 +     * Merges this mapping with given one.
 +     * @param other Mapping to merge with.
 +     * @return Merged nodes mapping.
 +     * @throws ColocationMappingException If involved nodes intersection is empty, hence there is no nodes capable to execute
 +     * being calculated fragment.
 +     */
 +    public ColocationGroup colocate(ColocationGroup other) throws ColocationMappingException {
 +        List<Long> sourceIds;
 +        if (this.sourceIds == null || other.sourceIds == null)
 +            sourceIds = U.firstNotNull(this.sourceIds, other.sourceIds);
 +        else
 +            sourceIds = Commons.combine(this.sourceIds, other.sourceIds);
 +
 +        List<UUID> nodeIds;
 +        if (this.nodeIds == null || other.nodeIds == null)
 +            nodeIds = U.firstNotNull(this.nodeIds, other.nodeIds);
 +        else
 +            nodeIds = Commons.intersect(other.nodeIds, this.nodeIds);
 +
 +        if (nodeIds != null && nodeIds.isEmpty()) {
 +            throw new ColocationMappingException("Failed to map fragment to location. " +
 +                "Replicated query parts are not co-located on all nodes");
 +        }
 +
 +        List<List<UUID>> assignments;
 +        if (this.assignments == null || other.assignments == null) {
 +            assignments = U.firstNotNull(this.assignments, other.assignments);
 +
 +            if (assignments != null && nodeIds != null) {
 +                Set<UUID> filter = new HashSet<>(nodeIds);
 +                List<List<UUID>> assignments0 = new ArrayList<>(assignments.size());
 +
 +                for (int i = 0; i < assignments.size(); i++) {
 +                    List<UUID> assignment = Commons.intersect(filter, assignments.get(i));
 +
-                     if (assignment.isEmpty()) // TODO check with partition filters
-                         throw new ColocationMappingException("Failed to map fragment to location. Partition mapping is empty [part=" + i + "]");
++                    if (assignment.isEmpty()) { // TODO check with partition filters
++                        throw new ColocationMappingException("Failed to map fragment to location. " +
++                            "Partition mapping is empty [part=" + i + "]");
++                    }
 +
 +                    assignments0.add(assignment);
 +                }
 +
 +                assignments = assignments0;
 +            }
 +        }
 +        else {
 +            assert this.assignments.size() == other.assignments.size();
 +            assignments = new ArrayList<>(this.assignments.size());
 +            Set<UUID> filter = nodeIds == null ? null : new HashSet<>(nodeIds);
 +            for (int i = 0; i < this.assignments.size(); i++) {
 +                List<UUID> assignment = Commons.intersect(this.assignments.get(i), other.assignments.get(i));
 +
 +                if (filter != null)
 +                    assignment.retainAll(filter);
 +
 +                if (assignment.isEmpty()) // TODO check with partition filters
 +                    throw new ColocationMappingException("Failed to map fragment to location. Partition mapping is empty [part=" + i + "]");
 +
 +                assignments.add(assignment);
 +            }
 +        }
 +
 +        return new ColocationGroup(sourceIds, nodeIds, assignments);
 +    }
 +
 +    /** */
 +    public ColocationGroup finalaze() {
 +        if (assignments == null && nodeIds == null)
 +            return this;
 +
 +        if (assignments != null) {
 +            List<List<UUID>> assignments = new ArrayList<>(this.assignments.size());
 +            Set<UUID> nodes = new HashSet<>();
 +            for (List<UUID> assignment : this.assignments) {
 +                UUID first = F.first(assignment);
 +                if (first != null)
 +                    nodes.add(first);
 +                assignments.add(first != null ? Collections.singletonList(first) : Collections.emptyList());
 +            }
 +
 +            return new ColocationGroup(sourceIds, new ArrayList<>(nodes), assignments);
 +        }
 +
 +        return forNodes0(nodeIds);
 +    }
 +
 +    /** */
 +    public ColocationGroup mapToNodes(List<UUID> nodeIds) {
 +        return !F.isEmpty(this.nodeIds) ? this : forNodes0(nodeIds);
 +    }
 +
 +    /** */
 +    @NotNull private ColocationGroup forNodes0(List<UUID> nodeIds) {
 +        List<List<UUID>> assignments = new ArrayList<>(SYNTHETIC_PARTITIONS_COUNT);
 +        for (int i = 0; i < SYNTHETIC_PARTITIONS_COUNT; i++)
 +            assignments.add(F.asList(nodeIds.get(i % nodeIds.size())));
 +        return new ColocationGroup(sourceIds, nodeIds, assignments);
 +    }
 +
 +    /**
 +     * Returns List of partitions to scan on the given node.
 +     *
 +     * @param nodeId Cluster node ID.
 +     * @return List of partitions to scan on the given node.
 +     */
 +    public int[] partitions(UUID nodeId) {
 +        GridIntList parts = new GridIntList(assignments.size());
 +
 +        for (int i = 0; i < assignments.size(); i++) {
 +            List<UUID> assignment = assignments.get(i);
 +            if (Objects.equals(nodeId, F.first(assignment)))
 +                parts.add(i);
 +        }
 +
 +        return parts.array();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public MessageType type() {
 +        return MessageType.COLOCATION_GROUP;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
 +        writer.setBuffer(buf);
 +
 +        if (!writer.isHeaderWritten()) {
 +            if (!writer.writeHeader(directType(), fieldsCount()))
 +                return false;
 +
 +            writer.onHeaderWritten();
 +        }
 +
 +        switch (writer.state()) {
 +            case 0:
 +                if (!writer.writeCollection("assignments0", assignments0, MessageCollectionItemType.MSG))
 +                    return false;
 +
 +                writer.incrementState();
 +
 +            case 1:
 +                if (!writer.writeCollection("nodeIds", nodeIds, MessageCollectionItemType.UUID))
 +                    return false;
 +
 +                writer.incrementState();
 +
 +            case 2:
 +                if (!writer.writeCollection("sourceIds", sourceIds, MessageCollectionItemType.LONG))
 +                    return false;
 +
 +                writer.incrementState();
 +
 +        }
 +
 +        return true;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
 +        reader.setBuffer(buf);
 +
 +        if (!reader.beforeMessageRead())
 +            return false;
 +
 +        switch (reader.state()) {
 +            case 0:
 +                assignments0 = reader.readCollection("assignments0", MessageCollectionItemType.MSG);
 +
 +                if (!reader.isLastRead())
 +                    return false;
 +
 +                reader.incrementState();
 +
 +            case 1:
 +                nodeIds = reader.readCollection("nodeIds", MessageCollectionItemType.UUID);
 +
 +                if (!reader.isLastRead())
 +                    return false;
 +
 +                reader.incrementState();
 +
 +            case 2:
 +                sourceIds = reader.readCollection("sourceIds", MessageCollectionItemType.LONG);
 +
 +                if (!reader.isLastRead())
 +                    return false;
 +
 +                reader.incrementState();
 +
 +        }
 +
 +        return reader.afterMessageRead(ColocationGroup.class);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public byte fieldsCount() {
 +        return 3;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void prepareMarshal(MarshallingContext ctx) {
 +        if (assignments != null && assignments0 == null)
 +            assignments0 = Commons.transform(assignments, this::transform);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void prepareUnmarshal(MarshallingContext ctx) {
 +        if (assignments0 != null && assignments == null)
 +            assignments = Commons.transform(assignments0, this::transform);
 +    }
 +
 +    /** */
 +    private List<UUID> transform(UUIDCollectionMessage message) {
 +        return message.uuids() instanceof List ? (List<UUID>)message.uuids() : new ArrayList<>(message.uuids());
 +    }
 +
 +    /** */
 +    private UUIDCollectionMessage transform(List<UUID> uuids) {
 +        return new UUIDCollectionMessage(uuids);
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdSelectivity.java
index 86ad57a,0000000..83bfc8f
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdSelectivity.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdSelectivity.java
@@@ -1,123 -1,0 +1,124 @@@
 +/*
 + * 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.calcite.metadata;
 +
 +import java.util.List;
 +
 +import org.apache.calcite.plan.RelOptUtil;
 +import org.apache.calcite.rel.metadata.ReflectiveRelMetadataProvider;
 +import org.apache.calcite.rel.metadata.RelMdSelectivity;
 +import org.apache.calcite.rel.metadata.RelMdUtil;
 +import org.apache.calcite.rel.metadata.RelMetadataProvider;
 +import org.apache.calcite.rel.metadata.RelMetadataQuery;
 +import org.apache.calcite.rex.RexCall;
 +import org.apache.calcite.rex.RexNode;
 +import org.apache.calcite.rex.RexUtil;
 +import org.apache.calcite.sql.SqlKind;
 +import org.apache.calcite.util.BuiltInMethod;
 +import org.apache.ignite.internal.processors.query.calcite.rel.AbstractIndexScan;
 +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteHashIndexSpool;
 +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSortedIndexSpool;
 +import org.apache.ignite.internal.processors.query.calcite.rel.ProjectableFilterableTableScan;
 +import org.apache.ignite.internal.processors.query.calcite.util.RexUtils;
 +import org.apache.ignite.internal.util.typedef.F;
 +
 +/** */
 +public class IgniteMdSelectivity extends RelMdSelectivity {
 +    /** */
 +    public static final RelMetadataProvider SOURCE =
 +        ReflectiveRelMetadataProvider.reflectiveSource(
 +            BuiltInMethod.SELECTIVITY.method, new IgniteMdSelectivity());
 +
 +    /** */
 +    public Double getSelectivity(AbstractIndexScan rel, RelMetadataQuery mq, RexNode predicate) {
 +        if (predicate != null)
 +            return getSelectivity((ProjectableFilterableTableScan)rel, mq, predicate);
 +
 +        List<RexNode> lowerCond = rel.lowerCondition();
 +        List<RexNode> upperCond = rel.upperCondition();
 +
 +        if (F.isEmpty(lowerCond) && F.isEmpty(upperCond))
 +            return RelMdUtil.guessSelectivity(rel.condition());
 +
 +        double idxSelectivity = 1.0;
-         int len = F.isEmpty(lowerCond) ? upperCond.size() : F.isEmpty(upperCond) ? lowerCond.size() : Math.max(lowerCond.size(), upperCond.size());
++        int len = F.isEmpty(lowerCond) ? upperCond.size() : F.isEmpty(upperCond) ? lowerCond.size() :
++            Math.max(lowerCond.size(), upperCond.size());
 +
 +        for (int i = 0; i < len; i++) {
 +            RexCall lower = F.isEmpty(lowerCond) || lowerCond.size() <= i ? null : (RexCall)lowerCond.get(i);
 +            RexCall upper = F.isEmpty(upperCond) || upperCond.size() <= i ? null : (RexCall)upperCond.get(i);
 +
 +            assert lower != null || upper != null;
 +
 +            if (lower != null && upper != null)
 +                idxSelectivity *= lower.op.kind == SqlKind.EQUALS ? .1 : .2;
 +            else
 +                idxSelectivity *= .35;
 +        }
 +
 +        List<RexNode> conjunctions = RelOptUtil.conjunctions(rel.condition());
 +
 +        if (!F.isEmpty(lowerCond))
 +            conjunctions.removeAll(lowerCond);
 +        if (!F.isEmpty(upperCond))
 +            conjunctions.removeAll(upperCond);
 +
 +        RexNode remaining = RexUtil.composeConjunction(RexUtils.builder(rel), conjunctions, true);
 +
 +        return idxSelectivity * RelMdUtil.guessSelectivity(remaining);
 +    }
 +
 +    /** */
 +    public Double getSelectivity(ProjectableFilterableTableScan rel, RelMetadataQuery mq, RexNode predicate) {
 +        if (predicate == null)
 +            return RelMdUtil.guessSelectivity(rel.condition());
 +
 +        RexNode condition = rel.pushUpPredicate();
 +        if (condition == null)
 +            return RelMdUtil.guessSelectivity(predicate);
 +
 +        RexNode diff = RelMdUtil.minusPreds(RexUtils.builder(rel), predicate, condition);
 +        return RelMdUtil.guessSelectivity(diff);
 +    }
 +
 +    /** */
 +    public Double getSelectivity(IgniteSortedIndexSpool rel, RelMetadataQuery mq, RexNode predicate) {
 +        if (predicate != null) {
 +            return mq.getSelectivity(rel.getInput(),
 +                RelMdUtil.minusPreds(
 +                    rel.getCluster().getRexBuilder(),
 +                    predicate,
 +                    rel.condition()));
 +        }
 +
 +        return mq.getSelectivity(rel.getInput(), rel.condition());
 +    }
 +
 +    /** */
 +    public Double getSelectivity(IgniteHashIndexSpool rel, RelMetadataQuery mq, RexNode predicate) {
 +        if (predicate != null) {
 +            return mq.getSelectivity(rel.getInput(),
 +                RelMdUtil.minusPreds(
 +                    rel.getCluster().getRexBuilder(),
 +                    predicate,
 +                    rel.condition()));
 +        }
 +
 +        return mq.getSelectivity(rel.getInput(), rel.condition());
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/MappingServiceImpl.java
index b823830,0000000..6f464a3
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/MappingServiceImpl.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/MappingServiceImpl.java
@@@ -1,77 -1,0 +1,78 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one or more
 + * contributor license agreements.  See the NOTICE file distributed with
 + * this work for additional information regarding copyright ownership.
 + * The ASF licenses this file to You under the Apache License, Version 2.0
 + * (the "License"); you may not use this file except in compliance with
 + * the License.  You may obtain a copy of the License at
 + *
 + *      http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +
 +package org.apache.ignite.internal.processors.query.calcite.metadata;
 +
 +import java.util.ArrayList;
 +import java.util.List;
 +import java.util.UUID;
 +import java.util.concurrent.ThreadLocalRandom;
 +import java.util.function.Predicate;
 +import java.util.stream.Collectors;
 +import org.apache.ignite.cluster.ClusterNode;
 +import org.apache.ignite.internal.GridKernalContext;
 +import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager;
 +import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 +import org.apache.ignite.internal.processors.query.calcite.util.AbstractService;
 +import org.apache.ignite.internal.processors.query.calcite.util.Commons;
 +import org.apache.ignite.internal.util.typedef.F;
 +import org.jetbrains.annotations.NotNull;
 +import org.jetbrains.annotations.Nullable;
 +
 +/**
 + *
 + */
 +public class MappingServiceImpl extends AbstractService implements MappingService {
 +    /** */
 +    private GridDiscoveryManager discoveryManager;
 +
 +    /**
 +     * @param ctx Kernal.
 +     */
 +    public MappingServiceImpl(GridKernalContext ctx) {
 +        super(ctx);
 +    }
 +
 +    /**
 +     * @param discoveryManager Discovery manager.
 +     */
 +    public void discoveryManager(GridDiscoveryManager discoveryManager) {
 +        this.discoveryManager = discoveryManager;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void onStart(GridKernalContext ctx) {
 +        discoveryManager(ctx.discovery());
 +    }
 +
 +    /** {@inheritDoc} */
-     @Override public List<UUID> executionNodes(@NotNull AffinityTopologyVersion topVer, boolean single, @Nullable Predicate<ClusterNode> nodeFilter) {
++    @Override public List<UUID> executionNodes(@NotNull AffinityTopologyVersion topVer, boolean single,
++        @Nullable Predicate<ClusterNode> nodeFilter) {
 +        List<ClusterNode> nodes = new ArrayList<>(discoveryManager.discoCache(topVer).serverNodes());
 +
 +        if (nodeFilter != null)
 +            nodes = nodes.stream().filter(nodeFilter).collect(Collectors.toList());
 +
 +        if (single && nodes.size() > 1)
 +            nodes = F.asList(nodes.get(ThreadLocalRandom.current().nextInt(nodes.size())));
 +
 +        if (F.isEmpty(nodes))
 +            throw new IllegalStateException("failed to map query to execution nodes. Nodes list is empty.");
 +
 +        return Commons.transform(nodes, ClusterNode::id);
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/CalciteQueryFieldMetadata.java
index 4113a1e,0000000..13627ea
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/CalciteQueryFieldMetadata.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/CalciteQueryFieldMetadata.java
@@@ -1,118 -1,0 +1,129 @@@
 +/*
 + * 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.calcite.prepare;
 +
 +import java.io.IOException;
 +import java.io.ObjectInput;
 +import java.io.ObjectOutput;
++import java.sql.ResultSetMetaData;
 +
 +import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
 +
 +/**
 + *
 + */
 +public class CalciteQueryFieldMetadata implements GridQueryFieldMetadata {
 +    /** */
 +    private String schemaName;
 +
 +    /** */
 +    private String typeName;
 +
 +    /** */
 +    private String fieldName;
 +
 +    /** */
 +    private String fieldTypeName;
 +
 +    /** */
 +    private int precision;
 +
 +    /** */
 +    private int scale;
 +
++    /** */
++    private boolean isNullable;
++
 +    /** Blank constructor for external serialization. */
 +    public CalciteQueryFieldMetadata() {
 +    }
 +
 +    /**
 +     * @param schemaName Schema name.
 +     * @param typeName Type name.
 +     * @param fieldName Field name.
 +     * @param fieldTypeName Field type name.
 +     * @param precision Precision.
 +     * @param scale Scale.
 +     */
-     public CalciteQueryFieldMetadata(String schemaName, String typeName, String fieldName, String fieldTypeName, int precision, int scale) {
++    public CalciteQueryFieldMetadata(String schemaName, String typeName, String fieldName, String fieldTypeName,
++        int precision, int scale, boolean isNullable) {
 +        this.schemaName = schemaName;
 +        this.typeName = typeName;
 +        this.fieldName = fieldName;
 +        this.fieldTypeName = fieldTypeName;
 +        this.precision = precision;
 +        this.scale = scale;
++        this.isNullable = isNullable;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public String schemaName() {
 +        return schemaName;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public String typeName() {
 +        return typeName;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public String fieldName() {
 +        return fieldName;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public String fieldTypeName() {
 +        return fieldTypeName;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public int precision() {
 +        return precision;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public int scale() {
 +        return scale;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void writeExternal(ObjectOutput out) throws IOException {
 +        out.writeUTF(schemaName);
 +        out.writeUTF(typeName);
 +        out.writeUTF(fieldName);
 +        out.writeUTF(fieldTypeName);
 +        out.writeInt(precision);
 +        out.writeInt(scale);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
 +        schemaName = in.readUTF();
 +        typeName = in.readUTF();
 +        fieldName = in.readUTF();
 +        fieldTypeName = in.readUTF();
 +        precision = in.readInt();
 +        scale = in.readInt();
 +    }
++
++    /** {@inheritDoc} */
++    @Override public int nullability() {
++        return isNullable ? ResultSetMetaData.columnNullable : ResultSetMetaData.columnNoNulls;
++    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/FieldsMetadata.java
index ed02794,0000000..492926c
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/FieldsMetadata.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/FieldsMetadata.java
@@@ -1,74 -1,0 +1,75 @@@
 +/*
 + * 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.calcite.prepare;
 +
 +import java.lang.reflect.Type;
 +import java.util.List;
 +import com.google.common.collect.ImmutableList;
 +import org.apache.calcite.rel.type.RelDataType;
 +import org.apache.calcite.rel.type.RelDataTypeField;
 +import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
 +import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
 +import org.apache.ignite.internal.util.typedef.F;
 +
 +/**
 + *
 + */
 +public interface FieldsMetadata {
 +    /**
 +     * @return Result row type.
 +     */
 +    RelDataType rowType();
 +
 +    /**
 +     * @return Result row origins (or where a field value comes from).
 +     */
 +    List<List<String>> origins();
 +
 +    /**
 +     * @param typeFactory Type factory.
 +     * @return Query field descriptors collection&
 +     */
 +    default List<GridQueryFieldMetadata> queryFieldsMetadata(IgniteTypeFactory typeFactory) {
 +        RelDataType rowType = rowType();
 +        List<List<String>> origins = origins();
 +        List<RelDataTypeField> fields = rowType.getFieldList();
 +
 +        assert origins == null || fields.size() == origins.size();
 +
 +        ImmutableList.Builder<GridQueryFieldMetadata> b = ImmutableList.builder();
 +
 +        for (int i = 0; i < fields.size(); i++) {
 +            List<String> origin = origins != null ? origins.get(i) : null;
 +            RelDataTypeField field = fields.get(i);
 +            RelDataType fieldType = field.getType();
 +            Type fieldCls = typeFactory.getResultClass(fieldType);
 +
 +            b.add(new CalciteQueryFieldMetadata(
 +                F.isEmpty(origin) ? null : origin.get(0),
 +                F.isEmpty(origin) ? null : origin.get(1),
 +                F.isEmpty(origin) ? field.getName() : origin.get(2),
 +                fieldCls == null ? Void.class.getName() : fieldCls.getTypeName(),
 +                fieldType.getPrecision(),
-                 fieldType.getScale()
++                fieldType.getScale(),
++                fieldType.isNullable()
 +            ));
 +        }
 +
 +        return b.build();
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Splitter.java
index 735fa85,0000000..249a48b
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Splitter.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Splitter.java
@@@ -1,122 -1,0 +1,123 @@@
 +/*
 + * 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.calcite.prepare;
 +
 +import java.util.ArrayList;
 +import java.util.Deque;
 +import java.util.LinkedList;
 +import java.util.List;
 +
 +import com.google.common.collect.ImmutableList;
 +import org.apache.calcite.plan.RelOptCluster;
 +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteExchange;
 +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexScan;
 +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteReceiver;
 +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
 +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSender;
 +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
 +import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTrimExchange;
 +
 +/**
 + * Splits a query into a list of query fragments.
 + */
 +public class Splitter extends IgniteRelShuttle {
 +    /** */
 +    private final Deque<FragmentProto> stack = new LinkedList<>();
 +
 +    /** */
 +    private FragmentProto curr;
 +
 +    /** */
 +    public List<Fragment> go(IgniteRel root) {
 +        ArrayList<Fragment> res = new ArrayList<>();
 +
 +        stack.push(new FragmentProto(IdGenerator.nextId(), root));
 +
 +        while (!stack.isEmpty()) {
 +            curr = stack.pop();
 +
 +            curr.root = visit(curr.root);
 +
 +            res.add(curr.build());
 +
 +            curr = null;
 +        }
 +
 +        return res;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public IgniteRel visit(IgniteReceiver rel) {
 +        throw new AssertionError();
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public IgniteRel visit(IgniteExchange rel) {
 +        RelOptCluster cluster = rel.getCluster();
 +
 +        long targetFragmentId = curr.id;
 +        long sourceFragmentId = IdGenerator.nextId();
 +        long exchangeId = sourceFragmentId;
 +
 +        IgniteReceiver receiver = new IgniteReceiver(cluster, rel.getTraitSet(), rel.getRowType(), exchangeId, sourceFragmentId);
-         IgniteSender sender = new IgniteSender(cluster, rel.getTraitSet(), rel.getInput(), exchangeId, targetFragmentId, rel.distribution());
++        IgniteSender sender = new IgniteSender(cluster, rel.getTraitSet(), rel.getInput(), exchangeId, targetFragmentId,
++            rel.distribution());
 +
 +        curr.remotes.add(receiver);
 +        stack.push(new FragmentProto(sourceFragmentId, sender));
 +
 +        return receiver;
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public IgniteRel visit(IgniteTrimExchange rel) {
 +        return ((IgniteTrimExchange)processNode(rel)).clone(IdGenerator.nextId());
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public IgniteRel visit(IgniteIndexScan rel) {
 +        return rel.clone(IdGenerator.nextId());
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public IgniteRel visit(IgniteTableScan rel) {
 +        return rel.clone(IdGenerator.nextId());
 +    }
 +
 +    /** */
 +    private static class FragmentProto {
 +        /** */
 +        private final long id;
 +
 +        /** */
 +        private IgniteRel root;
 +
 +        /** */
 +        private final ImmutableList.Builder<IgniteReceiver> remotes = ImmutableList.builder();
 +
 +        /** */
 +        private FragmentProto(long id, IgniteRel root) {
 +            this.id = id;
 +            this.root = root;
 +        }
 +
 +        Fragment build() {
 +            return new Fragment(id, root, remotes.build());
 +        }
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java
index 984ffb9,0000000..f0c43ba
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java
@@@ -1,372 -1,0 +1,373 @@@
 +/*
 + * 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.calcite.prepare.ddl;
 +
 +import java.util.ArrayList;
 +import java.util.Arrays;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Set;
 +import java.util.function.BiConsumer;
 +import java.util.function.BiFunction;
 +import java.util.function.Function;
 +import java.util.stream.Collectors;
 +import java.util.stream.Stream;
 +
 +import org.apache.calcite.rel.type.RelDataType;
 +import org.apache.calcite.sql.SqlDdl;
 +import org.apache.calcite.sql.SqlIdentifier;
 +import org.apache.calcite.sql.SqlLiteral;
 +import org.apache.calcite.sql.SqlNode;
 +import org.apache.calcite.sql.SqlNodeList;
 +import org.apache.calcite.sql.SqlNumericLiteral;
 +import org.apache.calcite.sql.ddl.SqlColumnDeclaration;
 +import org.apache.calcite.sql.ddl.SqlDropTable;
 +import org.apache.calcite.sql.ddl.SqlKeyConstraint;
 +import org.apache.ignite.cache.CacheAtomicityMode;
 +import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
 +import org.apache.ignite.internal.processors.query.IgniteSQLException;
 +import org.apache.ignite.internal.processors.query.QueryUtils;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.IgnitePlanner;
 +import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
 +import org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTable;
 +import org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOption;
 +import org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum;
 +import org.apache.ignite.internal.util.typedef.F;
 +
 +import static org.apache.calcite.sql.type.SqlTypeName.BOOLEAN;
 +import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.AFFINITY_KEY;
 +import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.ATOMICITY;
 +import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.BACKUPS;
 +import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.CACHE_GROUP;
 +import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.CACHE_NAME;
 +import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.DATA_REGION;
 +import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.ENCRYPTED;
 +import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.KEY_TYPE;
 +import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.TEMPLATE;
 +import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.VALUE_TYPE;
 +import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.WRITE_SYNCHRONIZATION_MODE;
 +
 +/** */
 +public class DdlSqlToCommandConverter {
 +    /** Processor that validates a value is a Sql Identifier. */
 +    private static final BiFunction<IgniteSqlCreateTableOption, PlanningContext, String> VALUE_IS_IDENTIFIER_VALIDATOR = (opt, ctx) -> {
 +        if (!(opt.value() instanceof SqlIdentifier) || !((SqlIdentifier)opt.value()).isSimple())
 +            throwOptionParsingException(opt, "a simple identifier", ctx.query());
 +
 +        return ((SqlIdentifier)opt.value()).getSimple();
 +    };
 +
 +    /** Processor that unconditionally throws an AssertionException. */
 +    private static final TableOptionProcessor<Void> UNSUPPORTED_OPTION_PROCESSOR = new TableOptionProcessor<>(
 +        null,
 +        (opt, ctx) -> {
 +            throw new AssertionError("Unsupported option " + opt.key());
 +        },
 +        null);
 +
 +    /** Map of the supported table option processors. */
 +    private final Map<IgniteSqlCreateTableOptionEnum, TableOptionProcessor<?>> tblOptionProcessors = Stream.of(
 +        new TableOptionProcessor<>(TEMPLATE, VALUE_IS_IDENTIFIER_VALIDATOR, CreateTableCommand::templateName),
 +        new TableOptionProcessor<>(AFFINITY_KEY, VALUE_IS_IDENTIFIER_VALIDATOR, CreateTableCommand::affinityKey),
 +        new TableOptionProcessor<>(CACHE_GROUP, VALUE_IS_IDENTIFIER_VALIDATOR, CreateTableCommand::cacheGroup),
 +        new TableOptionProcessor<>(CACHE_NAME, VALUE_IS_IDENTIFIER_VALIDATOR, CreateTableCommand::cacheName),
 +        new TableOptionProcessor<>(DATA_REGION, VALUE_IS_IDENTIFIER_VALIDATOR, CreateTableCommand::dataRegionName),
 +        new TableOptionProcessor<>(KEY_TYPE, VALUE_IS_IDENTIFIER_VALIDATOR, CreateTableCommand::keyTypeName),
 +        new TableOptionProcessor<>(VALUE_TYPE, VALUE_IS_IDENTIFIER_VALIDATOR, CreateTableCommand::valueTypeName),
 +        new TableOptionProcessor<>(ATOMICITY, validatorForEnumValue(CacheAtomicityMode.class), CreateTableCommand::atomicityMode),
-         new TableOptionProcessor<>(WRITE_SYNCHRONIZATION_MODE, validatorForEnumValue(CacheWriteSynchronizationMode.class), CreateTableCommand::writeSynchronizationMode),
++        new TableOptionProcessor<>(WRITE_SYNCHRONIZATION_MODE, validatorForEnumValue(CacheWriteSynchronizationMode.class),
++            CreateTableCommand::writeSynchronizationMode),
 +        new TableOptionProcessor<>(BACKUPS, (opt, ctx) -> {
 +                if (!(opt.value() instanceof SqlNumericLiteral)
 +                    || !((SqlNumericLiteral)opt.value()).isInteger()
 +                    || ((SqlLiteral)opt.value()).intValue(true) < 0
 +                )
 +                    throwOptionParsingException(opt, "a non-negative integer", ctx.query());
 +
 +                return ((SqlLiteral)opt.value()).intValue(true);
 +            }, CreateTableCommand::backups),
 +        new TableOptionProcessor<>(ENCRYPTED, (opt, ctx) -> {
 +            if (!(opt.value() instanceof SqlLiteral) && ((SqlLiteral)opt.value()).getTypeName() != BOOLEAN)
 +                throwOptionParsingException(opt, "a boolean", ctx.query());
 +
 +            return ((SqlLiteral)opt.value()).booleanValue();
 +        }, CreateTableCommand::encrypted)
 +        ).collect(Collectors.toMap(TableOptionProcessor::key, Function.identity()));
 +
 +    /**
 +     * Converts a given ddl AST to a ddl command.
 +     *
 +     * @param ddlNode Root node of the given AST.
 +     * @param ctx Planning context.
 +     */
 +    public DdlCommand convert(SqlDdl ddlNode, PlanningContext ctx) {
 +        if (ddlNode instanceof IgniteSqlCreateTable)
 +            return convertCreateTable((IgniteSqlCreateTable)ddlNode, ctx);
 +
 +        if (ddlNode instanceof SqlDropTable)
 +            return convertDropTable((SqlDropTable)ddlNode, ctx);
 +
 +        throw new IgniteSQLException("Unsupported operation [" +
 +            "sqlNodeKind=" + ddlNode.getKind() + "; " +
 +            "querySql=\"" + ctx.query() + "\"]", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
 +    }
 +
 +    /**
 +     * Converts a given CreateTable AST to a CreateTable command.
 +     *
 +     * @param createTblNode Root node of the given AST.
 +     * @param ctx Planning context.
 +     */
 +    private CreateTableCommand convertCreateTable(IgniteSqlCreateTable createTblNode, PlanningContext ctx) {
 +        CreateTableCommand createTblCmd = new CreateTableCommand();
 +
 +        createTblCmd.schemaName(deriveSchemaName(createTblNode.name(), ctx));
 +        createTblCmd.tableName(deriveObjectName(createTblNode.name(), ctx, "tableName"));
 +        createTblCmd.ifNotExists(createTblNode.ifNotExists());
 +        createTblCmd.templateName(QueryUtils.TEMPLATE_PARTITIONED);
 +
 +        if (createTblNode.createOptionList() != null) {
 +            for (SqlNode optNode : createTblNode.createOptionList().getList()) {
 +                IgniteSqlCreateTableOption opt = (IgniteSqlCreateTableOption)optNode;
 +
 +                tblOptionProcessors.getOrDefault(opt.key(), UNSUPPORTED_OPTION_PROCESSOR).process(opt, ctx, createTblCmd);
 +            }
 +        }
 +
 +        List<SqlColumnDeclaration> colDeclarations = createTblNode.columnList().getList().stream()
 +            .filter(SqlColumnDeclaration.class::isInstance)
 +            .map(SqlColumnDeclaration.class::cast)
 +            .collect(Collectors.toList());
 +
 +        IgnitePlanner planner = ctx.planner();
 +
 +        List<ColumnDefinition> cols = new ArrayList<>();
 +
 +        for (SqlColumnDeclaration col : colDeclarations) {
 +            if (!col.name.isSimple())
 +                throw new IgniteSQLException("Unexpected value of columnName [" +
 +                    "expected a simple identifier, but was " + col.name + "; " +
 +                    "querySql=\"" + ctx.query() + "\"]", IgniteQueryErrorCode.PARSING);
 +
 +            String name = col.name.getSimple();
 +            RelDataType type = planner.convert(col.dataType);
 +
 +            Object dflt = null;
 +            if (col.expression != null)
 +                dflt = ((SqlLiteral)col.expression).getValue();
 +
 +            cols.add(new ColumnDefinition(name, type, dflt));
 +        }
 +
 +        createTblCmd.columns(cols);
 +
 +        List<SqlKeyConstraint> pkConstraints = createTblNode.columnList().getList().stream()
 +            .filter(SqlKeyConstraint.class::isInstance)
 +            .map(SqlKeyConstraint.class::cast)
 +            .collect(Collectors.toList());
 +
 +        if (pkConstraints.size() > 1)
 +            throw new IgniteSQLException("Unexpected amount of primary key constraints [" +
 +                "expected at most one, but was " + pkConstraints.size() + "; " +
 +                "querySql=\"" + ctx.query() + "\"]", IgniteQueryErrorCode.PARSING);
 +
 +        if (!F.isEmpty(pkConstraints)) {
 +            Set<String> dedupSet = new HashSet<>();
 +
 +            List<String> pkCols = pkConstraints.stream()
 +                .map(pk -> pk.getOperandList().get(1))
 +                .map(SqlNodeList.class::cast)
 +                .flatMap(l -> l.getList().stream())
 +                .map(SqlIdentifier.class::cast)
 +                .map(SqlIdentifier::getSimple)
 +                .filter(dedupSet::add)
 +                .collect(Collectors.toList());
 +
 +            createTblCmd.primaryKeyColumns(pkCols);
 +        }
 +
 +        return createTblCmd;
 +    }
 +
 +    /**
 +     * Converts a given DropTable AST to a DropTable command.
 +     *
 +     * @param dropTblNode Root node of the given AST.
 +     * @param ctx Planning context.
 +     */
 +    private DropTableCommand convertDropTable(SqlDropTable dropTblNode, PlanningContext ctx) {
 +        DropTableCommand dropTblCmd = new DropTableCommand();
 +
 +        dropTblCmd.schemaName(deriveSchemaName(dropTblNode.name, ctx));
 +        dropTblCmd.tableName(deriveObjectName(dropTblNode.name, ctx, "tableName"));
 +        dropTblCmd.ifExists(dropTblNode.ifExists);
 +
 +        return dropTblCmd;
 +    }
 +
 +    /** Derives a schema name from the compound identifier. */
 +    private String deriveSchemaName(SqlIdentifier id, PlanningContext ctx) {
 +        String schemaName;
 +        if (id.isSimple())
 +            schemaName = ctx.schemaName();
 +        else {
 +            SqlIdentifier schemaId = id.skipLast(1);
 +
 +            if (!schemaId.isSimple()) {
 +                throw new IgniteSQLException("Unexpected value of schemaName [" +
 +                    "expected a simple identifier, but was " + schemaId + "; " +
 +                    "querySql=\"" + ctx.query() + "\"]", IgniteQueryErrorCode.PARSING);
 +            }
 +
 +            schemaName = schemaId.getSimple();
 +        }
 +
 +        ensureSchemaExists(ctx, schemaName);
 +
 +        return schemaName;
 +    }
 +
 +    /** Derives an object(a table, an index, etc) name from the compound identifier. */
 +    private String deriveObjectName(SqlIdentifier id, PlanningContext ctx, String objDesc) {
 +        if (id.isSimple())
 +            return id.getSimple();
 +
 +        SqlIdentifier objId = id.getComponent(id.skipLast(1).names.size());
 +
 +        if (!objId.isSimple()) {
 +            throw new IgniteSQLException("Unexpected value of " + objDesc + " [" +
 +                "expected a simple identifier, but was " + objId + "; " +
 +                "querySql=\"" + ctx.query() + "\"]", IgniteQueryErrorCode.PARSING);
 +        }
 +
 +        return objId.getSimple();
 +    }
 +
 +    /** */
 +    private void ensureSchemaExists(PlanningContext ctx, String schemaName) {
 +        if (ctx.catalogReader().getRootSchema().getSubSchema(schemaName, true) == null)
 +            throw new IgniteSQLException("Schema with name " + schemaName + " not found",
 +                IgniteQueryErrorCode.SCHEMA_NOT_FOUND);
 +    }
 +
 +    /**
 +     * Short cut for validating that option value is a simple identifier.
 +     *
 +     * @param opt An option to validate.
 +     * @param ctx Planning context.
 +     * @throws IgniteSQLException In case the validation was failed.
 +     */
 +    private String paramIsSqlIdentifierValidator(IgniteSqlCreateTableOption opt, PlanningContext ctx) {
 +        if (!(opt.value() instanceof SqlIdentifier) || !((SqlIdentifier)opt.value()).isSimple())
 +            throwOptionParsingException(opt, "a simple identifier", ctx.query());
 +
 +        return ((SqlIdentifier)opt.value()).getSimple();
 +    }
 +    
 +    /**
 +     * Creates a validator for an option which value should be value of given enumeration.
 +     *
 +     * @param clz Enumeration class to create validator for.
 +     */
 +    private static <T extends Enum<T>> BiFunction<IgniteSqlCreateTableOption, PlanningContext, T> validatorForEnumValue(
 +        Class<T> clz
 +    ) {
 +        return (opt, ctx) -> {
 +            T val = null;
 +
 +            if (opt.value() instanceof SqlIdentifier) {
 +                val = Arrays.stream(clz.getEnumConstants())
 +                    .filter(m -> m.name().equalsIgnoreCase(opt.value().toString()))
 +                    .findFirst()
 +                    .orElse(null);
 +            }
 +
 +            if (val == null)
 +                throwOptionParsingException(opt, "values are "
 +                    + Arrays.toString(clz.getEnumConstants()), ctx.query());
 +
 +            return val;
 +        };
 +    }
 +
 +    /**
 +     * Throws exception with message relates to validation of create table option.
 +     *
 +     * @param opt An option which validation was failed.
 +     * @param exp A string representing expected values.
 +     * @param qry A query the validation was failed for.
 +     */
 +    private static void throwOptionParsingException(IgniteSqlCreateTableOption opt, String exp, String qry) {
 +        throw new IgniteSQLException("Unexpected value for param " + opt.key() + " [" +
 +            "expected " + exp + ", but was " + opt.value() + "; " +
 +            "querySql=\"" + qry + "\"]", IgniteQueryErrorCode.PARSING);
 +    }
 +
 +    /** */
 +    private static class TableOptionProcessor<T> {
 +        /** */
 +        private final IgniteSqlCreateTableOptionEnum key;
 +
 +        /** */
 +        private final BiFunction<IgniteSqlCreateTableOption, PlanningContext, T> validator;
 +
 +        /** */
 +        private final BiConsumer<CreateTableCommand, T> valSetter;
 +
 +        /**
 +         * @param key Option key this processor is supopsed to handle.
 +         * @param validator Validator that derives a value from a {@link SqlNode},
 +         *                 validates it and then returns if validation passed,
 +         *                 throws an exeption otherwise.
 +         * @param valSetter Setter sets the value recived from the validator
 +         *                 to the given {@link CreateTableCommand}.
 +         */
 +        private TableOptionProcessor(
 +            IgniteSqlCreateTableOptionEnum key,
 +            BiFunction<IgniteSqlCreateTableOption, PlanningContext, T> validator,
 +            BiConsumer<CreateTableCommand, T> valSetter
 +        ) {
 +            this.key = key;
 +            this.validator = validator;
 +            this.valSetter = valSetter;
 +        }
 +
 +        /**
 +         * Processes the given option, validates it's value and then sets the appropriate
 +         * field in a given command, throws an exception if the validation failed.
 +         *
 +         * @param opt Option to validate.
 +         * @param ctx Planning context.
 +         * @param cmd Command instance to set a validation result.
 +         */
 +        private void process(IgniteSqlCreateTableOption opt, PlanningContext ctx, CreateTableCommand cmd) {
 +            assert key == null || key == opt.key() : "Unexpected create table option [expected=" + key + ", actual=" + opt.key() + "]";
 +
 +            valSetter.accept(cmd, validator.apply(opt, ctx));
 +        }
 +
 +        /**
 +         * @return Key this processor is supposed to handle.
 +         */
 +        private IgniteSqlCreateTableOptionEnum key() {
 +            return key;
 +        }
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/AbstractIgniteJoin.java
index 956ae76,0000000..28f2820
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/AbstractIgniteJoin.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/AbstractIgniteJoin.java
@@@ -1,317 -1,0 +1,318 @@@
 +/*
 + * 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.calcite.rel;
 +
 +import java.util.ArrayList;
 +import java.util.HashMap;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Set;
 +
 +import com.google.common.collect.ImmutableList;
 +import org.apache.calcite.plan.RelOptCluster;
 +import org.apache.calcite.plan.RelTraitSet;
 +import org.apache.calcite.rel.RelCollation;
 +import org.apache.calcite.rel.RelCollations;
 +import org.apache.calcite.rel.RelDistribution;
 +import org.apache.calcite.rel.RelFieldCollation;
 +import org.apache.calcite.rel.RelNode;
 +import org.apache.calcite.rel.RelWriter;
 +import org.apache.calcite.rel.core.CorrelationId;
 +import org.apache.calcite.rel.core.Join;
 +import org.apache.calcite.rel.core.JoinRelType;
 +import org.apache.calcite.rel.metadata.RelMetadataQuery;
 +import org.apache.calcite.rex.RexNode;
 +import org.apache.calcite.sql.SqlExplainLevel;
 +import org.apache.calcite.util.ImmutableIntList;
 +import org.apache.calcite.util.Pair;
 +import org.apache.calcite.util.Util;
 +import org.apache.calcite.util.mapping.Mappings;
 +import org.apache.ignite.internal.processors.query.calcite.trait.CorrelationTrait;
 +import org.apache.ignite.internal.processors.query.calcite.trait.DistributionFunction;
 +import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution;
 +import org.apache.ignite.internal.processors.query.calcite.trait.RewindabilityTrait;
 +import org.apache.ignite.internal.processors.query.calcite.trait.TraitUtils;
 +import org.apache.ignite.internal.processors.query.calcite.trait.TraitsAwareIgniteRel;
 +import org.apache.ignite.internal.processors.query.calcite.util.Commons;
 +import org.apache.ignite.internal.util.typedef.F;
 +
 +import static org.apache.calcite.rel.RelDistribution.Type.HASH_DISTRIBUTED;
 +import static org.apache.calcite.rel.core.JoinRelType.RIGHT;
 +import static org.apache.ignite.internal.processors.query.calcite.metadata.IgniteMdRowCount.joinRowCount;
 +import static org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions.broadcast;
 +import static org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions.hash;
 +import static org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions.random;
 +import static org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions.single;
 +
 +/** */
 +public abstract class AbstractIgniteJoin extends Join implements TraitsAwareIgniteRel {
 +    /** */
 +    protected AbstractIgniteJoin(RelOptCluster cluster, RelTraitSet traitSet, RelNode left, RelNode right,
 +        RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType) {
 +        super(cluster, traitSet, left, right, condition, variablesSet, joinType);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public RelWriter explainTerms(RelWriter pw) {
 +        return super.explainTerms(pw)
-             .itemIf("variablesSet", Commons.transform(variablesSet.asList(), CorrelationId::getId), pw.getDetailLevel() == SqlExplainLevel.ALL_ATTRIBUTES);
++            .itemIf("variablesSet", Commons.transform(variablesSet.asList(), CorrelationId::getId),
++                pw.getDetailLevel() == SqlExplainLevel.ALL_ATTRIBUTES);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public List<Pair<RelTraitSet, List<RelTraitSet>>> deriveCollation(RelTraitSet nodeTraits, List<RelTraitSet> inputTraits) {
 +        // We preserve left collation since it's translated into a nested loop join with an outer loop
 +        // over a left edge. The code below checks and projects left collation on an output row type.
 +
 +        RelTraitSet left = inputTraits.get(0), right = inputTraits.get(1);
 +
 +        RelTraitSet outTraits, leftTraits, rightTraits;
 +
 +        RelCollation collation = TraitUtils.collation(left);
 +
 +        // If nulls are possible at left we has to check whether NullDirection.LAST flag is set on sorted fields.
 +        // TODO set NullDirection.LAST for insufficient fields instead of erasing collation.
 +        if (joinType == RIGHT || joinType == JoinRelType.FULL) {
 +            for (RelFieldCollation field : collation.getFieldCollations()) {
 +                if (RelFieldCollation.NullDirection.LAST != field.nullDirection) {
 +                    collation = RelCollations.EMPTY;
 +                    break;
 +                }
 +            }
 +        }
 +
 +        outTraits = nodeTraits.replace(collation);
 +        leftTraits = left.replace(collation);
 +        rightTraits = right.replace(RelCollations.EMPTY);
 +
 +        return ImmutableList.of(Pair.of(outTraits, ImmutableList.of(leftTraits, rightTraits)));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public List<Pair<RelTraitSet, List<RelTraitSet>>> deriveRewindability(RelTraitSet nodeTraits, List<RelTraitSet> inputTraits) {
 +        // The node is rewindable only if both sources are rewindable.
 +
 +        RelTraitSet left = inputTraits.get(0), right = inputTraits.get(1);
 +
 +        RewindabilityTrait leftRewindability = TraitUtils.rewindability(left);
 +        RewindabilityTrait rightRewindability = TraitUtils.rewindability(right);
 +
 +        List<Pair<RelTraitSet, List<RelTraitSet>>> pairs = new ArrayList<>();
 +
 +        pairs.add(Pair.of(nodeTraits.replace(RewindabilityTrait.ONE_WAY),
 +            ImmutableList.of(left.replace(RewindabilityTrait.ONE_WAY), right.replace(RewindabilityTrait.ONE_WAY))));
 +
 +        if (leftRewindability.rewindable() && rightRewindability.rewindable())
 +            pairs.add(Pair.of(nodeTraits.replace(RewindabilityTrait.REWINDABLE),
 +                ImmutableList.of(left.replace(RewindabilityTrait.REWINDABLE), right.replace(RewindabilityTrait.REWINDABLE))));
 +
 +        return ImmutableList.copyOf(pairs);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public List<Pair<RelTraitSet, List<RelTraitSet>>> deriveDistribution(RelTraitSet nodeTraits, List<RelTraitSet> inputTraits) {
 +        // There are several rules:
 +        // 1) any join is possible on broadcast or single distribution
 +        // 2) hash distributed join is possible when join keys are superset of source distribution keys
 +        // 3) hash and broadcast distributed tables can be joined when join keys equal to hash
 +        //    distributed table distribution keys and:
 +        //      3.1) it's a left join and a hash distributed table is at left
 +        //      3.2) it's a right join and a hash distributed table is at right
 +        //      3.3) it's an inner join, this case a hash distributed table may be at any side
 +
 +        RelTraitSet left = inputTraits.get(0), right = inputTraits.get(1);
 +
 +        List<Pair<RelTraitSet, List<RelTraitSet>>> res = new ArrayList<>();
 +
 +        IgniteDistribution leftDistr = TraitUtils.distribution(left);
 +        IgniteDistribution rightDistr = TraitUtils.distribution(right);
 +
 +        IgniteDistribution left2rightProjectedDistr = leftDistr.apply(buildProjectionMapping(true));
 +        IgniteDistribution right2leftProjectedDistr = rightDistr.apply(buildProjectionMapping(false));
 +
 +        RelTraitSet outTraits;
 +        RelTraitSet leftTraits;
 +        RelTraitSet rightTraits;
 +
 +        if (leftDistr == broadcast() && rightDistr == broadcast()) {
 +            outTraits = nodeTraits.replace(broadcast());
 +            leftTraits = left.replace(broadcast());
 +            rightTraits = right.replace(broadcast());
 +        }
 +        else {
 +            outTraits = nodeTraits.replace(single());
 +            leftTraits = left.replace(single());
 +            rightTraits = right.replace(single());
 +        }
 +
 +        res.add(Pair.of(outTraits, ImmutableList.of(leftTraits, rightTraits)));
 +
 +        if (F.isEmpty(joinInfo.pairs()))
 +            return ImmutableList.copyOf(res);
 +
 +        if (leftDistr.getType() == HASH_DISTRIBUTED && left2rightProjectedDistr != random()) {
 +            outTraits = nodeTraits.replace(leftDistr);
 +            leftTraits = left.replace(leftDistr);
 +            rightTraits = right.replace(left2rightProjectedDistr);
 +
 +            res.add(Pair.of(outTraits, ImmutableList.of(leftTraits, rightTraits)));
 +        }
 +
 +        if (rightDistr.getType() == HASH_DISTRIBUTED && right2leftProjectedDistr != random()) {
 +            outTraits = nodeTraits.replace(rightDistr);
 +            leftTraits = left.replace(right2leftProjectedDistr);
 +            rightTraits = right.replace(rightDistr);
 +
 +            res.add(Pair.of(outTraits, ImmutableList.of(leftTraits, rightTraits)));
 +        }
 +
 +        leftTraits = left.replace(hash(joinInfo.leftKeys, DistributionFunction.hash()));
 +        rightTraits = right.replace(hash(joinInfo.rightKeys, DistributionFunction.hash()));
 +
 +        outTraits = nodeTraits.replace(hash(joinInfo.leftKeys, DistributionFunction.hash()));
 +        res.add(Pair.of(outTraits, ImmutableList.of(leftTraits, rightTraits)));
 +
 +        outTraits = nodeTraits.replace(hash(joinInfo.rightKeys, DistributionFunction.hash()));
 +        res.add(Pair.of(outTraits, ImmutableList.of(leftTraits, rightTraits)));
 +
 +        return ImmutableList.copyOf(res);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public List<Pair<RelTraitSet, List<RelTraitSet>>> deriveCorrelation(RelTraitSet nodeTraits,
 +        List<RelTraitSet> inTraits) {
 +        // left correlations
 +        Set<CorrelationId> corrIds = new HashSet<>(TraitUtils.correlation(inTraits.get(0)).correlationIds());
 +        // right correlations
 +        corrIds.addAll(TraitUtils.correlation(inTraits.get(1)).correlationIds());
 +
 +        return ImmutableList.of(Pair.of(nodeTraits.replace(CorrelationTrait.correlations(corrIds)), inTraits));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public Pair<RelTraitSet, List<RelTraitSet>> passThroughCollation(RelTraitSet nodeTraits, List<RelTraitSet> inputTraits) {
 +        // We preserve left collation since it's translated into a nested loop join with an outer loop
 +        // over a left edge. The code below checks whether a desired collation is possible and requires
 +        // appropriate collation from the left edge.
 +
 +        RelCollation collation = TraitUtils.collation(nodeTraits);
 +
 +        RelTraitSet left = inputTraits.get(0), right = inputTraits.get(1);
 +
 +        if (collation.equals(RelCollations.EMPTY))
 +            return Pair.of(nodeTraits,
 +                ImmutableList.of(left.replace(RelCollations.EMPTY), right.replace(RelCollations.EMPTY)));
 +
 +        if (!projectsLeft(collation))
 +            collation = RelCollations.EMPTY;
 +        else if (joinType == RIGHT || joinType == JoinRelType.FULL) {
 +            for (RelFieldCollation field : collation.getFieldCollations()) {
 +                if (RelFieldCollation.NullDirection.LAST != field.nullDirection) {
 +                    collation = RelCollations.EMPTY;
 +                    break;
 +                }
 +            }
 +        }
 +
 +        return Pair.of(nodeTraits.replace(collation),
 +            ImmutableList.of(left.replace(collation), right.replace(RelCollations.EMPTY)));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public Pair<RelTraitSet, List<RelTraitSet>> passThroughDistribution(
 +        RelTraitSet nodeTraits,
 +        List<RelTraitSet> inputTraits
 +    ) {
 +        // Tere are several rules:
 +        // 1) any join is possible on broadcast or single distribution
 +        // 2) hash distributed join is possible when join keys equal to source distribution keys
 +        // 3) hash and broadcast distributed tables can be joined when join keys equal to hash
 +        //    distributed table distribution keys and:
 +        //      3.1) it's a left join and a hash distributed table is at left
 +        //      3.2) it's a right join and a hash distributed table is at right
 +        //      3.3) it's an inner join, this case a hash distributed table may be at any side
 +
 +        RelTraitSet left = inputTraits.get(0), right = inputTraits.get(1);
 +
 +        IgniteDistribution distribution = TraitUtils.distribution(nodeTraits);
 +
 +        RelDistribution.Type distrType = distribution.getType();
 +        switch (distrType) {
 +            case BROADCAST_DISTRIBUTED:
 +            case SINGLETON:
 +                return Pair.of(nodeTraits, Commons.transform(inputTraits, t -> t.replace(distribution)));
 +
 +            case HASH_DISTRIBUTED:
 +            case RANDOM_DISTRIBUTED:
 +                // Such join may be replaced as a cross join with a filter uppon it.
 +                // It's impossible to get random or hash distribution from a cross join.
 +                if (F.isEmpty(joinInfo.pairs()))
 +                    break;
 +
 +                // We cannot provide random distribution without unique constrain on join keys,
 +                // so, we require hash distribution (wich satisfies random distribution) instead.
 +                DistributionFunction function = distrType == HASH_DISTRIBUTED
 +                    ? distribution.function()
 +                    : DistributionFunction.hash();
 +
 +                IgniteDistribution outDistr = hash(joinInfo.leftKeys, function);
 +
 +                if (distrType != HASH_DISTRIBUTED || outDistr.satisfies(distribution)) {
 +                    return Pair.of(nodeTraits.replace(outDistr),
 +                        ImmutableList.of(left.replace(outDistr), right.replace(hash(joinInfo.rightKeys, function))));
 +                }
 +
 +            default:
 +                // NO-OP
 +        }
 +
 +        return Pair.of(nodeTraits.replace(single()), Commons.transform(inputTraits, t -> t.replace(single())));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public double estimateRowCount(RelMetadataQuery mq) {
 +        return Util.first(joinRowCount(mq, this), 1D);
 +    }
 +
 +    /** */
 +    protected boolean projectsLeft(RelCollation collation) {
 +        int leftFieldCount = getLeft().getRowType().getFieldCount();
 +        for (int field : RelCollations.ordinals(collation)) {
 +            if (field >= leftFieldCount)
 +                return false;
 +        }
 +        return true;
 +    }
 +
 +    /** Creates mapping from left join keys to the right and vice versa with regards to {@code left2Right}. */
 +    protected Mappings.TargetMapping buildProjectionMapping(boolean left2Right) {
 +        ImmutableIntList sourceKeys = left2Right ? joinInfo.leftKeys : joinInfo.rightKeys;
 +        ImmutableIntList targetKeys = left2Right ? joinInfo.rightKeys : joinInfo.leftKeys;
 +
 +        Map<Integer, Integer> keyMap = new HashMap<>();
 +        for (int i = 0; i < joinInfo.leftKeys.size(); i++)
 +            keyMap.put(sourceKeys.get(i), targetKeys.get(i));
 +
 +        return Mappings.target(
 +            keyMap,
 +            (left2Right ? left : right).getRowType().getFieldCount(),
 +            (left2Right ? right : left).getRowType().getFieldCount()
 +        );
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteCorrelatedNestedLoopJoin.java
index c760dc6,0000000..bd62f1e
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteCorrelatedNestedLoopJoin.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteCorrelatedNestedLoopJoin.java
@@@ -1,238 -1,0 +1,241 @@@
 +/*
 + * 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.calcite.rel;
 +
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Set;
 +
 +import com.google.common.collect.ImmutableList;
 +import com.google.common.collect.ImmutableSet;
 +import org.apache.calcite.plan.RelOptCluster;
 +import org.apache.calcite.plan.RelOptCost;
 +import org.apache.calcite.plan.RelOptPlanner;
 +import org.apache.calcite.plan.RelTraitSet;
 +import org.apache.calcite.rel.RelCollation;
 +import org.apache.calcite.rel.RelCollations;
 +import org.apache.calcite.rel.RelInput;
 +import org.apache.calcite.rel.RelNode;
 +import org.apache.calcite.rel.RelWriter;
 +import org.apache.calcite.rel.core.CorrelationId;
 +import org.apache.calcite.rel.core.Join;
 +import org.apache.calcite.rel.core.JoinRelType;
 +import org.apache.calcite.rel.metadata.RelMetadataQuery;
 +import org.apache.calcite.rex.RexNode;
 +import org.apache.calcite.util.Pair;
 +import org.apache.ignite.internal.processors.query.calcite.metadata.cost.IgniteCost;
 +import org.apache.ignite.internal.processors.query.calcite.metadata.cost.IgniteCostFactory;
 +import org.apache.ignite.internal.processors.query.calcite.trait.CorrelationTrait;
 +import org.apache.ignite.internal.processors.query.calcite.trait.RewindabilityTrait;
 +import org.apache.ignite.internal.processors.query.calcite.trait.TraitUtils;
 +import org.apache.ignite.internal.processors.query.calcite.util.Commons;
 +import org.apache.ignite.internal.util.typedef.F;
 +
 +import static org.apache.ignite.internal.processors.query.calcite.util.Commons.maxPrefix;
 +
 +/**
 + * Relational expression that combines two relational expressions according to
 + * some condition.
 + *
 + * <p>Each output row has columns from the left and right inputs.
 + * The set of output rows is a subset of the cartesian product of the two
 + * inputs; precisely which subset depends on the join condition.
 + */
 +public class IgniteCorrelatedNestedLoopJoin extends AbstractIgniteJoin {
 +    /**
 +     * Creates a Join.
 +     *
 +     * @param cluster          Cluster
 +     * @param traitSet         Trait set
 +     * @param left             Left input
 +     * @param right            Right input
 +     * @param condition        Join condition
 +     * @param joinType         Join type
 +     * @param variablesSet     Set variables that are set by the
 +     *                         LHS and used by the RHS and are not available to
 +     *                         nodes above this Join in the tree
 +     */
-     public IgniteCorrelatedNestedLoopJoin(RelOptCluster cluster, RelTraitSet traitSet, RelNode left, RelNode right, RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType) {
++    public IgniteCorrelatedNestedLoopJoin(RelOptCluster cluster, RelTraitSet traitSet, RelNode left, RelNode right,
++        RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType) {
 +        super(cluster, traitSet, left, right, condition, variablesSet, joinType);
 +    }
 +
 +    /** */
 +    public IgniteCorrelatedNestedLoopJoin(RelInput input) {
 +        this(input.getCluster(),
 +            input.getTraitSet().replace(IgniteConvention.INSTANCE),
 +            input.getInputs().get(0),
 +            input.getInputs().get(1),
 +            input.getExpression("condition"),
 +            ImmutableSet.copyOf(Commons.transform(input.getIntegerList("variablesSet"), CorrelationId::new)),
 +            input.getEnum("joinType", JoinRelType.class));
 +    }
 +
 +    /** {@inheritDoc} */
-     @Override public Join copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode right, JoinRelType joinType, boolean semiJoinDone) {
++    @Override public Join copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode right, JoinRelType joinType,
++        boolean semiJoinDone) {
 +        return new IgniteCorrelatedNestedLoopJoin(getCluster(), traitSet, left, right, condition, variablesSet, joinType);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public <T> T accept(IgniteRelVisitor<T> visitor) {
 +        return visitor.visit(this);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public List<Pair<RelTraitSet, List<RelTraitSet>>> deriveCollation(
 +        RelTraitSet nodeTraits,
 +        List<RelTraitSet> inputTraits
 +    ) {
 +        RelTraitSet left = inputTraits.get(0), right = inputTraits.get(1);
 +        RelCollation leftCollation = TraitUtils.collation(left), rightCollation = TraitUtils.collation(right);
 +
 +        List<Integer> newRightCollationFields = maxPrefix(rightCollation.getKeys(), joinInfo.leftKeys);
 +
 +        if (F.isEmpty(newRightCollationFields))
 +            return ImmutableList.of(Pair.of(nodeTraits.replace(RelCollations.EMPTY), inputTraits));
 +
 +        // We preserve left edge collation only if batch size == 1
 +        if (variablesSet.size() == 1)
 +            nodeTraits = nodeTraits.replace(leftCollation);
 +        else
 +            nodeTraits = nodeTraits.replace(RelCollations.EMPTY);
 +
 +        return ImmutableList.of(Pair.of(nodeTraits, inputTraits));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public List<Pair<RelTraitSet, List<RelTraitSet>>> deriveRewindability(
 +        RelTraitSet nodeTraits,
 +        List<RelTraitSet> inputTraits
 +    ) {
 +        // Correlated nested loop requires rewindable right edge.
 +        RelTraitSet left = inputTraits.get(0), right = inputTraits.get(1);
 +
 +        RewindabilityTrait rewindability = TraitUtils.rewindability(left);
 +
 +        return ImmutableList.of(Pair.of(nodeTraits.replace(rewindability),
 +            ImmutableList.of(left, right.replace(RewindabilityTrait.REWINDABLE))));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public Pair<RelTraitSet, List<RelTraitSet>> passThroughCollation(
 +        RelTraitSet nodeTraits,
 +        List<RelTraitSet> inputTraits
 +    ) {
 +        RelTraitSet left = inputTraits.get(0), right = inputTraits.get(1);
 +
 +        // We preserve left edge collation only if batch size == 1
 +        if (variablesSet.size() == 1) {
 +            Pair<RelTraitSet, List<RelTraitSet>> baseTraits = super.passThroughCollation(nodeTraits, inputTraits);
 +
 +            return Pair.of(
 +                baseTraits.getKey(),
 +                ImmutableList.of(
 +                    baseTraits.getValue().get(0),
 +                    baseTraits.getValue().get(1)
 +                )
 +            );
 +        }
 +
 +        return Pair.of(nodeTraits.replace(RelCollations.EMPTY),
 +            ImmutableList.of(left.replace(RelCollations.EMPTY), right));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public Pair<RelTraitSet, List<RelTraitSet>> passThroughRewindability(RelTraitSet nodeTraits, List<RelTraitSet> inputTraits) {
 +        // Correlated nested loop requires rewindable right edge.
 +        RelTraitSet left = inputTraits.get(0), right = inputTraits.get(1);
 +
 +        RewindabilityTrait rewindability = TraitUtils.rewindability(nodeTraits);
 +
 +        return Pair.of(nodeTraits.replace(rewindability),
 +            ImmutableList.of(left.replace(rewindability), right.replace(RewindabilityTrait.REWINDABLE)));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) {
 +        IgniteCostFactory costFactory = (IgniteCostFactory)planner.getCostFactory();
 +
 +        double leftCount = mq.getRowCount(getLeft());
 +
 +        if (Double.isInfinite(leftCount))
 +            return costFactory.makeInfiniteCost();
 +
 +        double rightCount = mq.getRowCount(getRight());
 +
 +        if (Double.isInfinite(rightCount))
 +            return costFactory.makeInfiniteCost();
 +
 +        double rows = leftCount * rightCount;
 +
 +        return costFactory.makeCost(rows,
 +            rows * (IgniteCost.ROW_COMPARISON_COST + IgniteCost.ROW_PASS_THROUGH_COST), 0);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public Pair<RelTraitSet, List<RelTraitSet>> passThroughCorrelation(RelTraitSet nodeTraits,
 +        List<RelTraitSet> inTraits) {
 +        CorrelationTrait nodeCorr = TraitUtils.correlation(nodeTraits);
 +
 +        Set<CorrelationId> selfCorrIds = new HashSet<>(CorrelationTrait.correlations(variablesSet).correlationIds());
 +        selfCorrIds.addAll(nodeCorr.correlationIds());
 +
 +        return Pair.of(nodeTraits,
 +            ImmutableList.of(
 +                inTraits.get(0).replace(nodeCorr),
 +                inTraits.get(1).replace(CorrelationTrait.correlations(selfCorrIds))
 +            )
 +        );
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public List<Pair<RelTraitSet, List<RelTraitSet>>> deriveCorrelation(RelTraitSet nodeTraits,
 +        List<RelTraitSet> inTraits) {
 +        Set<CorrelationId> rightCorrIds = TraitUtils.correlation(inTraits.get(1)).correlationIds();
 +
 +        if (!rightCorrIds.containsAll(variablesSet))
 +            return ImmutableList.of();
 +
 +        Set<CorrelationId> corrIds = new HashSet<>(rightCorrIds);
 +
 +        // Left + right
 +        corrIds.addAll(TraitUtils.correlation(inTraits.get(0)).correlationIds());
 +
 +        corrIds.removeAll(variablesSet);
 +
 +        return ImmutableList.of(Pair.of(nodeTraits.replace(CorrelationTrait.correlations(corrIds)), inTraits));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public IgniteRel clone(RelOptCluster cluster, List<IgniteRel> inputs) {
-         return new IgniteCorrelatedNestedLoopJoin(cluster, getTraitSet(), inputs.get(0), inputs.get(1), getCondition(), getVariablesSet(), getJoinType());
++        return new IgniteCorrelatedNestedLoopJoin(cluster, getTraitSet(), inputs.get(0), inputs.get(1), getCondition(),
++            getVariablesSet(), getJoinType());
 +    }
 +
 +    /** */
 +    @Override public RelWriter explainTerms(RelWriter pw) {
 +        return super.explainTerms(pw).item("correlationVariables", getVariablesSet());
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public double estimateRowCount(RelMetadataQuery mq) {
 +        // condition selectivity already counted within the external filter
 +        return super.estimateRowCount(mq) / mq.getSelectivity(this, getCondition());
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteNestedLoopJoin.java
index 8614ece,0000000..3e8c6da
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteNestedLoopJoin.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteNestedLoopJoin.java
@@@ -1,112 -1,0 +1,115 @@@
 +/*
 + * 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.calcite.rel;
 +
 +import java.util.List;
 +import java.util.Set;
 +
 +import com.google.common.collect.ImmutableSet;
 +import org.apache.calcite.plan.RelOptCluster;
 +import org.apache.calcite.plan.RelOptCost;
 +import org.apache.calcite.plan.RelOptPlanner;
 +import org.apache.calcite.plan.RelTraitSet;
 +import org.apache.calcite.rel.RelInput;
 +import org.apache.calcite.rel.RelNode;
 +import org.apache.calcite.rel.core.CorrelationId;
 +import org.apache.calcite.rel.core.Join;
 +import org.apache.calcite.rel.core.JoinRelType;
 +import org.apache.calcite.rel.metadata.RelMetadataQuery;
 +import org.apache.calcite.rex.RexNode;
 +import org.apache.ignite.internal.processors.query.calcite.metadata.cost.IgniteCost;
 +import org.apache.ignite.internal.processors.query.calcite.metadata.cost.IgniteCostFactory;
 +import org.apache.ignite.internal.processors.query.calcite.util.Commons;
 +
 +/**
 + * Relational expression that combines two relational expressions according to
 + * some condition.
 + *
 + * <p>Each output row has columns from the left and right inputs.
 + * The set of output rows is a subset of the cartesian product of the two
 + * inputs; precisely which subset depends on the join condition.
 + */
 +public class IgniteNestedLoopJoin extends AbstractIgniteJoin {
 +    /**
 +     * Creates a Join.
 +     *
 +     * @param cluster          Cluster
 +     * @param traitSet         Trait set
 +     * @param left             Left input
 +     * @param right            Right input
 +     * @param condition        Join condition
 +     * @param joinType         Join type
 +     * @param variablesSet     Set variables that are set by the
 +     *                         LHS and used by the RHS and are not available to
 +     *                         nodes above this Join in the tree
 +     */
-     public IgniteNestedLoopJoin(RelOptCluster cluster, RelTraitSet traitSet, RelNode left, RelNode right, RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType) {
++    public IgniteNestedLoopJoin(RelOptCluster cluster, RelTraitSet traitSet, RelNode left, RelNode right,
++        RexNode condition, Set<CorrelationId> variablesSet, JoinRelType joinType) {
 +        super(cluster, traitSet, left, right, condition, variablesSet, joinType);
 +    }
 +
 +    /** */
 +    public IgniteNestedLoopJoin(RelInput input) {
 +        this(input.getCluster(),
 +            input.getTraitSet().replace(IgniteConvention.INSTANCE),
 +            input.getInputs().get(0),
 +            input.getInputs().get(1),
 +            input.getExpression("condition"),
 +            ImmutableSet.copyOf(Commons.transform(input.getIntegerList("variablesSet"), CorrelationId::new)),
 +            input.getEnum("joinType", JoinRelType.class));
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) {
 +        IgniteCostFactory costFactory = (IgniteCostFactory)planner.getCostFactory();
 +
 +        double leftCount = mq.getRowCount(getLeft());
 +
 +        if (Double.isInfinite(leftCount))
 +            return costFactory.makeInfiniteCost();
 +
 +        double rightCount = mq.getRowCount(getRight());
 +
 +        if (Double.isInfinite(rightCount))
 +            return costFactory.makeInfiniteCost();
 +
 +        double rows = leftCount * rightCount;
 +
 +        double rightSize = rightCount * getRight().getRowType().getFieldCount() * IgniteCost.AVERAGE_FIELD_SIZE;
 +
 +        return costFactory.makeCost(rows,
 +            rows * (IgniteCost.ROW_COMPARISON_COST + IgniteCost.ROW_PASS_THROUGH_COST), 0, rightSize, 0);
 +    }
 +
 +    /** {@inheritDoc} */
-     @Override public Join copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode right, JoinRelType joinType, boolean semiJoinDone) {
++    @Override public Join copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode right, JoinRelType joinType,
++        boolean semiJoinDone) {
 +        return new IgniteNestedLoopJoin(getCluster(), traitSet, left, right, condition, variablesSet, joinType);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public <T> T accept(IgniteRelVisitor<T> visitor) {
 +        return visitor.visit(this);
 +    }
 +
 +    /** {@inheritDoc} */
 +    @Override public IgniteRel clone(RelOptCluster cluster, List<IgniteRel> inputs) {
-         return new IgniteNestedLoopJoin(cluster, getTraitSet(), inputs.get(0), inputs.get(1), getCondition(), getVariablesSet(), getJoinType());
++        return new IgniteNestedLoopJoin(cluster, getTraitSet(), inputs.get(0), inputs.get(1), getCondition(),
++            getVariablesSet(), getJoinType());
 +    }
 +}
diff --cc modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableModify.java
index 66c274d,0000000..166c432
mode 100644,000000..100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableModify.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableModify.java
@@@ -1,103 -1,0 +1,104 @@@
 +/*
 + * 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.calcite.rel;
 +
 +import java.util.List;
 +import org.apache.calcite.plan.RelOptCluster;
 +import org.apache.calcite.plan.RelOptTable;
 +import org.apache.calcite.plan.RelTraitSet;
 +import org.apache.calcite.rel.RelInput;
 +import org.apache.calcite.rel.RelNode;
 +import org.apache.calcite.rel.core.TableModify;
 +import org.apache.calcite.rex.RexNode;
 +import org.apache.ignite.internal.processors.query.calcite.util.Commons;
 +
 +/** */
 +public class IgniteTableModify extends TableModify implements IgniteRel {
 +    /**
 +     * Creates a {@code TableModify}.
 +     *
 +     * <p>The UPDATE operation has format like this:
 +     * <blockquote>
... 12564 lines suppressed ...