- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
138 lines
5.4 KiB
TypeScript
138 lines
5.4 KiB
TypeScript
// SPDX-FileCopyrightText: 2026 Contributors to the CitrineOS Project
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
'use strict';
|
|
|
|
/** @type {import('sequelize-cli').Migration} */
|
|
import { QueryInterface } from 'sequelize';
|
|
|
|
// The initial migration created 7 partial unique indexes on VariableAttributes using
|
|
// stationId without tenantId, preventing different tenants from using the same
|
|
// variable attribute combinations. The 20260330000000-add-charging-station-pk-id
|
|
// migration replaced one of them (the all-null case) and the unconditional constraint
|
|
// with stationPkId-based equivalents, but left the remaining 6 partial indexes
|
|
// using stationId. This migration drops those and recreates them using stationPkId,
|
|
// which is a FK to ChargingStations(pkId) — globally unique per station-tenant pair —
|
|
// making the constraints effectively per-tenant.
|
|
export default {
|
|
up: async (queryInterface: QueryInterface) => {
|
|
const dropIndex = async (name: string) => {
|
|
await queryInterface.sequelize.query(`DROP INDEX IF EXISTS "${name}"`);
|
|
};
|
|
|
|
const oldIndexes = [
|
|
'variable_attributes_station_id_type',
|
|
'variable_attributes_station_id_variable_id',
|
|
'variable_attributes_station_id_component_id',
|
|
'variable_attributes_station_id_type_variable_id',
|
|
'variable_attributes_station_id_type_component_id',
|
|
'variable_attributes_station_id_variable_id_component_id',
|
|
];
|
|
|
|
for (const name of oldIndexes) {
|
|
console.log(`Dropping index ${name}...`);
|
|
await dropIndex(name);
|
|
}
|
|
|
|
console.log('Creating stationPkId-based partial unique indexes...');
|
|
|
|
await queryInterface.sequelize.query(`
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "variable_attributes_stationPkId_type"
|
|
ON "VariableAttributes" ("stationPkId", "type")
|
|
WHERE "variableId" IS NULL AND "componentId" IS NULL
|
|
`);
|
|
|
|
await queryInterface.sequelize.query(`
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "variable_attributes_stationPkId_variableId"
|
|
ON "VariableAttributes" ("stationPkId", "variableId")
|
|
WHERE "type" IS NULL AND "componentId" IS NULL
|
|
`);
|
|
|
|
await queryInterface.sequelize.query(`
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "variable_attributes_stationPkId_componentId"
|
|
ON "VariableAttributes" ("stationPkId", "componentId")
|
|
WHERE "type" IS NULL AND "variableId" IS NULL
|
|
`);
|
|
|
|
await queryInterface.sequelize.query(`
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "variable_attributes_stationPkId_type_variableId"
|
|
ON "VariableAttributes" ("stationPkId", "type", "variableId")
|
|
WHERE "componentId" IS NULL
|
|
`);
|
|
|
|
await queryInterface.sequelize.query(`
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "variable_attributes_stationPkId_type_componentId"
|
|
ON "VariableAttributes" ("stationPkId", "type", "componentId")
|
|
WHERE "variableId" IS NULL
|
|
`);
|
|
|
|
await queryInterface.sequelize.query(`
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "variable_attributes_stationPkId_variableId_componentId"
|
|
ON "VariableAttributes" ("stationPkId", "variableId", "componentId")
|
|
WHERE "type" IS NULL
|
|
`);
|
|
|
|
console.log('Successfully recreated VariableAttributes partial indexes with stationPkId.');
|
|
},
|
|
|
|
down: async (queryInterface: QueryInterface) => {
|
|
const dropIndex = async (name: string) => {
|
|
await queryInterface.sequelize.query(`DROP INDEX IF EXISTS "${name}"`);
|
|
};
|
|
|
|
const newIndexes = [
|
|
'variable_attributes_stationPkId_type',
|
|
'variable_attributes_stationPkId_variableId',
|
|
'variable_attributes_stationPkId_componentId',
|
|
'variable_attributes_stationPkId_type_variableId',
|
|
'variable_attributes_stationPkId_type_componentId',
|
|
'variable_attributes_stationPkId_variableId_componentId',
|
|
];
|
|
|
|
for (const name of newIndexes) {
|
|
console.log(`Dropping index ${name}...`);
|
|
await dropIndex(name);
|
|
}
|
|
|
|
console.log('Recreating original stationId-based partial unique indexes...');
|
|
|
|
await queryInterface.sequelize.query(`
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "variable_attributes_station_id_type"
|
|
ON "VariableAttributes" ("stationId", "type")
|
|
WHERE "variableId" IS NULL AND "componentId" IS NULL
|
|
`);
|
|
|
|
await queryInterface.sequelize.query(`
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "variable_attributes_station_id_variable_id"
|
|
ON "VariableAttributes" ("stationId", "variableId")
|
|
WHERE "type" IS NULL AND "componentId" IS NULL
|
|
`);
|
|
|
|
await queryInterface.sequelize.query(`
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "variable_attributes_station_id_component_id"
|
|
ON "VariableAttributes" ("stationId", "componentId")
|
|
WHERE "type" IS NULL AND "variableId" IS NULL
|
|
`);
|
|
|
|
await queryInterface.sequelize.query(`
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "variable_attributes_station_id_type_variable_id"
|
|
ON "VariableAttributes" ("stationId", "type", "variableId")
|
|
WHERE "componentId" IS NULL
|
|
`);
|
|
|
|
await queryInterface.sequelize.query(`
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "variable_attributes_station_id_type_component_id"
|
|
ON "VariableAttributes" ("stationId", "type", "componentId")
|
|
WHERE "variableId" IS NULL
|
|
`);
|
|
|
|
await queryInterface.sequelize.query(`
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "variable_attributes_station_id_variable_id_component_id"
|
|
ON "VariableAttributes" ("stationId", "variableId", "componentId")
|
|
WHERE "type" IS NULL
|
|
`);
|
|
|
|
console.log('Successfully restored original stationId-based partial indexes.');
|
|
},
|
|
};
|