Repository: ignite
Updated Branches:
  refs/heads/ignite-2.4 c214db879 -> 75c27d5e4


IGNITE-7274 Web Console: Support multiple statements on Queries screen.
(cherry picked from commit 1926783)


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

Branch: refs/heads/ignite-2.4
Commit: 75c27d5e49d7458e46eb46e6f87a445c3f1320ea
Parents: c214db8
Author: Alexey Kuznetsov <[email protected]>
Authored: Thu Jan 18 09:25:19 2018 +0700
Committer: Alexey Kuznetsov <[email protected]>
Committed: Thu Jan 18 09:48:20 2018 +0700

----------------------------------------------------------------------
 .../cache/GatewayProtectedCacheProxy.java       | 14 ++++
 .../processors/cache/IgniteCacheProxy.java      | 41 +++++++---
 .../processors/cache/IgniteCacheProxyImpl.java  | 86 +++++++++++++-------
 .../processors/query/GridQueryProcessor.java    | 40 ++++++---
 .../internal/visor/query/VisorQueryTask.java    | 14 +++-
 .../processors/query/h2/IgniteH2Indexing.java   |  3 +
 .../query/h2/sql/GridSqlQueryParser.java        | 21 ++++-
 .../cache/GridCacheCrossCacheQuerySelfTest.java | 78 ++++++++++++++----
 .../cache/index/H2DynamicTableSelfTest.java     |  6 +-
 9 files changed, 226 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/75c27d5e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java
index 564b18a..27fc395 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java
@@ -387,6 +387,20 @@ public class GatewayProtectedCacheProxy<K, V> extends 
AsyncSupportAdapter<Ignite
     }
 
     /** {@inheritDoc} */
+    @Override public List<FieldsQueryCursor<List<?>>> 
queryMultipleStatements(SqlFieldsQuery qry) {
+        GridCacheGateway<K, V> gate = gate();
+
+        CacheOperationContext prev = onEnter(gate, opCtx);
+
+        try {
+            return delegate.queryMultipleStatements(qry);
+        }
+        finally {
+            onLeave(gate, prev);
+        }
+    }
+
+    /** {@inheritDoc} */
     @Override public <T, R> QueryCursor<R> query(Query<T> qry, 
IgniteClosure<T, R> transformer) {
         GridCacheGateway<K, V> gate = gate();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/75c27d5e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
index 361764e..c333125 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
@@ -19,11 +19,16 @@ package org.apache.ignite.internal.processors.cache;
 
 import java.io.Externalizable;
 import java.util.Date;
+import java.util.List;
 import java.util.UUID;
 import org.apache.ignite.IgniteCache;
-import org.apache.ignite.lang.IgniteAsyncSupport;
+import org.apache.ignite.cache.query.FieldsQueryCursor;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.lang.IgniteFuture;
 
+/**
+ * Cache proxy.
+ */
 public interface IgniteCacheProxy<K, V> extends IgniteCache<K, V>, 
Externalizable {
     /**
      * @return Context.
@@ -39,15 +44,22 @@ public interface IgniteCacheProxy<K, V> extends 
IgniteCache<K, V>, Externalizabl
     public IgniteCacheProxy<K, V> cacheNoGate();
 
     /**
-     * Creates projection that will operate with binary objects. <p> 
Projection returned by this method will force
-     * cache not to deserialize binary objects, so keys and values will be 
returned from cache API methods without
-     * changes. Therefore, signature of the projection can contain only 
following types: <ul> <li>{@code BinaryObject}
-     * for binary classes</li> <li>All primitives (byte, int, ...) and there 
boxed versions (Byte, Integer, ...)</li>
-     * <li>Arrays of primitives (byte[], int[], ...)</li> <li>{@link String} 
and array of {@link String}s</li>
-     * <li>{@link UUID} and array of {@link UUID}s</li> <li>{@link Date} and 
array of {@link Date}s</li> <li>{@link
-     * java.sql.Timestamp} and array of {@link java.sql.Timestamp}s</li> 
<li>Enums and array of enums</li> <li> Maps,
-     * collections and array of objects (but objects inside them will still be 
converted if they are binary) </li>
-     * </ul> <p> For example, if you use {@link Integer} as a key and {@code 
Value} class as a value (which will be
+     * Creates projection that will operate with binary objects.
+     * <p> Projection returned by this method will force cache not to 
deserialize binary objects,
+     * so keys and values will be returned from cache API methods without 
changes.
+     * Therefore, signature of the projection can contain only following types:
+     * <ul>
+     *     <li>{@code BinaryObject} for binary classes</li>
+     *     <li>All primitives (byte, int, ...) and there boxed versions (Byte, 
Integer, ...)</li>
+     *     <li>Arrays of primitives (byte[], int[], ...)</li>
+     *     <li>{@link String} and array of {@link String}s</li>
+     *     <li>{@link UUID} and array of {@link UUID}s</li>
+     *     <li>{@link Date} and array of {@link Date}s</li>
+     *     <li>{@link java.sql.Timestamp} and array of {@link 
java.sql.Timestamp}s</li>
+     *     <li>Enums and array of enums</li>
+     *     <li> Maps, collections and array of objects (but objects inside 
them will still be converted if they are binary) </li>
+     * </ul>
+     * <p> For example, if you use {@link Integer} as a key and {@code Value} 
class as a value (which will be
      * stored in binary format), you should acquire following projection to 
avoid deserialization:
      * <pre>
      * IgniteInternalCache<Integer, GridBinaryObject> prj = cache.keepBinary();
@@ -100,4 +112,13 @@ public interface IgniteCacheProxy<K, V> extends 
IgniteCache<K, V>, Externalizabl
      * @return Future that contains cache close operation.
      */
     public IgniteFuture<?> closeAsync();
+
+    /**
+     * Queries cache with multiple statements. Accepts {@link SqlFieldsQuery} 
class.
+     *
+     * @param qry SqlFieldsQuery.
+     * @return List of cursors.
+     * @see SqlFieldsQuery
+     */
+    public List<FieldsQueryCursor<List<?>>> 
queryMultipleStatements(SqlFieldsQuery qry);
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/75c27d5e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxyImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxyImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxyImpl.java
index 4c638a9..1cbd2b0 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxyImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxyImpl.java
@@ -171,8 +171,7 @@ public class IgniteCacheProxyImpl<K, V> extends 
AsyncSupportAdapter<IgniteCache<
     /**
      * @return Context.
      */
-    @Override
-    public GridCacheContext<K, V> context() {
+    @Override public GridCacheContext<K, V> context() {
         return ctx;
     }
 
@@ -279,8 +278,8 @@ public class IgniteCacheProxyImpl<K, V> extends 
AsyncSupportAdapter<IgniteCache<
         try {
             if (ctx.cache().isLocal())
                 return 
(IgniteFuture<Void>)createFuture(ctx.cache().localLoadCacheAsync(p, args));
-            else
-                return 
(IgniteFuture<Void>)createFuture(ctx.cache().globalLoadCacheAsync(p, args));
+
+            return 
(IgniteFuture<Void>)createFuture(ctx.cache().globalLoadCacheAsync(p, args));
         }
         catch (IgniteCheckedException | IgniteException e) {
             throw cacheException(e);
@@ -356,15 +355,13 @@ public class IgniteCacheProxyImpl<K, V> extends 
AsyncSupportAdapter<IgniteCache<
         @Nullable ClusterGroup grp)
         throws IgniteCheckedException {
 
-        final CacheQuery<R> qry;
-
         CacheOperationContext opCtxCall = ctx.operationContextPerCall();
 
         boolean isKeepBinary = opCtxCall != null && opCtxCall.isKeepBinary();
 
         IgniteBiPredicate<K, V> p = scanQry.getFilter();
 
-        qry = ctx.queries().createScanQuery(p, transformer, 
scanQry.getPartition(), isKeepBinary);
+        final CacheQuery<R> qry = ctx.queries().createScanQuery(p, 
transformer, scanQry.getPartition(), isKeepBinary);
 
         if (scanQry.getPageSize() > 0)
             qry.pageSize(scanQry.getPageSize());
@@ -561,6 +558,30 @@ public class IgniteCacheProxyImpl<K, V> extends 
AsyncSupportAdapter<IgniteCache<
     }
 
     /** {@inheritDoc} */
+    @Override public List<FieldsQueryCursor<List<?>>> 
queryMultipleStatements(SqlFieldsQuery qry) {
+        A.notNull(qry, "qry");
+        try {
+            ctx.checkSecurity(SecurityPermission.CACHE_READ);
+
+            validate(qry);
+
+            convertToBinary(qry);
+
+            CacheOperationContext opCtxCall = ctx.operationContextPerCall();
+
+            boolean keepBinary = opCtxCall != null && opCtxCall.isKeepBinary();
+
+            return ctx.kernalContext().query().querySqlFields(ctx, qry, 
keepBinary, false);
+        }
+        catch (Exception e) {
+            if (e instanceof CacheException)
+                throw (CacheException)e;
+
+            throw new CacheException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
     @Override public <R> QueryCursor<R> query(Query<R> qry) {
         A.notNull(qry, "qry");
@@ -1582,15 +1603,22 @@ public class IgniteCacheProxyImpl<K, V> extends 
AsyncSupportAdapter<IgniteCache<
     }
 
     /**
-     * Creates projection that will operate with binary objects. <p> 
Projection returned by this method will force
-     * cache not to deserialize binary objects, so keys and values will be 
returned from cache API methods without
-     * changes. Therefore, signature of the projection can contain only 
following types: <ul> <li>{@code BinaryObject}
-     * for binary classes</li> <li>All primitives (byte, int, ...) and there 
boxed versions (Byte, Integer, ...)</li>
-     * <li>Arrays of primitives (byte[], int[], ...)</li> <li>{@link String} 
and array of {@link String}s</li>
-     * <li>{@link UUID} and array of {@link UUID}s</li> <li>{@link Date} and 
array of {@link Date}s</li> <li>{@link
-     * java.sql.Timestamp} and array of {@link java.sql.Timestamp}s</li> 
<li>Enums and array of enums</li> <li> Maps,
-     * collections and array of objects (but objects inside them will still be 
converted if they are binary) </li>
-     * </ul> <p> For example, if you use {@link Integer} as a key and {@code 
Value} class as a value (which will be
+     * Creates projection that will operate with binary objects.
+     * <p> Projection returned by this method will force cache not to 
deserialize binary objects,
+     * so keys and values will be returned from cache API methods without 
changes.
+     * Therefore, signature of the projection can contain only following types:
+     * <ul>
+     *     <li>{@code BinaryObject} for binary classes</li>
+     *     <li>All primitives (byte, int, ...) and there boxed versions (Byte, 
Integer, ...)</li>
+     *     <li>Arrays of primitives (byte[], int[], ...)</li>
+     *     <li>{@link String} and array of {@link String}s</li>
+     *     <li>{@link UUID} and array of {@link UUID}s</li>
+     *     <li>{@link Date} and array of {@link Date}s</li>
+     *     <li>{@link java.sql.Timestamp} and array of {@link 
java.sql.Timestamp}s</li>
+     *     <li>Enums and array of enums</li>
+     *     <li> Maps, collections and array of objects (but objects inside 
them will still be converted if they are binary) </li>
+     * </ul>
+     * <p> For example, if you use {@link Integer} as a key and {@code Value} 
class as a value (which will be
      * stored in binary format), you should acquire following projection to 
avoid deserialization:
      * <pre>
      * IgniteInternalCache<Integer, GridBinaryObject> prj = cache.keepBinary();
@@ -1604,9 +1632,8 @@ public class IgniteCacheProxyImpl<K, V> extends 
AsyncSupportAdapter<IgniteCache<
      *
      * @return Projection for binary objects.
      */
-    @Override
     @SuppressWarnings("unchecked")
-    public <K1, V1> IgniteCache<K1, V1> keepBinary() {
+    @Override public <K1, V1> IgniteCache<K1, V1> keepBinary() {
         throw new UnsupportedOperationException();
     }
 
@@ -1614,17 +1641,15 @@ public class IgniteCacheProxyImpl<K, V> extends 
AsyncSupportAdapter<IgniteCache<
      * @param dataCenterId Data center ID.
      * @return Projection for data center id.
      */
-    @Override
     @SuppressWarnings("unchecked")
-    public IgniteCache<K, V> withDataCenterId(byte dataCenterId) {
+    @Override public IgniteCache<K, V> withDataCenterId(byte dataCenterId) {
         throw new UnsupportedOperationException();
     }
 
     /**
      * @return Cache with skip store enabled.
      */
-    @Override
-    public IgniteCache<K, V> skipStore() {
+    @Override public IgniteCache<K, V> skipStore() {
         throw new UnsupportedOperationException();
     }
 
@@ -1671,8 +1696,7 @@ public class IgniteCacheProxyImpl<K, V> extends 
AsyncSupportAdapter<IgniteCache<
     /**
      * @return Internal proxy.
      */
-    @Override
-    public GridCacheProxyImpl<K, V> internalProxy() {
+    @Override public GridCacheProxyImpl<K, V> internalProxy() {
         return new GridCacheProxyImpl<>(ctx, delegate, 
ctx.operationContextPerCall());
     }
 
@@ -1757,17 +1781,17 @@ public class IgniteCacheProxyImpl<K, V> extends 
AsyncSupportAdapter<IgniteCache<
     public void restart() {
         GridFutureAdapter<Void> restartFut = new GridFutureAdapter<>();
 
-        final GridFutureAdapter<Void> currentFut = this.restartFut.get();
+        final GridFutureAdapter<Void> curFut = this.restartFut.get();
 
-        boolean changed = this.restartFut.compareAndSet(currentFut, 
restartFut);
+        boolean changed = this.restartFut.compareAndSet(curFut, restartFut);
 
-        if (changed && currentFut != null)
+        if (changed && curFut != null)
             restartFut.listen(new 
IgniteInClosure<IgniteInternalFuture<Void>>() {
-                @Override public void apply(IgniteInternalFuture<Void> future) 
{
-                    if (future.error() != null)
-                        currentFut.onDone(future.error());
+                @Override public void apply(IgniteInternalFuture<Void> fut) {
+                    if (fut.error() != null)
+                        curFut.onDone(fut.error());
                     else
-                        currentFut.onDone();
+                        curFut.onDone();
                 }
             });
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/75c27d5e/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index 1fd14f8..3bbe8f1 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -1977,6 +1977,22 @@ public class GridQueryProcessor extends 
GridProcessorAdapter {
     @SuppressWarnings("unchecked")
     public FieldsQueryCursor<List<?>> querySqlFields(final 
GridCacheContext<?,?> cctx, final SqlFieldsQuery qry,
         final boolean keepBinary) {
+        return querySqlFields(cctx, qry, keepBinary, true).get(0);
+    }
+
+    /**
+     * Query SQL fields.
+     *
+     * @param cctx Cache context.
+     * @param qry Query.
+     * @param keepBinary Keep binary flag.
+     * @param failOnMultipleStmts If {@code true} the method must throws 
exception when query contains
+     *      more then one SQL statement.
+     * @return Cursor.
+     */
+    @SuppressWarnings("unchecked")
+    public List<FieldsQueryCursor<List<?>>> querySqlFields(final 
GridCacheContext<?,?> cctx, final SqlFieldsQuery qry,
+        final boolean keepBinary, final boolean failOnMultipleStmts) {
         checkxEnabled();
 
         validateSqlFieldsQuery(qry);
@@ -1994,37 +2010,39 @@ public class GridQueryProcessor extends 
GridProcessorAdapter {
             final String schemaName = qry.getSchema() != null ? 
qry.getSchema() : idx.schema(cctx.name());
             final int mainCacheId = cctx.cacheId();
 
-            IgniteOutClosureX<FieldsQueryCursor<List<?>>> clo;
+            IgniteOutClosureX<List<FieldsQueryCursor<List<?>>>> clo;
 
             if (loc) {
-                clo = new IgniteOutClosureX<FieldsQueryCursor<List<?>>>() {
-                    @Override public FieldsQueryCursor<List<?>> applyx() 
throws IgniteCheckedException {
+                clo = new 
IgniteOutClosureX<List<FieldsQueryCursor<List<?>>>>() {
+                    @Override public List<FieldsQueryCursor<List<?>>> applyx() 
throws IgniteCheckedException {
                         GridQueryCancel cancel = new GridQueryCancel();
 
-                        FieldsQueryCursor<List<?>> cur;
+                        List<FieldsQueryCursor<List<?>>> cursors;
 
                         if (cctx.config().getQueryParallelism() > 1) {
                             qry.setDistributedJoins(true);
 
-                            cur = idx.queryDistributedSqlFields(schemaName, 
qry,
-                                keepBinary, cancel, mainCacheId, true).get(0);
+                            cursors = 
idx.queryDistributedSqlFields(schemaName, qry,
+                                keepBinary, cancel, mainCacheId, true);
                         }
                         else {
                             IndexingQueryFilter filter = 
idx.backupFilter(requestTopVer.get(), qry.getPartitions());
 
-                            cur = idx.queryLocalSqlFields(schemaName, qry, 
keepBinary, filter, cancel);
+                            cursors = new ArrayList<>(1);
+
+                            cursors.add(idx.queryLocalSqlFields(schemaName, 
qry, keepBinary, filter, cancel));
                         }
 
                         sendQueryExecutedEvent(qry.getSql(), qry.getArgs(), 
cctx.name());
 
-                        return cur;
+                        return cursors;
                     }
                 };
             }
             else {
-                clo = new IgniteOutClosureX<FieldsQueryCursor<List<?>>>() {
-                    @Override public FieldsQueryCursor<List<?>> applyx() 
throws IgniteCheckedException {
-                        return idx.queryDistributedSqlFields(schemaName, qry, 
keepBinary, null, mainCacheId, true).get(0);
+                clo = new 
IgniteOutClosureX<List<FieldsQueryCursor<List<?>>>>() {
+                    @Override public List<FieldsQueryCursor<List<?>>> applyx() 
throws IgniteCheckedException {
+                        return idx.queryDistributedSqlFields(schemaName, qry, 
keepBinary, null, mainCacheId, failOnMultipleStmts);
                     }
                 };
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/75c27d5e/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryTask.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryTask.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryTask.java
index 51bf7d6..1daa1f2 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryTask.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryTask.java
@@ -25,6 +25,7 @@ import java.util.UUID;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.query.FieldsQueryCursor;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.internal.processors.cache.IgniteCacheProxy;
 import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
 import org.apache.ignite.internal.processors.task.GridInternal;
 import org.apache.ignite.internal.util.typedef.F;
@@ -84,22 +85,27 @@ public class VisorQueryTask extends 
VisorOneNodeTask<VisorQueryTaskArg, VisorEit
 
                 long start = U.currentTimeMillis();
 
-                FieldsQueryCursor<List<?>> qryCursor;
+                List<FieldsQueryCursor<List<?>>> qryCursors;
 
                 String cacheName = arg.getCacheName();
 
                 if (F.isEmpty(cacheName))
-                    qryCursor = 
ignite.context().query().querySqlFieldsNoCache(qry, true);
+                    qryCursors = 
ignite.context().query().querySqlFieldsNoCache(qry, true, false);
                 else {
                     IgniteCache<Object, Object> c = ignite.cache(cacheName);
 
                     if (c == null)
                         throw new SQLException("Fail to execute query. Cache 
not found: " + cacheName);
 
-                    qryCursor = c.withKeepBinary().query(qry);
+                    qryCursors = 
((IgniteCacheProxy)c.withKeepBinary()).queryMultipleStatements(qry);
                 }
 
-                VisorQueryCursor<List<?>> cur = new 
VisorQueryCursor<>(qryCursor);
+                // In case of multiple statements leave opened only last 
cursor.
+                for (int i = 0; i < qryCursors.size() - 1; i++)
+                    U.closeQuiet(qryCursors.get(i));
+
+                // In case of multiple statements return last cursor as result.
+                VisorQueryCursor<List<?>> cur = new 
VisorQueryCursor<>(F.last(qryCursors));
 
                 Collection<GridQueryFieldMetadata> meta = cur.fieldsMeta();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/75c27d5e/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 349ee92..9cf86d0 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -886,6 +886,9 @@ public class IgniteH2Indexing implements GridQueryIndexing {
 
         final PreparedStatement stmt = preparedStatementWithParams(conn, qry, 
params, true);
 
+        if (GridSqlQueryParser.checkMultipleStatements(stmt))
+            throw new IgniteSQLException("Multiple statements queries are not 
supported for local queries");
+
         Prepared p = GridSqlQueryParser.prepared(stmt);
 
         if (DmlStatementsProcessor.isDmlStatement(p)) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/75c27d5e/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
index 61d7510..52dee60 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
@@ -408,10 +408,13 @@ public class GridSqlQueryParser {
     /** */
     private static final Getter<Command, String> REMAINING;
 
+    /** */
+    public static final String ORG_H2_COMMAND_COMMAND_LIST = 
"org.h2.command.CommandList";
+
     static {
         try {
             CLS_COMMAND_LIST = (Class<? extends 
Command>)CommandContainer.class.getClassLoader()
-                .loadClass("org.h2.command.CommandList");
+                .loadClass(ORG_H2_COMMAND_COMMAND_LIST);
 
             LIST_COMMAND = getter(CLS_COMMAND_LIST, "command");
 
@@ -517,6 +520,16 @@ public class GridSqlQueryParser {
     }
 
     /**
+     * @param stmt Prepared statement to check.
+     * @return {@code true} in case of multiple statements.
+     */
+    public static boolean checkMultipleStatements(PreparedStatement stmt) {
+        Command cmd = COMMAND.get((JdbcPreparedStatement)stmt);
+
+        return ORG_H2_COMMAND_COMMAND_LIST.equals(cmd.getClass().getName());
+    }
+
+    /**
      * @param stmt Prepared statement.
      * @return Parsed select.
      */
@@ -540,7 +553,7 @@ public class GridSqlQueryParser {
         else {
             Class<?> cmdCls = cmd.getClass();
 
-            if (cmdCls.getName().equals("org.h2.command.CommandList")) {
+            if (cmdCls.getName().equals(ORG_H2_COMMAND_COMMAND_LIST)) {
                 return new 
PreparedWithRemaining(PREPARED.get(LIST_COMMAND.get(cmd)), REMAINING.get(cmd));
             }
             else
@@ -1495,7 +1508,7 @@ public class GridSqlQueryParser {
         try {
             return Integer.parseInt(val);
         }
-        catch (NumberFormatException e) {
+        catch (NumberFormatException ignored) {
             throw new IgniteSQLException("Parameter value must be an integer 
[name=" + name + ", value=" + val + ']',
                 IgniteQueryErrorCode.PARSING);
         }
@@ -2013,4 +2026,4 @@ public class GridSqlQueryParser {
             return remainingSql;
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/75c27d5e/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
index 6344cba..bbd3d0d 100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
@@ -24,21 +24,26 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Callable;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.cache.query.FieldsQueryCursor;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteKernal;
 import org.apache.ignite.internal.processors.query.GridQueryProcessor;
+import org.apache.ignite.internal.processors.query.IgniteSQLException;
 import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 
 import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
@@ -49,6 +54,15 @@ import static 
org.apache.ignite.cache.CacheRebalanceMode.SYNC;
  */
 public class GridCacheCrossCacheQuerySelfTest extends GridCommonAbstractTest {
     /** */
+    private static final String PART_CACHE_NAME = "partitioned";
+
+    /** */
+    private static final String REPL_PROD_CACHE_NAME = "replicated-prod";
+
+    /** */
+    private static final String REPL_STORE_CACHE_NAME = "replicated-store";
+
+    /** */
     private static final TcpDiscoveryIpFinder ipFinder = new 
TcpDiscoveryVmIpFinder(true);
 
     /** */
@@ -65,9 +79,9 @@ public class GridCacheCrossCacheQuerySelfTest extends 
GridCommonAbstractTest {
         c.setDiscoverySpi(disco);
 
         c.setCacheConfiguration(
-            createCache("partitioned", CacheMode.PARTITIONED, Integer.class, 
FactPurchase.class),
-            createCache("replicated-prod", CacheMode.REPLICATED, 
Integer.class, DimProduct.class),
-            createCache("replicated-store", CacheMode.REPLICATED, 
Integer.class, DimStore.class));
+            createCache(PART_CACHE_NAME, CacheMode.PARTITIONED, Integer.class, 
FactPurchase.class),
+            createCache(REPL_PROD_CACHE_NAME, CacheMode.REPLICATED, 
Integer.class, DimProduct.class),
+            createCache(REPL_STORE_CACHE_NAME, CacheMode.REPLICATED, 
Integer.class, DimStore.class));
 
         return c;
     }
@@ -115,8 +129,7 @@ public class GridCacheCrossCacheQuerySelfTest extends 
GridCommonAbstractTest {
      * @throws Exception If failed.
      */
     public void testTwoStepGroupAndAggregates() throws Exception {
-        IgniteInternalCache<Integer, FactPurchase> cache =
-            ((IgniteKernal)ignite).getCache("partitioned");
+        IgniteInternalCache<Integer, FactPurchase> cache = 
((IgniteKernal)ignite).getCache(PART_CACHE_NAME);
 
         GridQueryProcessor qryProc = ((IgniteKernal) ignite).context().query();
 
@@ -216,7 +229,7 @@ public class GridCacheCrossCacheQuerySelfTest extends 
GridCommonAbstractTest {
      * @throws Exception If failed.
      */
     public void testApiQueries() throws Exception {
-        IgniteCache<Object,Object> c = ignite.cache("partitioned");
+        IgniteCache<Object,Object> c = ignite.cache(PART_CACHE_NAME);
 
         c.query(new SqlFieldsQuery("select cast(? as varchar) from 
FactPurchase").setArgs("aaa")).getAll();
 
@@ -227,9 +240,46 @@ public class GridCacheCrossCacheQuerySelfTest extends 
GridCommonAbstractTest {
         assertEquals("aaa", res.get(0).get(0));
     }
 
-//    @Override protected long getTestTimeout() {
-//        return 10 * 60 * 1000;
-//    }
+    /**
+     * @throws Exception If failed.
+     */
+    public void testMultiStatement() throws Exception {
+        final IgniteInternalCache<Integer, FactPurchase> cache = 
((IgniteKernal)ignite).getCache(PART_CACHE_NAME);
+
+        final GridQueryProcessor qryProc = ((IgniteKernal) 
ignite).context().query();
+
+        final SqlFieldsQuery qry = new SqlFieldsQuery(
+            "insert into FactPurchase(_key, id, productId, storeId, price) 
values (555, 555, 555, 555, 555);" +
+            "select count(*) from FactPurchase"
+        );
+
+        GridTestUtils.assertThrows(log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    qryProc.querySqlFields(cache.context(), qry, false, true);
+
+                    return null;
+                }
+            }, IgniteSQLException.class, "Multiple statements queries are not 
supported");
+
+        List<FieldsQueryCursor<List<?>>> cursors = 
qryProc.querySqlFields(cache.context(), qry, false, false);
+
+        assertEquals(2, cursors.size());
+
+        for(FieldsQueryCursor<List<?>> cur : cursors)
+            U.closeQuiet(cur);
+
+        qry.setLocal(true);
+
+        GridTestUtils.assertThrows(log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    qryProc.querySqlFields(cache.context(), qry, false, false);
+
+                    return null;
+                }
+            }, IgniteSQLException.class, "Multiple statements queries are not 
supported for local queries");
+    }
 
     /**
      * @param l List.
@@ -246,8 +296,8 @@ public class GridCacheCrossCacheQuerySelfTest extends 
GridCommonAbstractTest {
     private void fillCaches() throws IgniteCheckedException {
         int idGen = 0;
 
-        GridCacheAdapter<Integer, DimProduct> dimCacheProd = 
((IgniteKernal)ignite).internalCache("replicated-prod");
-        GridCacheAdapter<Integer, DimStore> dimCacheStore = 
((IgniteKernal)ignite).internalCache("replicated-store");
+        GridCacheAdapter<Integer, DimProduct> dimCacheProd = 
((IgniteKernal)ignite).internalCache(REPL_PROD_CACHE_NAME);
+        GridCacheAdapter<Integer, DimStore> dimCacheStore = 
((IgniteKernal)ignite).internalCache(REPL_STORE_CACHE_NAME);
 
         List<DimStore> dimStores = new ArrayList<>();
 
@@ -273,17 +323,17 @@ public class GridCacheCrossCacheQuerySelfTest extends 
GridCommonAbstractTest {
             dimProds.add(v);
         }
 
-        GridCacheAdapter<Integer, FactPurchase> factCache = 
((IgniteKernal)ignite).internalCache("partitioned");
+        GridCacheAdapter<Integer, FactPurchase> factCache = 
((IgniteKernal)ignite).internalCache(PART_CACHE_NAME);
 
         Collections.sort(dimStores, new Comparator<DimStore>() {
             @Override public int compare(DimStore o1, DimStore o2) {
-                return o1.getId() > o2.getId() ? 1 : o1.getId() < o2.getId() ? 
-1 : 0;
+                return Integer.compare(o1.getId(), o2.getId());
             }
         });
 
         Collections.sort(dimProds, new Comparator<DimProduct>() {
             @Override public int compare(DimProduct o1, DimProduct o2) {
-                return o1.getId() > o2.getId() ? 1 : o1.getId() < o2.getId() ? 
-1 : 0;
+                return Integer.compare(o1.getId(), o2.getId());
             }
         });
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/75c27d5e/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
index f3deec9..fb38c46 100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
@@ -74,13 +74,13 @@ import org.h2.value.DataType;
  */
 public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     /** Client node index. */
-    private final static int CLIENT = 2;
+    private static final int CLIENT = 2;
 
     /** */
-    private final static String INDEXED_CACHE_NAME = CACHE_NAME + "_idx";
+    private static final String INDEXED_CACHE_NAME = CACHE_NAME + "_idx";
 
     /** */
-    private final static String INDEXED_CACHE_NAME_2 = INDEXED_CACHE_NAME + 
"_2";
+    private static final String INDEXED_CACHE_NAME_2 = INDEXED_CACHE_NAME + 
"_2";
 
     /** Data region name. */
     public static final String DATA_REGION_NAME = "my_data_region";

Reply via email to