#1150 - Refactor convert RawSql and RawSqlBuilder into interfaces and push the parsers into io.ebeaninternal

This commit is contained in:
rob bygrave
2017-10-04 23:03:12 +13:00
parent 5a5cb7ffbd
commit f02a552cdf
33 changed files with 994 additions and 906 deletions
@@ -0,0 +1,65 @@
package io.ebeaninternal.server.rawsql;
import org.junit.Test;
import java.util.Arrays;
import static org.assertj.core.api.StrictAssertions.assertThat;
public class ColumnMappingTest {
SpiRawSql.ColumnMapping.Column col(int indexPos, String dbColumn, String dbAlias) {
return new SpiRawSql.ColumnMapping.Column(indexPos, dbColumn, dbAlias);
}
SpiRawSql.ColumnMapping mapping(SpiRawSql.ColumnMapping.Column... cols) {
return new SpiRawSql.ColumnMapping(Arrays.asList(cols));
}
@Test
public void equals_same() {
SpiRawSql.ColumnMapping mapping1 = mapping(col(1, "id", null), col(2, "name", null));
SpiRawSql.ColumnMapping mapping2 = mapping(col(1, "id", null), col(2, "name", null));
assertSame(mapping1, mapping2);
}
@Test
public void equals_diffPropertyName() {
SpiRawSql.ColumnMapping mapping1 = mapping(col(1, "id", null), col(2, "name", null));
SpiRawSql.ColumnMapping mapping2 = mapping(col(1, "id", null), col(2, "diff", null));
assertDifferent(mapping1, mapping2);
}
@Test
public void equals_moreColumns() {
SpiRawSql.ColumnMapping mapping1 = mapping(col(1, "id", null), col(2, "name", null));
SpiRawSql.ColumnMapping mapping2 = mapping(col(1, "id", null), col(2, "name", null), col(2, "diff", null));
assertDifferent(mapping1, mapping2);
}
@Test
public void equals_lessColumns() {
SpiRawSql.ColumnMapping mapping1 = mapping(col(1, "id", null), col(2, "name", null));
SpiRawSql.ColumnMapping mapping2 = mapping(col(1, "id", null));
assertDifferent(mapping1, mapping2);
}
private void assertSame(Object key, Object key1) {
assertThat(key).isEqualTo(key1);
assertThat(key.hashCode()).isEqualTo(key1.hashCode());
}
private void assertDifferent(Object key, Object key1) {
assertThat(key).isNotEqualTo(key1);
assertThat(key.hashCode()).isNotEqualTo(key1.hashCode());
}
}
@@ -0,0 +1,74 @@
package io.ebeaninternal.server.rawsql;
import io.ebean.RawSql;
import io.ebean.RawSqlBuilder;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class RawSqlKeyTest {
private SpiRawSql.Key key(String sqlStatement) {
return ((SpiRawSql) RawSqlBuilder.parse(sqlStatement).create()).getKey();
}
private SpiRawSql.Key key(RawSql rawSql) {
return ((SpiRawSql)rawSql).getKey();
}
@Test
public void equals_when_sameParsedSql() {
SpiRawSql.Key key = key("select id from customer");
SpiRawSql.Key key1 = key("select id from customer");
assertSame(key, key1);
}
@Test
public void equals_when_diffParsedSql() {
SpiRawSql.Key key = key("select id from customer");
SpiRawSql.Key key1 = key("select name from customer");
assertDifferent(key, key1);
}
@Test
public void equals_when_sameColumnMapping() {
SpiRawSql.Key key = key(RawSqlBuilder.parse("select id from customer").columnMapping("id", "b").create());
SpiRawSql.Key key1 = key(RawSqlBuilder.parse("select id from customer").columnMapping("id", "b").create());
assertSame(key, key1);
}
@Test
public void equals_when_diffColumnMapping() {
SpiRawSql.Key key = key(RawSqlBuilder.parse("select a from customer").columnMapping("a", "b").create());
SpiRawSql.Key key1 = key(RawSqlBuilder.parse("select a from customer").columnMapping("a", "c").create());
assertDifferent(key, key1);
}
@Test
public void equals_when_parseToUnpased() {
SpiRawSql.Key key = key(RawSqlBuilder.parse("select a from customer").columnMapping("a", "b").create());
SpiRawSql.Key key1 = key(RawSqlBuilder.unparsed("select a from customer").columnMapping("a", "c").create());
assertDifferent(key, key1);
}
private void assertSame(SpiRawSql.Key key, SpiRawSql.Key key1) {
assertThat(key).isEqualTo(key1);
assertThat(key.hashCode()).isEqualTo(key1.hashCode());
}
private void assertDifferent(SpiRawSql.Key key, SpiRawSql.Key key1) {
assertThat(key).isNotEqualTo(key1);
assertThat(key.hashCode()).isNotEqualTo(key1.hashCode());
}
}
@@ -0,0 +1,241 @@
package io.ebeaninternal.server.rawsql;
import io.ebean.BaseTestCase;
import io.ebean.Ebean;
import io.ebean.Query;
import io.ebean.RawSql;
import io.ebean.RawSqlBuilder;
import io.ebeaninternal.server.rawsql.SpiRawSql.Sql;
import org.assertj.core.api.StrictAssertions;
import org.tests.model.basic.Customer;
import org.tests.model.basic.ResetBasicData;
import org.tests.model.rawsql.ERawSqlAggBean;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
public class TestRawSqlBuilder extends BaseTestCase {
@Test
public void testDeriveProperty() {
StrictAssertions.assertThat(SpiRawSql.ColumnMapping.Column.derivePropertyName("item_total", "some_other")).isEqualTo("itemTotal");
assertThat(SpiRawSql.ColumnMapping.Column.derivePropertyName(null, "some_other")).isEqualTo("someOther");
assertThat(SpiRawSql.ColumnMapping.Column.derivePropertyName(null, "alias.some_other")).isEqualTo("someOther");
assertThat(SpiRawSql.ColumnMapping.Column.derivePropertyName(null, "alias.someOther")).isEqualTo("someOther");
assertThat(SpiRawSql.ColumnMapping.Column.derivePropertyName(null, "some")).isEqualTo("some");
assertThat(SpiRawSql.ColumnMapping.Column.derivePropertyName(null, "someOther")).isEqualTo("someOther");
}
private Sql getSql(String sqlStatement) {
RawSql r = RawSqlBuilder.parse(sqlStatement).create();
return ((SpiRawSql)r).getSql();
}
@Test
public void testSimple() {
Sql sql = getSql("select id from t_cust");
assertEquals("id", sql.getPreFrom());
assertEquals("from t_cust", sql.getPreWhere());
assertEquals("", sql.getPreHaving());
assertNull(sql.getOrderBy());
}
@Test
public void testWithNewLineCharacters() {
Sql sql = getSql("select\n id from\n o_customer");
assertEquals("id", sql.getPreFrom());
assertEquals("from o_customer", sql.getPreWhere());
assertEquals("", sql.getPreHaving());
assertNull(sql.getOrderBy());
ResetBasicData.reset();
RawSql rawSql = RawSqlBuilder.parse("select\n id from\n o_customer").create();
Ebean.find(Customer.class)
.setRawSql(rawSql)
.findList();
}
@Test
public void testWithWhere() {
Sql sql = getSql("select id from t_cust where id > ?");
assertEquals("id", sql.getPreFrom());
assertEquals("from t_cust where id > ?", sql.getPreWhere());
assertEquals("", sql.getPreHaving());
assertNull(sql.getOrderBy());
}
@Test
public void testWithOrder() {
Sql sql = getSql("select id from t_cust where id > ? order by id desc");
assertEquals("id", sql.getPreFrom());
assertEquals("from t_cust where id > ?", sql.getPreWhere());
assertEquals("", sql.getPreHaving());
assertEquals("order by", sql.getOrderByPrefix());
assertEquals("id desc", sql.getOrderBy());
sql = getSql("select id from t_cust order by id desc");
assertEquals("id", sql.getPreFrom());
assertEquals("from t_cust", sql.getPreWhere());
assertEquals("", sql.getPreHaving());
assertEquals("id desc", sql.getOrderBy());
sql = getSql("select id, sum(x) from t_cust where id > ? group by id order by id desc");
assertEquals("id, sum(x)", sql.getPreFrom());
assertEquals("from t_cust where id > ?", sql.getPreWhere());
assertEquals("group by id", sql.getPreHaving());
assertEquals("id desc", sql.getOrderBy());
}
@Test
public void testWithHaving() {
Sql sql = getSql("select id, sum(x) from t_cust where id > ? group by id having sum(x) > ? order by id desc");
assertEquals("id, sum(x)", sql.getPreFrom());
assertEquals("from t_cust where id > ?", sql.getPreWhere());
assertEquals("group by id having sum(x) > ?", sql.getPreHaving());
assertEquals("order by", sql.getOrderByPrefix());
assertEquals("id desc", sql.getOrderBy());
// no where
sql = getSql("select id, sum(x) from t_cust group by id having sum(x) > ? order by id desc");
assertEquals("id, sum(x)", sql.getPreFrom());
assertEquals("from t_cust", sql.getPreWhere());
assertEquals("group by id having sum(x) > ?", sql.getPreHaving());
assertEquals("order by", sql.getOrderByPrefix());
assertEquals("id desc", sql.getOrderBy());
// no where, no order by
sql = getSql("select id, sum(x) from t_cust group by id having sum(x) > ?");
assertEquals("id, sum(x)", sql.getPreFrom());
assertEquals("from t_cust", sql.getPreWhere());
assertEquals("group by id having sum(x) > ?", sql.getPreHaving());
assertNull(sql.getOrderBy());
assertEquals("order by", sql.getOrderByPrefix());
// no order by
sql = getSql("select id, sum(x) from t_cust where id > ? group by id having sum(x) > ?");
assertEquals("id, sum(x)", sql.getPreFrom());
assertEquals("from t_cust where id > ?", sql.getPreWhere());
assertEquals("group by id having sum(x) > ?", sql.getPreHaving());
assertNull(sql.getOrderBy());
assertEquals("order by", sql.getOrderByPrefix());
}
/**
* test support for order siblings by ... Oracle syntax.
*/
@Test
public void testWithOrderSiblingsByName() {
String s = "SELECT ID, DESCRIPTION, NAME, PARENT_ID FROM SOME_TABLE WHERE lower(NAME) like :name START WITH ID = :parentId CONNECT BY PRIOR ID = PARENT_ID order siblings by NAME";
Sql sql = getSql(s);
assertEquals("ID, DESCRIPTION, NAME, PARENT_ID", sql.getPreFrom());
assertEquals("order siblings by", sql.getOrderByPrefix());
assertEquals("NAME", sql.getOrderBy());
assertEquals("FROM SOME_TABLE WHERE lower(NAME) like :name START WITH ID = :parentId CONNECT BY PRIOR ID = PARENT_ID", sql.getPreWhere());
}
@Test
public void testWithAlias() {
String rs = "select o.id, o.status, c.id, c.name, " +
" d.id, d.order_qty, p.id, p.name " +
"from o_order o join o_customer c on c.id = o.kcustomer_id " +
"join o_order_detail d on d.order_id = o.id " +
"join o_product p on p.id = d.product_id " +
"where o.id <= :maxOrderId and p.id = :productId " +
"order by o.id, d.id asc";
SpiRawSql rawSql = (SpiRawSql)RawSqlBuilder.parse(rs)
.tableAliasMapping("c", "customer")
.tableAliasMapping("d", "details")
.tableAliasMapping("p", "details.product")
.create();
SpiRawSql.ColumnMapping columnMapping = rawSql.getColumnMapping();
assertEquals(0, columnMapping.getIndexPosition("id"));
assertEquals(1, columnMapping.getIndexPosition("status"));
assertEquals(2, columnMapping.getIndexPosition("customer.id"));
assertEquals(3, columnMapping.getIndexPosition("customer.name"));
assertEquals(4, columnMapping.getIndexPosition("details.id"));
assertEquals(5, columnMapping.getIndexPosition("details.orderQty"));
assertEquals(6, columnMapping.getIndexPosition("details.product.id"));
assertEquals(7, columnMapping.getIndexPosition("details.product.name"));
}
@Test
public void testWithCoalesceFunction() {
String rs = "select id, coalesce(status,'E') as status, " +
" budgets.amount as budget," +
" COALESCE(month_sums.sum,0.0) as transaction_sum, " +
" COALESCE(month_balances.balance,0.0) as balance, " +
" COALESCE(month_sums.end_date,date_trunc('month',budgets.month),month_balances.end_date) as data_month" +
" from o_order order by id asc";
RawSqlBuilder builder = RawSqlBuilder.parse(rs);
SpiRawSql rawSql = (SpiRawSql)builder.create();
SpiRawSql.ColumnMapping columnMapping = rawSql.getColumnMapping();
assertEquals(0, columnMapping.getIndexPosition("id"));
assertEquals(1, columnMapping.getIndexPosition("status"));
assertEquals(2, columnMapping.getIndexPosition("budget"));
assertEquals(3, columnMapping.getIndexPosition("transactionSum"));
assertEquals(4, columnMapping.getIndexPosition("balance"));
assertEquals(5, columnMapping.getIndexPosition("dataMonth"));
}
@Test
public void postgres_parse_withDateTruncCaseHaving() {
if (!isPostgres()) {
return;
}
ResetBasicData.reset();
String sql = "select DATE_TRUNC('DAY', d.order_date) as day," +
" count(*) as total," +
" sum(case when d.status = 0 then 2 else 3 end) as scheduled," +
" sum(case when d.status = 1 then 1 else 0 end) as completed" +
" from o_order d" +
" group by DATE_TRUNC('DAY', d.order_date)";
SpiRawSql rawSql = (SpiRawSql)RawSqlBuilder.parse(sql).create();
SpiRawSql.ColumnMapping columnMapping = rawSql.getColumnMapping();
assertEquals(0, columnMapping.getIndexPosition("day"));
assertEquals(1, columnMapping.getIndexPosition("total"));
assertEquals(2, columnMapping.getIndexPosition("scheduled"));
assertEquals(3, columnMapping.getIndexPosition("completed"));
Query<ERawSqlAggBean> query = Ebean.find(ERawSqlAggBean.class)
.setRawSql(rawSql)
.having().gt("total", 2)
.query();
query.findList();
String fullSql = query.getGeneratedSql();
assertThat(fullSql).contains(" having count(*) > ?");
}
}
@@ -0,0 +1,22 @@
package io.ebeaninternal.server.rawsql;
import io.ebean.RawSql;
import io.ebean.RawSqlBuilder;
import io.ebeaninternal.server.rawsql.SpiRawSql.Sql;
import junit.framework.TestCase;
import org.junit.Assert;
public class TestRawSqlBuilderDistinct extends TestCase {
public void testDistinct() {
RawSql r = RawSqlBuilder.parse("select distinct id, name from t_cust").create();
Sql sql = ((SpiRawSql)r).getSql();
Assert.assertEquals("id, name", sql.getPreFrom());
Assert.assertEquals("from t_cust", sql.getPreWhere());
Assert.assertEquals("", sql.getPreHaving());
Assert.assertNull(sql.getOrderBy());
}
}
@@ -0,0 +1,163 @@
package io.ebeaninternal.server.rawsql;
import io.ebeaninternal.server.rawsql.SpiRawSql.ColumnMapping;
import io.ebeaninternal.server.rawsql.SpiRawSql.ColumnMapping.Column;
import junit.framework.TestCase;
import java.util.Map;
public class TestRawSqlColumnParsing extends TestCase {
public void test_simple() {
ColumnMapping columnMapping = DRawSqlColumnsParser.parse("a,b,c");
Map<String, Column> mapping = columnMapping.mapping();
Column c = mapping.get("a");
assertEquals("a", c.getDbColumn());
assertEquals(0, c.getIndexPos());
assertEquals("a", c.getPropertyName());
c = mapping.get("b");
assertEquals("b", c.getDbColumn());
assertEquals(1, c.getIndexPos());
assertEquals("b", c.getPropertyName());
c = mapping.get("c");
assertEquals("c", c.getDbColumn());
assertEquals(2, c.getIndexPos());
assertEquals("c", c.getPropertyName());
}
public void test_simpleWithSpacing() {
ColumnMapping columnMapping = DRawSqlColumnsParser.parse(" a , b , c ");
Map<String, Column> mapping = columnMapping.mapping();
Column c = mapping.get("a");
assertEquals("a", c.getDbColumn());
assertEquals(0, c.getIndexPos());
assertEquals("a", c.getPropertyName());
c = mapping.get("b");
assertEquals("b", c.getDbColumn());
assertEquals(1, c.getIndexPos());
assertEquals("b", c.getPropertyName());
c = mapping.get("c");
assertEquals("c", c.getDbColumn());
assertEquals(2, c.getIndexPos());
assertEquals("c", c.getPropertyName());
}
public void test_withAlias() {
ColumnMapping columnMapping = DRawSqlColumnsParser.parse("a a0,b b1, c c2 , d d3 , e e4 ");
Map<String, Column> mapping = columnMapping.mapping();
assertEquals(5, mapping.size());
Column c = mapping.get("a0");
assertEquals("a", c.getDbColumn());
assertEquals(0, c.getIndexPos());
assertEquals("a0", c.getPropertyName());
c = mapping.get("b1");
assertEquals("b", c.getDbColumn());
assertEquals(1, c.getIndexPos());
assertEquals("b1", c.getPropertyName());
c = mapping.get("c2");
assertEquals("c", c.getDbColumn());
assertEquals(2, c.getIndexPos());
assertEquals("c2", c.getPropertyName());
c = mapping.get("d3");
assertEquals("d", c.getDbColumn());
assertEquals(3, c.getIndexPos());
assertEquals("d3", c.getPropertyName());
c = mapping.get("e4");
assertEquals("e", c.getDbColumn());
assertEquals(4, c.getIndexPos());
assertEquals("e4", c.getPropertyName());
}
public void test_withDatabaseFunction() {
ColumnMapping columnMapping = DRawSqlColumnsParser.parse("a a0,b b1, MONTH(MAKEDATE(2015, 241)) m2 , d d3 , e e4 ");
Map<String, Column> mapping = columnMapping.mapping();
assertEquals(5, mapping.size());
Column c = mapping.get("a0");
assertEquals("a", c.getDbColumn());
assertEquals(0, c.getIndexPos());
assertEquals("a0", c.getPropertyName());
c = mapping.get("b1");
assertEquals("b", c.getDbColumn());
assertEquals(1, c.getIndexPos());
assertEquals("b1", c.getPropertyName());
c = mapping.get("m2");
assertEquals("MONTH(MAKEDATE(2015, 241))", c.getDbColumn());
assertEquals(2, c.getIndexPos());
assertEquals("m2", c.getPropertyName());
c = mapping.get("d3");
assertEquals("d", c.getDbColumn());
assertEquals(3, c.getIndexPos());
assertEquals("d3", c.getPropertyName());
c = mapping.get("e4");
assertEquals("e", c.getDbColumn());
assertEquals(4, c.getIndexPos());
assertEquals("e4", c.getPropertyName());
}
public void test_withAsAlias() {
ColumnMapping columnMapping = DRawSqlColumnsParser.parse("a as a0,'b' b1, \"c(blah)\" as c2 , d as d3 , e as e4 ");
Map<String, Column> mapping = columnMapping.mapping();
assertEquals(5, mapping.size());
Column c = mapping.get("a0");
assertEquals("a", c.getDbColumn());
assertEquals(0, c.getIndexPos());
assertEquals("a0", c.getPropertyName());
c = mapping.get("b1");
assertEquals("'b'", c.getDbColumn());
assertEquals(1, c.getIndexPos());
assertEquals("b1", c.getPropertyName());
c = mapping.get("c2");
assertEquals("\"c(blah)\"", c.getDbColumn());
assertEquals(2, c.getIndexPos());
assertEquals("c2", c.getPropertyName());
c = mapping.get("d3");
assertEquals("d", c.getDbColumn());
assertEquals(3, c.getIndexPos());
assertEquals("d3", c.getPropertyName());
c = mapping.get("e4");
assertEquals("e", c.getDbColumn());
assertEquals(4, c.getIndexPos());
assertEquals("e4", c.getPropertyName());
}
}
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.rawsql;
import io.ebean.RawSql;
import io.ebean.RawSql.Sql;
import io.ebeaninternal.server.rawsql.SpiRawSql.Sql;
import io.ebean.RawSqlBuilder;
import junit.framework.TestCase;
@@ -20,7 +20,7 @@ public class TestRawSqlParsing extends TestCase {
//.columnMapping("sum(order_qty*unit_price)","totalAmount")
.create();
Sql rs = rawSql.getSql();
Sql rs = ((SpiRawSql)rawSql).getSql();
String s = rs.toString();
assertTrue(s, s.contains("[order_id, sum"));