ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From voze...@apache.org
Subject [04/19] ignite git commit: Scalar function escape sequence support prototype implemented. Quotation support added.
Date Wed, 24 Aug 2016 08:48:56 GMT
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
Commit: ed40518dc00bca6da5890555f9dbf23942bdeeb2
Parents: 98a2125
Author: Andrey V. Mashenkov <andrey.mashenkov@gmail.com>
Authored: Mon Aug 22 18:12:31 2016 +0300
Committer: Andrey V. Mashenkov <andrey.mashenkov@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);
     }
 }


Mime
View raw message