database.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. """
  2. Database connection and initialization module.
  3. Manages SQLite database connection and table creation.
  4. """
  5. import sqlite3
  6. import os
  7. from contextlib import contextmanager
  8. from typing import Generator
  9. # Database file path
  10. DB_PATH = os.getenv("DATABASE_PATH", "annotation_platform.db")
  11. @contextmanager
  12. def get_db_connection() -> Generator[sqlite3.Connection, None, None]:
  13. """
  14. Context manager for database connections.
  15. Ensures proper connection cleanup.
  16. """
  17. conn = sqlite3.connect(DB_PATH)
  18. conn.row_factory = sqlite3.Row # Enable column access by name
  19. conn.execute("PRAGMA foreign_keys = ON") # Enable foreign key constraints
  20. try:
  21. yield conn
  22. conn.commit()
  23. except Exception:
  24. conn.rollback()
  25. raise
  26. finally:
  27. conn.close()
  28. def init_database() -> None:
  29. """
  30. Initialize database and create tables if they don't exist.
  31. Creates projects, tasks, and annotations tables with proper relationships.
  32. """
  33. with get_db_connection() as conn:
  34. cursor = conn.cursor()
  35. # Enable foreign key constraints
  36. cursor.execute("PRAGMA foreign_keys = ON")
  37. # Create projects table
  38. cursor.execute("""
  39. CREATE TABLE IF NOT EXISTS projects (
  40. id TEXT PRIMARY KEY,
  41. name TEXT NOT NULL,
  42. description TEXT,
  43. config TEXT NOT NULL,
  44. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  45. )
  46. """)
  47. # Create tasks table
  48. cursor.execute("""
  49. CREATE TABLE IF NOT EXISTS tasks (
  50. id TEXT PRIMARY KEY,
  51. project_id TEXT NOT NULL,
  52. name TEXT NOT NULL,
  53. data TEXT NOT NULL,
  54. status TEXT DEFAULT 'pending',
  55. assigned_to TEXT,
  56. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  57. FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
  58. )
  59. """)
  60. # Create annotations table
  61. cursor.execute("""
  62. CREATE TABLE IF NOT EXISTS annotations (
  63. id TEXT PRIMARY KEY,
  64. task_id TEXT NOT NULL,
  65. user_id TEXT NOT NULL,
  66. result TEXT NOT NULL,
  67. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  68. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  69. FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE
  70. )
  71. """)
  72. conn.commit()
  73. def get_db() -> sqlite3.Connection:
  74. """
  75. Get a database connection.
  76. Note: Caller is responsible for closing the connection.
  77. """
  78. conn = sqlite3.connect(DB_PATH)
  79. conn.row_factory = sqlite3.Row
  80. conn.execute("PRAGMA foreign_keys = ON")
  81. return conn