protected Expression processPropertyTracedownTooneOptimized( Attribute<?, ?> attr, Expression builder, List<Parameter> parameters) { ConditionQuery subQuery = getTraceDownQuery(); Expression finalExp = null; for (PropertyCondition subPc : subQuery.getConditions()) { if (subPc.isReturnSimpleExpression()) { Expression subExp = subPc.processProperty(builder.get(getProp()), parameters); if (finalExp == null) { finalExp = subExp; } else { finalExp = finalExp.and(subExp); } } else { // low-performance query since an extra layer of exists added // but this is the only way to make it work. // this situation is rare. So we may do not need to optimize it Expression subBuilder = new ExpressionBuilder(); Expression subExp = subPc.processProperty(subBuilder, parameters); ReportQuery childQuery = formRelationReportQuery(attr, subBuilder); childQuery.retrievePrimaryKeys(); childQuery.setSelectionCriteria(subBuilder.equal(builder.get(getProp())).and(subExp)); if (finalExp == null) { finalExp = builder.exists(childQuery); } else { finalExp = finalExp.and(builder.exists(childQuery)); } } } return finalExp; }
protected Expression processPropertyNotLike( Attribute<?, ?> attr, Expression builder, List<Parameter> parameters) { ConditionQueryParameter p; // convenient expression, only used by simple case Expression exp = null; p = new ConditionQueryParameter(this, getQuery().getPrefix() + parameters.size()); parameters.add(p); if (attr.isCollection()) { if (isAllColllectionMode()) { ReportQuery subQuery = formReportQueryForDirectCollection(attr, builder); if (isIgnoreCase()) { subQuery.setSelectionCriteria( builder.anyOf(getProp()).likeIgnoreCase(builder.getParameter(p.getParamName()))); } else { subQuery.setSelectionCriteria( builder.anyOf(getProp()).like(builder.getParameter(p.getParamName()))); } exp = builder.notExists(subQuery); } else if (isNoneColllectionMode()) { ReportQuery subQuery = formReportQueryForDirectCollection(attr, builder); if (isIgnoreCase()) { subQuery.setSelectionCriteria( builder .anyOf(getProp()) .toUpperCase() .notLike(builder.getParameter(p.getParamName()))); } else { subQuery.setSelectionCriteria( builder.anyOf(getProp()).notLike(builder.getParameter(p.getParamName()))); } exp = builder.notExists(subQuery); } else { if (isIgnoreCase()) { exp = builder .anyOf(getProp()) .toUpperCase() .notLike(builder.getParameter(p.getParamName())); } else { exp = builder.anyOf(getProp()).notLike(builder.getParameter(p.getParamName())); } } } else { if (isIgnoreCase()) { exp = builder.get(getProp()).toUpperCase().notLike(builder.getParameter(p.getParamName())); } else { exp = builder.get(getProp()).notLike(builder.getParameter(p.getParamName())); } } return exp; }
public void testEmployeeJoinProjectsJoinTeamLeaderJoinAddressWhereManagerIsNull() { ReadAllQuery query = new ReadAllQuery(); query.setReferenceClass(Employee.class); query.setSelectionCriteria(query.getExpressionBuilder().get("manager").isNull()); ReadAllQuery controlQuery = (ReadAllQuery) query.clone(); Expression projects = query.getExpressionBuilder().anyOf("projects"); query.addJoinedAttribute(projects); Expression teamLeader = projects.get("teamLeader"); query.addJoinedAttribute(teamLeader); Expression teamLeaderAddress = teamLeader.get("address"); query.addJoinedAttribute(teamLeaderAddress); String errorMsg = executeQueriesAndCompareResults(controlQuery, query); if (errorMsg.length() > 0) { fail(errorMsg); } }
/** * INTERNAL: Rebuild myself against the base, with the values of parameters supplied by the * context expression. This is used for transforming a standalone expression (e.g. the join * criteria of a mapping) into part of some larger expression. You normally would not call this * directly, instead calling twist See the comment there for more details" */ public Expression twistedForBaseAndContext(Expression newBase, Expression context) { Expression twistedBase = getBaseExpression().twistedForBaseAndContext(newBase, context); QueryKeyExpression result = (QueryKeyExpression) twistedBase.get(getName()); if (shouldUseOuterJoin) { result.doUseOuterJoin(); } if (shouldQueryToManyRelationship) { result.doQueryToManyRelationship(); } return result; }
public void setup() { Employee emp = (Employee) getSomeEmployees().firstElement(); PhoneNumber phone = (PhoneNumber) emp.getPhoneNumbers().firstElement(); String areaCode = phone.getAreaCode(); String firstName = emp.getFirstName(); setReferenceClass(Employee.class); ExpressionBuilder employeeBuilder = new ExpressionBuilder(); Expression phones = employeeBuilder.anyOf("phoneNumbers"); Expression whereClause = phones .get("owner") .get("firstName") .equal(firstName) .and(phones.get("areaCode").equal(areaCode)); ReportQuery rq = new ReportQuery(); rq.setSelectionCriteria(whereClause); rq.addAttribute("number", phones.get("number")); rq.setReferenceClass(Employee.class); setOriginalOject(getAttributeFromAll("number", (Vector) getSession().executeQuery(rq))); getSession().getIdentityMapAccessor().initializeAllIdentityMaps(); String ejbqlString; ejbqlString = "SELECT phone.number FROM Employee employee, IN(employee.phoneNumbers) phone " + "WHERE phone.owner.firstName = \"" + firstName + "\" AND phone.areaCode = \"" + areaCode + "\""; useReportQuery(); setEjbqlString(ejbqlString); super.setup(); }
protected Expression processPropertyBetween( Attribute<?, ?> attr, Expression builder, List<Parameter> parameters) { ConditionQueryParameter p; ConditionQueryParameter p1; // convenient expression, only used by simple case Expression exp = null; p = new ConditionQueryParameter(this, getQuery().getPrefix() + parameters.size()); parameters.add(p); p1 = new ConditionQueryParameter(this, getQuery().getPrefix() + parameters.size()); p1.setIndex(2); parameters.add(p1); if (attr.isCollection()) { if (isAllColllectionMode()) { ReportQuery subQuery = formReportQueryForDirectCollection(attr, builder); subQuery.setSelectionCriteria( builder .anyOf(getProp()) .notBetween( builder.getParameter(p.getParamName()), builder.getParameter(p1.getParamName()))); exp = builder.notExists(subQuery); } else if (isNoneColllectionMode()) { ReportQuery subQuery = formReportQueryForDirectCollection(attr, builder); subQuery.setSelectionCriteria( builder .anyOf(getProp()) .between( builder.getParameter(p.getParamName()), builder.getParameter(p1.getParamName()))); exp = builder.notExists(subQuery); } else { exp = builder .anyOf(getProp()) .between( builder.getParameter(p.getParamName()), builder.getParameter(p1.getParamName())); } } else { exp = builder .get(getProp()) .between( builder.getParameter(p.getParamName()), builder.getParameter(p1.getParamName())); } return exp; }
public void testEmployeeJoinManagerAddressOuterJoinManagerAddress() { ReadAllQuery query = new ReadAllQuery(); query.setReferenceClass(Employee.class); query.setSelectionCriteria( query .getExpressionBuilder() .get("lastName") .equal("Way") .or(query.getExpressionBuilder().get("lastName").equal("Jones"))); ReadAllQuery controlQuery = (ReadAllQuery) query.clone(); Expression manager = query.getExpressionBuilder().get("manager"); query.addJoinedAttribute(manager); query.addJoinedAttribute(manager.get("address")); Expression managersManager = manager.getAllowingNull("manager"); query.addJoinedAttribute(managersManager); query.addJoinedAttribute(managersManager.get("address")); String errorMsg = executeQueriesAndCompareResults(controlQuery, query); if (errorMsg.length() > 0) { fail(errorMsg); } }
/** * INTERNAL: This expression is built on a different base than the one we want. Rebuild it and * return the root of the new tree */ public Expression rebuildOn(Expression newBase) { Expression newLocalBase = getBaseExpression().rebuildOn(newBase); QueryKeyExpression result = null; // For bug 3096634 rebuild outer joins correctly from the start. if (shouldUseOuterJoin) { result = (QueryKeyExpression) newLocalBase.getAllowingNull(getName()); } else { result = (QueryKeyExpression) newLocalBase.get(getName()); } if (shouldQueryToManyRelationship) { result.doQueryToManyRelationship(); } result.setSelectIfOrderedBy(selectIfOrderedBy()); return result; }
public void testProjectOuterJoinTeamMembersJoinAddress() { ReadAllQuery query = new ReadAllQuery(); query.setReferenceClass(Project.class); ReadAllQuery controlQuery = (ReadAllQuery) query.clone(); Expression teamMembers = query.getExpressionBuilder().anyOfAllowingNone("teamMembers"); query.addJoinedAttribute(teamMembers); Expression teamMembersAddress = teamMembers.get("address"); query.addJoinedAttribute(teamMembersAddress); String errorMsg = executeQueriesAndCompareResults(controlQuery, query); if (errorMsg.length() > 0) { fail(errorMsg); } }
public void testProblemReporterProjectJoinTeamMembersJoinAddress() { ReadAllQuery query = new ReadAllQuery(); query.setReferenceClass(Project.class); query.setSelectionCriteria(query.getExpressionBuilder().get("name").equal("Problem Reporter")); ReadAllQuery controlQuery = (ReadAllQuery) query.clone(); Expression teamMembers = query.getExpressionBuilder().anyOf("teamMembers"); query.addJoinedAttribute(teamMembers); Expression teamMembersAddress = teamMembers.get("address"); query.addJoinedAttribute(teamMembersAddress); String errorMsg = executeQueriesAndCompareResults(controlQuery, query); if (errorMsg.length() > 0) { fail(errorMsg); } }
public void testProjectJoinTeamLeaderJoinAddressWhereTeamLeaderNotNull() { ReadAllQuery query = new ReadAllQuery(); query.setReferenceClass(Project.class); Expression teamLeader = query.getExpressionBuilder().get("teamLeader"); query.setSelectionCriteria(teamLeader.notNull()); ReadAllQuery controlQuery = (ReadAllQuery) query.clone(); query.addJoinedAttribute(teamLeader); Expression teamLeaderAddress = teamLeader.get("address"); query.addJoinedAttribute(teamLeaderAddress); String errorMsg = executeQueriesAndCompareResults(controlQuery, query); if (errorMsg.length() > 0) { fail(errorMsg); } }
private Expression buildExpressionFrom(Expression expression) { String name = ""; if (getQueryable() != null) { name = getQueryable().getName(); } if (getQueryable() != null && !getQueryable().usesAnyOf()) { if (!this.allowsNull) { return expression.get(name); } return expression.getAllowingNull(name); } if (!this.allowsNull) { return expression.anyOf(name); } return expression.anyOfAllowingNone(name); }
protected Expression processPropertyNe( Attribute<?, ?> attr, Expression builder, List<Parameter> parameters) { ConditionQueryParameter p; // convenient expression, only used by simple case Expression exp = null; p = new ConditionQueryParameter(this, getQuery().getPrefix() + parameters.size()); parameters.add(p); boolean isString = JpaMetamodelHelper.isString(attr); if (attr.isCollection()) { if (isAllColllectionMode()) { ReportQuery subQuery = formReportQueryForDirectCollection(attr, builder); if (isString && isIgnoreCase()) { subQuery.setSelectionCriteria( builder.anyOf(getProp()).equalsIgnoreCase(builder.getParameter(p.getParamName()))); } else { subQuery.setSelectionCriteria( builder.anyOf(getProp()).equal(builder.getParameter(p.getParamName()))); } exp = builder.notExists(subQuery); } else if (isNoneColllectionMode()) { ReportQuery subQuery = formReportQueryForDirectCollection(attr, builder); if (isString && isIgnoreCase()) { subQuery.setSelectionCriteria( builder .anyOf(getProp()) .toUpperCase() .notEqual(builder.getParameter(p.getParamName()))); } else { subQuery.setSelectionCriteria( builder.anyOf(getProp()).notEqual(builder.getParameter(p.getParamName()))); } exp = builder.notExists(subQuery); } else { if (isString && isIgnoreCase()) { exp = builder .anyOf(getProp()) .toUpperCase() .notEqual(builder.getParameter(p.getParamName())); } else { exp = builder.anyOf(getProp()).notEqual(builder.getParameter(p.getParamName())); } } } else { if (JpaMetamodelHelper.isRelation(attr)) { if (JpaMetamodelHelper.isRelationOwner(attr)) { Expression exp1 = builder.get(getProp()).notEqual(builder.getParameter(p.getParamName())); // null is not considered as equal Expression exp2 = builder.get(getProp()).isNull(); exp = exp1.or(exp2); } else { exp = builder.get(getProp()).notEqual(builder.getParameter(p.getParamName())); } } else { if (isString && isIgnoreCase()) { exp = builder.get(getProp()).toUpperCase().notEqual(builder.getParameter(p.getParamName())); } else { exp = builder.get(getProp()).notEqual(builder.getParameter(p.getParamName())); } } } return exp; }
/** * @param type * @param builder * @param parameters * @return a fully parameterized query. A default value for this query should be set to query at a * late time. */ public Expression processProperty(Expression builder, List<Parameter> parameters) { Attribute<?, ?> attr = getAttribute(); Operator op = getOperator(); ConditionQueryParameter p; // convenient expression, only used by simple case Expression exp = builder.get(getProp()); switch (op) { // Operator for primtive type first: lt, le, gt, ge, eq, ne, between, // notbetween, like(String), notlike(String), checked, unchecked // oneof(in(...)), notoneof(notin(...)) case lt: return processPropertyLt(attr, builder, parameters); case le: return processPropertyLe(attr, builder, parameters); case eq: return processPropertyEq(attr, builder, parameters); case gt: return processPropertyGt(attr, builder, parameters); case ge: return processPropertyGe(attr, builder, parameters); case ne: return processPropertyNe(attr, builder, parameters); case between: return processPropertyBetween(attr, builder, parameters); case notbetween: return processPropertyNotBetween(attr, builder, parameters); case like: return processPropertyLike(attr, builder, parameters); case notlike: return processPropertyNotLike(attr, builder, parameters); case oneof: return processPropertyOneof(attr, builder, parameters); case notoneof: // for direct follection. return processPropertyNotOneof(attr, builder, parameters); case checked: exp = exp.equal(true); return exp; case unchecked: exp = exp.equal(false); return exp; /** *************** The above is for comparison of primitive value */ // null, notnull are not primitive attr, only property with single // value case notnull: if (attr.isCollection()) { return this.processPropertyNotEmpty(attr, builder, parameters); } else { exp = exp.notNull(); return exp; } case isnull: if (attr.isCollection()) { return this.processPropertyEmpty(attr, builder, parameters); } else { if (JpaMetamodelHelper.isRelation(attr) && !JpaMetamodelHelper.isRelationOwner(attr)) { ExpressionBuilder main = new ExpressionBuilder(); ReportQuery subQuery = formRelationReportQuery(attr, main); subQuery.setSelectionCriteria(main.equal(builder.get(getProp()))); subQuery.addAttribute("id"); exp = builder.notExists(subQuery); } else { exp = exp.isNull(); } return exp; } // -----------------size operation for collection: size, sizegt, // sizelt, empty, notempty case size: // do not work for simple collection. // need test case for simple collection p = new ConditionQueryParameter(this, getQuery().getPrefix() + parameters.size()); parameters.add(p); if (JpaMetamodelHelper.isRelation(attr)) { exp = builder.size(getProp()).equal(builder.getParameter(p.getParamName())); } else { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=396892 exp = builder .subQuery(this.formSizeReportQuery(attr, builder)) .equal(builder.getParameter(p.getParamName())); } return exp; case sizeGt: p = new ConditionQueryParameter(this, getQuery().getPrefix() + parameters.size()); parameters.add(p); if (JpaMetamodelHelper.isRelation(attr)) { exp = builder.size(getProp()).greaterThan(builder.getParameter(p.getParamName())); } else { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=396892 exp = builder .subQuery(this.formSizeReportQuery(attr, builder)) .greaterThan(builder.getParameter(p.getParamName())); } return exp; case sizeLt: p = new ConditionQueryParameter(this, getQuery().getPrefix() + parameters.size()); parameters.add(p); if (JpaMetamodelHelper.isRelation(attr)) { exp = builder.size(getProp()).lessThan(builder.getParameter(p.getParamName())); } else { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=396892 exp = builder .subQuery(this.formSizeReportQuery(attr, builder)) .lessThan(builder.getParameter(p.getParamName())); } return exp; case empty: return this.processPropertyEmpty(attr, builder, parameters); case notempty: return this.processPropertyNotEmpty(attr, builder, parameters); case tracedown: if (attr.isCollection()) { if (isAllColllectionMode()) { return this.processPropertyTracedownToManyAll(attr, builder, parameters); } else if (isNoneColllectionMode()) { return this.processPropertyTracedownToManyNone(attr, builder, parameters); } else { return this.processPropertyTracedownToManySomeOptimized(attr, builder, parameters); } } else { return this.processPropertyTracedownTooneOptimized(attr, builder, parameters); } default: break; } return null; }
public void test() { // clear cache getSession().getIdentityMapAccessor().initializeAllIdentityMaps(); // create batch read query, set its selectionCriteria ReadAllQuery query = new ReadAllQuery(Employee.class); setSelectionCriteria(query); // before adding batch read attributes clone the query to create control query ReadAllQuery controlQuery = (ReadAllQuery) query.clone(); // add batch read attributes Expression managedEmployees = query.getExpressionBuilder().get("managedEmployees"); Expression managedEmployeesPhoneNumbers = managedEmployees.get("phoneNumbers"); query.addBatchReadAttribute(managedEmployeesPhoneNumbers); // execute the query List employees = (List) getSession().executeQuery(query); if (employees.isEmpty()) { throw new TestProblemException("No Employees were read"); } // need to instantiate only a single Phone on a single managed Employee to trigger sql that // reads data from the db for all. // still need to trigger all the indirections - but (except the first one) they are not // accessing the db // (the data is already cached in the value holders). printDebug("Trigger batch reading results"); boolean isConnected = true; for (int i = 0; i < employees.size(); i++) { Employee manager = (Employee) employees.get(i); if (!manager.getManagedEmployees().isEmpty()) { printDebug("Manager = " + manager); for (int j = 0; j < manager.getManagedEmployees().size(); j++) { Employee emp = (Employee) manager.getManagedEmployees().get(j); printDebug(" " + emp); for (int k = 0; k < emp.getPhoneNumbers().size(); k++) { if (isConnected) { // need to instantiate only a single Phone on a single managed Employee to trigger // sql that reads data from the db for all. // to ensure that no other sql is issued close connection. ((AbstractSession) getSession()).getAccessor().closeConnection(); isConnected = false; } PhoneNumber phone = (PhoneNumber) emp.getPhoneNumbers().get(k); printDebug(" " + phone); } } } else { printDebug(manager.toString()); } } if (!isConnected) { // reconnect connection ((AbstractSession) getSession()) .getAccessor() .reestablishConnection((AbstractSession) getSession()); } printDebug(""); // obtain control results // clear cache getSession().getIdentityMapAccessor().initializeAllIdentityMaps(); // execute control query List controlEmployees = (List) getSession().executeQuery(controlQuery); // instantiate all value holders that the batch query expected to instantiate printDebug("Trigger control results"); for (int i = 0; i < controlEmployees.size(); i++) { Employee manager = (Employee) controlEmployees.get(i); if (!manager.getManagedEmployees().isEmpty()) { printDebug("Manager = " + manager); for (int j = 0; j < manager.getManagedEmployees().size(); j++) { Employee emp = (Employee) manager.getManagedEmployees().get(j); printDebug(" " + emp); for (int k = 0; k < emp.getPhoneNumbers().size(); k++) { PhoneNumber phone = (PhoneNumber) emp.getPhoneNumbers().get(k); printDebug(" " + phone); } } } else { printDebug(manager.toString()); } } // compare results String errorMsg = JoinedAttributeTestHelper.compareCollections( employees, controlEmployees, getSession().getClassDescriptor(Employee.class), ((AbstractSession) getSession())); if (errorMsg.length() > 0) { throw new TestErrorException(errorMsg); } }