if (sql != null)
{
return sql;
}
DatabaseAdapter dba = getDatabaseAdapter();
boolean lock = false;
Boolean val = (Boolean)getValueForExtension("lock-for-update");
if (val != null)
{
lock = val.booleanValue();
}
// SELECT ..., ..., ...
sql = new SQLText("SELECT ");
if (distinct)
{
sql.append("DISTINCT ");
}
addOrderingColumnsToSelect();
Iterator<String> selectIter = selects.iterator();
while (selectIter.hasNext())
{
String selected = selectIter.next();
sql.append(selected);
if (selectIter.hasNext())
{
sql.append(',');
}
}
if ((rangeOffset > -1 || rangeCount > -1) && dba.getRangeByRowNumberColumn().length() > 0)
{
// Add a ROW NUMBER column if supported as the means of handling ranges by the RDBMS
sql.append(',').append(dba.getRangeByRowNumberColumn()).append(" rn");
}
// FROM ...
sql.append(" FROM ");
sql.append(primaryTable.toString());
if (joins != null)
{
if (requiresJoinReorder)
{
List<SQLJoin> theJoins = new ArrayList<SQLJoin>(joins.size());
reorderJoins(theJoins, joins);
joins = theJoins;
}
Iterator<SQLJoin> iter = joins.iterator();
while (iter.hasNext())
{
SQLJoin join = iter.next();
if (join.getType() == JoinType.CROSS_JOIN)
{
if (dba.supportsOption(RDBMSAdapter.ANSI_CROSSJOIN_SYNTAX))
{
// ANSI-92 style joins, separate joins by space
sql.append(" ");
sql.append(join.toFromClause(dba, lock));
}
else if (dba.supportsOption(RDBMSAdapter.CROSSJOIN_ASINNER11_SYNTAX))
{
sql.append(" INNER JOIN " + join.getTable() + " ON 1=1");
}
else
{
// "ANSI-86" style cross join, separate join by comma
sql.append(",");
sql.append(join.getTable().toString());
}
}
else
{
if (dba.supportsOption(RDBMSAdapter.ANSI_JOIN_SYNTAX))
{
// ANSI-92 style joins, separate joins by space
sql.append(" ");
sql.append(join.toFromClause(dba, lock));
}
else
{
// "ANSI-86" style joins, separate joins by comma
sql.append(",");
sql.append(join.toFromClause(dba, lock));
}
}
}
}
// WHERE ...
if (where != null)
{
sql.append(" WHERE ").append(where.toSQLText());
}
// GROUP BY ...
if (groupingExpressions != null)
{
List groupBy = new ArrayList();
Iterator<SQLExpression> groupIter = groupingExpressions.iterator();
while (groupIter.hasNext())
{
SQLExpression expr = groupIter.next();
String exprText = expr.toSQLText().toSQL();
if (!groupBy.contains(exprText))
{
groupBy.add(exprText);
}
}
if (groupBy.size() > 0 && aggregated)
{
sql.append(" GROUP BY ");
for (int i=0; i<groupBy.size(); i++)
{
if (i > 0)
{
sql.append(',');
}
sql.append((String)groupBy.get(i));
}
}
}
// HAVING ...
if (having != null)
{
sql.append(" HAVING ").append(having.toSQLText());
}
if (unions != null)
{
// Add on any UNIONed statements
if (!dba.supportsOption(RDBMSAdapter.UNION_SYNTAX))
{
throw new NucleusException(LOCALISER.msg("052504", "UNION")).setFatal();
}
Iterator<SQLStatement> unionIter = unions.iterator();
while (unionIter.hasNext())
{
if (dba.supportsOption(RDBMSAdapter.USE_UNION_ALL))
{
sql.append(" UNION ALL ");
}
else
{
sql.append(" UNION ");
}
SQLStatement stmt = unionIter.next();
SQLText unionSql = stmt.getSelectStatement();
sql.append(unionSql);
}
}
// ORDER BY ...
SQLText orderStmt = generateOrderingStatement();
if (orderStmt != null)
{
sql.append(" ORDER BY ").append(orderStmt);
}
// RANGE
if (rangeOffset > -1 || rangeCount > -1)
{
// Add a LIMIT clause to end of statement if supported by the adapter
String limitClause = dba.getRangeByLimitEndOfStatementClause(rangeOffset, rangeCount);
if (limitClause.length() > 0)
{
sql.append(" ").append(limitClause);
}
}
if (lock && dba.supportsOption(RDBMSAdapter.LOCK_WITH_SELECT_FOR_UPDATE))
{
// Add any required locking based on the RDBMS capability
if (distinct && !dba.supportsOption(RDBMSAdapter.DISTINCT_WITH_SELECT_FOR_UPDATE))
{
NucleusLogger.QUERY.warn(LOCALISER.msg("052502"));
}
else
{
sql.append(" " + dba.getSelectForUpdateText());
}
}
if (lock && !dba.supportsOption(RDBMSAdapter.LOCK_WITH_SELECT_FOR_UPDATE) &&
!dba.supportsOption(RDBMSAdapter.LOCK_OPTION_PLACED_AFTER_FROM) &&
!dba.supportsOption(RDBMSAdapter.LOCK_OPTION_PLACED_WITHIN_JOIN))
{
NucleusLogger.QUERY.warn("Requested locking of query statement, but this RDBMS doesn't suppot a convenient mechanism");
}
if (rangeOffset > -1 || rangeCount > -1)
{
if (dba.getRangeByRowNumberColumn().length() > 0)
{
// Wrap the required query inside an outer query for the rownum - see issue CORE-2721
// Must select all columns of the inner query, except for the ROWNUM column
// Add conditions on the row number to meet the required range
SQLText innerQuery = sql;