diff --git a/src/org/redkale/source/ColumnFuncNode.java b/src/org/redkale/source/ColumnFuncNode.java new file mode 100644 index 000000000..c0ba981ec --- /dev/null +++ b/src/org/redkale/source/ColumnFuncNode.java @@ -0,0 +1,83 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkale.source; + +import java.io.Serializable; + +/** + * 与ColumnNodeValue 组合,用于复杂的字段表达式 。 + * String 视为 字段名 + * + *

+ * 详情见: https://redkale.org + * + * @author zhangjx + * @since 2.0.0 + */ +public class ColumnFuncNode implements ColumnNode { + + protected FilterFunc func; + + protected Serializable value;//类型只能是String、ColumnNodeValue + + public ColumnFuncNode() { + } + + public ColumnFuncNode(FilterFunc func, Serializable node) { + if (!(node instanceof String) && !(node instanceof ColumnNodeValue)) throw new IllegalArgumentException("value must be String or ColumnNodeValue"); + this.func = func; + this.value = node; + } + + public static ColumnFuncNode create(FilterFunc func, Serializable node) { + return new ColumnFuncNode(func, node); + } + + public static ColumnFuncNode avg(Serializable node) { + return new ColumnFuncNode(FilterFunc.AVG, node); + } + + public static ColumnFuncNode count(Serializable node) { + return new ColumnFuncNode(FilterFunc.COUNT, node); + } + + public static ColumnFuncNode distinctCount(Serializable node) { + return new ColumnFuncNode(FilterFunc.DISTINCTCOUNT, node); + } + + public static ColumnFuncNode max(Serializable node) { + return new ColumnFuncNode(FilterFunc.MAX, node); + } + + public static ColumnFuncNode min(Serializable node) { + return new ColumnFuncNode(FilterFunc.MIN, node); + } + + public static ColumnFuncNode sum(Serializable node) { + return new ColumnFuncNode(FilterFunc.SUM, node); + } + + public FilterFunc getFunc() { + return func; + } + + public void setFunc(FilterFunc func) { + this.func = func; + } + + public Serializable getValue() { + return value; + } + + public void setValue(Serializable value) { + this.value = value; + } + + @Override + public String toString() { + return "{\"func\":\"" + func + "\", \"value\":" + ((value instanceof CharSequence) ? ("\"" + value + "\"") : value) + "}"; + } +} diff --git a/src/org/redkale/source/ColumnNode.java b/src/org/redkale/source/ColumnNode.java new file mode 100644 index 000000000..e73e69015 --- /dev/null +++ b/src/org/redkale/source/ColumnNode.java @@ -0,0 +1,21 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkale.source; + +import java.io.Serializable; + +/** + * ColumnFuncNode与ColumnNodeValue 的接口 + * + *

+ * 详情见: https://redkale.org + * + * @author zhangjx + * @since 2.0.0 + */ +public interface ColumnNode extends Serializable { + +} diff --git a/src/org/redkale/source/ColumnNodeValue.java b/src/org/redkale/source/ColumnNodeValue.java index 530c9dbd0..2deb9950e 100644 --- a/src/org/redkale/source/ColumnNodeValue.java +++ b/src/org/redkale/source/ColumnNodeValue.java @@ -13,21 +13,33 @@ import static org.redkale.source.ColumnExpress.*; * String 视为 字段名 * Number 视为 数值 * + *

+ * 详情见: https://redkale.org + * * @author zhangjx + * @since 2.0.0 */ -public class ColumnNodeValue implements Serializable { +public class ColumnNodeValue implements ColumnNode { - private Serializable left;//类型只能是String、Number、ColumnNodeValue + protected Serializable left;//类型只能是String、Number、ColumnNodeValue - private ColumnExpress express; //不能是MOV + protected ColumnExpress express; //不能是MOV - private Serializable right;//类型只能是String、Number、ColumnNodeValue + protected Serializable right;//类型只能是String、Number、ColumnNodeValue public ColumnNodeValue() { } public ColumnNodeValue(Serializable left, ColumnExpress express, Serializable right) { - if (express == null || express == ColumnExpress.MOV) throw new IllegalArgumentException("express cannot be null or MOV"); + if (express == null || express == ColumnExpress.MOV) { + throw new IllegalArgumentException("express cannot be null or MOV"); + } + if (!(left instanceof String) && !(left instanceof Number) && !(left instanceof ColumnNodeValue) && !(left instanceof ColumnFuncNode)) { + throw new IllegalArgumentException("left value must be String, Number, ColumnFuncNode or ColumnNodeValue"); + } + if (!(right instanceof String) && !(right instanceof Number) && !(right instanceof ColumnNodeValue) && !(right instanceof ColumnFuncNode)) { + throw new IllegalArgumentException("right value must be String, Number, ColumnFuncNode or ColumnNodeValue"); + } this.left = left; this.express = express; this.right = right; @@ -72,7 +84,7 @@ public class ColumnNodeValue implements Serializable { public ColumnNodeValue dec(Serializable right) { return any(DEC, right); } - + public ColumnNodeValue mul(Serializable right) { return any(MUL, right); } diff --git a/src/org/redkale/source/DataJdbcSource.java b/src/org/redkale/source/DataJdbcSource.java index 65fd23f20..5a977b203 100644 --- a/src/org/redkale/source/DataJdbcSource.java +++ b/src/org/redkale/source/DataJdbcSource.java @@ -421,6 +421,42 @@ public class DataJdbcSource extends DataSqlSource { } } + @Override + protected CompletableFuture> queryColumnMapDB(EntityInfo info, String sql, final ColumnNode[] funcNodes, final String[] groupByColumns) { + Connection conn = null; + Map rs = new LinkedHashMap<>(); + try { + conn = readPool.poll(); + //conn.setReadOnly(true); + final Statement stmt = conn.createStatement(); + ResultSet set = stmt.executeQuery(sql); + ResultSetMetaData rsd = set.getMetaData(); + boolean smallint = rsd == null ? false : rsd.getColumnType(1) == Types.SMALLINT; + while (set.next()) { + int index = 0; + Serializable[] keys = new Serializable[groupByColumns.length]; + for (int i = 0; i < keys.length; i++) { + keys[i] = (Serializable) ((smallint && index == 0) ? set.getShort(++index) : set.getObject(++index)); + } + Number[] vals = new Number[funcNodes.length]; + for (int i = 0; i < vals.length; i++) { + vals[i] = (Number) set.getObject(++index); + } + rs.put(keys, vals); + } + set.close(); + stmt.close(); + return CompletableFuture.completedFuture(rs); + } catch (SQLException e) { + if (info.getTableStrategy() != null && info.isTableNotExist(e)) return CompletableFuture.completedFuture(rs); + CompletableFuture future = new CompletableFuture(); + future.completeExceptionally(e); + return future;//return CompletableFuture.failedFuture(e); + } finally { + if (conn != null) readPool.offerConnection(conn); + } + } + @Override protected CompletableFuture findDB(EntityInfo info, String sql, boolean onlypk, SelectColumn selects) { Connection conn = null; diff --git a/src/org/redkale/source/DataMemorySource.java b/src/org/redkale/source/DataMemorySource.java index 13ebf2723..cfe268cb0 100644 --- a/src/org/redkale/source/DataMemorySource.java +++ b/src/org/redkale/source/DataMemorySource.java @@ -128,6 +128,11 @@ public class DataMemorySource extends DataSqlSource { return CompletableFuture.completedFuture(null); } + @Override + protected CompletableFuture> queryColumnMapDB(final EntityInfo info, final String sql, final ColumnNode[] funcNodes, final String[] groupByColumns) { + return CompletableFuture.completedFuture(null); + } + @Override protected CompletableFuture findDB(EntityInfo info, String sql, boolean onlypk, SelectColumn selects) { return CompletableFuture.completedFuture(null); diff --git a/src/org/redkale/source/DataSource.java b/src/org/redkale/source/DataSource.java index 58d57c07f..28212565e 100644 --- a/src/org/redkale/source/DataSource.java +++ b/src/org/redkale/source/DataSource.java @@ -702,7 +702,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果, 无结果返回null
* 等价SQL: SELECT FUNC{column} FROM {table}
- * 如 getNumberResultAsync(Record.class, FilterFunc.COUNT, null) 等价于: SELECT COUNT(*) FROM {table}
+ * 如 getNumberResultAsync(User.class, FilterFunc.COUNT, null) 等价于: SELECT COUNT(*) FROM {table}
* * @param entityClass Entity类 * @param func 聚合函数 @@ -715,7 +715,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果, 无结果返回null
* 等价SQL: SELECT FUNC{column} FROM {table}
- * 如 getNumberResultAsync(Record.class, FilterFunc.COUNT, null) 等价于: SELECT COUNT(*) FROM {table}
+ * 如 getNumberResultAsync(User.class, FilterFunc.COUNT, null) 等价于: SELECT COUNT(*) FROM {table}
* * @param entityClass Entity类 * @param func 聚合函数 @@ -728,7 +728,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果, 无结果返回null
* 等价SQL: SELECT FUNC{column} FROM {table} WHERE {filter bean}
- * 如 getNumberResultAsync(Record.class, FilterFunc.COUNT, null, (FilterBean)null) 等价于: SELECT COUNT(*) FROM {table}
+ * 如 getNumberResultAsync(User.class, FilterFunc.COUNT, null, (FilterBean)null) 等价于: SELECT COUNT(*) FROM {table}
* * @param entityClass Entity类 * @param func 聚合函数 @@ -742,7 +742,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果, 无结果返回null
* 等价SQL: SELECT FUNC{column} FROM {table} WHERE {filter bean}
- * 如 getNumberResultAsync(Record.class, FilterFunc.COUNT, null, (FilterBean)null) 等价于: SELECT COUNT(*) FROM {table}
+ * 如 getNumberResultAsync(User.class, FilterFunc.COUNT, null, (FilterBean)null) 等价于: SELECT COUNT(*) FROM {table}
* * @param entityClass Entity类 * @param func 聚合函数 @@ -756,7 +756,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果, 无结果返回null
* 等价SQL: SELECT FUNC{column} FROM {table} WHERE {filter node}
- * 如 getNumberResultAsync(Record.class, FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberResultAsync(User.class, FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT MAX(createtime) FROM {table}
* * @param entityClass Entity类 * @param func 聚合函数 @@ -770,7 +770,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果, 无结果返回null
* 等价SQL: SELECT FUNC{column} FROM {table} WHERE {filter node}
- * 如 getNumberResultAsync(Record.class, FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberResultAsync(User.class, FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT MAX(createtime) FROM {table}
* * @param entityClass Entity类 * @param func 聚合函数 @@ -784,7 +784,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果, 无结果返回默认值
* 等价SQL: SELECT FUNC{column} FROM {table}
- * 如 getNumberResultAsync(Record.class, FilterFunc.MAX, "createtime") 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberResultAsync(User.class, FilterFunc.MAX, "createtime") 等价于: SELECT MAX(createtime) FROM {table}
* * @param entityClass Entity类 * @param func 聚合函数 @@ -798,7 +798,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果, 无结果返回默认值
* 等价SQL: SELECT FUNC{column} FROM {table}
- * 如 getNumberResultAsync(Record.class, FilterFunc.MAX, "createtime") 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberResultAsync(User.class, FilterFunc.MAX, "createtime") 等价于: SELECT MAX(createtime) FROM {table}
* * @param entityClass Entity类 * @param func 聚合函数 @@ -812,7 +812,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果, 无结果返回默认值
* 等价SQL: SELECT FUNC{column} FROM {table} WHERE {filter bean}
- * 如 getNumberResultAsync(Record.class, FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberResultAsync(User.class, FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT MAX(createtime) FROM {table}
* * @param entityClass Entity类 * @param func 聚合函数 @@ -827,7 +827,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果, 无结果返回默认值
* 等价SQL: SELECT FUNC{column} FROM {table} WHERE {filter bean}
- * 如 getNumberResultAsync(Record.class, FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberResultAsync(User.class, FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT MAX(createtime) FROM {table}
* * @param entityClass Entity类 * @param func 聚合函数 @@ -842,7 +842,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果, 无结果返回默认值
* 等价SQL: SELECT FUNC{column} FROM {table} WHERE {filter node}
- * 如 getNumberResultAsync(Record.class, FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberResultAsync(User.class, FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT MAX(createtime) FROM {table}
* * @param entityClass Entity类 * @param func 聚合函数 @@ -857,7 +857,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果, 无结果返回默认值
* 等价SQL: SELECT FUNC{column} FROM {table} WHERE {filter node}
- * 如 getNumberResultAsync(Record.class, FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberResultAsync(User.class, FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT MAX(createtime) FROM {table}
* * @param entityClass Entity类 * @param func 聚合函数 @@ -872,7 +872,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果Map
* 等价SQL: SELECT FUNC1{column1}, FUNC2{column2}, ··· FROM {table}
- * 如 getNumberMapAsync(Record.class, new FilterFuncColumn(FilterFunc.MAX, "createtime")) 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberMapAsync(User.class, new FilterFuncColumn(FilterFunc.MAX, "createtime")) 等价于: SELECT MAX(createtime) FROM {table}
* * @param Number * @param entityClass Entity类 @@ -885,7 +885,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果Map
* 等价SQL: SELECT FUNC1{column1}, FUNC2{column2}, ··· FROM {table}
- * 如 getNumberMapAsync(Record.class, new FilterFuncColumn(FilterFunc.MAX, "createtime")) 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberMapAsync(User.class, new FilterFuncColumn(FilterFunc.MAX, "createtime")) 等价于: SELECT MAX(createtime) FROM {table}
* * @param Number * @param entityClass Entity类 @@ -898,7 +898,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果Map
* 等价SQL: SELECT FUNC1{column1}, FUNC2{column2}, ··· FROM {table} WHERE {filter bean}
- * 如 getNumberMapAsync(Record.class, (FilterBean)null, new FilterFuncColumn(FilterFunc.MAX, "createtime")) 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberMapAsync(User.class, (FilterBean)null, new FilterFuncColumn(FilterFunc.MAX, "createtime")) 等价于: SELECT MAX(createtime) FROM {table}
* * @param Number * @param entityClass Entity类 @@ -912,7 +912,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果Map
* 等价SQL: SELECT FUNC1{column1}, FUNC2{column2}, ··· FROM {table} WHERE {filter bean}
- * 如 getNumberMapAsync(Record.class, (FilterBean)null, new FilterFuncColumn(FilterFunc.MAX, "createtime")) 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberMapAsync(User.class, (FilterBean)null, new FilterFuncColumn(FilterFunc.MAX, "createtime")) 等价于: SELECT MAX(createtime) FROM {table}
* * @param Number * @param entityClass Entity类 @@ -926,7 +926,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果Map
* 等价SQL: SELECT FUNC1{column1}, FUNC2{column2}, ··· FROM {table} WHERE {filter node}
- * 如 getNumberMapAsync(Record.class, (FilterNode)null, new FilterFuncColumn(FilterFunc.MAX, "createtime")) 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberMapAsync(User.class, (FilterNode)null, new FilterFuncColumn(FilterFunc.MAX, "createtime")) 等价于: SELECT MAX(createtime) FROM {table}
* * @param Number * @param entityClass Entity类 @@ -940,7 +940,7 @@ public interface DataSource { /** * 获取符合过滤条件记录的聚合结果Map
* 等价SQL: SELECT FUNC1{column1}, FUNC2{column2}, ··· FROM {table} WHERE {filter node}
- * 如 getNumberMapAsync(Record.class, (FilterNode)null, new FilterFuncColumn(FilterFunc.MAX, "createtime")) 等价于: SELECT MAX(createtime) FROM {table}
+ * 如 getNumberMapAsync(User.class, (FilterNode)null, new FilterFuncColumn(FilterFunc.MAX, "createtime")) 等价于: SELECT MAX(createtime) FROM {table}
* * @param Number * @param entityClass Entity类 @@ -954,7 +954,7 @@ public interface DataSource { /** * 查询符合过滤条件记录的GROUP BY聚合结果Map
* 等价SQL: SELECT keyColumn, FUNC{funcColumn} FROM {table} GROUP BY {keyColumn}
- * 如 queryColumnMapAsync(Record.class, "name", FilterFunc.MAX, "createtime") 等价于: SELECT name, MAX(createtime) FROM user GROUP BY name
+ * 如 queryColumnMapAsync(User.class, "name", FilterFunc.MAX, "createtime") 等价于: SELECT name, MAX(createtime) FROM user GROUP BY name
* * @param Entity泛型 * @param Key字段的数据类型 @@ -971,7 +971,7 @@ public interface DataSource { /** * 查询符合过滤条件记录的GROUP BY聚合结果Map
* 等价SQL: SELECT keyColumn, FUNC{funcColumn} FROM {table} GROUP BY {keyColumn}
- * 如 queryColumnMapAsync(Record.class, "name", FilterFunc.MAX, "createtime") 等价于: SELECT name, MAX(createtime) FROM user GROUP BY name
+ * 如 queryColumnMapAsync(User.class, "name", FilterFunc.MAX, "createtime") 等价于: SELECT name, MAX(createtime) FROM user GROUP BY name
* * @param Entity泛型 * @param Key字段的数据类型 @@ -988,7 +988,7 @@ public interface DataSource { /** * 查询符合过滤条件记录的GROUP BY聚合结果Map
* 等价SQL: SELECT keyColumn, FUNC{funcColumn} FROM {table} WHERE {filter bean} GROUP BY {keyColumn}
- * 如 queryColumnMapAsync(Record.class, "name", FilterFunc.MAX, "createtime", (FilterBean)null) 等价于: SELECT name, MAX(createtime) FROM user GROUP BY name
+ * 如 queryColumnMapAsync(User.class, "name", FilterFunc.MAX, "createtime", (FilterBean)null) 等价于: SELECT name, MAX(createtime) FROM user GROUP BY name
* * @param Entity泛型 * @param Key字段的数据类型 @@ -1006,7 +1006,7 @@ public interface DataSource { /** * 查询符合过滤条件记录的GROUP BY聚合结果Map
* 等价SQL: SELECT keyColumn, FUNC{funcColumn} FROM {table} WHERE {filter bean} GROUP BY {keyColumn}
- * 如 queryColumnMapAsync(Record.class, "name", FilterFunc.MAX, "createtime", (FilterBean)null) 等价于: SELECT name, MAX(createtime) FROM user GROUP BY name
+ * 如 queryColumnMapAsync(User.class, "name", FilterFunc.MAX, "createtime", (FilterBean)null) 等价于: SELECT name, MAX(createtime) FROM user GROUP BY name
* * @param Entity泛型 * @param Key字段的数据类型 @@ -1024,7 +1024,7 @@ public interface DataSource { /** * 查询符合过滤条件记录的GROUP BY聚合结果Map
* 等价SQL: SELECT keyColumn, FUNC{funcColumn} FROM {table} WHERE {filter node} GROUP BY {keyColumn}
- * 如 queryColumnMapAsync(Record.class, "name", FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT name, MAX(createtime) FROM user GROUP BY name
+ * 如 queryColumnMapAsync(User.class, "name", FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT name, MAX(createtime) FROM user GROUP BY name
* * @param Entity泛型 * @param Key字段的数据类型 @@ -1042,7 +1042,7 @@ public interface DataSource { /** * 查询符合过滤条件记录的GROUP BY聚合结果Map
* 等价SQL: SELECT keyColumn, FUNC{funcColumn} FROM {table} WHERE {filter node} GROUP BY {keyColumn}
- * 如 queryColumnMapAsync(Record.class, "name", FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT name, MAX(createtime) FROM user GROUP BY name
+ * 如 queryColumnMapAsync(User.class, "name", FilterFunc.MAX, "createtime", (FilterNode)null) 等价于: SELECT name, MAX(createtime) FROM user GROUP BY name
* * @param Entity泛型 * @param Key字段的数据类型 @@ -1057,6 +1057,218 @@ public interface DataSource { */ public CompletableFuture> queryColumnMapAsync(final Class entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, final FilterNode node); + /** + * 查询符合过滤条件记录的GROUP BY聚合结果Map
+ * 等价SQL: SELECT col1, FUNC{funcColumn1}, FUNC{funcColumn2} FROM {table} WHERE GROUP BY {col1}
+ * 如 queryColumnMapAsync(OrderRecord.class, Utility.ofArray(ColumnNodeValue.div(ColumnFuncNode.sum("money"), 100), ColumnFuncNode.avg(ColumnNodeValue.dec("money", 20)))), "targetid") + * 等价于: SELECT targetid, SUM(money) / 100, AVG(money - 20) FROM orderrecord GROUP BY targetid
+ * + * @param Entity泛型 + * @param Key字段的数据类型 + * @param Number + * @param entityClass Entity类 + * @param funcNodes ColumnNode[] + * @param groupByColumn GROUP BY字段 + * + * @return 聚合结果Map CompletableFuture + */ + public Map queryColumnMap(final Class entityClass, final ColumnNode[] funcNodes, final String groupByColumn); + + /** + * 查询符合过滤条件记录的GROUP BY聚合结果Map
+ * 等价SQL: SELECT col1, FUNC{funcColumn1}, FUNC{funcColumn2} FROM {table} GROUP BY {col1}
+ * 如 queryColumnMapAsync(OrderRecord.class, Utility.ofArray(ColumnNodeValue.div(ColumnFuncNode.sum("money"), 100), ColumnFuncNode.avg(ColumnNodeValue.dec("money", 20)))), "targetid") + * 等价于: SELECT targetid, SUM(money) / 100, AVG(money - 20) FROM orderrecord GROUP BY targetid
+ * + * @param Entity泛型 + * @param Key字段的数据类型 + * @param Number + * @param entityClass Entity类 + * @param funcNodes ColumnNode[] + * @param groupByColumn GROUP BY字段 + * + * @return 聚合结果Map CompletableFuture + */ + public CompletableFuture> queryColumnMapAsync(final Class entityClass, final ColumnNode[] funcNodes, final String groupByColumn); + + /** + * 查询符合过滤条件记录的GROUP BY聚合结果Map
+ * 等价SQL: SELECT col1, FUNC{funcColumn1}, FUNC{funcColumn2} FROM {table} WHERE {filter bean} GROUP BY {col1}
+ * 如 queryColumnMapAsync(OrderRecord.class, Utility.ofArray(ColumnNodeValue.div(ColumnFuncNode.sum("money"), 100), ColumnFuncNode.avg(ColumnNodeValue.dec("money", 20)))), "targetid", (FilterBean)null) + * 等价于: SELECT targetid, SUM(money) / 100, AVG(money - 20) FROM orderrecord GROUP BY targetid
+ * + * @param Entity泛型 + * @param Key字段的数据类型 + * @param Number + * @param entityClass Entity类 + * @param funcNodes ColumnNode[] + * @param groupByColumn GROUP BY字段 + * @param bean 过滤条件 + * + * @return 聚合结果Map CompletableFuture + */ + public Map queryColumnMap(final Class entityClass, final ColumnNode[] funcNodes, final String groupByColumn, final FilterBean bean); + + /** + * 查询符合过滤条件记录的GROUP BY聚合结果Map
+ * 等价SQL: SELECT col1, FUNC{funcColumn1}, FUNC{funcColumn2} FROM {table} WHERE {filter bean} GROUP BY {col1}
+ * 如 queryColumnMapAsync(OrderRecord.class, Utility.ofArray(ColumnNodeValue.div(ColumnFuncNode.sum("money"), 100), ColumnFuncNode.avg(ColumnNodeValue.dec("money", 20)))), "targetid", (FilterBean)null) + * 等价于: SELECT targetid, SUM(money) / 100, AVG(money - 20) FROM orderrecord GROUP BY targetid
+ * + * @param Entity泛型 + * @param Key字段的数据类型 + * @param Number + * @param entityClass Entity类 + * @param funcNodes ColumnNode[] + * @param groupByColumn GROUP BY字段 + * @param bean 过滤条件 + * + * @return 聚合结果Map CompletableFuture + */ + public CompletableFuture> queryColumnMapAsync(final Class entityClass, final ColumnNode[] funcNodes, final String groupByColumn, final FilterBean bean); + + /** + * 查询符合过滤条件记录的GROUP BY聚合结果Map
+ * 等价SQL: SELECT col1, FUNC{funcColumn1}, FUNC{funcColumn2} FROM {table} WHERE {filter node} GROUP BY {col1}
+ * 如 queryColumnMapAsync(OrderRecord.class, Utility.ofArray(ColumnNodeValue.div(ColumnFuncNode.sum("money"), 100), ColumnFuncNode.avg(ColumnNodeValue.dec("money", 20)))), "targetid", (FilterNode)null) + * 等价于: SELECT targetid, SUM(money) / 100, AVG(money - 20) FROM orderrecord GROUP BY targetid
+ * + * @param Entity泛型 + * @param Key字段的数据类型 + * @param Number + * @param entityClass Entity类 + * @param funcNodes ColumnNode[] + * @param groupByColumn GROUP BY字段 + * @param node 过滤条件 + * + * @return 聚合结果Map CompletableFuture + */ + public Map queryColumnMap(final Class entityClass, final ColumnNode[] funcNodes, final String groupByColumn, final FilterNode node); + + /** + * 查询符合过滤条件记录的GROUP BY聚合结果Map
+ * 等价SQL: SELECT col1, FUNC{funcColumn1}, FUNC{funcColumn2} FROM {table} WHERE {filter node} GROUP BY {col1}
+ * 如 queryColumnMapAsync(OrderRecord.class, Utility.ofArray(ColumnNodeValue.div(ColumnFuncNode.sum("money"), 100), ColumnFuncNode.avg(ColumnNodeValue.dec("money", 20)))), "targetid", (FilterNode)null) + * 等价于: SELECT targetid, SUM(money) / 100, AVG(money - 20) FROM orderrecord GROUP BY targetid
+ * + * @param Entity泛型 + * @param Key字段的数据类型 + * @param Number + * @param entityClass Entity类 + * @param funcNodes ColumnNode[] + * @param groupByColumn GROUP BY字段 + * @param node 过滤条件 + * + * @return 聚合结果Map CompletableFuture + */ + public CompletableFuture> queryColumnMapAsync(final Class entityClass, final ColumnNode[] funcNodes, final String groupByColumn, final FilterNode node); + + /** + * 查询符合过滤条件记录的GROUP BY聚合结果Map
+ * 等价SQL: SELECT col1, col2, FUNC{funcColumn1}, FUNC{funcColumn2} FROM {table} GROUP BY {col1}, {col2}
+ * 如 queryColumnMapAsync(OrderRecord.class, Utility.ofArray(ColumnNodeValue.div(ColumnFuncNode.sum("money"), 100), ColumnFuncNode.avg(ColumnNodeValue.dec("money", 20)))), Utility.ofArray("fromid", "targetid")) + * 等价于: SELECT fromid, targetid, SUM(money) / 100, AVG(money - 20) FROM orderrecord GROUP BY fromid, targetid
+ * + * @param Entity泛型 + * @param Key字段的数据类型 + * @param Number + * @param entityClass Entity类 + * @param funcNodes ColumnNode[] + * @param groupByColumns GROUP BY字段 + * + * @return 聚合结果Map CompletableFuture + */ + public Map queryColumnMap(final Class entityClass, final ColumnNode[] funcNodes, final String[] groupByColumns); + + /** + * 查询符合过滤条件记录的GROUP BY聚合结果Map
+ * 等价SQL: SELECT col1, col2, FUNC{funcColumn1}, FUNC{funcColumn2} FROM {table} GROUP BY {col1}, {col2}
+ * 如 queryColumnMapAsync(OrderRecord.class, Utility.ofArray(ColumnNodeValue.div(ColumnFuncNode.sum("money"), 100), ColumnFuncNode.avg(ColumnNodeValue.dec("money", 20)))), Utility.ofArray("fromid", "targetid")) + * 等价于: SELECT fromid, targetid, SUM(money) / 100, AVG(money - 20) FROM orderrecord GROUP BY fromid, targetid
+ * + * @param Entity泛型 + * @param Key字段的数据类型 + * @param Number + * @param entityClass Entity类 + * @param funcNodes ColumnNode[] + * @param groupByColumns GROUP BY字段 + * + * @return 聚合结果Map CompletableFuture + */ + public CompletableFuture> queryColumnMapAsync(final Class entityClass, final ColumnNode[] funcNodes, final String[] groupByColumns); + + /** + * 查询符合过滤条件记录的GROUP BY聚合结果Map
+ * 等价SQL: SELECT col1, col2, FUNC{funcColumn1}, FUNC{funcColumn2} FROM {table} WHERE {filter bean} GROUP BY {col1}, {col2}
+ * 如 queryColumnMapAsync(OrderRecord.class, Utility.ofArray(ColumnNodeValue.div(ColumnFuncNode.sum("money"), 100), ColumnFuncNode.avg(ColumnNodeValue.dec("money", 20)))), Utility.ofArray("fromid", "targetid"), (FilterBean)null) + * 等价于: SELECT fromid, targetid, SUM(money) / 100, AVG(money - 20) FROM orderrecord GROUP BY fromid, targetid
+ * + * @param Entity泛型 + * @param Key字段的数据类型 + * @param Number + * @param entityClass Entity类 + * @param funcNodes ColumnNode[] + * @param groupByColumns GROUP BY字段 + * @param bean 过滤条件 + * + * @return 聚合结果Map CompletableFuture + */ + public Map queryColumnMap(final Class entityClass, final ColumnNode[] funcNodes, final String[] groupByColumns, final FilterBean bean); + + /** + * 查询符合过滤条件记录的GROUP BY聚合结果Map
+ * 等价SQL: SELECT col1, col2, FUNC{funcColumn1}, FUNC{funcColumn2} FROM {table} WHERE {filter bean} GROUP BY {col1}, {col2}
+ * 如 queryColumnMapAsync(OrderRecord.class, Utility.ofArray(ColumnNodeValue.div(ColumnFuncNode.sum("money"), 100), ColumnFuncNode.avg(ColumnNodeValue.dec("money", 20)))), Utility.ofArray("fromid", "targetid"), (FilterBean)null) + * 等价于: SELECT fromid, targetid, SUM(money) / 100, AVG(money - 20) FROM orderrecord GROUP BY fromid, targetid
+ * + * @param Entity泛型 + * @param Key字段的数据类型 + * @param Number + * @param entityClass Entity类 + * @param funcNodes ColumnNode[] + * @param groupByColumns GROUP BY字段 + * @param bean 过滤条件 + * + * @return 聚合结果Map CompletableFuture + */ + public CompletableFuture> queryColumnMapAsync(final Class entityClass, final ColumnNode[] funcNodes, final String[] groupByColumns, final FilterBean bean); + + /** + * 查询符合过滤条件记录的GROUP BY聚合结果Map
+ * 等价SQL: SELECT col1, col2, FUNC{funcColumn1}, FUNC{funcColumn2} FROM {table} WHERE {filter node} GROUP BY {col1}, {col2}
+ * 如 queryColumnMapAsync(OrderRecord.class, Utility.ofArray(ColumnNodeValue.div(ColumnFuncNode.sum("money"), 100), ColumnFuncNode.avg(ColumnNodeValue.dec("money", 20)))), Utility.ofArray("fromid", "targetid"), (FilterNode)null) + * 等价于: SELECT fromid, targetid, SUM(money) / 100, AVG(money - 20) FROM orderrecord GROUP BY fromid, targetid
+ * + * @param Entity泛型 + * @param Key字段的数据类型 + * @param Number + * @param entityClass Entity类 + * @param funcNodes ColumnNode[] + * @param groupByColumns GROUP BY字段 + * @param node 过滤条件 + * + * @return 聚合结果Map + */ + public Map queryColumnMap(final Class entityClass, final ColumnNode[] funcNodes, final String[] groupByColumns, final FilterNode node); + + /** + * 查询符合过滤条件记录的GROUP BY聚合结果Map
+ * 等价SQL: SELECT col1, col2, FUNC{funcColumn1}, FUNC{funcColumn2} FROM {table} WHERE {filter node} GROUP BY {col1}, {col2}
+ * 如 queryColumnMapAsync(OrderRecord.class, Utility.ofArray(ColumnNodeValue.div(ColumnFuncNode.sum("money"), 100), ColumnFuncNode.avg(ColumnNodeValue.dec("money", 20)))), Utility.ofArray("fromid", "targetid"), (FilterNode)null) + * 等价于: SELECT fromid, targetid, SUM(money) / 100, AVG(money - 20) FROM orderrecord GROUP BY fromid, targetid
+ * + * @param Entity泛型 + * @param Key字段的数据类型 + * @param Number + * @param entityClass Entity类 + * @param funcNodes ColumnNode[] + * @param groupByColumns GROUP BY字段 + * @param node 过滤条件 + * + * @return 聚合结果Map CompletableFuture + */ + public CompletableFuture> queryColumnMapAsync(final Class entityClass, final ColumnNode[] funcNodes, final String[] groupByColumns, final FilterNode node); + //-----------------------findAsync---------------------------- /** * 获取指定主键值的单个记录, 返回null表示不存在值
diff --git a/src/org/redkale/source/DataSqlSource.java b/src/org/redkale/source/DataSqlSource.java index 5f6b7f9db..927c20e4b 100644 --- a/src/org/redkale/source/DataSqlSource.java +++ b/src/org/redkale/source/DataSqlSource.java @@ -157,6 +157,9 @@ public abstract class DataSqlSource extends AbstractService implement //查询Map数据 protected abstract CompletableFuture> queryColumnMapDB(final EntityInfo info, final String sql, final String keyColumn); + //查询Map数据 + protected abstract CompletableFuture> queryColumnMapDB(final EntityInfo info, final String sql, final ColumnNode[] funcNodes, final String[] groupByColumns); + //查询单条记录 protected abstract CompletableFuture findDB(final EntityInfo info, final String sql, final boolean onlypk, final SelectColumn selects); @@ -1532,6 +1535,118 @@ public abstract class DataSqlSource extends AbstractService implement return queryColumnMapDB(info, sql, keyColumn); } + @Override + public Map queryColumnMap(final Class entityClass, final ColumnNode[] funcNodes, final String groupByColumn) { + return queryColumnMap(entityClass, funcNodes, groupByColumn, (FilterNode) null); + } + + @Override + public CompletableFuture> queryColumnMapAsync(final Class entityClass, final ColumnNode[] funcNodes, final String groupByColumn) { + return queryColumnMapAsync(entityClass, funcNodes, groupByColumn, (FilterNode) null); + } + + @Override + public Map queryColumnMap(final Class entityClass, final ColumnNode[] funcNodes, final String groupByColumn, final FilterBean bean) { + return queryColumnMap(entityClass, funcNodes, groupByColumn, FilterNodeBean.createFilterNode(bean)); + } + + @Override + public CompletableFuture> queryColumnMapAsync(final Class entityClass, final ColumnNode[] funcNodes, final String groupByColumn, final FilterBean bean) { + return queryColumnMapAsync(entityClass, funcNodes, groupByColumn, FilterNodeBean.createFilterNode(bean)); + } + + @Override + public Map queryColumnMap(final Class entityClass, final ColumnNode[] funcNodes, final String groupByColumn, final FilterNode node) { + Map map = queryColumnMap(entityClass, funcNodes, Utility.ofArray(groupByColumn), node); + final Map rs = new LinkedHashMap<>(); + map.forEach((keys, values) -> rs.put(keys[0], values)); + return rs; + } + + @Override + public CompletableFuture> queryColumnMapAsync(final Class entityClass, final ColumnNode[] funcNodes, final String groupByColumn, final FilterNode node) { + CompletableFuture> future = queryColumnMapAsync(entityClass, funcNodes, Utility.ofArray(groupByColumn), node); + return future.thenApply(map -> { + final Map rs = new LinkedHashMap<>(); + map.forEach((keys, values) -> rs.put(keys[0], values)); + return rs; + }); + } + + @Override + public Map queryColumnMap(final Class entityClass, final ColumnNode[] funcNodes, final String[] groupByColumns) { + return queryColumnMap(entityClass, funcNodes, groupByColumns, (FilterNode) null); + } + + @Override + public CompletableFuture> queryColumnMapAsync(final Class entityClass, final ColumnNode[] funcNodes, final String[] groupByColumns) { + return queryColumnMapAsync(entityClass, funcNodes, groupByColumns, (FilterNode) null); + } + + @Override + public Map queryColumnMap(final Class entityClass, final ColumnNode[] funcNodes, final String[] groupByColumns, final FilterBean bean) { + return queryColumnMap(entityClass, funcNodes, groupByColumns, FilterNodeBean.createFilterNode(bean)); + } + + @Override + public CompletableFuture> queryColumnMapAsync(final Class entityClass, final ColumnNode[] funcNodes, final String[] groupByColumns, final FilterBean bean) { + return queryColumnMapAsync(entityClass, funcNodes, groupByColumns, FilterNodeBean.createFilterNode(bean)); + } + + @Override + public Map queryColumnMap(final Class entityClass, final ColumnNode[] funcNodes, final String[] groupByColumns, final FilterNode node) { + final EntityInfo info = loadEntityInfo(entityClass); + final EntityCache cache = info.getCache(); + if (cache != null && (isOnlyCache(info) || cache.isFullLoaded())) { + if (node == null || node.isCacheUseable(this)) { + return cache.queryColumnMap(funcNodes, groupByColumns, node); + } + } + return (Map) queryColumnMapCompose(info, funcNodes, groupByColumns, node).join(); + } + + @Override + public CompletableFuture> queryColumnMapAsync(final Class entityClass, final ColumnNode[] funcNodes, final String[] groupByColumns, final FilterNode node) { + final EntityInfo info = loadEntityInfo(entityClass); + final EntityCache cache = info.getCache(); + if (cache != null && (isOnlyCache(info) || cache.isFullLoaded())) { + if (node == null || node.isCacheUseable(this)) { + return CompletableFuture.completedFuture(cache.queryColumnMap(funcNodes, groupByColumns, node)); + } + } + if (isAsync()) return queryColumnMapCompose(info, funcNodes, groupByColumns, node); + return CompletableFuture.supplyAsync(() -> (Map) queryColumnMapCompose(info, funcNodes, groupByColumns, node).join(), getExecutor()); + } + + protected CompletableFuture> queryColumnMapCompose(final EntityInfo info, final ColumnNode[] funcNodes, final String[] groupByColumns, final FilterNode node) { + final StringBuilder groupBySqlColumns = new StringBuilder(); + if (groupByColumns != null && groupByColumns.length > 0) { + for (int i = 0; i < groupByColumns.length; i++) { + if (groupBySqlColumns.length() > 0) groupBySqlColumns.append(", "); + groupBySqlColumns.append(info.getSQLColumn("a", groupByColumns[i])); + } + } + final StringBuilder funcSqlColumns = new StringBuilder(); + for (int i = 0; i < funcNodes.length; i++) { + if (funcSqlColumns.length() > 0) funcSqlColumns.append(", "); + if (funcNodes[i] instanceof ColumnFuncNode) { + funcSqlColumns.append(info.formatSQLValue((Attribute) null, "a", (ColumnFuncNode) funcNodes[i], sqlFormatter)); + } else { + funcSqlColumns.append(info.formatSQLValue((Attribute) null, "a", (ColumnNodeValue) funcNodes[i], sqlFormatter)); + } + } + final Map joinTabalis = node == null ? null : node.getJoinTabalis(); + final Set haset = new HashSet<>(); + final CharSequence join = node == null ? null : node.createSQLJoin(this, false, joinTabalis, haset, info); + final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis); + String sql = "SELECT "; + if (groupBySqlColumns.length() > 0) sql += groupBySqlColumns + ", "; + sql += funcSqlColumns + " FROM " + info.getTable(node) + " a" + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)); + if (groupBySqlColumns.length() > 0) sql += " GROUP BY " + groupBySqlColumns; + if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " querycolumnmap sql=" + sql); + return queryColumnMapDB(info, sql, funcNodes, groupByColumns); + } + //----------------------------- findCompose ----------------------------- /** * 根据主键获取对象 diff --git a/src/org/redkale/source/EntityCache.java b/src/org/redkale/source/EntityCache.java index 459816a46..6cec2ab27 100644 --- a/src/org/redkale/source/EntityCache.java +++ b/src/org/redkale/source/EntityCache.java @@ -310,6 +310,10 @@ public final class EntityCache { return rs; } + public Map queryColumnMap(final ColumnNode[] funcNodes, final String[] groupByColumns, FilterNode node) { + throw new UnsupportedOperationException("Not supported yet."); + } + public Number getNumberResult(final FilterFunc func, final Number defResult, final String column, final FilterNode node) { final Attribute attr = column == null ? null : info.getAttribute(column); final Predicate filter = node == null ? null : node.createPredicate(this); diff --git a/src/org/redkale/source/EntityInfo.java b/src/org/redkale/source/EntityInfo.java index c13ab5512..39f401591 100644 --- a/src/org/redkale/source/EntityInfo.java +++ b/src/org/redkale/source/EntityInfo.java @@ -974,7 +974,8 @@ public final class EntityInfo { if (cv == null) return null; Object val = cv.getValue(); //ColumnNodeValue时 cv.getExpress() == ColumnExpress.MOV 只用于updateColumn - if (val instanceof ColumnNodeValue) return formatSQLValue(attr, (ColumnNodeValue) val, formatter); + if (val instanceof ColumnNodeValue) return formatSQLValue(attr, null, (ColumnNodeValue) val, formatter); + if (val instanceof ColumnFuncNode) return formatSQLValue(attr, null, (ColumnFuncNode) val, formatter); switch (cv.getExpress()) { case INC: return new StringBuilder().append(sqlColumn).append(" + ").append(val); @@ -1000,18 +1001,30 @@ public final class EntityInfo { return formatter == null ? formatToString(val) : formatter.apply(this, val); } - protected CharSequence formatSQLValue(Attribute attr, final ColumnNodeValue node, BiFunction formatter) { + protected CharSequence formatSQLValue(Attribute attr, String tabalis, final ColumnFuncNode node, BiFunction formatter) { + if (node.getValue() instanceof ColumnNodeValue) { + return node.getFunc().getColumn(formatSQLValue(attr, tabalis, (ColumnNodeValue) node.getValue(), formatter).toString()); + } else { + return node.getFunc().getColumn(this.getSQLColumn(tabalis, String.valueOf(node.getValue()))); + } + } + + protected CharSequence formatSQLValue(Attribute attr, String tabalis, final ColumnNodeValue node, BiFunction formatter) { Serializable left = node.getLeft(); if (left instanceof CharSequence) { - left = this.getSQLColumn(null, left.toString()); + left = this.getSQLColumn(tabalis, left.toString()); } else if (left instanceof ColumnNodeValue) { - left = "(" + formatSQLValue(attr, (ColumnNodeValue) left, formatter) + ")"; + left = "(" + formatSQLValue(attr, tabalis, (ColumnNodeValue) left, formatter) + ")"; + } else if (left instanceof ColumnFuncNode) { + left = "(" + formatSQLValue(attr, tabalis, (ColumnFuncNode) left, formatter) + ")"; } Serializable right = node.getRight(); if (right instanceof CharSequence) { right = this.getSQLColumn(null, right.toString()); } else if (left instanceof ColumnNodeValue) { - right = "(" + formatSQLValue(attr, (ColumnNodeValue) right, formatter) + ")"; + right = "(" + formatSQLValue(attr, tabalis, (ColumnNodeValue) right, formatter) + ")"; + } else if (left instanceof ColumnFuncNode) { + right = "(" + formatSQLValue(attr, tabalis, (ColumnFuncNode) right, formatter) + ")"; } switch (node.getExpress()) { case INC: