Skip to content

Commit 25f1bda

Browse files
committed
Fix NULL constraints
1 parent 82a53d0 commit 25f1bda

20 files changed

+119
-124
lines changed

airflow-core/src/airflow/models/backfill.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class Backfill(Base):
120120
from_date: Mapped[UtcDateTime] = mapped_column(UtcDateTime, nullable=False)
121121
to_date: Mapped[UtcDateTime] = mapped_column(UtcDateTime, nullable=False)
122122
dag_run_conf: Mapped[JSONField] = mapped_column(JSONField(json=json), nullable=False, default={})
123-
is_paused: Mapped[bool] = mapped_column(Boolean, default=False)
123+
is_paused: Mapped[bool | None] = mapped_column(Boolean, default=False, nullable=True)
124124
"""
125125
Controls whether new dag runs will be created for this backfill.
126126
@@ -172,7 +172,7 @@ class BackfillDagRun(Base):
172172
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
173173
backfill_id: Mapped[int] = mapped_column(Integer, nullable=False)
174174
dag_run_id: Mapped[int | None] = mapped_column(Integer, nullable=True)
175-
exception_reason: Mapped[str] = mapped_column(StringID())
175+
exception_reason: Mapped[str | None] = mapped_column(StringID(), nullable=True)
176176
logical_date: Mapped[UtcDateTime] = mapped_column(UtcDateTime, nullable=False)
177177
sort_ordinal: Mapped[int] = mapped_column(Integer, nullable=False)
178178

airflow-core/src/airflow/models/connection.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,18 +130,18 @@ class Connection(Base, LoggingMixin):
130130
id: Mapped[int] = mapped_column(Integer(), primary_key=True)
131131
conn_id: Mapped[str] = mapped_column(String(ID_LEN), unique=True, nullable=False)
132132
conn_type: Mapped[str] = mapped_column(String(500), nullable=False)
133-
description: Mapped[str] = mapped_column(
134-
Text().with_variant(Text(5000), "mysql").with_variant(String(5000), "sqlite")
133+
description: Mapped[str | None] = mapped_column(
134+
Text().with_variant(Text(5000), "mysql").with_variant(String(5000), "sqlite"), nullable=True
135135
)
136-
host: Mapped[str] = mapped_column(String(500))
137-
schema: Mapped[str] = mapped_column(String(500))
138-
login: Mapped[str] = mapped_column(Text())
139-
_password: Mapped[str] = mapped_column("password", Text())
140-
port: Mapped[int] = mapped_column(Integer())
136+
host: Mapped[str | None] = mapped_column(String(500), nullable=True)
137+
schema: Mapped[str | None] = mapped_column(String(500), nullable=True)
138+
login: Mapped[str | None] = mapped_column(Text(), nullable=True)
139+
_password: Mapped[str | None] = mapped_column("password", Text(), nullable=True)
140+
port: Mapped[int | None] = mapped_column(Integer(), nullable=True)
141141
is_encrypted: Mapped[bool] = mapped_column(Boolean, unique=False, default=False)
142142
is_extra_encrypted: Mapped[bool] = mapped_column(Boolean, unique=False, default=False)
143143
team_id: Mapped[str | None] = mapped_column(UUIDType(binary=False), ForeignKey("team.id"), nullable=True)
144-
_extra: Mapped[str] = mapped_column("extra", Text())
144+
_extra: Mapped[str | None] = mapped_column("extra", Text(), nullable=True)
145145

146146
def __init__(
147147
self,

airflow-core/src/airflow/models/dag.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -322,29 +322,29 @@ class DagModel(Base):
322322
# Whether that DAG was seen on the last DagBag load
323323
is_stale: Mapped[bool] = mapped_column(Boolean, default=True)
324324
# Last time the scheduler started
325-
last_parsed_time: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
325+
last_parsed_time: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
326326
# How long it took to parse this file
327-
last_parse_duration: Mapped[float] = mapped_column(Float)
327+
last_parse_duration: Mapped[float | None] = mapped_column(Float, nullable=True)
328328
# Time when the DAG last received a refresh signal
329329
# (e.g. the DAG's "refresh" button was clicked in the web UI)
330-
last_expired: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
330+
last_expired: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
331331
# The location of the file containing the DAG object
332332
# Note: Do not depend on fileloc pointing to a file; in the case of a
333333
# packaged DAG, it will point to the subpath of the DAG within the
334334
# associated zip.
335-
fileloc: Mapped[str] = mapped_column(String(2000))
336-
relative_fileloc: Mapped[str] = mapped_column(String(2000))
335+
fileloc: Mapped[str | None] = mapped_column(String(2000), nullable=True)
336+
relative_fileloc: Mapped[str | None] = mapped_column(String(2000), nullable=True)
337337
bundle_name: Mapped[str] = mapped_column(StringID(), ForeignKey("dag_bundle.name"), nullable=False)
338338
# The version of the bundle the last time the DAG was processed
339339
bundle_version: Mapped[str | None] = mapped_column(String(200), nullable=True)
340340
# String representing the owners
341-
owners: Mapped[str] = mapped_column(String(2000))
341+
owners: Mapped[str | None] = mapped_column(String(2000), nullable=True)
342342
# Display name of the dag
343343
_dag_display_property_value: Mapped[str | None] = mapped_column(
344344
"dag_display_name", String(2000), nullable=True
345345
)
346346
# Description of the dag
347-
description: Mapped[str] = mapped_column(Text)
347+
description: Mapped[str | None] = mapped_column(Text, nullable=True)
348348
# Timetable summary
349349
timetable_summary: Mapped[str | None] = mapped_column(Text, nullable=True)
350350
# Timetable description
@@ -374,14 +374,14 @@ class DagModel(Base):
374374
has_import_errors: Mapped[bool] = mapped_column(Boolean(), default=False, server_default="0")
375375

376376
# The logical date of the next dag run.
377-
next_dagrun: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
377+
next_dagrun: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
378378

379379
# Must be either both NULL or both datetime.
380-
next_dagrun_data_interval_start: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
381-
next_dagrun_data_interval_end: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
380+
next_dagrun_data_interval_start: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
381+
next_dagrun_data_interval_end: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
382382

383383
# Earliest time at which this ``next_dagrun`` can be created.
384-
next_dagrun_create_after: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
384+
next_dagrun_create_after: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
385385

386386
__table_args__ = (Index("idx_next_dagrun_create_after", next_dagrun_create_after, unique=False),)
387387

airflow-core/src/airflow/models/dag_favorite.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,12 @@
1717
# under the License.
1818
from __future__ import annotations
1919

20-
from typing import TYPE_CHECKING
21-
2220
from sqlalchemy import ForeignKey
21+
from sqlalchemy.orm import Mapped
2322

2423
from airflow.models.base import Base, StringID
2524
from airflow.utils.sqlalchemy import mapped_column
2625

27-
if TYPE_CHECKING:
28-
from sqlalchemy.orm import Mapped
29-
3026

3127
class DagFavorite(Base):
3228
"""Association table model linking users to their favorite DAGs."""

airflow-core/src/airflow/models/dag_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class DagVersion(Base):
4949
)
5050
dag_model = relationship("DagModel", back_populates="dag_versions")
5151
bundle_name: Mapped[str | None] = mapped_column(StringID(), nullable=True)
52-
bundle_version: Mapped[str] = mapped_column(StringID())
52+
bundle_version: Mapped[str | None] = mapped_column(StringID(), nullable=True)
5353
dag_code = relationship(
5454
"DagCode",
5555
back_populates="dag_version",

airflow-core/src/airflow/models/dagbundle.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class DagBundleModel(Base, LoggingMixin):
4343

4444
__tablename__ = "dag_bundle"
4545
name: Mapped[str] = mapped_column(StringID(length=250), primary_key=True, nullable=False)
46-
active: Mapped[bool] = mapped_column(Boolean, default=True)
46+
active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
4747
version: Mapped[str | None] = mapped_column(String(200), nullable=True)
4848
last_refreshed: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
4949
signed_url_template: Mapped[str | None] = mapped_column(String(200), nullable=True)

airflow-core/src/airflow/models/dagrun.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -149,29 +149,31 @@ class DagRun(Base, LoggingMixin):
149149

150150
id: Mapped[int] = mapped_column(Integer, primary_key=True)
151151
dag_id: Mapped[str] = mapped_column(StringID(), nullable=False)
152-
queued_at: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
152+
queued_at: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
153153
logical_date: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
154-
start_date: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
155-
end_date: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
154+
start_date: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
155+
end_date: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
156156
_state: Mapped[str] = mapped_column("state", String(50), default=DagRunState.QUEUED)
157157
run_id: Mapped[str] = mapped_column(StringID(), nullable=False)
158-
creating_job_id: Mapped[int] = mapped_column(Integer)
158+
creating_job_id: Mapped[int | None] = mapped_column(Integer, nullable=True)
159159
run_type: Mapped[str] = mapped_column(String(50), nullable=False)
160-
triggered_by: Mapped[DagRunTriggeredByType] = mapped_column(
161-
Enum(DagRunTriggeredByType, native_enum=False, length=50)
160+
triggered_by: Mapped[DagRunTriggeredByType | None] = mapped_column(
161+
Enum(DagRunTriggeredByType, native_enum=False, length=50), nullable=True
162162
) # Airflow component that triggered the run.
163163
triggering_user_name: Mapped[str | None] = mapped_column(
164164
String(512),
165165
nullable=True,
166166
) # The user that triggered the DagRun, if applicable
167-
conf: Mapped[dict[str, Any]] = mapped_column(JSON().with_variant(postgresql.JSONB, "postgresql"))
167+
conf: Mapped[dict[str, Any] | None] = mapped_column(
168+
JSON().with_variant(postgresql.JSONB, "postgresql"), nullable=True
169+
)
168170
# These two must be either both NULL or both datetime.
169-
data_interval_start: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
170-
data_interval_end: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
171+
data_interval_start: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
172+
data_interval_end: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
171173
# Earliest time when this DagRun can start running.
172174
run_after: Mapped[UtcDateTime] = mapped_column(UtcDateTime, default=_default_run_after, nullable=False)
173175
# When a scheduler last attempted to schedule TIs for this DagRun
174-
last_scheduling_decision: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
176+
last_scheduling_decision: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
175177
# Foreign key to LogTemplate. DagRun rows created prior to this column's
176178
# existence have this set to NULL. Later rows automatically populate this on
177179
# insert to point to the latest LogTemplate entry.
@@ -193,11 +195,13 @@ class DagRun(Base, LoggingMixin):
193195
194196
It's possible this could change if e.g. the dag run is cleared to be rerun, or perhaps re-backfilled.
195197
"""
196-
bundle_version: Mapped[str] = mapped_column(StringID())
198+
bundle_version: Mapped[str | None] = mapped_column(StringID(), nullable=True)
197199

198-
scheduled_by_job_id: Mapped[int] = mapped_column(Integer)
200+
scheduled_by_job_id: Mapped[int | None] = mapped_column(Integer, nullable=True)
199201
# Span context carrier, used for context propagation.
200-
context_carrier: Mapped[dict[str, Any]] = mapped_column(MutableDict.as_mutable(ExtendedJSON))
202+
context_carrier: Mapped[dict[str, Any] | None] = mapped_column(
203+
MutableDict.as_mutable(ExtendedJSON), nullable=True
204+
)
201205
span_status: Mapped[str] = mapped_column(
202206
String(250), server_default=SpanStatus.NOT_STARTED, nullable=False
203207
)

airflow-core/src/airflow/models/db_callback_request.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,13 @@
2121
from typing import TYPE_CHECKING
2222

2323
from sqlalchemy import Integer, String
24+
from sqlalchemy.orm import Mapped
2425

2526
from airflow._shared.timezones import timezone
2627
from airflow.models.base import Base
2728
from airflow.utils.sqlalchemy import ExtendedJSON, UtcDateTime, mapped_column
2829

2930
if TYPE_CHECKING:
30-
from sqlalchemy.orm import Mapped
31-
3231
from airflow.callbacks.callback_requests import CallbackRequest
3332

3433

airflow-core/src/airflow/models/deadline.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ class Deadline(Base):
100100
id: Mapped[str] = mapped_column(UUIDType(binary=False), primary_key=True, default=uuid6.uuid7)
101101

102102
# If the Deadline Alert is for a DAG, store the DAG run ID from the dag_run.
103-
dagrun_id: Mapped[int] = mapped_column(Integer, ForeignKey("dag_run.id", ondelete="CASCADE"))
103+
dagrun_id: Mapped[int | None] = mapped_column(
104+
Integer, ForeignKey("dag_run.id", ondelete="CASCADE"), nullable=True
105+
)
104106

105107
# The time after which the Deadline has passed and the callback should be triggered.
106108
deadline_time: Mapped[UtcDateTime] = mapped_column(UtcDateTime, nullable=False)
@@ -109,7 +111,7 @@ class Deadline(Base):
109111
"callback", sqlalchemy_jsonfield.JSONField(json=json), nullable=False
110112
)
111113
# The state of the deadline callback
112-
callback_state: Mapped[str] = mapped_column(String(20))
114+
callback_state: Mapped[str | None] = mapped_column(String(20), nullable=True)
113115

114116
dagrun = relationship("DagRun", back_populates="deadlines")
115117

airflow-core/src/airflow/models/errors.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,23 @@
1717
# under the License.
1818
from __future__ import annotations
1919

20-
from typing import TYPE_CHECKING
21-
2220
from sqlalchemy import Integer, String, Text
21+
from sqlalchemy.orm import Mapped
2322

2423
from airflow.dag_processing.bundles.manager import DagBundlesManager
2524
from airflow.models.base import Base, StringID
2625
from airflow.utils.sqlalchemy import UtcDateTime, mapped_column
2726

28-
if TYPE_CHECKING:
29-
from sqlalchemy.orm import Mapped
30-
3127

3228
class ParseImportError(Base):
3329
"""Stores all Import Errors which are recorded when parsing DAGs and displayed on the Webserver."""
3430

3531
__tablename__ = "import_error"
3632
id: Mapped[int] = mapped_column(Integer, primary_key=True)
37-
timestamp: Mapped[UtcDateTime] = mapped_column(UtcDateTime)
38-
filename: Mapped[str] = mapped_column(String(1024))
39-
bundle_name: Mapped[str] = mapped_column(StringID())
40-
stacktrace: Mapped[str] = mapped_column(Text)
33+
timestamp: Mapped[UtcDateTime | None] = mapped_column(UtcDateTime, nullable=True)
34+
filename: Mapped[str | None] = mapped_column(String(1024), nullable=True)
35+
bundle_name: Mapped[str | None] = mapped_column(StringID(), nullable=True)
36+
stacktrace: Mapped[str | None] = mapped_column(Text, nullable=True)
4137

4238
def full_file_path(self) -> str:
4339
"""Return the full file path of the dag."""

0 commit comments

Comments
 (0)