diff --git a/homeassistant/components/recorder/db_schema.py b/homeassistant/components/recorder/db_schema.py index 2e9e71f04f2..8a1de979641 100644 --- a/homeassistant/components/recorder/db_schema.py +++ b/homeassistant/components/recorder/db_schema.py @@ -166,6 +166,14 @@ class FAST_PYSQLITE_DATETIME(sqlite.DATETIME): return lambda value: None if value is None else ciso8601.parse_datetime(value) +class NativeLargeBinary(LargeBinary): + """A faster version of LargeBinary for engines that support python bytes natively.""" + + def result_processor(self, dialect, coltype): # type: ignore[no-untyped-def] + """No conversion needed for engines that support native bytes.""" + return None + + # For MariaDB and MySQL we can use an unsigned integer type since it will fit 2**32 # for sqlite and postgresql we use a bigint UINT_32_TYPE = BigInteger().with_variant( @@ -191,6 +199,9 @@ DOUBLE_TYPE = ( UNUSED_LEGACY_COLUMN = Unused(0) UNUSED_LEGACY_DATETIME_COLUMN = UnusedDateTime(timezone=True) DOUBLE_PRECISION_TYPE_SQL = "DOUBLE PRECISION" +CONTEXT_BINARY_TYPE = LargeBinary(CONTEXT_ID_BIN_MAX_LENGTH).with_variant( + NativeLargeBinary(CONTEXT_ID_BIN_MAX_LENGTH), "mysql", "mariadb", "sqlite" +) TIMESTAMP_TYPE = DOUBLE_TYPE @@ -243,15 +254,9 @@ class Events(Base): data_id: Mapped[int | None] = mapped_column( Integer, ForeignKey("event_data.data_id"), index=True ) - context_id_bin: Mapped[bytes | None] = mapped_column( - LargeBinary(CONTEXT_ID_BIN_MAX_LENGTH), - ) - context_user_id_bin: Mapped[bytes | None] = mapped_column( - LargeBinary(CONTEXT_ID_BIN_MAX_LENGTH), - ) - context_parent_id_bin: Mapped[bytes | None] = mapped_column( - LargeBinary(CONTEXT_ID_BIN_MAX_LENGTH) - ) + context_id_bin: Mapped[bytes | None] = mapped_column(CONTEXT_BINARY_TYPE) + context_user_id_bin: Mapped[bytes | None] = mapped_column(CONTEXT_BINARY_TYPE) + context_parent_id_bin: Mapped[bytes | None] = mapped_column(CONTEXT_BINARY_TYPE) event_type_id: Mapped[int | None] = mapped_column( Integer, ForeignKey("event_types.event_type_id") ) @@ -435,15 +440,9 @@ class States(Base): ) # 0 is local, 1 is remote old_state: Mapped[States | None] = relationship("States", remote_side=[state_id]) state_attributes: Mapped[StateAttributes | None] = relationship("StateAttributes") - context_id_bin: Mapped[bytes | None] = mapped_column( - LargeBinary(CONTEXT_ID_BIN_MAX_LENGTH), - ) - context_user_id_bin: Mapped[bytes | None] = mapped_column( - LargeBinary(CONTEXT_ID_BIN_MAX_LENGTH), - ) - context_parent_id_bin: Mapped[bytes | None] = mapped_column( - LargeBinary(CONTEXT_ID_BIN_MAX_LENGTH) - ) + context_id_bin: Mapped[bytes | None] = mapped_column(CONTEXT_BINARY_TYPE) + context_user_id_bin: Mapped[bytes | None] = mapped_column(CONTEXT_BINARY_TYPE) + context_parent_id_bin: Mapped[bytes | None] = mapped_column(CONTEXT_BINARY_TYPE) metadata_id: Mapped[int | None] = mapped_column( Integer, ForeignKey("states_meta.metadata_id") )