yahoo / squidb

SquiDB is a SQLite database library for Android and iOS
https://github.com/yahoo/squidb/wiki
Apache License 2.0
1.31k stars 132 forks source link

Primitives default value #193

Closed aminelaadhari closed 8 years ago

aminelaadhari commented 8 years ago

Actually primitive members don't have any default value and cause a NullPointerException when you try to read them. I think they should have the default values defined by java by default: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

jdkoren commented 8 years ago

I think we did this intentionally because we did not want to insert those default values into SQLite (SQLite can have null values in any column, regardless of type). Any insert would write those values to the database, so if you want to have those default values in Java, we want you to commit to holding them in the database as well.

aminelaadhari commented 8 years ago

I think this is misleading because in java when you define something like this in the Spec: boolean isDeleted; by default it is false and not null.

in generates this: public Boolean isDeleted() { return get(IS_DELETED); }

and you get a null value. So something is not coherent between the spec and the generated code.

sbosley commented 8 years ago

Indeed, all column values in SquiDB (with the exception of the row id) are represented as objects (e.g. java.lang.Long instead of primitive long), not primitives, so they have a default value of null and/or can be assigned a null value. As @jdkoren suggests, this behavior is meant to mimic SQLite, where the default value of a column that does not otherwise specify a default is null.

To specify a default value for any column, you can annotate the field with e.g. @ColumnSpec(defaultValue="0L"). However, it is always still possible to set any value to null at runtime. To perform a null check before reading the value, you can do this:

if (model.containsNonNullValue(MyModel.IS_DELETED)) {
   ...
}

The spec is just meant to be a shorthand for specifying a table schema -- it's not a "real" Java object and shouldn't really be thought of as one. In fact, the fields in spec itself aren't even used at runtime -- they're only there for the code generator to parse. It's a core architectural detail of SquiDB that the values stored in model objects are objects, not primitives, and this is unlikely to change.

Maybe someday we'll add additional annotations and validation for things like NOT NULL constraints that could make use of primitives, but we can't commit to any specific timeline for such a change.

aminelaadhari commented 8 years ago

Ok got it. Thank you both.

aminelaadhari commented 8 years ago

I don't want to add this checks everywhere: if (model.containsNonNullValue(MyModel.IS_DELETED)) { ... }

I would like to use something more generic like Optional or a plugin which generates hasIsDeleted method.

what is the best option here ? any thoughts? Thanks

sbosley commented 8 years ago

So many options! You can pick your favorite:

That last option is kind of hard to describe, so if it sounds good to you but you need some more guidance, let me know and I'll put up a gist somewhere. Obviously using primitives isn't something that's built into the core of SquiDB by default, so it does come with risks as we've never tried it ourselves, but it might serve your use case best.

aminelaadhari commented 8 years ago

Great thank you. I like how much flexible is Squidb! Feel free to close the issue. Thanks a lot !

sbosley commented 8 years ago

Glad to help!