Add initial project
This commit is contained in:
@@ -0,0 +1 @@
|
||||
Generic single-database configuration.
|
||||
@@ -0,0 +1,91 @@
|
||||
from logging.config import fileConfig
|
||||
|
||||
from sqlalchemy import engine_from_config
|
||||
from sqlalchemy import pool
|
||||
|
||||
from alembic import context
|
||||
|
||||
# this is the Alembic Config object, which provides
|
||||
# access to the values within the .ini file in use.
|
||||
config = context.config
|
||||
|
||||
# Interpret the config file for Python logging.
|
||||
# This line sets up loggers basically.
|
||||
if config.config_file_name is not None:
|
||||
fileConfig(config.config_file_name)
|
||||
|
||||
import os
|
||||
import sys
|
||||
sys.path.append(os.getcwd())
|
||||
|
||||
# Import Base and all models to ensure they're registered with metadata
|
||||
from backend.database import Base
|
||||
from backend import models # This imports all models via __init__.py
|
||||
|
||||
# add your model's MetaData object here
|
||||
# for 'autogenerate' support
|
||||
# from myapp import mymodel
|
||||
# target_metadata = mymodel.Base.metadata
|
||||
target_metadata = Base.metadata
|
||||
|
||||
# other values from the config, defined by the needs of env.py,
|
||||
# can be acquired:
|
||||
# my_important_option = config.get_main_option("my_important_option")
|
||||
# ... etc.
|
||||
|
||||
|
||||
def run_migrations_offline() -> None:
|
||||
"""Run migrations in 'offline' mode.
|
||||
|
||||
This configures the context with just a URL
|
||||
and not an Engine, though an Engine is acceptable
|
||||
here as well. By skipping the Engine creation
|
||||
we don't even need a DBAPI to be available.
|
||||
|
||||
Calls to context.execute() here emit the given string to the
|
||||
script output.
|
||||
|
||||
"""
|
||||
url = config.get_main_option("sqlalchemy.url")
|
||||
context.configure(
|
||||
url=url,
|
||||
target_metadata=target_metadata,
|
||||
literal_binds=True,
|
||||
dialect_opts={"paramstyle": "named"},
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
def run_migrations_online() -> None:
|
||||
"""Run migrations in 'online' mode.
|
||||
|
||||
In this scenario we need to create an Engine
|
||||
and associate a connection with the context.
|
||||
|
||||
"""
|
||||
# Override URL from settings
|
||||
from backend.core.config import settings
|
||||
configuration = config.get_section(config.config_ini_section, {})
|
||||
configuration["sqlalchemy.url"] = settings.DATABASE_URL
|
||||
|
||||
connectable = engine_from_config(
|
||||
configuration,
|
||||
prefix="sqlalchemy.",
|
||||
poolclass=pool.NullPool,
|
||||
)
|
||||
|
||||
with connectable.connect() as connection:
|
||||
context.configure(
|
||||
connection=connection, target_metadata=target_metadata
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
if context.is_offline_mode():
|
||||
run_migrations_offline()
|
||||
else:
|
||||
run_migrations_online()
|
||||
@@ -0,0 +1,28 @@
|
||||
"""${message}
|
||||
|
||||
Revision ID: ${up_revision}
|
||||
Revises: ${down_revision | comma,n}
|
||||
Create Date: ${create_date}
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
${imports if imports else ""}
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = ${repr(up_revision)}
|
||||
down_revision: Union[str, Sequence[str], None] = ${repr(down_revision)}
|
||||
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
|
||||
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
${upgrades if upgrades else "pass"}
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
${downgrades if downgrades else "pass"}
|
||||
@@ -0,0 +1,34 @@
|
||||
"""Add icon and image_url
|
||||
|
||||
Revision ID: 4cc2e86d9794
|
||||
Revises: 8ba5ee682bc1
|
||||
Create Date: 2025-12-27 23:38:43.414279
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '4cc2e86d9794'
|
||||
down_revision: Union[str, Sequence[str], None] = '8ba5ee682bc1'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('challenges', sa.Column('icon', sa.String(), nullable=True))
|
||||
op.add_column('challenges', sa.Column('image_url', sa.String(), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('challenges', 'image_url')
|
||||
op.drop_column('challenges', 'icon')
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,32 @@
|
||||
"""Add description
|
||||
|
||||
Revision ID: 5ea126309171
|
||||
Revises: 4cc2e86d9794
|
||||
Create Date: 2025-12-28 00:11:14.788582
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '5ea126309171'
|
||||
down_revision: Union[str, Sequence[str], None] = '4cc2e86d9794'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('challenges', sa.Column('description', sa.String(), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('challenges', 'description')
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,32 @@
|
||||
"""Add awake_duration_minutes to daily health metrics
|
||||
|
||||
Revision ID: 6c3fce1dd49a
|
||||
Revises: d208fd79a572
|
||||
Create Date: 2025-12-29 13:49:31.181979
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '6c3fce1dd49a'
|
||||
down_revision: Union[str, Sequence[str], None] = 'd208fd79a572'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('daily_health_metrics', sa.Column('awake_duration_minutes', sa.Integer(), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('daily_health_metrics', 'awake_duration_minutes')
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,34 @@
|
||||
"""Add unit_type and rest_days
|
||||
|
||||
Revision ID: 8ba5ee682bc1
|
||||
Revises:
|
||||
Create Date: 2025-12-27 22:29:05.909161
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '8ba5ee682bc1'
|
||||
down_revision: Union[str, Sequence[str], None] = None
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('challenges', sa.Column('unit_type', sa.String(), nullable=True))
|
||||
op.add_column('challenges', sa.Column('rest_days', sa.String(), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('challenges', 'rest_days')
|
||||
op.drop_column('challenges', 'unit_type')
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,41 @@
|
||||
"""Add data_source columns for provider tracking
|
||||
|
||||
Revision ID: a1b2c3d4e5f6
|
||||
Revises: 6c3fce1dd49a
|
||||
Create Date: 2026-01-01 14:30:00.000000
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'a1b2c3d4e5f6'
|
||||
down_revision: Union[str, None] = '6c3fce1dd49a'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# Add data_source column to daily_health_metrics
|
||||
op.add_column(
|
||||
'daily_health_metrics',
|
||||
sa.Column('data_source', sa.String(50), nullable=True, server_default='google_fit')
|
||||
)
|
||||
|
||||
# Add data_source column to workout_sessions
|
||||
op.add_column(
|
||||
'workout_sessions',
|
||||
sa.Column('data_source', sa.String(50), nullable=True, server_default='google_fit')
|
||||
)
|
||||
|
||||
# Update existing rows to have default value
|
||||
op.execute("UPDATE daily_health_metrics SET data_source = 'google_fit' WHERE data_source IS NULL")
|
||||
op.execute("UPDATE workout_sessions SET data_source = 'google_fit' WHERE data_source IS NULL")
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column('daily_health_metrics', 'data_source')
|
||||
op.drop_column('workout_sessions', 'data_source')
|
||||
@@ -0,0 +1,103 @@
|
||||
"""Add Health Connect tables
|
||||
|
||||
Revision ID: b2c3d4e5f6g7
|
||||
Revises: a1b2c3d4e5f6
|
||||
Create Date: 2026-01-01 14:35:00.000000
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'b2c3d4e5f6g7'
|
||||
down_revision: Union[str, None] = 'a1b2c3d4e5f6'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# Create health_connect_sync_logs table
|
||||
op.create_table(
|
||||
'health_connect_sync_logs',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('device_id', sa.String(100), nullable=True),
|
||||
sa.Column('sync_timestamp', sa.DateTime(), nullable=True),
|
||||
sa.Column('records_pushed', sa.Integer(), nullable=True),
|
||||
sa.Column('status', sa.String(50), nullable=True),
|
||||
sa.Column('error_message', sa.Text(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index('ix_health_connect_sync_logs_id', 'health_connect_sync_logs', ['id'])
|
||||
op.create_index('ix_health_connect_sync_logs_user_id', 'health_connect_sync_logs', ['user_id'])
|
||||
|
||||
# Create health_connect_daily_metrics table
|
||||
op.create_table(
|
||||
'health_connect_daily_metrics',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('date', sa.Date(), nullable=True),
|
||||
sa.Column('step_count', sa.Integer(), nullable=True),
|
||||
sa.Column('distance_meters', sa.Float(), nullable=True),
|
||||
sa.Column('calories_burned', sa.Float(), nullable=True),
|
||||
sa.Column('total_calories', sa.Float(), nullable=True),
|
||||
sa.Column('sleep_duration_minutes', sa.Integer(), nullable=True),
|
||||
sa.Column('deep_sleep_minutes', sa.Integer(), nullable=True),
|
||||
sa.Column('light_sleep_minutes', sa.Integer(), nullable=True),
|
||||
sa.Column('rem_sleep_minutes', sa.Integer(), nullable=True),
|
||||
sa.Column('awake_duration_minutes', sa.Integer(), nullable=True),
|
||||
sa.Column('avg_heart_rate', sa.Integer(), nullable=True),
|
||||
sa.Column('min_heart_rate', sa.Integer(), nullable=True),
|
||||
sa.Column('max_heart_rate', sa.Integer(), nullable=True),
|
||||
sa.Column('resting_heart_rate', sa.Integer(), nullable=True),
|
||||
sa.Column('avg_spo2', sa.Float(), nullable=True),
|
||||
sa.Column('min_spo2', sa.Float(), nullable=True),
|
||||
sa.Column('max_spo2', sa.Float(), nullable=True),
|
||||
sa.Column('weight', sa.Float(), nullable=True),
|
||||
sa.Column('last_synced', sa.DateTime(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index('ix_health_connect_daily_metrics_id', 'health_connect_daily_metrics', ['id'])
|
||||
op.create_index('ix_health_connect_daily_metrics_user_id', 'health_connect_daily_metrics', ['user_id'])
|
||||
op.create_index('ix_health_connect_daily_metrics_date', 'health_connect_daily_metrics', ['date'])
|
||||
|
||||
# Create health_connect_exercise_sessions table
|
||||
op.create_table(
|
||||
'health_connect_exercise_sessions',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('start_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('end_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('exercise_type', sa.Integer(), nullable=True),
|
||||
sa.Column('exercise_type_name', sa.String(100), nullable=True),
|
||||
sa.Column('duration_seconds', sa.Integer(), nullable=True),
|
||||
sa.Column('distance_meters', sa.Float(), nullable=True),
|
||||
sa.Column('calories_burned', sa.Float(), nullable=True),
|
||||
sa.Column('avg_heart_rate', sa.Integer(), nullable=True),
|
||||
sa.Column('max_heart_rate', sa.Integer(), nullable=True),
|
||||
sa.Column('min_heart_rate', sa.Integer(), nullable=True),
|
||||
sa.Column('steps', sa.Integer(), nullable=True),
|
||||
sa.Column('elevation_gained', sa.Float(), nullable=True),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('last_synced', sa.DateTime(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index('ix_health_connect_exercise_sessions_id', 'health_connect_exercise_sessions', ['id'])
|
||||
op.create_index('ix_health_connect_exercise_sessions_user_id', 'health_connect_exercise_sessions', ['user_id'])
|
||||
op.create_index('ix_health_connect_exercise_sessions_start_time', 'health_connect_exercise_sessions', ['start_time'])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_table('health_connect_exercise_sessions')
|
||||
op.drop_table('health_connect_daily_metrics')
|
||||
op.drop_table('health_connect_sync_logs')
|
||||
@@ -0,0 +1,36 @@
|
||||
"""Add Zepp fields
|
||||
|
||||
Revision ID: c3049b0cefc4
|
||||
Revises: 6c3fce1dd49a
|
||||
Create Date: 2025-12-29 17:26:48.144904
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'c3049b0cefc4'
|
||||
down_revision: Union[str, Sequence[str], None] = '6c3fce1dd49a'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('daily_health_metrics', sa.Column('weight', sa.Float(), nullable=True))
|
||||
op.add_column('daily_health_metrics', sa.Column('resting_heart_rate', sa.Integer(), nullable=True))
|
||||
op.add_column('daily_health_metrics', sa.Column('hrv', sa.Float(), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('daily_health_metrics', 'hrv')
|
||||
op.drop_column('daily_health_metrics', 'resting_heart_rate')
|
||||
op.drop_column('daily_health_metrics', 'weight')
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,34 @@
|
||||
"""Add_frequency_fields
|
||||
|
||||
Revision ID: d208fd79a572
|
||||
Revises: 5ea126309171
|
||||
Create Date: 2025-12-28 12:59:55.198335
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'd208fd79a572'
|
||||
down_revision: Union[str, Sequence[str], None] = '5ea126309171'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('challenges', sa.Column('frequency_count', sa.Integer(), nullable=True))
|
||||
op.add_column('challenges', sa.Column('selected_days', sa.String(), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('challenges', 'selected_days')
|
||||
op.drop_column('challenges', 'frequency_count')
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,51 @@
|
||||
"""Add data_source columns to health_connect_daily_metrics
|
||||
|
||||
Revision ID: e4f5g6h7i8j9
|
||||
Revises: b2c3d4e5f6g7
|
||||
Create Date: 2026-01-07 15:40:00.000000
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'e4f5g6h7i8j9'
|
||||
down_revision: Union[str, None] = 'b2c3d4e5f6g7'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# Add data_source column to health_connect_daily_metrics
|
||||
op.add_column(
|
||||
'health_connect_daily_metrics',
|
||||
sa.Column('data_source', sa.String(200), nullable=True)
|
||||
)
|
||||
|
||||
# Add data_source_name column to health_connect_daily_metrics
|
||||
op.add_column(
|
||||
'health_connect_daily_metrics',
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True)
|
||||
)
|
||||
|
||||
# Add data_source column to health_connect_exercise_sessions
|
||||
op.add_column(
|
||||
'health_connect_exercise_sessions',
|
||||
sa.Column('data_source', sa.String(200), nullable=True)
|
||||
)
|
||||
|
||||
# Add data_source_name column to health_connect_exercise_sessions
|
||||
op.add_column(
|
||||
'health_connect_exercise_sessions',
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True)
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column('health_connect_daily_metrics', 'data_source')
|
||||
op.drop_column('health_connect_daily_metrics', 'data_source_name')
|
||||
op.drop_column('health_connect_exercise_sessions', 'data_source')
|
||||
op.drop_column('health_connect_exercise_sessions', 'data_source_name')
|
||||
@@ -0,0 +1,391 @@
|
||||
"""Add Health Connect raw data tables
|
||||
|
||||
Revision ID: f5g6h7i8j9k0
|
||||
Revises: e4f5g6h7i8j9
|
||||
Create Date: 2026-01-08 12:00:00.000000
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'f5g6h7i8j9k0'
|
||||
down_revision = 'e4f5g6h7i8j9'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# === Steps ===
|
||||
op.create_table(
|
||||
'hc_raw_steps',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('start_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('end_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('count', sa.Integer(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_steps_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_steps_id', 'hc_raw_steps', ['id'])
|
||||
op.create_index('ix_hc_raw_steps_user_id', 'hc_raw_steps', ['user_id'])
|
||||
op.create_index('ix_hc_raw_steps_record_id', 'hc_raw_steps', ['record_id'])
|
||||
op.create_index('ix_hc_raw_steps_start_time', 'hc_raw_steps', ['start_time'])
|
||||
op.create_index('ix_steps_user_date', 'hc_raw_steps', ['user_id', 'start_time'])
|
||||
|
||||
# === Heart Rate ===
|
||||
op.create_table(
|
||||
'hc_raw_heart_rate',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('start_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('end_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_hr_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_heart_rate_id', 'hc_raw_heart_rate', ['id'])
|
||||
op.create_index('ix_hc_raw_heart_rate_user_id', 'hc_raw_heart_rate', ['user_id'])
|
||||
op.create_index('ix_hc_raw_heart_rate_record_id', 'hc_raw_heart_rate', ['record_id'])
|
||||
op.create_index('ix_hc_raw_heart_rate_start_time', 'hc_raw_heart_rate', ['start_time'])
|
||||
op.create_index('ix_hr_user_date', 'hc_raw_heart_rate', ['user_id', 'start_time'])
|
||||
|
||||
# === Heart Rate Samples ===
|
||||
op.create_table(
|
||||
'hc_raw_heart_rate_samples',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('record_id', sa.Integer(), nullable=True),
|
||||
sa.Column('time', sa.DateTime(), nullable=True),
|
||||
sa.Column('bpm', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['record_id'], ['hc_raw_heart_rate.id'], ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index('ix_hc_raw_heart_rate_samples_id', 'hc_raw_heart_rate_samples', ['id'])
|
||||
op.create_index('ix_hc_raw_heart_rate_samples_record_id', 'hc_raw_heart_rate_samples', ['record_id'])
|
||||
op.create_index('ix_hc_raw_heart_rate_samples_time', 'hc_raw_heart_rate_samples', ['time'])
|
||||
|
||||
# === Resting Heart Rate ===
|
||||
op.create_table(
|
||||
'hc_raw_resting_hr',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('bpm', sa.Integer(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_resting_hr_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_resting_hr_id', 'hc_raw_resting_hr', ['id'])
|
||||
op.create_index('ix_hc_raw_resting_hr_user_id', 'hc_raw_resting_hr', ['user_id'])
|
||||
op.create_index('ix_hc_raw_resting_hr_record_id', 'hc_raw_resting_hr', ['record_id'])
|
||||
op.create_index('ix_hc_raw_resting_hr_time', 'hc_raw_resting_hr', ['time'])
|
||||
op.create_index('ix_resting_hr_user_date', 'hc_raw_resting_hr', ['user_id', 'time'])
|
||||
|
||||
# === Sleep Sessions ===
|
||||
op.create_table(
|
||||
'hc_raw_sleep_sessions',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('start_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('end_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('title', sa.String(200), nullable=True),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_sleep_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_sleep_sessions_id', 'hc_raw_sleep_sessions', ['id'])
|
||||
op.create_index('ix_hc_raw_sleep_sessions_user_id', 'hc_raw_sleep_sessions', ['user_id'])
|
||||
op.create_index('ix_hc_raw_sleep_sessions_record_id', 'hc_raw_sleep_sessions', ['record_id'])
|
||||
op.create_index('ix_hc_raw_sleep_sessions_start_time', 'hc_raw_sleep_sessions', ['start_time'])
|
||||
op.create_index('ix_sleep_user_date', 'hc_raw_sleep_sessions', ['user_id', 'start_time'])
|
||||
|
||||
# === Sleep Stages ===
|
||||
op.create_table(
|
||||
'hc_raw_sleep_stages',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('session_id', sa.Integer(), nullable=True),
|
||||
sa.Column('start_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('end_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('stage_type', sa.Integer(), nullable=True),
|
||||
sa.Column('stage_name', sa.String(50), nullable=True),
|
||||
sa.ForeignKeyConstraint(['session_id'], ['hc_raw_sleep_sessions.id'], ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index('ix_hc_raw_sleep_stages_id', 'hc_raw_sleep_stages', ['id'])
|
||||
op.create_index('ix_hc_raw_sleep_stages_session_id', 'hc_raw_sleep_stages', ['session_id'])
|
||||
|
||||
# === Distance ===
|
||||
op.create_table(
|
||||
'hc_raw_distance',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('start_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('end_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('distance_meters', sa.Float(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_distance_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_distance_id', 'hc_raw_distance', ['id'])
|
||||
op.create_index('ix_hc_raw_distance_user_id', 'hc_raw_distance', ['user_id'])
|
||||
op.create_index('ix_hc_raw_distance_record_id', 'hc_raw_distance', ['record_id'])
|
||||
op.create_index('ix_hc_raw_distance_start_time', 'hc_raw_distance', ['start_time'])
|
||||
op.create_index('ix_distance_user_date', 'hc_raw_distance', ['user_id', 'start_time'])
|
||||
|
||||
# === Calories ===
|
||||
op.create_table(
|
||||
'hc_raw_calories',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('start_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('end_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('calories', sa.Float(), nullable=True),
|
||||
sa.Column('record_type', sa.String(20), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_calories_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_calories_id', 'hc_raw_calories', ['id'])
|
||||
op.create_index('ix_hc_raw_calories_user_id', 'hc_raw_calories', ['user_id'])
|
||||
op.create_index('ix_hc_raw_calories_record_id', 'hc_raw_calories', ['record_id'])
|
||||
op.create_index('ix_hc_raw_calories_start_time', 'hc_raw_calories', ['start_time'])
|
||||
op.create_index('ix_calories_user_date', 'hc_raw_calories', ['user_id', 'start_time'])
|
||||
|
||||
# === Oxygen Saturation (SpO2) ===
|
||||
op.create_table(
|
||||
'hc_raw_spo2',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('percentage', sa.Float(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_spo2_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_spo2_id', 'hc_raw_spo2', ['id'])
|
||||
op.create_index('ix_hc_raw_spo2_user_id', 'hc_raw_spo2', ['user_id'])
|
||||
op.create_index('ix_hc_raw_spo2_record_id', 'hc_raw_spo2', ['record_id'])
|
||||
op.create_index('ix_hc_raw_spo2_time', 'hc_raw_spo2', ['time'])
|
||||
op.create_index('ix_spo2_user_date', 'hc_raw_spo2', ['user_id', 'time'])
|
||||
|
||||
# === Weight ===
|
||||
op.create_table(
|
||||
'hc_raw_weight',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('weight_kg', sa.Float(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_weight_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_weight_id', 'hc_raw_weight', ['id'])
|
||||
op.create_index('ix_hc_raw_weight_user_id', 'hc_raw_weight', ['user_id'])
|
||||
op.create_index('ix_hc_raw_weight_record_id', 'hc_raw_weight', ['record_id'])
|
||||
op.create_index('ix_hc_raw_weight_time', 'hc_raw_weight', ['time'])
|
||||
op.create_index('ix_weight_user_date', 'hc_raw_weight', ['user_id', 'time'])
|
||||
|
||||
# === Height ===
|
||||
op.create_table(
|
||||
'hc_raw_height',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('height_meters', sa.Float(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_height_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_height_id', 'hc_raw_height', ['id'])
|
||||
op.create_index('ix_hc_raw_height_user_id', 'hc_raw_height', ['user_id'])
|
||||
op.create_index('ix_hc_raw_height_record_id', 'hc_raw_height', ['record_id'])
|
||||
op.create_index('ix_hc_raw_height_time', 'hc_raw_height', ['time'])
|
||||
op.create_index('ix_height_user_date', 'hc_raw_height', ['user_id', 'time'])
|
||||
|
||||
# === Body Fat ===
|
||||
op.create_table(
|
||||
'hc_raw_body_fat',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('percentage', sa.Float(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_body_fat_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_body_fat_id', 'hc_raw_body_fat', ['id'])
|
||||
op.create_index('ix_hc_raw_body_fat_user_id', 'hc_raw_body_fat', ['user_id'])
|
||||
op.create_index('ix_hc_raw_body_fat_record_id', 'hc_raw_body_fat', ['record_id'])
|
||||
op.create_index('ix_hc_raw_body_fat_time', 'hc_raw_body_fat', ['time'])
|
||||
op.create_index('ix_body_fat_user_date', 'hc_raw_body_fat', ['user_id', 'time'])
|
||||
|
||||
# === Exercise Sessions ===
|
||||
op.create_table(
|
||||
'hc_raw_exercise_sessions',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('start_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('end_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('exercise_type', sa.Integer(), nullable=True),
|
||||
sa.Column('exercise_type_name', sa.String(100), nullable=True),
|
||||
sa.Column('title', sa.String(200), nullable=True),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('distance_meters', sa.Float(), nullable=True),
|
||||
sa.Column('calories', sa.Float(), nullable=True),
|
||||
sa.Column('avg_heart_rate', sa.Integer(), nullable=True),
|
||||
sa.Column('max_heart_rate', sa.Integer(), nullable=True),
|
||||
sa.Column('min_heart_rate', sa.Integer(), nullable=True),
|
||||
sa.Column('steps', sa.Integer(), nullable=True),
|
||||
sa.Column('elevation_gained_meters', sa.Float(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_exercise_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_exercise_sessions_id', 'hc_raw_exercise_sessions', ['id'])
|
||||
op.create_index('ix_hc_raw_exercise_sessions_user_id', 'hc_raw_exercise_sessions', ['user_id'])
|
||||
op.create_index('ix_hc_raw_exercise_sessions_record_id', 'hc_raw_exercise_sessions', ['record_id'])
|
||||
op.create_index('ix_hc_raw_exercise_sessions_start_time', 'hc_raw_exercise_sessions', ['start_time'])
|
||||
op.create_index('ix_exercise_user_date', 'hc_raw_exercise_sessions', ['user_id', 'start_time'])
|
||||
|
||||
# === Nutrition ===
|
||||
op.create_table(
|
||||
'hc_raw_nutrition',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('start_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('end_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('name', sa.String(200), nullable=True),
|
||||
sa.Column('meal_type', sa.Integer(), nullable=True),
|
||||
sa.Column('calories', sa.Float(), nullable=True),
|
||||
sa.Column('protein_grams', sa.Float(), nullable=True),
|
||||
sa.Column('carbohydrates_grams', sa.Float(), nullable=True),
|
||||
sa.Column('fat_grams', sa.Float(), nullable=True),
|
||||
sa.Column('fiber_grams', sa.Float(), nullable=True),
|
||||
sa.Column('sugar_grams', sa.Float(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_nutrition_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_nutrition_id', 'hc_raw_nutrition', ['id'])
|
||||
op.create_index('ix_hc_raw_nutrition_user_id', 'hc_raw_nutrition', ['user_id'])
|
||||
op.create_index('ix_hc_raw_nutrition_record_id', 'hc_raw_nutrition', ['record_id'])
|
||||
op.create_index('ix_hc_raw_nutrition_start_time', 'hc_raw_nutrition', ['start_time'])
|
||||
op.create_index('ix_nutrition_user_date', 'hc_raw_nutrition', ['user_id', 'start_time'])
|
||||
|
||||
# === Hydration ===
|
||||
op.create_table(
|
||||
'hc_raw_hydration',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('record_id', sa.String(100), nullable=True),
|
||||
sa.Column('data_source', sa.String(200), nullable=True),
|
||||
sa.Column('data_source_name', sa.String(100), nullable=True),
|
||||
sa.Column('start_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('end_time', sa.DateTime(), nullable=True),
|
||||
sa.Column('synced_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('volume_liters', sa.Float(), nullable=True),
|
||||
sa.Column('sync_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id']),
|
||||
sa.ForeignKeyConstraint(['sync_id'], ['health_connect_sync_logs.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('user_id', 'record_id', 'data_source', name='uq_hydration_record')
|
||||
)
|
||||
op.create_index('ix_hc_raw_hydration_id', 'hc_raw_hydration', ['id'])
|
||||
op.create_index('ix_hc_raw_hydration_user_id', 'hc_raw_hydration', ['user_id'])
|
||||
op.create_index('ix_hc_raw_hydration_record_id', 'hc_raw_hydration', ['record_id'])
|
||||
op.create_index('ix_hc_raw_hydration_start_time', 'hc_raw_hydration', ['start_time'])
|
||||
op.create_index('ix_hydration_user_date', 'hc_raw_hydration', ['user_id', 'start_time'])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# Drop all raw data tables
|
||||
op.drop_table('hc_raw_hydration')
|
||||
op.drop_table('hc_raw_nutrition')
|
||||
op.drop_table('hc_raw_exercise_sessions')
|
||||
op.drop_table('hc_raw_body_fat')
|
||||
op.drop_table('hc_raw_height')
|
||||
op.drop_table('hc_raw_weight')
|
||||
op.drop_table('hc_raw_spo2')
|
||||
op.drop_table('hc_raw_calories')
|
||||
op.drop_table('hc_raw_distance')
|
||||
op.drop_table('hc_raw_sleep_stages')
|
||||
op.drop_table('hc_raw_sleep_sessions')
|
||||
op.drop_table('hc_raw_resting_hr')
|
||||
op.drop_table('hc_raw_heart_rate_samples')
|
||||
op.drop_table('hc_raw_heart_rate')
|
||||
op.drop_table('hc_raw_steps')
|
||||
Reference in New Issue
Block a user