/* * Copyright Aduna (http://www.aduna-software.com/) (c) 2008. * * Licensed under the Aduna BSD-style license. */ package org.openrdf.sail.rdbms.evaluation; import java.util.List; /** * Facilitates the building of a SQL query. * * @author James Leigh * */ public class SqlQueryBuilder { private QueryBuilderFactory factory; private boolean distinct; private SqlExprBuilder select; private SqlJoinBuilder from; private StringBuilder group = new StringBuilder(); private SqlExprBuilder order; private SqlQueryBuilder union; private Integer offset; private Integer limit; public SqlQueryBuilder(QueryBuilderFactory factory) { super(); this.factory = factory; select = factory.createSqlExprBuilder(); order = factory.createSqlExprBuilder(); } public List<Object> findParameters(List<Object> parameters) { parameters.addAll(select.getParameters()); if (from != null) { from.findParameters(parameters); } if (union != null) { union.findParameters(parameters); } parameters.addAll(order.getParameters()); return parameters; } public void distinct() { distinct = true; } public SqlExprBuilder select() { if (!select.isEmpty()) select.append(",\n "); return select; } public SqlJoinBuilder from(String table, String alias) { assert from == null : alias; return from = factory.createSqlJoinBuilder(table, alias); } public SqlJoinBuilder from(String alias) { assert from == null : alias; return from = factory.createSqlJoinBuilder(null, alias); } public SqlExprBuilder filter() { assert from != null; return from.on(); } public SqlQueryBuilder groupBy(String... expressions) { for (String expr : expressions) { if (group.length() == 0) { group.append("\nGROUP BY "); } else { group.append(", "); } group.append(expr); } return this; } public SqlQueryBuilder union() { assert union == null : union; return union = factory.createSqlQueryBuilder(); } public boolean isEmpty() { return select.isEmpty() && from == null; } @Override public String toString() { StringBuilder sb = new StringBuilder(); if (union != null && !union.isEmpty()) { sb.append("SELECT * FROM ("); } sb.append("SELECT "); /* TODO Workaround: Always make results distinct, so that LIMIT can be applied in a meaningful way * Reduces the number of results from of the based_near sample query from 1,300 to 60 * * - This is not caused by duplicate DB entries, cf. SELECT * FROM [LABEL_VALUES, URI_VALUES etc.]id IN (208531, 805506008, 1603, 805312806, 208432,208433) * - Neither by the modified behavior of always joining on LONG_LABEL_URIs etc. (they are empty). * - Thus the cause probably lies with a join on NULL columns somewhere */ // if (distinct) { sb.append("DISTINCT "); // } if (select.isEmpty()) { sb.append("*"); } else { sb.append(select.toSql()); } if (from != null) { sb.append("\nFROM ").append(from.getFromClause()); if (!from.on().isEmpty()) { sb.append("\nWHERE "); sb.append(from.on().toSql()); } } sb.append(group); if (union != null && !union.isEmpty()) { sb.append("\nUNION ALL "); sb.append(union.toString()); } if (!order.isEmpty()) { sb.append("\nORDER BY ").append(order.toSql()); } if (limit != null) { sb.append("\nLIMIT ").append(limit); } if (offset != null) { sb.append("\nOFFSET ").append(offset); } if (union != null && !union.isEmpty()) { sb.append(") mysqlfix "); } return sb.toString(); } public SqlExprBuilder orderBy() { if (!order.isEmpty()) order.append(",\n "); return order; } public void offset(Integer offset) { this.offset = offset; if (limit == null) { limit = Integer.MAX_VALUE; } } public void limit(Integer limit) { this.limit = limit; } }