com.avaje.ebeaninternal.server.query.CQueryBuilderRawSql Maven / Gradle / Ivy
package com.avaje.ebeaninternal.server.query;
import com.avaje.ebean.RawSql;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebean.config.dbplatform.SqlLimitResponse;
import com.avaje.ebean.config.dbplatform.SqlLimiter;
import com.avaje.ebeaninternal.api.BindParams;
import com.avaje.ebeaninternal.api.SpiQuery;
import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.querydefn.OrmQueryLimitRequest;
import com.avaje.ebeaninternal.server.util.BindParamsParser;
public class CQueryBuilderRawSql {
private final SqlLimiter sqlLimiter;
private final DatabasePlatform dbPlatform;
CQueryBuilderRawSql(SqlLimiter sqlLimiter, DatabasePlatform dbPlatform) {
this.sqlLimiter = sqlLimiter;
this.dbPlatform = dbPlatform;
}
/**
* Build the full SQL Select statement for the request.
*/
public SqlLimitResponse buildSql(OrmQueryRequest> request, CQueryPredicates predicates, RawSql.Sql rsql) {
if (rsql == null) {
// this is a ResultSet based RawSql query - just use some placeholder for the SQL
return new SqlLimitResponse("--ResultSetBasedRawSql", false);
}
if (!rsql.isParsed()) {
String sql = rsql.getUnparsedSql();
BindParams bindParams = request.getQuery().getBindParams();
if (bindParams != null && bindParams.requiresNamedParamsPrepare()) {
// convert named parameters into positioned parameters
sql = BindParamsParser.parse(bindParams, sql);
}
return new SqlLimitResponse(sql, false);
}
String orderBy = getOrderBy(predicates, rsql);
// build the actual sql String
String sql = buildMainQuery(orderBy, request, predicates, rsql);
SpiQuery> query = request.getQuery();
if (query.hasMaxRowsOrFirstRow() && sqlLimiter != null) {
// wrap with a limit offset or ROW_NUMBER() etc
return sqlLimiter.limit(new OrmQueryLimitRequest(sql, orderBy, query, dbPlatform));
} else {
// add back select keyword (it was removed to support sqlQueryLimiter)
String prefix = "select " + (rsql.isDistinct() ? "distinct " : "");
sql = prefix + sql;
return new SqlLimitResponse(sql, false);
}
}
private String buildMainQuery(String orderBy, OrmQueryRequest> request, CQueryPredicates predicates, RawSql.Sql sql) {
StringBuilder sb = new StringBuilder();
sb.append(sql.getPreFrom());
sb.append(" ");
String s = sql.getPreWhere();
BindParams bindParams = request.getQuery().getBindParams();
if (bindParams != null && bindParams.requiresNamedParamsPrepare()) {
// convert named parameters into positioned parameters
// Named Parameters only allowed prior to dynamic where
// clause (so not allowed in having etc - use unparsed)
s = BindParamsParser.parse(bindParams, s);
}
sb.append(s);
sb.append(" ");
String dynamicWhere = null;
if (request.getQuery().getId() != null) {
// need to convert this as well. This avoids the
// assumption that id has its proper dbColumn assigned
// which may change if using multiple raw sql statements
// against the same bean.
BeanDescriptor> descriptor = request.getBeanDescriptor();
//FIXME: I think this is broken... needs to be logical
// and then parsed for RawSqlSelect...
dynamicWhere = descriptor.getIdBinderIdSql();
}
String dbWhere = predicates.getDbWhere();
if (!isEmpty(dbWhere)) {
if (dynamicWhere == null) {
dynamicWhere = dbWhere;
} else {
dynamicWhere += " and " + dbWhere;
}
}
if (!isEmpty(dynamicWhere)) {
if (sql.isAndWhereExpr()) {
sb.append(" and ");
} else {
sb.append(" where ");
}
sb.append(dynamicWhere);
sb.append(" ");
}
String preHaving = sql.getPreHaving();
if (!isEmpty(preHaving)) {
sb.append(preHaving);
sb.append(" ");
}
String dbHaving = predicates.getDbHaving();
if (!isEmpty(dbHaving)) {
sb.append(" ");
if (sql.isAndHavingExpr()) {
sb.append("and ");
} else {
sb.append("having ");
}
sb.append(dbHaving);
sb.append(" ");
}
if (!isEmpty(orderBy)) {
sb.append(" ").append(sql.getOrderByPrefix()).append(" ").append(orderBy);
}
return sb.toString().trim();
}
private boolean isEmpty(String s) {
return s == null || s.isEmpty();
}
private String getOrderBy(CQueryPredicates predicates, RawSql.Sql sql) {
String orderBy = predicates.getDbOrderBy();
if (orderBy != null) {
return orderBy;
} else {
return sql.getOrderBy();
}
}
}