Fix for #185 - RawSql parse not working with "order siblings by NAME"

This commit is contained in:
rbygrave
2014-12-17 21:03:53 +13:00
parent 15be5dd4c7
commit 43ecfe7c19
5 changed files with 53 additions and 16 deletions
@@ -16,8 +16,6 @@ class DRawSqlParser {
public static final String $_WHERE = "${where}";
private static final String ORDER_BY = "order by";
private final SimpleTextParser textParser;
private String sql;
@@ -35,6 +33,7 @@ class DRawSqlParser {
private int groupByPos = -1;
private int havingPos = -1;
private int orderByPos = -1;
private int orderByStmtPos = -1;
private boolean whereExprAnd;
private int whereExprPos = -1;
@@ -66,12 +65,12 @@ class DRawSqlParser {
String preFrom = removeWhitespace(findPreFromSql());
String preWhere = removeWhitespace(findPreWhereSql());
String preHaving = removeWhitespace(findPreHavingSql());
String orderByPrefix = findOrderByPrefixSql();
String orderBySql = findOrderBySql();
preFrom = trimSelectKeyword(preFrom);
return new Sql(sql.hashCode(), preFrom, preWhere, whereExprAnd, preHaving, havingExprAnd,
orderBySql, (distinctPos > -1));
return new Sql(sql.hashCode(), preFrom, preWhere, whereExprAnd, preHaving, havingExprAnd, orderByPrefix, orderBySql, (distinctPos > -1));
}
/**
@@ -142,12 +141,12 @@ class DRawSqlParser {
return preWhereExprSql;
}
private String findOrderByPrefixSql() {
return (orderByPos < 1) ? null : sql.substring(orderByPos, orderByStmtPos);
}
private String findOrderBySql() {
if (orderByPos > -1) {
int pos = orderByPos + ORDER_BY.length();
return sql.substring(pos).trim();
}
return null;
return (orderByStmtPos < 1) ? null : sql.substring(orderByStmtPos).trim();
}
private String findPreHavingSql() {
@@ -226,6 +225,11 @@ class DRawSqlParser {
}
orderByPos = textParser.findWordLower("order", startOrderBy);
if (orderByPos > 1) {
// there might be keywords like siblings in between the order
// and by so search for the by keyword explicitly
orderByStmtPos = 2 + textParser.findWordLower("by", orderByPos);
}
}
private int findWhereExprPosition() {
+15 -5
View File
@@ -222,6 +222,8 @@ public final class RawSql implements Serializable {
private final boolean andHavingExpr;
private final String orderByPrefix;
private final String orderBy;
private final boolean distinct;
@@ -240,6 +242,7 @@ public final class RawSql implements Serializable {
this.preWhere = null;
this.andHavingExpr = false;
this.andWhereExpr = false;
this.orderByPrefix = null;
this.orderBy = null;
this.distinct = false;
}
@@ -248,8 +251,7 @@ public final class RawSql implements Serializable {
* Construct for parsed SQL.
*/
protected Sql(int queryHashCode, String preFrom, String preWhere, boolean andWhereExpr,
String preHaving, boolean andHavingExpr,
String orderBy, boolean distinct) {
String preHaving, boolean andHavingExpr, String orderByPrefix, String orderBy, boolean distinct) {
this.queryHashCode = queryHashCode;
this.parsed = true;
@@ -259,6 +261,7 @@ public final class RawSql implements Serializable {
this.preWhere = preWhere;
this.andHavingExpr = andHavingExpr;
this.andWhereExpr = andWhereExpr;
this.orderByPrefix = orderByPrefix;
this.orderBy = orderBy;
this.distinct = distinct;
}
@@ -337,6 +340,14 @@ public final class RawSql implements Serializable {
return andHavingExpr;
}
/**
* Return the 'order by' keywords.
* This can contain additional keywords, for example 'order siblings by' as Oracle syntax.
*/
public String getOrderByPrefix() {
return (orderByPrefix == null) ? "order by" : orderByPrefix;
}
/**
* Return the SQL ORDER BY clause.
*/
@@ -429,9 +440,8 @@ public final class RawSql implements Serializable {
for (Column c : dbColumnMap.values()) {
pMap.put(c.getPropertyName(), c.getDbColumn());
pcMap.put(c.getPropertyName(), c);
hc = 31 * hc + c.getPropertyName() == null ? 0 : c.getPropertyName().hashCode();
hc = 31 * hc + c.getDbColumn() == null ? 0 : c.getDbColumn().hashCode();
hc = 31 * hc + ((c.getPropertyName() == null) ? 0 : c.getPropertyName().hashCode());
hc = 31 * hc + ((c.getDbColumn() == null) ? 0 : c.getDbColumn().hashCode());
}
this.propertyMap = Collections.unmodifiableMap(pMap);
this.propertyColumnMap = Collections.unmodifiableMap(pcMap);
@@ -127,7 +127,7 @@ public class CQueryBuilderRawSql implements Constants {
}
if (!isEmpty(orderBy)) {
sb.append(" order by ").append(orderBy);
sb.append(" ").append(sql.getOrderByPrefix()).append(" ").append(orderBy);
}
return sb.toString().trim();
@@ -38,6 +38,7 @@ public class TestRawSqlBuilder extends BaseTestCase {
Assert.assertEquals("id", sql.getPreFrom());
Assert.assertEquals("from t_cust where id > ?", sql.getPreWhere());
Assert.assertEquals("", sql.getPreHaving());
Assert.assertEquals("order by", sql.getOrderByPrefix());
Assert.assertEquals("id desc", sql.getOrderBy());
r = RawSqlBuilder.parse("select id from t_cust order by id desc");
@@ -65,6 +66,7 @@ public class TestRawSqlBuilder extends BaseTestCase {
Assert.assertEquals("id, sum(x)", sql.getPreFrom());
Assert.assertEquals("from t_cust where id > ?", sql.getPreWhere());
Assert.assertEquals("group by id having sum(x) > ?", sql.getPreHaving());
Assert.assertEquals("order by", sql.getOrderByPrefix());
Assert.assertEquals("id desc", sql.getOrderBy());
// no where
@@ -74,6 +76,7 @@ public class TestRawSqlBuilder extends BaseTestCase {
Assert.assertEquals("id, sum(x)", sql.getPreFrom());
Assert.assertEquals("from t_cust", sql.getPreWhere());
Assert.assertEquals("group by id having sum(x) > ?", sql.getPreHaving());
Assert.assertEquals("order by", sql.getOrderByPrefix());
Assert.assertEquals("id desc", sql.getOrderBy());
// no where, no order by
@@ -83,6 +86,7 @@ public class TestRawSqlBuilder extends BaseTestCase {
Assert.assertEquals("from t_cust", sql.getPreWhere());
Assert.assertEquals("group by id having sum(x) > ?", sql.getPreHaving());
Assert.assertNull(sql.getOrderBy());
Assert.assertEquals("order by", sql.getOrderByPrefix());
// no order by
r = RawSqlBuilder
@@ -92,5 +96,24 @@ public class TestRawSqlBuilder extends BaseTestCase {
Assert.assertEquals("from t_cust where id > ?", sql.getPreWhere());
Assert.assertEquals("group by id having sum(x) > ?", sql.getPreHaving());
Assert.assertNull(sql.getOrderBy());
Assert.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";
RawSql rawSql = RawSqlBuilder.parse(s).create();
Sql sql = rawSql.getSql();
Assert.assertEquals("ID, DESCRIPTION, NAME, PARENT_ID", sql.getPreFrom());
Assert.assertEquals("order siblings by", sql.getOrderByPrefix());
Assert.assertEquals("NAME", sql.getOrderBy());
Assert.assertEquals("FROM SOME_TABLE WHERE lower(NAME) like :name START WITH ID = :parentId CONNECT BY PRIOR ID = PARENT_ID", sql.getPreWhere());
}
}
@@ -23,7 +23,7 @@ public class TestRawSqlOrmWrapper2 extends BaseTestCase {
ResetBasicData.reset();
String sql = " select order_id, 'ignoreMe', sum(d.order_qty*d.unit_price) as totalAmount "
+ " from o_order_detail d" + " group by order_id ";
+ " from o_order_detail d group by order_id ";
RawSql rawSql = RawSqlBuilder.parse(sql).columnMapping("order_id", "order.id")
.columnMappingIgnore("'ignoreMe'")