/** * Migration: Add AnalysisResult relations * * Fixes: AnalysisResult is completely orphaned with no relationships * Changes: * - Add validated_event_id FK (nullable) * - Add device_id FK (nullable) * - Add user_profile_id FK (nullable) * * @type {import('node-pg-migrate').ColumnDefinitions | undefined} */ export const shorthands = undefined; /** * @param pgm {import('node-pg-migrate').MigrationBuilder} * @param run {() => void | undefined} * @returns {Promise | void} */ export const up = (pgm) => { console.log('Adding AnalysisResult relations...'); // Add relationship columns pgm.addColumns('analysis_results', { validated_event_id: { type: 'uuid', notNull: false, comment: 'FK to validated_events - the event this analysis is for', }, device_id: { type: 'uuid', notNull: false, comment: 'FK to devices - the device that captured the analyzed event', }, user_profile_id: { type: 'uuid', notNull: false, comment: 'FK to user_profiles - the owner of the analyzed event', }, raw_event_id: { type: 'uuid', notNull: false, comment: 'FK to raw_events - the original raw event', }, }); // Add FK constraints pgm.addConstraint('analysis_results', 'analysis_results_validated_event_id_fkey', { foreignKeys: { columns: 'validated_event_id', references: 'validated_events(id)', onDelete: 'SET NULL', }, }); pgm.addConstraint('analysis_results', 'analysis_results_device_id_fkey', { foreignKeys: { columns: 'device_id', references: 'devices(id)', onDelete: 'SET NULL', }, }); pgm.addConstraint('analysis_results', 'analysis_results_user_profile_id_fkey', { foreignKeys: { columns: 'user_profile_id', references: 'user_profiles(id)', onDelete: 'SET NULL', }, }); pgm.addConstraint('analysis_results', 'analysis_results_raw_event_id_fkey', { foreignKeys: { columns: 'raw_event_id', references: 'raw_events(id)', onDelete: 'SET NULL', }, }); // Add indexes pgm.createIndex('analysis_results', 'validated_event_id', { name: 'idx_analysis_results_validated_event_id', where: 'validated_event_id IS NOT NULL', }); pgm.createIndex('analysis_results', 'device_id', { name: 'idx_analysis_results_device_id', where: 'device_id IS NOT NULL', }); pgm.createIndex('analysis_results', 'user_profile_id', { name: 'idx_analysis_results_user_profile_id', where: 'user_profile_id IS NOT NULL', }); pgm.createIndex('analysis_results', 'raw_event_id', { name: 'idx_analysis_results_raw_event_id', where: 'raw_event_id IS NOT NULL', }); // Add composite index for common query pattern pgm.createIndex('analysis_results', ['analysis_type', 'user_profile_id'], { name: 'idx_analysis_results_type_user', }); console.log('AnalysisResult relations added.'); }; /** * @param pgm {import('node-pg-migrate').MigrationBuilder} * @param run {() => void | undefined} * @returns {Promise | void} */ export const down = (pgm) => { console.log('Rolling back AnalysisResult relations...'); // Drop indexes const indexes = [ 'idx_analysis_results_validated_event_id', 'idx_analysis_results_device_id', 'idx_analysis_results_user_profile_id', 'idx_analysis_results_raw_event_id', 'idx_analysis_results_type_user', ]; indexes.forEach((name) => { pgm.dropIndex('analysis_results', [], { name, ifExists: true }); }); // Drop FK constraints const constraints = [ 'analysis_results_validated_event_id_fkey', 'analysis_results_device_id_fkey', 'analysis_results_user_profile_id_fkey', 'analysis_results_raw_event_id_fkey', ]; constraints.forEach((name) => { pgm.dropConstraint('analysis_results', name, { ifExists: true }); }); // Drop columns pgm.dropColumns('analysis_results', [ 'validated_event_id', 'device_id', 'user_profile_id', 'raw_event_id', ]); console.log('AnalysisResult relations rollback complete.'); };