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

[30/50] [abbrv] ignite git commit: IGNITE-3742: ODBC: Added support for OUTER JOIN escape sequence. This closes #1000.

IGNITE-3742: ODBC: Added support for OUTER JOIN escape sequence. This closes #1000.


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

Branch: refs/heads/ignite-961
Commit: 3244a5c9dabf6d4fcaa32a661cc0adc6f8ea30de
Parents: f9ff97c
Author: Andrey V. Mashenkov <an...@gmail.com>
Authored: Tue Aug 30 11:49:11 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Aug 30 11:49:11 2016 +0300

----------------------------------------------------------------------
 .../processors/odbc/escape/OdbcEscapeUtils.java |  32 +++---
 .../odbc/OdbcEscapeSequenceSelfTest.java        | 109 ++++++++++++++++++-
 2 files changed, 122 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/3244a5c9/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeUtils.java
index a4b89c3..27120d4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeUtils.java
@@ -105,14 +105,14 @@ public class OdbcEscapeUtils {
 
                     if (nested == null)
                         // Found sequence without nesting, process it.
-                        parseRes = parseExpression(text, openPos, curPos + 1 - openPos);
+                        parseRes = parseEscapeSequence(text, openPos, curPos + 1 - openPos);
                     else {
                         // Special case to process nesting.
                         String res0 = appendNested(text, openPos, curPos + 1, nested);
 
                         nested = null;
 
-                        parseRes = parseExpression(res0, 0, res0.length());
+                        parseRes = parseEscapeSequence(res0, 0, res0.length());
                     }
 
                     if (earlyExit)
@@ -139,14 +139,14 @@ public class OdbcEscapeUtils {
     }
 
     /**
-     * Parse concrete expression.
+     * Parse escape sequence: {escape_sequence}.
      *
      * @param text Text.
      * @param startPos Start position within text.
      * @param len Length.
      * @return Result.
      */
-    private static String parseExpression(String text, int startPos, int len) {
+    private static String parseEscapeSequence(String text, int startPos, int len) {
         assert validSubstring(text, startPos, len);
 
         char firstChar = text.charAt(startPos);
@@ -228,7 +228,7 @@ public class OdbcEscapeUtils {
     }
 
     /**
-     * Parse standard token.
+     * Parse standard expression: {TOKEN expression}
      *
      * @param text Text.
      * @param startPos Start position.
@@ -245,10 +245,13 @@ public class OdbcEscapeUtils {
 
         switch (token.type()) {
             case SCALAR_FUNCTION:
-                return parseScalarExpression(text, startPos0, len0);
+                return parseExpression(text, startPos0, len0);
+
+            case GUID: {
+                String res = parseExpression(text, startPos0, len0, token.type(), GUID_PATTERN);
 
-            case GUID:
-                return parseExpression(text, startPos0, len0, token.type(), GUID_PATTERN);
+                return "CAST(" + res + " AS UUID)";
+            }
 
             case DATE:
                 return parseExpression(text, startPos0, len0, token.type(), DATE_PATTERN);
@@ -259,6 +262,9 @@ public class OdbcEscapeUtils {
             case TIMESTAMP:
                 return parseExpression(text, startPos0, len0, token.type(), TIMESTAMP_PATTERN);
 
+            case OUTER_JOIN:
+                return parseExpression(text, startPos0, len0);
+
             default:
                 throw new IgniteException("Unsupported escape sequence token [text=" +
                     substring(text, startPos, len) + ", token=" + token.type().body() + ']');
@@ -266,19 +272,19 @@ public class OdbcEscapeUtils {
     }
 
     /**
-     * Parse scalar function expression.
+     * Parse simple expression.
      *
      * @param text Text.
      * @param startPos Start position.
      * @param len Length.
      * @return Parsed expression.
      */
-    private static String parseScalarExpression(String text, int startPos, int len) {
+    private static String parseExpression(String text, int startPos, int len) {
         return substring(text, startPos, len).trim();
     }
 
     /**
-     * Parse concrete expression.
+     * Parse expression and validate against ODBC specification with regex pattern.
      *
      * @param text Text.
      * @param startPos Start position.
@@ -286,12 +292,12 @@ public class OdbcEscapeUtils {
      * @return Parsed expression.
      */
     private static String parseExpression(String text, int startPos, int len, OdbcEscapeType type, Pattern pattern) {
-        String val = substring(text, startPos, len).trim();
+        String val = parseExpression(text, startPos, len);
 
         if (!pattern.matcher(val).matches())
             throw new IgniteException("Invalid " + type + " escape sequence: " + substring(text, startPos, len));
 
-        return "CAST(" + val + " AS UUID)";
+        return val;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/3244a5c9/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcEscapeSequenceSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcEscapeSequenceSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcEscapeSequenceSelfTest.java
index 1aa90fd..4887a67 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcEscapeSequenceSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/odbc/OdbcEscapeSequenceSelfTest.java
@@ -167,17 +167,17 @@ public class OdbcEscapeSequenceSelfTest extends GridCommonAbstractTest {
      */
     public void testGuidEscapeSequence() {
         check(
-            "'12345678-9abc-def0-1234-123456789abc'",
+            "CAST('12345678-9abc-def0-1234-123456789abc' AS UUID)",
             "{guid '12345678-9abc-def0-1234-123456789abc'}"
         );
 
         check(
-            "select '12345678-9abc-def0-1234-123456789abc' from SomeTable;",
+            "select CAST('12345678-9abc-def0-1234-123456789abc' AS UUID) from SomeTable;",
             "select {guid '12345678-9abc-def0-1234-123456789abc'} from SomeTable;"
         );
 
         check(
-            "select '12345678-9abc-def0-1234-123456789abc'",
+            "select CAST('12345678-9abc-def0-1234-123456789abc' AS UUID)",
             "select {guid '12345678-9abc-def0-1234-123456789abc'}"
         );
     }
@@ -212,17 +212,17 @@ public class OdbcEscapeSequenceSelfTest extends GridCommonAbstractTest {
      */
     public void testGuidEscapeSequenceWithWhitespaces() throws Exception {
         check(
-            "'12345678-9abc-def0-1234-123456789abc'",
+            "CAST('12345678-9abc-def0-1234-123456789abc' AS UUID)",
             "{ guid '12345678-9abc-def0-1234-123456789abc'}"
         );
 
         check(
-            "'12345678-9abc-def0-1234-123456789abc'",
+            "CAST('12345678-9abc-def0-1234-123456789abc' AS UUID)",
             "{    guid  '12345678-9abc-def0-1234-123456789abc'}"
         );
 
         check(
-            "'12345678-9abc-def0-1234-123456789abc'",
+            "CAST('12345678-9abc-def0-1234-123456789abc' AS UUID)",
             "{  \n guid\n'12345678-9abc-def0-1234-123456789abc'}"
         );
     }
@@ -388,6 +388,103 @@ public class OdbcEscapeSequenceSelfTest extends GridCommonAbstractTest {
         checkFail("select {}ts '2016-08-26 13:15:08'} from table;");
     }
 
+
+    /**
+     * Test escape sequence series.
+     */
+    public void testOuterJoinFunction() throws Exception {
+        check(
+            "t OUTER JOIN t2 ON t.id=t2.id",
+            "{oj t OUTER JOIN t2 ON t.id=t2.id}"
+        );
+
+        check(
+            "select * from t OUTER JOIN t2 ON t.id=t2.id",
+            "select * from {oj t OUTER JOIN t2 ON t.id=t2.id}"
+        );
+
+        check(
+            "select * from t OUTER JOIN t2 ON t.id=t2.id ORDER BY t2.id",
+            "select * from {oj t OUTER JOIN t2 ON t.id=t2.id} ORDER BY t2.id"
+        );
+    }
+
+    /**
+     * Test simple nested escape sequences. Depth = 2.
+     */
+    public void testNestedOuterJoin() throws Exception {
+        check(
+            "t OUTER JOIN (t2 OUTER JOIN t3 ON t2.id=t3.id) ON t.id=t2.id",
+            "{oj t OUTER JOIN ({oj t2 OUTER JOIN t3 ON t2.id=t3.id}) ON t.id=t2.id}"
+        );
+
+        check(
+            "select * from t OUTER JOIN (t2 OUTER JOIN t3 ON t2.id=t3.id) ON t.id=t2.id",
+            "select * from {oj t OUTER JOIN ({oj  t2 OUTER JOIN t3 ON t2.id=t3.id}) ON t.id=t2.id}"
+        );
+
+        check(
+            "select * from t OUTER JOIN (t2 OUTER JOIN t3 ON t2.id=t3.id) ON t.id=t2.id ORDER BY t2.id",
+            "select * from {oj t OUTER JOIN ({oj t2 OUTER JOIN t3 ON t2.id=t3.id}) ON t.id=t2.id} ORDER BY t2.id"
+        );
+    }
+
+    /**
+     * Test nested escape sequences. Depth > 2.
+     */
+    public void testDeepNestedOuterJoin() {
+        check(
+            "t OUTER JOIN (t2 OUTER JOIN (t3 OUTER JOIN t4 ON t3.id=t4.id) ON t2.id=t3.id) ON t.id=t2.id",
+            "{oj t OUTER JOIN ({oj t2 OUTER JOIN ({oj t3 OUTER JOIN t4 ON t3.id=t4.id}) ON t2.id=t3.id}) ON t.id=t2.id}"
+        );
+
+        check(
+            "select * from " +
+                "t OUTER JOIN (t2 OUTER JOIN (t3 OUTER JOIN t4 ON t3.id=t4.id) ON t2.id=t3.id) ON t.id=t2.id",
+            "select * from " +
+                "{oj t OUTER JOIN ({oj t2 OUTER JOIN ({oj t3 OUTER JOIN t4 ON t3.id=t4.id}) ON t2.id=t3.id})" +
+                " ON t.id=t2.id}"
+        );
+
+        check(
+            "select * from t OUTER JOIN (t2 OUTER JOIN (t3 OUTER JOIN t4 ON t3.id=t4.id) " +
+                "ON t2.id=t3.id) ON t.id=t2.id ORDER BY t4.id",
+            "select * from {oj t OUTER JOIN ({oj t2 OUTER JOIN ({oj t3 OUTER JOIN t4 ON t3.id=t4.id}) " +
+                "ON t2.id=t3.id}) ON t.id=t2.id} ORDER BY t4.id"
+        );
+    }
+
+    /**
+     * Test invalid escape sequence.
+     */
+    public void testFailedOnInvalidOuterJoinSequence() {
+        checkFail("{ojt OUTER JOIN t2 ON t.id=t2.id}");
+
+        checkFail("select {oj t OUTER JOIN ({oj t2 OUTER JOIN t3 ON t2.id=t3.id) ON t.id=t2.id} from SomeTable;");
+
+        checkFail("select oj t OUTER JOIN t2 ON t.id=t2.id} from SomeTable;");
+    }
+
+    /**
+     * Test escape sequences with additional whitespace characters
+     */
+    public void testOuterJoinSequenceWithWhitespaces() throws Exception {
+        check(
+            "t OUTER JOIN t2 ON t.id=t2.id",
+            "{ oj t OUTER JOIN t2 ON t.id=t2.id}"
+        );
+
+        check(
+            "t OUTER JOIN t2 ON t.id=t2.id",
+            "{    oj  t OUTER JOIN t2 ON t.id=t2.id}"
+        );
+
+        check(
+            "t OUTER JOIN t2 ON t.id=t2.id",
+            "  \n { oj\nt OUTER JOIN t2 ON t.id=t2.id}"
+        );
+    }
+
     /**
      * Check parsing logic.
      *