You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/08/23 09:39:10 UTC

[01/12] ignite git commit: Merge remote-tracking branch 'remotes/community/ignite-1.7.2'

Repository: ignite
Updated Branches:
  refs/heads/ignite-3716-1 [created] d087c7827


Merge remote-tracking branch 'remotes/community/ignite-1.7.2'


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

Branch: refs/heads/ignite-3716-1
Commit: 37f22893e4aaf7f398928b95575a64b6280ab635
Parents: ae04efb 8bf0a48
Author: tledkov-gridgain <tl...@gridgain.com>
Authored: Wed Aug 10 12:21:13 2016 +0300
Committer: tledkov-gridgain <tl...@gridgain.com>
Committed: Wed Aug 10 12:21:13 2016 +0300

----------------------------------------------------------------------
 .../ignite/codegen/MessageCodeGenerator.java    |   6 +-
 .../java/org/apache/ignite/IgniteCompute.java   |  69 +-
 .../configuration/ConnectorConfiguration.java   |   1 +
 .../ignite/internal/GridJobExecuteRequest.java  | 148 +++-
 .../ignite/internal/GridJobExecuteResponse.java |  42 +-
 .../ignite/internal/IgniteComputeImpl.java      | 120 ++-
 .../ignite/internal/binary/BinaryContext.java   |   2 +
 .../failover/GridFailoverContextImpl.java       |  27 +-
 .../managers/failover/GridFailoverManager.java  |  17 +-
 .../affinity/GridAffinityProcessor.java         |  18 +
 .../processors/cache/GridCacheSwapManager.java  |  22 +-
 .../distributed/dht/GridDhtCacheAdapter.java    |  19 +-
 .../distributed/dht/GridDhtLocalPartition.java  |  33 +-
 .../cache/query/GridCacheQueryManager.java      |  10 +-
 .../processors/closure/AffinityTask.java        |  17 +-
 .../closure/GridClosureProcessor.java           | 142 +++-
 .../processors/igfs/IgfsFileAffinityRange.java  |  40 +-
 .../processors/igfs/IgfsMetaManager.java        |   9 +
 .../internal/processors/igfs/IgfsUtils.java     |  42 +-
 .../meta/IgfsClientMetaUnlockCallable.java      | 123 +++
 .../processors/job/GridJobProcessor.java        | 139 ++-
 .../internal/processors/job/GridJobWorker.java  | 203 +++--
 .../processors/query/GridQueryProcessor.java    |  22 +-
 .../processors/task/GridTaskWorker.java         | 235 +++--
 .../ignite/internal/util/IgniteUtils.java       |  10 +
 .../ignite/spi/failover/FailoverContext.java    |  15 +-
 .../spi/failover/always/AlwaysFailoverSpi.java  |  15 +-
 .../GridJobMasterLeaveAwareSelfTest.java        |   4 +-
 ...ectionLocalJobMultipleArgumentsSelfTest.java |   4 +-
 .../GridTaskFailoverAffinityRunTest.java        |   2 +-
 .../IgniteComputeEmptyClusterGroupTest.java     |   8 +-
 .../binary/GridBinaryAffinityKeySelfTest.java   |   6 +-
 ...acheAbstractUsersAffinityMapperSelfTest.java |   2 +-
 ...niteDynamicCacheStartStopConcurrentTest.java |   2 +-
 .../spi/failover/GridFailoverTestContext.java   |   6 +
 .../ignite/testframework/IgniteTestSuite.java   | 191 +++++
 .../apache/ignite/testsuites/IgniteIgnore.java  |  35 +
 .../testsuites/IgniteIgnoredTestSuite.java      |  63 ++
 ...eLockPartitionOnAffinityRunAbstractTest.java | 413 +++++++++
 ...PartitionOnAffinityRunAtomicCacheOpTest.java | 329 +++++++
 ...niteCacheLockPartitionOnAffinityRunTest.java | 852 +++++++++++++++++++
 ...LockPartitionOnAffinityRunTxCacheOpTest.java |  33 +
 ...titionOnAffinityRunWithCollisionSpiTest.java | 204 +++++
 .../IgniteCacheAffinityRunTestSuite.java        |  45 +
 .../apache/ignite/cache/spring/SpringCache.java |  44 +-
 .../ignite/cache/spring/SpringCacheManager.java |   7 +-
 .../spring/GridSpringCacheManagerSelfTest.java  | 438 ++++++++++
 .../cache/spring/GridSpringCacheTestKey.java    |  61 ++
 .../spring/GridSpringCacheTestKeyGenerator.java |  40 +
 .../spring/GridSpringCacheTestService.java      | 181 ++++
 .../GridSpringDynamicCacheTestService.java      |  85 ++
 .../SpringCacheManagerContextInjectionTest.java | 125 +++
 .../ignite/cache/spring/spring-caching.xml      |  57 ++
 .../spring/GridSpringCacheManagerSelfTest.java  | 342 --------
 .../ignite/spring/GridSpringCacheTestKey.java   |  61 --
 .../spring/GridSpringCacheTestKeyGenerator.java |  40 -
 .../spring/GridSpringCacheTestService.java      | 125 ---
 .../GridSpringDynamicCacheTestService.java      |  85 --
 .../SpringCacheManagerContextInjectionTest.java | 126 ---
 .../org/apache/ignite/spring/spring-caching.xml |  57 --
 .../testsuites/IgniteSpringTestSuite.java       |   4 +-
 61 files changed, 4480 insertions(+), 1143 deletions(-)
----------------------------------------------------------------------



[03/12] ignite git commit: Scalar function escape sequence support prototype implemented.

Posted by vo...@apache.org.
Scalar function escape sequence support prototype implemented.


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

Branch: refs/heads/ignite-3716-1
Commit: 98a21256b9aff373766521c18e662811433bfa76
Parents: f376cbb
Author: Andrey V. Mashenkov <an...@gmail.com>
Authored: Mon Aug 22 17:10:11 2016 +0300
Committer: Andrey V. Mashenkov <an...@gmail.com>
Committed: Mon Aug 22 17:10:11 2016 +0300

----------------------------------------------------------------------
 .../processors/odbc/escape/EscapeSQLParser.java | 108 +++++++++++++++++++
 .../OdbcScalarFunctionEscapeSequenceTest.java   |  49 +++++++++
 2 files changed, 157 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/98a21256/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java
new file mode 100644
index 0000000..4630e7d
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java
@@ -0,0 +1,108 @@
+package org.apache.ignite.internal.processors.odbc.escape;
+
+import org.apache.ignite.internal.util.typedef.T2;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Process ODBC escape sequences in sql query.
+ * See ODBC escape sequence syntax.
+ */
+public class EscapeSQLParser {
+
+    /**
+     * Process ODBC escape sequences in sql query.
+     * @param sql - sql query text
+     * @return - processed sql query text
+     */
+    public String parse(String sql) {
+        T2<Integer, String> value = parseInternal(sql, 0, false);
+
+        return value.get2();
+    }
+
+    /**
+     * Parse escape sequence using appropriate parser.
+     * Supports:
+     *  - Scalar function escape sequence. Example: "{fn func(arg1, arg2)}"
+     *
+     * @param sql - sql query text
+     * @param startPosition - parser start position
+     * @return pair of end of processed sequence position and parse result
+     */
+    T2<Integer, String> parseEscapeSqeuence(String sql, int startPosition) {
+        assert sql.charAt(startPosition) == '{';
+
+        int pos = sql.indexOf(' ', startPosition + 1);
+
+        if (pos == -1)
+            throw new IllegalStateException("Escape sequence parsing error at (" + startPosition + "): " + sql);
+
+        String esType = sql.substring(startPosition + 1, pos);
+
+        switch (esType) {
+            case "fn":
+                return parseInternal(sql, pos + 1, true);
+
+            default:
+                throw new IllegalStateException("Unsupported escape sequence found at  (" + startPosition + "): " + sql);
+        }
+    }
+
+    /**
+     * Process ODBC escape sequences in sql query.
+     * @param sql - sql query text
+     * @param startPosition - parser start position
+     * @param insideEscapeSequence - inside escape sequence flag
+     * @return pair of end of processed sequence position and parse result
+     */
+    @NotNull private T2<Integer, String> parseInternal(String sql, int startPosition, boolean insideEscapeSequence) {
+        StringBuffer sb = null;
+
+        int end = -1;
+        int offset = startPosition;
+
+        for (int i = startPosition; i < sql.length(); i++) {
+            // Current escape sequence ends up.
+            if (sql.charAt(i) == '}') {
+                end = i;
+
+                break;
+            }
+            // Inner escape sequence starts
+            else if (sql.charAt(i) == '{') {
+                T2<Integer, String> res = parseEscapeSqeuence(sql, i);
+
+                if (sb == null)
+                    sb = new StringBuffer();
+
+                sb.append(sql, offset, i);
+                sb.append(res.get2());
+
+                i = res.get1();
+
+                assert sql.charAt(i) == '}';
+
+                offset = res.get1() + 1;
+            }
+        }
+
+        if (insideEscapeSequence && end == -1)
+            // Closing bracket character '}' was not found in inner escape sequence
+            throw new IllegalStateException("Escape sequence started at position (" + startPosition + ") is not closed: " + sql);
+        else if (!insideEscapeSequence && end != -1)
+            // Closing bracket character '}' was found out of escape sequence
+            throw new IllegalStateException("Unexpected end of escaped sequence found at position (" + startPosition + ") is not closed: " + sql);
+
+        if (end == -1)
+            end = sql.length();
+
+        // Add tail to the result
+        if (sb == null)
+            return new T2<>(end, sql.substring(startPosition, end));
+        else if (offset < end)
+            sb.append(sql, offset, end);
+
+        return new T2<>(end, sb.toString());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/98a21256/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
new file mode 100644
index 0000000..7d60b42
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
@@ -0,0 +1,49 @@
+package org.apache.ignite.internal.processors.odbc;
+
+import junit.framework.TestCase;
+import org.apache.ignite.internal.processors.odbc.escape.EscapeSQLParser;
+
+public class OdbcScalarFunctionEscapeSequenceTest extends TestCase {
+
+    public void testTrivialFunction() throws Exception {
+        String sqlQry = "select {fn func(field1)} {fn func(field2)} from table;";
+        String expRes = "select func(field1) func(field2) from table;";
+
+        EscapeSQLParser parser = new EscapeSQLParser();
+
+        String actualRes = parser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+
+
+        sqlQry = "select {fn func(field1)} {fn func(field2)}";
+        expRes = "select func(field1) func(field2)";
+
+        parser = new EscapeSQLParser();
+
+        actualRes = parser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+    }
+
+    public void testNestedFunction() throws Exception {
+        String sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)} from SomeTable;";
+        String expRes = "select func1(field1, func2(field2), field3) from SomeTable;";
+
+        EscapeSQLParser parser = new EscapeSQLParser();
+
+        String actualResult = parser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualResult);
+
+
+        sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)}";
+        expRes = "select func1(field1, func2(field2), field3)";
+
+        parser = new EscapeSQLParser();
+
+        actualResult = parser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualResult);
+    }
+}


[02/12] ignite git commit: Merge branch 'master' of github.com:gridgain/apache-ignite

Posted by vo...@apache.org.
Merge branch 'master' of github.com:gridgain/apache-ignite


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

Branch: refs/heads/ignite-3716-1
Commit: f376cbbba26d75a623c6754aab7b79bad8a16fdb
Parents: 37f2289 354318a
Author: Andrey V. Mashenkov <an...@gmail.com>
Authored: Mon Aug 22 13:11:28 2016 +0300
Committer: Andrey V. Mashenkov <an...@gmail.com>
Committed: Mon Aug 22 13:11:28 2016 +0300

----------------------------------------------------------------------
 .../hibernate/HibernateL2CacheExample.java      |    2 +-
 .../internal/jdbc2/JdbcResultSetSelfTest.java   |    4 +-
 .../ignite/jdbc/JdbcResultSetSelfTest.java      |    4 +-
 .../org/apache/ignite/IgniteFileSystem.java     |   27 +-
 .../apache/ignite/IgniteSystemProperties.java   |   10 +
 .../affinity/fair/FairAffinityFunction.java     |    6 +-
 .../rendezvous/RendezvousAffinityFunction.java  |    4 +
 .../store/jdbc/CacheAbstractJdbcStore.java      |   43 +-
 .../store/jdbc/dialect/BasicJdbcDialect.java    |    7 +-
 .../cache/store/jdbc/dialect/JdbcDialect.java   |   11 +-
 .../cache/store/jdbc/dialect/MySQLDialect.java  |   18 +-
 .../igfs/secondary/IgfsSecondaryFileSystem.java |    2 +-
 .../local/LocalIgfsSecondaryFileSystem.java     |  396 +++++++
 .../igfs/secondary/local/package-info.java      |   22 +
 .../ignite/igfs/secondary/package-info.java     |    2 +-
 .../internal/GridEventConsumeHandler.java       |    5 +
 .../internal/GridMessageListenHandler.java      |    5 +
 .../internal/binary/BinaryClassDescriptor.java  |   43 +-
 .../ignite/internal/binary/BinaryContext.java   |   21 +-
 .../binary/BinaryMethodWriteReplacer.java       |   59 +
 .../ignite/internal/binary/BinaryTreeMap.java   |   96 ++
 .../binary/BinaryTreeMapWriteReplacer.java      |   34 +
 .../ignite/internal/binary/BinaryTreeSet.java   |   93 ++
 .../binary/BinaryTreeSetWriteReplacer.java      |   34 +
 .../ignite/internal/binary/BinaryUtils.java     |   37 +-
 .../internal/binary/BinaryWriteReplacer.java    |   33 +
 .../internal/binary/BinaryWriterExImpl.java     |   35 +-
 .../internal/cluster/IgniteClusterImpl.java     |    9 +-
 .../logger/platform/PlatformLogger.java         |  223 ++++
 .../discovery/GridDiscoveryManager.java         |    3 +-
 .../processors/cache/GridCacheContext.java      |    8 +
 .../processors/cache/GridCacheIoManager.java    |   24 +-
 .../processors/cache/GridCacheMessage.java      |    2 +-
 .../binary/CacheObjectBinaryProcessorImpl.java  |   19 +
 .../distributed/GridCacheTxRecoveryFuture.java  |    6 +-
 .../cache/distributed/dht/GridDhtGetFuture.java |    4 +-
 .../distributed/dht/GridDhtLockFuture.java      |    6 +-
 .../distributed/dht/GridDhtTxPrepareFuture.java |    6 +-
 .../dht/atomic/GridDhtAtomicCache.java          |  176 ++-
 .../colocated/GridDhtColocatedLockFuture.java   |    6 +-
 .../distributed/near/GridNearLockFuture.java    |    6 +-
 ...arOptimisticSerializableTxPrepareFuture.java |    6 +-
 .../near/GridNearOptimisticTxPrepareFuture.java |    6 +-
 .../GridNearPessimisticTxPrepareFuture.java     |    8 +-
 .../near/GridNearTransactionalCache.java        |    2 +-
 .../near/GridNearTxFinishFuture.java            |   34 +-
 .../cache/distributed/near/GridNearTxLocal.java |   14 +-
 .../continuous/CacheContinuousQueryEntry.java   |   16 +-
 .../continuous/CacheContinuousQueryHandler.java |   85 +-
 .../cache/transactions/IgniteTxHandler.java     |    1 -
 .../continuous/GridContinuousHandler.java       |    5 +
 .../continuous/GridContinuousProcessor.java     |   11 +-
 .../continuous/GridContinuousQueryBatch.java    |   47 +
 .../internal/processors/igfs/IgfsAsyncImpl.java |    5 +
 .../ignite/internal/processors/igfs/IgfsEx.java |    7 +
 .../internal/processors/igfs/IgfsFileImpl.java  |   20 +-
 .../internal/processors/igfs/IgfsImpl.java      |    8 +-
 .../processors/igfs/IgfsMetaManager.java        |    2 +-
 .../processors/igfs/IgfsOutputStreamImpl.java   |    7 +-
 .../internal/processors/igfs/IgfsUtils.java     |   53 +
 .../local/LocalFileSystemIgfsFile.java          |  134 +++
 ...fsSecondaryFileSystemPositionedReadable.java |   65 ++
 .../platform/PlatformAbstractBootstrap.java     |   18 +-
 .../platform/PlatformAbstractTarget.java        |   17 +-
 .../platform/PlatformConfigurationEx.java       |    6 +
 .../platform/PlatformNoopProcessor.java         |   10 +
 .../processors/platform/PlatformProcessor.java  |   16 +
 .../platform/PlatformProcessorImpl.java         |   56 +
 .../platform/cache/PlatformCache.java           |  335 +++---
 .../callback/PlatformCallbackGateway.java       |   45 +
 .../callback/PlatformCallbackUtils.java         |   20 +
 .../cpp/PlatformCppConfigurationEx.java         |    6 +
 .../dotnet/PlatformDotNetBootstrap.java         |    9 +
 .../dotnet/PlatformDotNetCacheStore.java        |   12 +-
 .../PlatformDotNetConfigurationClosure.java     |   11 +-
 .../dotnet/PlatformDotNetConfigurationEx.java   |   12 +-
 .../utils/PlatformConfigurationUtils.java       |   57 +-
 .../platform/utils/PlatformFutureUtils.java     |    6 +-
 .../platform/utils/PlatformUtils.java           |   25 +
 .../handlers/query/QueryCommandHandler.java     |   16 +-
 .../rest/request/RestQueryRequest.java          |    2 +-
 .../ignite/internal/util/GridJavaProcess.java   |    5 +-
 .../util/future/GridCompoundFuture.java         |   90 +-
 .../util/nio/GridTcpNioCommunicationClient.java |    5 +-
 .../visor/cache/VisorCacheTypeMetadata.java     |   20 +-
 .../internal/visor/util/VisorTaskUtils.java     |    8 +
 .../communication/tcp/TcpCommunicationSpi.java  |   49 +-
 .../ignite/spi/discovery/tcp/ClientImpl.java    |    8 +-
 .../AbstractAffinityFunctionSelfTest.java       |   18 +-
 .../IgniteLocalNodeMapBeforeStartTest.java      |   82 ++
 .../internal/binary/BinaryTreeSelfTest.java     |  341 ++++++
 .../CacheSerializableTransactionsTest.java      |    5 +
 .../CacheTxNotAllowReadFromBackupTest.java      |  297 +++++
 .../IgniteCacheConnectionRecoveryTest.java      |  205 ++++
 .../IgniteCacheMessageRecoveryAbstractTest.java |   14 +-
 ...gniteCacheMessageRecoveryIdleConnection.java |  154 ---
 ...eCacheMessageRecoveryIdleConnectionTest.java |  157 +++
 .../rebalancing/CacheNodeSafeAssertion.java     |  118 ++
 ...cheRebalancingPartitionDistributionTest.java |  149 +++
 .../CacheEntryProcessorNonSerializableTest.java |  410 +++++++
 ...niteCacheContinuousQueryBackupQueueTest.java |  184 ++-
 ...teCacheContinuousQueryNoUnsubscribeTest.java |  153 +++
 ...faultIgfsSecondaryFileSystemTestAdapter.java |  117 ++
 .../processors/igfs/IgfsAbstractSelfTest.java   | 1057 ++++++++++--------
 .../igfs/IgfsBackupFailoverSelfTest.java        |    2 +-
 .../igfs/IgfsDualAbstractSelfTest.java          |  252 +----
 .../igfs/IgfsExUniversalFileSystemAdapter.java  |  116 --
 ...SecondaryFileSystemDualAbstractSelfTest.java |   76 ++
 ...ondaryFileSystemDualAsyncClientSelfTest.java |   28 +
 ...calSecondaryFileSystemDualAsyncSelfTest.java |   32 +
 ...condaryFileSystemDualSyncClientSelfTest.java |   28 +
 ...ocalSecondaryFileSystemDualSyncSelfTest.java |   32 +
 ...IgfsLocalSecondaryFileSystemTestAdapter.java |  141 +++
 .../internal/processors/igfs/IgfsMock.java      |    5 +
 .../IgfsSecondaryFileSystemTestAdapter.java     |  118 ++
 .../igfs/UniversalFileSystemAdapter.java        |  109 --
 .../query/GridQueryCommandHandlerTest.java      |  191 ++++
 .../assertions/AlwaysAssertion.java             |   29 +
 .../testframework/assertions/Assertion.java     |   31 +
 .../testframework/assertions/package-info.java  |   22 +
 .../testframework/junits/GridAbstractTest.java  |   10 +-
 .../common/GridRollingRestartAbstractTest.java  |  324 ++++++
 .../junits/multijvm/IgniteProcessProxy.java     |   24 +-
 .../ignite/testsuites/IgniteBasicTestSuite.java |    3 +-
 .../IgniteBinaryObjectsTestSuite.java           |    2 +
 .../IgniteCacheFailoverTestSuite.java           |    2 +
 .../ignite/testsuites/IgniteCacheTestSuite.java |    8 +-
 .../testsuites/IgniteCacheTestSuite4.java       |    2 +
 .../ignite/testsuites/IgniteIgfsTestSuite.java  |    9 +
 .../testsuites/IgniteRestHandlerTestSuite.java  |    2 +
 modules/docker/1.7.0/Dockerfile                 |   44 +
 modules/docker/1.7.0/run.sh                     |   51 +
 modules/docker/Dockerfile                       |    2 +-
 .../fs/IgniteHadoopIgfsSecondaryFileSystem.java |    2 +-
 .../ignite/igfs/Hadoop1DualAbstractTest.java    |    3 +-
 ...oopFileSystemUniversalFileSystemAdapter.java |  139 ---
 .../igfs/HadoopIgfsDualAbstractSelfTest.java    |    2 +-
 ...adoopIgfsSecondaryFileSystemTestAdapter.java |  149 +++
 .../query/h2/GridH2ResultSetIterator.java       |   62 +-
 .../processors/query/h2/IgniteH2Indexing.java   |    4 +-
 .../processors/query/h2/opt/GridH2Row.java      |    2 +-
 .../query/h2/opt/GridH2ValueCacheObject.java    |   11 +-
 .../query/h2/twostep/GridMapQueryExecutor.java  |   34 +-
 .../h2/twostep/GridReduceQueryExecutor.java     |    3 +-
 .../cache/CacheSqlQueryValueCopySelfTest.java   |  226 ++++
 .../ClientReconnectAfterClusterRestartTest.java |  225 ++++
 .../IgniteCacheAbstractFieldsQuerySelfTest.java |    2 +-
 ...eLockPartitionOnAffinityRunAbstractTest.java |   17 +
 .../IgniteCacheLocalFieldsQuerySelfTest.java    |   16 +
 .../h2/GridIndexingSpiAbstractSelfTest.java     |    2 +-
 .../IgniteCacheQuerySelfTestSuite2.java         |    2 +
 .../IgniteCacheQuerySelfTestSuite3.java         |    2 +
 .../IgniteCacheWithIndexingTestSuite.java       |    5 +-
 .../include/ignite/impl/binary/binary_utils.h   |   87 ++
 .../src/impl/binary/binary_reader_impl.cpp      |   30 +-
 .../ignite/impl/interop/interop_target.h        |   15 +-
 .../cpp/core/include/ignite/impl/operations.h   |   47 +-
 .../cpp/core/src/impl/cache/cache_impl.cpp      |   14 +-
 .../core/src/impl/interop/interop_target.cpp    |   41 +-
 .../src/impl/transactions/transactions_impl.cpp |    5 +
 .../cpp/jni/include/ignite/jni/exports.h        |    2 +
 .../platforms/cpp/jni/include/ignite/jni/java.h |   13 +
 modules/platforms/cpp/jni/project/vs/module.def |    3 +-
 modules/platforms/cpp/jni/src/exports.cpp       |   12 +-
 modules/platforms/cpp/jni/src/java.cpp          |   72 +-
 .../Apache.Ignite.Benchmarks/BenchmarkRunner.cs |    5 +-
 .../Interop/PlatformBenchmarkBase.cs            |    2 +-
 .../Apache.Ignite.Core.Tests.NuGet.csproj       |    9 +-
 .../packages.config                             |    1 +
 .../Apache.Ignite.Core.Tests.csproj             |   31 +-
 .../Binary/BinaryBuilderSelfTest.cs             |   24 +-
 .../Binary/BinaryReaderWriterTest.cs            |  171 +++
 .../Binary/BinaryStringTest.cs                  |   26 +-
 .../Binary/IO/BinaryStreamsTest.cs              |  151 +++
 .../Binary/JavaTypeMappingTest.cs               |  158 +++
 .../Binary/TypeResolverTest.cs                  |  107 ++
 .../Cache/Affinity/AffinityKeyTest.cs           |   66 ++
 .../Affinity/AffinityTopologyVersionTest.cs     |   59 +
 .../Cache/CacheAbstractTest.cs                  |   64 +-
 .../Cache/CacheResultTest.cs                    |   75 ++
 .../Query/CacheQueriesCodeConfigurationTest.cs  |   12 +
 .../Cache/Query/CacheQueriesTest.cs             |   45 +-
 .../Continuous/ContinuousQueryAbstractTest.cs   |   42 +-
 .../Cache/Store/CacheParallelLoadStoreTest.cs   |    2 +-
 .../Cache/Store/CacheStoreAdapterTest.cs        |   90 ++
 .../Cache/Store/CacheStoreTest.cs               |   39 +-
 .../Cache/Store/CacheTestParallelLoadStore.cs   |    9 +
 .../Cache/Store/CacheTestStore.cs               |   50 +-
 .../Collections/MultiValueDictionaryTest.cs     |   58 +
 .../Collections/ReadOnlyCollectionTest.cs       |   59 +
 .../Collections/ReadOnlyDictionaryTest.cs       |   70 ++
 .../Common/IgniteGuidTest.cs                    |   62 +
 .../Compute/AbstractTaskTest.cs                 |   40 +-
 .../Compute/BinarizableClosureTaskTest.cs       |   18 +-
 .../Compute/BinarizableTaskTest.cs              |   18 +-
 .../Compute/CancellationTest.cs                 |   10 +
 .../Compute/ClosureTaskTest.cs                  |  192 +---
 .../Compute/ComputeApiTest.cs                   |   92 +-
 .../Compute/FailoverTaskSelfTest.cs             |    5 +-
 .../Compute/IgniteExceptionTaskSelfTest.cs      |   43 +-
 .../Compute/ResourceTaskTest.cs                 |   51 +
 .../Compute/SerializableClosureTaskTest.cs      |    5 +
 .../Compute/TaskAdapterTest.cs                  |    5 +-
 .../Compute/TaskResultTest.cs                   |   14 +-
 .../Config/Compute/compute-standalone.xml       |    1 +
 .../Config/Log/custom-log.xml                   |   50 +
 .../Config/Log/dotnet-log4j.xml                 |  143 +++
 .../Config/cache-query.xml                      |   38 +-
 .../Apache.Ignite.Core.Tests/EventsTest.cs      |  192 +++-
 .../Examples/ExamplesTest.cs                    |    2 +-
 .../Apache.Ignite.Core.Tests/ExceptionsTest.cs  |   46 +
 .../IgniteConfigurationSerializerTest.cs        |   24 +
 .../Log/CustomLoggerTest.cs                     |  449 ++++++++
 .../Log/DefaultLoggerTest.cs                    |  114 ++
 .../Apache.Ignite.Core.Tests/TestUtils.cs       |   36 +-
 .../TypeResolverTest.cs                         |  107 --
 .../Apache.Ignite.Core.Tests/packages.config    |    4 +
 .../Apache.Ignite.Core.csproj                   |    9 +-
 .../Cache/Affinity/AffinityKey.cs               |   11 +
 .../Cache/CachePartialUpdateException.cs        |    6 +-
 .../Cache/Configuration/CacheConfiguration.cs   |   19 +-
 .../Cache/Configuration/QueryEntity.cs          |   25 +-
 .../Cache/Configuration/QueryField.cs           |   19 +-
 .../Store/CacheParallelLoadStoreAdapter.cs      |    7 +
 .../Apache.Ignite.Core/Common/JavaException.cs  |    1 +
 .../dotnet/Apache.Ignite.Core/IIgnite.cs        |    8 +
 .../Apache.Ignite.Core/IgniteConfiguration.cs   |   25 +
 .../IgniteConfigurationSection.xsd              |   12 +
 .../dotnet/Apache.Ignite.Core/Ignition.cs       |   39 +-
 .../Impl/Binary/BinaryObject.cs                 |    2 +
 .../Impl/Binary/BinaryObjectBuilder.cs          |    2 +-
 .../Impl/Binary/BinaryObjectHandle.cs           |   59 -
 .../Impl/Binary/BinaryObjectHeader.cs           |    5 +-
 .../Binary/BinarySurrogateTypeDescriptor.cs     |    2 +-
 .../Impl/Binary/BinaryWriter.cs                 |   20 -
 .../Impl/Binary/Io/BinaryStreamAdapter.cs       |    5 +
 .../Impl/Binary/Io/BinaryStreamBase.cs          |   11 +-
 .../Impl/Binary/Io/IBinaryStream.cs             |    2 +-
 .../Apache.Ignite.Core/Impl/Binary/JavaTypes.cs |   75 +-
 .../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs  |  239 ++--
 .../Cache/Event/JavaCacheEntryEventFilter.cs    |    2 +
 .../Impl/Collections/MultiValueDictionary.cs    |   26 -
 .../Impl/Collections/ReadOnlyDictionary.cs      |    2 +-
 .../Apache.Ignite.Core/Impl/Common/Classpath.cs |   12 +-
 .../Impl/Common/IgniteHome.cs                   |   30 +-
 .../Apache.Ignite.Core/Impl/Common/Logger.cs    |   37 -
 .../Impl/Common/ResizeableArray.cs              |   64 --
 .../Impl/Events/EventTypeConverter.cs           |    3 +
 .../Apache.Ignite.Core/Impl/Events/Events.cs    |    3 +
 .../Apache.Ignite.Core/Impl/ExceptionUtils.cs   |   11 +-
 .../Apache.Ignite.Core/Impl/Handle/Handle.cs    |   12 +-
 .../Impl/Handle/HandleRegistry.cs               |   19 +-
 .../Apache.Ignite.Core/Impl/Handle/IHandle.cs   |    5 -
 .../dotnet/Apache.Ignite.Core/Impl/Ignite.cs    |    9 +
 .../Apache.Ignite.Core/Impl/IgniteManager.cs    |    6 +-
 .../Apache.Ignite.Core/Impl/IgniteProxy.cs      |    8 +
 .../Apache.Ignite.Core/Impl/IgniteUtils.cs      |   48 +-
 .../Impl/InteropExceptionHolder.cs              |   88 --
 .../Apache.Ignite.Core/Impl/Log/JavaLogger.cs   |  110 ++
 .../Impl/Memory/PlatformMemoryUtils.cs          |   30 -
 .../Impl/Memory/PlatformRawMemory.cs            |    5 +
 .../Apache.Ignite.Core/Impl/PlatformTarget.cs   |   88 +-
 .../Impl/Unmanaged/IgniteJniNativeMethods.cs    |    7 +
 .../Impl/Unmanaged/UnmanagedCallbackHandlers.cs |    3 +
 .../Impl/Unmanaged/UnmanagedCallbacks.cs        |  108 +-
 .../Impl/Unmanaged/UnmanagedUtils.cs            |   27 +-
 .../Apache.Ignite.Core/Log/CategoryLogger.cs    |   82 ++
 .../dotnet/Apache.Ignite.Core/Log/ILogger.cs    |   51 +
 .../dotnet/Apache.Ignite.Core/Log/LogLevel.cs   |   53 +
 .../Apache.Ignite.Core/Log/LoggerExtensions.cs  |  320 ++++++
 .../Datagrid/LinqExample.cs                     |  209 +++-
 .../Datagrid/QueryExample.cs                    |  189 +++-
 .../Apache.Ignite.ExamplesDll.csproj            |    1 -
 .../Binary/Employee.cs                          |   10 +-
 .../Binary/EmployeeKey.cs                       |   88 --
 .../parser/dialect/DatabaseMetadataDialect.java |   18 +
 .../parser/dialect/JdbcMetadataDialect.java     |    5 +-
 .../parser/dialect/OracleMetadataDialect.java   |    5 +-
 .../ignite/schema/generator/CodeGenerator.java  |    7 +-
 .../schema/parser/DatabaseMetadataParser.java   |    4 +-
 .../ignite/schema/ui/SchemaImportApp.java       |    3 +-
 .../schema/test/AbstractSchemaImportTest.java   |   27 +-
 .../test/generator/CodeGeneratorTest.java       |   28 +-
 .../schema/test/generator/XmlGeneratorTest.java |   22 +-
 .../ignite/schema/test/model/CacheConfig.txt    |  409 +++++++
 .../schema/test/model/ignite-type-metadata.xml  |   50 +-
 .../test/parser/DbMetadataParserTest.java       |    6 +-
 .../jdbc/CacheJdbcPojoStoreFactorySelfTest.java |   11 +-
 288 files changed, 12409 insertions(+), 3097 deletions(-)
----------------------------------------------------------------------



[05/12] ignite git commit: Scalar function escape sequence support prototype implemented. Quotation support added.

Posted by vo...@apache.org.
Scalar function escape sequence support prototype implemented.
Quotation support added.


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

Branch: refs/heads/ignite-3716-1
Commit: 06df24921b3e36ef14813688e52e93baba77b4f1
Parents: 98a2125
Author: Andrey V. Mashenkov <an...@gmail.com>
Authored: Mon Aug 22 18:12:31 2016 +0300
Committer: Andrey V. Mashenkov <an...@gmail.com>
Committed: Mon Aug 22 18:18:51 2016 +0300

----------------------------------------------------------------------
 .../processors/odbc/escape/EscapeSQLParser.java | 108 ----------------
 .../odbc/escape/OdbcEscapeSequenceParser.java   | 126 +++++++++++++++++++
 .../OdbcScalarFunctionEscapeSequenceTest.java   |  80 ++++++++++--
 3 files changed, 197 insertions(+), 117 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/06df2492/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java
deleted file mode 100644
index 4630e7d..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.apache.ignite.internal.processors.odbc.escape;
-
-import org.apache.ignite.internal.util.typedef.T2;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Process ODBC escape sequences in sql query.
- * See ODBC escape sequence syntax.
- */
-public class EscapeSQLParser {
-
-    /**
-     * Process ODBC escape sequences in sql query.
-     * @param sql - sql query text
-     * @return - processed sql query text
-     */
-    public String parse(String sql) {
-        T2<Integer, String> value = parseInternal(sql, 0, false);
-
-        return value.get2();
-    }
-
-    /**
-     * Parse escape sequence using appropriate parser.
-     * Supports:
-     *  - Scalar function escape sequence. Example: "{fn func(arg1, arg2)}"
-     *
-     * @param sql - sql query text
-     * @param startPosition - parser start position
-     * @return pair of end of processed sequence position and parse result
-     */
-    T2<Integer, String> parseEscapeSqeuence(String sql, int startPosition) {
-        assert sql.charAt(startPosition) == '{';
-
-        int pos = sql.indexOf(' ', startPosition + 1);
-
-        if (pos == -1)
-            throw new IllegalStateException("Escape sequence parsing error at (" + startPosition + "): " + sql);
-
-        String esType = sql.substring(startPosition + 1, pos);
-
-        switch (esType) {
-            case "fn":
-                return parseInternal(sql, pos + 1, true);
-
-            default:
-                throw new IllegalStateException("Unsupported escape sequence found at  (" + startPosition + "): " + sql);
-        }
-    }
-
-    /**
-     * Process ODBC escape sequences in sql query.
-     * @param sql - sql query text
-     * @param startPosition - parser start position
-     * @param insideEscapeSequence - inside escape sequence flag
-     * @return pair of end of processed sequence position and parse result
-     */
-    @NotNull private T2<Integer, String> parseInternal(String sql, int startPosition, boolean insideEscapeSequence) {
-        StringBuffer sb = null;
-
-        int end = -1;
-        int offset = startPosition;
-
-        for (int i = startPosition; i < sql.length(); i++) {
-            // Current escape sequence ends up.
-            if (sql.charAt(i) == '}') {
-                end = i;
-
-                break;
-            }
-            // Inner escape sequence starts
-            else if (sql.charAt(i) == '{') {
-                T2<Integer, String> res = parseEscapeSqeuence(sql, i);
-
-                if (sb == null)
-                    sb = new StringBuffer();
-
-                sb.append(sql, offset, i);
-                sb.append(res.get2());
-
-                i = res.get1();
-
-                assert sql.charAt(i) == '}';
-
-                offset = res.get1() + 1;
-            }
-        }
-
-        if (insideEscapeSequence && end == -1)
-            // Closing bracket character '}' was not found in inner escape sequence
-            throw new IllegalStateException("Escape sequence started at position (" + startPosition + ") is not closed: " + sql);
-        else if (!insideEscapeSequence && end != -1)
-            // Closing bracket character '}' was found out of escape sequence
-            throw new IllegalStateException("Unexpected end of escaped sequence found at position (" + startPosition + ") is not closed: " + sql);
-
-        if (end == -1)
-            end = sql.length();
-
-        // Add tail to the result
-        if (sb == null)
-            return new T2<>(end, sql.substring(startPosition, end));
-        else if (offset < end)
-            sb.append(sql, offset, end);
-
-        return new T2<>(end, sb.toString());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/06df2492/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java
new file mode 100644
index 0000000..cfaa7c0
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java
@@ -0,0 +1,126 @@
+package org.apache.ignite.internal.processors.odbc.escape;
+
+import org.apache.ignite.internal.util.typedef.T2;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Process ODBC escape sequences in sql query.
+ * See ODBC escape sequence syntax.
+ */
+public class OdbcEscapeSequenceParser {
+
+    /**
+     * Process ODBC escape sequences in sql query.
+     *
+     * @param sql - sql query text
+     * @return - processed sql query text
+     */
+    public String parse(String sql) {
+        T2<Integer, String> val = parseInternal(sql, 0, false);
+
+        return val.get2();
+    }
+
+    /**
+     * Parse escape sequence using appropriate parser.
+     * Supports:
+     * - Scalar function escape sequence. Example: "{fn func(arg1, arg2)}"
+     *
+     * @param sql - sql query text
+     * @param startPosition - parser start position
+     * @return pair of end of processed sequence position and parse result
+     */
+    private T2<Integer, String> parseEscapeSqeuence(String sql, int startPosition) {
+        assert sql.charAt(startPosition) == '{';
+
+        int pos = sql.indexOf(' ', startPosition + 1);
+
+        if (pos == -1)
+            throw new IllegalStateException("Escape sequence parsing error at (" + startPosition + "): " + sql);
+
+        String esType = sql.substring(startPosition + 1, pos);
+
+        switch (esType) {
+            case "fn":
+                return parseInternal(sql, pos + 1, true);
+
+            default:
+                throw new IllegalStateException("Unsupported escape sequence found at  (" + startPosition + "): " + sql);
+        }
+    }
+
+    /**
+     * Process ODBC escape sequences in sql query.
+     *
+     * @param sql - sql query text
+     * @param startPosition - parser start position
+     * @param insideEscapeSeq - inside escape sequence flag
+     * @return pair of end of processed sequence position and parse result
+     */
+    @NotNull private T2<Integer, String> parseInternal(String sql, int startPosition, boolean insideEscapeSeq) {
+        StringBuffer sb = null;
+
+        int off = startPosition;
+        int seqEndPos = -1;
+
+        char quoted = 0;
+
+        for (int i = startPosition; i < sql.length(); i++) {
+            char ch = sql.charAt(i);
+
+            if ((ch == '\'' || ch == '"') && (i == 0 || sql.charAt(i - 1) != '\\')) {
+                if (quoted == 0)
+                    quoted = ch;
+                else if (quoted == ch)
+                    quoted = 0;
+
+                continue;
+            }
+
+            if (quoted > 0)
+                continue;
+
+            // Current escape sequence ends up.
+            if (ch == '}') {
+                seqEndPos = i;
+
+                break;
+            }
+            // Inner escape sequence starts
+            else if (ch == '{') {
+                T2<Integer, String> res = parseEscapeSqeuence(sql, i);
+
+                if (sb == null)
+                    sb = new StringBuffer();
+
+                sb.append(sql, off, i);
+                sb.append(res.get2());
+
+                i = res.get1();
+
+                assert sql.charAt(res.get1()) == '}';
+
+                off = res.get1() + 1;
+            }
+        }
+
+        if (insideEscapeSeq && seqEndPos == -1)
+            // Closing bracket character '}' was not found in inner escape sequence
+            throw new IllegalStateException("Escape sequence started at position (" + startPosition + ") is not closed: " + sql);
+        else if (!insideEscapeSeq && seqEndPos != -1)
+            // Closing bracket character '}' was found out of escape sequence
+            throw new IllegalStateException("Unexpected seqEndPos of escaped sequence found at position (" + startPosition + ") is not closed: " + sql);
+
+        if (seqEndPos == -1)
+            seqEndPos = sql.length();
+
+        // Add tail to the result
+        if (sb == null)
+            return new T2<>(seqEndPos, sql.substring(startPosition, seqEndPos));
+        else if (off < seqEndPos)
+            sb.append(sql, off, seqEndPos);
+
+        return new T2<>(seqEndPos, sb.toString());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/06df2492/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
index 7d60b42..9c6cf7f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
@@ -1,15 +1,21 @@
 package org.apache.ignite.internal.processors.odbc;
 
+import java.util.concurrent.Callable;
 import junit.framework.TestCase;
-import org.apache.ignite.internal.processors.odbc.escape.EscapeSQLParser;
+import org.apache.ignite.internal.processors.odbc.escape.OdbcEscapeSequenceParser;
+import org.apache.ignite.testframework.GridTestUtils;
 
+/**
+ *
+ */
 public class OdbcScalarFunctionEscapeSequenceTest extends TestCase {
 
+    /** */
     public void testTrivialFunction() throws Exception {
         String sqlQry = "select {fn func(field1)} {fn func(field2)} from table;";
         String expRes = "select func(field1) func(field2) from table;";
 
-        EscapeSQLParser parser = new EscapeSQLParser();
+        OdbcEscapeSequenceParser parser = new OdbcEscapeSequenceParser();
 
         String actualRes = parser.parse(sqlQry);
 
@@ -19,31 +25,87 @@ public class OdbcScalarFunctionEscapeSequenceTest extends TestCase {
         sqlQry = "select {fn func(field1)} {fn func(field2)}";
         expRes = "select func(field1) func(field2)";
 
-        parser = new EscapeSQLParser();
+        parser = new OdbcEscapeSequenceParser();
 
         actualRes = parser.parse(sqlQry);
 
         assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
     }
 
+    /** */
     public void testNestedFunction() throws Exception {
         String sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)} from SomeTable;";
         String expRes = "select func1(field1, func2(field2), field3) from SomeTable;";
 
-        EscapeSQLParser parser = new EscapeSQLParser();
+        OdbcEscapeSequenceParser parser = new OdbcEscapeSequenceParser();
 
-        String actualResult = parser.parse(sqlQry);
+        String actualRes = parser.parse(sqlQry);
 
-        assertEquals("Scalar function escape sequence parsing fails", expRes, actualResult);
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
 
 
         sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)}";
         expRes = "select func1(field1, func2(field2), field3)";
 
-        parser = new EscapeSQLParser();
+        parser = new OdbcEscapeSequenceParser();
+
+        actualRes = parser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+    }
+
+    /** */
+    public void testEscapeSequenceWithQuotation() throws Exception {
+        String sqlQry = "select {fn func1(field1, {fn func2(\"}\")}, field3)} from SomeTable;";
+        String expRes = "select func1(field1, func2(\"}\"), field3) from SomeTable;";
+
+        OdbcEscapeSequenceParser parser = new OdbcEscapeSequenceParser();
+
+        String actualRes = parser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+
+        sqlQry = "select {fn func1(field1, '\\'{fn f(arg)}', field3)} from SomeTable;";
+        expRes = "select func1(field1, '\\\'{fn f(arg)}', field3) from SomeTable;";
+
+        parser = new OdbcEscapeSequenceParser();
+
+        actualRes = parser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+    }
+
+    /** */
+    public void testFailedOnNotClosedSequence() throws Exception {
+        GridTestUtils.assertThrows(null, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                String sqlQry = "select {fn func1(field1, {fn func2(field2), field3)} from SomeTable;";
+
+                OdbcEscapeSequenceParser parser = new OdbcEscapeSequenceParser();
+
+                parser.parse(sqlQry);
+
+                fail("Scalar function escape sequence parsing should failed");
+
+                return null;
+            }
+        }, IllegalStateException.class, null);
+    }
+
+    /** */
+    public void testFailedOnClosingNotOpenedSequence() throws Exception {
+        GridTestUtils.assertThrows(null, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                String sqlQry = "select {fn func1(field1, func2(field2)}, field3)} from SomeTable;";
+
+                OdbcEscapeSequenceParser parser = new OdbcEscapeSequenceParser();
+
+                parser.parse(sqlQry);
 
-        actualResult = parser.parse(sqlQry);
+                fail("Scalar function escape sequence parsing should failed");
 
-        assertEquals("Scalar function escape sequence parsing fails", expRes, actualResult);
+                return null;
+            }
+        }, IllegalStateException.class, null);
     }
 }


[10/12] ignite git commit: Minors.

Posted by vo...@apache.org.
Minors.


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

Branch: refs/heads/ignite-3716-1
Commit: 7694fbe72c6edca9d1e0dedbf285ed0065a86eaf
Parents: cc8f1e9
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Tue Aug 23 12:13:36 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Aug 23 12:13:36 2016 +0300

----------------------------------------------------------------------
 .../processors/odbc/escape/OdbcParser.java      | 109 ++++++++++---------
 .../OdbcScalarFunctionEscapeSequenceTest.java   |   5 +-
 2 files changed, 59 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/7694fbe7/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java
index 3d5eff61..f4d822a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java
@@ -116,6 +116,9 @@ public class OdbcParser {
             curPos++;
         }
 
+        if (openPos != -1)
+            throw new IgniteException("Malformed escape sequence (closing curly brace missing): " + text);
+
         if (curPos > plainPos)
             res.append(text, plainPos, curPos);
 
@@ -123,37 +126,6 @@ public class OdbcParser {
     }
 
     /**
-     * Append nested results.
-     *
-     * @param text Original text.
-     * @param startPos Start position.
-     * @param endPos End position.
-     * @param nestedRess Nested results.
-     * @return Result.
-     */
-    private static String appendNested(String text, int startPos, int endPos, LinkedList<ParseResult> nestedRess) {
-        StringBuilder res = new StringBuilder();
-
-        int curPos = startPos;
-
-        for (ParseResult nestedRes : nestedRess) {
-            // Append text between current position and replace.
-            res.append(text, curPos, nestedRes.originalStart);
-
-            // Append replaced text.
-            res.append(nestedRes.res);
-
-            // Advance position.
-            curPos = nestedRes.originalStart + nestedRes.originalLen;
-        }
-
-        // Append remainder.
-        res.append(text, curPos, endPos);
-
-        return res.toString();
-    }
-
-    /**
      * Parse concrete expression.
      *
      * @param text Text.
@@ -196,43 +168,48 @@ public class OdbcParser {
     }
 
     /**
-     * Perform "substring" using start position and length.
+     * Parse concrete expression.
      *
      * @param text Text.
      * @param startPos Start position.
      * @param len Length.
-     * @return Substring.
+     * @return Parsed expression.
      */
-    private static String substring(String text, int startPos, int len) {
+    private static String parseScalarExpression(String text, int startPos, int len) {
         assert validSubstring(text, startPos, len);
 
-        return text.substring(startPos, startPos + len);
+        return substring(text, startPos + 3, len - 3).trim();
     }
 
     /**
-     * Check whether substring is valid.
+     * Append nested results.
      *
-     * @param text Substring.
+     * @param text Original text.
      * @param startPos Start position.
-     * @param len Length.
-     * @return {@code True} if valid.
+     * @param endPos End position.
+     * @param nestedRess Nested results.
+     * @return Result.
      */
-    private static boolean validSubstring(String text, int startPos, int len) {
-        return text != null && startPos + len <= text.length();
-    }
+    private static String appendNested(String text, int startPos, int endPos, LinkedList<ParseResult> nestedRess) {
+        StringBuilder res = new StringBuilder();
 
-    /**
-     * Parse concrete expression.
-     *
-     * @param text Text.
-     * @param startPos Start position.
-     * @param len Length.
-     * @return Parsed expression.
-     */
-    private static String parseScalarExpression(String text, int startPos, int len) {
-        assert validSubstring(text, startPos, len);
+        int curPos = startPos;
 
-        return substring(text, startPos + 3, len - 3).trim();
+        for (ParseResult nestedRes : nestedRess) {
+            // Append text between current position and replace.
+            res.append(text, curPos, nestedRes.originalStart);
+
+            // Append replaced text.
+            res.append(nestedRes.res);
+
+            // Advance position.
+            curPos = nestedRes.originalStart + nestedRes.originalLen;
+        }
+
+        // Append remainder.
+        res.append(text, curPos, endPos);
+
+        return res.toString();
     }
 
     /**
@@ -253,6 +230,32 @@ public class OdbcParser {
     }
 
     /**
+     * Perform "substring" using start position and length.
+     *
+     * @param text Text.
+     * @param startPos Start position.
+     * @param len Length.
+     * @return Substring.
+     */
+    private static String substring(String text, int startPos, int len) {
+        assert validSubstring(text, startPos, len);
+
+        return text.substring(startPos, startPos + len);
+    }
+
+    /**
+     * Check whether substring is valid.
+     *
+     * @param text Substring.
+     * @param startPos Start position.
+     * @param len Length.
+     * @return {@code True} if valid.
+     */
+    private static boolean validSubstring(String text, int startPos, int len) {
+        return text != null && startPos + len <= text.length();
+    }
+
+    /**
      * Escape sequence type.
      */
     private enum SequenceType {

http://git-wip-us.apache.org/repos/asf/ignite/blob/7694fbe7/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
index 4aa62c4..19e8bf1 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.odbc;
 
 import java.util.concurrent.Callable;
 import junit.framework.TestCase;
+import org.apache.ignite.IgniteException;
 import org.apache.ignite.internal.processors.odbc.escape.OdbcEscapeSequenceUtils;
 import org.apache.ignite.internal.processors.odbc.escape.OdbcParser;
 import org.apache.ignite.testframework.GridTestUtils;
@@ -171,7 +172,7 @@ public class OdbcScalarFunctionEscapeSequenceTest extends TestCase {
 
                 return null;
             }
-        }, IllegalStateException.class, null);
+        }, IgniteException.class, null);
     }
 
     /** */
@@ -186,6 +187,6 @@ public class OdbcScalarFunctionEscapeSequenceTest extends TestCase {
 
                 return null;
             }
-        }, IllegalStateException.class, null);
+        }, IgniteException.class, null);
     }
 }


[04/12] ignite git commit: Scalar function escape sequence support prototype implemented. Quotation support added.

Posted by vo...@apache.org.
Scalar function escape sequence support prototype implemented.
Quotation support added.


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

Branch: refs/heads/ignite-3716-1
Commit: ed40518dc00bca6da5890555f9dbf23942bdeeb2
Parents: 98a2125
Author: Andrey V. Mashenkov <an...@gmail.com>
Authored: Mon Aug 22 18:12:31 2016 +0300
Committer: Andrey V. Mashenkov <an...@gmail.com>
Committed: Mon Aug 22 18:12:31 2016 +0300

----------------------------------------------------------------------
 .../processors/odbc/escape/EscapeSQLParser.java | 63 +++++++++++-------
 .../OdbcScalarFunctionEscapeSequenceTest.java   | 70 ++++++++++++++++++--
 2 files changed, 106 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ed40518d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java
index 4630e7d..a995b58 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSQLParser.java
@@ -11,25 +11,26 @@ public class EscapeSQLParser {
 
     /**
      * Process ODBC escape sequences in sql query.
+     *
      * @param sql - sql query text
      * @return - processed sql query text
      */
     public String parse(String sql) {
-        T2<Integer, String> value = parseInternal(sql, 0, false);
+        T2<Integer, String> val = parseInternal(sql, 0, false);
 
-        return value.get2();
+        return val.get2();
     }
 
     /**
      * Parse escape sequence using appropriate parser.
      * Supports:
-     *  - Scalar function escape sequence. Example: "{fn func(arg1, arg2)}"
+     * - Scalar function escape sequence. Example: "{fn func(arg1, arg2)}"
      *
      * @param sql - sql query text
      * @param startPosition - parser start position
      * @return pair of end of processed sequence position and parse result
      */
-    T2<Integer, String> parseEscapeSqeuence(String sql, int startPosition) {
+    private T2<Integer, String> parseEscapeSqeuence(String sql, int startPosition) {
         assert sql.charAt(startPosition) == '{';
 
         int pos = sql.indexOf(' ', startPosition + 1);
@@ -50,59 +51,75 @@ public class EscapeSQLParser {
 
     /**
      * Process ODBC escape sequences in sql query.
+     *
      * @param sql - sql query text
      * @param startPosition - parser start position
-     * @param insideEscapeSequence - inside escape sequence flag
+     * @param insideEscapeSeq - inside escape sequence flag
      * @return pair of end of processed sequence position and parse result
      */
-    @NotNull private T2<Integer, String> parseInternal(String sql, int startPosition, boolean insideEscapeSequence) {
+    @NotNull private T2<Integer, String> parseInternal(String sql, int startPosition, boolean insideEscapeSeq) {
         StringBuffer sb = null;
 
-        int end = -1;
-        int offset = startPosition;
+        int off = startPosition;
+        int seqEndPos = -1;
+
+        char quoted = 0;
 
         for (int i = startPosition; i < sql.length(); i++) {
+            char ch = sql.charAt(i);
+
+            if ((ch == '\'' || ch == '"') && (i == 0 || sql.charAt(i - 1) != '\\')) {
+                if (quoted == 0)
+                    quoted = ch;
+                else if (quoted == ch)
+                    quoted = 0;
+                continue;
+            }
+
+            if (quoted > 0)
+                continue;
+
             // Current escape sequence ends up.
-            if (sql.charAt(i) == '}') {
-                end = i;
+            if (ch == '}') {
+                seqEndPos = i;
 
                 break;
             }
             // Inner escape sequence starts
-            else if (sql.charAt(i) == '{') {
+            else if (ch == '{') {
                 T2<Integer, String> res = parseEscapeSqeuence(sql, i);
 
                 if (sb == null)
                     sb = new StringBuffer();
 
-                sb.append(sql, offset, i);
+                sb.append(sql, off, i);
                 sb.append(res.get2());
 
                 i = res.get1();
 
-                assert sql.charAt(i) == '}';
+                assert sql.charAt(res.get1()) == '}';
 
-                offset = res.get1() + 1;
+                off = res.get1() + 1;
             }
         }
 
-        if (insideEscapeSequence && end == -1)
+        if (insideEscapeSeq && seqEndPos == -1)
             // Closing bracket character '}' was not found in inner escape sequence
             throw new IllegalStateException("Escape sequence started at position (" + startPosition + ") is not closed: " + sql);
-        else if (!insideEscapeSequence && end != -1)
+        else if (!insideEscapeSeq && seqEndPos != -1)
             // Closing bracket character '}' was found out of escape sequence
-            throw new IllegalStateException("Unexpected end of escaped sequence found at position (" + startPosition + ") is not closed: " + sql);
+            throw new IllegalStateException("Unexpected seqEndPos of escaped sequence found at position (" + startPosition + ") is not closed: " + sql);
 
-        if (end == -1)
-            end = sql.length();
+        if (seqEndPos == -1)
+            seqEndPos = sql.length();
 
         // Add tail to the result
         if (sb == null)
-            return new T2<>(end, sql.substring(startPosition, end));
-        else if (offset < end)
-            sb.append(sql, offset, end);
+            return new T2<>(seqEndPos, sql.substring(startPosition, seqEndPos));
+        else if (off < seqEndPos)
+            sb.append(sql, off, seqEndPos);
 
-        return new T2<>(end, sb.toString());
+        return new T2<>(seqEndPos, sb.toString());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed40518d/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
index 7d60b42..c7f0d36 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
@@ -1,10 +1,16 @@
 package org.apache.ignite.internal.processors.odbc;
 
+import java.util.concurrent.Callable;
 import junit.framework.TestCase;
 import org.apache.ignite.internal.processors.odbc.escape.EscapeSQLParser;
+import org.apache.ignite.testframework.GridTestUtils;
 
+/**
+ *
+ */
 public class OdbcScalarFunctionEscapeSequenceTest extends TestCase {
 
+    /** */
     public void testTrivialFunction() throws Exception {
         String sqlQry = "select {fn func(field1)} {fn func(field2)} from table;";
         String expRes = "select func(field1) func(field2) from table;";
@@ -26,15 +32,16 @@ public class OdbcScalarFunctionEscapeSequenceTest extends TestCase {
         assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
     }
 
+    /** */
     public void testNestedFunction() throws Exception {
         String sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)} from SomeTable;";
         String expRes = "select func1(field1, func2(field2), field3) from SomeTable;";
 
         EscapeSQLParser parser = new EscapeSQLParser();
 
-        String actualResult = parser.parse(sqlQry);
+        String actualRes = parser.parse(sqlQry);
 
-        assertEquals("Scalar function escape sequence parsing fails", expRes, actualResult);
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
 
 
         sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)}";
@@ -42,8 +49,63 @@ public class OdbcScalarFunctionEscapeSequenceTest extends TestCase {
 
         parser = new EscapeSQLParser();
 
-        actualResult = parser.parse(sqlQry);
+        actualRes = parser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+    }
+
+    /** */
+    public void testEscapedCharsInFunction() throws Exception {
+        String sqlQry = "select {fn func1(field1, {fn func2(\"}\")}, field3)} from SomeTable;";
+        String expRes = "select func1(field1, func2(\"}\"), field3) from SomeTable;";
+
+        EscapeSQLParser parser = new EscapeSQLParser();
+
+        String actualRes = parser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+
+        sqlQry = "select {fn func1(field1, '\\'{fn f(arg)}', field3)} from SomeTable;";
+        expRes = "select func1(field1, '\\\'{fn f(arg)}', field3) from SomeTable;";
+
+        parser = new EscapeSQLParser();
+
+        actualRes = parser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+    }
+
+    /** */
+    public void testFailedNotClosedSequence() throws Exception {
+        GridTestUtils.assertThrows(null, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                String sqlQry = "select {fn func1(field1, {fn func2(field2), field3)} from SomeTable;";
+
+                EscapeSQLParser parser = new EscapeSQLParser();
+
+                parser.parse(sqlQry);
+
+                fail("Scalar function escape sequence parsing should failed");
+
+                return null;
+            }
+        }, IllegalStateException.class, null);
+    }
+
+    /** */
+    public void testFailedNotOpenedSequenceCloses() throws Exception {
+        GridTestUtils.assertThrows(null, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                String sqlQry = "select {fn func1(field1, func2(field2)}, field3)} from SomeTable;";
+
+                EscapeSQLParser parser = new EscapeSQLParser();
+
+                parser.parse(sqlQry);
+
+                fail("Scalar function escape sequence parsing should failed");
 
-        assertEquals("Scalar function escape sequence parsing fails", expRes, actualResult);
+                return null;
+            }
+        }, IllegalStateException.class, null);
     }
 }


[12/12] ignite git commit: Minors.

Posted by vo...@apache.org.
Minors.


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

Branch: refs/heads/ignite-3716-1
Commit: d087c782768abf52ab2f162568ed264dc5dea428
Parents: e48853d
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Tue Aug 23 12:38:56 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Aug 23 12:38:56 2016 +0300

----------------------------------------------------------------------
 .../processors/odbc/escape/OdbcParser.java      | 26 +++++++++-----------
 1 file changed, 11 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d087c782/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java
index f4d822a..71999da 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java
@@ -86,27 +86,23 @@ public class OdbcParser {
                     throw new IgniteException("Malformed escape sequence " +
                         "(closing curly brace without opening curly brace): " + text);
                 else {
-                    if (nested == null) {
-                        // Found sequence without nesting, process it.
-                        String parseRes = parseExpression(text, openPos, curPos - openPos);
+                    String parseRes;
 
-                        if (earlyExit)
-                            return new ParseResult(startPos, curPos - startPos + 1, parseRes);
-                        else
-                            res.append(parseRes);
-                    }
+                    if (nested == null)
+                        // Found sequence without nesting, process it.
+                        parseRes = parseExpression(text, openPos, curPos - openPos);
                     else {
-                        // Process nesting.
+                        // Special case to process nesting.
                         String res0 = appendNested(text, openPos, curPos + 1, nested);
 
-                        String parseRes = parse0(res0, 0, true).res;
-
-                        if (earlyExit)
-                            return new ParseResult(startPos, curPos - startPos + 1, parseRes);
-                        else
-                            res.append(parseRes);
+                        parseRes = parse0(res0, 0, true).res;
                     }
 
+                    if (earlyExit)
+                        return new ParseResult(startPos, curPos - startPos + 1, parseRes);
+                    else
+                        res.append(parseRes);
+
                     openPos = -1;
 
                     plainPos = curPos + 1;


[11/12] ignite git commit: Minors.

Posted by vo...@apache.org.
Minors.


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

Branch: refs/heads/ignite-3716-1
Commit: e48853dfef2ef3f94a1c6d910e46c8ca03948833
Parents: 7694fbe
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Tue Aug 23 12:36:46 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Aug 23 12:36:46 2016 +0300

----------------------------------------------------------------------
 .../internal/processors/odbc/escape/EscapeSequenceParser.java     | 3 ---
 .../internal/processors/odbc/escape/OdbcEscapeSequenceUtils.java  | 1 -
 2 files changed, 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e48853df/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParser.java
index 26bbff6..aa2446a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParser.java
@@ -17,9 +17,7 @@
 
 package org.apache.ignite.internal.processors.odbc.escape;
 
-/** */
 interface EscapeSequenceParser {
-
     /**
      * Process ODBC escape sequences in sql query.
      *
@@ -28,5 +26,4 @@ interface EscapeSequenceParser {
      * @return escape sequence parse result
      */
     EscapeSequenceParseResult parse(String sql, int start);
-
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e48853df/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceUtils.java
index da44914..a77a722 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceUtils.java
@@ -22,7 +22,6 @@ package org.apache.ignite.internal.processors.odbc.escape;
  * See ODBC escape sequence syntax.
  */
 public class OdbcEscapeSequenceUtils {
-
     /** Scalar function escape sequence parser */
     private static EscapeSequenceParser FN = new ScalarFunctionEscapeSequenceParser();
 


[08/12] ignite git commit: Scalar function escape sequence support prototype implemented.

Posted by vo...@apache.org.
Scalar function escape sequence support prototype implemented.


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

Branch: refs/heads/ignite-3716-1
Commit: 902b45ba0a85a8b66b7f40d3865b7aaa3a367a30
Parents: 4c96007
Author: Andrey V. Mashenkov <an...@gmail.com>
Authored: Mon Aug 22 20:27:34 2016 +0300
Committer: Andrey V. Mashenkov <an...@gmail.com>
Committed: Mon Aug 22 20:27:34 2016 +0300

----------------------------------------------------------------------
 .../odbc/escape/EscapeSequenceParseResult.java  |  46 +++++++
 .../odbc/escape/EscapeSequenceParser.java       |  32 +++++
 .../odbc/escape/OdbcEscapeSequenceParser.java   | 129 -------------------
 .../odbc/escape/OdbcEscapeSequenceUtils.java    |  98 ++++++++++++++
 .../ScalarFunctionEscapeSequenceParser.java     |  73 +++++++++++
 .../OdbcScalarFunctionEscapeSequenceTest.java   |  88 +++++++------
 6 files changed, 292 insertions(+), 174 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/902b45ba/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParseResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParseResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParseResult.java
new file mode 100644
index 0000000..1039028
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParseResult.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc.escape;
+
+/**
+ * Uses in parsing Odbc escape sequences
+ */
+class EscapeSequenceParseResult {
+
+    /** Sequence last character position in source sql query string. */
+    private int endPosition;
+
+    /** Escape sequence calculated value. */
+    private String value;
+
+    /** */
+    public EscapeSequenceParseResult(int endPosition, String value) {
+        this.endPosition = endPosition;
+        this.value = value;
+    }
+
+    /** */
+    public int endPosition() {
+        return endPosition;
+    }
+
+    /** */
+    public String value() {
+        return value;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/902b45ba/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParser.java
new file mode 100644
index 0000000..26bbff6
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParser.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc.escape;
+
+/** */
+interface EscapeSequenceParser {
+
+    /**
+     * Process ODBC escape sequences in sql query.
+     *
+     * @param sql - sql query string
+     * @param start - start position in given sql string
+     * @return escape sequence parse result
+     */
+    EscapeSequenceParseResult parse(String sql, int start);
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/902b45ba/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java
deleted file mode 100644
index 911aede..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package org.apache.ignite.internal.processors.odbc.escape;
-
-import org.apache.ignite.internal.util.typedef.T2;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Process ODBC escape sequences in sql query.
- * See ODBC escape sequence syntax.
- */
-public class OdbcEscapeSequenceParser {
-
-    /**
-     * Process ODBC escape sequences in sql query.
-     *
-     * @param sql - sql query text
-     * @return - processed sql query text
-     */
-    // TODO: Set static.
-    public String parse(String sql) {
-        // TODO: The whole string could be escape sequence. Need to check it here, not simply pass false.
-        T2<Integer, String> val = parse0(sql, 0, false);
-
-        return val.get2();
-    }
-
-    /**
-     * Process ODBC escape sequences in sql query.
-     *
-     * @param sql - sql query text
-     * @param startPosition - parser start position
-     * @param insideEscapeSeq - inside escape sequence flag
-     * @return pair of end of processed sequence position and parse result
-     */
-    // TODO: Do not use T2, create separate class instead.
-    @NotNull private T2<Integer, String> parse0(String sql, int startPosition, boolean insideEscapeSeq) {
-        StringBuffer sb = null;
-
-        int off = startPosition;
-        int seqEndPos = -1;
-
-        char quoted = 0;
-
-        for (int i = startPosition; i < sql.length(); i++) {
-            char ch = sql.charAt(i);
-
-            // TODO: This should be implemented as separate parsers.
-            if ((ch == '\'' || ch == '"') && (i == 0 || sql.charAt(i - 1) != '\\')) {
-                if (quoted == 0)
-                    quoted = ch;
-                else if (quoted == ch)
-                    quoted = 0;
-
-                continue;
-            }
-
-            if (quoted > 0)
-                continue;
-
-            // Current escape sequence ends up.
-            if (ch == '}') {
-                seqEndPos = i;
-
-                break;
-            }
-            // Inner escape sequence starts
-            else if (ch == '{') {
-                T2<Integer, String> res = processEscapeSequence(sql, i);
-
-                if (sb == null)
-                    sb = new StringBuffer();
-
-                sb.append(sql, off, i);
-                sb.append(res.get2());
-
-                i = res.get1();
-
-                assert sql.charAt(res.get1()) == '}';
-
-                off = res.get1() + 1;
-            }
-        }
-
-        if (insideEscapeSeq && seqEndPos == -1)
-            // Closing bracket character '}' was not found in inner escape sequence
-            throw new IllegalStateException("Escape sequence started at position (" + startPosition + ") is not closed: " + sql);
-        else if (!insideEscapeSeq && seqEndPos != -1)
-            // Closing bracket character '}' was found out of escape sequence
-            throw new IllegalStateException("Unexpected seqEndPos of escaped sequence found at position (" + startPosition + ") is not closed: " + sql);
-
-        if (seqEndPos == -1)
-            seqEndPos = sql.length();
-
-        // Add tail to the result
-        if (sb == null)
-            return new T2<>(seqEndPos, sql.substring(startPosition, seqEndPos));
-        else if (off < seqEndPos)
-            sb.append(sql, off, seqEndPos);
-
-        return new T2<>(seqEndPos, sb.toString());
-    }
-
-    /**
-     * Parse escape sequence using appropriate parser.
-     * Supports:
-     * - Scalar function escape sequence. Example: "{fn func(arg1, arg2)}"
-     *
-     * @param sql - sql query text
-     * @param startPosition - parser start position
-     * @return pair of end of processed sequence position and parse result
-     */
-    private T2<Integer, String> processEscapeSequence(String sql, int startPosition) {
-        assert sql.charAt(startPosition) == '{';
-
-        int pos = sql.indexOf(' ', startPosition + 1);
-
-        if (pos == -1)
-            throw new IllegalStateException("Escape sequence parsing error at (" + startPosition + "): " + sql);
-
-        String esType = sql.substring(startPosition + 1, pos);
-
-        switch (esType) {
-            case "fn":
-                return parse0(sql, pos + 1, true);
-
-            default:
-                throw new IllegalStateException("Unsupported escape sequence found at  (" + startPosition + "): " + sql);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/902b45ba/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceUtils.java
new file mode 100644
index 0000000..da44914
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceUtils.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc.escape;
+
+/**
+ * Process ODBC escape sequences in sql query.
+ * See ODBC escape sequence syntax.
+ */
+public class OdbcEscapeSequenceUtils {
+
+    /** Scalar function escape sequence parser */
+    private static EscapeSequenceParser FN = new ScalarFunctionEscapeSequenceParser();
+
+    /**
+     * Process ODBC escape sequences in sql query.
+     *
+     * @param sql - sql query text
+     * @return - processed sql query text
+     */
+    public static String parse(String sql) {
+        return parse0(sql, 0);
+    }
+
+    /**
+     * Process ODBC escape sequences in sql query.
+     *
+     * @param sql - sql query text
+     * @return - processed sql query text
+     */
+    private static String parse0(String sql, int startPos) {
+        StringBuffer res = null;
+
+        int off = startPos;
+
+        for (int i = startPos; i < sql.length(); i++) {
+            char ch = sql.charAt(i);
+
+            // Current escape sequence ends up.
+            if (ch == '}')
+                throw new IllegalStateException("Unexpected end of escaped sequence found at (" + i + "): " + sql);
+                // Inner escape sequence starts
+            else if (ch == '{') {
+                EscapeSequenceParseResult escapeRes = processEscapeSequence(sql, i);
+
+                if (res == null)
+                    res = new StringBuffer();
+
+                res.append(sql, off, i);
+                res.append(escapeRes.value());
+
+                i = escapeRes.endPosition();
+
+                assert sql.charAt(escapeRes.endPosition()) == '}';
+
+                off = escapeRes.endPosition() + 1;
+            }
+        }
+
+        if (res == null)
+            return sql;
+        else if (off < sql.length())
+            res.append(sql, off, sql.length());
+
+        return res.toString();
+    }
+
+    /**
+     * Parse escape sequence using appropriate parser.
+     *
+     * @param sql - sql query text
+     * @param startPosition - parser start position
+     * @return pair of end of processed sequence position and parse result
+     */
+    static EscapeSequenceParseResult processEscapeSequence(String sql, int startPosition) {
+        assert sql.charAt(startPosition) == '{';
+
+        // New escape sequence parsers should be added here.
+        if (sql.startsWith("fn ", startPosition + 1))
+            return FN.parse(sql, startPosition + 4);
+
+        throw new IllegalStateException("Unsupported escape sequence found at  (" + startPosition + "): " + sql);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/902b45ba/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/ScalarFunctionEscapeSequenceParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/ScalarFunctionEscapeSequenceParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/ScalarFunctionEscapeSequenceParser.java
new file mode 100644
index 0000000..9b2a09c
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/ScalarFunctionEscapeSequenceParser.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc.escape;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Scalar function escape sequence parser.
+ * Escape sequence example: "{fn func(arg1, arg2)}"
+ */
+class ScalarFunctionEscapeSequenceParser implements EscapeSequenceParser {
+
+    /** {@inheritDoc} */
+    @NotNull public EscapeSequenceParseResult parse(String sql, int start) {
+        int off = start;
+        int end = -1;
+
+        StringBuffer sb = null;
+
+        for (int i = start; i < sql.length(); i++) {
+            char ch = sql.charAt(i);
+
+            // Current escape sequence ends up.
+            if (ch == '}') {
+                end = i;
+
+                break;
+            }
+            // Inner escape sequence starts
+            else if (ch == '{') {
+                EscapeSequenceParseResult res = OdbcEscapeSequenceUtils.processEscapeSequence(sql, i);
+
+                if (sb == null)
+                    sb = new StringBuffer();
+
+                sb.append(sql, off, i);
+                sb.append(res.value());
+
+                i = res.endPosition();
+
+                assert sql.charAt(res.endPosition()) == '}';
+
+                off = res.endPosition() + 1;
+            }
+        }
+
+        if (end == -1)
+            // Closing bracket character '}' was not found in escape sequence
+            throw new IllegalStateException("Escape sequence started at position (" + start + ") is not closed: " + sql);
+
+        if (sb != null && off < end)
+            sb.append(sql, off, end);
+
+        String res = (sb != null) ? sb.toString() : sql.substring(start, end);
+
+        return new EscapeSequenceParseResult(end, res);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/902b45ba/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
index 9c6cf7f..bab9feb 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
@@ -1,76 +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.odbc;
 
 import java.util.concurrent.Callable;
 import junit.framework.TestCase;
-import org.apache.ignite.internal.processors.odbc.escape.OdbcEscapeSequenceParser;
+import org.apache.ignite.internal.processors.odbc.escape.OdbcEscapeSequenceUtils;
 import org.apache.ignite.testframework.GridTestUtils;
 
-/**
- *
- */
+/** */
 public class OdbcScalarFunctionEscapeSequenceTest extends TestCase {
 
     /** */
-    public void testTrivialFunction() throws Exception {
-        String sqlQry = "select {fn func(field1)} {fn func(field2)} from table;";
-        String expRes = "select func(field1) func(field2) from table;";
-
-        OdbcEscapeSequenceParser parser = new OdbcEscapeSequenceParser();
+    public void testTrivial() throws Exception {
+        String sqlQry = "{fn test()}";
+        String expRes = "test()";
 
-        String actualRes = parser.parse(sqlQry);
+        String actualRes = OdbcEscapeSequenceUtils.parse(sqlQry);
 
         assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
 
+        sqlQry = "select * from table;";
+        expRes = "select * from table;";
 
-        sqlQry = "select {fn func(field1)} {fn func(field2)}";
-        expRes = "select func(field1) func(field2)";
-
-        parser = new OdbcEscapeSequenceParser();
-
-        actualRes = parser.parse(sqlQry);
+        actualRes = OdbcEscapeSequenceUtils.parse(sqlQry);
 
         assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
     }
 
-    /** */
-    public void testNestedFunction() throws Exception {
-        String sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)} from SomeTable;";
-        String expRes = "select func1(field1, func2(field2), field3) from SomeTable;";
 
-        OdbcEscapeSequenceParser parser = new OdbcEscapeSequenceParser();
+    /** */
+    public void testSimpleFunction() throws Exception {
+        String sqlQry = "select {fn func(field1)} {fn func(field2)} from table;";
+        String expRes = "select func(field1) func(field2) from table;";
 
-        String actualRes = parser.parse(sqlQry);
+        String actualRes = OdbcEscapeSequenceUtils.parse(sqlQry);
 
         assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
 
+        sqlQry = "select {fn func(field1)} {fn func(field2)}";
+        expRes = "select func(field1) func(field2)";
 
-        sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)}";
-        expRes = "select func1(field1, func2(field2), field3)";
-
-        parser = new OdbcEscapeSequenceParser();
-
-        actualRes = parser.parse(sqlQry);
+        actualRes = OdbcEscapeSequenceUtils.parse(sqlQry);
 
         assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
     }
 
     /** */
-    public void testEscapeSequenceWithQuotation() throws Exception {
-        String sqlQry = "select {fn func1(field1, {fn func2(\"}\")}, field3)} from SomeTable;";
-        String expRes = "select func1(field1, func2(\"}\"), field3) from SomeTable;";
-
-        OdbcEscapeSequenceParser parser = new OdbcEscapeSequenceParser();
+    public void testNestedFunction() throws Exception {
+        String sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)} from SomeTable;";
+        String expRes = "select func1(field1, func2(field2), field3) from SomeTable;";
 
-        String actualRes = parser.parse(sqlQry);
+        String actualRes = OdbcEscapeSequenceUtils.parse(sqlQry);
 
         assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
 
-        sqlQry = "select {fn func1(field1, '\\'{fn f(arg)}', field3)} from SomeTable;";
-        expRes = "select func1(field1, '\\\'{fn f(arg)}', field3) from SomeTable;";
-
-        parser = new OdbcEscapeSequenceParser();
+        sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)}";
+        expRes = "select func1(field1, func2(field2), field3)";
 
-        actualRes = parser.parse(sqlQry);
+        actualRes = OdbcEscapeSequenceUtils.parse(sqlQry);
 
         assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
     }
@@ -81,9 +83,7 @@ public class OdbcScalarFunctionEscapeSequenceTest extends TestCase {
             @Override public Void call() throws Exception {
                 String sqlQry = "select {fn func1(field1, {fn func2(field2), field3)} from SomeTable;";
 
-                OdbcEscapeSequenceParser parser = new OdbcEscapeSequenceParser();
-
-                parser.parse(sqlQry);
+                String actualRes = OdbcEscapeSequenceUtils.parse(sqlQry);
 
                 fail("Scalar function escape sequence parsing should failed");
 
@@ -98,9 +98,7 @@ public class OdbcScalarFunctionEscapeSequenceTest extends TestCase {
             @Override public Void call() throws Exception {
                 String sqlQry = "select {fn func1(field1, func2(field2)}, field3)} from SomeTable;";
 
-                OdbcEscapeSequenceParser parser = new OdbcEscapeSequenceParser();
-
-                parser.parse(sqlQry);
+                OdbcEscapeSequenceUtils.parse(sqlQry);
 
                 fail("Scalar function escape sequence parsing should failed");
 


[06/12] ignite git commit: Merge remote-tracking branch 'origin/ignite-3716' into ignite-3716

Posted by vo...@apache.org.
Merge remote-tracking branch 'origin/ignite-3716' into ignite-3716

# Conflicts:
#	modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java
#	modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java


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

Branch: refs/heads/ignite-3716-1
Commit: 59a734a884d96b53647aed9f93a0f20d6837a7d7
Parents: 06df249 ed40518
Author: Andrey V. Mashenkov <an...@gmail.com>
Authored: Mon Aug 22 18:20:20 2016 +0300
Committer: Andrey V. Mashenkov <an...@gmail.com>
Committed: Mon Aug 22 18:20:20 2016 +0300

----------------------------------------------------------------------

----------------------------------------------------------------------



[07/12] ignite git commit: Review.

Posted by vo...@apache.org.
Review.


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

Branch: refs/heads/ignite-3716-1
Commit: 4c960071b25fb2846e272923175740cb523729ab
Parents: 59a734a
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Mon Aug 22 18:58:53 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Mon Aug 22 18:58:53 2016 +0300

----------------------------------------------------------------------
 .../odbc/escape/OdbcEscapeSequenceParser.java   | 65 ++++++++++----------
 1 file changed, 34 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/4c960071/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java
index cfaa7c0..911aede 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceParser.java
@@ -15,41 +15,15 @@ public class OdbcEscapeSequenceParser {
      * @param sql - sql query text
      * @return - processed sql query text
      */
+    // TODO: Set static.
     public String parse(String sql) {
-        T2<Integer, String> val = parseInternal(sql, 0, false);
+        // TODO: The whole string could be escape sequence. Need to check it here, not simply pass false.
+        T2<Integer, String> val = parse0(sql, 0, false);
 
         return val.get2();
     }
 
     /**
-     * Parse escape sequence using appropriate parser.
-     * Supports:
-     * - Scalar function escape sequence. Example: "{fn func(arg1, arg2)}"
-     *
-     * @param sql - sql query text
-     * @param startPosition - parser start position
-     * @return pair of end of processed sequence position and parse result
-     */
-    private T2<Integer, String> parseEscapeSqeuence(String sql, int startPosition) {
-        assert sql.charAt(startPosition) == '{';
-
-        int pos = sql.indexOf(' ', startPosition + 1);
-
-        if (pos == -1)
-            throw new IllegalStateException("Escape sequence parsing error at (" + startPosition + "): " + sql);
-
-        String esType = sql.substring(startPosition + 1, pos);
-
-        switch (esType) {
-            case "fn":
-                return parseInternal(sql, pos + 1, true);
-
-            default:
-                throw new IllegalStateException("Unsupported escape sequence found at  (" + startPosition + "): " + sql);
-        }
-    }
-
-    /**
      * Process ODBC escape sequences in sql query.
      *
      * @param sql - sql query text
@@ -57,7 +31,8 @@ public class OdbcEscapeSequenceParser {
      * @param insideEscapeSeq - inside escape sequence flag
      * @return pair of end of processed sequence position and parse result
      */
-    @NotNull private T2<Integer, String> parseInternal(String sql, int startPosition, boolean insideEscapeSeq) {
+    // TODO: Do not use T2, create separate class instead.
+    @NotNull private T2<Integer, String> parse0(String sql, int startPosition, boolean insideEscapeSeq) {
         StringBuffer sb = null;
 
         int off = startPosition;
@@ -68,6 +43,7 @@ public class OdbcEscapeSequenceParser {
         for (int i = startPosition; i < sql.length(); i++) {
             char ch = sql.charAt(i);
 
+            // TODO: This should be implemented as separate parsers.
             if ((ch == '\'' || ch == '"') && (i == 0 || sql.charAt(i - 1) != '\\')) {
                 if (quoted == 0)
                     quoted = ch;
@@ -88,7 +64,7 @@ public class OdbcEscapeSequenceParser {
             }
             // Inner escape sequence starts
             else if (ch == '{') {
-                T2<Integer, String> res = parseEscapeSqeuence(sql, i);
+                T2<Integer, String> res = processEscapeSequence(sql, i);
 
                 if (sb == null)
                     sb = new StringBuffer();
@@ -123,4 +99,31 @@ public class OdbcEscapeSequenceParser {
         return new T2<>(seqEndPos, sb.toString());
     }
 
+    /**
+     * Parse escape sequence using appropriate parser.
+     * Supports:
+     * - Scalar function escape sequence. Example: "{fn func(arg1, arg2)}"
+     *
+     * @param sql - sql query text
+     * @param startPosition - parser start position
+     * @return pair of end of processed sequence position and parse result
+     */
+    private T2<Integer, String> processEscapeSequence(String sql, int startPosition) {
+        assert sql.charAt(startPosition) == '{';
+
+        int pos = sql.indexOf(' ', startPosition + 1);
+
+        if (pos == -1)
+            throw new IllegalStateException("Escape sequence parsing error at (" + startPosition + "): " + sql);
+
+        String esType = sql.substring(startPosition + 1, pos);
+
+        switch (esType) {
+            case "fn":
+                return parse0(sql, pos + 1, true);
+
+            default:
+                throw new IllegalStateException("Unsupported escape sequence found at  (" + startPosition + "): " + sql);
+        }
+    }
 }


[09/12] ignite git commit: Alternate implementation.

Posted by vo...@apache.org.
Alternate implementation.


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

Branch: refs/heads/ignite-3716-1
Commit: cc8f1e92fffafc532ac547f3fdf57676ad1bebf5
Parents: 902b45b
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Tue Aug 23 11:58:44 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Aug 23 11:58:44 2016 +0300

----------------------------------------------------------------------
 .../processors/odbc/escape/OdbcParser.java      | 289 +++++++++++++++++++
 .../OdbcScalarFunctionEscapeSequenceTest.java   |  82 ++++++
 2 files changed, 371 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/cc8f1e92/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java
new file mode 100644
index 0000000..3d5eff61
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcParser.java
@@ -0,0 +1,289 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc.escape;
+
+import org.apache.ignite.IgniteException;
+
+import java.util.LinkedList;
+
+/**
+ * ODBC escape sequence parse.
+ */
+public class OdbcParser {
+    /**
+     * Parse escape sequence.
+     *
+     * @param text Original text.
+     * @return Result.
+     */
+    public static String parse(String text) {
+        if (text == null)
+            throw new IgniteException("Text cannot be null.");
+
+        return parse0(text.trim(), 0, false).res;
+    }
+
+    /**
+     * Internal parse routine.
+     *
+     * @param text Text.
+     * @param startPos Start position.
+     * @param earlyExit When set to {@code true} we must return as soon as single expression is parsed.
+     * @return Parse result.
+     */
+    private static ParseResult parse0(String text, int startPos, boolean earlyExit) {
+        StringBuilder res = new StringBuilder();
+
+        int curPos = startPos;
+
+        int plainPos = startPos;
+        int openPos = -1;
+
+        LinkedList<ParseResult> nested = null;
+
+        while (curPos < text.length()) {
+            char curChar = text.charAt(curPos);
+
+            if (curChar == '{') {
+                if (openPos == -1) {
+                    // Top-level opening brace. Append previous portion and remember current position.
+                    res.append(text, plainPos, curPos);
+
+                    openPos = curPos;
+                }
+                else {
+                    // Nested opening brace -> perform recursion.
+                    ParseResult nestedRes = parse0(text, curPos, true);
+
+                    if (nested == null)
+                        nested = new LinkedList<>();
+
+                    nested.add(nestedRes);
+
+                    curPos += nestedRes.originalLen;
+
+                    plainPos = curPos;
+                }
+            }
+            else if (curChar == '}') {
+                if (openPos == -1)
+                    // Close without open -> exception.
+                    throw new IgniteException("Malformed escape sequence " +
+                        "(closing curly brace without opening curly brace): " + text);
+                else {
+                    if (nested == null) {
+                        // Found sequence without nesting, process it.
+                        String parseRes = parseExpression(text, openPos, curPos - openPos);
+
+                        if (earlyExit)
+                            return new ParseResult(startPos, curPos - startPos + 1, parseRes);
+                        else
+                            res.append(parseRes);
+                    }
+                    else {
+                        // Process nesting.
+                        String res0 = appendNested(text, openPos, curPos + 1, nested);
+
+                        String parseRes = parse0(res0, 0, true).res;
+
+                        if (earlyExit)
+                            return new ParseResult(startPos, curPos - startPos + 1, parseRes);
+                        else
+                            res.append(parseRes);
+                    }
+
+                    openPos = -1;
+
+                    plainPos = curPos + 1;
+                }
+            }
+
+            curPos++;
+        }
+
+        if (curPos > plainPos)
+            res.append(text, plainPos, curPos);
+
+        return new ParseResult(startPos, curPos - startPos + 1, res.toString());
+    }
+
+    /**
+     * Append nested results.
+     *
+     * @param text Original text.
+     * @param startPos Start position.
+     * @param endPos End position.
+     * @param nestedRess Nested results.
+     * @return Result.
+     */
+    private static String appendNested(String text, int startPos, int endPos, LinkedList<ParseResult> nestedRess) {
+        StringBuilder res = new StringBuilder();
+
+        int curPos = startPos;
+
+        for (ParseResult nestedRes : nestedRess) {
+            // Append text between current position and replace.
+            res.append(text, curPos, nestedRes.originalStart);
+
+            // Append replaced text.
+            res.append(nestedRes.res);
+
+            // Advance position.
+            curPos = nestedRes.originalStart + nestedRes.originalLen;
+        }
+
+        // Append remainder.
+        res.append(text, curPos, endPos);
+
+        return res.toString();
+    }
+
+    /**
+     * Parse concrete expression.
+     *
+     * @param text Text.
+     * @param startPos Start position within text.
+     * @param len Length.
+     * @return Result.
+     */
+    private static String parseExpression(String text, int startPos, int len) {
+        assert validSubstring(text, startPos, len);
+
+        char firstChar = text.charAt(startPos);
+
+        if (firstChar == '{') {
+            char lastChar = text.charAt(startPos + len);
+
+            if (lastChar != '}')
+                throw new IgniteException("Failed to parse escape sequence because it is not enclosed: " +
+                    substring(text, startPos, len));
+
+            SequenceType typ = sequenceType(text, startPos, len);
+
+            switch (typ) {
+                case FN:
+                    return parseScalarExpression(text, startPos, len);
+
+                default: {
+                    assert false : "Unknown expression type: " + typ;
+
+                    return null;
+                }
+            }
+        }
+        else {
+            // Nothing to escape, return original string.
+            if (startPos == 0 || text.length() == len)
+                return text;
+            else
+                return text.substring(startPos, startPos + len);
+        }
+    }
+
+    /**
+     * Perform "substring" using start position and length.
+     *
+     * @param text Text.
+     * @param startPos Start position.
+     * @param len Length.
+     * @return Substring.
+     */
+    private static String substring(String text, int startPos, int len) {
+        assert validSubstring(text, startPos, len);
+
+        return text.substring(startPos, startPos + len);
+    }
+
+    /**
+     * Check whether substring is valid.
+     *
+     * @param text Substring.
+     * @param startPos Start position.
+     * @param len Length.
+     * @return {@code True} if valid.
+     */
+    private static boolean validSubstring(String text, int startPos, int len) {
+        return text != null && startPos + len <= text.length();
+    }
+
+    /**
+     * Parse concrete expression.
+     *
+     * @param text Text.
+     * @param startPos Start position.
+     * @param len Length.
+     * @return Parsed expression.
+     */
+    private static String parseScalarExpression(String text, int startPos, int len) {
+        assert validSubstring(text, startPos, len);
+
+        return substring(text, startPos + 3, len - 3).trim();
+    }
+
+    /**
+     * Get escape sequence type.
+     *
+     * @param text Text.
+     * @param startPos Start position.
+     * @return Escape sequence type.
+     */
+    private static SequenceType sequenceType(String text, int startPos, int len) {
+        assert validSubstring(text, startPos, len);
+        assert text.charAt(startPos) == '{';
+
+        if (text.startsWith("fn", startPos + 1))
+            return SequenceType.FN;
+
+        throw new IgniteException("Unsupported escape sequence: " + text.substring(startPos, startPos + len));
+    }
+
+    /**
+     * Escape sequence type.
+     */
+    private enum SequenceType {
+        /** Scalar function. */
+        FN
+    }
+
+    /**
+     * Parse result.
+     */
+    private static class ParseResult {
+        /** Original start position. */
+        private final int originalStart;
+
+        /** Original length. */
+        private final int originalLen;
+
+        /** Resulting text. */
+        private final String res;
+
+        /**
+         * Constructor.
+         *
+         * @param originalStart Original start position.
+         * @param originalLen Original length.
+         * @param res Resulting text.
+         */
+        public ParseResult(int originalStart, int originalLen, String res) {
+            this.originalStart = originalStart;
+            this.originalLen = originalLen;
+            this.res = res;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cc8f1e92/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
index bab9feb..4aa62c4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcScalarFunctionEscapeSequenceTest.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.odbc;
 import java.util.concurrent.Callable;
 import junit.framework.TestCase;
 import org.apache.ignite.internal.processors.odbc.escape.OdbcEscapeSequenceUtils;
+import org.apache.ignite.internal.processors.odbc.escape.OdbcParser;
 import org.apache.ignite.testframework.GridTestUtils;
 
 /** */
@@ -106,4 +107,85 @@ public class OdbcScalarFunctionEscapeSequenceTest extends TestCase {
             }
         }, IllegalStateException.class, null);
     }
+
+    /** */
+    public void testTrivial2() throws Exception {
+        String sqlQry = "{fn test()}";
+        String expRes = "test()";
+
+        String actualRes = OdbcParser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+
+        sqlQry = "select * from table;";
+        expRes = "select * from table;";
+
+        actualRes = OdbcParser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+    }
+
+    /** */
+    public void testSimpleFunction2() throws Exception {
+        String sqlQry = "select {fn func(field1)} {fn func(field2)} from table;";
+        String expRes = "select func(field1) func(field2) from table;";
+
+        String actualRes = OdbcParser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+
+        sqlQry = "select {fn func(field1)} {fn func(field2)}";
+        expRes = "select func(field1) func(field2)";
+
+        actualRes = OdbcParser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+    }
+
+    /** */
+    public void testNestedFunction2() throws Exception {
+        String sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)} from SomeTable;";
+        String expRes = "select func1(field1, func2(field2), field3) from SomeTable;";
+
+        String actualRes = OdbcParser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+
+        sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)}";
+        expRes = "select func1(field1, func2(field2), field3)";
+
+        actualRes = OdbcParser.parse(sqlQry);
+
+        assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes);
+    }
+
+    /** */
+    public void testFailedOnNotClosedSequence2() throws Exception {
+        GridTestUtils.assertThrows(null, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                String sqlQry = "select {fn func1(field1, {fn func2(field2), field3)} from SomeTable;";
+
+                OdbcParser.parse(sqlQry);
+
+                fail("Scalar function escape sequence parsing should failed");
+
+                return null;
+            }
+        }, IllegalStateException.class, null);
+    }
+
+    /** */
+    public void testFailedOnClosingNotOpenedSequence2() throws Exception {
+        GridTestUtils.assertThrows(null, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                String sqlQry = "select {fn func1(field1, func2(field2)}, field3)} from SomeTable;";
+
+                OdbcParser.parse(sqlQry);
+
+                fail("Scalar function escape sequence parsing should failed");
+
+                return null;
+            }
+        }, IllegalStateException.class, null);
+    }
 }