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

Something (JDK 7?) caused a type-mapping regression in DDR generation #39

Closed
jcflack opened this issue May 31, 2015 · 3 comments
Closed

Comments

@jcflack
Copy link
Contributor

jcflack commented May 31, 2015

This is a story that has to be pieced together out of commits and pulls, because there wasn't an issue filed (until now) to report the regression.

In August 2014, sptrakesh was working on Java 7 and clang support, and made a commit f49cf50 that commented pljava-examples out of the build in pom.xml, apparently because at least one example had stopped working.

In October 2014, fbroda made a commit bd6f79c that re-enabled pljava-examples and added an explicit complexType annotation to

@Function
Iterator<String> getProperties()

(and then a later commit 7b5f28d that corrected the complexType).

Apparently the regression was that Iterator<String> was no longer automatically recognized as RETURNS SETOF VARCHAR, as had been tested and known to work in Java 6.

The real problem is devilishly subtle and I'm not sure what to do about it yet. The annotation framework in javac calls the annotation processor in more than one "round" - we currently collect information about all the SQL-related annotations in the non-final round(s), then generate the DDR file in the final round.

What has started happening in Java 7 is that getElementUtils().getTypeElement(x) will always return the same TypeElement instance for a given name x within one round, but will now return a different TypeElement instance for the same type name x from one round to the next. Ultimately DDRProcessorImpl.TypeMapper.getSQLType ends up calling isAssignable(tm,ktm) to compare tm (java.lang.String from the Iterator type seen in earlier round) and ktm (java.lang.String mapped to VARCHAR, in current round), and isAssignable returns false because the two TypeElement instances representing java.lang.String are not the same!

I don't know if this is a Java 7 bug. Seems as if it might be ... at the very least, it is highly counterintuitive and seems likely to break stuff. I haven't stumbled easily on any other reports of it though.

I'm still looking at ways to get it working again. I'll add more when I learn more.

Meanwhile, there's kind of a moral in this issue. As pointed out in #11, at the moment the examples are about the nearest thing we have to regression testing. If at some point an example stops working, we need to report an issue to find out why it stopped working and solve the regression - not commit a change to the example that hides the problem (like the explicit annotation in this case). Hiding the problem in the example isn't going to stop anybody's real code from breaking in the same way. If it had been reported as an issue back in August 2014 there'd have been an extra year to get to the bottom of it.

jcflack referenced this issue May 31, 2015
What the TypeMapper was doing was correct for a function return value,
matching the return value to the narrowest mapped type that the actual
return value could be assigned to.

It was not correct for a function parameter, which needs to be matched
to the widest mapped type that could be assigned to the parameter.

Jens, if you ever read this, forgive me. At least I caught it quickly.
@jcflack
Copy link
Contributor Author

jcflack commented May 31, 2015

The line where isAssignable(tm, ktm) actually returns false for tm and ktm that both represent java.lang.String is here.

@jcflack
Copy link
Contributor Author

jcflack commented Jun 1, 2015

I did find some related reports in the Java bug database:

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8038455
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7026845
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6191665
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=2206926

8038455 is written as an 'enhancement' (due for Java 9) and I didn't see anything clearly reflecting that they knew stuff had broken in 7 that worked in 6. (I also found a machine that still had 6 on it, and confirmed it's still not broken in 6.) So I made another report they will (I hope) at least check, to make sure that this issue is the same as what they're enhancing for 9....

I can't give that bug number yet ... their system never has given a number at submission time, it has to go through one review queue before they even decide it gets a number.

jcflack added a commit to jcflack/pljava that referenced this issue Jul 15, 2015
The annotation processor in javac runs in multiple 'rounds', as long as
generated source files keep appearing, and one final round after they
don't. This code used to save some mapping of Class objects to the
javax.lang.model objects (TypeElement/TypeMirror) until the final round,
which worked in Java 6, but as of 7 one gets back different model objects
in different rounds, for the same types, and they don't match, so type
mapping breaks.

This workaround moves all those lookups to before or during round 1, when
a consistent set of model objects can be looked up. So, it will work as
long as all the source files that might contain pljava annotations will be
found in round 1. That should always be the case unless someone is using a
very fancy build with _other_ annotation processors generating new source
files with pljava annotations that have to be processed in additional
rounds. For now, that won't work, because their types won't seem to match
what was computed in round 1. So don't do that.

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8038455 might refer
to this problem, and promises a fix in Java 9, for what it's worth.
jcflack added a commit to jcflack/pljava that referenced this issue Jul 15, 2015
Issue tada#39 stopped the DDRProcessor from finding the correct return type
for this example function, so in bd6f79c and 7b5f28d an explicit type
annotation was added. DDRProcessor finds the right type again, so
reverting the explicit annotation (which only served to mask a problem).
thallgren added a commit that referenced this issue Jul 15, 2015
Workaround #39 breakage seen with Java 7
jcflack added a commit to jcflack/pljava that referenced this issue Sep 20, 2015
I want to close issue tada#39 (pull tada#42 provided a workaround), but the
workaround has a limitation and in case anybody runs into it, it should
be mentioned in at least one place that doesn't have to be looked up
in closed issues or in the code.
@jcflack
Copy link
Contributor Author

jcflack commented Sep 20, 2015

The workaround added in #42 is probably going to be the last word on this until at least Java 9. Closing.

@jcflack jcflack closed this as completed Sep 20, 2015
jcflack added a commit that referenced this issue Feb 9, 2016
Certain later-detected annotation errors were being output with no
source location info, probably because of that javac (new with 7?
see also #39) habit of throwing away symbol tables between rounds.

Merge branch 'workaround/REL1_5_STABLE-BASE/sourcelocs' into REL1_5_STABLE.
jcflack added a commit that referenced this issue Feb 9, 2016
Certain later-detected annotation errors were being output with no
source location info, probably because of that javac (new with 7?
see also #39) habit of throwing away symbol tables between rounds.

Merge branch 'workaround/REL1_5_STABLE-BASE/sourcelocs'
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

No branches or pull requests

1 participant