Value.isNull slightly non-intuitive in stream mode
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Akiban Persistit |
Fix Released
|
Low
|
Peter Beaman |
Bug Description
In stream mode, Value.isNull() never advances to the next object. When isNull() == false, this seems perfectly reasonable; it lets you do a pattern such as:
if (!value.isNull) {
int intValue = value.getInt();
}
But when isNull() returns true, this behavior can be a bit counter-intuitive; we probably want to skip to the next item. This is a tiny bit awkward, but worse, it's not obvious we need it. Consider this code:
StringBuilder sb = new StringBuilder();
for(int i = 0; i < segments; ++i) {
if (!value.isNull()) {
int intVal = persistitValue.
}
else {
}
}
It looks reasonable, but it's broken; after we hit the first null value, we'll not advance to any more values, and every subsequent segment will look like null. The solution is:
...
else {
}
I'm not sure what to do about this. One solution would be to keep it as-is, but note this use case in the javadoc. Another would be to add an argument to isNull, a boolean specifying whether we should skip to the next segment if this one is null. I would prefer that one, as it forces users to learn about this problem and declare how they want to solve it.
Related branches
- Akiban Technologies: Pending requested
-
Diff: 360 lines (+57/-36)10 files modifiedsrc/main/java/com/persistit/Value.java (+24/-3)
src/test/java/com/persistit/stress/unit/Stress10.java (+1/-1)
src/test/java/com/persistit/stress/unit/Stress11.java (+1/-1)
src/test/java/com/persistit/stress/unit/Stress2.java (+1/-1)
src/test/java/com/persistit/stress/unit/Stress2txn.java (+1/-1)
src/test/java/com/persistit/stress/unit/Stress3.java (+5/-5)
src/test/java/com/persistit/stress/unit/Stress3txn.java (+5/-5)
src/test/java/com/persistit/stress/unit/Stress9.java (+1/-1)
src/test/java/com/persistit/stress/unit/StressBase.java (+1/-1)
src/test/java/com/persistit/unit/ValueTest2.java (+17/-17)
- Akiban Build User: Needs Fixing
- Nathan Williams: Approve
-
Diff: 838 lines (+226/-528)4 files modifiedsrc/main/java/com/persistit/Key.java (+22/-0)
src/main/java/com/persistit/Value.java (+74/-3)
src/test/java/com/persistit/unit/KeyTest1.java (+25/-0)
src/test/java/com/persistit/unit/ValueTest4.java (+105/-525)
Changed in akiban-persistit: | |
status: | Fix Committed → Fix Released |
I think I would prefer isNull() not to advance the cursor. I know it's a little inconvenient to add a call to skip() but I think that's the path of least surprise. It would be especially surprising, I believe, for the method to conditionally advance the cursor. I would be more than happy to add documentation on this to help hapless hackers avoid the anomaly.
I agree that in your code pattern the result of not knowing to call skip (or getNull()) causes a big surprise too, but if the behavior is properly documented I think others won't fall into the same trap.
Note that this is a problem caused by use of primitives in Java. The get() method that returns an object cleanly returns either the object or null and advances the cursor. If there were only objects, then getInt() could return an Integer or a null. Perhaps that's the ultimate solution.