def test_partitioning_time_daily_apply_insert(): """Tests whether automatically created daily partitions line up perfectly.""" model = define_fake_partitioned_model( {"timestamp": models.DateTimeField()}, {"key": ["timestamp"]}) schema_editor = connection.schema_editor() schema_editor.create_partitioned_model(model) # that's a monday with freezegun.freeze_time("2019-1-07"): manager = PostgresPartitioningManager( [partition_by_current_time(model, days=1, count=2)]) manager.plan().apply() table = _get_partitioned_table(model) assert len(table.partitions) == 2 model.objects.create(timestamp=datetime.date(2019, 1, 7)) model.objects.create(timestamp=datetime.date(2019, 1, 8)) with transaction.atomic(): with pytest.raises(IntegrityError): model.objects.create(timestamp=datetime.date(2019, 1, 9)) model.objects.create(timestamp=datetime.date(2019, 1, 10)) with freezegun.freeze_time("2019-1-07"): manager = PostgresPartitioningManager( [partition_by_current_time(model, days=1, count=4)]) manager.plan().apply() model.objects.create(timestamp=datetime.date(2019, 1, 9)) model.objects.create(timestamp=datetime.date(2019, 1, 10))
def test_partitioning_time_monthly_apply_insert(): """Tests whether automatically created monthly partitions line up perfectly.""" model = define_fake_partitioned_model( {"timestamp": models.DateTimeField()}, {"key": ["timestamp"]}) schema_editor = connection.schema_editor() schema_editor.create_partitioned_model(model) with freezegun.freeze_time("2019-1-1"): manager = PostgresPartitioningManager( [partition_by_current_time(model, months=1, count=2)]) manager.plan().apply() model.objects.create(timestamp=datetime.date(2019, 1, 1)) model.objects.create(timestamp=datetime.date(2019, 1, 31)) model.objects.create(timestamp=datetime.date(2019, 2, 28)) with transaction.atomic(): with pytest.raises(IntegrityError): model.objects.create(timestamp=datetime.date(2019, 3, 1)) model.objects.create(timestamp=datetime.date(2019, 3, 2)) with freezegun.freeze_time("2019-1-1"): manager = PostgresPartitioningManager( [partition_by_current_time(model, months=1, count=3)]) manager.plan().apply() model.objects.create(timestamp=datetime.date(2019, 3, 1)) model.objects.create(timestamp=datetime.date(2019, 3, 2))
def test_partitioning_time_yearly_apply(): """Tests whether automatically creating new partitions ahead yearly works as expected.""" model = define_fake_partitioned_model( {"timestamp": models.DateTimeField()}, {"key": ["timestamp"]}) schema_editor = connection.schema_editor() schema_editor.create_partitioned_model(model) with freezegun.freeze_time("2019-1-1"): manager = PostgresPartitioningManager( [partition_by_current_time(model, years=1, count=2)]) manager.plan().apply() table = _get_partitioned_table(model) assert len(table.partitions) == 2 assert table.partitions[0].name == "2019" assert table.partitions[1].name == "2020" with freezegun.freeze_time("2019-12-30"): manager = PostgresPartitioningManager( [partition_by_current_time(model, years=1, count=3)]) manager.plan().apply() table = _get_partitioned_table(model) assert len(table.partitions) == 3 assert table.partitions[0].name == "2019" assert table.partitions[1].name == "2020" assert table.partitions[2].name == "2021"
def test_partitioning_time_monthly_apply(): """Tests whether automatically creating new partitions ahead monthly works as expected.""" model = define_fake_partitioned_model( {"timestamp": models.DateTimeField()}, {"key": ["timestamp"]}) schema_editor = connection.schema_editor() schema_editor.create_partitioned_model(model) # create partitions for the next 12 months (including the current) with freezegun.freeze_time("2019-1-30"): manager = PostgresPartitioningManager( [partition_by_current_time(model, months=1, count=12)]) manager.plan().apply() table = _get_partitioned_table(model) assert len(table.partitions) == 12 assert table.partitions[0].name == "2019_jan" assert table.partitions[1].name == "2019_feb" assert table.partitions[2].name == "2019_mar" assert table.partitions[3].name == "2019_apr" assert table.partitions[4].name == "2019_may" assert table.partitions[5].name == "2019_jun" assert table.partitions[6].name == "2019_jul" assert table.partitions[7].name == "2019_aug" assert table.partitions[8].name == "2019_sep" assert table.partitions[9].name == "2019_oct" assert table.partitions[10].name == "2019_nov" assert table.partitions[11].name == "2019_dec" # re-running it with 13, should just create one additional partition with freezegun.freeze_time("2019-1-30"): manager = PostgresPartitioningManager( [partition_by_current_time(model, months=1, count=13)]) manager.plan().apply() table = _get_partitioned_table(model) assert len(table.partitions) == 13 assert table.partitions[12].name == "2020_jan" # it's november now, we only want to create 4 partitions ahead, # so only one new partition should be created for february 1338 with freezegun.freeze_time("2019-11-1"): manager = PostgresPartitioningManager( [partition_by_current_time(model, months=1, count=4)]) manager.plan().apply() table = _get_partitioned_table(model) assert len(table.partitions) == 14 assert table.partitions[13].name == "2020_feb"
def test_partitioning_time_delete_ignore_manual(): """Tests whether partitions that were created manually are ignored. Partitions created automatically have a special comment attached to them. Only partitions with this special comments would be deleted. """ model = define_fake_partitioned_model( {"timestamp": models.DateTimeField()}, {"key": ["timestamp"]}) schema_editor = connection.schema_editor() schema_editor.create_partitioned_model(model) manager = PostgresPartitioningManager( [partition_by_current_time(model, count=2, months=1)]) schema_editor.add_range_partition(model, "2019_jan", from_values="2019-1-1", to_values="2019-2-1") with freezegun.freeze_time("2020-1-1"): manager.plan(skip_create=True).apply() table = _get_partitioned_table(model) assert len(table.partitions) == 1
def test_partitioning_time_daily_apply(): """Tests whether automatically creating new partitions ahead daily works as expected.""" model = define_fake_partitioned_model( {"timestamp": models.DateTimeField()}, {"key": ["timestamp"]}) schema_editor = connection.schema_editor() schema_editor.create_partitioned_model(model) # create partitions for the next 4 days (including the current) with freezegun.freeze_time("2019-1-23"): manager = PostgresPartitioningManager( [partition_by_current_time(model, days=1, count=4)]) manager.plan().apply() table = _get_partitioned_table(model) assert len(table.partitions) == 4 assert table.partitions[0].name == "2019_jan_23" assert table.partitions[1].name == "2019_jan_24" assert table.partitions[2].name == "2019_jan_25" assert table.partitions[3].name == "2019_jan_26" # re-running it with 5, should just create one additional partition with freezegun.freeze_time("2019-1-23"): manager = PostgresPartitioningManager( [partition_by_current_time(model, days=1, count=5)]) manager.plan().apply() table = _get_partitioned_table(model) assert len(table.partitions) == 5 assert table.partitions[4].name == "2019_jan_27" # it's june now, we want to partition two days ahead with freezegun.freeze_time("2019-06-03"): manager = PostgresPartitioningManager( [partition_by_current_time(model, days=1, count=2)]) manager.plan().apply() table = _get_partitioned_table(model) assert len(table.partitions) == 7 assert table.partitions[5].name == "2019_jun_03" assert table.partitions[6].name == "2019_jun_04"
def test_partitioning_manager_plan_not_partitioned_model(): """Tests that the auto partitioner does not try to auto partition for non- partitioned models/tables.""" model = get_fake_model({"timestamp": models.DateTimeField()}) with pytest.raises(PostgresPartitioningError): manager = PostgresPartitioningManager( [partition_by_current_time(model, months=1, count=2)] ) manager.plan()
def test_partitioning_time_multiple(kwargs, partition_names): model = define_fake_partitioned_model( {"timestamp": models.DateTimeField()}, {"key": ["timestamp"]}) schema_editor = connection.schema_editor() schema_editor.create_partitioned_model(model) with freezegun.freeze_time("2019-1-1"): manager = PostgresPartitioningManager( [partition_by_current_time(model, **kwargs, count=2)]) manager.plan().apply() table = _get_partitioned_table(model) assert len(table.partitions) == 2 assert partition_names == [par.name for par in table.partitions]
def test_partitioning_manager_duplicate_model(): """Tests whether it is not possible to have more than one partitioning config per model.""" model = define_fake_partitioned_model( {"timestamp": models.DateTimeField()}, {"key": ["timestamp"]} ) with pytest.raises(PostgresPartitioningError): PostgresPartitioningManager( [ partition_by_current_time(model, years=1, count=3), partition_by_current_time(model, years=1, count=3), ] )
def test_partitioning_manager_find_config_for_model(): """Tests that finding a partitioning config by the model works as expected.""" model1 = define_fake_partitioned_model( {"timestamp": models.DateTimeField()}, {"key": ["timestamp"]} ) config1 = partition_by_current_time(model1, years=1, count=3) model2 = define_fake_partitioned_model( {"timestamp": models.DateTimeField()}, {"key": ["timestamp"]} ) config2 = partition_by_current_time(model2, months=1, count=2) manager = PostgresPartitioningManager([config1, config2]) assert manager.find_config_for_model(model1) == config1 assert manager.find_config_for_model(model2) == config2
def test_partitioning_time_delete(kwargs, timepoints): """Tests whether partitions older than the specified max_age are automatically deleted.""" model = define_fake_partitioned_model( {"timestamp": models.DateTimeField()}, {"key": ["timestamp"]}) schema_editor = connection.schema_editor() schema_editor.create_partitioned_model(model) partition_kwargs = {"model": model, "count": 6, **kwargs} manager = PostgresPartitioningManager( [partition_by_current_time(**partition_kwargs)]) with freezegun.freeze_time(timepoints[0][0]): manager.plan().apply() for index, (dt, partition_count) in enumerate(timepoints): with freezegun.freeze_time(dt): manager.plan(skip_create=True).apply() table = _get_partitioned_table(model) assert len(table.partitions) == partition_count
def fake_partitioning_manager(fake_model, fake_strategy): manager = PostgresPartitioningManager( [PostgresPartitioningConfig(fake_model, fake_strategy)]) with override_settings(PSQLEXTRA_PARTITIONING_MANAGER=manager): yield manager