Skip to content

Commit 2adc13f

Browse files
ckrybusPhotonios
authored andcommitted
Make time partition suffix customizable
1 parent 8f6bac6 commit 2adc13f

File tree

4 files changed

+65
-5
lines changed

4 files changed

+65
-5
lines changed

psqlextra/partitioning/current_time_strategy.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def __init__(
2424
size: PostgresTimePartitionSize,
2525
count: int,
2626
max_age: Optional[relativedelta] = None,
27+
name_format: Optional[str] = None,
2728
) -> None:
2829
"""Initializes a new instance of :see:PostgresTimePartitioningStrategy.
2930
@@ -44,13 +45,16 @@ def __init__(
4445
self.size = size
4546
self.count = count
4647
self.max_age = max_age
48+
self.name_format = name_format
4749

4850
def to_create(self) -> Generator[PostgresTimePartition, None, None]:
4951
current_datetime = self.size.start(self.get_start_datetime())
5052

5153
for _ in range(self.count):
5254
yield PostgresTimePartition(
53-
start_datetime=current_datetime, size=self.size
55+
start_datetime=current_datetime,
56+
size=self.size,
57+
name_format=self.name_format,
5458
)
5559

5660
current_datetime += self.size.as_delta()
@@ -65,7 +69,9 @@ def to_delete(self) -> Generator[PostgresTimePartition, None, None]:
6569

6670
while True:
6771
yield PostgresTimePartition(
68-
start_datetime=current_datetime, size=self.size
72+
start_datetime=current_datetime,
73+
size=self.size,
74+
name_format=self.name_format,
6975
)
7076

7177
current_datetime -= self.size.as_delta()

psqlextra/partitioning/shorthands.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def partition_by_current_time(
1717
weeks: Optional[int] = None,
1818
days: Optional[int] = None,
1919
max_age: Optional[relativedelta] = None,
20+
name_format: Optional[str] = None,
2021
) -> PostgresPartitioningConfig:
2122
"""Short-hand for generating a partitioning config that partitions the
2223
specified model by time.
@@ -48,6 +49,10 @@ def partition_by_current_time(
4849
4950
Partitions older than this are deleted when running
5051
a delete/cleanup run.
52+
53+
name_format:
54+
The datetime format which is being passed to datetime.strftime
55+
to generate the partition name.
5156
"""
5257

5358
size = PostgresTimePartitionSize(
@@ -57,7 +62,10 @@ def partition_by_current_time(
5762
return PostgresPartitioningConfig(
5863
model=model,
5964
strategy=PostgresCurrentTimePartitioningStrategy(
60-
size=size, count=count, max_age=max_age
65+
size=size,
66+
count=count,
67+
max_age=max_age,
68+
name_format=name_format,
6169
),
6270
)
6371

psqlextra/partitioning/time_partition.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from datetime import datetime
2+
from typing import Optional
23

34
from .error import PostgresPartitioningError
45
from .range_partition import PostgresRangePartition
@@ -22,7 +23,10 @@ class PostgresTimePartition(PostgresRangePartition):
2223
}
2324

2425
def __init__(
25-
self, size: PostgresTimePartitionSize, start_datetime: datetime
26+
self,
27+
size: PostgresTimePartitionSize,
28+
start_datetime: datetime,
29+
name_format: Optional[str] = None,
2630
) -> None:
2731
end_datetime = start_datetime + size.as_delta()
2832

@@ -34,9 +38,12 @@ def __init__(
3438
self.size = size
3539
self.start_datetime = start_datetime
3640
self.end_datetime = end_datetime
41+
self.name_format = name_format
3742

3843
def name(self) -> str:
39-
name_format = self._unit_name_format.get(self.size.unit)
44+
name_format = self.name_format or self._unit_name_format.get(
45+
self.size.unit
46+
)
4047
if not name_format:
4148
raise PostgresPartitioningError("Unknown size/unit")
4249

tests/test_partitioning_time.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,45 @@ def test_partitioning_time_monthly_apply():
115115
assert table.partitions[13].name == "2020_feb"
116116

117117

118+
@pytest.mark.postgres_version(lt=110000)
119+
def test_partitioning_time_monthly_with_custom_naming_apply():
120+
"""Tests whether automatically created new partitions are named according
121+
to the specified name_format."""
122+
123+
model = define_fake_partitioned_model(
124+
{"timestamp": models.DateTimeField()}, {"key": ["timestamp"]}
125+
)
126+
127+
schema_editor = connection.schema_editor()
128+
schema_editor.create_partitioned_model(model)
129+
130+
# create partitions for the next 12 months (including the current)
131+
with freezegun.freeze_time("2019-1-30"):
132+
manager = PostgresPartitioningManager(
133+
[
134+
partition_by_current_time(
135+
model, months=1, count=12, name_format="%Y_%m"
136+
)
137+
]
138+
)
139+
manager.plan().apply()
140+
141+
table = _get_partitioned_table(model)
142+
assert len(table.partitions) == 12
143+
assert table.partitions[0].name == "2019_01"
144+
assert table.partitions[1].name == "2019_02"
145+
assert table.partitions[2].name == "2019_03"
146+
assert table.partitions[3].name == "2019_04"
147+
assert table.partitions[4].name == "2019_05"
148+
assert table.partitions[5].name == "2019_06"
149+
assert table.partitions[6].name == "2019_07"
150+
assert table.partitions[7].name == "2019_08"
151+
assert table.partitions[8].name == "2019_09"
152+
assert table.partitions[9].name == "2019_10"
153+
assert table.partitions[10].name == "2019_11"
154+
assert table.partitions[11].name == "2019_12"
155+
156+
118157
@pytest.mark.postgres_version(lt=110000)
119158
def test_partitioning_time_weekly_apply():
120159
"""Tests whether automatically creating new partitions ahead weekly works

0 commit comments

Comments
 (0)