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

Statement

public abstract class Statement extends Object implements Cloneable
This class is used to represent a SQL statement.

Fields Summary
private static final Integer
ONE
protected static final int
OP_PREFIX_MASK
protected static final int
OP_INFIX_MASK
protected static final int
OP_POSTFIX_MASK
protected static final int
OP_PAREN_MASK
protected static final int
OP_ORDERBY_MASK
protected static final int
OP_WHERE_MASK
protected static final int
OP_IRREGULAR_MASK
protected static final int
OP_OTHER_MASK
protected static final int
OP_PARAM_MASK
protected static final int
OP_BINOP_MASK
protected static final int
OP_FUNC_MASK
protected static final int
OP_PCOUNT_MASK
protected StringBuffer
statementText
private String
quoteCharStart
private String
quoteCharEnd
protected ArrayList
columns
array of ColumnRef
Constraint
constraint
protected InputDesc
inputDesc
int
action
public ArrayList
tableList
array of QueryTable
protected com.sun.jdo.spi.persistence.support.sqlstore.database.DBVendorType
vendorType
protected ArrayList
secondaryTableStatements
protected static final ResourceBundle
messages
I18N message handler
Constructors Summary
public Statement(com.sun.jdo.spi.persistence.support.sqlstore.database.DBVendorType vendorType)



       

        inputDesc = new InputDesc();
        columns = new ArrayList();
        constraint = new Constraint();
        tableList = new ArrayList();
        this.vendorType = vendorType;

        if (vendorType.getQuoteSpecialOnly() == false) {
            // DO NOT SUPPORT QUOTING OTHERWISE
            this.quoteCharStart = vendorType.getQuoteCharStart();
            this.quoteCharEnd = vendorType.getQuoteCharEnd();
        }
    
Methods Summary
protected voidaddColumnRef(ColumnRef columnRef)

        columnRef.setIndex(columns.size()+1);
        columns.add(columnRef);
    
public voidaddConstraint(com.sun.jdo.spi.persistence.support.sqlstore.model.LocalFieldDesc lf, java.lang.Object value)
Adds a comparison on local field lf and value value.

        int operation;
        if (value == null) {
            operation = ActionDesc.OP_NULL;
        } else {
            constraint.addValue(value, lf);
            if (lf.isPrimitiveMappedToNullableColumn() ||
                       (vendorType.mapEmptyStringToNull() && lf.getType() == String.class)) {
                // Primitive fields mapped to nullable columns might hold
                // a default value indicting that the actual db column is null.
                // Databases might treat zero length Strings as null.
                operation = ActionDesc.OP_MAYBE_NULL;
            } else {
                // Object type fields or primitive fields
                // mapped to non nullable columns are compared exactly
                operation = ActionDesc.OP_EQ;
            }
        }
        constraint.addField(lf);
        constraint.addOperation(operation);
    
public voidaddQueryTable(QueryTable table)

        //
        // First check to make sure this is not a duplicate.
        //
        if (tableList.indexOf(table) == -1) {
            tableList.add(table);
        }
    
public voidaddSecondaryTableStatement(com.sun.jdo.spi.persistence.support.sqlstore.sql.generator.Statement s)

        if (s == null) return;

        if (secondaryTableStatements == null)
            secondaryTableStatements = new ArrayList();

        secondaryTableStatements.add(s);
    
protected voidappendQuotedText(java.lang.StringBuffer buffer, java.lang.String text)
Append text surrounded by quote char to buffer

param
buffer The given buffer
param
text The given text

        buffer.append(quoteCharStart);
        buffer.append(text);
        buffer.append(quoteCharEnd);
    
public voidappendTableText(java.lang.StringBuffer text, QueryTable table)

        appendQuotedText(text, table.getTableDesc().getName());
        text.append(" t"); // NOI18N
        text.append(table.getTableIndex());
    
public voidbindInputValues(DBStatement s)
Binds input valus corrsponding to this Statement object to database statement s.

param
s The database statement
throws
SQLException

        for (int i = 0, size = inputDesc.values.size(); i < size; i++) {
            InputValue inputVal = (InputValue) inputDesc.values.get(i);
            s.bindInputColumn(i + 1, inputVal.getValue(),
                    inputVal.getColumnElement(), vendorType);
        }
    
public java.lang.Objectclone()

        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            //
            // shouldn't happen.
            //
            return null;
        }
    
protected QueryTablefindQueryTable(org.netbeans.modules.dbschema.TableElement tableElement)
Matches the table element tableElement to the corresponding query table from the list tableList.

param
tableElement Table element to be found.
return
Query table object corresponding to table element.
see
QueryPlan#findQueryTable(TableElement)

        QueryTable table = null;

        for (Iterator iter = tableList.iterator(); iter.hasNext() && table == null; ) {
            QueryTable t = (QueryTable) iter.next();
            if (t.getTableDesc().getTableElement() == tableElement) {
            // if (t.getTableDesc().getTableElement().equals(tableElement)) {
                table = t;
            }
        }

        return table;
    
protected static java.lang.StringformatSqlText(java.lang.String sqlText, java.lang.Object[] input)
The formatSqlText method returns a string containing the text of the SQL statement about to be executed and the input values for the placeholders.

param
sqlText Specifies the text of the SQL statement to be executed.
param
input Holds the input values used for the SQL statement.
return
The SQL text and the input values formatted into a printable string.

        StringBuffer str = new StringBuffer();

        str.append(I18NHelper.getMessage(messages,
                "sqlstore.sql.generator.statement.sqlStatement") );   //NOI18N
        str.append("<").append(sqlText).append("> "); // NOI18N

        if (input != null && input.length > 0) {
            str.append(I18NHelper.getMessage(messages,
            "sqlstore.sql.generator.statement.withinputvalues")); // NOI18N
            for (int i = 0; i < input.length; i++) {
                if (i > 0) {
                    str.append(", "); // NOI18N
                }
                Object inputValue = input[i];
                if (inputValue == null) {
                    str.append("<null>"); // NOI18N
                } else {
                    str.append(inputValue.getClass().getName());
                    str.append(":"); // NOI18N
                    str.append(inputValue.toString());
                }
            }
        } else {
            str.append(I18NHelper.getMessage(messages,
            "sqlstore.sql.generator.statement.withnoinputvalues")); // NOI18N
       }

        return str.toString();
    
protected voidgenerateColumnText(com.sun.jdo.spi.persistence.support.sqlstore.model.LocalFieldDesc desc, QueryPlan thePlan, java.lang.StringBuffer sb)
Generates the column text for field desc. The column has to be associated to the corresponding query table from the list tableList. For fields mapped to multiple columns choose one column to be included, as all mapped columns should have the same value.

param
desc Local field descriptor to be included in the constraint text.
param
thePlan Query plan corresponding to desc.
param
sb String buffer taking the resulting text.

        QueryTable table = null;
        ColumnElement column = null;
        Iterator iter = desc.getColumnElements();

        while (iter.hasNext() && table == null) {
            column = (ColumnElement) iter.next();

            // For updates, the member variable tableList is complete
            // at this point and includes only the table being updated.
            // For selects, new tables are still added to tableList
            // when join constraints are processed. Take the table list
            // from the query plan to find the table matching the column.
            if (action == QueryPlan.ACT_SELECT) {
                table = thePlan.findQueryTable(column.getDeclaringTable());
            } else {
                table = findQueryTable(column.getDeclaringTable());
            }
        }

        if (table == null) {
            throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.configuration.fieldnotable", // NOI18N
                    desc.getName()));
        }

        // Select statements might include columns from several tables.
        // Qualify the column with the table index.
        if (action == QueryPlan.ACT_SELECT) {
            sb.append("t").append(table.getTableIndex()).append("."); // NOI18N
        }

        appendQuotedText(sb, column.getName().getName());
    
protected voidgenerateInputValueForConstraintValueNode(ConstraintValue node)
Generates InputValue for node.

param
node The input node.

        inputDesc.values.add(new InputValue(node.getValue(), getColumnElementForValueNode(node) ));
    
protected abstract voidgenerateStatementText()
Generates the SQL text for the query described by this object.

public intgetAction()

        return action;
    
private static org.netbeans.modules.dbschema.ColumnElementgetColumnElementForValueNode(ConstraintValue node)
Gets the column information for the field to which node is bound.

param
node The input node.
return
Returns null if the node isn't bound to a field. Otherwise returns ColumnElement for the primary column of the field to which the node is bound.

        ColumnElement columnElement = null;
        LocalFieldDesc field = node.getLocalField();
        if(field != null) {
            //For fields mapped to multiple columns, we assume
            //that all the columns have the same value in the database.
            //Hence we only use the primary column in where clause.
            columnElement = field.getPrimaryColumn();
        }
        return columnElement;
    
protected ColumnRefgetColumnRef(org.netbeans.modules.dbschema.ColumnElement columnElement)

        //
        // Check whether this column has already been added.
        // If so, simply return.
        //
        int size = columns.size();

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

            if (cref.getColumnElement() == columnElement) return cref;
        }

        return null;
    
public java.util.ArrayListgetColumnRefs()

        return columns;
    
public java.lang.StringgetFormattedSQLText()
Gets formatted sql text corrsponding to this statement object. The text also contains values for input to the statement.

return
formatted sql text corrsponding to this statement object.

        return formatSqlText(getText(), getInputValues());
    
private java.lang.Object[]getInputValues()
Gets input values corrsponding to this Statement.

return
An Object array containing input values.

        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] = inputValue.getValue();
        }
        return inputValues;
    
protected QueryPlangetOriginalPlan(ConstraintField fieldNode)

        return (fieldNode.originalPlan != null) ? fieldNode.originalPlan : getQueryPlan();
    
public abstract QueryPlangetQueryPlan()
Get QueryPlan for this statement

return
QueryPlan for this statement

public java.util.ArrayListgetQueryTables()

        return tableList;
    
public java.util.ArrayListgetSecondaryTableStatements()

        return secondaryTableStatements;
    
public java.lang.StringgetText()
Returns the SQL text for the query described by this object.

return
The text of the SQL query described by this object.


        if (statementText == null) {
            generateStatementText();
        }


        return statementText.toString();
    
public com.sun.jdo.spi.persistence.support.sqlstore.database.DBVendorTypegetVendorType()

        return vendorType;
    
protected java.lang.StringgetWhereText(java.util.List stack)
Constructs the where clause for the statement from the constraint stack.

param
stack The stack parameter holds the constraint stack to be decoded. RESOLVE: We don't support constraints on multiple statements yet. We would need to sort constraints out by statement and do something about constraints that span statements (e.g. t1.c1 = t2.c2).


        StringBuffer result = new StringBuffer();
        ConstraintNode node;

        if (stack.size() == 0) {
            throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.constraint.stackempty")); // NOI18N
        }

        node = (ConstraintNode) stack.get(stack.size() - 1);
        stack.remove(stack.size() - 1);

        if (node instanceof ConstraintParamIndex) {
            processConstraintParamIndex((ConstraintParamIndex) node, result);
        } else if (node instanceof ConstraintValue) {
            processConstraintValue((ConstraintValue) node, result);
        } else if (node instanceof ConstraintField) {
            processConstraintField((ConstraintField) node, result);
        } else if (node instanceof ConstraintConstant) {
            result.append(((ConstraintConstant) node).value.toString());
        } else if (node instanceof ConstraintOperation) {
            processConstraintOperation((ConstraintOperation) node, stack, result);
        } else {
            throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.constraint.illegalnode", // NOI18N
                    node.getClass().getName()));
        }

        return result.toString();
    
protected java.lang.StringinfixOperator(int operation, int position)

        //
        //	InfixOperator
        //		The InfixOperator method returns the SQL text for the operator specified
        //		by the operation parameter.
        //
        //	operation
        //		The operation parameter specifies which operation for which to return
        //		SQL text.  Legal values are defined by the ConstraintOperation class.
        //
        StringBuffer result = new StringBuffer();

        switch (operation) {
            case ActionDesc.OP_ADD:
                result.append(" + "); // NOI18N
                break;
            case ActionDesc.OP_AND:
                result.append(" and ");
                break;
            case ActionDesc.OP_DIV:
                result.append(" / "); // NOI18N
                break;
            case ActionDesc.OP_EQ:
                result.append(" = "); // NOI18N
                break;
            case ActionDesc.OP_GE:
                result.append(" >= "); // NOI18N
                break;
            case ActionDesc.OP_GT:
                result.append(" > "); // NOI18N
                break;
            case ActionDesc.OP_LE:
                result.append(" <= "); // NOI18N
                break;
            case ActionDesc.OP_LT:
                result.append(" < "); // NOI18N
                break;
            case ActionDesc.OP_NE:
                result.append(" != "); // NOI18N
                break;
            case ActionDesc.OP_OR:
                result.append(" or "); // NOI18N
                break;
            case ActionDesc.OP_LIKE:
                result.append(" like "); // NOI18N
                break;
            case ActionDesc.OP_MUL:
                result.append(" * "); // NOI18N
                break;
            case ActionDesc.OP_SUB:
                result.append(" - "); // NOI1N8
                break;
            case ActionDesc.OP_MOD:
                result.append(" % "); // NOI1N8
                break;
            case ActionDesc.OP_BETWEEN:
                if (position == 1) {
                    result.append(" between "); // NOI18N
                } else {
                    result.append(" and ");
                }
                break;
            case ActionDesc.OP_CONCAT:
                result.append(vendorType.getStringConcat());
                break;
            default:
                throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                        "core.constraint.illegalop", // NOI18N
                        "" + operation)); // NOI18N
        }

        return result.toString();
    
protected intoperationFormat(int operation)

        int format = 0;
        switch (operation) {
            // Binary operators
            case ActionDesc.OP_EQ:
            case ActionDesc.OP_NE:
            case ActionDesc.OP_GT:
            case ActionDesc.OP_GE:
            case ActionDesc.OP_LT:
            case ActionDesc.OP_LE:
            case ActionDesc.OP_AND:
            case ActionDesc.OP_MUL:
            case ActionDesc.OP_LIKE:
                format = OP_BINOP_MASK;
                break;

            // Binary operators that require Parenthesis
            case ActionDesc.OP_ADD:
            case ActionDesc.OP_SUB:
            case ActionDesc.OP_DIV:
            case ActionDesc.OP_OR:
                format = OP_BINOP_MASK | OP_PAREN_MASK;
                break;

            // Functions
            case ActionDesc.OP_ABS:
            case ActionDesc.OP_SQRT:
            case ActionDesc.OP_LENGTH:
            case ActionDesc.OP_LTRIM:
            case ActionDesc.OP_NOT:
            case ActionDesc.OP_NULL_COMPARISION_FUNCTION:
                format = OP_FUNC_MASK;
                break;

            // Irregular operators
            case ActionDesc.OP_BETWEEN:
            case ActionDesc.OP_LIKE_ESCAPE:
            case ActionDesc.OP_IN:
            case ActionDesc.OP_NOTIN:
            case ActionDesc.OP_NULL:
            case ActionDesc.OP_NOTNULL:
            case ActionDesc.OP_MAYBE_NULL:
            case ActionDesc.OP_CONCAT:
            case ActionDesc.OP_EQUIJOIN:
                format = OP_IRREGULAR_MASK | OP_WHERE_MASK;
                break;

            // Irregular operators that can never be at the root of a where clause.
            // Hence they do not have OP_WHERE_MASK set.
            case ActionDesc.OP_SUBSTRING:
            case ActionDesc.OP_POSITION:
            case ActionDesc.OP_POSITION_START:
                format = OP_IRREGULAR_MASK;
                break;

            case ActionDesc.OP_NOTEXISTS:
            case ActionDesc.OP_EXISTS:
                format = OP_IRREGULAR_MASK | OP_WHERE_MASK | OP_PREFIX_MASK;
                break;

            case ActionDesc.OP_MOD:
                format = vendorType.isModOperationUsingFunction() ?
                    OP_IRREGULAR_MASK : OP_BINOP_MASK | OP_PAREN_MASK;
                break;

            case ActionDesc.OP_DISTINCT:
                format = OP_OTHER_MASK;
                break;

            case ActionDesc.OP_ORDERBY:
            case ActionDesc.OP_ORDERBY_DESC:
                format = OP_ORDERBY_MASK;
                break;

            case ActionDesc.OP_RTRIM:
            case ActionDesc.OP_RTRIMFIXED:
                if (vendorType.isAnsiTrim()) {
                    format = OP_WHERE_MASK | OP_PREFIX_MASK | OP_POSTFIX_MASK | OP_PARAM_MASK;
                } else {
                    format = OP_FUNC_MASK;
                }
                break;

            //TODO: Check how can this masks be optimized
            case ActionDesc.OP_LEFTJOIN:
                format = OP_IRREGULAR_MASK | OP_WHERE_MASK | OP_INFIX_MASK;
                format = format | OP_POSTFIX_MASK;
                break;
            case ActionDesc.OP_RIGHTJOIN:
                format = OP_IRREGULAR_MASK | OP_WHERE_MASK | OP_INFIX_MASK;
                format = format | OP_PREFIX_MASK;
                break;

            default:
                throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                        "core.constraint.illegalop", // NOI18N
                        "" + operation)); // NOI18N
        }

        return format;
    
protected java.lang.StringpostfixOperator(int operation)

        //
        //	PostfixOperator
        //		The PostfixOperator method returns the SQL text for the operator specified
        //		by the operation parameter.
        //
        //	operation
        //		The operation parameter specifies which operation for which to return
        //		SQL text.  Legal values are defined by the ConstraintOperation class.
        //
        StringBuffer result = new StringBuffer();

        switch (operation) {
            case ActionDesc.OP_RTRIM:
                result.append(vendorType.getRtrimPost());
                break;
            case ActionDesc.OP_RTRIMFIXED:
                result.append(postfixOperator(ActionDesc.OP_RTRIM));
                break;
            case ActionDesc.OP_LEFTJOIN:
                result.append(vendorType.getLeftJoinPost());
                break;
            default:
                throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                        "core.constraint.illegalop", // NOI18N
                        "" + operation)); // NOI18N
        }

        return result.toString();
    
protected java.lang.StringprefixOperator(int operation)

        //
        //  PrefixOperator
        //      The PrefixOperator method returns the SQL text for the operator specified
        //      by the operation parameter.
        //
        //  operation
        //      The operation parameter specifies which operation for which to return
        //      SQL text.  Legal values are defined by the ConstraintOperation class.
        //
        StringBuffer result = new StringBuffer();

        switch (operation) {
            case ActionDesc.OP_ABS:
                result.append(vendorType.getAbs()); // NOI18N
                break;
            case ActionDesc.OP_LENGTH:
                result.append(vendorType.getCharLength()); // NOI18N
                break;
            case ActionDesc.OP_RTRIM:
                result.append(vendorType.getRtrim());
                break;
            case ActionDesc.OP_RTRIMFIXED:
                result.append(prefixOperator(ActionDesc.OP_RTRIM));
                break;
            case ActionDesc.OP_NOT:
                result.append("not "); // NOI18N
                break;
            case ActionDesc.OP_SQRT:
                result.append(vendorType.getSqrt());
                break;
            case ActionDesc.OP_NOTEXISTS:
                result.append("not exists "); // NOI18N
                break;
            case ActionDesc.OP_EXISTS:
                result.append("exists "); // NOI18N
                break;
            case ActionDesc.OP_NULL_COMPARISION_FUNCTION:
                result.append(vendorType.getNullComparisonFunctionName());
                break;
            case ActionDesc.OP_MOD:
                result.append(vendorType.getModFunctionName()); // NOI18N
                break;

            default:
                throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                        "core.constraint.illegalop", "" + operation)); // NOI18N
        }

        return result.toString();
    
private voidprocessConcatOperation(int opCode, java.util.List stack, java.lang.StringBuffer result)


        if (stack.size() < 2) {
            throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.constraint.stackempty")); // NOI18N
        }
        String concatCast = vendorType.getConcatCast();
        if (concatCast.length() != 0) {
            result.append(concatCast);
            //Opening brace for concat cast
            result.append("( "); // NOI18N
        }
        // Concat is a binary infix operator. Process it manually here.
        // Resolve: Why should CONCAT operation be inside braces.
        // Opening brace around CONCAT operation
        result.append("( "); // NOI18N
        result.append(getWhereText(stack));
        result.append(infixOperator(opCode, 0));
        result.append(getWhereText(stack));
        // Closing brace around CONCAT operation
        result.append(" ) "); // NOI18N

        if (concatCast.length() != 0) {
            // Closing brace for concat cast
            result.append(" ) "); // NOI18N
        }
    
private voidprocessConstraintField(ConstraintField fieldNode, java.lang.StringBuffer result)

        LocalFieldDesc desc = null;

        QueryPlan thePlan = getOriginalPlan(fieldNode);

        if (fieldNode instanceof ConstraintFieldDesc) {
            desc = ((ConstraintFieldDesc) fieldNode).desc;
        } else if (fieldNode instanceof ConstraintFieldName) {
            desc = thePlan.config.getLocalFieldDesc(((ConstraintFieldName) fieldNode).name);
        } else {
            throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.generic.notinstanceof", // NOI18N
                    fieldNode.getClass().getName(),
                    "ConstraintFieldDesc/ConstraintFieldName")); // NOI18N
        }
        generateColumnText(desc, thePlan, result);
    
private voidprocessConstraintOperation(ConstraintOperation opNode, java.util.List stack, java.lang.StringBuffer result)

        int opCode = opNode.operation;
        int format = operationFormat(opCode);

        if ((format & OP_IRREGULAR_MASK) == 0) {
            processFunctionOrBinaryOperation(format, opCode, stack, result);
        } else {
            processIrregularOperation(opNode, opCode, stack, result);
        }
    
protected voidprocessConstraintParamIndex(ConstraintParamIndex node, java.lang.StringBuffer result)

        // DB2 requires cast for parameter markers involved in numeric expressions.
        result.append(vendorType.getParameterMarker(node.getType()));
        Integer index = node.getIndex();
        inputDesc.values.add(new InputParamValue(index, getColumnElementForValueNode(node) ));
    
protected voidprocessConstraintValue(ConstraintValue node, java.lang.StringBuffer result)

        boolean generateValueInSQLStatement = false;
        String strToAppend = "?"; // NOI18N

        // DB2 requires cast for parameter markers involved in numeric expressions.
        // For DB2, do not generate parameter markers, but inline values in generated SQL.
        // TODO: Inline numerics for all the databases not just DB2.

        if (vendorType.isInlineNumeric()) {
        // TODO: Ask Michael to pass on type for values also as enums.
        // Suggestion : Convert FieldTypeEnumeration to a class. Implement methods like
        // isNumeric(int type) for following if condition
            Object value = node.getValue();
            if (value != null && value instanceof Number) {
                generateValueInSQLStatement = true;
                strToAppend = value.toString();
            }
        }
        result.append(strToAppend);

        if(!generateValueInSQLStatement) {
            // We have added a "?" to sql. Add value to inputDesc
            generateInputValueForConstraintValueNode(node);
        }
    
public java.lang.StringBufferprocessConstraints()
Processes the constraint stack and adds it to the query. This means turning the constraint stack into SQL text and adding it to the where clause.

return
Where clause based on the constraint stack.

        StringBuffer whereText = new StringBuffer();
        List stack = constraint.getConstraints();

        while (stack.size() > 0) {
            ConstraintNode node = (ConstraintNode) stack.get(stack.size() - 1);

            if (!(node instanceof ConstraintOperation)) {
                throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                        "core.generic.notinstanceof", // NOI18N
                        node.getClass().getName(), "ConstraintOperation")); // NOI18N
            }

            processRootConstraint((ConstraintOperation) node, stack, whereText);
        }

        return whereText;
    
private voidprocessFunctionOrBinaryOperation(int format, int opCode, java.util.List stack, java.lang.StringBuffer result)


        if ((format & OP_PREFIX_MASK) > 0) {
            result.append(prefixOperator(opCode));
        }

        if ((format & OP_PCOUNT_MASK) > 0) {
            if ((format & OP_PAREN_MASK) > 0) {
                result.append("("); // NOI18N
            }

            result.append(getWhereText(stack));

            for (int i = 0; i < ((format & OP_PCOUNT_MASK) / OP_PARAM_MASK) - 1; i++) {
                if ((format & OP_INFIX_MASK) > 0) {
                    // opCode for which OP_BINOP_MASK is set
                    result.append(infixOperator(opCode, i - 1));
                } else {
                    // opCode for which OP_FUNC_MASK is set
                    result.append(", "); // NOI18N
                }

                result.append(getWhereText(stack));
            }

            if ((format & OP_PAREN_MASK) > 0) {
                result.append(")"); // NOI18N
            }
        }

        if ((format & OP_POSTFIX_MASK) > 0) {
            result.append(postfixOperator(opCode));
        }
    
private voidprocessInOperation(int opCode, java.util.List stack, java.lang.StringBuffer result)

        //We are trying to construct a where clause like following in the quotes here
        // where "(t0.field1, t0.field2, t0.field3,...) in
        //        ( select t1.fld1, t1.fld2, t2.fld3,...where ....)"

        StringBuffer c = new StringBuffer();

        if (stack.size() < 2) {
            throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.constraint.stackempty")); // NOI18N
        }

        //Append the first bracket "(" to the result
        result.append("("); // NOI18N

        if (!(stack.get(stack.size() - 1) instanceof ConstraintField)) {
            throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.constraint.needfieldnode")); // NOI18N
        } else {
            //append "t0.field1" to c
            c.append(getWhereText(stack));
        }

        //Append ", t0.field2, t0fld3,...."
        while (stack.size() > 1 && (stack.get(stack.size() - 1) instanceof ConstraintField)) {
            c.replace(0, 0, ", "); // NOI18N
            c.replace(0, 0, getWhereText(stack));
        }
        result.append(c.toString());
        result.append(") "); // NOI18N
        if (opCode == ActionDesc.OP_NOTIN) {
            result.append("not "); // NOI18N
        }
        result.append("in ("); // NOI18N


        ConstraintNode currentNode = (ConstraintNode)stack.remove(stack.size() - 1);
        if ( ! ( currentNode instanceof ConstraintSubquery)) {
            throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.generic.notinstanceof", // NOI18N
                    currentNode.getClass().getName(), "ConstraintSubquery")); // NOI18N
        } else {

            ConstraintSubquery sqnode = (ConstraintSubquery) currentNode;

            Statement sqstmt = (Statement) sqnode.plan.statements.get(0);
            //Append the subquery i.e. "select t1.fld1, t1.fld2, t2.fld3,...where ...."
            result.append(sqstmt.getText());

            //Close the final bracket
            result.append(")"); // NOI18N

            //Append the Input values to the InputDesc of current statement
            inputDesc.values.addAll(sqstmt.inputDesc.values);
        }

        /*
          //This is old code that takes care of case when we just have a list of values
          //as the parameter to the IN clause. We might uncomment and enhance this code
          //when we implement the functionality to have list of values inside IN clause.
        if (!(stack.get(stack.size() - 1) instanceof ConstraintValue)) {
            throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.constraint.needvalnode")); // NOI18N
        } else {
            result.append(((ConstraintValue) stack.get(stack.size() - 1)).value.toString());
            stack.remove(stack.size() - 1);
        }

        result.append(")"); // NOI18N
        */
    
protected voidprocessIrregularOperation(ConstraintOperation opNode, int opCode, java.util.List stack, java.lang.StringBuffer result)

        switch (opCode) {
            case ActionDesc.OP_NULL:
            case ActionDesc.OP_NOTNULL:
                processNullOperation(opCode, stack, result);
                break;
           case ActionDesc.OP_BETWEEN:
                if (stack.size() < 3) {
                    throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                            "core.constraint.stackempty")); // NOI18N
                }

                if (!(stack.get(stack.size() - 1) instanceof ConstraintField)) {
                    throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                            "core.constraint.needfieldnode")); // NOI18N
                } else {
                    result.append(getWhereText(stack));
                    result.append(" between "); // NOI18N
                }
                result.append(getWhereText(stack));
                result.append(" and ");
                result.append(getWhereText(stack));
                break;
            case ActionDesc.OP_IN:
            case ActionDesc.OP_NOTIN:
                processInOperation(opCode, stack, result);
                break;
            case ActionDesc.OP_NOTEXISTS:
            case ActionDesc.OP_EXISTS:
                if (!(opNode instanceof ConstraintSubquery)) {
                    throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                            "core.generic.notinstanceof", // NOI18N
                            opNode.getClass().getName(), "ConstraintSubquery")); // NOI18N
                }

                ConstraintSubquery sqNode = (ConstraintSubquery) opNode;

                result.append(prefixOperator(opCode));
                result.append("("); // NOI18N

                Statement sqstmt = (Statement) sqNode.plan.statements.get(0);

                result.append(sqstmt.getText());

                result.append(")"); // NOI18N
                break;
            case ActionDesc.OP_LIKE_ESCAPE:
                if (stack.size() < 3) {
                    throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                            "core.constraint.stackempty")); // NOI18N
                }

                if (vendorType.supportsLikeEscape()) {
                    if (!(stack.get(stack.size() - 1) instanceof ConstraintField)) {
                        throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                                "core.constraint.needfieldnode")); // NOI18N
                    } else {
                        result.append(getWhereText(stack));
                        result.append(" LIKE "); // NOI18N
                    }
                    result.append(getWhereText(stack));
                    result.append(vendorType.getLeftLikeEscape());
                    result.append(" ESCAPE "); // NOI18N
                    result.append(getWhereText(stack));
                    result.append(vendorType.getRightLikeEscape());
                } else {
                    throw new JDOFatalInternalException(
                            I18NHelper.getMessage(messages,
                                    "sqlstore.sql.generator.statement.likeescapenotsupported")); //NOI18N
                }

                break;
            case ActionDesc.OP_SUBSTRING:
                if (stack.size() < 3) {
                    throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                            "core.constraint.stackempty")); // NOI18N
                }

                result.append(vendorType.getSubstring());
                result.append("("); // NOI18N
                result.append(getWhereText(stack));
                result.append(vendorType.getSubstringFrom());
                result.append(getWhereText(stack));
                result.append(vendorType.getSubstringFor());
                result.append(getWhereText(stack));
                result.append(")"); // NOI18N
                break;
            case ActionDesc.OP_POSITION:
                if (stack.size() < 2) {
                    throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                            "core.constraint.stackempty")); // NOI18N
                }

                result.append(vendorType.getPosition());
                result.append("("); // NOI18N
                boolean swap = vendorType.isPositionSearchSource();
                if (swap) {
                    ConstraintNode expr =
                            (ConstraintNode)stack.remove(stack.size() - 1);
                    ConstraintNode pattern =
                            (ConstraintNode)stack.remove(stack.size() - 1);
                    stack.add(expr);
                    stack.add(pattern);
                }

                result.append(getWhereText(stack));
                result.append(vendorType.getPositionSep());
                result.append(" ").append(getWhereText(stack)); // NOI18N
                result.append(")"); // NOI18N
                break;
            case ActionDesc.OP_POSITION_START:
                if (stack.size() < 3) {
                    throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                            "core.constraint.stackempty")); // NOI18N
                }

                boolean swapArgs = vendorType.isPositionSearchSource();
                boolean threeArgs = vendorType.isPositionThreeArgs();

                if (threeArgs) {
                    if (swapArgs) {
                        ConstraintNode expr =
                                (ConstraintNode)stack.remove(stack.size() - 1);
                        ConstraintNode pattern =
                                (ConstraintNode)stack.remove(stack.size() - 1);
                        stack.add(expr);
                        stack.add(pattern);
                    }
                    result.append(vendorType.getPosition());
                    result.append("("); // NOI18N
                    result.append(getWhereText(stack));
                    result.append(vendorType.getPositionSep());
                    result.append(" ").append(getWhereText(stack)); // NOI18N
                    result.append(vendorType.getPositionSep());
                    result.append(" ").append(getWhereText(stack)); // NOI18N
                    result.append(")"); // NOI18N
                } else { //twoArgs
                    ConstraintValue valueNode =
                            (ConstraintValue)stack.remove(stack.size() - 3);
                    if (valueNode != null && ONE.equals(valueNode.getValue())) {
                        stack.add(new ConstraintOperation(ActionDesc.OP_POSITION));
                        result.append(getWhereText(stack));
                    } else {
                        throw new JDOFatalInternalException(
                                I18NHelper.getMessage(messages,
                                        "sqlstore.sql.generator.statement.positionthreeargsnotsupported")); // NOI18N
                    }
                }
                break;
            case ActionDesc.OP_MAYBE_NULL:
                processMaybeNullOperation(stack, result);
                break;
            case ActionDesc.OP_MOD:
                if (stack.size() < 2) {
                    throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                            "core.constraint.stackempty")); // NOI18N
                }
                result.append(prefixOperator(opCode));
                result.append("("); // NOI18N
                result.append(getWhereText(stack));
                result.append(", "); // NOI18N
                result.append(getWhereText(stack));
                result.append(")"); // NOI18N
                break;
            case ActionDesc.OP_CONCAT:
                processConcatOperation(opCode, stack, result);
                break;

            default:
                throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                        "core.constraint.illegalop", // NOI18N
                        "" + opCode)); // NOI18N
        }
    
private voidprocessMaybeNullOperation(java.util.List stack, java.lang.StringBuffer result)

        ConstraintValue valueNode = null;
        ConstraintField fieldNode = null;

        if (stack.size() < 2) {
            throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.constraint.stackempty")); // NOI18N
        }

        if (!(stack.get(stack.size() - 1) instanceof ConstraintField)) {
            throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.constraint.needfieldnode")); // NOI18N
        } else {
            fieldNode = (ConstraintField) stack.get(stack.size() - 1);
            stack.remove(stack.size() - 1);
        }

        if (!(stack.get(stack.size() - 1) instanceof ConstraintValue)) {
            throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.constraint.needvalnode")); // NOI18N
        } else {
            valueNode = (ConstraintValue) stack.get(stack.size() - 1);
            stack.remove(stack.size() - 1);
        }

        Object value = valueNode.getValue();
        if (value instanceof String) {
            String v = (String) value;

            if (v.length() == 0) {
                stack.add(fieldNode);
                stack.add(new ConstraintOperation(ActionDesc.OP_NULL));
            } else {
                stack.add(valueNode);
                stack.add(fieldNode);
                stack.add(new ConstraintOperation(ActionDesc.OP_EQ));
            }
        } else {
            stack.add(valueNode);
            stack.add(fieldNode);
            stack.add(new ConstraintOperation(ActionDesc.OP_EQ));

            //
            // This takes care of the case where a nullable database column
            // is mapped to a primitive field.
            // This check adds a "OR numericColumn IS NULL" to the constraint.
            // See FieldDesc#setValue(StateManager, Object) for the conversions
            // done on binding a primitive field from the store.
            //
            // RESOLVE: Don't we have to do this in each OP_EQ comparison
            // involving primitive Fields?
            //
            boolean maybeNull = false;

            if ((value instanceof Number) &&
                    ((Number) value).doubleValue() == 0) {
                maybeNull = true;
            } else if ((value instanceof Boolean) &&
                    ((Boolean) value).booleanValue() == false) {
                maybeNull = true;
            } else if ((value instanceof Character) &&
                    ((Character) value).charValue() == '\0") {
                maybeNull = true;
            }

            if (maybeNull) {
                stack.add(fieldNode);
                stack.add(new ConstraintOperation(ActionDesc.OP_NULL));
                stack.add(new ConstraintOperation(ActionDesc.OP_OR));
            }
        }

        if (stack.size() > 0) {
            result.append(getWhereText(stack));
        }
    
private voidprocessNullOperation(int opCode, java.util.List stack, java.lang.StringBuffer result)

        String nullComparisionFunctionName =
            vendorType.getNullComparisonFunctionName();
        if( nullComparisionFunctionName.length() != 0) {
            // Null comparision for LOB type fields is
            // through function for this DB
            Object nextNode = stack.get(stack.size() - 1);
            if( nextNode != null) {
                if ( nextNode instanceof ConstraintFieldName) {
                    ConstraintFieldName fieldNode =
                            (ConstraintFieldName) nextNode;
                    QueryPlan originalPlan = getQueryPlan();
                    if (fieldNode.originalPlan != null) {
                        originalPlan = fieldNode.originalPlan;
                    }
                    LocalFieldDesc desc = (LocalFieldDesc) originalPlan.config.getField(fieldNode.name);
                    if ( desc.isMappedToLob() ) {
                        // Add a dummy ConstraintOperation Node corresponding
                        // to null comparision func.
                        stack.add (new ConstraintOperation(
                                ActionDesc.OP_NULL_COMPARISION_FUNCTION) );
                    }
                }
            } else {
                throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                    "core.constraint.stackempty")); // NOI18N
           }
        }
        result.append (getWhereText(stack));
        String str = (opCode == ActionDesc.OP_NULL) ? vendorType.getIsNull() : vendorType.getIsNotNull();
        result.append(str);
    
protected voidprocessRootConstraint(ConstraintOperation opNode, java.util.List stack, java.lang.StringBuffer whereText)

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

        if ((opInfo & OP_WHERE_MASK) > 0) {
            String constraint = getWhereText(stack);
            if (whereText.length() > 0 && constraint.length() > 0) {
                // This is neccessary, if the constraint stack is "un-balanced",
                // see OrderingTest#ordering006 for an example.
                whereText.append(" and ");
            }
            whereText.append(constraint);
        } else {
                throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
                        "sqlstore.sql.generator.statement.unexpectedconstraint", op)); // NOI18N
        }
    
public voidsetAction(int action)

        this.action = action;