package jef.database.query;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import jef.common.log.LogUtil;
import jef.database.DbUtils;
import jef.database.Field;
import jef.database.QueryAlias;
import jef.database.dialect.type.ColumnMapping;
import jef.database.jsqlparser.expression.Column;
import jef.database.jsqlparser.parser.ParseException;
import jef.database.jsqlparser.statement.select.SelectExpressionItem;
import jef.database.jsqlparser.visitor.Expression;
import jef.database.jsqlparser.visitor.SelectItem;
import jef.database.meta.FBIField;
import jef.database.meta.ITableMetadata;
import jef.database.meta.MetaHolder;
import jef.tools.Assert;
/**
* SelectItems的实现类,供选取列,用于在Criteria API中定制查询
*
* @author Jiyi
*
*/
public class SelectsImpl extends AbstractEntityMappingProvider implements Selects {
private static final long serialVersionUID = -7074691304983975019L;
Set<QueryAlias> touchQueries=new HashSet<QueryAlias>();
public SelectsImpl() {
}
// private void add(QueryAlias config,IReferenceColumn field){
// if(!touchQueries.contains(config)){
// if(config.getReferenceObj()!=null){
// noColums(config.getTableDef());
// }
// }
// config.addField(field);
// touchQueries.add(config);
// }
//
// private void add(QueryAlias config,IReferenceAllTable field){
// config.addField(field);
// touchQueries.add(config);
// }
public SelectsImpl(List<QueryAlias> context) {
this.queries = context;
}
public AllTableColumns allTableColumns(Query<?> query) {
return allColumns(query);
}
public AllTableColumns allColumns(Query<?> q) {
return allTableColumns(null, q);
}
public SelectColumn column(Field field) {
ITableMetadata meta = DbUtils.getTableMeta(field);
QueryAlias qa = findQuery(meta, null);
Query<?> found;
if (qa == null) {
throw new IllegalArgumentException("the " + meta.getThisType() + " not found in the query tables.");
}else{
found=qa.getTableDef();
}
return column(found, field, null, field.name());
}
public void columns(Field... fields) {
for (Field f : fields) {
column(f);
}
}
public SelectColumn column(Query<?> query, Field name) {
return column(query, name, null, null);
}
/*
* (non-Javadoc)
*
* @see jef.database.query.SelectItems#column(jef.database.query.Query,
* java.lang.String)
*/
public SelectColumn column(Query<?> query, String name) {
QueryAlias config = findQuery(query); // 目前其实只有QueryAlias一个实现
Assert.notNull(config, "the query is not contain in the join tables.");
ITableMetadata meta = MetaHolder.getMeta(query.getInstance());
Field field = meta.getField(name);
if (field == null)
field = new FBIField(name, query);
return column(query, field, null, null);
}
/*
* (non-Javadoc)
*
* @see jef.database.query.SelectItems#guessColumn(java.lang.String,
* java.lang.String)
*/
public SelectColumn guessColumn(String name) {
Field field = null;
Query<?> matched = null;
if (name.indexOf('(') > -1 || name.indexOf('|') > -1) {// 无法支持FBIField?
if (queries.size() > 0) {
matched = queries.get(0).getTableDef();
field = new FBIField(name, matched);
return column(matched, field, null, null);
}
}
for (ISelectItemProvider qa : this.queries) {
ITableMetadata meta = MetaHolder.getMeta(qa.getTableDef().getInstance());
Field find = meta.getField(name);
if (find != null && field != null) {
LogUtil.error("There are duplicate field named '" + name + "' in multi table columns");
} else if (find != null) {
field = find;
matched = qa.getTableDef();
}
}
if (field == null)
return null;
return column(matched, field, null, null);
}
/*
* (non-Javadoc)
*
* @see jef.database.query.SelectItems#clearSelectItems()
*/
public void clearSelectItems() {
for (ISelectItemProvider i : this.queries) {
i.setFields(null);
}
}
public void columns(String string) {
if (queries.size() == 1) {
QueryAlias q = (QueryAlias) queries.get(0);
columns(q.getQuery(), string);
} else {
throw new IllegalArgumentException("This method allowed only for one table query.");
}
}
/*
* (non-Javadoc)
*
* @see jef.database.query.SelectItems#columns(jef.database.query.Query,
* java.lang.String)
*/
public void columns(Query<?> q, String columns) {
try {
List<SelectItem> items = DbUtils.parseSelectItems(columns);
ITableMetadata meta =q.getMeta();
for (SelectItem item : items) {
if (item instanceof SelectExpressionItem) {
SelectExpressionItem expression = (SelectExpressionItem) item;
Expression column=expression.getExpression();
String exp = column.toString();
ColumnMapping mapping = (column instanceof Column)?meta.findField(exp):null;
Field field;
if (mapping == null){
field = new FBIField(exp, q);
}else{
field=mapping.field();
}
this.column(q, field, expression.getAlias(), null);
} else if (item instanceof jef.database.jsqlparser.statement.select.AllTableColumns) {
jef.database.jsqlparser.statement.select.AllTableColumns at = (jef.database.jsqlparser.statement.select.AllTableColumns) item;
this.allTableColumns(at.getTable().getAlias(), q);
}
}
} catch (ParseException e) {
throw new IllegalArgumentException(columns);
}
}
public void merge(AbstractEntityMappingProvider selectItems) {
this.distinct=selectItems.distinct;
for (ISelectItemProvider os : this.getReference()) { // 新的
boolean found=false;
for (ISelectItemProvider is : selectItems.getReference()) { // 原先的
if (is.getTableDef() == os.getTableDef()) {
os.setFields(is.getReferenceObj(), is.getReferenceCol());
found=true;
break;
}
}
if(!found){
AllTableColumns ac = new AllTableColumns(os.getTableDef());
ac.notSelectAnyColumn();
ac.setName(null);
os.setFields(ac);
}
}
}
/**
* 创建查询表达式,支持方言改写。
* {@inheritDoc}
* <p>
* 如果在表达式中需要引用第一个表的别名,使用$1,$2...以此类推
*/
public SelectExpression sqlExpression(String sql) {
List<SelectItem> items;
try {
items = DbUtils.parseSelectItems(sql);
} catch (ParseException e) {
throw new IllegalArgumentException("unsupported expression: " + sql);
}
SelectExpression2 ac = null;
for (SelectItem item : items) {
if (item instanceof SelectExpressionItem) {
SelectExpressionItem i = (SelectExpressionItem) item;
ac = new SelectExpression2(i.getExpression());
ac.as(i.getAlias());
ISelectItemProvider config = this.queries.get(0);
config.addField(ac);
} else {
throw new IllegalArgumentException("unsupported expression: " + sql);
}
}
return ac;
}
/**
* {@inheritDoc}
*
* <p>
* 如果在表达式中需要引用第一个表的别名,使用$1,$2...以此类推
*/
public SelectExpression rawExpression(String sql) {
SelectExpression ac = new SelectExpression(sql);
ISelectItemProvider config = this.queries.get(0);
config.addField(ac);
return ac;
}
/**
* 指定一个选择列和别名
*
* @param fld
* 列
* @param alias
* 列的别名(在select中使用)
* @param query
* 对应的查询实例
* @param populateTo
* 结果最终拼装时的字段名
*/
private SelectColumn column(Query<?> query, Field fld, String alias, String populateTo) {
if (fld instanceof LazyQueryBindField) {
LazyQueryBindField qb = (LazyQueryBindField) fld;
if (!qb.isBind()) {
qb.setBind(query);
}
}
QueryAlias config = findQuery(query); // 目前其实只有QueryAlias一个实现
Assert.notNull(config, "the query is not contain in the join tables.");
SelectColumn ac = new SelectColumn(fld, populateTo);
ac.as(alias);
config.addField(ac);
return ac;
}
private AllTableColumns allTableColumns(String toField, Query<?> q) {
QueryAlias config = findQuery(q); // 目前其实只有QueryAlias一个实现
Assert.notNull(config, "the query is not contain in the join tables.");
AllTableColumns ac = new AllTableColumns(q);
ac.setName(toField);
config.addField(ac);
return ac;
}
/*
* (non-Javadoc)
*
* @see jef.database.query.SelectItems#noColums(jef.database.query.Query)
*/
public void noColums(Query<?> query) {
allColumns(query).notSelectAnyColumn();
}
}