diff --git a/.gitignore b/.gitignore index 6769e21..8761d73 100644 --- a/.gitignore +++ b/.gitignore @@ -152,6 +152,9 @@ dmypy.json # Cython debug symbols cython_debug/ +#MacOS +.DS_Store + # PyCharm # JetBrains specific template is maintained in a separate JetBrains.gitignore that can # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore diff --git a/README.md b/README.md index cfc0f17..ac58a88 100644 --- a/README.md +++ b/README.md @@ -103,11 +103,11 @@ configuration.yaml ## Details The states are stored in a single table ([hypertable](https://docs.timescale.com/latest/using-timescaledb/hypertables), when TimescaleDB is available) with the following layout: -| Column name: | id | time | entity_id | state | attributes | location [PostGIS-only] | -|:---|:---:|:---:|:---:|:---:|:---:|:-----------------------:| -| Type: | bigint | timestamp with timezone | string | string | JSONB | POINT(4326) | +| Column name: | time | entity_id | state | attributes | location [PostGIS-only] | +|:---:|:---:|:---:|:---:|:---:|:-----------------------:| +| Type: | timestamp with timezone | string | string | JSONB | POINT(4326) | | Primary key: | x | x | | | | -| Index: | x | x | x | x | x | | +| Index: | x | x | x | x | | ### Only available with TimescaleDB: [Chunk size](https://docs.timescale.com/latest/using-timescaledb/hypertables#best-practices) of the hypertable is configurable using the `chunk_time_interval` config option. It defaults to 2592000000000 microseconds (30 days). diff --git a/custom_components/ltss/manifest.json b/custom_components/ltss/manifest.json index f1e9607..0a096c0 100644 --- a/custom_components/ltss/manifest.json +++ b/custom_components/ltss/manifest.json @@ -1,6 +1,6 @@ { "domain": "ltss", - "version": "2.0.1", + "version": "2.1.0", "name": "Long Time State Storage (LTSS)", "documentation": "https://github.com/freol35241/ltss", "requirements": [ diff --git a/custom_components/ltss/migrations.py b/custom_components/ltss/migrations.py index db47ad1..52979fc 100644 --- a/custom_components/ltss/migrations.py +++ b/custom_components/ltss/migrations.py @@ -46,6 +46,13 @@ def index_exists(index_name): _LOGGER.warning("Index on entity_id no longer needed, dropping...") drop_entityid_index(engine) + # id column? + if any(col["name"] == "id" for col in columns): + _LOGGER.warning( + "Migrating you LTSS table to the latest schema, this might take a couple of minutes!" + ) + remove_id_column(engine) + def migrate_attributes_text_to_jsonb(engine): with engine.connect() as con: @@ -75,3 +82,22 @@ def drop_entityid_index(engine): autocommit=True ) ) + + +def remove_id_column(engine): + with engine.begin() as con: + con.execute( + text( + f"""ALTER TABLE {LTSS.__tablename__} + DROP CONSTRAINT {LTSS.__tablename__}_pkey CASCADE, + ADD PRIMARY KEY(time,entity_id);""" + ) + ) + con.execute( + text( + f"""ALTER TABLE {LTSS.__tablename__} + DROP COLUMN id""" + ) + ) + con.commit() + _LOGGER.info("Migration completed successfully!") diff --git a/custom_components/ltss/models.py b/custom_components/ltss/models.py index 53b3bbe..87381c5 100644 --- a/custom_components/ltss/models.py +++ b/custom_components/ltss/models.py @@ -27,9 +27,8 @@ class LTSS(Base): # type: ignore """State change history.""" __tablename__ = "ltss" - id = Column(BigInteger, primary_key=True, autoincrement=True) time = Column(DateTime(timezone=True), default=datetime.utcnow, primary_key=True) - entity_id = Column(String(255)) + entity_id = Column(String(255), primary_key=True) state = Column(String(255), index=True) attributes = Column(JSONB) location = None # when not activated, no location column will be added to the table/database diff --git a/tests/pytest/test_databases.py b/tests/pytest/test_databases.py index 298f7ca..b2a5770 100644 --- a/tests/pytest/test_databases.py +++ b/tests/pytest/test_databases.py @@ -128,7 +128,7 @@ def _is_hypertable(con): @staticmethod def _has_columns(con): return ( - 5 + 4 <= con.execute( text( f"SELECT COLUMN_NAME\