diff --git a/common/src/main/java/org/opensearch/sql/common/utils/StringUtils.java b/common/src/main/java/org/opensearch/sql/common/utils/StringUtils.java index 2e5ef7803e..0699245338 100644 --- a/common/src/main/java/org/opensearch/sql/common/utils/StringUtils.java +++ b/common/src/main/java/org/opensearch/sql/common/utils/StringUtils.java @@ -27,16 +27,54 @@ public static String unquote(String text, String mark) { /** * Unquote Identifier which has " or ' or ` as mark. + * Strings quoted by ' or " with two of these quotes appearing next to each other in the quote + * acts as an escape + * Example: 'Test''s' will result in 'Test's', similar with those single quotes being replaced + * with double. * @param text string * @return An unquoted string whose outer pair of (single/double/back-tick) quotes have been * removed */ public static String unquoteText(String text) { - if (isQuoted(text, "\"") || isQuoted(text, "'") || isQuoted(text, "`")) { - return text.substring(1, text.length() - 1); + + if (text.length() < 2) { + return text; + } + + char enclosingQuote; + char firstChar = text.charAt(0); + char lastChar = text.charAt(text.length() - 1); + + if (firstChar == lastChar + && (firstChar == '\'' + || firstChar == '"' + || firstChar == '`')) { + enclosingQuote = firstChar; } else { return text; } + + if (enclosingQuote == '`') { + return text.substring(1, text.length() - 1); + } + + char currentChar; + char nextChar; + + StringBuilder textSB = new StringBuilder(); + + // Ignores first and last character as they are the quotes that should be removed + for (int chIndex = 1; chIndex < text.length() - 1; chIndex++) { + currentChar = text.charAt(chIndex); + nextChar = text.charAt(chIndex + 1); + if (currentChar == enclosingQuote + && nextChar == currentChar) { + chIndex++; + } + textSB.append(currentChar); + } + + return textSB.toString(); } /** diff --git a/core/src/test/java/org/opensearch/sql/common/utils/StringUtilsTest.java b/core/src/test/java/org/opensearch/sql/common/utils/StringUtilsTest.java new file mode 100644 index 0000000000..06ea404fc2 --- /dev/null +++ b/core/src/test/java/org/opensearch/sql/common/utils/StringUtilsTest.java @@ -0,0 +1,48 @@ +package org.opensearch.sql.common.utils; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.opensearch.sql.common.utils.StringUtils.unquoteText; + +import org.junit.jupiter.api.Test; + +class StringUtilsTest { + @Test + void unquoteTest() { + assertEquals("test", unquoteText("test")); + assertEquals("test", unquoteText("'test'")); + assertEquals("test", unquoteText("`test`")); + + assertEquals("test'", unquoteText("'test'''")); + assertEquals("test\"", unquoteText("\"test\"\"\"")); + + assertEquals("te``st", unquoteText("'te``st'")); + assertEquals("te``st", unquoteText("\"te``st\"")); + assertEquals("te``st", unquoteText("`te``st`")); + + assertEquals("te'st", unquoteText("'te''st'")); + assertEquals("te''st", unquoteText("\"te''st\"")); + assertEquals("te''st", unquoteText("`te''st`")); + + assertEquals("te\"\"st", unquoteText("'te\"\"st'")); + assertEquals("te\"st", unquoteText("\"te\"\"st\"")); + assertEquals("te\"\"st", unquoteText("`te\"\"st`")); + + assertEquals("''", unquoteText("''''''")); + assertEquals("\"\"", unquoteText("\"\"\"\"\"\"")); + assertEquals("````", unquoteText("``````")); + + assertEquals("test'", unquoteText("'test''")); + + assertEquals("", unquoteText("")); + assertEquals("'", unquoteText("'")); + assertEquals("`", unquoteText("`")); + assertEquals("\"", unquoteText("\"")); + + assertEquals("hello'", unquoteText("'hello''")); + assertEquals("don't", unquoteText("'don't'")); + assertEquals("hello`", unquoteText("`hello``")); + assertEquals("don\"t", unquoteText("\"don\"t\"")); + + } + +} diff --git a/integ-test/src/test/resources/correctness/expressions/literals.txt b/integ-test/src/test/resources/correctness/expressions/literals.txt index 39eedc28e7..c7dfcc8156 100644 --- a/integ-test/src/test/resources/correctness/expressions/literals.txt +++ b/integ-test/src/test/resources/correctness/expressions/literals.txt @@ -8,4 +8,7 @@ true 2147483647 -2147483648 2147483648 --2147483649 \ No newline at end of file +-2147483649 +'im' +'i''m' +'i""m'