package com.ctrip.platform.dal.dao.sqlbuilder; import java.sql.SQLException; import java.util.Comparator; import com.ctrip.platform.dal.common.enums.DatabaseCategory; import com.ctrip.platform.dal.dao.DalHintEnum; import com.ctrip.platform.dal.dao.DalHints; import com.ctrip.platform.dal.dao.DalResultSetExtractor; import com.ctrip.platform.dal.dao.DalRowMapper; import com.ctrip.platform.dal.dao.ResultMerger; import com.ctrip.platform.dal.dao.StatementParameters; import com.ctrip.platform.dal.dao.helper.DalFirstResultMerger; import com.ctrip.platform.dal.dao.helper.DalListMerger; import com.ctrip.platform.dal.dao.helper.DalObjectRowMapper; import com.ctrip.platform.dal.dao.helper.DalRangedResultMerger; import com.ctrip.platform.dal.dao.helper.DalRowMapperExtractor; import com.ctrip.platform.dal.dao.helper.DalSingleResultExtractor; import com.ctrip.platform.dal.dao.helper.DalSingleResultMerger; import com.ctrip.platform.dal.dao.helper.SupportPartialResultMapping; public class FreeSelectSqlBuilder<K> implements SqlBuilder, SelectBuilder { private String selectSqlTemplate; private DatabaseCategory dbCategory; private StatementParameters parameters; private DalRowMapper mapper; private ResultMerger merger; private DalResultSetExtractor extractor; private boolean requireFirst = false; private boolean requireSingle = false; private boolean nullable = false; private int count; private int start; public FreeSelectSqlBuilder(DatabaseCategory dbCategory) { this.dbCategory = dbCategory; } /** * If there is IN parameter, no matter how many values in the IN clause, the IN clause only need to * contain one "?". * E.g. SELECT ... WHERE id IN (?) * @param updateSqlTemplate */ public FreeSelectSqlBuilder<K> setTemplate(String selectSqlTemplate) { this.selectSqlTemplate= selectSqlTemplate; return this; } public FreeSelectSqlBuilder<K> with(StatementParameters parameters) { this.parameters = parameters; return this; } @Override public StatementParameters buildParameters() { return parameters; } public String build(){ if(count == 0) return selectSqlTemplate; return dbCategory.buildPage(selectSqlTemplate, start, count); } public <T> FreeSelectSqlBuilder<K> mapWith(DalRowMapper<T> mapper) { this.mapper = mapper; return this; } public <T> FreeSelectSqlBuilder<K> mapWith(Class<T> type) { return mapWith(new DalObjectRowMapper(type)); } public FreeSelectSqlBuilder<K> simpleType() { return mapWith(new DalObjectRowMapper()); } public FreeSelectSqlBuilder<K> requireFirst() { requireFirst = true; return this; } public FreeSelectSqlBuilder<K> requireSingle() { requireSingle = true; return this; } public FreeSelectSqlBuilder<K> nullable() { nullable = true; return this; } public FreeSelectSqlBuilder<K> setNullable(boolean nullable) { this.nullable = nullable; return this; } public boolean isRequireFirst () { return requireFirst; } public boolean isRequireSingle() { return requireSingle; } public boolean isNullable() { return nullable; } public FreeSelectSqlBuilder<K> top(int count) { this.count = count; return this; } public FreeSelectSqlBuilder<K> range(int start, int count) { this.start = start; this.count = count; return this; } public FreeSelectSqlBuilder<K> atPage(int pageNo, int pageSize) throws SQLException { if(pageNo < 1 || pageSize < 1) throw new SQLException("Illigal pagesize or pageNo, please check"); range((pageNo - 1) * pageSize, pageSize); return this; } @Override public <T> FreeSelectSqlBuilder<K> mergerWith(ResultMerger<T> merger) { this.merger = merger; return this; } @Override public <T> FreeSelectSqlBuilder<K> extractorWith(DalResultSetExtractor<T> extractor) { this.extractor = extractor; return this; } public <T> ResultMerger<T> getResultMerger(DalHints hints){ if(hints.is(DalHintEnum.resultMerger)) return (ResultMerger<T>)hints.get(DalHintEnum.resultMerger); if(merger != null) return merger; if(isRequireSingle() || isRequireFirst()) return isRequireSingle() ? new DalSingleResultMerger() : new DalFirstResultMerger((Comparator)hints.getSorter()); return count > 0 ? new DalRangedResultMerger((Comparator)hints.getSorter(), count): new DalListMerger((Comparator)hints.getSorter()); } public <T> DalResultSetExtractor<T> getResultExtractor(DalHints hints) throws SQLException { if(extractor != null) return extractor; DalRowMapper<T> mapper = checkAllowPartial(hints, this.mapper); if(isRequireSingle() || isRequireFirst()) return new DalSingleResultExtractor<>(mapper, isRequireSingle()); return count > 0 ? new DalRowMapperExtractor(mapper, count) : new DalRowMapperExtractor(mapper); } public static <T> DalRowMapper<T> checkAllowPartial(DalHints hints, DalRowMapper<T> mapper) throws SQLException { if(!(mapper instanceof SupportPartialResultMapping)) return mapper; if(!hints.is(DalHintEnum.partialQuery)) return mapper; //Otherwise we assume it is partial. The default implementation of generated code should support this return ((SupportPartialResultMapping)mapper).mapWith(hints.getPartialQueryColumns(), hints.is(DalHintEnum.ignoreMissingFields)); } }