提交 8d7c763f authored 作者: Thomas Mueller's avatar Thomas Mueller

JaQu improvements

上级 195ed7f8
......@@ -11,17 +11,26 @@ import java.math.BigDecimal;
import java.util.List;
import org.h2.jaqu.Db;
import static org.h2.jaqu.Function.*;
//## Java 1.5 end ##
import org.h2.test.TestBase;
/**
* Implementation of the 101 LINQ Samples as described in
* <p>
* This is the implementation of the 101 LINQ Samples as described in
* http://msdn2.microsoft.com/en-us/vcsharp/aa336760.aspx
* </p><p>Why should you use JaQu?
* Type checking,
* autocomplete,
* no separate SQL scripts,
* no more SQL injection.</p>
*/
public class SamplesTest extends TestBase {
//## Java 1.5 begin ##
private Db db;
Db db;
// TODO length
public static void main(String[] args) throws Exception {
new SamplesTest().test();
......@@ -34,12 +43,14 @@ public class SamplesTest extends TestBase {
db.insertAll(Product.getProductList());
db.insertAll(Customer.getCustomerList());
db.insertAll(Order.getOrderList());
testGroup();
testSelectManyCompoundFrom2();
testWhereSimple4();
testSelectSimple2();
testAnonymousTypes3();
testWhereSimple2();
testWhereSimple3();
testCountStar();
db.close();
//## Java 1.5 end ##
}
......@@ -220,6 +231,7 @@ public class SamplesTest extends TestBase {
db.from(c).
innerJoin(o).on(c.customerId).is(o.customerId).
where(o.total).smaller(new BigDecimal("500.00")).
orderBy(1).
select(new CustOrder() { {
customerId = c.customerId;
orderId = o.orderId;
......@@ -239,6 +251,56 @@ public class SamplesTest extends TestBase {
"c:ANATR/o:10625;c:ANATR/o:10759;c:ANTON/o:10355;" +
"c:ANTON/o:10365;c:ANTON/o:10682;", s);
}
private void testCountStar() throws Exception {
long count = db.from(new Product()).
selectCountStar();
assertEquals(77, count);
}
//## Java 1.5 end ##
/**
* A result set class containing customer data and the order total.
*/
//## Java 1.5 begin ##
public static class OrderGroup {
public String category;
public Long productCount;
}
private void testGroup() throws Exception {
// var orderGroups =
// from p in products
// group p by p.Category into g
// select new {
// Category = g.Key,
// Products = g
// };
final Product p = new Product();
List<OrderGroup> list =
db.from(p).
groupBy(p.category).
orderBy(1).
select(new OrderGroup() { {
category = p.category;
productCount = countStar();
}});
StringBuilder buff = new StringBuilder();
for (OrderGroup og: list) {
buff.append(og.category);
buff.append("=");
buff.append(og.productCount);
buff.append(';');
}
String s = buff.toString();
assertEquals("Beverages=12;Condiments=12;Confections=13;" +
"Dairy Products=10;Grains/Cereals=7;Meat/Poultry=6;" +
"Produce=5;Seafood=12;", s);
}
//## Java 1.5 end ##
}
/*
* Copyright 2004-2008 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
/**
* This class provides static methods that represents common SQL functions.
*/
public class Function {
private static final Long COUNT_STAR = new Long(0);
public static Long countStar() {
return COUNT_STAR;
}
}
/*
* Copyright 2004-2008 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
/**
* An expression to order by in a query.
*
* @param <T> the expression data type
*/
//## Java 1.5 begin ##
class OrderExpression<T> {
private Query query;
private T expression;
private boolean desc;
private boolean nullsFirst;
private boolean nullsLast;
OrderExpression(Query query, T expression, boolean desc, boolean nullsFirst, boolean nullsLast) {
this.query = query;
this.expression = expression;
this.desc = desc;
this.nullsFirst = nullsFirst;
this.nullsLast = nullsLast;
}
String getString() {
StringBuilder buff = new StringBuilder();
buff.append(query.getString(expression));
if (desc) {
buff.append(" DESC");
}
if (nullsLast) {
buff.append(" NULLS LAST");
}
if (nullsFirst) {
buff.append(" NULLS FIRST");
}
return buff.toString();
}
}
//## Java 1.5 end ##
......@@ -13,7 +13,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.h2.jaqu.TableDefinition.FieldDefinition;
import org.h2.jaqu.util.Utils;
//## Java 1.5 end ##
......@@ -30,6 +29,8 @@ public class Query<T> {
private ArrayList<ConditionToken> conditions = Utils.newArrayList();
private ArrayList<SelectTable> joins = Utils.newArrayList();
private final HashMap<Object, SelectColumn> aliasMap = Utils.newHashMap();
private ArrayList<OrderExpression> orderByList = Utils.newArrayList();
private Object[] groupByExpressions;
Query(Db db) {
this.db = db;
......@@ -43,9 +44,20 @@ public class Query<T> {
return query;
}
public long selectCountStar() {
ResultSet rs = db.executeQuery(getString("COUNT(*)"));
try {
rs.next();
long value = rs.getLong(1);
return value;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public List<T> select() {
List<T> result = Utils.newArrayList();
ResultSet rs = db.executeQuery(getString());
ResultSet rs = db.executeQuery(getString("*"));
try {
while (rs.next()) {
T item = from.newObject();
......@@ -68,22 +80,15 @@ public class Query<T> {
}
private <X> List<X> select(Class<X> clazz, X x) {
List<X> result = Utils.newArrayList();
TableDefinition<X> def = db.define(clazz);
ResultSet rs = db.executeQuery(getString());
String selectList = def.getSelectList(this, x);
ResultSet rs = db.executeQuery(getString(selectList));
List<X> result = Utils.newArrayList();
try {
while (rs.next()) {
T item = from.newObject();
from.getAliasDefinition().readRow(item, rs);
from.setCurrent(item);
for (SelectTable s: joins) {
Object item2 = s.newObject();
s.getAliasDefinition().readRow(item2, rs);
s.setCurrent(item2);
}
X item2 = Utils.newObject(clazz);
def.copyAttributeValues(this, item2, x);
result.add(item2);
X row = Utils.newObject(clazz);
def.readRow(row, rs);
result.add(row);
}
} catch (SQLException e) {
throw new RuntimeException(e);
......@@ -92,18 +97,17 @@ public class Query<T> {
}
private <X> List<X> selectSimple(X x) {
String selectList = getString(x);
ResultSet rs = db.executeQuery(getString(selectList));
List<X> result = Utils.newArrayList();
ResultSet rs = db.executeQuery(getString());
FieldDefinition<X> def = aliasMap.get(x).getFieldDefinition();
try {
while (rs.next()) {
X item;
if (def == null) {
item = x;
} else {
item = def.read(rs);
try {
X value = (X) rs.getObject(1);
result.add(value);
} catch (Exception e) {
throw new RuntimeException(e);
}
result.add(item);
}
} catch (SQLException e) {
throw new RuntimeException(e);
......@@ -119,15 +123,57 @@ public class Query<T> {
/**
* Order by a number of columns.
*
* @param columns the columns
* @param expressions the columns
* @return the query
*/
//## Java 1.5 begin ##
public Query<T> orderBy(Integer... columns) {
public Query<T> orderBy(Object... expressions) {
for (Object expr : expressions) {
OrderExpression<Object> e = new OrderExpression<Object>(this, expr, false, false, false);
addOrderBy(e);
}
return this;
}
public Query<T> orderByNullsFirst(Object expr) {
OrderExpression<Object> e = new OrderExpression<Object>(this, expr, false, true, false);
addOrderBy(e);
return this;
}
public Query<T> orderByNullsLast(Object expr) {
OrderExpression<Object> e = new OrderExpression<Object>(this, expr, false, false, true);
addOrderBy(e);
return this;
}
public Query<T> orderByDesc(Object expr) {
OrderExpression<Object> e = new OrderExpression<Object>(this, expr, true, false, false);
addOrderBy(e);
return this;
}
public Query<T> orderByDescNullsFirst(Object expr) {
OrderExpression<Object> e = new OrderExpression<Object>(this, expr, true, true, false);
addOrderBy(e);
return this;
}
public Query<T> orderByDescNullsLast(Object expr) {
OrderExpression<Object> e = new OrderExpression<Object>(this, expr, true, false, true);
addOrderBy(e);
return this;
}
public Query<T> groupBy(Object... groupByExpressions) {
this.groupByExpressions = groupByExpressions;
return this;
}
String getString(Object x) {
if (x == Function.countStar()) {
return "COUNT(*)";
}
SelectColumn col = aliasMap.get(x);
if (col != null) {
return col.getString();
......@@ -139,8 +185,10 @@ public class Query<T> {
conditions.add(condition);
}
String getString() {
StringBuilder buff = new StringBuilder("SELECT * FROM ");
String getString(String selectList) {
StringBuilder buff = new StringBuilder("SELECT ");
buff.append(selectList);
buff.append(" FROM ");
buff.append(from.getString());
for (SelectTable join : joins) {
buff.append(join.getStringAsJoin());
......@@ -152,6 +200,28 @@ public class Query<T> {
buff.append(' ');
}
}
if (groupByExpressions != null) {
buff.append(" GROUP BY ");
for (int i = 0; i < groupByExpressions.length; i++) {
if (i > 0) {
buff.append(", ");
}
Object obj = groupByExpressions[i];
buff.append(getString(obj));
buff.append(' ');
}
}
if (!orderByList.isEmpty()) {
buff.append(" ORDER BY ");
for (int i = 0; i < orderByList.size(); i++) {
if (i > 0) {
buff.append(", ");
}
OrderExpression o = orderByList.get(i);
buff.append(o.getString());
buff.append(' ');
}
}
return buff.toString();
}
//## Java 1.5 end ##
......@@ -183,5 +253,9 @@ public class Query<T> {
return aliasMap.get(obj);
}
void addOrderBy(OrderExpression expr) {
orderByList.add(expr);
}
}
//## Java 1.5 end ##
......@@ -46,11 +46,45 @@ public class QueryWhere<T> {
/**
* Order by a number of columns.
*
* @param columns the columns
* @param expressions the order by expressions
* @return the query
*/
//## Java 1.5 begin ##
public QueryWhere<T> orderBy(Integer... columns) {
public QueryWhere<T> orderBy(Object... expressions) {
for (Object expr : expressions) {
OrderExpression<Object> e = new OrderExpression<Object>(query, expr, false, false, false);
query.addOrderBy(e);
}
return this;
}
public QueryWhere<T> orderByNullsFirst(Object expr) {
OrderExpression<Object> e = new OrderExpression<Object>(query, expr, false, true, false);
query.addOrderBy(e);
return this;
}
public QueryWhere<T> orderByNullsLast(Object expr) {
OrderExpression<Object> e = new OrderExpression<Object>(query, expr, false, false, true);
query.addOrderBy(e);
return this;
}
public QueryWhere<T> orderByDesc(Object expr) {
OrderExpression<Object> e = new OrderExpression<Object>(query, expr, true, false, false);
query.addOrderBy(e);
return this;
}
public QueryWhere<T> orderByDescNullsFirst(Object expr) {
OrderExpression<Object> e = new OrderExpression<Object>(query, expr, true, true, false);
query.addOrderBy(e);
return this;
}
public QueryWhere<T> orderByDescNullsLast(Object expr) {
OrderExpression<Object> e = new OrderExpression<Object>(query, expr, true, false, true);
query.addOrderBy(e);
return this;
}
......
......@@ -63,6 +63,7 @@ class TableDefinition<T> {
void setValue(Object obj, Object o) {
try {
o = Utils.convert(o, field.getType());
field.set(obj, o);
} catch (Exception e) {
throw new RuntimeException(e);
......@@ -70,10 +71,10 @@ class TableDefinition<T> {
}
@SuppressWarnings("unchecked")
X read(ResultSet rs) {
X read(ResultSet rs, int columnIndex) {
try {
return (X) rs.getObject(columnName);
} catch (Exception e) {
return (X) rs.getObject(columnIndex);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
......@@ -238,12 +239,27 @@ class TableDefinition<T> {
}
void readRow(Object item, ResultSet rs) {
for (FieldDefinition def : fields) {
Object o = def.read(rs);
for (int i = 0; i < fields.size(); i++) {
FieldDefinition def = fields.get(i);
Object o = def.read(rs, i + 1);
def.setValue(item, o);
}
}
<X> String getSelectList(Query query, X x) {
StringBuilder buff = new StringBuilder();
for (int i = 0; i < fields.size(); i++) {
if (i > 0) {
buff.append(", ");
}
FieldDefinition def = fields.get(i);
Object obj = def.getValue(x);
String s = query.getString(obj);
buff.append(s);
}
return buff.toString();
}
<U, X> void copyAttributeValues(Query query, X to, X map) {
for (FieldDefinition def : fields) {
Object obj = def.getValue(map);
......
......@@ -128,5 +128,31 @@ public class Utils {
return false;
}
public static Object convert(Object o, Class< ? > targetType) {
if (o == null) {
return null;
}
Class currentType = o.getClass();
if (currentType == currentType) {
return o;
}
if (targetType == String.class) {
return o.toString();
}
if (Number.class.isAssignableFrom(currentType)) {
Number n = (Number) o;
if (targetType == Integer.class) {
return n.intValue();
} else if (targetType == Long.class) {
return n.longValue();
} else if (targetType == Double.class) {
return n.doubleValue();
} else if (targetType == Float.class) {
return n.floatValue();
}
}
throw new RuntimeException("Can not convert the value " + o + " from " + currentType + " to " + targetType);
}
}
//## Java 1.5 end ##
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论