Flow Meter Asset ID Migration
Date: 2026-01-15
Migration: 20260115000000_add_asset_id_to_flow_meters.sql
Overview
This migration adds asset_id foreign key columns to flow meter related tables, replacing the string-based flow_meter identifier with a proper foreign key relationship to the data_assets table.
Changes
Database Schema
Three tables were modified to add asset_id UUID foreign key:
data_flow_meters- Added:
asset_id UUID(nullable) - Foreign Key: References
data_assets(asset_id)ON DELETE SET NULL - Index:
idx_data_flow_meters_asset_id - Deprecation:
flow_metercolumn marked as deprecated (kept for backward compatibility)
- Added:
ops_dustloc_refills- Added:
asset_id UUID(nullable) - Foreign Key: References
data_assets(asset_id)ON DELETE SET NULL - Index:
idx_ops_dustloc_refills_asset_id - Deprecation:
flow_metercolumn marked as deprecated (kept for backward compatibility)
- Added:
ops_flow_calibrations- Fixed: Changed
asset_idfrom TEXT to UUID - Foreign Key: References
data_assets(asset_id)ON DELETE SET NULL - Index:
idx_ops_flow_calibrations_asset_id - Deprecation:
flow_metercolumn marked as deprecated (kept for backward compatibility)
- Fixed: Changed
TypeScript Types
Updated src/lib/supabaseTypes.ts to include asset_id: string | null in:
data_flow_meters(Row, Insert, Update)ops_dustloc_refills(Row, Insert, Update)ops_flow_calibrations(already had it, type corrected from TEXT to UUID)
Data Migration
A helper function migrate_flow_meter_to_asset_id() was created to automatically map existing flow_meter string values to asset_id by matching against data_assets.display_id.
Migration Results
SELECT * FROM migrate_flow_meter_to_asset_id();| Table Name | Records Updated |
|---|---|
| data_flow_meters | 971 |
| ops_dustloc_refills | 21 |
| ops_flow_calibrations | 0 |
Coverage:
data_flow_meters: 971/971 (100%)ops_dustloc_refills: 21/22 (95.5%)ops_flow_calibrations: 0/1 (0%)
Unmapped Records
Records that couldn't be automatically mapped (1 in ops_dustloc_refills, 1 in ops_flow_calibrations) will need manual review. These records either:
- Have
flow_metervalues that don't match anydisplay_idindata_assets - Have NULL
flow_metervalues - Reference flow meters that don't exist in the assets database
Backward Compatibility
The original flow_meter string columns are retained to maintain backward compatibility:
- Existing code will continue to work without modification
- New code should prefer using
asset_idfor better data integrity - The
flow_metercolumns are marked as deprecated in database comments
Benefits
- Data Integrity: Foreign key constraints ensure flow meter references are valid
- Rich Metadata: Access to full asset information (type, status, location, etc.)
- Cascading Updates: Changes to asset identifiers propagate automatically
- Better Performance: UUID indexes are more efficient than text string comparisons
- Unified Asset Management: Consistent approach across all asset types
Future Work
Phase 2 (Optional)
Once all applications are updated to use asset_id:
- Remove
flow_meterstring columns - Update all queries to use
asset_idjoins - Simplify data import scripts
Recommended Code Updates
While not required (backward compatible), consider updating:
Flow Meter Service (
src/features/flow-meter/services/databaseService.ts)- Use
asset_idfor insertions where possible - Join with
data_assetsto get display names
- Use
Refills Management
- Update forms to select assets via dropdown (from
data_assets) - Store
asset_idinstead of string identifier
- Update forms to select assets via dropdown (from
Calibration Management
- Already has
asset_idfield in forms - Ensure proper UUID type handling
- Already has
Verification Queries
-- Check coverage
SELECT COUNT(*) as total, COUNT(asset_id) as with_asset_id
FROM data_flow_meters;
-- Find unmapped records
SELECT DISTINCT fm.flow_meter
FROM data_flow_meters fm
LEFT JOIN data_assets da ON da.display_id = fm.flow_meter
WHERE fm.asset_id IS NULL
AND fm.flow_meter IS NOT NULL
AND da.asset_id IS NULL;
-- Verify foreign key constraints
SELECT conname, contype, conrelid::regclass, confrelid::regclass
FROM pg_constraint
WHERE conname LIKE '%flow%asset%';Rollback
If needed, the migration can be rolled back:
-- Remove foreign keys
ALTER TABLE data_flow_meters DROP CONSTRAINT IF EXISTS fk_data_flow_meters_asset_id;
ALTER TABLE ops_dustloc_refills DROP CONSTRAINT IF EXISTS fk_ops_dustloc_refills_asset_id;
ALTER TABLE ops_flow_calibrations DROP CONSTRAINT IF EXISTS fk_ops_flow_calibrations_asset_id;
-- Drop columns
ALTER TABLE data_flow_meters DROP COLUMN IF EXISTS asset_id;
ALTER TABLE ops_dustloc_refills DROP COLUMN IF EXISTS asset_id;
-- Revert ops_flow_calibrations.asset_id to TEXT if needed
ALTER TABLE ops_flow_calibrations ALTER COLUMN asset_id TYPE TEXT;
-- Drop helper function
DROP FUNCTION IF EXISTS migrate_flow_meter_to_asset_id();Testing
- [x] Migration applied successfully
- [x] TypeScript types updated
- [x] Build passes without errors
- [x] Data migration function executed
- [x] 971 flow meter records mapped
- [x] Foreign key constraints working