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

Add Interleaved annotation implementation #168

Merged
merged 17 commits into from Dec 2, 2019
Merged

Add Interleaved annotation implementation #168

merged 17 commits into from Dec 2, 2019

Conversation

dzou
Copy link
Contributor

@dzou dzou commented Nov 21, 2019

This is the initial implementation of the @Interleaved annotation.

I would like to get this in and add the full polishing and integration tests in separate PRs.

In progress #140.

Notes:

  • You must control the order in which interleaved tables are created and dropped. When creating, parent tables must be created first before creating the interleaved tables. When dropping, interleaved tables must be dropped first before dropping the parent tables.
  • Sorting the PK columns in the create table statements for interleaved tables. The PK declaration of the child table must have a prefix which matches the PK declaration of the parent table. See SpannerTableStatements.getSortedPkColumns(..). Details: https://cloud.google.com/spanner/docs/schema-and-data-model

Copy link
Member

@meltsufin meltsufin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the graph algorithm could potentially be separated into its own class and tested independently.
Just something to consider.
Also, please add more comments to the dense parts of the code.

/**
* Returns a {@link Map} which maps a table to the table it is interleaved with.
*/
private Map<Table, Table> buildCreateTableDependencies(Metadata metadata) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this method belong here rather than the SpannerTableExporter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, I went with your suggestion of splitting out the table-dependency-tracking stuff to a separate class; this work is now done in that class.

/**
* Returns a {@link Map} which maps a table to the table that must be dropped before it.
*/
private static Map<Table, Table> buildDropTableDependencies(Metadata metadata) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this method belong here rather than the SpannerTableExporter?
Also, please try to factor out the duplication with the method above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done; same as above.


private final String createTableTemplate;
private Map<Table, Table> tableDependencies;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which generic argument is parent and which is child?
I think the use of the term "dependent" or "dependencies" is a bit confusing.
Would it make sense to call the variables and methods more in terms of "child" tables and "parent" tables?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Map<Table, Table> for each (key, value) entry, the Table in the value must be processed (either created or dropped) before the Table in the key position.

Copy link
Member

@meltsufin meltsufin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the refactoring.

@dzou
Copy link
Contributor Author

dzou commented Nov 21, 2019

Do we have something to test this?

Unfortunately right now we don't have test coverage over the SchemaMigrator. I think this is best tested through Integration test. I tried to write a unit test for this (i.e. running Hibernate in a unit test with ddl-mode.auto=UPDATE triggers the SchemaMigrator) but it tries to make queries to the underlying Spanner instance to see what the current tables are and see which tables need to be altered. I decided its not worth digging around in the Hibernate code and seeing what mock objects we need to inject in which fields to get this to work.

I created #170 to track the integration test efforts.

Note that create and drop are covered via unit tests.

@dzou dzou requested a review from meltsufin November 22, 2019 18:04
dzou and others added 3 commits November 25, 2019 14:33
…e/cloud/spanner/hibernate/Interleaved.java

Co-Authored-By: Mike Eltsufin <meltsufin@google.com>
@dzou dzou requested a review from meltsufin November 26, 2019 19:12
Copy link
Member

@meltsufin meltsufin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more, but minor comments.

Copy link
Contributor

@elefeint elefeint left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, a few nits.

*/

ArrayList<String> dropStrings = new ArrayList<>();
private String[] buildSqlStrings(Table currentTable, Metadata metadata, boolean isCreateTables) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking personal opinion: an enum would be clearer than boolean for CREATE vs DROP.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, but then you need to check for nulls and invalid options, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to use the Action Enum provided in the Hibernate libraries (it has Action.CREATE, Action.DROP, etc.)

It'll be fine to use this; as far as invalid options/nulls, I think we will be able to avoid these problems since these functions are not intended to be called by end users. It is more to just make the code easier for us to understand with enums over booleans.

Copy link
Member

@meltsufin meltsufin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good, after you address Elena's comments.

*/

ArrayList<String> dropStrings = new ArrayList<>();
private String[] buildSqlStrings(Table currentTable, Metadata metadata, boolean isCreateTables) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, but then you need to check for nulls and invalid options, etc.

@dzou dzou requested a review from elefeint December 2, 2019 19:14
@dzou dzou merged commit 1733a4d into master Dec 2, 2019
@dzou dzou deleted the interleaved branch December 2, 2019 19:31
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

Successfully merging this pull request may close these issues.

None yet

3 participants