package jef.database.query; import java.util.ArrayList; import java.util.List; import jef.database.Condition; import jef.database.Condition.Operator; import jef.database.DbFunction; import jef.database.DbUtils; import jef.database.Field; import jef.database.dialect.DatabaseDialect; import jef.database.dialect.type.ColumnMapping; import jef.database.meta.ITableMetadata; import jef.database.wrapper.clause.HavingEle; public final class SelectColumn extends SingleColumnSelect{ private String populateTo;//拼装路径,默认应该和alias一致 private String alias; private Field targetField; private ITableMetadata meta; protected List<DbFunctionCall> func; //附加的函数 //缓存一个不带别名的列,以提高速度 private String columnSimpleName;//不带别名的参数 /** * 转换为Having子句 */ public HavingEle toHavingClause(DatabaseDialect profile,String tableAlias,SqlContext context){ HavingEle h=new HavingEle(); String column=innerGetColumn(profile, tableAlias); h.column=column; h.sql=Condition.toSql(column, havingCondOperator, havingCondValue, profile, null, null); h.havingCondOperator=this.havingCondOperator; h.havingCondValue=this.havingCondValue; return h; } /** * 设置having子句条件 * @param oper * @param value * @return */ public SelectColumn having(Operator oper,Object value){ this.projection=projection| PROJECTION_HAVING; this.havingCondOperator=oper; this.havingCondValue=value; return this; } /** * 设置having子句条件(该表达式不作为被选择列)。默认情况下 .column().sum().having(">",100);时, column().sum()也会作为查询列之一被查出。 * 使用havingOnly方法添加的having则是纯作为条件,不会作为查询列。 * * @param oper * @param value * @return */ public SelectColumn havingOnly(Operator oper,Object value){ this.projection=projection |PROJECTION_HAVING_NOT_SELECT; this.havingCondOperator=oper; this.havingCondValue=value; return this; } /** * count(xxx) * @return */ public SelectColumn count(){ this.projection=PROJECTION_COUNT; return this; } /** * 求和 * @return */ public SelectColumn sum(){ this.projection=PROJECTION_SUM; return this; } /** * 求平均数 * @return */ public SelectColumn avg(){ this.projection=PROJECTION_AVG; return this; } /** * 取最大值 * @return */ public SelectColumn max(){ this.projection=PROJECTION_MAX; return this; } /** * 取最小值 * @return */ public SelectColumn min(){ this.projection=PROJECTION_MIN; return this; } /** * 对应count(distinct xx) * @return */ public SelectColumn countDistinct(){ this.projection=PROJECTION_COUNT_DISTINCT; return this; } /** * 指定按照此列进行 group by操作,同时选出此列 * @return */ public SelectColumn group() { this.projection=PROJECTION_GROUP; return this; } /** * 指定按此列进行函数计算 * @param func * @param params * @return */ public SelectColumn funcTemplate(String func,String... params){ this.projection=PROJECTION_CUST_FUNC; if(this.func==null){ this.func=new ArrayList<DbFunctionCall>(); } this.func.add(new DbFunctionCall(func,params)); return this; } /** * 指定按此列进行函数计算 * @param func * @param params * @return */ public SelectColumn func(DbFunction func,String... params){ this.projection=PROJECTION_CUST_FUNC; if(this.func==null){ this.func=new ArrayList<DbFunctionCall>(); } this.func.add(new DbFunctionCall(func,params)); return this; } SelectColumn(Field field,String populateTo){ this.targetField=field; if(populateTo==null)populateTo=field.name(); this.populateTo=populateTo; this.meta=DbUtils.getTableMeta(field); } void setProjection(int projection) { this.projection = projection; } /** * 将Projection重置 */ public void clearProjection(){ this.projection=PROJECTION_NORMAL; this.func=null; } /** * 指定别名。这个方法不仅仅指定该查询列的别名,还指定该列将写入到指定对象字段中去 * @param alias * @return */ public SelectColumn as(String alias) { this.alias = alias; if(alias!=null){ this.populateTo=alias; } return this; } public SelectColumn toField(String property){ this.populateTo=property; return this; } public String getName() { return populateTo; } // 生成选择语句时生成列名别,null表示无别名 public String getSelectedAlias(String tableAlias,DatabaseDialect profile) { return DbUtils.escapeColumn(profile,profile.getObjectNameToUse(alias)); } @Override public String getResultAlias(String tableAlias, DatabaseDialect profile) { if(alias==null){ if(columnSimpleName==null){ throw new IllegalArgumentException(); } return columnSimpleName.toUpperCase(); }else{ return alias.toUpperCase(); } } private String innerGetColumn(DatabaseDialect profile,String tableAlias){ //因为第一次操作列名改为额大写,造成第二次Parse出错 columnSimpleName=DbUtils.toColumnName(targetField, profile,null);//不带别名的列名 String name= DbUtils.toColumnName(targetField, profile,tableAlias); int key=projection & 0xFF; if(key>0){ // if(StringUtils.isEmpty(alias)){//强行取Alias(无必要) // alias="C".concat(RandomStringUtils.randomAlphanumeric(12)); // } switch(key){ case PROJECTION_COUNT: return "count(".concat(name).concat(")"); case PROJECTION_COUNT_DISTINCT: return "count(distinct ".concat(name).concat(")"); case PROJECTION_SUM: return "sum(".concat(name).concat(")"); case PROJECTION_AVG: return "avg(".concat(name).concat(")"); case PROJECTION_MAX: return "max(".concat(name).concat(")"); case PROJECTION_MIN: return "min(".concat(name).concat(")"); case PROJECTION_CUST_FUNC: String start=name; for(DbFunctionCall func:this.func){ Object[] args; if(func.getVarIndex()==-1){ args=new String[]{start}; }else{ args=func.getArgs(); args[func.getVarIndex()]=start; } if(func.getFunc()==null){ StringBuilder sb=new StringBuilder(func.getName()).append('('); for(int i=0;i<args.length;i++){ if(i>0){ sb.append(", "); } sb.append(args[i]); } start=sb.append(')').toString(); }else{ start=profile.getFunction(func.getFunc(),args); } } return start; default: throw new IllegalArgumentException("Unknown projection "+ key); } }else{ return name; } } //当生成选择语句时计算列名称 public String getSelectItem(DatabaseDialect profile,String tableAlias,SqlContext context) { if(targetField==null)return null; if((projection & PROJECTION_HAVING_NOT_SELECT)>0){ return null;//纯having的列,不进行select,也不进行group } if(targetField instanceof JpqlExpression){ return columnSimpleName=((JpqlExpression) targetField).toSqlAndBindAttribs(context, profile); } return innerGetColumn(profile,tableAlias); } public boolean isSingleColumn() { return true; } public ColumnMapping getTargetColumnType() { return meta.getColumnDef(targetField); } @Override public String toString() { return populateTo+":"+targetField+(alias==null?"":" as "+alias); } }