提交 902de3ff authored 作者: Thomas Mueller's avatar Thomas Mueller

JaQu improvements

上级 faab0abd
......@@ -130,9 +130,15 @@ public class Product implements Table {
create(74, "Longlife Tofu", "Produce", 10.0, 4),
create(75, "Rhoenbraeu Klosterbier", "Beverages", 7.7500, 125),
create(76, "Lakkalikoeoeri", "Beverages", 18.0, 57),
create(77, "Original Frankfurter gruene Sosse", "Condiments", 13.0, 32) };
create(77, "Original Frankfurter gruene Sosse", "Condiments", 13.0, 32),
};
return Arrays.asList(list);
}
public String toString() {
return productName + ": " + unitsInStock;
}
}
//## Java 1.5 end ##
......@@ -43,6 +43,15 @@ public class SamplesTest extends TestBase {
db.insertAll(Product.getProductList());
db.insertAll(Customer.getCustomerList());
db.insertAll(Order.getOrderList());
// TODO SUM, MIN, MAX, LIKE, LIKE ESCAPE...
// TODO +, -, *, /, ||, nested operations
// TODO nested AND/OR
// TODO NOT
// TODO DELETE: FROM ... DELETE?
// TODO UPDATE: FROM ... UPDATE?
// TODO SELECT UNION
testLength();
testCount();
testGroup();
testSelectManyCompoundFrom2();
testWhereSimple4();
......@@ -50,7 +59,6 @@ public class SamplesTest extends TestBase {
testAnonymousTypes3();
testWhereSimple2();
testWhereSimple3();
testCountStar();
db.close();
//## Java 1.5 end ##
}
......@@ -252,19 +260,28 @@ public class SamplesTest extends TestBase {
"c:ANTON/o:10365;c:ANTON/o:10682;", s);
}
private void testCountStar() throws Exception {
long count = db.from(new Product()).
selectCountStar();
private void testLength() throws Exception {
Product p = new Product();
List<Integer> lengths = db.from(p).
where(length(p.productName)).smaller(10).
orderBy(1).
selectDistinct(length(p.productName));
String s = lengths.toString();
assertEquals("[4, 5, 7, 8, 9]", s);
}
private void testCount() throws Exception {
long count = db.from(new Product()).selectCount();
assertEquals(77, count);
}
//## Java 1.5 end ##
/**
* A result set class containing customer data and the order total.
* A result set class containing product groups.
*/
//## Java 1.5 begin ##
public static class OrderGroup {
public static class ProductGroup {
public String category;
public Long productCount;
}
......@@ -280,17 +297,17 @@ public class SamplesTest extends TestBase {
// };
final Product p = new Product();
List<OrderGroup> list =
List<ProductGroup> list =
db.from(p).
groupBy(p.category).
orderBy(1).
select(new OrderGroup() { {
select(new ProductGroup() { {
category = p.category;
productCount = countStar();
productCount = count();
}});
StringBuilder buff = new StringBuilder();
for (OrderGroup og: list) {
for (ProductGroup og: list) {
buff.append(og.category);
buff.append("=");
buff.append(og.productCount);
......
......@@ -12,7 +12,7 @@ package org.h2.jaqu;
* @param <A> the operand type
*/
//## Java 1.5 begin ##
class Condition<A> implements ConditionToken {
class Condition<A> implements Token {
Query< ? > query;
CompareType compareType;
A x, y;
......@@ -24,7 +24,7 @@ class Condition<A> implements ConditionToken {
this.y = y;
}
public String getString() {
public String getString(Query query) {
if (compareType.hasRightExpression()) {
return query.getString(x) + compareType.getString() + query.getString(y);
}
......
......@@ -10,7 +10,7 @@ package org.h2.jaqu;
* An OR or an AND condition.
*/
//## Java 1.5 begin ##
enum ConditionAndOr implements ConditionToken {
enum ConditionAndOr implements Token {
AND("AND"),
OR("OR");
......@@ -20,7 +20,7 @@ enum ConditionAndOr implements ConditionToken {
this.text = text;
}
public String getString() {
public String getString(Query query) {
return text;
}
......
......@@ -16,6 +16,7 @@ import java.util.Map;
import java.util.Properties;
import org.h2.jaqu.util.Utils;
import org.h2.jaqu.util.WeakIdentityHashMap;
import org.h2.util.JdbcUtils;
//## Java 1.5 end ##
......@@ -25,6 +26,8 @@ import org.h2.util.JdbcUtils;
//## Java 1.5 begin ##
public class Db {
private static final WeakIdentityHashMap<Object, Token> TOKENS = Utils.newWeakIdentityHashMap();
private final Connection conn;
private final Map<Class, TableDefinition> classMap = Utils.newHashMap();
......@@ -32,6 +35,15 @@ public class Db {
this.conn = conn;
}
static <X> X registerToken(X x, Token token) {
TOKENS.put(x, token);
return x;
}
static Token getToken(Object x) {
return TOKENS.get(x);
}
private static <T> T instance(Class<T> clazz) {
try {
return clazz.newInstance();
......
......@@ -6,15 +6,55 @@
*/
package org.h2.jaqu;
//## Java 1.5 begin ##
import org.h2.jaqu.util.Utils;
//## Java 1.5 end ##
/**
* This class provides static methods that represents common SQL functions.
*/
public class Function {
public class Function implements Token {
//## Java 1.5 begin ##
private static final Long COUNT_STAR = new Long(0);
public static Long countStar() {
private String name;
private Object x;
private Function(String name, Object x) {
this.name = name;
this.x = x;
}
public String getString(Query query) {
return name + "(" + query.getString(x) + ")";
}
//## Java 1.5 end ##
public static Long count() {
return COUNT_STAR;
}
public static Integer length(Object x) {
return Db.registerToken(Utils.newObject(Integer.class), new Function("LENGTH", x));
}
public static Long count(Object x) {
return Db.registerToken(Utils.newObject(Long.class), new Function("COUNT", x));
}
public static <X> X min(X x) {
Class<X> clazz = (Class<X>) x.getClass();
X o = Utils.newObject(clazz);
return Db.registerToken(o, new Function("MIN", x));
}
public static <X> X max(X x) {
Class<X> clazz = (Class<X>) x.getClass();
X o = Utils.newObject(clazz);
return Db.registerToken(o, new Function("MAX", x));
}
//## Java 1.5 end ##
}
......@@ -26,7 +26,7 @@ public class Query<T> {
private Db db;
private SelectTable<T> from;
private ArrayList<ConditionToken> conditions = Utils.newArrayList();
private ArrayList<Token> conditions = Utils.newArrayList();
private ArrayList<SelectTable> joins = Utils.newArrayList();
private final HashMap<Object, SelectColumn> aliasMap = Utils.newHashMap();
private ArrayList<OrderExpression> orderByList = Utils.newArrayList();
......@@ -44,8 +44,8 @@ public class Query<T> {
return query;
}
public long selectCountStar() {
ResultSet rs = db.executeQuery(getString("COUNT(*)"));
public long selectCount() {
ResultSet rs = db.executeQuery(getSQL("COUNT(*)", false));
try {
rs.next();
long value = rs.getLong(1);
......@@ -56,8 +56,16 @@ public class Query<T> {
}
public List<T> select() {
return select(false);
}
public List<T> selectDistinct() {
return select(true);
}
private List<T> select(boolean distinct) {
List<T> result = Utils.newArrayList();
ResultSet rs = db.executeQuery(getString("*"));
ResultSet rs = db.executeQuery(getSQL("*", distinct));
try {
while (rs.next()) {
T item = from.newObject();
......@@ -70,19 +78,27 @@ public class Query<T> {
return result;
}
public <X, Z> List<X> selectDistinct(Z x) {
return select(x, true);
}
public <X, Z> List<X> select(Z x) {
return select(x, false);
}
private <X, Z> List<X> select(Z x, boolean distinct) {
Class< ? > clazz = x.getClass();
if (Utils.isSimpleType(clazz)) {
return selectSimple((X) x);
return getSimple((X) x, distinct);
}
clazz = clazz.getSuperclass();
return select((Class<X>) clazz, (X) x);
return select((Class<X>) clazz, (X) x, distinct);
}
private <X> List<X> select(Class<X> clazz, X x) {
private <X> List<X> select(Class<X> clazz, X x, boolean distinct) {
TableDefinition<X> def = db.define(clazz);
String selectList = def.getSelectList(this, x);
ResultSet rs = db.executeQuery(getString(selectList));
ResultSet rs = db.executeQuery(getSQL(selectList, distinct));
List<X> result = Utils.newArrayList();
try {
while (rs.next()) {
......@@ -96,9 +112,9 @@ public class Query<T> {
return result;
}
private <X> List<X> selectSimple(X x) {
private <X> List<X> getSimple(X x, boolean distinct) {
String selectList = getString(x);
ResultSet rs = db.executeQuery(getString(selectList));
ResultSet rs = db.executeQuery(getSQL(selectList, distinct));
List<X> result = Utils.newArrayList();
try {
while (rs.next()) {
......@@ -135,45 +151,25 @@ public class Query<T> {
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()) {
if (x == Function.count()) {
return "COUNT(*)";
}
Token token = Db.getToken(x);
if (token != null) {
return token.getString(this);
}
SelectColumn col = aliasMap.get(x);
if (col != null) {
return col.getString();
......@@ -181,22 +177,25 @@ public class Query<T> {
return Utils.quoteSQL(x);
}
void addConditionToken(ConditionToken condition) {
void addConditionToken(Token condition) {
conditions.add(condition);
}
String getString(String selectList) {
String getSQL(String selectList, boolean distinct) {
StringBuilder buff = new StringBuilder("SELECT ");
if (distinct) {
buff.append("DISTINCT ");
}
buff.append(selectList);
buff.append(" FROM ");
buff.append(from.getString());
for (SelectTable join : joins) {
buff.append(join.getStringAsJoin());
buff.append(join.getStringAsJoin(this));
}
if (!conditions.isEmpty()) {
buff.append(" WHERE ");
for (ConditionToken token : conditions) {
buff.append(token.getString());
for (Token token : conditions) {
buff.append(token.getString(this));
buff.append(' ');
}
}
......
/*
* 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 represents a query with an incomplete condition.
*
* @param <T> the return type of the query
* @param <A> the incomplete condition data type
*/
//## Java 1.5 begin ##
public class QueryCondition<T, A> {
private Query<T> query;
private A x;
QueryCondition(Query<T> query, A x) {
this.query = query;
this.x = x;
}
public QueryWhere<T> is(A y) {
query.addConditionToken(new Condition<A>(query, x, y, CompareType.EQUAL));
return new QueryWhere<T>(query);
}
public QueryWhere<T> bigger(A y) {
query.addConditionToken(new Condition<A>(query, x, y, CompareType.BIGGER));
return new QueryWhere<T>(query);
}
public QueryWhere<T> smaller(A y) {
query.addConditionToken(new Condition<A>(query, x, y, CompareType.SMALLER));
return new QueryWhere<T>(query);
}
}
//## 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 represents a query with an incomplete condition.
*
* @param <T> the return type of the query
* @param <A> the incomplete condition data type
*/
//## Java 1.5 begin ##
public class QueryCondition<T, A> {
private Query<T> query;
private A x;
QueryCondition(Query<T> query, A x) {
this.query = query;
this.x = x;
}
public QueryWhere<T> is(A y) {
query.addConditionToken(new Condition<A>(query, x, y, CompareType.EQUAL));
return new QueryWhere<T>(query);
}
public QueryWhere<T> bigger(A y) {
query.addConditionToken(new Condition<A>(query, x, y, CompareType.BIGGER));
return new QueryWhere<T>(query);
}
public QueryWhere<T> smaller(A y) {
query.addConditionToken(new Condition<A>(query, x, y, CompareType.SMALLER));
return new QueryWhere<T>(query);
}
}
//## Java 1.5 end ##
......@@ -38,9 +38,18 @@ public class QueryWhere<T> {
return (List<X>) query.select(x);
}
public <X, Z> List<X> selectDistinct(Z x) {
return (List<X>) query.selectDistinct(x);
}
public List<T> select() {
return query.select();
}
public List<T> selectDistinct() {
return query.selectDistinct();
}
//## Java 1.5 end ##
/**
......
......@@ -6,9 +6,9 @@
*/
package org.h2.jaqu;
//## Java 1.5 begin ##
import java.util.ArrayList;
//## Java 1.5 begin ##
import org.h2.jaqu.util.ClassUtils;
import org.h2.jaqu.util.Utils;
//## Java 1.5 end ##
......@@ -28,7 +28,7 @@ class SelectTable <T> {
private String as;
private TableDefinition<T> aliasDef;
private boolean outerJoin;
private ArrayList<ConditionToken> joinConditions = Utils.newArrayList();
private ArrayList<Token> joinConditions = Utils.newArrayList();
SelectTable(Db db, Query query, T alias, boolean outerJoin) {
this.query = query;
......@@ -53,7 +53,7 @@ class SelectTable <T> {
return aliasDef.tableName;
}
String getStringAsJoin() {
String getStringAsJoin(Query query) {
StringBuilder buff = new StringBuilder();
if (outerJoin) {
buff.append(" LEFT OUTER JOIN ");
......@@ -63,8 +63,8 @@ class SelectTable <T> {
buff.append(getString());
if (!joinConditions.isEmpty()) {
buff.append(" ON ");
for (ConditionToken token : joinConditions) {
buff.append(token.getString());
for (Token token : joinConditions) {
buff.append(token.getString(query));
buff.append(' ');
}
}
......@@ -83,7 +83,7 @@ class SelectTable <T> {
return as;
}
void addConditionToken(ConditionToken condition) {
void addConditionToken(Token condition) {
joinConditions.add(condition);
}
......
......@@ -7,9 +7,10 @@
package org.h2.jaqu;
/**
* Classes implementing this interface can be used as a token in a conditional
* expression.
* Classes implementing this interface can be used as a token in a statement.
*/
interface ConditionToken {
String getString();
interface Token {
//## Java 1.5 begin ##
String getString(Query query);
//## Java 1.5 end ##
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论