BigDecimal and BigInteger can be serialized#85
BigDecimal and BigInteger can be serialized#85ghajba wants to merge 7 commits intofirebase:masterfrom
Conversation
|
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed, please reply here (e.g.
|
|
I signed it!
actually with my primary email address: hajbag@gmail.com
2017-10-08 9:00 GMT+02:00 googlebot <notifications@github.com>:
… Thanks for your pull request. It looks like this may be your first
contribution to a Google open source project. Before we can look at your
pull request, you'll need to sign a Contributor License Agreement (CLA).
📝 *Please visit https://cla.developers.google.com/
<https://cla.developers.google.com/> to sign.*
Once you've signed, please reply here (e.g. I signed it!) and we'll
verify. Thanks.
------------------------------
- If you've already signed a CLA, it's possible we don't have your
GitHub username or you're using a different email address. Check your
existing CLA data <https://cla.developers.google.com/clas> and verify
that your email is set on your git commits
<https://help.github.com/articles/setting-your-email-in-git/>.
- If your company signed a CLA, they designated a Point of Contact who
decides which employees are authorized to participate. You may need to
contact the Point of Contact for your company and ask to be added to the
group of authorized contributors. If you don't know who your Point of
Contact is, direct the project maintainer to go/cla#troubleshoot.
- In order to pass this check, please resolve this problem and have
the pull request author add another comment and the bot will run again.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#85 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ACoigEzRoOWfPTt5DEZmiZw65W251ibeks5sqHMhgaJpZM4PxnZJ>
.
|
|
CLAs look good, thanks! |
hiranya911
left a comment
There was a problem hiding this comment.
Thank you for the patch. Can you address a couple of questions, and also provide some test cases? See MapperTest, MutableDataTest and DataSnapshotTest.
| } else if (value instanceof Boolean) { | ||
| return new BooleanNode((Boolean) value, priority); | ||
| } else if (value instanceof BigDecimal) { | ||
| return new DoubleNode(((BigDecimal) value).doubleValue(), priority); |
There was a problem hiding this comment.
This is a lossy conversion. What happens when the BigDecimal is too large to fit in a double?
There was a problem hiding this comment.
I think BigDecimals should be serialized to String. The entire point of using BigDecimals is to avoid the rounding errors inherent in floating point representation.
| } else if (value instanceof BigDecimal) { | ||
| return new DoubleNode(((BigDecimal) value).doubleValue(), priority); | ||
| } else if (value instanceof BigInteger) { | ||
| return new LongNode(((BigInteger)value).longValue(), priority); |
There was a problem hiding this comment.
Same question applies here. What happens when the BigInteger is too large to fit in a long?
There was a problem hiding this comment.
Ditto for BigInteger -- we should serialize these to String to maintain the full representation.
|
I know that these are lossy conversions. If the values don't fit, they'll be converted to infinity (positive or negative) for both types. But I've already asked in #75 how the conversion should happen. After we clear this, I will adjust the code and write the tests too. |
|
I think you will have to implement a whole new Node type to support these types. In there you can just hold on to the string representation of the numbers. |
|
Just to let you know: I am working on the changes but at a slow pace. I hope I can push my changes this week. |
added new node types I have still no idea how the tests should work.
hiranya911
left a comment
There was a problem hiding this comment.
Thanks @ghajba
Implementation looks pretty close to what I had in mind. Just some minor comments. Also please add the test cases.
|
|
||
| @Override | ||
| protected LeafType getLeafType() { | ||
| return LeafType.String; |
There was a problem hiding this comment.
I believe this should be LeafType.Number
There was a problem hiding this comment.
And as a heads up, you will have to revise how leaf nodes are compared in the parent LeafNode.compareTo() method. You will see that longs and doubles have been special cased there. Perhaps you can implement a new comparison method for all number types, which converts values to BigDecimal and then does the comparison.
|
|
||
| @Override | ||
| public String getHashRepresentation(HashVersion version) { | ||
| return null; |
There was a problem hiding this comment.
I think this should do something similar to what the StringNode does.
| serverCache = currentSyncPoint.getCompleteServerCache(relativePath); | ||
| } | ||
| } while (!pathToFollow.isEmpty() && serverCache == null); | ||
| } |
There was a problem hiding this comment.
Please revert to keep the change footprint small as possible.
| @@ -0,0 +1,60 @@ | |||
| package com.google.firebase.database.snapshot; | |||
| @@ -0,0 +1,60 @@ | |||
| package com.google.firebase.database.snapshot; | |||
There was a problem hiding this comment.
Lot of the comments made on BigDecimalNode are also applicable here. Please revise as appropriate.
There was a problem hiding this comment.
I'd add the tests, but I don't see the idea behind how you test your code. The structure is not clear to find an easy entry-point.
There was a problem hiding this comment.
NodeTest might be a good place to start. Also check MapperTest. See if you can serialize/deserialize some made up big integers and big decimals via the new code.
|
|
||
| @Override | ||
| public Object getValue() { | ||
| return this.value; |
There was a problem hiding this comment.
Should this return a BigDecimal? You can reconstruct the original value from the string.
|
Thanks for the feedback. A big part of the codebase and what is expected is really unclear because of the missing JavaDoc. |
added some tests and code changes
|
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. |
hiranya911
left a comment
There was a problem hiding this comment.
Thanks @ghajba for the PR. This is starting to look pretty good. I've made some more comments (mostly syntactic changes).
Btw would you be able to provide an integration test too? I think we can add something to DataTestIT to cover the new functionality. The test case should write some big numbers to the database, and try to retrieve them back.
|
|
||
| public class BigDecimalNode extends LeafNode<BigDecimalNode> { | ||
|
|
||
| private final String value; |
There was a problem hiding this comment.
I'm starting to wonder whether we get any benefit by keeping this as a string. I think we can just store it as a BigDecimal here.
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return this.value.hashCode() + this.priority.hashCode(); |
There was a problem hiding this comment.
This is not a very good hash function. Please use MoreObjects.hashCode() here. See https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained#hashcode
|
|
||
| public class BigIntegerNode extends LeafNode<BigIntegerNode> { | ||
|
|
||
| private final String value; |
There was a problem hiding this comment.
Use BigInteger directly.
| public void bigIntegerDeserialize() { | ||
| BigIntegerBean beanBigInteger = deserialize("{'value':'1'}", BigIntegerBean.class); | ||
| assertEquals(0,BigInteger.ONE.compareTo(beanBigInteger.getValue())); | ||
|
|
| BigIntegerBean beanBigInteger = deserialize("{'value':'1'}", BigIntegerBean.class); | ||
| assertEquals(0,BigInteger.ONE.compareTo(beanBigInteger.getValue())); | ||
|
|
||
| BigIntegerBean beanBigIntegerBig = |
There was a problem hiding this comment.
Can you use a value that is guaranteed to be larger then what can fit in a long? Something like:
BigInteger value = new BigInteger(String.valueOf(Long.MAX_VALUE)).add(BigInteger.ONE);
| @Test | ||
| public void bigIntegerDeserialize() { | ||
| BigIntegerBean beanBigInteger = deserialize("{'value':'1'}", BigIntegerBean.class); | ||
| assertEquals(0,BigInteger.ONE.compareTo(beanBigInteger.getValue())); |
There was a problem hiding this comment.
Can we just do:
assertEquals(BigInteger.ONE, beanBigInteger.getValue());
| BigDecimalBean.class); | ||
| assertEquals(0,BigDecimal.ONE.compareTo(beanBigDecimal.getValue())); | ||
|
|
||
| BigDecimalBean beanBigDecimalBig = |
There was a problem hiding this comment.
Same comments made on the test case above applies here.
|
Instructions for integration tests can be found at: https://github.com/firebase/firebase-admin-java/blob/master/CONTRIBUTING.md#integration-testing |
|
Want to give a note that I have not abandoned my PR, but had some busy days. I am back now and will add the required changes/tests and will take a look at the comparison method too @hiranya911 mentioned previously. |
|
CLAs look good, thanks! |
|
Well, the integration testing description seems not working. I updated my sources to the latest version of firebase and the FirebaseCredentialsTest, using a new authentication which is not described in the mentioned documentation, fail. |
|
The instructions look correct to me. I use them fairly regularly in multiple dev environments, and haven't had any issues. What is the code/test you're trying to run, and what is the error you get? FWIW, |
|
These are the errors I get when running And unit tests are executed with |
|
The test case does set the Looks like this doesn't work in your environment. What is your OS and JVM build? We test this on Linux and Mac, where it works fine. |
|
:) |
|
@ghajba Feel free to ignore those 2 failures. It's not related to your changes anyway. I'll try to come up with a way to skip those tests on Windows. |
|
Hi @ghajba and @hiranya911, Sorry for jumping late into this, but I think BigDecimal should serialize to String. The number 1 reason for using BigDecimals (such as in code that deals with money) is for it's exact representation of the fraction, rather than for the large values that it holds. Serializing it to double throws this out the window. |
|
Over to @schmidt-sebastian who's been looking at #75. Based on the comment there, I assume we are not going to implement these changes? |
|
Sorry for being slow to respond on this PR and thank you for your awesome contribution! |
|
Closing this PR for now. If we get significant feedback from a number of customers, we can revisit this, in which case this PR can probably just be merged as is. |
This is my solution to #75.
Because I didn't get any response and I need this change, I've solved it like this. But as mentioned in the related issue, I am open to suggestions.
And a question: when will be changes released that we can use the latest version instead of a snapshot?