FileDocCategorySizeDatePackage
SelectStatement.javaAPI DocGlassfish v2 API34792Fri May 04 22:35:16 BST 2007com.sun.jdo.spi.persistence.support.sqlstore.sql.generator

SelectStatement

public class SelectStatement extends Statement
This class generates select statements.

Fields Summary
private boolean
isJoined
Flag indicating if this statement has been joined.
private StringBuffer
orderClause
SelectQueryPlan
plan
SelectQueryplan
Constructors Summary
public SelectStatement(com.sun.jdo.spi.persistence.support.sqlstore.database.DBVendorType vendorType, SelectQueryPlan plan)


         
        super(vendorType);
        this.plan = plan;
        constraint = plan.getConstraint();
    
Methods Summary
public ColumnRefaddColumn(org.netbeans.modules.dbschema.ColumnElement columnElement, QueryTable queryTable)


        ColumnRef columnRef = null;

        if ((columnRef = getColumnRef(columnElement)) == null) {
            columnRef = new ColumnRef(columnElement, queryTable);
            addColumnRef(columnRef);
        }

        return columnRef;
    
private voidappendAnsiJoinTableText(java.lang.StringBuffer text, QueryTable table)
Appends sql text corresponding to specified table to specified text. The linked list starting with table.nextTable is walked recursively to generate join text.

param
text The string buffer receiving sql text.
param
table Table to be joined.


        if (table.joinOp == ActionDesc.OP_RIGHTJOIN) {
            text.append(vendorType.getRightJoinPre());
        }

        if (table.prevTable == null) {
            appendTableText(text, table);
        }

        for (int i = 0; i < table.nextTable.size(); i++) {
            QueryTable toTable = (QueryTable) table.nextTable.get(i);
            text.append(getJoinOperator(table.joinOp)).append(" "); // NOI18N

            appendTableText(text, toTable);

            if (toTable.onClause != null) {
                text.append(" on "); // NOI18N
                text.append(toTable.onClause);
            }

            if (toTable.nextTable != null) {
                appendAnsiJoinTableText(text, toTable);
            }

            // Note: Since this method is called only for ANSI joins,
            // and only oracle has getLeftJoinPost() defined, we will never
            // append any text through following code.
            if (table.joinOp == ActionDesc.OP_LEFTJOIN) {
                text.append(vendorType.getLeftJoinPost());
            }
        }
    
private voidappendAnsiJoinText(java.lang.StringBuffer str, QueryTable t)

        // TODO: getTableListStart() and getTableListEnd() returns ""
        // for all the databases. Do we need it ?
        str.append(vendorType.getTableListStart());
        appendAnsiJoinTableText(str, t);
        str.append(vendorType.getTableListEnd());
        str.append(", "); // NOI18N
    
private voidappendJoinCondition(java.lang.StringBuffer result, QueryTable fromTable, QueryTable toTable, org.netbeans.modules.dbschema.ColumnElement fromColumn, org.netbeans.modules.dbschema.ColumnElement toColumn, java.lang.String joinOp)
Appends join condition corresponding to specified fromTable, toTable, fromColumn, toColumn, joinOp to result. If result is not empty " and " will be appended to it before appending the join condition.

param
result The string buffer to which the condition will be appended.
param
fromTable The from table.
param
toTable The to table.
param
fromColumn The from column.
param
toColumn The to column.
param
joinOp Join operation.

        if (result.length() > 0) {
            // Composite fk.
            result.append(" and ");
        }

        result.append("t").append(fromTable.getTableIndex()).append("."); // NOI18N
        appendQuotedText(result, fromColumn.getName().getName());
        result.append(" ").append(joinOp). // NOI18N
           append(" t").append(toTable.getTableIndex()).append("."); // NOI18N
        appendQuotedText(result, toColumn.getName().getName());
    
public voidappendTableText(java.lang.StringBuffer text, QueryTable table)

        super.appendTableText(text, table);

        if (isUpdateLockRequired(table)) {
            //Append eqivalent of "with (updlock)" to the table text
            text.append(vendorType.getHoldlock() );

            //For efficiency, the test whether a database is capable of supporting
            //holdlock would be made in method getText() where we generate
            //text corresponding to vendorType.getForUpdate()
        }
    
public voidbindInputValues(DBStatement s, com.sun.jdo.spi.persistence.support.sqlstore.ValueFetcher parameters)
Binds input valus corrsponding to this Statement object to database statement s.

param
s The database statement.
param
parameters If an InputValue to be bound is a parameter, the actual value is contained in this.
throws
SQLException

        for (int i = 0, size = inputDesc.values.size(); i < size; i++) {
            InputValue inputVal = (InputValue) inputDesc.values.get(i);
            s.bindInputColumn(i + 1, getInputValue(inputVal, parameters),
                    inputVal.getColumnElement(), vendorType);
        }
    
public voidcopyColumns(com.sun.jdo.spi.persistence.support.sqlstore.sql.generator.SelectStatement sourceStatement)

        ArrayList columnRefs = sourceStatement.getColumnRefs();

        int index = columns.size() + 1;

        for (int i = 0; i < columnRefs.size(); i++) {
            //addColumnRef((ColumnRef) columnRefs.get(i));
            ColumnRef cref = (ColumnRef) columnRefs.get(i);
            cref.setIndex(index + i);
            columns.add(cref);
        }
    
private static QueryTablefindQueryTable(QueryPlan plan, org.netbeans.modules.dbschema.ColumnElement ce)

        QueryTable table = plan.findQueryTable(ce.getDeclaringTable());

        if (table == null) {
            // TODO: throw exception
        }

        return table;
    
private voidgenerateAnsiJoin(com.sun.jdo.spi.persistence.support.sqlstore.sql.constraint.ConstraintJoin jnode, int opCode)
Generates an ANSI compliant join. The columns for the join condition end up in the from clause. The joined tables are added indirectly to the member variable tableList by being added to {@link QueryTable#nextTable} associated with the "from-" table.

param
jnode Join constraint.
param
opCode Join operation.
see
#processFromClause


        for (int i = 0; i < jnode.fromColumns.size(); i++) {
            ColumnElement fromColumn = (ColumnElement)jnode.fromColumns.get(i);
            ColumnElement toColumn = (ColumnElement)jnode.toColumns.get(i);
            QueryTable fromTable = findQueryTable(jnode.fromPlan, fromColumn);
            QueryTable toTable = findQueryTable(jnode.toPlan, toColumn);

            // Process the from clause
            processFromClause(fromTable, toTable);

            // Process the on clause.
            if (toTable.onClause == null) {
                toTable.onClause = new StringBuffer();
            }

            appendJoinCondition(toTable.onClause, fromTable, toTable, fromColumn, toColumn, "="); //NOI18N

            fromTable.joinOp = opCode;
        }
    
protected java.lang.StringBuffergenerateColumnText()

        StringBuffer columnText = new StringBuffer();

        for (int i = 0; i < columns.size(); i++) {
            ColumnRef cr = (ColumnRef) columns.get(i);

            columnText.append("t").append(cr.getQueryTable().getTableIndex()).append("."); // NOI18N
            appendQuotedText(columnText, cr.getName());
            columnText.append(", "); // NOI18N
        }
        columnText.delete(columnText.length() - 2, columnText.length());
        return columnText;
    
private voidgenerateCorrelatedExistsText(java.lang.StringBuffer whereClause)
Generates the text for a correlated exists query. Count distinct queries on objects with composite primary key are mapped to a correlated exists query. The "outer" select on the primary table to is correlated to the "inner" select by the already generated where clause.

param
whereClause Query's where clause.


        statementText = new StringBuffer();

        // TODO: Use correlated exists subquery in SelectQueryPlan?
        // - Do we handle secondary tables correctly?
        // - Do we need order by and for update clauses?

        // Generate for update clause while we still have all tables in tableList
        boolean updateLockRequired = isUpdateLockRequired();
        StringBuffer forUpdateClause = generateForUpdateClause(updateLockRequired);

        StringBuffer primaryTableText = new StringBuffer();
        QueryTable primaryTable = generatePrimaryTableText(primaryTableText);

        // Prepare the generation of the correlated "inner" select clause by
        // removing the primary table from the table list.
        // As count queries are never generated internally, we're preparing
        // a user query here. User queries never have outer joins. It's safe
        // remove the table from tableList.
        tableList.remove(primaryTable);
        String tableListText = generateTableListText();

        // Create the query with the previous generated parts.
        statementText.append("select count(*) from "). // NOI18N
                append(primaryTableText).
                append(" where exists (select * from "). // NOI18N
                append(tableListText).append(whereClause).append(")"). //NOI18N
                append(forUpdateClause);
    
private voidgenerateCountStatementText(java.lang.StringBuffer whereClause)
Generates the statement text for a count query. Count queries on persistence capable objects have been mapped to selecting the primary key columns in {@link SelectQueryPlan#addFetchGroups(int, ArrayList, ArrayList)}. Queries w/o a distinct restriction can be relaxed to select only one of the primary key columns. Distinct queries on objects with composite primary key have to be treated special to avoid duplicates.

param
whereClause Query's where clause.
see
#generateCorrelatedExistsText


        final int selectedColumns = columns.size();

        if (selectedColumns == 1) {
            // Single PK. Call regular statement generation.
            generateRegularStatementText(whereClause);
        } else {
            boolean oneTable = tableList.size() == 1;

            if ((plan.options & RetrieveDescImpl.OPT_DISTINCT) == 0
                    || oneTable) {
                // Without DISTINCT or when querying just one table, we can
                // select only one of the pk columns and get the correct result.
                // Remove the rest.
                for (int i = selectedColumns; i > 1; ) { columns.remove(--i); }
                if (oneTable) {
                    // When selecting only one table, remove the DISTINCT
                    // contraint from the query options to get all rows.
                    plan.options &= ~RetrieveDescImpl.OPT_DISTINCT;
                }
                // Now call regular statement generation.
               generateRegularStatementText(whereClause);
            } else {
                // This is a distinct count on objects having a composite pk and the query
                // includes join constraints. We map this to a correlated exists query.
                // Note: columns can only be cleared after this call.
                generateCorrelatedExistsText(whereClause);

                // Since we're not selecting any columns in this query, remove all column
                // information. Oracle's special DB operation code gets confused otherwise.
                // See OracleSpecialDBOperation#defineColumnTypeForResult(Statement, List)
                columns.clear();
            }
        }
    
private java.lang.StringBuffergenerateForUpdateClause(boolean updateLockRequired)

        StringBuffer forUpdateClause = new StringBuffer();

        if (updateLockRequired) {
            // Check if vendor actually supports updatelock
            if (!vendorType.isUpdateLockSupported() ) {
                // Throw an exception user wanted to have update lock
                // But vendor is not supporting it. Do not allow user to proceed
                throw new JDOFatalDataStoreException(I18NHelper.getMessage(messages,
                        "sqlstore.selectstatement.noupdatelocksupport"));// NOI18N
            }

            // generating the ForUpdate Clause
            String vendorForUpdate = vendorType.getForUpdate().trim();
            boolean vendorHasForUpdateClause = (vendorForUpdate.length() != 0);

            if (vendorHasForUpdateClause) {
                forUpdateClause.append(" ").append(vendorForUpdate).append(" ");

                if (vendorType.isLockColumnListSupported()) {
                    for (int i = 0; i < tableList.size(); i++) {
                        QueryTable queryTable = (QueryTable) tableList.get(i);
                        if (isUpdateLockRequired(queryTable)) {
                            TableDesc tableDesc = queryTable.getTableDesc();
                            //Get the first column of primary key
                            ColumnElement ce = (ColumnElement) tableDesc.getKey().getColumns().get(0);
                            forUpdateClause.append("t").append(i).append("."); // NOI18N
                            appendQuotedText(forUpdateClause, ce.getName().getName());
                            forUpdateClause.append(", "); // NOI18N
                        }
                    }
                    // Remove trailing ", "
                    forUpdateClause.delete(forUpdateClause.length() - 2, forUpdateClause.length());
                }
            }
        }

        return forUpdateClause;
    
private voidgenerateJoin(com.sun.jdo.spi.persistence.support.sqlstore.sql.constraint.ConstraintJoin jnode, java.lang.StringBuffer whereText, int opCode)
Generate a "regular" join. The columns for the join condition end up in the where clause. The corresponding tables are added directly to the member variable tableList. Note that this method is normally called to process EQUI- joins only. For databases that are marked for native join sematics, this method will be called to process both EQUI- and OUTER- joins.

param
jnode Join constraint.
param
whereText String buffer taking the join condition. Generated join condition is appended to this string buffer.
param
opCode Join operation.


        for (int i = 0; i < jnode.fromColumns.size(); i++) {
            ColumnElement fromColumn = (ColumnElement)jnode.fromColumns.get(i);
            ColumnElement toColumn = (ColumnElement)jnode.toColumns.get(i);
            QueryTable fromTable = findQueryTable(jnode.fromPlan, fromColumn);
            QueryTable toTable = findQueryTable(jnode.toPlan, toColumn);

            addQueryTable(fromTable);
            addQueryTable(toTable);
            toTable.prevTable = null;

            appendJoinCondition(whereText,
                    fromTable, toTable, fromColumn, toColumn,
                    getJoinOperator(opCode));

            if (opCode == ActionDesc.OP_LEFTJOIN ) {
                // Append oracle style (+) or similar.
                whereText.append(vendorType.getLeftJoinPost());
            }
        }
    
private QueryTablegeneratePrimaryTableText(java.lang.StringBuffer primaryTableText)
Generates the table text for the first column of the column list.

param
primaryTableText Takes the resulting statement text.
return
The table from the first selected column.

        // Get the primary table from the first selected column.
        // TODO: Is the first column always mapped to the primary table?
        QueryTable primaryTable = ((ColumnRef)columns.get(0)).getQueryTable();

        // Generate the table text.
        appendTableText(primaryTableText, primaryTable);

        return primaryTable;
    
private voidgenerateRegularStatementText(java.lang.StringBuffer whereClause)
Generates the statement text for a "regular" select query. Count queries have to get special attention in case of objects with composite primary key.

param
whereClause Query's where clause.
see
#generateCountStatementText


        statementText = new StringBuffer();

        StringBuffer columnText = generateColumnText();
        String tableListText = generateTableListText();
        String aggregateText = getAggregateText();
        String aggregateEnd = (aggregateText.length() > 0) ? ")" : ""; // NOI18N

        if (orderClause.length() > 0) {
            orderClause.insert(0, " order by ");
        }

        final boolean updateLockRequired = isUpdateLockRequired();
        StringBuffer forUpdateClause = generateForUpdateClause(updateLockRequired);
        String distinctText = getDistinctText(updateLockRequired);

        // Create the query filling in the column list, table name, etc.
        statementText.append("select "). // NOI18N
                append(aggregateText).append(distinctText).append(columnText).append(aggregateEnd).
                append(" from ").append(tableListText). // NOI18N
                append(whereClause).append(orderClause).append(forUpdateClause);
    
protected voidgenerateStatementText()

inheritDoc

        // Because join conditions for ANSI outer joins end up in the
        // from clause, the constraint stack has to be processed before we
        // generate the from clause.
        StringBuffer constraints = processConstraints();
        StringBuffer outerJoinText = processOuterJoinConstraints();

        if (outerJoinText != null && outerJoinText.length() > 0) {
            if (constraints.length() > 0 ) {
                constraints.append(" and ");
            }
            constraints.append(outerJoinText);
        }

        StringBuffer whereClause = new StringBuffer();

        if (constraints.length() > 0 ) {
            whereClause.append(" where ").append(constraints);
        }

        if ((plan.options & RetrieveDescImpl.OPT_COUNT_PC) == 0) {
            generateRegularStatementText(whereClause);
        } else {
            generateCountStatementText(whereClause);
        }
    
private java.lang.StringgenerateTableListText()

        StringBuffer str = new StringBuffer();

        for (int i = 0; i < tableList.size(); i++) {
            QueryTable t = (QueryTable) tableList.get(i);

            if (t.prevTable == null && t.nextTable == null) {
                appendTableText(str, t);
                str.append(", "); // NOI18N
            } else {
                // Table is part of an outer join list.

                if (t.prevTable == null) {
                    // Beginning of the list.

                    appendAnsiJoinText(str, t);
                } else {
                    // The table is in the "middle" of the list.

                    while (t.prevTable != null) {
                        t = t.prevTable;
                    }

                    if (!tableList.contains(t)) {
                        // Outer join list starts with a join table.
                        // Because join tables aren't in the table list,
                        // they wouldn't be included in the table text.

                        appendAnsiJoinText(str, t);
                    }
                }
            }
        }

        str.delete(str.length() - 2, str.length());

        return str.toString();
    
private java.lang.StringgetAggregateText()

        int aggregateOption = plan.options & RetrieveDescImpl.OPT_AGGREGATE;

        switch (aggregateOption) {
            case RetrieveDescImpl.OPT_AVG:
                return "AVG( "; // NOI18N
            case RetrieveDescImpl.OPT_MIN:
                return "MIN("; // NOI18N
            case RetrieveDescImpl.OPT_MAX:
                return "MAX("; // NOI18N
            case RetrieveDescImpl.OPT_SUM:
                return "SUM("; // NOI18N
            case RetrieveDescImpl.OPT_COUNT:
            case RetrieveDescImpl.OPT_COUNT_PC:
                return "COUNT("; // NOI18N
            default:
                return ""; // NOI18N
        }
    
private java.lang.StringgetDistinctText(boolean updateLockRequired)

        String distinctText = ""; // NOI18N

        if ((plan.options & RetrieveDescImpl.OPT_DISTINCT) > 0) {
            if( !updateLockRequired || vendorType.isDistinctSupportedWithUpdateLock()) {
                //Include DISTINCT only if update lock is not required
                //If update lock is required, include DISTINCT only if vendor supports update lock with DISTINCT
                //(e.g. ORACLE throws ORA-01786 if DISTINCT and FOR UPDATE are used in same query

                //For the case where update lock is required and vendor does not support DISTINCT/
                //with update lock, we would do DISTINCT in our code after retrieving the data
                //see SQLStoreManger::retrieve()
                distinctText = "distinct "; // NOI18N
            }
        }
        return distinctText;
    
public java.lang.StringgetFormattedSQLText(com.sun.jdo.spi.persistence.support.sqlstore.ValueFetcher parameters)
Gets formatted sql text corrsponding to this statement object. The text also contains values for input to the statement.

param
parameters The input paramters to this statement.
return
formatted sql text corrsponding to this statement object.

        return formatSqlText(getText(), getInputValues(parameters)) ;
    
private static java.lang.ObjectgetInputValue(InputValue inputVal, com.sun.jdo.spi.persistence.support.sqlstore.ValueFetcher parameters)
Gets actual value corresponding to inputVal. If inputVal is an instanceof InputValue then value contained in inputVal is returned. If inputVal is an instanceof InputParamValue then value returned is obtained from parameters .

param
inputVal The input value.
param
parameters The parameters.
return
Appropriate value as described above.

        Object val;
        if (inputVal instanceof InputParamValue) {
            int paramIndex = ((InputParamValue) inputVal).getParamIndex().intValue();
            val = parameters.getValue(paramIndex);
        }
        else {
            val = inputVal.getValue();
        }
        return val;
    
private java.lang.Object[]getInputValues(com.sun.jdo.spi.persistence.support.sqlstore.ValueFetcher parameters)
Get Input values to be bound to this statement.

param
parameters If an InputValue to be bound is a parameter, the actual value is contained in this.
return
An Object array containing input values to be bound to this statement.

        final int size = inputDesc.values.size();
        Object[] inputValues = new Object[size];
        for (int i = 0; i < size; i++) {
            InputValue inputValue = (InputValue) inputDesc.values.get(i);
            inputValues[i] = getInputValue(inputValue, parameters);
        }
        return inputValues;
    
protected java.lang.StringgetJoinOperator(int operation)
Returns join operator for specified operation.

param
operation The join operation. Should be one of ActionDesc.OP_EQUIJOIN, ActionDesc.OP_LEFTJOIN or ActionDesc.OP_RIGHTJOIN.
return
join operator for specified operation.

        String result = null;

        switch (operation) {
            case ActionDesc.OP_EQUIJOIN:
                result = " = "; // NOI18N
                break;
            case ActionDesc.OP_LEFTJOIN:
                result = vendorType.getLeftJoin();
                break;
            case ActionDesc.OP_RIGHTJOIN:
                result = vendorType.getRightJoin();
                break;
            default:
                throw new JDOFatalInternalException(
                        I18NHelper.getMessage(messages,
                        "core.constraint.illegalop", operation)); // NOI18N
        }
        return result;
    
public QueryPlangetQueryPlan()

inheritDoc

        return plan;
    
public booleanisColumnTypeDefinitionNeeded()
Determines if Column Type definition is needed for this statement. Column Type definition is a performance optimization that allows defining Column Type for the resultset. If the query to be executed is counting pc instances, the column used inside COUNT() is one of the pk columns. If the pk column happens to be not convertable to an int (for example timestamp), database will throw an exception. To prevent this situation, column type definition should not be performed on such queries.

return
true if column type definition is needed, false otherwise.

         return (plan.options & RetrieveDescImpl.OPT_COUNT_PC ) == 0;
     
public booleanisJoined()

        return isJoined;
    
private booleanisUpdateLockRequired()
Determines if an update lock is required while executing this query.

return
True if any of the tables invloved in this query requires update lock

        boolean updateLockRequired = false;

        // TODO: We can optimize this by storing the value in a member variable
        for (int i = 0; i < tableList.size() && !updateLockRequired; i++) {
            QueryTable queryTable = (QueryTable) tableList.get(i);
            updateLockRequired = isUpdateLockRequired(queryTable);
        }

        return updateLockRequired;
    
protected booleanisUpdateLockRequired(QueryTable table)

        return (plan.options & RetrieveDescImpl.OPT_AGGREGATE) == 0
                && table.getTableDesc().isUpdateLockRequired();
    
public voidmarkJoined()

        isJoined = true;
    
private static voidprocessFromClause(QueryTable fromTable, QueryTable toTable)
Processes specified fromTable and toTable to generate appropriate from clause when table text is generated. toTable is added to fromTable.nextTable if not already present. See {@link #appendAnsiJoinTableText(StringBuffer,QueryTable)} for details on how this is used to generate table text.

param
fromTable The from table
param
toTable The to table.


        if (toTable.prevTable != null && toTable.prevTable != fromTable) {
            // TODO
        }

        // TODO:
        // Check that these tables aren't already participating in
        // a join (except to each other).  If either of them are
        // then we will have to make a new table alias for that
        // table and put in an addtional equijoin between the old
        // alias and the new based, of course, on the key columns.

        if (fromTable.nextTable == null) {
            fromTable.nextTable = new ArrayList();
            fromTable.nextTable.add(toTable);
            toTable.prevTable = fromTable;
        } else {
            // Make sure we don't add the same table twice.
            if (!fromTable.nextTable.contains(toTable)) {
                fromTable.nextTable.add(toTable);
                toTable.prevTable = fromTable;
            }
        }
    
protected voidprocessIrregularOperation(com.sun.jdo.spi.persistence.support.sqlstore.sql.constraint.ConstraintOperation opNode, int opCode, java.util.List stack, java.lang.StringBuffer result)

        switch (opCode) {
            case ActionDesc.OP_EQUIJOIN:
                processJoinOperation((ConstraintJoin)opNode, result);
                break;
            default:
                super.processIrregularOperation(opNode, opCode, stack, result);
        }
    
private voidprocessJoinOperation(com.sun.jdo.spi.persistence.support.sqlstore.sql.constraint.ConstraintJoin jnode, java.lang.StringBuffer whereText)
Generates a join condition for specified jnode. Equi joins and native outer joins end up in the where clause. Ansi compliant outer join conditions end up in the from clause.

param
jnode Join constraint.
param
whereText String buffer taking the join condition. Generated join condition is appended to this string buffer.

        int opCode = jnode.operation;
        // Generate ANSI outer joins if doAnsiJoin == true,
        // i.e. the vendor has no "native" outer join semantics.
        boolean doAnsiJoin = opCode != ActionDesc.OP_EQUIJOIN
                && !vendorType.isNativeOuterJoin();

        if (doAnsiJoin) {
            generateAnsiJoin(jnode, opCode);
        } else {
            generateJoin(jnode, whereText, opCode);
        }
    
private voidprocessOrderByField(com.sun.jdo.spi.persistence.support.sqlstore.sql.constraint.ConstraintFieldDesc fieldNode, int op)
Adds a column corresponding to field fieldNode and order operation op to the order constraint.

param
fieldNode Constraint on a field name of a persistence capable class.
param
op Order operation.

        QueryPlan thePlan = getOriginalPlan(fieldNode);
        StringBuffer orderText = new StringBuffer();

        generateColumnText(fieldNode.desc, thePlan, orderText);

        if (op == ActionDesc.OP_ORDERBY_DESC) {
            orderText.append(" desc"); // NOI18N
        }

        if (orderClause.length() > 0) {
            orderText.append(", "); // NOI18N
            orderText.append(orderClause);
        }
        orderClause = orderText;
    
private java.lang.StringBufferprocessOuterJoinConstraints()
Process outer join constraints for this statement.

return
A string buffer representing outer join conditions for this statement. Please note that the returned string buffer will have text only for Oracle

        StringBuffer joinCondition = null;
        final List joinStack = constraint.getOuterJoinConstraints();
        final int joinStackSize = joinStack.size();

        if (joinStackSize > 0) {
            joinCondition = new StringBuffer();
            for (int i = 0; i < joinStackSize; i++) {
                ConstraintJoin joinNode = (ConstraintJoin) joinStack.get(i);
                processJoinOperation(joinNode, joinCondition);
            }
        }
        return joinCondition;
    
protected voidprocessRootConstraint(com.sun.jdo.spi.persistence.support.sqlstore.sql.constraint.ConstraintOperation opNode, java.util.List stack, java.lang.StringBuffer whereText)
Processes Order By constraints and calls the super class method for all other constrains.

        int op = opNode.operation;
        int opInfo = operationFormat(op);

        if ((opInfo & OP_ORDERBY_MASK) > 0) {
            stack.remove(stack.size() - 1);
            ConstraintNode node = (ConstraintNode) stack.get(stack.size() - 1);

            if (!(node instanceof ConstraintField)) {
                throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                        "core.constraint.needfieldnode")); // NOI18N
            } else {
                processOrderByField((ConstraintFieldDesc) node, op);
                stack.remove(stack.size() - 1);
            }
        } else {
            super.processRootConstraint(opNode, stack, whereText);
        }