/**********************************************************************
Copyright (c) 2002 Mike Martin (TJDO) and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Contributors:
2003 Erik Bengtson - removed toStatement and toString methods enherited
from QueryStatement. setOrdering now goes thought
union queries.
2003 Andy Jefferson - coding standards
...
**********************************************************************/
package org.jpox.store.rdbms.query;
import org.jpox.ClassLoaderResolver;
import org.jpox.exceptions.JPOXException;
import org.jpox.store.mapped.DatastoreContainerObject;
import org.jpox.store.mapped.DatastoreIdentifier;
import org.jpox.store.mapped.expression.BooleanCharColumnExpression;
import org.jpox.store.mapped.expression.BooleanExpression;
import org.jpox.store.mapped.expression.CharacterExpression;
import org.jpox.store.mapped.expression.LogicSetExpression;
import org.jpox.store.mapped.expression.ObjectExpression;
import org.jpox.store.mapped.expression.ScalarExpression;
import org.jpox.store.mapped.query.StatementText;
import org.jpox.store.rdbms.adapter.RDBMSAdapter;
/**
* Representation of a Query Statement in Oracle 8.
* Oracle 8 or below doesnt support SQL 92. Join definitions are added to the WHERE clause instead of the FROM clause.
* <pre>
* FROM TABLE1,TABLE2
* WHERE
* TABLE1.KEY = TABLE2.KEY
* </pre>
* Additionally Oracle has an NLSSortOrder control for order clauses.
*/
public class OracleQueryStatement extends QueryStatement
{
/**
* The system property that selects the "linguistic definition" to be used for native language sorting
* of String fields. The default value is "LATIN". A value of "BINARY" disables native language sorting.
*/
private String nlsSortOrder = "LATIN";
/**
* QueryStatement constructor
* @param initialTable The main table for this statement.
* @param clr ClassLoader resolver
*/
public OracleQueryStatement(DatastoreContainerObject initialTable, ClassLoaderResolver clr)
{
this(initialTable, null, clr);
}
/**
* QueryStatement constructor
* @param initialTable The main table for this statement.
* @param alias The alias for the main table
* @param clr ClassLoader resolver
*/
public OracleQueryStatement(DatastoreContainerObject initialTable, DatastoreIdentifier alias, ClassLoaderResolver clr)
{
super(initialTable, alias, clr);
String sortOrder = storeMgr.getOMFContext().getPersistenceConfiguration().getStringProperty("org.jpox.rdbms.oracleNlsSortOrder");
if (sortOrder != null)
{
nlsSortOrder = sortOrder.toUpperCase();
}
stmtJoinsSeparator = ',';
}
/**
* Convenience method to generate the ordering statement to add to the overall query statement.
* @return The ordering statement
*/
protected StatementText generateOrderingStatement()
{
StatementText orderByStmt = null;
if (orderingExpressions != null && orderingExpressions.length > 0)
{
orderByStmt = new StatementText();
boolean needsSelect = ((RDBMSAdapter)storeMgr.getDatastoreAdapter()).includeOrderByColumnsInSelect();
for (int i=0; i<orderingExpressions.length; ++i)
{
String orderExpr = "JPOXORDER" + i;
if (i > 0)
{
orderByStmt.append(',');
}
if (needsSelect && !hasAggregateExpression)
{
// Order by the "JPOXORDER?" if we need them to be selected and it isn't an aggregate
if (orderingExpressions[i] instanceof CharacterExpression && !nlsSortOrder.equals("BINARY"))
{
orderByStmt.append("NLSSORT(").append(orderExpr).append(", 'NLS_SORT = ").append(nlsSortOrder).append("')");
}
else if (orderingExpressions[i] instanceof BooleanExpression &&
!(orderingExpressions[i] instanceof BooleanCharColumnExpression))
{
throw new JPOXException(LOCALISER.msg("052505")).setFatal();
}
else
{
orderByStmt.append(orderExpr);
}
}
else
{
// Order by the "THIS.COLUMN" otherwise
if (orderingExpressions[i] instanceof CharacterExpression && !nlsSortOrder.equals("BINARY"))
{
orderByStmt.append("NLSSORT(").append(
orderingExpressions[i].toStatementText(ScalarExpression.PROJECTION).toStatementString(
ScalarExpression.PROJECTION)).append(", 'NLS_SORT = ").append(nlsSortOrder).append("')");
}
else if (orderingExpressions[i] instanceof BooleanExpression &&
!(orderingExpressions[i] instanceof BooleanCharColumnExpression))
{
throw new JPOXException(LOCALISER.msg("052505")).setFatal();
}
else
{
orderByStmt.append(orderingExpressions[i].toStatementText(ScalarExpression.PROJECTION).toStatementString(ScalarExpression.PROJECTION));
}
}
if (orderingDirections[i])
{
orderByStmt.append(" DESC");
}
}
}
return orderByStmt;
}
/**
* Method to do an inner join to another table.
* Requires ANSI-86 syntax, providing the table to the FROM clause and the join within the WHERE clause.
* @param expr the left hand expression
* @param expr2 the right hand expression
* @param tblExpr The table expression
**/
public void innerJoin(ScalarExpression expr, ScalarExpression expr2, LogicSetExpression tblExpr)
{
assertNotFrozen();
//TODO copy implementation from QueryStatement
Join join = new Join(expr, expr2, tblExpr);
if (tblExpr.equals(getMainTableExpression()))
{
andCondition(expr.eq(expr2));
return;
}
if (crossJoins.contains(tblExpr))
{
crossJoins.remove(tblExpr);
}
// if we already have this join, return
if (joinsToTableAliases.contains(tblExpr.getAlias()))
{
return;
}
joinsToTableAliases.add(tblExpr.getAlias());
joins.add(join);
andCondition(expr.eq(expr2));
}
/**
* Method to do a left outer join to another table.
* Requires ANSI-86 syntax, providing the table to the FROM clause and the join within the WHERE clause.
* @param expr the left hand expression
* @param expr2 the right hand expression
* @param tblExpr The table expression
**/
public void leftOuterJoin(ScalarExpression expr, ScalarExpression expr2, LogicSetExpression tblExpr)
{
assertNotFrozen();
//TODO copy implementation from QueryStatement
Join join = new Join(expr, expr2, tblExpr);
// if we already have this join, return
if (joinsToTableAliases.contains(tblExpr.getAlias()))
{
return;
}
joinsToTableAliases.add(tblExpr.getAlias());
joins.add(join);
// Update the right-hand-side to use Oracle outer join syntax
if (expr2 instanceof ObjectExpression)
{
((ObjectExpression)expr2).addOuterJoinSuffix("(+)");
}
andCondition(expr.eq(expr2));
}
/**
* Method to do a right outer join to another table.
* Requires ANSI-86 syntax, providing the table to the FROM clause and the join within the WHERE clause.
* @param expr the left hand expression
* @param expr2 the right hand expression
* @param tblExpr The table expression
**/
public void rightOuterJoin(ScalarExpression expr, ScalarExpression expr2, LogicSetExpression tblExpr)
{
assertNotFrozen();
//TODO copy implementation from QueryStatement
Join join = new Join(expr, expr2, tblExpr);
// if we already have this join, return
if (joinsToTableAliases.contains(tblExpr.getAlias()))
{
return;
}
joinsToTableAliases.add(tblExpr.getAlias());
joins.add(join);
// Update the left-hand-side to use Oracle outer join syntax
if (expr instanceof ObjectExpression)
{
((ObjectExpression)expr).addOuterJoinSuffix("(+)");
}
andCondition(expr.eq(expr2));
}
}