From 42f9e74d91a63a95e07be71ba0dc4e7b7620c59b Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Thu, 20 Sep 2018 23:12:26 +1200 Subject: [PATCH] #1483 - Invalid SQL with allQuotedIdentifiers true - where t0.[t0.[COND]] in (?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) --- .../server/deploy/DeployParser.java | 8 ++++-- .../deploy/DeployPropertyParserTest.java | 13 ++++++++++ .../org/tests/model/basic/BWithQIdent.java | 12 ++++++++- .../TestQuotedIdentifierQuery.java | 26 +++++++++++++++++++ 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 src/test/java/org/tests/quotedidentifier/TestQuotedIdentifierQuery.java diff --git a/src/main/java/io/ebeaninternal/server/deploy/DeployParser.java b/src/main/java/io/ebeaninternal/server/deploy/DeployParser.java index 75f0a3b1a..a5e71183e 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/DeployParser.java +++ b/src/main/java/io/ebeaninternal/server/deploy/DeployParser.java @@ -22,6 +22,10 @@ public abstract class DeployParser { */ protected static final char UNDERSCORE = '_'; + protected static final char OPEN_SQUARE_BRACKET = '['; + protected static final char CLOSE_SQUARE_BRACKET = ']'; + protected static final char DOUBLE_QUOTE = '\"'; + /** * Used to determine when a column name terminates. */ @@ -183,10 +187,10 @@ public abstract class DeployParser { wordBuffer.append(ch); return false; } - return Character.isLetterOrDigit(ch) || ch == UNDERSCORE || ch == PERIOD; + return Character.isLetterOrDigit(ch) || ch == UNDERSCORE || ch == PERIOD || ch == DOUBLE_QUOTE || ch == CLOSE_SQUARE_BRACKET; } private boolean isWordStart(char ch) { - return Character.isLetter(ch) || ch == UNDERSCORE; + return Character.isLetter(ch) || ch == UNDERSCORE || ch == DOUBLE_QUOTE || ch == OPEN_SQUARE_BRACKET; } } diff --git a/src/test/java/io/ebeaninternal/server/deploy/DeployPropertyParserTest.java b/src/test/java/io/ebeaninternal/server/deploy/DeployPropertyParserTest.java index 10056984e..1c387aa49 100644 --- a/src/test/java/io/ebeaninternal/server/deploy/DeployPropertyParserTest.java +++ b/src/test/java/io/ebeaninternal/server/deploy/DeployPropertyParserTest.java @@ -3,6 +3,7 @@ package io.ebeaninternal.server.deploy; import io.ebean.BaseTestCase; import org.junit.Test; import org.tests.model.basic.Address; +import org.tests.model.basic.BWithQIdent; import org.tests.model.basic.Customer; import static org.assertj.core.api.Assertions.assertThat; @@ -14,6 +15,8 @@ public class DeployPropertyParserTest extends BaseTestCase { private final BeanDescriptor
addressBeanDescriptor = getBeanDescriptor(Address.class); + private final BeanDescriptor bWithQIdentDescriptor = getBeanDescriptor(BWithQIdent.class); + @Test public void from_prefix_expect_unchanged() { assertThat(parser().parse("(select x from status join status)")).isEqualTo("(select x from status join status)"); @@ -49,6 +52,12 @@ public class DeployPropertyParserTest extends BaseTestCase { assertThat(addressParser().parse("concat(line1, line2, '-EA')")).isEqualTo("concat(${}line_1, ${}line_2, '-EA')"); } + @Test + public void withQuote_when_match() { + assertThat(withQuoteParser().parse("name like ?")).isEqualTo("${}\"Name\" like ?"); + assertThat(withQuoteParser().parse("t0.\"CODE\" like ?")).isEqualTo("t0.\"CODE\" like ?"); + } + @Test public void unknown_path() { assertThat(parser().parse(" foo ")).isEqualTo(" foo "); @@ -62,4 +71,8 @@ public class DeployPropertyParserTest extends BaseTestCase { return addressBeanDescriptor.parser(); } + private DeployPropertyParser withQuoteParser() { + return bWithQIdentDescriptor.parser(); + } + } diff --git a/src/test/java/org/tests/model/basic/BWithQIdent.java b/src/test/java/org/tests/model/basic/BWithQIdent.java index 329d40f41..fcb91cdb3 100644 --- a/src/test/java/org/tests/model/basic/BWithQIdent.java +++ b/src/test/java/org/tests/model/basic/BWithQIdent.java @@ -5,7 +5,6 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Version; import javax.validation.constraints.Size; - import java.sql.Timestamp; @Entity @@ -18,6 +17,9 @@ public class BWithQIdent { @Size(max = 191) // key must not exceed 767 Bytes, so max key len for mysql with utf8mb4 = 191*4 = 764 bytes String name; + @Column(name = "`CODE`") + String CODE; + @Version Timestamp lastUpdated; @@ -37,6 +39,14 @@ public class BWithQIdent { this.name = name; } + public String getCODE() { + return CODE; + } + + public void setCODE(String CODE) { + this.CODE = CODE; + } + public Timestamp getLastUpdated() { return lastUpdated; } diff --git a/src/test/java/org/tests/quotedidentifier/TestQuotedIdentifierQuery.java b/src/test/java/org/tests/quotedidentifier/TestQuotedIdentifierQuery.java new file mode 100644 index 000000000..90f6b3be8 --- /dev/null +++ b/src/test/java/org/tests/quotedidentifier/TestQuotedIdentifierQuery.java @@ -0,0 +1,26 @@ +package org.tests.quotedidentifier; + +import io.ebean.BaseTestCase; +import io.ebean.Ebean; +import org.junit.Test; +import org.tests.model.basic.BWithQIdent; + +public class TestQuotedIdentifierQuery extends BaseTestCase { + + @Test + public void test() { + + BWithQIdent bean = new BWithQIdent(); + bean.setName("foo"); + bean.setCODE("bar"); + + Ebean.save(bean); + + Ebean.find(BWithQIdent.class) + .where() + .eq("name", "foo") + .raw("t0.\"Name\" = ?", "foo") + .raw("t0.\"CODE\" = ?", "bar") + .findList(); + } +}