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

JaQu improvements

上级 195ed7f8
...@@ -11,17 +11,26 @@ import java.math.BigDecimal; ...@@ -11,17 +11,26 @@ import java.math.BigDecimal;
import java.util.List; import java.util.List;
import org.h2.jaqu.Db; import org.h2.jaqu.Db;
import static org.h2.jaqu.Function.*;
//## Java 1.5 end ## //## Java 1.5 end ##
import org.h2.test.TestBase; 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 * 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 { public class SamplesTest extends TestBase {
//## Java 1.5 begin ## //## Java 1.5 begin ##
private Db db; Db db;
// TODO length
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
new SamplesTest().test(); new SamplesTest().test();
...@@ -34,12 +43,14 @@ public class SamplesTest extends TestBase { ...@@ -34,12 +43,14 @@ public class SamplesTest extends TestBase {
db.insertAll(Product.getProductList()); db.insertAll(Product.getProductList());
db.insertAll(Customer.getCustomerList()); db.insertAll(Customer.getCustomerList());
db.insertAll(Order.getOrderList()); db.insertAll(Order.getOrderList());
testGroup();
testSelectManyCompoundFrom2(); testSelectManyCompoundFrom2();
testWhereSimple4(); testWhereSimple4();
testSelectSimple2(); testSelectSimple2();
testAnonymousTypes3(); testAnonymousTypes3();
testWhereSimple2(); testWhereSimple2();
testWhereSimple3(); testWhereSimple3();
testCountStar();
db.close(); db.close();
//## Java 1.5 end ## //## Java 1.5 end ##
} }
...@@ -220,6 +231,7 @@ public class SamplesTest extends TestBase { ...@@ -220,6 +231,7 @@ public class SamplesTest extends TestBase {
db.from(c). db.from(c).
innerJoin(o).on(c.customerId).is(o.customerId). innerJoin(o).on(c.customerId).is(o.customerId).
where(o.total).smaller(new BigDecimal("500.00")). where(o.total).smaller(new BigDecimal("500.00")).
orderBy(1).
select(new CustOrder() { { select(new CustOrder() { {
customerId = c.customerId; customerId = c.customerId;
orderId = o.orderId; orderId = o.orderId;
...@@ -239,6 +251,56 @@ public class SamplesTest extends TestBase { ...@@ -239,6 +251,56 @@ public class SamplesTest extends TestBase {
"c:ANATR/o:10625;c:ANATR/o:10759;c:ANTON/o:10355;" + "c:ANATR/o:10625;c:ANATR/o:10759;c:ANTON/o:10355;" +
"c:ANTON/o:10365;c:ANTON/o:10682;", s); "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 ## //## 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; ...@@ -13,7 +13,6 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import org.h2.jaqu.TableDefinition.FieldDefinition;
import org.h2.jaqu.util.Utils; import org.h2.jaqu.util.Utils;
//## Java 1.5 end ## //## Java 1.5 end ##
...@@ -30,6 +29,8 @@ public class Query<T> { ...@@ -30,6 +29,8 @@ public class Query<T> {
private ArrayList<ConditionToken> conditions = Utils.newArrayList(); private ArrayList<ConditionToken> conditions = Utils.newArrayList();
private ArrayList<SelectTable> joins = Utils.newArrayList(); private ArrayList<SelectTable> joins = Utils.newArrayList();
private final HashMap<Object, SelectColumn> aliasMap = Utils.newHashMap(); private final HashMap<Object, SelectColumn> aliasMap = Utils.newHashMap();
private ArrayList<OrderExpression> orderByList = Utils.newArrayList();
private Object[] groupByExpressions;
Query(Db db) { Query(Db db) {
this.db = db; this.db = db;
...@@ -43,9 +44,20 @@ public class Query<T> { ...@@ -43,9 +44,20 @@ public class Query<T> {
return query; 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() { public List<T> select() {
List<T> result = Utils.newArrayList(); List<T> result = Utils.newArrayList();
ResultSet rs = db.executeQuery(getString()); ResultSet rs = db.executeQuery(getString("*"));
try { try {
while (rs.next()) { while (rs.next()) {
T item = from.newObject(); T item = from.newObject();
...@@ -68,22 +80,15 @@ public class Query<T> { ...@@ -68,22 +80,15 @@ public class Query<T> {
} }
private <X> List<X> select(Class<X> clazz, X x) { private <X> List<X> select(Class<X> clazz, X x) {
List<X> result = Utils.newArrayList();
TableDefinition<X> def = db.define(clazz); 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 { try {
while (rs.next()) { while (rs.next()) {
T item = from.newObject(); X row = Utils.newObject(clazz);
from.getAliasDefinition().readRow(item, rs); def.readRow(row, rs);
from.setCurrent(item); result.add(row);
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);
} }
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
...@@ -92,18 +97,17 @@ public class Query<T> { ...@@ -92,18 +97,17 @@ public class Query<T> {
} }
private <X> List<X> selectSimple(X x) { private <X> List<X> selectSimple(X x) {
String selectList = getString(x);
ResultSet rs = db.executeQuery(getString(selectList));
List<X> result = Utils.newArrayList(); List<X> result = Utils.newArrayList();
ResultSet rs = db.executeQuery(getString());
FieldDefinition<X> def = aliasMap.get(x).getFieldDefinition();
try { try {
while (rs.next()) { while (rs.next()) {
X item; try {
if (def == null) { X value = (X) rs.getObject(1);
item = x; result.add(value);
} else { } catch (Exception e) {
item = def.read(rs); throw new RuntimeException(e);
} }
result.add(item);
} }
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
...@@ -119,15 +123,57 @@ public class Query<T> { ...@@ -119,15 +123,57 @@ public class Query<T> {
/** /**
* Order by a number of columns. * Order by a number of columns.
* *
* @param columns the columns * @param expressions the columns
* @return the query * @return the query
*/ */
//## Java 1.5 begin ## //## 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; return this;
} }
public Query<T> groupBy(Object... groupByExpressions) {
this.groupByExpressions = groupByExpressions;
return this;
}
String getString(Object x) { String getString(Object x) {
if (x == Function.countStar()) {
return "COUNT(*)";
}
SelectColumn col = aliasMap.get(x); SelectColumn col = aliasMap.get(x);
if (col != null) { if (col != null) {
return col.getString(); return col.getString();
...@@ -139,8 +185,10 @@ public class Query<T> { ...@@ -139,8 +185,10 @@ public class Query<T> {
conditions.add(condition); conditions.add(condition);
} }
String getString() { String getString(String selectList) {
StringBuilder buff = new StringBuilder("SELECT * FROM "); StringBuilder buff = new StringBuilder("SELECT ");
buff.append(selectList);
buff.append(" FROM ");
buff.append(from.getString()); buff.append(from.getString());
for (SelectTable join : joins) { for (SelectTable join : joins) {
buff.append(join.getStringAsJoin()); buff.append(join.getStringAsJoin());
...@@ -152,6 +200,28 @@ public class Query<T> { ...@@ -152,6 +200,28 @@ public class Query<T> {
buff.append(' '); 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(); return buff.toString();
} }
//## Java 1.5 end ## //## Java 1.5 end ##
...@@ -183,5 +253,9 @@ public class Query<T> { ...@@ -183,5 +253,9 @@ public class Query<T> {
return aliasMap.get(obj); return aliasMap.get(obj);
} }
void addOrderBy(OrderExpression expr) {
orderByList.add(expr);
}
} }
//## Java 1.5 end ## //## Java 1.5 end ##
...@@ -46,11 +46,45 @@ public class QueryWhere<T> { ...@@ -46,11 +46,45 @@ public class QueryWhere<T> {
/** /**
* Order by a number of columns. * Order by a number of columns.
* *
* @param columns the columns * @param expressions the order by expressions
* @return the query * @return the query
*/ */
//## Java 1.5 begin ## //## 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; return this;
} }
......
...@@ -63,6 +63,7 @@ class TableDefinition<T> { ...@@ -63,6 +63,7 @@ class TableDefinition<T> {
void setValue(Object obj, Object o) { void setValue(Object obj, Object o) {
try { try {
o = Utils.convert(o, field.getType());
field.set(obj, o); field.set(obj, o);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
...@@ -70,10 +71,10 @@ class TableDefinition<T> { ...@@ -70,10 +71,10 @@ class TableDefinition<T> {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
X read(ResultSet rs) { X read(ResultSet rs, int columnIndex) {
try { try {
return (X) rs.getObject(columnName); return (X) rs.getObject(columnIndex);
} catch (Exception e) { } catch (SQLException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
...@@ -238,12 +239,27 @@ class TableDefinition<T> { ...@@ -238,12 +239,27 @@ class TableDefinition<T> {
} }
void readRow(Object item, ResultSet rs) { void readRow(Object item, ResultSet rs) {
for (FieldDefinition def : fields) { for (int i = 0; i < fields.size(); i++) {
Object o = def.read(rs); FieldDefinition def = fields.get(i);
Object o = def.read(rs, i + 1);
def.setValue(item, o); 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) { <U, X> void copyAttributeValues(Query query, X to, X map) {
for (FieldDefinition def : fields) { for (FieldDefinition def : fields) {
Object obj = def.getValue(map); Object obj = def.getValue(map);
......
...@@ -128,5 +128,31 @@ public class Utils { ...@@ -128,5 +128,31 @@ public class Utils {
return false; 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 ## //## Java 1.5 end ##
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论