package Express.services;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import DisplayProject.binding.beans.ExtendedPropertyChangeSupport;
import DisplayProject.binding.beans.Observable;
import Express.domains.LongTextDomain;
import Framework.Array_Of_DataValue;
import Framework.Array_Of_TextData;
import Framework.CloneHelper;
import Framework.DataValue;
import Framework.IntegerData;
import Framework.ParameterHolder_TextData;
import Framework.ParameterHolder_integer;
import Framework.RuntimeProperties;
import Framework.TextData;
import GenericDBMS.Constants;
import GenericDBMS.DBConnectionManager;
/**
* Builds an SQL query for select, insert, update, or delete operations.
* <p>
* @author ITerative Consulting
* @since 26-Feb-2008
*/
@RuntimeProperties(isDistributed=false, isAnchored=false, isShared=false, isTransactional=false)
@SuppressWarnings("serial")
public class SqlQuery
implements Serializable, Observable
{
// ---------
// Constants
// ---------
public static final int ATTRTYPE_CUSTOM = 4;
public static final int ATTRTYPE_DB = 2;
public static final int OP_FORMAT_ABS = 9;
public static final int OP_FORMAT_ADD = 10;
public static final int OP_FORMAT_AND = 2;
public static final int OP_FORMAT_BETWEEN = 2;
public static final int OP_FORMAT_DIV = 10;
public static final int OP_FORMAT_EQ = 2;
public static final int OP_FORMAT_EQUIJOIN = 2;
public static final int OP_FORMAT_GE = 2;
public static final int OP_FORMAT_GT = 2;
public static final int OP_FORMAT_IN = 0;
public static final int OP_FORMAT_LE = 2;
public static final int OP_FORMAT_LIKE = 2;
public static final int OP_FORMAT_LT = 2;
public static final int OP_FORMAT_MUL = 2;
public static final int OP_FORMAT_NE = 2;
public static final int OP_FORMAT_NOT = 9;
public static final int OP_FORMAT_NOTNULL = 4;
public static final int OP_FORMAT_NULL = 4;
public static final int OP_FORMAT_OR = 10;
public static final int OP_FORMAT_RTRIM = 9;
public static final int OP_FORMAT_SUB = 10;
public static final int OP_INFIX_MASK = 2;
public static final int OP_PAREN_MASK = 8;
public static final int OP_POSTFIX_MASK = 4;
public static final int OP_PREFIX_MASK = 1;
public static final int OPT_COLLECTIVE_FOR_ONE = 2;
public static final int OPT_INNER_JOIN = 4;
public static final int OPT_JOIN_TYPE = 12;
public static final int OPT_NO_COLLECTIVE = 1;
public static final int OPT_NO_MULT_OUTER_JOIN = 64;
public static final int OPT_NO_OUTER_JOIN = 32;
public static final int OPT_NO_TRANSITIVE_OUTER_JOIN = 16;
public static final int OPT_OUTER_JOIN = 8;
// ----------
// Attributes
// ----------
public PropertyChangeSupport qq_Listeners = new ExtendedPropertyChangeSupport(this, true);
private Array_Of_TextData<TextData> columnList;
private Array_Of_SqlData<SqlData> data;
private DBConnectionManager dBSession;
private boolean distinct;
private boolean forUpdate;
private int maxRows;
private IntegerData numTables;
private int operation;
private TextData orderClause;
private BusinessQuery query;
private Array_Of_SqlQueryTable<SqlQueryTable> tableList;
private Array_Of_TextData<TextData> whereClause;
private int options;
// ------------
// Constructors
// ------------
public SqlQuery() {
// Explicitly call the superclass constructor to prevent the implicit call
super();
this.setOperation(0);
this.setNumTables(new IntegerData());
this.columnList = new Array_Of_TextData<TextData>();
this.tableList = new Array_Of_SqlQueryTable<SqlQueryTable>();
this.setData(new Array_Of_SqlData<SqlData>());
this.setWhereClause(new Array_Of_TextData<TextData>());
}
public SqlQuery(int pOperation) {
this();
this.setOperation( pOperation );
}
// ----------------------
// Accessors and Mutators
// ----------------------
@SuppressWarnings("unused")
private void setColumnList(Array_Of_TextData<TextData> columnList) {
Array_Of_TextData<TextData> oldValue = this.columnList;
this.columnList = columnList;
this.qq_Listeners.firePropertyChange("columnList", oldValue, this.columnList);
}
/**
* The GetColumnList method returns the columns previously added by the
* AddColumn method. For DML (insert, update, delete), each element in the
* array corresponds to one table. Each element will contain a
* comma-separated list of column names. For a Select query, one element
* will be returned. This lone TextData object will contain a
* comma-separated list of column names qualified by a table alias of the
* form t<n> where <n> is the number of the table to which it belongs
*
* @return
*/
public Array_Of_TextData<TextData> getColumnList() {
return this.columnList;
}
public void setData(Array_Of_SqlData<SqlData> data) {
Array_Of_SqlData<SqlData> oldValue = this.data;
this.data = data;
this.qq_Listeners.firePropertyChange("data", oldValue, this.data);
}
public Array_Of_SqlData<SqlData> getData() {
return this.data;
}
public void setDBSession(DBConnectionManager dBSession) {
DBConnectionManager oldValue = this.dBSession;
this.dBSession = dBSession;
this.qq_Listeners.firePropertyChange("DBSession", oldValue, this.dBSession);
}
public DBConnectionManager getDBSession() {
return this.dBSession;
}
public void setDistinct(boolean distinct) {
boolean oldValue = this.distinct;
this.distinct = distinct;
this.qq_Listeners.firePropertyChange("distinct", oldValue, this.distinct);
}
public boolean getDistinct() {
return this.distinct;
}
public void setForUpdate(boolean forUpdate) {
boolean oldValue = this.forUpdate;
this.forUpdate = forUpdate;
this.qq_Listeners.firePropertyChange("forUpdate", oldValue, this.forUpdate);
}
public boolean getForUpdate() {
return this.forUpdate;
}
public void setMaxRows(int maxRows) {
int oldValue = this.maxRows;
this.maxRows = maxRows;
this.qq_Listeners.firePropertyChange("maxRows", oldValue, this.maxRows);
}
public int getMaxRows() {
return this.maxRows;
}
public void setNumTables(IntegerData numTables) {
IntegerData oldValue = this.numTables;
this.numTables = numTables;
this.qq_Listeners.firePropertyChange("numTables", oldValue, this.numTables);
}
public IntegerData getNumTables() {
return this.numTables;
}
public void setOperation(int operation) {
int oldValue = this.operation;
this.operation = operation;
this.qq_Listeners.firePropertyChange("operation", oldValue, this.operation);
}
public int getOperation() {
return this.operation;
}
public void setOrderClause(TextData orderClause) {
TextData oldValue = this.orderClause;
this.orderClause = orderClause;
this.qq_Listeners.firePropertyChange("orderClause", oldValue, this.orderClause);
}
public TextData getOrderClause() {
return this.orderClause;
}
public void setQuery(BusinessQuery query) {
BusinessQuery oldValue = this.query;
this.query = query;
this.qq_Listeners.firePropertyChange("query", oldValue, this.query);
}
public BusinessQuery getQuery() {
return this.query;
}
@SuppressWarnings("unused")
private void setTableList(Array_Of_SqlQueryTable<SqlQueryTable> tableList) {
Array_Of_SqlQueryTable<SqlQueryTable> oldValue = this.tableList;
this.tableList = tableList;
this.qq_Listeners.firePropertyChange("tableList", oldValue, this.tableList);
}
@SuppressWarnings("unused")
private Array_Of_SqlQueryTable<SqlQueryTable> getTableList() {
return this.tableList;
}
public void setWhereClause(Array_Of_TextData<TextData> whereClause) {
Array_Of_TextData<TextData> oldValue = this.whereClause;
this.whereClause = whereClause;
this.qq_Listeners.firePropertyChange("whereClause", oldValue, this.whereClause);
}
public Array_Of_TextData<TextData> getWhereClause() {
return this.whereClause;
}
public void setOptions(int options) {
int oldValue = this.options;
this.options = options;
this.qq_Listeners.firePropertyChange("options", oldValue, this.options);
}
public int getOptions() {
return this.options;
}
// -------
// Methods
// -------
public void addPropertyChangeListener(String property, PropertyChangeListener listener) {
qq_Listeners.addPropertyChangeListener(property, listener);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
qq_Listeners.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(String property, PropertyChangeListener listener) {
qq_Listeners.removePropertyChangeListener(property, listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
qq_Listeners.removePropertyChangeListener(listener);
}
/**
* addColumn<p>
* AddColumn<br>
* The AddColumn method is used to spcify the name of a column to be<br>
* added to the query. For select querries the column will be put in the<br>
* select list, for update querries the column will be put in the set<br>
* list, and for insert querries the column will be put into the insert<br>
* and values lists.<br>
* <p>
* tableIndex<br>
* The tableIndex parameter specifies to which table this column<br>
* belongs.<br>
* <p>
* columnName<br>
* The columnName parameter holds the name of the column being added.<br>
* <p>
* value<br>
* The value parameter holds the value to which this column should be<br>
* set. This is only used for insert and update querries.<br>
* <p>
* @param tableIndex Type: int
* @param columnName Type: TextData
* @param value Type: DataValue (Input) (default in Forte: NIL)
*/
public void addColumn(int tableIndex, TextData columnName, DataValue value) {
if (this.getOperation() == 0) {
throw new Error(Error.SQL_OPERATION_UNINITIALIZED, "AddColumn", this).getException();
}
else if (this.getOperation() == BusinessQuery.OP_SELECT) {
//
// Selects only use the first element of the column list. Add this
// column to the end of it.
//
if (this.columnList.get(0).getActualSize() > 0) {
this.columnList.get(0).concat(", ");
}
this.columnList.get(0).concat(new TextData().replaceParameters("t%1.%2", new IntegerData(tableIndex), columnName));
}
else if ((this.getOperation() == BusinessQuery.OP_INSERT) || (this.getOperation() == BusinessQuery.OP_UPDATE)) {
if (this.columnList.get(tableIndex-1).getActualSize() > 0) {
this.columnList.get(tableIndex-1).concat(", ");
}
//
// Add this column to the list for the associated table.
//
this.columnList.get(tableIndex-1).concat(columnName);
if (this.getOperation() == BusinessQuery.OP_UPDATE) {
//
// For update the column list is the set clause and we need to add
// the '=' and the placeholder to which the value will be bound.
//
this.columnList.get(tableIndex-1).concat("=?");
}
//
// Add the value to the data list. For insert these values will be
// bound to the values clause. For update they will be bound to the
// placeholders we created in the set clause.
//
if (value == null) {
throw new Error(Error.SQL_NEED_VALUE, "AddColumn", this).getException();
}
else {
this.getData().get(tableIndex-1).getValues().add(value);
}
}
else {
throw new Error(Error.SQL_ILLEGAL_FOR_OPERATION, "AddColumn", this, new IntegerData(this.getOperation()), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
}
public void addColumn(int tableIndex, TextData columnName) {
this.addColumn(tableIndex, columnName, null);
}
/**
* addConstraint<p>
* AddConstraint<br>
* The AddConstraint method adds a constraint to the where clause and<br>
* 'and's it to the other constraints if there are any.<br>
* <p>
* constraint<br>
* The constraint parameter holds the constraint text.<br>
* <p>
* @param constraint Type: String
*/
public void addConstraint(String constraint) {
if (constraint != null && !("".equals(constraint))) {
if (this.getWhereClause().get(0).getActualSize() > 0) {
this.getWhereClause().get(0).concat(" and ");
}
this.getWhereClause().get(0).concat(constraint);
}
}
/**
* addConstraint<p>
* AddConstraint<br>
* The AddConstraint method adds a constraint to the where clause and<br>
* 'and's it to the other constraints if there are any.<br>
* <p>
* tableIndex<br>
* The tableIndex parameter specifies to which table this constraint<br>
* applies.<br>
* <p>
* columnName<br>
* The columnName parameter specfies the column to project against.<br>
* <p>
* operation<br>
* The operation parameter specifies the relationship that the column<br>
* should hold to the value. Legal values are specified by the<br>
* ConstraintOperation class.<br>
* <p>
* value<br>
* The value parameter holds the value that the column should be<br>
* compared against.<br>
* <p>
* @param tableIndex Type: int
* @param columnName Type: TextData
* @param operation Type: int
* @param value Type: DataValue
*/
public void addConstraint(int tableIndex, TextData columnName, int operation, DataValue value) {
if (operation == 0) {
throw new Error(Error.SQL_OPERATION_UNINITIALIZED, "AddConstraint", this).getException();
}
else if (this.getOperation() == BusinessQuery.OP_SELECT) {
this.addConstraint(new TextData().replaceParameters("t%1.%2%3?", new IntegerData(tableIndex), columnName, this.infixOperator(operation, 1)).toString());
this.getData().get(0).getValues().add(value);
}
else {
this.addConstraint(tableIndex, new TextData().replaceParameters("%1%2?", columnName, this.infixOperator(operation, 1)).toString());
this.getData().get(tableIndex-1).getValues().add(value);
}
}
/**
* addConstraint<p>
* AddConstraint<br>
* The AddConstraint method processes a constraint stack and adds it to<br>
* the query. For select this means turning the consraint stack into<br>
* SQL text and adding it to the where clause. For update the constraint<br>
* stack contains the columns and values that need to be used in the set<br>
* clause.<br>
* <p>
* constraint<br>
* The constraint parameter holds the constraint stack to process.<br>
* <p>
* @param constraint Type: QueryConstraint
*/
public void addConstraint(QueryConstraint constraint) {
ConstraintNode node = null;
Array_Of_ConstraintNode<ConstraintNode> stack = null;
int attrMask = 0;
int valueCount = 0;
int tableIndex = 0;
if (this.getOperation() == 0) {
throw new Error(Error.SQL_OPERATION_UNINITIALIZED, "AddConstraint", this).getException();
}
else if (constraint != null && constraint.getStack().size() > 0) {
stack = new Array_Of_ConstraintNode<ConstraintNode>();
Array_Of_ConstraintNode<ConstraintNode> qq_localVector = constraint.getStack();
if (qq_localVector != null) {
for (ConstraintNode n : qq_localVector) {
stack.add(n);
}
}
while (stack.size() > 0) {
node = stack.get(stack.size()-1);
int op = 0;
if (node instanceof ConstraintOperation) {
op = ((ConstraintOperation)node).getOperation();
}
else {
throw new Error(Error.QC_NEED_OPERATION_NODE, "AddConstraint", this).getException();
}
if ((op&ConstraintOperation.TYPE_MASK) == 0) {
//
// It's a where constraint
//
attrMask = 0;
valueCount = 0;
tableIndex = 1;
// -----------------------------------
// Parameters for call to GetWhereText
// -----------------------------------
ParameterHolder_integer qq_attrMask = new ParameterHolder_integer(attrMask);
ParameterHolder_integer qq_valueCount = new ParameterHolder_integer(valueCount);
ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(tableIndex);
TextData qq_GetWhereText = this.getWhereText(stack, qq_attrMask, qq_valueCount, qq_tableIndex);
attrMask = qq_attrMask.getInt();
valueCount = qq_valueCount.getInt();
tableIndex = qq_tableIndex.getInt();
this.addConstraint(tableIndex, qq_GetWhereText.toString());
}
else if (this.getOperation() != BusinessQuery.OP_SELECT) {
throw new Error(Error.SQL_ILLEGAL_FOR_OPERATION, "AddConstraint", this, new IntegerData(this.getOperation()), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
else if (op == ConstraintOperation.OP_FOR_UPDATE) {
stack.deleteRow(stack.size()- 1);
this.setForUpdate(true);
}
else if (op == ConstraintOperation.OP_DISTINCT) {
stack.deleteRow(stack.size()- 1);
this.setDistinct(true);
}
else if (op == ConstraintOperation.OP_NO_COLLECTIVE) {
stack.deleteRow(stack.size()- 1);
this.setOptions(SqlQuery.OPT_NO_COLLECTIVE);
}
else if (op == ConstraintOperation.OP_USE_COLLECTIVE) {
stack.deleteRow(stack.size()- 1);
this.setOptions(this.getOptions()&(~(SqlQuery.OPT_NO_COLLECTIVE|SqlQuery.OPT_COLLECTIVE_FOR_ONE)));
}
else if (op == ConstraintOperation.OP_MAX_ROWS) {
stack.deleteRow(stack.size()- 1);
node = stack.get(stack.size()-1);
if (!(node instanceof ConstraintValue)) {
throw new Error(Error.QC_NEED_VALUE_NODE, "AddConstraint", this).getException();
}
else {
this.setMaxRows(((ConstraintValue)node).getValue().asI4());
stack.deleteRow(stack.size()- 1);
}
}
else if ((op&ConstraintOperation.TYPE_MASK) == ConstraintOperation.TYPE_ORDERBY) {
stack.deleteRow(stack.size()- 1);
node = stack.get(stack.size()-1);
if (!(node instanceof ConstraintAttr)) {
throw new Error(Error.QC_NEED_ATTR_NODE, "AddConstraint", this).getException();
}
else {
TextData c = null, oldClause = null;
ConstraintAttr attrNode = (ConstraintAttr)node;
int t = attrNode.getTableIndex();
// ------------------------------------
// Parameters for call to GetColumnName
// ------------------------------------
ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t);
ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
attrNode.getEntity().getColumnName(attrNode.getAttr(), qq_tableIndex, qq_columnName);
t = qq_tableIndex.getInt();
c = (TextData)qq_columnName.getObject();
if (this.getOrderClause().getActualSize() > 0) {
oldClause = this.getOrderClause();
this.setOrderClause(new TextData());
}
this.getOrderClause().replaceParameters("t%1.%2", new IntegerData(t), c);
if (op == ConstraintOperation.OP_ORDERBY_DESC) {
this.getOrderClause().concat(" desc");
}
if (oldClause != null) {
this.getOrderClause().concat(", ");
this.getOrderClause().concat(oldClause);
}
stack.deleteRow(stack.size()- 1);
}
}
else {
stack.deleteRow(stack.size()- 1);
while (stack.size() > 0 && stack.get(stack.size()-1) instanceof ConstraintOperation) {
stack.deleteRow(stack.size()- 1);
}
}
}
}
}
/**
* addConstraint<p>
* AddConstraint<br>
* The AddConstraint method adds a constraint to the where clause and<br>
* 'and's it to the other constraints if there are any.<br>
* <p>
* tableIndex<br>
* The tableIndex parameter specifies to which table this constraint<br>
* applies.<br>
* <p>
* constraint<br>
* The constraint parameter holds the constraint text.<br>
* <p>
* @param tableIndex Type: int
* @param constraint Type: String
*/
public void addConstraint(int tableIndex, String constraint) {
if (this.getOperation() == 0) {
throw new Error(Error.SQL_OPERATION_UNINITIALIZED, "AddConstraint", this).getException();
}
else if (this.getOperation() == BusinessQuery.OP_SELECT && tableIndex > 1) {
throw new Error(Error.SQL_ILLEGAL_FOR_OPERATION, "AddConstraint", this, new IntegerData(this.getOperation()), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
else if (constraint != null && !("".equals(constraint))) {
if (this.getWhereClause().get(tableIndex-1).getActualSize() > 0) {
this.getWhereClause().get(tableIndex-1).concat(" and ");
}
this.getWhereClause().get(tableIndex-1).concat(constraint);
}
}
/**
* addTable<p>
* AddTable<br>
* The AddTable method is used to add database tables to the query being<br>
* constructed. As a side effect a unique integer is returned which<br>
* identifies the table and should be used in subsequent references to<br>
* the table added (e.g. in AddColumn). AddTable also initializes the<br>
* ColumnList, Data, and WhereClause lists for the table added. Since<br>
* a different query will be created for each table (except in the case<br>
* of selects) there must be a separate column list for each one as well<br>
* as separate data (for placeholders) and where clause (for key<br>
* constraint).<br>
* <p>
* tableName<br>
* The tableName parameter holds the name of the database table being<br>
* added to the query.<br>
* <p>
* Returns<br>
* AddTable returns an Integer object whose value is the number by<br>
* which the table added should be referred.<br>
* <p>
* @param tableName Type: TextData
* @return IntegerData
*/
public IntegerData addTable(TextData tableName) {
if (this.getOperation() == 0) {
throw new Error(Error.SQL_OPERATION_UNINITIALIZED, "AddTable", this).getException();
}
this.getNumTables().increment();
if (this.getOperation() != BusinessQuery.OP_SELECT) {
//
// A non-Select (insert, update, delete) operation. We save the table
// name in the next element in the table list, and then initialize each
// of the other lists.
//
this.columnList.set(this.getNumTables().getValue()-1, new TextData());
this.getData().set(this.getNumTables().getValue()-1, new SqlData());
this.getWhereClause().set(this.getNumTables().getValue()-1, new TextData());
}
else if (this.tableList.get(0) == null) {
//
// Select can accomodate multiple tables in a single statement so
// we only use the first element of the various lists and just append
// everything onto them. We only need to initialize them when the
// first table is added.
//
this.columnList.set(0, new TextData());
this.getData().set(0, new SqlData());
this.getWhereClause().set(0, new TextData());
this.setOrderClause(new TextData());
}
SqlQueryTable sqlTable = new SqlQueryTable();
sqlTable.setTableName(tableName);
sqlTable.setTableIndex(this.getNumTables().getValue());
this.tableList.set(this.getNumTables().getValue()-1, sqlTable);
return CloneHelper.deepClone(this.getNumTables());
}
/**
* addValue<p>
* AddValue<br>
* The AddValue method adds values for the values clause of an insert<br>
* or set clause of an update query. The values and the columns to which<br>
* they apply are described in a constraint stack.<br>
* <p>
* constraint<br>
* The constraint parameter holds the constraint stack to process.<br>
* <p>
* @param constraint Type: QueryConstraint
*/
public void addValue(QueryConstraint constraint) {
Array_Of_ConstraintNode<ConstraintNode> stack = null;
if (this.getOperation() == 0) {
throw new Error(Error.SQL_OPERATION_UNINITIALIZED, "AddConstraint", this).getException();
}
else if (constraint == null || constraint.getStack().size() <= 0) {
return;
}
else if (this.getOperation() != BusinessQuery.OP_UPDATE && this.getOperation() != BusinessQuery.OP_INSERT) {
throw new Error(Error.SQL_ILLEGAL_FOR_OPERATION, "AddValue", this, new IntegerData(this.getOperation()), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
else {
stack = new Array_Of_ConstraintNode<ConstraintNode>();
Array_Of_ConstraintNode<ConstraintNode> qq_localVector = constraint.getStack();
if (qq_localVector != null) {
for (ConstraintNode n : qq_localVector) {
stack.add(n);
}
}
ConstraintNode node1 = null;
ConstraintValue valueNode = null;
ConstraintAttr attrNode = null;
TextData c = null;
while (stack.size() > 0) {
node1 = stack.get(stack.size()-1);
stack.deleteRow(stack.size()- 1);
while (stack.size() > 0) {
if (!(node1 instanceof ConstraintOperation)) {
throw new Error(Error.QC_ILLEGAL_CONSTRAINT_NODE, "AddConstraint", this).getException();
}
else if (((ConstraintOperation)node1).getOperation() == ConstraintOperation.OP_EQ) {
break;
}
else if (((ConstraintOperation)node1).getOperation() != ConstraintOperation.OP_AND) {
throw new Error(Error.QC_ILLEGAL_CONSTRAINT_NODE, "AddConstraint", this).getException();
}
node1 = stack.get(stack.size()-1);
stack.deleteRow(stack.size()- 1);
}
if (stack.size() <= 0) {
throw new Error(Error.QC_CONSTRAINT_STACK_EMPTY, "AddConstraint", this).getException();
}
valueNode = null;
attrNode = null;
for (int i = 1; i <= 2; i++) {
node1 = stack.get(stack.size()-1);
stack.deleteRow(stack.size()- 1);
if (node1 instanceof ConstraintValue) {
if (valueNode == null) {
valueNode = (ConstraintValue)node1;
}
else {
throw new Error(Error.QC_ILLEGAL_CONSTRAINT_NODE, "AddConstraint", this).getException();
}
}
else if (node1 instanceof ConstraintAttr) {
if (attrNode == null) {
attrNode = (ConstraintAttr)node1;
}
else {
throw new Error(Error.QC_ILLEGAL_CONSTRAINT_NODE, "AddConstraint", this).getException();
}
}
else {
throw new Error(Error.QC_ILLEGAL_CONSTRAINT_NODE, "AddConstraint", this).getException();
}
}
int t1 = 0;
for (int i = 1; i <= this.getNumTables().getValue(); i++) {
t1 = i;
// ------------------------------------
// Parameters for call to GetColumnName
// ------------------------------------
ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t1);
ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
attrNode.getEntity().getColumnName(attrNode.getAttr(), qq_tableIndex, qq_columnName);
t1 = qq_tableIndex.getInt();
c = (TextData)qq_columnName.getObject();
if (c != null) {
//
// Key columns get added for all tables. Other columns only
// get added for the table to which they apply.
//
if (t1 != i) {
if (i == 1) {
this.addColumn(t1, c, valueNode.getValue());
}
break;
}
this.addColumn(t1, c, valueNode.getValue());
}
}
}
}
}
/**
* clearColumnList<p>
* ClearColumnList<br>
* The ClearColumnList method is used to clear the column list.<br>
* <p>
*/
public void clearColumnList() {
if (this.getOperation() != BusinessQuery.OP_SELECT) {
throw new Error(Error.SQL_ILLEGAL_FOR_OPERATION, "ClearColumnList", this, new IntegerData(this.getOperation()), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
this.columnList = new Array_Of_TextData<TextData>();
this.columnList.set(0, new TextData());
}
// Method GetColumnList() : Framework.Array of Framework.TextData skipped because it is replaced by accessor / mutator.
/**
* getJoinTableText<p>
* <p>
* @param joinTable Type: SqlQueryTable
* @param text Type: TextData
*/
public void getJoinTableText(SqlQueryTable joinTable, TextData text) {
int format = this.operationFormat(joinTable.getJoinOp());
if ((format&SqlQuery.OP_PREFIX_MASK) > 0) {
text.concat(this.prefixOperator(joinTable.getJoinOp()));
}
text.concat(joinTable.getTableName());
text.concat(" t");
text.concat(joinTable.getTableIndex());
Array_Of_SqlQueryTable<SqlQueryTable> qq_localVector = joinTable.getNextTable();
if (qq_localVector != null) {
for (SqlQueryTable toTable : qq_localVector) {
text.concat(this.infixOperator(joinTable.getJoinOp(), 1));
if (toTable.getNextTable() == null) {
text.concat(toTable.getTableName());
text.concat(" t");
text.concat(toTable.getTableIndex());
}
else {
text.concat("(");
this.getJoinTableText(toTable, text);
text.concat(")");
}
if ((format&SqlQuery.OP_POSTFIX_MASK) > 0) {
text.concat(this.postfixOperator(joinTable.getJoinOp()));
}
if (toTable.getOnClause() != null) {
text.concat(" on ");
text.concat(toTable.getOnClause());
}
}
}
}
/**
* getTableListText<p>
* <p>
* @return TextData
*/
private TextData getTableListText() {
TextData str = new TextData();
if (this.tableList != null) {
for (SqlQueryTable t : this.tableList) {
if (t.getPrevTable() == null && t.getNextTable() == null) {
str.concat(t.getTableName());
str.concat(" t");
str.concat(t.getTableIndex());
str.concat(", ");
}
else if (t.getPrevTable() == null) {
if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ODBC) {
str.concat("{oj ");
}
this.getJoinTableText(t, str);
if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ODBC) {
str.concat(" }");
}
str.concat(", ");
}
}
}
str.setOffset(str.totalLength()-2);
str.truncate();
if (this.getForUpdate() && this.getDBSession().getDBVendorType() == Constants.DB_VT_SYBASE) {
str.concat(" holdlock");
}
return str;
}
/**
* getText<p>
* GetText<br>
* The GetText method returns the SQL text for the queries described by<br>
* this object. To use SqlQuery, set the Operation attribute from the<br>
* operations codes defined by BusinessQuery, then use AddTable,<br>
* AddColumn, and AddConstraint to describe the query. Finally GetText<br>
* will give you the text of the SQL needed to execute the query<br>
* described.<br>
* <p>
* Returns<br>
* The text of the SQL queries described by this object. For select<br>
* queries there will only be one element in the array. For other<br>
* queries there will be one element in the array for each table.<br>
* Note: if no query needs to be run for a given table then that<br>
* element in the array will contain an empty string.<br>
* <p>
* @return Array_Of_TextData<TextData>
*/
public Array_Of_TextData<TextData> getText() {
Array_Of_TextData<TextData> queries = new Array_Of_TextData<TextData>();
TextData text = null;
TextData whereText = new TextData();
Tables:
for (int i = 1; i <= this.tableList.size(); i++) {
text = new TextData();
queries.add(text);
if (this.columnList.get(i-1).getActualSize() <= 1 && this.getOperation() != BusinessQuery.OP_DELETE) {
//
// If there are no columns specified we don't generate a query for
// this table. The one exception being delete where we never specify
// columns anyway.
//
continue;
}
//
// If there is going to be a where clause we need to introduce it. We
// parameterize this since we don't always have a where clause.
//
if (this.getWhereClause().get(i-1).getActualSize() > 0) {
whereText.setValue( " where " );
}
else {
whereText.setValue( "" );
}
//
// Create the query filling in the column list, table name, etc.
//
switch (this.getOperation()) {
case BusinessQuery.OP_SELECT: {
if (this.getDistinct()) {
text.replaceParameters("select distinct %1 from %2%3%4", this.columnList.get(i-1), this.getTableListText(), whereText, this.getWhereClause().get(0));
}
else {
text.replaceParameters("select %1 from %2%3%4", this.columnList.get(i-1), this.getTableListText(), whereText, this.getWhereClause().get(0));
}
if (this.getOrderClause().getActualSize() > 2) {
text.concat(" order by ");
text.concat(this.getOrderClause());
}
if (this.getForUpdate() && this.getDBSession().getDBVendorType() != Constants.DB_VT_RDB && this.getDBSession().getDBVendorType() != Constants.DB_VT_SYBASE && this.getDBSession().getDBVendorType() != Constants.DB_VT_DB2) {
text.concat(" for update");
}
break Tables;
}
case BusinessQuery.OP_UPDATE: {
text.replaceParameters("update %1 set %2%3%4", this.tableList.get(i-1).getTableName(), this.columnList.get(i-1), whereText, this.getWhereClause().get(i-1));
break;
}
case BusinessQuery.OP_DELETE: {
text.replaceParameters("delete from %1%2%3", this.tableList.get(i-1).getTableName(), whereText, this.getWhereClause().get(i-1));
break;
}
case BusinessQuery.OP_INSERT: {
//
// For insert we need to create placeholders for the values
// clause -- one for each column in the column list.
//
TextData values = new TextData("?");
this.columnList.get(i-1).setOffset(0);
while (this.columnList.get(i-1).moveToChar(",")) {
values.concat(",?");
this.columnList.get(i-1).moveNext();
}
text.replaceParameters("insert into %1(%2) values (%3)", this.tableList.get(i-1).getTableName(), this.columnList.get(i-1), values);
break;
}
}
}
return queries;
}
/**
* getWhereText<p>
* GetWhereText<br>
* The GetWhereText method is used to construct a where clause<br>
* for a select statement from a constraint stack.<br>
* <p>
* stack<br>
* The stack parameter holds the constraint stack to be decoded.<br>
* <p>
* @param stack Type: Array_Of_ConstraintNode<ConstraintNode>
* @param attrMask Type: int
* @param valueCount Type: int
* @param tableIndex Type: int
* @return TextData
*/
private TextData getWhereText(Array_Of_ConstraintNode<ConstraintNode> stack, ParameterHolder_integer attrMask, ParameterHolder_integer valueCount, ParameterHolder_integer tableIndex) {
TextData result = new TextData();
ConstraintNode node = null;
int opNodeOp = 0;
int opNodeOpCode = 0;
ConstraintAttr attrNode = null;
int t = 0;
TextData c = null, c2 = null;
int initialValueCount = valueCount.getInt();
if (stack.size() <= 0) {
throw new Error(Error.QC_CONSTRAINT_STACK_EMPTY, "GetWhereText", this).getException();
}
node = stack.get(stack.size()-1);
stack.deleteRow(stack.size()- 1);
if (node instanceof ConstraintValue) {
result.setValue( "?" );
this.getData().get(tableIndex.getInt()-1).getValues().add(((ConstraintValue)node).getValue());
valueCount.setInt(valueCount.getInt()+1);
}
else if (node instanceof ConstraintAttr) {
attrNode = (ConstraintAttr)node;
t = attrNode.getTableIndex();
// ------------------------------------
// Parameters for call to GetColumnName
// ------------------------------------
ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t);
ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
attrNode.getEntity().getColumnName(attrNode.getAttr(), qq_tableIndex, qq_columnName);
t = qq_tableIndex.getInt();
c = (TextData)qq_columnName.getObject();
if ((c == null || c.getActualSize() == 0) && (attrNode.getAttr() > attrNode.getEntity().getNumDBAttrs())) {
attrMask.setInt(attrMask.getInt()|SqlQuery.ATTRTYPE_CUSTOM);
}
else {
attrMask.setInt(attrMask.getInt()|SqlQuery.ATTRTYPE_DB);
}
if (this.getOperation() == BusinessQuery.OP_SELECT) {
result.replaceParameters("t%1.%2", new IntegerData(t), c);
}
else {
result.concat(c);
tableIndex.setInt(t);
}
}
else if (node instanceof ConstraintConstant) {
result.setValue( ((ConstraintConstant)node).getValue() );
}
else if (node instanceof ConstraintOperation) {
opNodeOp = ((ConstraintOperation)node).getOperation();
opNodeOpCode = opNodeOp&ConstraintOperation.OPCODE_MASK;
if (opNodeOpCode == ConstraintOperation.OPCODE_IN) {
if (stack.size() < 2) {
throw new Error(Error.QC_CONSTRAINT_STACK_EMPTY, "GetWhereText", this).getException();
}
result.setValue( "(" );
if (!(stack.get(stack.size()-1) instanceof ConstraintAttr)) {
throw new Error(Error.QC_NEED_ATTR_NODE, "GetWhereText", this).getException();
}
else {
// -----------------------------------
// Parameters for call to GetWhereText
// -----------------------------------
ParameterHolder_integer qq_attrMask = new ParameterHolder_integer(attrMask.getInt());
ParameterHolder_integer qq_valueCount = new ParameterHolder_integer(valueCount.getInt());
ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(tableIndex.getInt());
TextData qq_GetWhereText = this.getWhereText(stack, qq_attrMask, qq_valueCount, qq_tableIndex);
attrMask.setInt(qq_attrMask.getInt());
valueCount.setInt(qq_valueCount.getInt());
tableIndex.setInt(qq_tableIndex.getInt());
c = qq_GetWhereText;
}
while (stack.size() > 1 && stack.get(stack.size()-1) instanceof ConstraintAttr) {
c.replaceRange(", ", 0, 0);
// -----------------------------------
// Parameters for call to GetWhereText
// -----------------------------------
ParameterHolder_integer qq_attrMask = new ParameterHolder_integer(attrMask.getInt());
ParameterHolder_integer qq_valueCount = new ParameterHolder_integer(valueCount.getInt());
ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(tableIndex.getInt());
TextData qq_GetWhereText = this.getWhereText(stack, qq_attrMask, qq_valueCount, qq_tableIndex);
attrMask.setInt(qq_attrMask.getInt());
valueCount.setInt(qq_valueCount.getInt());
tableIndex.setInt(qq_tableIndex.getInt());
c.replaceRange(qq_GetWhereText, 0, 0);
}
result.concat(c);
result.concat(") in (");
if (!(stack.get(stack.size()-1) instanceof ConstraintValue)) {
throw new Error(Error.QC_NEED_VALUE_NODE, "GetWhereText", this).getException();
}
else {
result.concat(((ConstraintValue)(stack.get(stack.size()-1))).getValue());
stack.deleteRow(stack.size()- 1);
}
result.concat(")");
if (stack.size() > 0 && stack.get(stack.size()-1) instanceof ConstraintSqlData) {
Array_Of_DataValue<DataValue> qq_localVector = ((ConstraintSqlData)(stack.get(stack.size()-1))).getData().getValues();
if (qq_localVector != null) {
for (DataValue d : qq_localVector) {
this.getData().get(tableIndex.getInt()-1).getValues().add(d);
}
}
stack.deleteRow(stack.size()- 1);
}
}
else if (opNodeOpCode == ConstraintOperation.OPCODE_LEFTJOIN || opNodeOpCode == ConstraintOperation.OPCODE_RIGHTJOIN || opNodeOpCode == ConstraintOperation.OPCODE_EQUIJOIN) {
boolean doFancyJoin = opNodeOpCode != ConstraintOperation.OPCODE_EQUIJOIN && this.getDBSession().getDBVendorType() != Constants.DB_VT_ORACLE && this.getDBSession().getDBVendorType() != Constants.DB_VT_SYBASE;
int oldFromTable = 0, newFromTable = 0, oldToTable = 0, newToTable = 0;
if (opNodeOpCode == ConstraintOperation.OPCODE_EQUIJOIN) {
this.setOptions(this.getOptions()|SqlQuery.OPT_INNER_JOIN);
}
else {
this.setOptions(this.getOptions()|SqlQuery.OPT_OUTER_JOIN);
}
TextData c3 = new TextData();
if (doFancyJoin) {
node = stack.get(stack.size()-1);
if (!(node instanceof ConstraintAttr)) {
throw new Error(Error.QC_NEED_ATTR_NODE, "GetWhereText", this).getException();
}
attrNode = (ConstraintAttr)node;
if (attrNode.getTableIndex() > this.tableList.size()) {
throw new Error(Error.QC_ILLEGAL_TABLE_INDEX, "GetWhereText", this, new IntegerData(attrNode.getTableIndex()), new IntegerData(this.tableList.size())).getException();
}
node = stack.get(stack.size()-1-1);
if (!(node instanceof ConstraintAttr)) {
throw new Error(Error.QC_NEED_ATTR_NODE, "GetWhereText", this).getException();
}
if (((ConstraintAttr)node).getTableIndex() > this.tableList.size()) {
throw new Error(Error.QC_ILLEGAL_TABLE_INDEX, "GetWhereText", this, new IntegerData(attrNode.getTableIndex()), new IntegerData(this.tableList.size())).getException();
}
t = attrNode.getEntity().getTableAliases().get(attrNode.getTableIndex()-1).getValue();
int t2 = ((ConstraintAttr)node).getEntity().getTableAliases().get(((ConstraintAttr)node).getTableIndex()-1).getValue();
//
// We want to put in a join for attrNode. We know the table
// aliases t, and t2 to use. We have to check that these
// tables aren't already participating in a join. 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. The one
// exception is that t can participate in multiple joins if
// the OPT_NO_MULT_OUTER_JOIN option is not set.
//
int t3 = 0;
if (this.tableList.get(t2-1).getPrevTable() != null) {
oldToTable = t2;
this.addTable(this.tableList.get(t2-1).getTableName());
for (int i = 1; i <= attrNode.getEntity().getNumKeyAttrs(); i++) {
t3 = attrNode.getTableIndex();
// ------------------------------------
// Parameters for call to GetColumnName
// ------------------------------------
ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t3);
ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
attrNode.getEntity().getColumnName(i, qq_tableIndex, qq_columnName);
t3 = qq_tableIndex.getInt();
c = (TextData)qq_columnName.getObject();
if (c == null) {
c = new TextData();
}
this.addConstraint(c3.replaceParameters("t%1.%2 = t%3.%2", new IntegerData(t2), c, this.getNumTables()).toString());
}
t2 = this.getNumTables().getValue();
newToTable = t2;
}
if (this.tableList.get(t-1).getNextTable() == null) {
this.tableList.get(t-1).setNextTable(new Array_Of_SqlQueryTable<SqlQueryTable>());
this.tableList.get(t-1).getNextTable().add(this.tableList.get(t2-1));
this.tableList.get(t2-1).setPrevTable(this.tableList.get(t-1));
}
else if ((this.getOptions()&SqlQuery.OPT_NO_MULT_OUTER_JOIN) == 0) {
this.tableList.get(t-1).getNextTable().add(this.tableList.get(t2-1));
this.tableList.get(t2-1).setPrevTable(this.tableList.get(t-1));
}
else {
oldFromTable = t;
this.addTable(this.tableList.get(t-1).getTableName());
for (int i = 1; i <= attrNode.getEntity().getNumKeyAttrs(); i++) {
t3 = attrNode.getTableIndex();
// ------------------------------------
// Parameters for call to GetColumnName
// ------------------------------------
ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t3);
ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
attrNode.getEntity().getColumnName(i, qq_tableIndex, qq_columnName);
t3 = qq_tableIndex.getInt();
c = (TextData)qq_columnName.getObject();
if (c == null) {
c = new TextData();
}
this.addConstraint(c3.replaceParameters("t%1.%2 = t%3.%2", new IntegerData(t), c, this.getNumTables()).toString());
}
t = this.getNumTables().getValue();
newFromTable = t;
this.tableList.get(t-1).setNextTable(new Array_Of_SqlQueryTable<SqlQueryTable>());
this.tableList.get(t-1).getNextTable().add(this.tableList.get(t2-1));
this.tableList.get(t2-1).setPrevTable(this.tableList.get(t-1));
}
this.tableList.get(t-1).setJoinOp(opNodeOpCode);
if (this.getDBSession().getDBVendorType() != Constants.DB_VT_INFORMIX) {
this.tableList.get(t2-1).setOnClause(result);
}
}
//
// We've now completed linking the joined tables together in the
// table list. Now we need to create the join condition. Depending
// on the database this may end up in the where clause or in the
// join clause.
//
int params = (opNodeOp&ConstraintOperation.PCOUNT_MASK)/ConstraintOperation.PCOUNT_INCREMENT;
if (stack.size() < params*2) {
throw new Error(Error.QC_CONSTRAINT_STACK_EMPTY, "GetWhereText", this).getException();
}
int format = this.operationFormat(opNodeOp);
if (doFancyJoin) {
c2 = new TextData(" = ");
}
else {
c2 = this.infixOperator(opNodeOp, 1);
}
for (int i = 1; i <= params*2; i++) {
if (i > 1) {
if ((i&1) > 0) {
result.concat(" and ");
}
else {
result.concat(c2);
}
}
node = stack.get(stack.size()-1);
if (!(node instanceof ConstraintAttr)) {
throw new Error(Error.QC_NEED_ATTR_NODE, "GetWhereText", this).getException();
}
stack.deleteRow(stack.size()- 1);
attrNode = (ConstraintAttr)node;
t = attrNode.getTableIndex();
// ------------------------------------
// Parameters for call to GetColumnName
// ------------------------------------
ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t);
ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
attrNode.getEntity().getColumnName(attrNode.getAttr(), qq_tableIndex, qq_columnName);
t = qq_tableIndex.getInt();
c = (TextData)qq_columnName.getObject();
if (t == oldFromTable) {
t = newFromTable;
}
else if (t == oldToTable) {
t = newToTable;
}
if (c == null) {
c = new TextData();
}
result.concat(c3.replaceParameters("t%1.%2", new IntegerData(t), c));
if ((i&1) == 0 && (format&SqlQuery.OP_POSTFIX_MASK) > 0) {
result.concat(this.postfixOperator(opNodeOp));
}
}
if (doFancyJoin && this.getDBSession().getDBVendorType() != Constants.DB_VT_INFORMIX) {
result = new TextData();
}
}
else if (opNodeOpCode == ConstraintOperation.OPCODE_APPROX) {
ConstraintValue valueNode = null;
QueryConstraint constraint = new QueryConstraint();
constraint.setStack(stack);
if (stack.size() < 2) {
throw new Error(Error.QC_CONSTRAINT_STACK_EMPTY, "GetWhereText", this).getException();
}
if (!(stack.get(stack.size()-1) instanceof ConstraintAttr)) {
throw new Error(Error.QC_NEED_ATTR_NODE, "GetWhereText", this).getException();
}
else {
attrNode = (ConstraintAttr)(stack.get(stack.size()-1));
stack.deleteRow(stack.size()- 1);
}
if (!(stack.get(stack.size()-1) instanceof ConstraintValue)) {
throw new Error(Error.QC_NEED_VALUE_NODE, "GetWhereText", this).getException();
}
else {
valueNode = (ConstraintValue)(stack.get(stack.size()-1));
stack.deleteRow(stack.size()- 1);
}
if (attrNode.getAttr() > attrNode.getEntity().getNumDBAttrs()) {
// Custom attribute -- skip it.
return result;
}
int dtype = valueNode.getValue().dataType()&127;
if (dtype == 6) {
// value.IsA(TextData)
if (!(valueNode.getValue() instanceof LongTextDomain)) {
TextData v = (TextData)valueNode.getValue();
if (v.getIsNull()) {
stack.add(attrNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_NULL));
}
else if (this.getDBSession().getDBVendorType() == Constants.DB_VT_RDB || this.getDBSession().getDBVendorType() == Constants.DB_VT_DB2) {
stack.add(valueNode);
stack.add(attrNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_EQ));
}
else if (v.getActualSize() == 0) {
constraint.addConstant(new TextData("' '"));
stack.add(attrNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_EQ));
stack.add(attrNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_NULL));
stack.add(new ConstraintOperation(ConstraintOperation.OP_OR));
}
else {
stack.add(valueNode);
stack.add(attrNode);
v.setOffset(v.getActualSize()-1);
if (!(v.isChar(" "))) {
stack.add(new ConstraintOperation(ConstraintOperation.OP_RTRIM));
}
stack.add(new ConstraintOperation(ConstraintOperation.OP_EQ));
}
}
}
else if (dtype == 8 || dtype == 9) {
// if value.IsA(BinaryData) or value.IsA(ImageData) leave it out of the
// constraint.
}
else if (dtype == 7 || dtype == 1) {
// value.IsA(DoubleData)
if (valueNode.getValue().getIsNull()) {
stack.add(attrNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_NULL));
}
else if (this.getDBSession().getDBVendorType() != Constants.DB_VT_DB2) {
constraint.addConstant(new TextData(".000000000001"));
stack.add(attrNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_MUL));
stack.add(new ConstraintOperation(ConstraintOperation.OP_ABS));
stack.add(valueNode);
stack.add(attrNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_SUB));
stack.add(new ConstraintOperation(ConstraintOperation.OP_ABS));
stack.add(new ConstraintOperation(ConstraintOperation.OP_LE));
}
else {
constraint.addConstant(new TextData(".000000000001"));
stack.add(attrNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_MUL));
stack.add(valueNode);
stack.add(attrNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_SUB));
stack.add(new ConstraintOperation(ConstraintOperation.OP_LE));
constraint.addConstant(new TextData(".000000000001"));
stack.add(attrNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_MUL));
stack.add(attrNode);
stack.add(valueNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_SUB));
stack.add(new ConstraintOperation(ConstraintOperation.OP_LE));
stack.add(new ConstraintOperation(ConstraintOperation.OP_OR));
}
}
else if (valueNode.getValue().getIsNull()) {
stack.add(attrNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_NULL));
}
else {
stack.add(valueNode);
stack.add(attrNode);
stack.add(new ConstraintOperation(ConstraintOperation.OP_EQ));
}
if (stack.size() > 0) {
// -----------------------------------
// Parameters for call to GetWhereText
// -----------------------------------
ParameterHolder_integer qq_attrMask = new ParameterHolder_integer(attrMask.getInt());
ParameterHolder_integer qq_valueCount = new ParameterHolder_integer(valueCount.getInt());
ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(tableIndex.getInt());
TextData qq_GetWhereText = this.getWhereText(stack, qq_attrMask, qq_valueCount, qq_tableIndex);
attrMask.setInt(qq_attrMask.getInt());
valueCount.setInt(qq_valueCount.getInt());
tableIndex.setInt(qq_tableIndex.getInt());
result = qq_GetWhereText;
}
}
else {
int format = this.operationFormat(opNodeOp);
if ((format&SqlQuery.OP_PREFIX_MASK) > 0) {
result = this.prefixOperator(opNodeOp);
}
if ((opNodeOp&ConstraintOperation.PCOUNT_MASK) > 0) {
if ((format&SqlQuery.OP_PAREN_MASK) > 0) {
result.concat("(");
}
// -----------------------------------
// Parameters for call to GetWhereText
// -----------------------------------
ParameterHolder_integer qq_attrMask = new ParameterHolder_integer(attrMask.getInt());
ParameterHolder_integer qq_valueCount = new ParameterHolder_integer(valueCount.getInt());
ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(tableIndex.getInt());
TextData qq_GetWhereText = this.getWhereText(stack, qq_attrMask, qq_valueCount, qq_tableIndex);
attrMask.setInt(qq_attrMask.getInt());
valueCount.setInt(qq_valueCount.getInt());
tableIndex.setInt(qq_tableIndex.getInt());
result.concat(qq_GetWhereText);
for (int i = 2; i <= (opNodeOp&ConstraintOperation.PCOUNT_MASK)/ConstraintOperation.PCOUNT_INCREMENT; i++) {
if ((format&SqlQuery.OP_INFIX_MASK) > 0) {
result.concat(this.infixOperator(opNodeOp, i-1));
}
else {
result.concat(", ");
}
// -----------------------------------
// Parameters for call to GetWhereText
// -----------------------------------
ParameterHolder_integer qq_attrMask1 = new ParameterHolder_integer(attrMask.getInt());
ParameterHolder_integer qq_valueCount1 = new ParameterHolder_integer(valueCount.getInt());
ParameterHolder_integer qq_tableIndex1 = new ParameterHolder_integer(tableIndex.getInt());
TextData qq_GetWhereText1 = this.getWhereText(stack, qq_attrMask1, qq_valueCount1, qq_tableIndex1);
attrMask.setInt(qq_attrMask1.getInt());
valueCount.setInt(qq_valueCount1.getInt());
tableIndex.setInt(qq_tableIndex1.getInt());
result.concat(qq_GetWhereText1);
}
if ((format&SqlQuery.OP_PAREN_MASK) > 0) {
result.concat(")");
}
}
if ((format&SqlQuery.OP_POSTFIX_MASK) > 0) {
result.concat(this.postfixOperator(opNodeOp));
}
}
if ((attrMask.getInt()&SqlQuery.ATTRTYPE_CUSTOM) > 0) {
if ((attrMask.getInt()&SqlQuery.ATTRTYPE_DB) > 0) {
throw new Error(Error.QC_CUSTOM_AND_DB_ATTR, "GetWhereText", this, result, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
result.clear();
for (int i = initialValueCount+1; i <= valueCount.getInt(); i++) {
this.getData().get(tableIndex.getInt()-1).getValues().deleteRow(this.getData().get(tableIndex.getInt()-1).getValues().size()- 1);
}
valueCount.setInt(initialValueCount);
}
}
else {
throw new Error(Error.QC_ILLEGAL_CONSTRAINT_NODE, "GetWhereText", this).getException();
}
return result;
}
/**
* infixOperator<p>
* InfixOperator<br>
* The InfixOperator method returns the SQL text for the operator specified<br>
* by the operation parameter.<br>
* <p>
* operation<br>
* The operation parameter specifies which operation for which to return<br>
* SQL text. Legal values are defined by the ConstraintOperation class.<br>
* <p>
* @param operation Type: int
* @param position Type: int (Input) (default in Forte: 1)
* @return TextData
*/
private TextData infixOperator(int operation, int position) {
TextData result = new TextData();
switch (operation&ConstraintOperation.OPCODE_MASK) {
case ConstraintOperation.OPCODE_ADD: {
result.setValue( " + " );
break;
}
case ConstraintOperation.OPCODE_AND: {
result.setValue( " and " );
break;
}
case ConstraintOperation.OPCODE_DIV: {
result.setValue( " / " );
break;
}
case ConstraintOperation.OPCODE_EQ: {
result.setValue( " = " );
break;
}
case ConstraintOperation.OPCODE_EQUIJOIN: {
result.setValue( " = " );
break;
}
case ConstraintOperation.OPCODE_GE: {
result.setValue( " >= " );
break;
}
case ConstraintOperation.OPCODE_GT: {
result.setValue( " > " );
break;
}
case ConstraintOperation.OPCODE_LE: {
result.setValue( " <= " );
break;
}
case ConstraintOperation.OPCODE_LT: {
result.setValue( " < " );
break;
}
case ConstraintOperation.OPCODE_NE: {
result.setValue( " <> " );
break;
}
case ConstraintOperation.OPCODE_OR: {
result.setValue( " or " );
break;
}
case ConstraintOperation.OPCODE_LIKE: {
result.setValue( " like " );
break;
}
case ConstraintOperation.OPCODE_MUL: {
result.setValue( " * " );
break;
}
case ConstraintOperation.OPCODE_SUB: {
result.setValue( " - " );
break;
}
case ConstraintOperation.OPCODE_BETWEEN: {
if (position == 1) {
result.setValue( " between " );
}
else {
result.setValue( " and " );
}
break;
}
case ConstraintOperation.OPCODE_LEFTJOIN: {
switch (this.getDBSession().getDBVendorType()) {
case Constants.DB_VT_SYBASE: {
result.setValue( " *= " );
break;
}
case Constants.DB_VT_ORACLE: {
result.setValue( " = " );
break;
}
case Constants.DB_VT_RDB: {
result.setValue( " left outer join " );
break;
}
case Constants.DB_VT_INFORMIX: {
result.setValue( ", outer " );
break;
}
case Constants.DB_VT_INGRES: {
result.setValue( " left join " );
break;
}
case Constants.DB_VT_ODBC: {
result.setValue( " left outer join " );
break;
}
default: {
throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "InfixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
}
break;
}
case ConstraintOperation.OPCODE_RIGHTJOIN: {
switch (this.getDBSession().getDBVendorType()) {
case Constants.DB_VT_SYBASE: {
result.setValue( " =* " );
break;
}
case Constants.DB_VT_ORACLE: {
result.setValue( " (+) = " );
break;
}
case Constants.DB_VT_RDB: {
result.setValue( " right outer join " );
break;
}
case Constants.DB_VT_INFORMIX: {
result.setValue( ", " );
break;
}
case Constants.DB_VT_INGRES: {
result.setValue( " right join " );
break;
}
case Constants.DB_VT_ODBC: {
result.setValue( " right outer join " );
break;
}
default: {
throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "InfixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
}
break;
}
default: {
throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "InfixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
}
return result;
}
/**
* operationFormat<p>
* <p>
* @param operation Type: int
* @return int
*/
private int operationFormat(int operation) {
int format = 0;
switch (operation&ConstraintOperation.OPCODE_MASK) {
case ConstraintOperation.OPCODE_ADD: {
format = SqlQuery.OP_FORMAT_ADD;
break;
}
case ConstraintOperation.OPCODE_AND: {
format = SqlQuery.OP_FORMAT_AND;
break;
}
case ConstraintOperation.OPCODE_DIV: {
format = SqlQuery.OP_FORMAT_DIV;
break;
}
case ConstraintOperation.OPCODE_EQ: {
format = SqlQuery.OP_FORMAT_EQ;
break;
}
case ConstraintOperation.OPCODE_EQUIJOIN: {
format = SqlQuery.OP_FORMAT_EQUIJOIN;
break;
}
case ConstraintOperation.OPCODE_GE: {
format = SqlQuery.OP_FORMAT_GE;
break;
}
case ConstraintOperation.OPCODE_GT: {
format = SqlQuery.OP_FORMAT_GT;
break;
}
case ConstraintOperation.OPCODE_LE: {
format = SqlQuery.OP_FORMAT_LE;
break;
}
case ConstraintOperation.OPCODE_LT: {
format = SqlQuery.OP_FORMAT_LT;
break;
}
case ConstraintOperation.OPCODE_NE: {
format = SqlQuery.OP_FORMAT_NE;
break;
}
case ConstraintOperation.OPCODE_OR: {
format = SqlQuery.OP_FORMAT_OR;
break;
}
case ConstraintOperation.OPCODE_LIKE: {
format = SqlQuery.OP_FORMAT_LIKE;
break;
}
case ConstraintOperation.OPCODE_MUL: {
format = SqlQuery.OP_FORMAT_MUL;
break;
}
case ConstraintOperation.OPCODE_NOT: {
format = SqlQuery.OP_FORMAT_NOT;
break;
}
case ConstraintOperation.OPCODE_NULL: {
format = SqlQuery.OP_FORMAT_NULL;
break;
}
case ConstraintOperation.OPCODE_NOTNULL: {
format = SqlQuery.OP_FORMAT_NOTNULL;
break;
}
case ConstraintOperation.OPCODE_SUB: {
format = SqlQuery.OP_FORMAT_SUB;
break;
}
case ConstraintOperation.OPCODE_BETWEEN: {
format = SqlQuery.OP_FORMAT_BETWEEN;
break;
}
case ConstraintOperation.OPCODE_LEFTJOIN: {
format = SqlQuery.OP_INFIX_MASK;
if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ORACLE) {
format = SqlQuery.OP_INFIX_MASK|SqlQuery.OP_POSTFIX_MASK;
}
break;
}
case ConstraintOperation.OPCODE_RIGHTJOIN: {
format = SqlQuery.OP_INFIX_MASK;
if (this.getDBSession().getDBVendorType() == Constants.DB_VT_INFORMIX) {
format = SqlQuery.OP_INFIX_MASK|SqlQuery.OP_PREFIX_MASK;
}
break;
}
case ConstraintOperation.OPCODE_ABS: {
format = SqlQuery.OP_FORMAT_ABS;
break;
}
case ConstraintOperation.OPCODE_RTRIM: {
format = SqlQuery.OP_FORMAT_RTRIM;
if (this.getDBSession().getDBVendorType() == Constants.DB_VT_INFORMIX || this.getDBSession().getDBVendorType() == Constants.DB_VT_RDB) {
format = SqlQuery.OP_PREFIX_MASK|SqlQuery.OP_POSTFIX_MASK;
}
else if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ODBC) {
format = format|SqlQuery.OP_POSTFIX_MASK;
}
break;
}
case ConstraintOperation.OPCODE_RTRIMFIXED: {
format = 0;
if (this.getDBSession().getDBVendorType() != Constants.DB_VT_RDB && this.getDBSession().getDBVendorType() != Constants.DB_VT_DB2) {
format = this.operationFormat(ConstraintOperation.OPCODE_RTRIM);
}
break;
}
default: {
throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "OperationFormat", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
}
return format;
}
/**
* postfixOperator<p>
* PostfixOperator<br>
* The PostfixOperator method returns the SQL text for the operator specified<br>
* by the operation parameter.<br>
* <p>
* operation<br>
* The operation parameter specifies which operation for which to return<br>
* SQL text. Legal values are defined by the ConstraintOperation class.<br>
* <p>
* @param operation Type: int
* @return TextData
*/
private TextData postfixOperator(int operation) {
TextData result = new TextData();
switch (operation&ConstraintOperation.OPCODE_MASK) {
case ConstraintOperation.OPCODE_RTRIM: {
if (this.getDBSession().getDBVendorType() == Constants.DB_VT_INFORMIX || this.getDBSession().getDBVendorType() == Constants.DB_VT_RDB) {
result.setValue( ")" );
}
else if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ODBC) {
result.setValue( "}" );
}
else {
throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "PostfixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
break;
}
case ConstraintOperation.OPCODE_RTRIMFIXED: {
result = this.postfixOperator(ConstraintOperation.OPCODE_RTRIM);
break;
}
case ConstraintOperation.OPCODE_NULL: {
result.setValue( " is null" );
break;
}
case ConstraintOperation.OPCODE_NOTNULL: {
result.setValue( " is not null" );
break;
}
case ConstraintOperation.OPCODE_LEFTJOIN: {
if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ORACLE) {
result.setValue( " (+)" );
}
else {
throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "PostfixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
break;
}
default: {
throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "PostfixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
}
return result;
}
/**
* prefixOperator<p>
* PrefixOperator<br>
* The PrefixOperator method returns the SQL text for the operator specified<br>
* by the operation parameter.<br>
* <p>
* operation<br>
* The operation parameter specifies which operation for which to return<br>
* SQL text. Legal values are defined by the ConstraintOperation class.<br>
* <p>
* @param operation Type: int
* @return TextData
*/
private TextData prefixOperator(int operation) {
TextData result = new TextData();
switch (operation&ConstraintOperation.OPCODE_MASK) {
case ConstraintOperation.OPCODE_ABS: {
result.setValue( "abs" );
break;
}
case ConstraintOperation.OPCODE_RTRIM: {
if (this.getDBSession().getDBVendorType() == Constants.DB_VT_INFORMIX || this.getDBSession().getDBVendorType() == Constants.DB_VT_RDB) {
result.setValue( "trim (trailing ' ' from " );
}
else if (this.getDBSession().getDBVendorType() == Constants.DB_VT_INGRES) {
result.setValue( "trim" );
}
else if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ODBC) {
result.setValue( "{fn rtrim" );
}
else {
result.setValue( "rtrim" );
}
break;
}
case ConstraintOperation.OPCODE_RTRIMFIXED: {
result = this.prefixOperator(ConstraintOperation.OPCODE_RTRIM);
break;
}
case ConstraintOperation.OPCODE_NOT: {
result.setValue( "not " );
break;
}
case ConstraintOperation.OPCODE_RIGHTJOIN: {
if (this.getDBSession().getDBVendorType() == Constants.DB_VT_INFORMIX) {
result.setValue( "outer " );
}
else {
throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "PrefixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
break;
}
default: {
throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "PrefixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
}
}
return result;
}
/**
* setup<p>
* <p>
* @param query Type: BusinessQuery
* @param operation Type: int
* @param dbSession Type: DBConnectionManager
* @return SqlQuery
*/
public SqlQuery setup(BusinessQuery query, int operation, DBConnectionManager dbSession) {
this.setQuery(query);
this.setOperation(operation);
this.setDBSession(dbSession);
if (this.getDBSession() != null) {
int vt = this.getDBSession().getDBVendorType();
if (vt == Constants.DB_VT_RDB || vt == Constants.DB_VT_ODBC) {
this.setOptions(SqlQuery.OPT_COLLECTIVE_FOR_ONE);
}
else if (vt == Constants.DB_VT_SYBASE) {
this.setOptions(SqlQuery.OPT_NO_TRANSITIVE_OUTER_JOIN|SqlQuery.OPT_NO_MULT_OUTER_JOIN);
}
else if (vt == Constants.DB_VT_DB2) {
this.setOptions(SqlQuery.OPT_COLLECTIVE_FOR_ONE);
}
else if (vt == Constants.DB_VT_ORACLE) {
this.setOptions(SqlQuery.OPT_NO_MULT_OUTER_JOIN);
}
}
return this;
}
} // end class SqlQuery
// c Pass 2 Conversion Time: 6281 milliseconds