db.php 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. <?php
  2. // PDO SQLite bootstrap + idempotent schema migrations.
  3. // Call db() from any endpoint to get the connection.
  4. function db(): PDO {
  5. static $pdo = null;
  6. if ($pdo !== null) return $pdo;
  7. $dir = __DIR__ . '/../data';
  8. if (!is_dir($dir)) {
  9. mkdir($dir, 0775, true);
  10. }
  11. $path = $dir . '/pdq.sqlite';
  12. $pdo = new PDO('sqlite:' . $path);
  13. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  14. $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
  15. $pdo->exec('PRAGMA foreign_keys = ON');
  16. $pdo->exec('PRAGMA journal_mode = WAL');
  17. db_migrate($pdo);
  18. return $pdo;
  19. }
  20. function db_migrate(PDO $pdo): void {
  21. $version = (int) $pdo->query('PRAGMA user_version')->fetchColumn();
  22. if ($version < 1) {
  23. $pdo->exec("
  24. CREATE TABLE vendors (
  25. id INTEGER PRIMARY KEY,
  26. slug TEXT NOT NULL UNIQUE,
  27. name TEXT NOT NULL,
  28. active INTEGER NOT NULL DEFAULT 1
  29. );
  30. CREATE TABLE jobs (
  31. id INTEGER PRIMARY KEY,
  32. vendor_id INTEGER NOT NULL REFERENCES vendors(id),
  33. job TEXT NOT NULL DEFAULT 'New',
  34. material TEXT NOT NULL DEFAULT '',
  35. description TEXT NOT NULL DEFAULT '',
  36. qty INTEGER NOT NULL DEFAULT 0,
  37. due_date TEXT,
  38. ack TEXT NOT NULL DEFAULT 'new',
  39. status TEXT NOT NULL DEFAULT '',
  40. created_at TEXT NOT NULL DEFAULT (datetime('now')),
  41. updated_at TEXT NOT NULL DEFAULT (datetime('now'))
  42. );
  43. CREATE INDEX jobs_vendor_status ON jobs(vendor_id, status);
  44. CREATE TABLE job_history (
  45. id INTEGER PRIMARY KEY,
  46. job_id INTEGER NOT NULL REFERENCES jobs(id),
  47. field TEXT NOT NULL,
  48. old_value TEXT,
  49. new_value TEXT,
  50. actor TEXT NOT NULL,
  51. changed_at TEXT NOT NULL DEFAULT (datetime('now'))
  52. );
  53. CREATE INDEX job_history_job ON job_history(job_id, changed_at);
  54. CREATE TABLE messages (
  55. id INTEGER PRIMARY KEY,
  56. vendor_id INTEGER NOT NULL REFERENCES vendors(id),
  57. author TEXT NOT NULL,
  58. body TEXT NOT NULL,
  59. posted_at TEXT NOT NULL DEFAULT (datetime('now'))
  60. );
  61. CREATE INDEX messages_vendor_time ON messages(vendor_id, posted_at);
  62. ");
  63. $pdo->prepare('INSERT INTO vendors(slug, name) VALUES(?, ?)')
  64. ->execute(['bill', 'Bill']);
  65. $pdo->exec('PRAGMA user_version = 1');
  66. }
  67. }
  68. function find_vendor_by_slug(string $slug): ?array {
  69. $stmt = db()->prepare('SELECT * FROM vendors WHERE slug = ? AND active = 1');
  70. $stmt->execute([$slug]);
  71. $row = $stmt->fetch();
  72. return $row ?: null;
  73. }
  74. function all_vendors(): array {
  75. return db()->query('SELECT * FROM vendors WHERE active = 1 ORDER BY name')->fetchAll();
  76. }