Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQL generation fix for EOKeyValueQualifiers when key is key path with derived attribute #828

Closed
wants to merge 12 commits into from

Conversation

rparada
Copy link
Contributor

@rparada rparada commented Mar 17, 2017

Overview

This bug fix can be disabled with a property and everything works just like before. The fix will be enabled by default and the property to disable it is named er.extensions.KeyValueQualifierSQLGenerationSupport.handlesKeyPathWithDerivedAttribute.

The fix adds SQL generation support for EOKeyValueQualifiers in an edge case where the key is a key path (with two or more keys) and the last key references a derived attribute.

Example #1:

The the key in the key-value qualifier is customer.fullNameReversed and the last key fullNameReversed is defined as: lastName || ', ' || firstName.

Example #2:

A more complex example I tested involves a key-value qualifier with the key claim.patientAge where patientAge is a derived attribute that is defined as TRUNC(MONTHS_BETWEEN(dateOfService,patient.birthDate)/12,0). My object model has a Claim entity, a LineItem entity and a Patient entity.

My test:

This test uses both

EOEditingContext ec = ERXEC.newEditingContext();
EOQualifier q = Claim.USER_GROUP_ID.is(4)
		.and(Claim.REFERENCE1.is("349069"))
		.and(Claim.PATIENT_AGE.greaterThan(30))
		.and(Claim.PATIENT.dot(Patient.FULL_NAME_REVERSED.likeInsensitive("wilson*")));
		
NSArray<Claim> claims = Claim.fetchClaims(ec, q, null);
q = LineItem.USER_GROUP_ID.is(4).and(LineItem.CLAIM.prefix(q));
NSArray<LineItem> items = LineItem.fetchLineItems(ec, q, null);
System.out.println(claims);
System.out.println(items);
if (claims.count() == 1 && items.count() == 5) {
	System.out.println("Success");
}

Without the fix, EOF throws an exception. With the fix the SQL is generated perfectly as follows:

Mar 16 23:41:46 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  - KeyValueQualifierSQLGenerationSupport handled edge case for key-value qualifier with key path referencing a derived attribute: Patient.fullNameReversed
Mar 16 23:41:46 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  -    Key value qualifier: (patient.fullNameReversed caseinsensitivelike 'wilson*')
Mar 16 23:41:46 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  -    Key path: patient.fullNameReversed
Mar 16 23:41:48 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  -    Attribute fullNameReversed is defined as: lastName || ', ' || firstName
Mar 16 23:41:48 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  -    SQL generated: UPPER(T1.LAST_NAME || ', ' || T1.FIRST_NAME) LIKE UPPER(?) ESCAPE '\'
Mar 16 23:41:48 KeyValueQualifierTest[49536] DEBUG NSLog  -  === Begin Internal Transaction
Mar 16 23:41:48 KeyValueQualifierTest[49536] DEBUG NSLog  -  evaluateExpression: <com.webobjects.jdbcadaptor.EROracleExpression: "SELECT t0.CLAIM_ID, t0.DATE_OF_SERVICE, TRUNC(MONTHS_BETWEEN(t0.DATE_OF_SERVICE, T1.BIRTH_DATE)/12,0), t0.PATIENT_ID, t0.REFERENCE1, t0.USER_GROUP_ID FROM CLAIM t0, PATIENT T1 WHERE t0.PATIENT_ID = T1.PATIENT_ID AND (t0.USER_GROUP_ID = ? AND t0.REFERENCE1 = ? AND TRUNC(MONTHS_BETWEEN(t0.DATE_OF_SERVICE, T1.BIRTH_DATE)/12,0) > ? AND UPPER(T1.LAST_NAME || ', ' || T1.FIRST_NAME) LIKE UPPER(?) ESCAPE '\')" withBindings: 1:4(userGroupID), 2:"349069"(reference1), 3:30(patientAge), 4:"wilson%"(fullNameReversed)>
Mar 16 23:41:49 KeyValueQualifierTest[49536] DEBUG NSLog  - 1 row(s) processed
Mar 16 23:41:49 KeyValueQualifierTest[49536] DEBUG NSLog  -  === Commit Internal Transaction
Mar 16 23:41:58 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  - KeyValueQualifierSQLGenerationSupport handled edge case for key-value qualifier with key path referencing a derived attribute: Claim.patientAge
Mar 16 23:41:58 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  -    Key value qualifier: (claim.patientAge > 30)
Mar 16 23:41:58 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  -    Key path: claim.patientAge
Mar 16 23:42:04 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  -    Attribute patientAge is defined as: TRUNC(MONTHS_BETWEEN(dateOfService, patient.birthDate)/12,0)
Mar 16 23:42:04 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  -    SQL generated: TRUNC(MONTHS_BETWEEN(T1.DATE_OF_SERVICE, T2.BIRTH_DATE)/12,0) > ?
Mar 16 23:42:04 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  - KeyValueQualifierSQLGenerationSupport handled edge case for key-value qualifier with key path referencing a derived attribute: Patient.fullNameReversed
Mar 16 23:42:04 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  -    Key value qualifier: (claim.patient.fullNameReversed caseinsensitivelike 'wilson*')
Mar 16 23:42:04 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  -    Key path: claim.patient.fullNameReversed
Mar 16 23:42:14 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  -    Attribute fullNameReversed is defined as: lastName || ', ' || firstName
Mar 16 23:42:14 KeyValueQualifierTest[49536] DEBUG er.extensions.ERXExtensions  -    SQL generated: UPPER(T2.LAST_NAME || ', ' || T2.FIRST_NAME) LIKE UPPER(?) ESCAPE '\'
Mar 16 23:42:14 KeyValueQualifierTest[49536] DEBUG NSLog  -  === Begin Internal Transaction
Mar 16 23:42:14 KeyValueQualifierTest[49536] DEBUG NSLog  -  evaluateExpression: <com.webobjects.jdbcadaptor.EROracleExpression: "SELECT t0.CLAIM_ID, t0.CPT_CODE, t0.LINE_ITEM_ID, t0.USER_GROUP_ID FROM LINE_ITEM t0, PATIENT T2, CLAIM T1 WHERE T1.PATIENT_ID = T2.PATIENT_ID AND t0.CLAIM_ID = T1.CLAIM_ID AND (t0.USER_GROUP_ID = ? AND (T1.USER_GROUP_ID = ? AND T1.REFERENCE1 = ? AND TRUNC(MONTHS_BETWEEN(T1.DATE_OF_SERVICE, T2.BIRTH_DATE)/12,0) > ? AND UPPER(T2.LAST_NAME || ', ' || T2.FIRST_NAME) LIKE UPPER(?) ESCAPE '\'))" withBindings: 1:4(userGroupID), 2:4(userGroupID), 3:"349069"(reference1), 4:30(patientAge), 5:"wilson%"(fullNameReversed)>
Mar 16 23:42:14 KeyValueQualifierTest[49536] DEBUG NSLog  - 5 row(s) processed
Mar 16 23:42:14 KeyValueQualifierTest[49536] DEBUG NSLog  -  === Commit Internal Transaction
(<your.app.model.Claim pk:"111454491">)
(<your.app.model.LineItem pk:"180693217">, <your.app.model.LineItem pk:"180693218">, <your.app.model.LineItem pk:"180693216">, <your.app.model.LineItem pk:"180693219">, <your.app.model.LineItem pk:"180693215">)
Success

Ricardo J. Parada and others added 10 commits April 6, 2012 14:15
ERXEC.DefaultFactory's _createEditingContext() uses the er.extensions.ERXEC.editingContextClassName property to determine the name of the class to be instantiated when creating an editing context.  It defaults to er.extensions.eof.ERXEC.
where the key is a key path (with two or more keys) and the last key
is a derived attribute.  For example, "customer.fullName" where the
last key fullName is defined as: 'firstName || ' ' || lastName.
Copy link
Contributor Author

@rparada rparada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please ignore the changes to the flying saucer .jar files. I had a conflict when I merged wonder master into my clone and this is just an artifact of that. The fix for this pull request is on ERExtensions.java only.

Ricardo Parada added 2 commits March 19, 2017 00:40
…E … GROUP BY … HAVING … ORDER BY …” using EOF/Wonder constructs (EOQualifiers, key paths, ERXKeys, EOAttributes, EOSortOrderings, etc.)
@rparada
Copy link
Contributor Author

rparada commented Mar 19, 2017

I learned how to use feature branches to create pull requests that contain only the change that needs to be applied to Wonder. I have created a separate pull request for this that excludes the stuff that is needed and includes only the change to ERXExtensions.java which is the only thing needed.

@darkv darkv closed this Mar 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants