package io.ebeaninternal.server.grammer; import io.ebean.BaseTestCase; import io.ebean.Ebean; import io.ebean.Query; import io.ebean.annotation.ForPlatform; import io.ebean.annotation.IgnorePlatform; import io.ebean.annotation.Platform; import io.ebeaninternal.api.SpiQuery; import org.junit.Test; import org.tests.model.basic.Customer; import org.tests.model.basic.ResetBasicData; import java.util.Arrays; import java.util.List; import javax.xml.ws.RequestWrapper; import static org.assertj.core.api.Assertions.assertThat; public class EqlParserTest extends BaseTestCase { @Test(expected = IllegalArgumentException.class) public void illegal_syntax() { parse("find Article where name = :p0"); } @Test public void where_eq() { Query query = parse("where name eq 'Rob'"); query.findList(); assertThat(query.getGeneratedSql()).contains("where t0.name = ?"); } @Test public void where_eq_reverse() { Query query = parse("where 'Rob' eq name"); query.findList(); assertThat(query.getGeneratedSql()).contains("where t0.name = ?"); } @Test public void where_gt_reverse() { Query query = parse("where 'Rob' > name"); query.findList(); assertThat(query.getGeneratedSql()).contains("where t0.name < ?"); } @Test public void where_gte_reverse() { Query query = parse("where 'Rob' >= name"); query.findList(); assertThat(query.getGeneratedSql()).contains("where t0.name <= ?"); } @Test public void where_lt_reverse() { Query query = parse("where 'Rob' < name"); query.findList(); assertThat(query.getGeneratedSql()).contains("where t0.name > ?"); } @Test public void where_lte_reverse() { Query query = parse("where 'Rob' <= name"); query.findList(); assertThat(query.getGeneratedSql()).contains("where t0.name >= ?"); } @Test public void where_ieq() { Query query = parse("where name ieq 'Rob'"); query.findList(); assertThat(query.getGeneratedSql()).contains("where lower(t0.name) =?"); } @Test public void where_ieq_reverse() { Query query = parse("where 'Rob' ieq name"); query.findList(); assertThat(query.getGeneratedSql()).contains("where lower(t0.name) =?"); } @Test public void where_eq2() { Query query = parse("where name = 'Rob'"); query.findList(); assertThat(query.getGeneratedSql()).contains("where t0.name = ?"); } @Test public void where_namedParam() { Query query = parse("where name eq :name"); query.setParameter("name", "Rob"); query.findList(); assertThat(query.getGeneratedSql()).contains("where t0.name = ?"); } @Test public void where_namedParam_otherOrder() { Query query = parse("where :nm < name"); query.setParameter("nm", "Rob"); query.findList(); assertThat(query.getGeneratedSql()).contains("where t0.name > ?"); } @Test public void where_namedParam_startsWith() { Query query = parse("where name startsWith :name"); query.setParameter("name", "Rob"); query.findList(); assertThat(query.getGeneratedSql()).contains("where t0.name like "); } @Test @IgnorePlatform(Platform.HANA) // The HANA JDBC driver checks the field length on binding and rejects 'NEW' public void where_or1() { Query query = parse("where name = 'Rob' or (status = 'NEW' and smallnote is null)"); query.findList(); assertThat(query.getGeneratedSql()).contains("where (t0.name = ? or (t0.status = ? and t0.smallnote is null ) )"); } @Test @ForPlatform(Platform.HANA) public void where_or1_hana() { Query query = parse("where name = 'Rob' or (status = 'N' and smallnote is null)"); query.findList(); assertThat(query.getGeneratedSql()).contains("where (t0.name = ? or (t0.status = ? and t0.smallnote is null ) )"); } @Test @IgnorePlatform(Platform.HANA) // The HANA JDBC driver checks the field length on binding and rejects 'NEW' public void where_or2() { Query query = parse("where (name = 'Rob' or status = 'NEW') and smallnote is null"); query.findList(); assertThat(query.getGeneratedSql()).contains("where ((t0.name = ? or t0.status = ? ) and t0.smallnote is null )"); } @Test @ForPlatform(Platform.HANA) public void where_or2_hana() { Query query = parse("where (name = 'Rob' or status = 'N') and smallnote is null"); query.findList(); assertThat(query.getGeneratedSql()).contains("where ((t0.name = ? or t0.status = ? ) and t0.smallnote is null )"); } @Test @IgnorePlatform(Platform.HANA) // The HANA JDBC driver checks the field length on binding and rejects 'NEW' public void test_simplifyExpressions() { Query query = parse("where not (name = 'Rob' and status = 'NEW')"); query.findList(); assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ? )"); query = parse("where not ((name = 'Rob' and status = 'NEW'))"); query.findList(); assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ? )"); query = parse("where not (((name = 'Rob') and (status = 'NEW')))"); query.findList(); assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ? )"); } @Test @ForPlatform(Platform.HANA) public void test_simplifyExpressions_hana() { Query query = parse("where not (name = 'Rob' and status = 'N')"); query.findList(); assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ? )"); query = parse("where not ((name = 'Rob' and status = 'N'))"); query.findList(); assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ? )"); query = parse("where not (((name = 'Rob') and (status = 'N')))"); query.findList(); assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ? )"); } @Test public void where_in() { Query query = parse("where name in ('Rob','Jim')"); query.findList(); platformAssertIn(query.getGeneratedSql(),"where t0.name"); } @Test public void where_in_when_namedParams() { Query query = parse("where name in (:one, :two)"); query.setParameter("one", "Foo"); query.setParameter("two", "Bar"); query.findList(); platformAssertIn(query.getGeneratedSql(),"where t0.name"); } @Test public void where_in_when_namedParams_withWhitespace() { Query query = parse("where name in (:one, :two)"); query.setParameter("one", "Foo"); query.setParameter("two", "Bar"); query.findList(); platformAssertIn(query.getGeneratedSql(),"where t0.name"); } @Test public void where_in_when_namedParams_withNoWhitespace() { Query query = parse("where name in (:one,:two)"); query.setParameter("one", "Foo"); query.setParameter("two", "Bar"); query.findList(); platformAssertIn(query.getGeneratedSql(),"where t0.name"); } @Test public void where_in_when_namedParamAsList() { Query query = parse("where name in (:names)"); query.setParameter("names", Arrays.asList("Baz", "Maz", "Jim")); query.findList(); platformAssertIn(query.getGeneratedSql(),"where t0.name"); } @Test public void where_between() { Query query = parse("where name between 'As' and 'B'"); query.findList(); assertThat(query.getGeneratedSql()).contains("where t0.name between ? and ? "); } @Test public void where_between_withNamedParams() { Query query = parse("where name between :one and :two"); query.setParameter("one", "a"); query.setParameter("two", "b"); query.findList(); assertThat(query.getGeneratedSql()).contains("where t0.name between ? and ? "); } @Test public void where_betweenProperty() { Query query = parse("where 'x' between name and smallnote"); query.findList(); assertThat(query.getGeneratedSql()).contains("where ? between t0.name and t0.smallnote"); } @Test public void where_betweenProperty_withNamed() { Query query = parse("where :some between name and smallnote"); query.setParameter("some", "A"); query.findList(); assertThat(query.getGeneratedSql()).contains("where ? between t0.name and t0.smallnote"); } @Test public void fetch_basic() { Query query = parse("fetch billingAddress"); query.findList(); assertThat(query.getGeneratedSql()).contains(", t1.id"); } @Test public void fetch_withProperty() { Query query = parse("fetch billingAddress (city)"); query.findList(); assertThat(sqlOf(query, 10)).contains(", t1.id, t1.city"); } @Test public void fetch_withProperty_noWhitespace() { Query query = parse("fetch billingAddress(city)"); query.findList(); assertThat(sqlOf(query, 10)).contains(", t1.id, t1.city"); } @Test public void fetch_basic_multiple() { Query query = parse("fetch billingAddress fetch shippingAddress"); query.findList(); assertThat(query.getGeneratedSql()).contains(", t1.city"); assertThat(query.getGeneratedSql()).contains(", t2.city"); } @Test public void fetch_basic_multiple_withProperties() { Query query = parse("fetch billingAddress (city) fetch shippingAddress (city)"); query.findList(); assertThat(sqlOf(query, 12)).contains(", t1.id, t1.city, t2.id, t2.city"); } @Test public void fetch_lazy() { Query query = parse("fetch lazy billingAddress"); query.findList(); assertThat(query.getGeneratedSql()).doesNotContain(", t1.city"); } @Test public void fetch_lazy50() { Query query = parse("fetch lazy(50) billingAddress"); query.findList(); assertThat(query.getGeneratedSql()).doesNotContain(", t1.city"); } @Test public void fetch_query50() { ResetBasicData.reset(); Query query = parse("fetch query(50) billingAddress"); query.findList(); assertThat(query.getGeneratedSql()).doesNotContain(", t1.city"); } @Test public void fetch_query50_asHint() { ResetBasicData.reset(); Query query = parse("fetch billingAddress (+query(50),city)"); query.findList(); assertThat(query.getGeneratedSql()).doesNotContain(", t1.city"); } @Test public void fetch_lazy50_asHint() { ResetBasicData.reset(); Query query = parse("fetch billingAddress (+lazy(50),city) order by id"); List list = query.findList(); assertThat(query.getGeneratedSql()).doesNotContain(", t1.city"); Customer customer = list.get(0); customer.getBillingAddress().getCity(); } @Test public void select() { ResetBasicData.reset(); Query query = parse("select (name)"); query.findList(); assertThat(sqlOf(query, 1)).contains("select t0.id, t0.name from o_customer t0"); } @Test public void selectDistinct() { ResetBasicData.reset(); Query query = parse("select distinct (name)"); query.findList(); assertThat(sqlOf(query, 1)).contains("select distinct t0.name from o_customer t0"); } @Test public void limit() { ResetBasicData.reset(); Query query = parse("limit 10"); query.findList(); if (isH2()) { assertThat(query.getGeneratedSql()).contains(" limit 10"); } } @Test public void limitOffset() { ResetBasicData.reset(); Query query = parse("limit 10 offset 5"); query.findList(); if (isH2()) { assertThat(query.getGeneratedSql()).contains(" limit 10 offset 5"); } } @Test public void orderBy() { ResetBasicData.reset(); Query query = parse("order by id"); query.findList(); if (isH2()) { assertThat(query.getGeneratedSql()).contains("from o_customer t0 order by t0.id"); } } @Test public void orderBy_desc() { ResetBasicData.reset(); Query query = parse("order by id desc"); query.findList(); if (isH2()) { assertThat(query.getGeneratedSql()).contains("from o_customer t0 order by t0.id desc"); } } @Test public void orderBy_nullsLast() { if (!isPlatformOrderNullsSupport()) { return; } ResetBasicData.reset(); Query query = parse("order by id desc nulls last"); query.findList(); if (isH2()) { assertThat(query.getGeneratedSql()).contains(" from o_customer t0 order by t0.id desc nulls last"); } } @Test public void orderBy_nullsFirst() { if (!isPlatformOrderNullsSupport()) { return; } ResetBasicData.reset(); Query query = parse("order by id nulls first"); query.findList(); if (isH2()) { assertThat(query.getGeneratedSql()).contains(" from o_customer t0 order by t0.id nulls first"); } } @Test public void orderBy_multiple() { if (!isPlatformOrderNullsSupport()) { return; } ResetBasicData.reset(); Query query = parse("order by billingAddress.city desc nulls last, name, id desc nulls last"); query.findList(); if (isH2()) { assertThat(query.getGeneratedSql()).contains(" order by t1.city desc nulls last, t0.name, t0.id desc nulls last"); } } private Query parse(String raw) { Query query = Ebean.find(Customer.class); EqlParser.parse(raw, (SpiQuery) query); return query; } }