Minor fixed. Tests added.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/5e4dd65c Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/5e4dd65c Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/5e4dd65c Branch: refs/heads/ignite-3716 Commit: 5e4dd65ca6246d2f76b37b1152404bbb8f063cbb Parents: a5ad442 Author: Andrey V. Mashenkov <[email protected]> Authored: Tue Aug 23 15:46:18 2016 +0300 Committer: Andrey V. Mashenkov <[email protected]> Committed: Tue Aug 23 15:46:18 2016 +0300 ---------------------------------------------------------------------- .../odbc/escape/EscapeSequenceParseResult.java | 46 ------ .../odbc/escape/EscapeSequenceParser.java | 29 ---- .../odbc/escape/OdbcEscapeSequenceUtils.java | 97 ------------- .../processors/odbc/escape/OdbcParser.java | 9 +- .../ScalarFunctionEscapeSequenceParser.java | 73 ---------- .../OdbcScalarFunctionEscapeSequenceTest.java | 139 ++++++++++--------- 6 files changed, 83 insertions(+), 310 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/5e4dd65c/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 deleted file mode 100644 index 1039028..0000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParseResult.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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/5e4dd65c/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 deleted file mode 100644 index aa2446a..0000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/EscapeSequenceParser.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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/5e4dd65c/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 deleted file mode 100644 index a77a722..0000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/OdbcEscapeSequenceUtils.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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/5e4dd65c/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 71999da..0e9f5fa 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 @@ -17,9 +17,8 @@ package org.apache.ignite.internal.processors.odbc.escape; -import org.apache.ignite.IgniteException; - import java.util.LinkedList; +import org.apache.ignite.IgniteException; /** * ODBC escape sequence parse. @@ -78,6 +77,8 @@ public class OdbcParser { curPos += nestedRes.originalLen; plainPos = curPos; + + continue; } } else if (curChar == '}') { @@ -95,7 +96,9 @@ public class OdbcParser { // Special case to process nesting. String res0 = appendNested(text, openPos, curPos + 1, nested); - parseRes = parse0(res0, 0, true).res; + nested = null; + + parseRes = parseExpression(res0, 0, res0.length()-1); } if (earlyExit) http://git-wip-us.apache.org/repos/asf/ignite/blob/5e4dd65c/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 deleted file mode 100644 index 9b2a09c..0000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/escape/ScalarFunctionEscapeSequenceParser.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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/5e4dd65c/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 19e8bf1..011d00f 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,7 +20,6 @@ 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; @@ -29,139 +28,155 @@ public class OdbcScalarFunctionEscapeSequenceTest extends TestCase { /** */ public void testTrivial() throws Exception { - String sqlQry = "{fn test()}"; - String expRes = "test()"; + String sqlQry= "select * from table;"; + String expRes = "select * from table;"; - String actualRes = OdbcEscapeSequenceUtils.parse(sqlQry); + String actualRes = OdbcParser.parse(sqlQry); assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes); + } - sqlQry = "select * from table;"; - expRes = "select * from table;"; + /** */ + public void testTrivial2() throws Exception { + String sqlQry = "select {fn test()} from table;"; + String expRes = "select test() from table;"; - actualRes = OdbcEscapeSequenceUtils.parse(sqlQry); + String actualRes = OdbcParser.parse(sqlQry); assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes); } - /** */ - 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;"; + public void testTrivial3() throws Exception { + String sqlQry = "select {fn test()}"; + String expRes = "select test()"; - String actualRes = OdbcEscapeSequenceUtils.parse(sqlQry); + 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)"; + /** */ + public void testTrivial4() throws Exception { + String sqlQry = "{fn test()}"; + String expRes = "test()"; - actualRes = OdbcEscapeSequenceUtils.parse(sqlQry); + String actualRes = OdbcParser.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;"; + 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 = OdbcEscapeSequenceUtils.parse(sqlQry); + String 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)}"; + String expRes = "select func(field1), func(field2)"; - sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)}"; - expRes = "select func1(field1, func2(field2), field3)"; - - actualRes = OdbcEscapeSequenceUtils.parse(sqlQry); + String actualRes = OdbcParser.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;"; - - String actualRes = OdbcEscapeSequenceUtils.parse(sqlQry); + public void testSimpleFunction3() throws Exception { + String sqlQry = "{fn func(field1)} {fn func(field2)}"; + String expRes = "func(field1) func(field2)"; - fail("Scalar function escape sequence parsing should failed"); + String actualRes = OdbcParser.parse(sqlQry); - return null; - } - }, IllegalStateException.class, null); + assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes); } /** */ - 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;"; + 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;"; - OdbcEscapeSequenceUtils.parse(sqlQry); + String actualRes = OdbcParser.parse(sqlQry); - fail("Scalar function escape sequence parsing should failed"); + assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes); + } - return null; - } - }, IllegalStateException.class, null); + /** */ + public void testNestedFunction2() throws Exception { + String sqlQry = "select {fn func1(field1, {fn func2(field2)}, field3)}"; + String expRes = "select func1(field1, func2(field2), field3)"; + + String actualRes = OdbcParser.parse(sqlQry); + + assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes); } /** */ - public void testTrivial2() throws Exception { - String sqlQry = "{fn test()}"; - String expRes = "test()"; + public void testDeepNestedFunction() throws Exception { + String sqlQry = "select {fn func1(field1, {fn func2({fn func3(field2)}, field3)})} from SomeTable;"; + String expRes = "select func1(field1, func2(func3(field2), field3)) from SomeTable;"; String actualRes = OdbcParser.parse(sqlQry); assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes); + } - sqlQry = "select * from table;"; - expRes = "select * from table;"; + /** */ + public void testDeepNestedFunction2() throws Exception { + String sqlQry = "select {fn func1(field1, {fn func2({fn func3(field2)}, field3)})}"; + String expRes = "select func1(field1, func2(func3(field2), field3))"; - actualRes = OdbcParser.parse(sqlQry); + String 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;"; + public void testDeepNestedFunction3() throws Exception { + String sqlQry = "{fn func1({fn func2({fn func3(field1)})})}"; + String expRes = "func1(func2(func3(field1)))"; 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)"; + /** */ + public void testNestedFunctionMixed() throws Exception { + String sqlQry = "select {fn func1({fn func2(field1)}, {fn func3(field2)})} from table;"; + String expRes = "select func1(func2(field1), func3(field2)) from table;"; - actualRes = OdbcParser.parse(sqlQry); + String 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;"; + public void testNestedFunctionMixed1() throws Exception { + String sqlQry = "{fn func1({fn func2(field1)}, {fn func3(field2)})}"; + String expRes = "func1(func2(field1), func3(field2))"; 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)"; + /** */ + public void testNestedFunctionMixed2() throws Exception { + String sqlQry = "{fn func1({fn func2({fn func3(field1)})})} {fn func1({fn func2(field2)})}"; + String expRes = "func1(func2(func3(field1))) func1(func2(field2))"; - actualRes = OdbcParser.parse(sqlQry); + String actualRes = OdbcParser.parse(sqlQry); assertEquals("Scalar function escape sequence parsing fails", expRes, actualRes); } /** */ - public void testFailedOnNotClosedSequence2() throws Exception { + 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;"; @@ -176,7 +191,7 @@ public class OdbcScalarFunctionEscapeSequenceTest extends TestCase { } /** */ - public void testFailedOnClosingNotOpenedSequence2() throws Exception { + 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;";
