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

More constraint annotations [4.0] #273

Closed sbosley closed 7 years ago

sbosley commented 7 years ago

This PR fleshes out the idea begun with the default value annotations (#272) by introducing new annotations for most types of table and column constraints. These annotations have the advantage over specifying constraints as raw SQL in that they can help avoid SQL syntax errors/typos, and can be subject to additional validation or introspection at compile time, by either plugins or the code generator. For example, we could enhance the getters/setters of any column annotated with @NotNull to add nullability annotations to the accessors, only allow primitive values for get/set, do runtime checking, or any combination thereof. (Such options will in fact probably be introduced in a future PR). Similarly, we can detect if users have declared a PRIMARY KEY as a table level constraint, and if we detect the column referred to is an integer column we can use it for our rowid bookkeeping. As a final example, we can validate that any column names referred to in table-level constraints like @UniqueColumns or @PrimaryKeyColumns do in fact exist in the model's schema. One constraint type that we don't support with an annotation (at least for now) is foreign key constraints. Model specs don't necessarily have compile-time knowledge about/access to other models, so this annotation wouldn't be validatable, plus foreign key clauses have a much more complex grammar than other constraint types, which could make for a messy annotation. For cases like these (or if they just prefer to do so), users can use @ConstraintSql to specify constraints as raw SQL.

These new annotations live in a new package: com.yahoo.squidb.annotations.tables.constraints. The default value annotations from the previous PR have also moved, to com.yahoo.squidb.annotations.tables.defaults. (Since these aren't in production yet this move will not be disruptive). Note that one thing that will be disruptive is that the column-level @PrimaryKey annotation has moved from the root annotations package into this constraints package, and will need to be reimported. Now that we have a lot more annotations than we used to, we should consider reorganizing the other annotations into packages like tables, views, etc. as well.

This PR also includes unit tests for the new code generator components that handle these annotations, as well as a new ModelSchemaTest test case in the integration tests project. This test in particular will be useful in guarding against future regressions -- I wrote the test against the test table/model schemas as they exist on the master branch, and then moved them to the dev branch to verify that they still passed using the new code generator (with only trivial, non-SQL changes). This test will help us verify that we won't accidentally break any schema generation when moving from 3.x to 4.0, or if we make future implementation changes to the 4.0 code generator.