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

Revision 7b139906ac46: Add NOT NULL constraints to certain Variable (meta_vars) columns #111

Merged
merged 13 commits into from
Jan 27, 2022

Conversation

helfy18
Copy link
Contributor

@helfy18 helfy18 commented Jan 19, 2022

Resolves #29

Add not null constraints to meta_vars.

Add not null constraints to three variables in the meta_vars table
modify the subset data so that the constraint is not violated
@helfy18 helfy18 force-pushed the i29-add-not-null-constraint branch from 8299fcb to 16213ce Compare January 21, 2022 19:29
Copy link
Contributor

@rod-glover rod-glover left a comment

Choose a reason for hiding this comment

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

Looking good so far, Johnathan.

Minor point: Suggest you run Black on
pycds/alembic/versions/7b139906ac46_add_not_null_constraint_on_meta_vars.py
tests/climate_baseline_helpers/conftest.py
to clean up their formatting.

I think it is worth creating a test to test the data migration part of the migration (hmm, a lot of repetitions there). The test have to do something very like this:

  • establish a database at the previous revision
  • populate the meta_vars table with some rows with null values and some without
  • run the upgrade to your revision
  • check that meta_vars has been updated as expected - the nulls have been replaced

See if you can figure out how to do this by looking at other tests. This particular test will be best placed alongside the smoke tests for this migration, not under behavioural.

Copy link
Contributor

@rod-glover rod-glover left a comment

Choose a reason for hiding this comment

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

Good work, @helfy18 ! You've done a great job of checking the schema migration. There's really only one thing left -- checks for the data migrations. Comment below outlines how.

# Set up database to version 7b139906ac46
engine, script = prepared_schema_from_migrations_left

# Check that views have been added
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment needs revising. Copy/pasta?

engine, script = prepared_schema_from_migrations_left

# Check that views have been added
table = inspect(engine).get_columns("meta_vars", schema=schema_name)
Copy link
Contributor

Choose a reason for hiding this comment

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

Excellent use of inspection to check the migration action. 💯


@pytest.mark.usefixtures("new_db_left")
def test_upgrade(prepared_schema_from_migrations_left, schema_name):
"""test migration from 3d50ec832e47 to 7b139906ac46. """
Copy link
Contributor

@rod-glover rod-glover Jan 26, 2022

Choose a reason for hiding this comment

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

We also need a check of the data migration action. That would look like the following:

  • Migrate to 3d50ec832e47
  • Load meta_vars with rows containing nulls in the migration columns. You can probably do that with a few inserts just to meta_vars, rather than loading all kinds of stuff as the big behavioural tests do.
  • Migrate to 7b139906ac46
  • Check the effects of the data migration
  • Check the effects of the schema migration (already coded)

Copy link
Contributor

Choose a reason for hiding this comment

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

You can find an example of this kind of two-stage upgrade test in tests/alembic_migrations/versions/v_e688e520d265_refactor_flags_association_tables. The way the initial target revision for test_upgrade is set up is subtle (a synonym for confusing): It is overridden by the parametrization

@pytest.mark.parametrize(
    "prepared_schema_from_migrations_left", ("bdc28573df56",), indirect=True
)

of that method. You can do the same, except using of course the prior revision to this one.

If you get too stuck or confused, don't hesitate to reach out for help.

def test_downgrade(
prepared_schema_from_migrations_left, alembic_config_left, schema_name
):
"""Test the schema migration from 7b139906ac46 to 3d50ec832e47. """
Copy link
Contributor

Choose a reason for hiding this comment

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

And likewise a check of the downgrade data migration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For this one there is a call of command.downgrade(), which I think means that I am testing the downgrade data migration. As far as not testing the upgrade though, I will add that in. I followed the views tests, as you noticed by my copy paste mistake, and that one did not run command.upgrade() in the test_upgrade feature, so that's why it is the way it is for me

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, this means you are testing the downgrade migration -- both schema and data.

Copy link
Contributor

Choose a reason for hiding this comment

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

For testing the upgrade, see my remarks above.

Copy link
Contributor

@rod-glover rod-glover left a comment

Choose a reason for hiding this comment

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

Keep at it, @helfy18 , it's coming along well.

def test_downgrade(
prepared_schema_from_migrations_left, alembic_config_left, schema_name
):
"""Test the schema migration from 7b139906ac46 to 3d50ec832e47. """
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, this means you are testing the downgrade migration -- both schema and data.

def test_downgrade(
prepared_schema_from_migrations_left, alembic_config_left, schema_name
):
"""Test the schema migration from 7b139906ac46 to 3d50ec832e47. """
Copy link
Contributor

Choose a reason for hiding this comment

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

For testing the upgrade, see my remarks above.


@pytest.mark.usefixtures("new_db_left")
def test_upgrade(prepared_schema_from_migrations_left, schema_name):
"""test migration from 3d50ec832e47 to 7b139906ac46. """
Copy link
Contributor

Choose a reason for hiding this comment

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

You can find an example of this kind of two-stage upgrade test in tests/alembic_migrations/versions/v_e688e520d265_refactor_flags_association_tables. The way the initial target revision for test_upgrade is set up is subtle (a synonym for confusing): It is overridden by the parametrization

@pytest.mark.parametrize(
    "prepared_schema_from_migrations_left", ("bdc28573df56",), indirect=True
)

of that method. You can do the same, except using of course the prior revision to this one.

If you get too stuck or confused, don't hesitate to reach out for help.

Copy link
Contributor

@rod-glover rod-glover left a comment

Choose a reason for hiding this comment

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

A bit more to do.

)

command.upgrade(alembic_config_left, "+1")

Copy link
Contributor

Choose a reason for hiding this comment

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

After the migration check that the nulls in the row(s) you inserted have been set to the expected non-null values (or just not null).

"""Test the schema migration from 7b139906ac46 to 3d50ec832e47. """

# Set up database to version 7b139906ac46
engine, script = prepared_schema_from_migrations_left
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add the downgrade data migration check: non-null values to nulls.

def sesh_with_large_data(prepared_schema_from_migrations_left):
engine, script = prepared_schema_from_migrations_left
sesh = sessionmaker(bind=engine)()
insert_crmp_data(sesh)
Copy link
Contributor

Choose a reason for hiding this comment

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

If you omit this you will have a clean empty database. That's probably desirable for this test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

so remove this entire function from conftest.py?


# Check that data has been modified to remove nulls
result = engine.execute(
f"SELECT * FROM {schema_name}.meta_vars"
Copy link
Contributor

Choose a reason for hiding this comment

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

To make comparisons simpler (see below), specify the columns explicitly here.

result = engine.execute(
f"SELECT * FROM {schema_name}.meta_vars"
)
for row in result:
Copy link
Contributor

Choose a reason for hiding this comment

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

If the database starts out empty, you can assume that only the one row you inserted comes back. Try

row = next(result)

instead of the for loop.

And then you can check assert row == (....) where the parens are a tuple.

engine.execute(
f"INSERT INTO {schema_name}.meta_vars(vars_id, cell_method, standard_name, display_name)"
f"VALUES (10000, 'foo: bar', 'foo_bar', 'foo bar')"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

result = engine.execute(
f"SELECT * FROM {schema_name}.meta_vars"
)
for row in result:
Copy link
Contributor

Choose a reason for hiding this comment

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

See comments for test_upgrade.

Copy link
Contributor

@rod-glover rod-glover left a comment

Choose a reason for hiding this comment

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

Looks great, @helfy18 ! Ready to merge!

)

row = next(result)
assert row == (1, "foo: bar", "foo_bar", "foo bar")
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

)

row = next(result)
assert row == (10000, None, None, None)
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

Copy link
Contributor

@rod-glover rod-glover left a comment

Choose a reason for hiding this comment

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

Approved!

@helfy18 helfy18 merged commit 0a8e9cd into master Jan 27, 2022
@helfy18 helfy18 deleted the i29-add-not-null-constraint branch January 27, 2022 23:31
@rod-glover rod-glover changed the title I29 add not null constraint Add NOT NULL constraints to certain Variable (meta_vars) columns Jan 31, 2022
@rod-glover rod-glover changed the title Add NOT NULL constraints to certain Variable (meta_vars) columns Revision 7b139906ac46: Add NOT NULL constraints to certain Variable (meta_vars) columns Nov 2, 2022
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.

Add NOT NULL constraints to certain Variable columns
2 participants