From 6c2c3fed9abdd0c212f4f0560a508e629043da74 Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Fri, 2 Jan 2026 17:39:24 -0800 Subject: [PATCH 1/3] Consolidate SQL scripts to *-0.000-25.000.sql --- api/src/org/labkey/api/Constants.java | 2 +- .../postgresql/assay-0.000-24.000.sql | 118 --- .../postgresql/assay-0.000-25.000.sql | 332 ++++++++ .../postgresql/assay-24.000-24.001.sql | 27 - .../postgresql/assay-24.001-24.002.sql | 63 -- .../postgresql/assay-24.002-24.003.sql | 5 - .../postgresql/assay-24.003-24.004.sql | 27 - .../postgresql/assay-24.004-24.005.sql | 16 - .../postgresql/assay-24.005-24.006.sql | 6 - .../postgresql/assay-24.006-24.007.sql | 7 - .../postgresql/assay-24.007-24.008.sql | 1 - .../postgresql/assay-24.008-24.009.sql | 5 - .../postgresql/assay-24.009-24.010.sql | 1 - .../postgresql/assay-24.010-24.011.sql | 8 - .../postgresql/assay-24.011-24.012.sql | 25 - .../postgresql/assay-24.012-24.013.sql | 11 - .../postgresql/assay-24.013-24.014.sql | 1 - .../postgresql/assay-24.014-24.015.sql | 5 - .../postgresql/assay-24.015-24.016.sql | 16 - .../sqlserver/assay-0.000-24.000.sql | 119 --- .../sqlserver/assay-0.000-25.000.sql | 356 ++++++++ .../sqlserver/assay-24.000-24.001.sql | 30 - .../sqlserver/assay-24.001-24.002.sql | 63 -- .../sqlserver/assay-24.002-24.003.sql | 6 - .../sqlserver/assay-24.003-24.004.sql | 28 - .../sqlserver/assay-24.004-24.005.sql | 16 - .../sqlserver/assay-24.005-24.006.sql | 8 - .../sqlserver/assay-24.006-24.007.sql | 7 - .../sqlserver/assay-24.007-24.008.sql | 2 - .../sqlserver/assay-24.008-24.009.sql | 5 - .../sqlserver/assay-24.009-24.010.sql | 1 - .../sqlserver/assay-24.010-24.011.sql | 12 - .../sqlserver/assay-24.011-24.012.sql | 26 - .../sqlserver/assay-24.012-24.013.sql | 15 - .../sqlserver/assay-24.013-24.014.sql | 1 - .../sqlserver/assay-24.014-24.015.sql | 7 - .../sqlserver/assay-24.015-24.016.sql | 20 - .../org/labkey/assay/AssayUpgradeCode.java | 791 ------------------ .../org/labkey/assay/plate/PlateManager.java | 4 +- ...0.000-24.000.sql => core-0.000-25.000.sql} | 32 + .../postgresql/core-24.001-24.002.sql | 1 - .../postgresql/core-24.002-24.003.sql | 2 - .../postgresql/core-24.003-24.004.sql | 1 - .../postgresql/core-24.004-24.005.sql | 2 - .../postgresql/core-24.005-24.006.sql | 4 - .../postgresql/core-24.006-24.007.sql | 4 - .../postgresql/core-24.007-24.008.sql | 9 - .../postgresql/core-24.008-24.009.sql | 2 - ...0.000-24.000.sql => prop-0.000-25.000.sql} | 0 .../postgresql/prop-24.000-24.001.sql | 2 - ...0.000-24.000.sql => core-0.000-25.000.sql} | 37 + .../sqlserver/core-24.001-24.002.sql | 1 - .../sqlserver/core-24.002-24.003.sql | 1 - .../sqlserver/core-24.003-24.004.sql | 1 - .../sqlserver/core-24.004-24.005.sql | 2 - .../sqlserver/core-24.005-24.006.sql | 4 - .../sqlserver/core-24.006-24.007.sql | 4 - .../sqlserver/core-24.007-24.008.sql | 13 - .../sqlserver/core-24.008-24.009.sql | 3 - ...0.000-24.000.sql => prop-0.000-25.000.sql} | 0 .../sqlserver/prop-24.000-24.001.sql | 2 - core/src/org/labkey/core/CoreUpgradeCode.java | 103 --- ...-0.000-24.000.sql => exp-0.000-25.000.sql} | 55 ++ .../postgresql/exp-24.000-24.001.sql | 26 - .../postgresql/exp-24.001-24.002.sql | 2 - .../postgresql/exp-24.002-24.003.sql | 25 - .../postgresql/exp-24.003-24.004.sql | 1 - .../postgresql/exp-24.004-24.005.sql | 2 - .../postgresql/exp-24.005-24.006.sql | 1 - ...-0.000-24.000.sql => exp-0.000-25.000.sql} | 56 ++ .../dbscripts/sqlserver/exp-24.000-24.001.sql | 26 - .../dbscripts/sqlserver/exp-24.001-24.002.sql | 2 - .../dbscripts/sqlserver/exp-24.002-24.003.sql | 24 - .../dbscripts/sqlserver/exp-24.003-24.004.sql | 1 - .../dbscripts/sqlserver/exp-24.004-24.005.sql | 2 - .../dbscripts/sqlserver/exp-24.005-24.006.sql | 1 - .../experiment/ExperimentUpgradeCode.java | 77 -- ...000-21.000.sql => search-0.000-25.000.sql} | 0 .../postgresql/search-24.000-24.001.sql | 4 - ...000-21.000.sql => search-0.000-25.000.sql} | 2 - .../sqlserver/search-24.000-24.001.sql | 4 - 81 files changed, 871 insertions(+), 1863 deletions(-) delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-0.000-24.000.sql create mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-0.000-25.000.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.000-24.001.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.001-24.002.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.002-24.003.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.003-24.004.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.004-24.005.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.005-24.006.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.006-24.007.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.007-24.008.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.008-24.009.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.009-24.010.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.010-24.011.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.011-24.012.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.012-24.013.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.013-24.014.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.014-24.015.sql delete mode 100644 assay/resources/schemas/dbscripts/postgresql/assay-24.015-24.016.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-0.000-24.000.sql create mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-0.000-25.000.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.000-24.001.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.001-24.002.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.002-24.003.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.003-24.004.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.004-24.005.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.005-24.006.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.006-24.007.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.007-24.008.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.008-24.009.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.009-24.010.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.010-24.011.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.011-24.012.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.012-24.013.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.013-24.014.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.014-24.015.sql delete mode 100644 assay/resources/schemas/dbscripts/sqlserver/assay-24.015-24.016.sql rename core/resources/schemas/dbscripts/postgresql/{core-0.000-24.000.sql => core-0.000-25.000.sql} (93%) delete mode 100644 core/resources/schemas/dbscripts/postgresql/core-24.001-24.002.sql delete mode 100644 core/resources/schemas/dbscripts/postgresql/core-24.002-24.003.sql delete mode 100644 core/resources/schemas/dbscripts/postgresql/core-24.003-24.004.sql delete mode 100644 core/resources/schemas/dbscripts/postgresql/core-24.004-24.005.sql delete mode 100644 core/resources/schemas/dbscripts/postgresql/core-24.005-24.006.sql delete mode 100644 core/resources/schemas/dbscripts/postgresql/core-24.006-24.007.sql delete mode 100644 core/resources/schemas/dbscripts/postgresql/core-24.007-24.008.sql delete mode 100644 core/resources/schemas/dbscripts/postgresql/core-24.008-24.009.sql rename core/resources/schemas/dbscripts/postgresql/{prop-0.000-24.000.sql => prop-0.000-25.000.sql} (100%) delete mode 100644 core/resources/schemas/dbscripts/postgresql/prop-24.000-24.001.sql rename core/resources/schemas/dbscripts/sqlserver/{core-0.000-24.000.sql => core-0.000-25.000.sql} (95%) delete mode 100644 core/resources/schemas/dbscripts/sqlserver/core-24.001-24.002.sql delete mode 100644 core/resources/schemas/dbscripts/sqlserver/core-24.002-24.003.sql delete mode 100644 core/resources/schemas/dbscripts/sqlserver/core-24.003-24.004.sql delete mode 100644 core/resources/schemas/dbscripts/sqlserver/core-24.004-24.005.sql delete mode 100644 core/resources/schemas/dbscripts/sqlserver/core-24.005-24.006.sql delete mode 100644 core/resources/schemas/dbscripts/sqlserver/core-24.006-24.007.sql delete mode 100644 core/resources/schemas/dbscripts/sqlserver/core-24.007-24.008.sql delete mode 100644 core/resources/schemas/dbscripts/sqlserver/core-24.008-24.009.sql rename core/resources/schemas/dbscripts/sqlserver/{prop-0.000-24.000.sql => prop-0.000-25.000.sql} (100%) delete mode 100644 core/resources/schemas/dbscripts/sqlserver/prop-24.000-24.001.sql rename experiment/resources/schemas/dbscripts/postgresql/{exp-0.000-24.000.sql => exp-0.000-25.000.sql} (94%) delete mode 100644 experiment/resources/schemas/dbscripts/postgresql/exp-24.000-24.001.sql delete mode 100644 experiment/resources/schemas/dbscripts/postgresql/exp-24.001-24.002.sql delete mode 100644 experiment/resources/schemas/dbscripts/postgresql/exp-24.002-24.003.sql delete mode 100644 experiment/resources/schemas/dbscripts/postgresql/exp-24.003-24.004.sql delete mode 100644 experiment/resources/schemas/dbscripts/postgresql/exp-24.004-24.005.sql delete mode 100644 experiment/resources/schemas/dbscripts/postgresql/exp-24.005-24.006.sql rename experiment/resources/schemas/dbscripts/sqlserver/{exp-0.000-24.000.sql => exp-0.000-25.000.sql} (95%) delete mode 100644 experiment/resources/schemas/dbscripts/sqlserver/exp-24.000-24.001.sql delete mode 100644 experiment/resources/schemas/dbscripts/sqlserver/exp-24.001-24.002.sql delete mode 100644 experiment/resources/schemas/dbscripts/sqlserver/exp-24.002-24.003.sql delete mode 100644 experiment/resources/schemas/dbscripts/sqlserver/exp-24.003-24.004.sql delete mode 100644 experiment/resources/schemas/dbscripts/sqlserver/exp-24.004-24.005.sql delete mode 100644 experiment/resources/schemas/dbscripts/sqlserver/exp-24.005-24.006.sql rename search/resources/schemas/dbscripts/postgresql/{search-0.000-21.000.sql => search-0.000-25.000.sql} (100%) delete mode 100644 search/resources/schemas/dbscripts/postgresql/search-24.000-24.001.sql rename search/resources/schemas/dbscripts/sqlserver/{search-0.000-21.000.sql => search-0.000-25.000.sql} (98%) delete mode 100644 search/resources/schemas/dbscripts/sqlserver/search-24.000-24.001.sql diff --git a/api/src/org/labkey/api/Constants.java b/api/src/org/labkey/api/Constants.java index 50ce1f2e13e..9f4f6108f46 100644 --- a/api/src/org/labkey/api/Constants.java +++ b/api/src/org/labkey/api/Constants.java @@ -47,7 +47,7 @@ public static double getLowestSchemaVersion() */ public static double getEarliestUpgradeVersion() { - return 24.000; + return 25.000; } /** diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-0.000-24.000.sql b/assay/resources/schemas/dbscripts/postgresql/assay-0.000-24.000.sql deleted file mode 100644 index 67a7f22a10a..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-0.000-24.000.sql +++ /dev/null @@ -1,118 +0,0 @@ -/* - For LabKey 19.2 and earlier, the assayresult schema and the Plate, WellGroup, and Well tables were managed by the - study module. As of 19.3, the assay module now manages these objects, with the tables moving from the "study" schema - to the new "assay" schema. - */ - -CREATE SCHEMA assay; -CREATE SCHEMA assayresult; - -CREATE TABLE assay.Plate -( - RowId SERIAL, - LSID VARCHAR(200) NOT NULL, - Container ENTITYID NOT NULL, - Name VARCHAR(200) NULL, - CreatedBy USERID NOT NULL, - Created TIMESTAMP NOT NULL, - Template BOOLEAN NOT NULL, - DataFileId ENTITYID, - Rows INT NOT NULL, - Columns INT NOT NULL, - Type VARCHAR(200), - - CONSTRAINT PK_Plate PRIMARY KEY (RowId) -); - -CREATE INDEX IX_Plate_Container ON assay.Plate(Container); - -ALTER TABLE assay.plate - ADD Modified TIMESTAMP, - ADD ModifiedBy USERID; - -ALTER TABLE assay.plate - ALTER Modified SET NOT NULL, - ALTER ModifiedBy SET NOT NULL; - -ALTER TABLE assay.plate - ADD CONSTRAINT uq_plate_lsid UNIQUE (lsid); - --- plate template (not instances) names are unique in each container -CREATE UNIQUE INDEX uq_plate_container_name_template ON assay.plate (container, name) WHERE template=true; - -CREATE TABLE assay.WellGroup -( - RowId SERIAL, - PlateId INT NOT NULL, - LSID VARCHAR(200) NOT NULL, - Container ENTITYID NOT NULL, - Name VARCHAR(200) NULL, - Template BOOLEAN NOT NULL, - TypeName VARCHAR(50) NOT NULL, - - CONSTRAINT PK_WellGroup PRIMARY KEY (RowId), - CONSTRAINT FK_WellGroup_Plate FOREIGN KEY (PlateId) REFERENCES assay.Plate(RowId) -); - -CREATE INDEX IX_WellGroup_PlateId ON assay.WellGroup(PlateId); -CREATE INDEX IX_WellGroup_Container ON assay.WellGroup(Container); - -ALTER TABLE assay.wellgroup - ADD CONSTRAINT uq_wellgroup_lsid UNIQUE (lsid); - --- well group names must be unique within each well group type -ALTER TABLE assay.wellgroup - ADD CONSTRAINT uq_wellgroup_plateid_typename_name UNIQUE (plateid, typename, name); - -CREATE TABLE assay.Well -( - RowId SERIAL, - LSID VARCHAR(200) NOT NULL, - Container ENTITYID NOT NULL, - Value FLOAT NULL, - Dilution FLOAT NULL, - PlateId INT NOT NULL, - Row INT NOT NULL, - Col INT NOT NULL, - - CONSTRAINT PK_Well PRIMARY KEY (RowId), - CONSTRAINT FK_Well_Plate FOREIGN KEY (PlateId) REFERENCES assay.Plate(RowId) -); - -CREATE INDEX IX_Well_PlateId ON assay.Well(PlateId); -CREATE INDEX IX_Well_Container ON assay.Well(Container); - -ALTER TABLE assay.well - ADD CONSTRAINT uq_well_lsid UNIQUE (lsid); - --- each well position is unique on the plate -ALTER TABLE assay.well - ADD CONSTRAINT uq_well_plateid_row_col UNIQUE (plateid, row, col); - -ALTER TABLE Assay.Well ADD COLUMN SampleId INTEGER NULL; -ALTER TABLE Assay.Well ADD CONSTRAINT FK_SampleId_ExpMaterial FOREIGN KEY (SampleId) REFERENCES exp.material (RowId); - -CREATE TABLE assay.WellGroupPositions -( - RowId SERIAL, - WellId INT NOT NULL, - WellGroupId INT NOT NULL, - - CONSTRAINT PK_WellGroupPositions PRIMARY KEY (RowId), - CONSTRAINT FK_WellGroupPositions_Well FOREIGN KEY (WellId) REFERENCES assay.Well(RowId), - CONSTRAINT FK_WellGroupPositions_WellGroup FOREIGN KEY (WellGroupId) REFERENCES assay.WellGroup(RowId), - CONSTRAINT UQ_WellGroupPositions_WellGroup_Well UNIQUE (WellGroupId, WellId) -); - -CREATE TABLE assay.PlateProperty -( - RowId SERIAL, - PlateId INT NOT NULL, - PropertyId INT NOT NULL, - PropertyURI VARCHAR(300) NOT NULL, - - CONSTRAINT PK_PlateProperty PRIMARY KEY (RowId), - CONSTRAINT UQ_PlateProperty_PlateId_PropertyId UNIQUE (PlateId, PropertyId), - CONSTRAINT FK_PlateProperty_PlateId FOREIGN KEY (PlateId) REFERENCES assay.Plate(RowId), - CONSTRAINT FK_PlateProperty_PropertyId FOREIGN KEY (PropertyId) REFERENCES exp.PropertyDescriptor(PropertyId) -); diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-0.000-25.000.sql b/assay/resources/schemas/dbscripts/postgresql/assay-0.000-25.000.sql new file mode 100644 index 00000000000..97baa9392f2 --- /dev/null +++ b/assay/resources/schemas/dbscripts/postgresql/assay-0.000-25.000.sql @@ -0,0 +1,332 @@ +/* + For LabKey 19.2 and earlier, the assayresult schema and the Plate, WellGroup, and Well tables were managed by the + study module. As of 19.3, the assay module now manages these objects, with the tables moving from the "study" schema + to the new "assay" schema. + */ + +CREATE SCHEMA assay; +CREATE SCHEMA assayresult; +-- Provisioned schema used by PlateMetadataDomainKind +CREATE SCHEMA assaywell; + +CREATE TABLE assay.Plate +( + RowId SERIAL, + LSID VARCHAR(200) NOT NULL, + Container ENTITYID NOT NULL, + Name VARCHAR(200) NULL, + CreatedBy USERID NOT NULL, + Created TIMESTAMP NOT NULL, + Template BOOLEAN NOT NULL, + DataFileId ENTITYID, + Rows INT NOT NULL, + Columns INT NOT NULL, + Type VARCHAR(200), + + CONSTRAINT PK_Plate PRIMARY KEY (RowId) +); + +CREATE INDEX IX_Plate_Container ON assay.Plate(Container); + +ALTER TABLE assay.plate + ADD Modified TIMESTAMP, + ADD ModifiedBy USERID; + +ALTER TABLE assay.plate + ALTER Modified SET NOT NULL, + ALTER ModifiedBy SET NOT NULL; + +ALTER TABLE assay.plate + ADD CONSTRAINT uq_plate_lsid UNIQUE (lsid); + +-- plate template (not instances) names are unique in each container +CREATE UNIQUE INDEX uq_plate_container_name_template ON assay.plate (container, name) WHERE template=true; + +CREATE TABLE assay.WellGroup +( + RowId SERIAL, + PlateId INT NOT NULL, + LSID VARCHAR(200) NOT NULL, + Container ENTITYID NOT NULL, + Name VARCHAR(200) NULL, + Template BOOLEAN NOT NULL, + TypeName VARCHAR(50) NOT NULL, + + CONSTRAINT PK_WellGroup PRIMARY KEY (RowId), + CONSTRAINT FK_WellGroup_Plate FOREIGN KEY (PlateId) REFERENCES assay.Plate(RowId) +); + +CREATE INDEX IX_WellGroup_PlateId ON assay.WellGroup(PlateId); +CREATE INDEX IX_WellGroup_Container ON assay.WellGroup(Container); + +ALTER TABLE assay.wellgroup + ADD CONSTRAINT uq_wellgroup_lsid UNIQUE (lsid); + +-- well group names must be unique within each well group type +ALTER TABLE assay.wellgroup + ADD CONSTRAINT uq_wellgroup_plateid_typename_name UNIQUE (plateid, typename, name); + +CREATE TABLE assay.Well +( + RowId SERIAL, + LSID VARCHAR(200) NOT NULL, + Container ENTITYID NOT NULL, + Value FLOAT NULL, + Dilution FLOAT NULL, + PlateId INT NOT NULL, + Row INT NOT NULL, + Col INT NOT NULL, + + CONSTRAINT PK_Well PRIMARY KEY (RowId), + CONSTRAINT FK_Well_Plate FOREIGN KEY (PlateId) REFERENCES assay.Plate(RowId) +); + +CREATE INDEX IX_Well_PlateId ON assay.Well(PlateId); +CREATE INDEX IX_Well_Container ON assay.Well(Container); + +ALTER TABLE assay.well + ADD CONSTRAINT uq_well_lsid UNIQUE (lsid); + +-- each well position is unique on the plate +ALTER TABLE assay.well + ADD CONSTRAINT uq_well_plateid_row_col UNIQUE (plateid, row, col); + +ALTER TABLE Assay.Well ADD COLUMN SampleId INTEGER NULL; +ALTER TABLE Assay.Well ADD CONSTRAINT FK_SampleId_ExpMaterial FOREIGN KEY (SampleId) REFERENCES exp.material (RowId); + +CREATE TABLE assay.WellGroupPositions +( + RowId SERIAL, + WellId INT NOT NULL, + WellGroupId INT NOT NULL, + + CONSTRAINT PK_WellGroupPositions PRIMARY KEY (RowId), + CONSTRAINT FK_WellGroupPositions_Well FOREIGN KEY (WellId) REFERENCES assay.Well(RowId), + CONSTRAINT FK_WellGroupPositions_WellGroup FOREIGN KEY (WellGroupId) REFERENCES assay.WellGroup(RowId), + CONSTRAINT UQ_WellGroupPositions_WellGroup_Well UNIQUE (WellGroupId, WellId) +); + +CREATE TABLE assay.PlateProperty +( + RowId SERIAL, + PlateId INT NOT NULL, + PropertyId INT NOT NULL, + PropertyURI VARCHAR(300) NOT NULL, + + CONSTRAINT PK_PlateProperty PRIMARY KEY (RowId), + CONSTRAINT UQ_PlateProperty_PlateId_PropertyId UNIQUE (PlateId, PropertyId), + CONSTRAINT FK_PlateProperty_PlateId FOREIGN KEY (PlateId) REFERENCES assay.Plate(RowId), + CONSTRAINT FK_PlateProperty_PropertyId FOREIGN KEY (PropertyId) REFERENCES exp.PropertyDescriptor(PropertyId) +); + +/* 24.xxx SQL scripts */ + +CREATE TABLE assay.PlateSet +( + RowId INT NOT NULL, + Name VARCHAR(200) NOT NULL, + Container ENTITYID NOT NULL, + Created TIMESTAMP NOT NULL, + CreatedBy USERID NOT NULL, + Modified TIMESTAMP NOT NULL, + ModifiedBy USERID NOT NULL, + Archived BOOLEAN NOT NULL DEFAULT FALSE, + + CONSTRAINT PK_PlateSet PRIMARY KEY (RowId) +); + +-- Insert a row into the plate set table for every plate in the system, store the plate row ID in the plate set table +-- in order to create the FK from the plate to plate set table +INSERT INTO assay.PlateSet (RowId, Name, Container, Created, CreatedBy, Modified, ModifiedBy) + SELECT RowId, 'TempPlateSet', Container, now(), CreatedBy, now(), ModifiedBy FROM assay.Plate; + +-- Add the plate set field to the plate table and populate it with the plate set row ID +ALTER TABLE assay.Plate ADD COLUMN PlateSet INTEGER; +UPDATE assay.Plate SET PlateSet = RowId; +ALTER TABLE assay.Plate ADD CONSTRAINT FK_Plate_PlateSet FOREIGN KEY (PlateSet) REFERENCES assay.PlateSet (RowId); +CREATE INDEX IX_Plate_PlateSet ON assay.Plate (PlateSet); + +CREATE TABLE assay.PlateType +( + RowId SERIAL, + Rows INT NOT NULL, + Columns INT NOT NULL, + Description VARCHAR(300) NOT NULL, + Archived BOOLEAN NOT NULL DEFAULT FALSE, + + CONSTRAINT PK_PlateType PRIMARY KEY (RowId), + CONSTRAINT UQ_PlateType_Rows_Cols UNIQUE (Rows, Columns) +); + +-- @SkipOnEmptySchemasBegin +INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (3, 4, '12 well (3x4)'); +INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (4, 6, '24 well (4x6)'); +INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (6, 8, '48 well (6x8)'); +INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (8, 12, '96 well (8x12)'); +INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (16, 24, '384 well (16x24)'); +INSERT INTO assay.PlateType (Rows, Columns, Description, Archived) VALUES (32, 48, '1536 well (32x48)', TRUE); +INSERT INTO assay.PlateType (Rows, Columns, Description, Archived) VALUES (0, 0, 'Invalid Plate Type (Plates which were created with non-valid row & column combinations)', TRUE); +-- @SkipOnEmptySchemasEnd + +-- Rename type column to assayType +ALTER TABLE assay.Plate RENAME COLUMN Type TO AssayType; +-- Add plateType as a FK to assay.PlateType +ALTER TABLE assay.Plate ADD COLUMN PlateType INTEGER; +ALTER TABLE assay.Plate ADD CONSTRAINT FK_Plate_PlateType FOREIGN KEY (PlateType) REFERENCES assay.PlateType (RowId); + +-- Add ID and description columns to Plate and PlateSet tables +ALTER TABLE assay.Plate ADD COLUMN PlateId VARCHAR(200); +ALTER TABLE assay.Plate ADD COLUMN Description VARCHAR(300); +ALTER TABLE assay.PlateSet ADD COLUMN PlateSetId VARCHAR(200); +ALTER TABLE assay.PlateSet ADD COLUMN Description VARCHAR(300); + +-- Most existing plate sets will have a generated name, but mutated ones will get fixed up by the java upgrade script +UPDATE assay.PlateSet SET PlateSetId = Name; + +UPDATE assay.Plate +SET PlateType = + CASE + WHEN (Rows = 3 AND Columns = 4) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 3 AND Columns = 4) + WHEN (Rows = 4 AND Columns = 6) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 4 AND Columns = 6) + WHEN (Rows = 6 AND Columns = 8) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 6 AND Columns = 8) + WHEN (Rows = 8 AND Columns = 12) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 8 AND Columns = 12) + WHEN (Rows = 16 AND Columns = 24) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 16 AND Columns = 24) + WHEN (Rows = 32 AND Columns = 48) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 32 AND Columns = 48) + ELSE (SELECT RowId FROM assay.PlateType WHERE Rows = 0 AND Columns = 0) + END +WHERE PlateType IS NULL; + +ALTER TABLE assay.Plate ALTER COLUMN PlateType SET NOT NULL; +ALTER TABLE assay.Plate DROP COLUMN Rows; +ALTER TABLE assay.Plate DROP COLUMN Columns; + +-- finalize plate and plateSet ID columns +ALTER TABLE assay.Plate ALTER COLUMN PlateId SET NOT NULL; +ALTER TABLE assay.Plate ADD CONSTRAINT UQ_Plate_PlateId UNIQUE (PlateId); + +ALTER TABLE assay.PlateSet ALTER COLUMN PlateSetId SET NOT NULL; +ALTER TABLE assay.PlateSet ADD CONSTRAINT UQ_PlateSet_PlateSetId UNIQUE (PlateSetId); + +ALTER TABLE assay.PlateSet ADD COLUMN Type VARCHAR(64); +ALTER TABLE assay.PlateSet ADD COLUMN RootPlateSetId INT; +ALTER TABLE assay.PlateSet ADD COLUMN PrimaryPlateSetId INT; +ALTER TABLE assay.PlateSet ADD CONSTRAINT FK_PlateSet_RootPlateSetId FOREIGN KEY (RootPlateSetId) REFERENCES assay.PlateSet (RowId); +ALTER TABLE assay.PlateSet ADD CONSTRAINT FK_PlateSet_PrimaryPlateSetId FOREIGN KEY (PrimaryPlateSetId) REFERENCES assay.PlateSet (RowId); + +-- Update all pre-existing plate sets to type "assay" +UPDATE assay.PlateSet SET type = 'assay'; + +ALTER TABLE assay.PlateSet ALTER COLUMN Type SET NOT NULL; + +CREATE TABLE assay.PlateSetEdge +( + FromPlateSetId INT NOT NULL, + ToPlateSetId INT NOT NULL, + RootPlateSetId INT NOT NULL, + + CONSTRAINT FK_PlateSet_FromPlate FOREIGN KEY (FromPlateSetId) REFERENCES assay.PlateSet (RowId), + CONSTRAINT FK_PlateSet_ToPlate FOREIGN KEY (ToPlateSetId) REFERENCES assay.PlateSet (RowId), + CONSTRAINT FK_PlateSet_RootPlate FOREIGN KEY (RootPlateSetId) REFERENCES assay.PlateSet (RowId), + CONSTRAINT UQ_PlateSetEdge_FromPlate_ToPlate UNIQUE (FromPlateSetId, ToPlateSetId) +); + +CREATE INDEX IX_PlateSetEdge_FromPlateSetId ON assay.PlateSetEdge (FromPlateSetId); +CREATE INDEX IX_PlateSetEdge_ToPlateSetId ON assay.PlateSetEdge (ToPlateSetId); +CREATE INDEX IX_PlateSetEdge_RootPlateSetId ON assay.PlateSetEdge (RootPlateSetId); + +CREATE TABLE assay.Hit +( + RowId SERIAL, + Container ENTITYID NOT NULL, + ProtocolId INT NOT NULL, + ResultId INT NOT NULL, + RunId INT NOT NULL, + WellLsid VARCHAR(200) NOT NULL, + + CONSTRAINT PK_Hit PRIMARY KEY (RowId), + CONSTRAINT FK_Hit_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId), + CONSTRAINT FK_Protocol_ProtocolId FOREIGN KEY (ProtocolId) REFERENCES exp.Protocol (RowId), + CONSTRAINT FK_Run_RunId FOREIGN KEY (RunId) REFERENCES exp.ExperimentRun (RowId), + CONSTRAINT FK_Well_WellLsid FOREIGN KEY (WellLsid) REFERENCES assay.Well (Lsid), + CONSTRAINT UQ_Hit_RunId_ResultId UNIQUE (RunId, ResultId) +); + +ALTER TABLE assay.Hit ADD COLUMN PlateSetPath VARCHAR (4000); + +ALTER TABLE assay.Hit ALTER COLUMN PlateSetPath SET NOT NULL; + +ALTER TABLE assay.PlateSet ADD COLUMN Template BOOLEAN NOT NULL DEFAULT FALSE; +UPDATE assay.Plate SET Template = False WHERE Template = True; + +ALTER TABLE assay.Plate ADD COLUMN Archived BOOLEAN NOT NULL DEFAULT FALSE; + +UPDATE assay.Plate SET AssayType = 'Standard' WHERE AssayType IS NULL; +ALTER TABLE assay.Plate ALTER COLUMN AssayType SET NOT NULL; + +-- Add index on assay.Well.SampleId to improve performance of DELETE operation on exp.Material table. +CREATE INDEX IX_Well_SampleId ON assay.Well (SampleId); + +-- Add index on assay.WellGroupPositions.WellId to improve performance of DELETE operation on assay.Well table. +CREATE INDEX IX_WellGroupPositions_WellId ON assay.WellGroupPositions (WellId); + +ALTER TABLE assay.plate ADD Barcode VARCHAR(255); +ALTER TABLE assay.plate ADD CONSTRAINT UQ_Barcode UNIQUE (Barcode); + +UPDATE assay.plate SET Barcode = LPAD(rowid::text, 9, '0') WHERE plate.Barcode IS NULL AND plate.template IS FALSE; + +ALTER TABLE assay.plate ADD CONSTRAINT check_template_true_barcode_null CHECK (NOT plate.template OR plate.Barcode IS NULL); + +-- Specify plate metadata columns on the plate set rather than the individual plates +CREATE TABLE assay.PlateSetProperty +( + RowId SERIAL, + PlateSetId INT NOT NULL, + PropertyId INT NOT NULL, + PropertyURI VARCHAR(300) NOT NULL, + + CONSTRAINT PK_PlateSetProperty PRIMARY KEY (RowId), + CONSTRAINT UQ_PlateSetProperty_PlateSetId_PropertyId UNIQUE (PlateSetId, PropertyId), + CONSTRAINT FK_PlateSetProperty_PlateSetId FOREIGN KEY (PlateSetId) REFERENCES assay.PlateSet(RowId) ON DELETE CASCADE, + CONSTRAINT FK_PlateSetProperty_PropertyId FOREIGN KEY (PropertyId) REFERENCES exp.PropertyDescriptor(PropertyId) ON DELETE CASCADE +); + +INSERT INTO assay.PlateSetProperty (PlateSetId, PropertyId, PropertyURI) +SELECT + PL.PlateSet AS PlateSetId, + PP.PropertyId, + PP.PropertyURI +FROM assay.PlateProperty AS PP +INNER JOIN assay.Plate AS PL ON PP.PlateId = PL.RowId +GROUP BY PlateSetId, PropertyId, PropertyURI +ORDER BY PlateSetId, PropertyId; + +DROP TABLE assay.PlateProperty; + +ALTER TABLE assay.platesetproperty + ADD COLUMN FieldKey VARCHAR(255); + +ALTER TABLE assay.platesetproperty + ADD CONSTRAINT either_identifier + CHECK (PropertyURI IS NOT NULL OR FieldKey IS NOT NULL); + +ALTER TABLE assay.platesetproperty ALTER COLUMN PropertyURI DROP NOT NULL; +ALTER TABLE assay.platesetproperty ALTER COLUMN PropertyId DROP NOT NULL; + +ALTER TABLE assay.plateset ADD COLUMN LSID LSIDtype; + +ALTER TABLE assay.plateset ALTER COLUMN LSID SET NOT NULL; + +CREATE TABLE assay.FilterCriteria +( + RowId SERIAL, + PropertyId INT NOT NULL, + ReferencePropertyId INT NOT NULL, + DomainId INT NOT NULL, + Operation VARCHAR(50) NOT NULL, + Value VARCHAR(4000) NULL, + + CONSTRAINT PK_FilterCriteria PRIMARY KEY (RowId), + CONSTRAINT FK_FilterCriteria_PropertyDescriptor FOREIGN KEY (PropertyId) REFERENCES exp.PropertyDescriptor (PropertyId) ON DELETE CASCADE, + CONSTRAINT FK_FilterCriteria_PropertyDescriptor_Reference FOREIGN KEY (ReferencePropertyId) REFERENCES exp.PropertyDescriptor (PropertyId) ON DELETE CASCADE, + CONSTRAINT FK_FilterCriteria_DomainDescriptor FOREIGN KEY (DomainId) REFERENCES exp.DomainDescriptor (DomainId) ON DELETE CASCADE +); diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.000-24.001.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.000-24.001.sql deleted file mode 100644 index ea78b142261..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.000-24.001.sql +++ /dev/null @@ -1,27 +0,0 @@ -CREATE TABLE assay.PlateSet -( - RowId INT NOT NULL, - Name VARCHAR(200) NOT NULL, - Container ENTITYID NOT NULL, - Created TIMESTAMP NOT NULL, - CreatedBy USERID NOT NULL, - Modified TIMESTAMP NOT NULL, - ModifiedBy USERID NOT NULL, - Archived BOOLEAN NOT NULL DEFAULT FALSE, - - CONSTRAINT PK_PlateSet PRIMARY KEY (RowId) -); - --- Insert a row into the plate set table for every plate in the system, store the plate row ID in the plate set table --- in order to create the FK from the plate to plate set table -INSERT INTO assay.PlateSet (RowId, Name, Container, Created, CreatedBy, Modified, ModifiedBy) - SELECT RowId, 'TempPlateSet', Container, now(), CreatedBy, now(), ModifiedBy FROM assay.Plate; - --- Add the plate set field to the plate table and populate it with the plate set row ID -ALTER TABLE assay.Plate ADD COLUMN PlateSet INTEGER; -UPDATE assay.Plate SET PlateSet = RowId; -ALTER TABLE assay.Plate ADD CONSTRAINT FK_Plate_PlateSet FOREIGN KEY (PlateSet) REFERENCES assay.PlateSet (RowId); -CREATE INDEX IX_Plate_PlateSet ON assay.Plate (PlateSet); - --- Run the java upgrade script to update plate set and plate tables to create the name expression based name values -SELECT core.executeJavaUpgradeCode('updatePlateSetNames'); \ No newline at end of file diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.001-24.002.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.001-24.002.sql deleted file mode 100644 index d86ed7e0ad6..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.001-24.002.sql +++ /dev/null @@ -1,63 +0,0 @@ -CREATE TABLE assay.PlateType -( - RowId SERIAL, - Rows INT NOT NULL, - Columns INT NOT NULL, - Description VARCHAR(300) NOT NULL, - Archived BOOLEAN NOT NULL DEFAULT FALSE, - - CONSTRAINT PK_PlateType PRIMARY KEY (RowId), - CONSTRAINT UQ_PlateType_Rows_Cols UNIQUE (Rows, Columns) -); - --- @SkipOnEmptySchemasBegin -INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (3, 4, '12 well (3x4)'); -INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (4, 6, '24 well (4x6)'); -INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (6, 8, '48 well (6x8)'); -INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (8, 12, '96 well (8x12)'); -INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (16, 24, '384 well (16x24)'); -INSERT INTO assay.PlateType (Rows, Columns, Description, Archived) VALUES (32, 48, '1536 well (32x48)', TRUE); -INSERT INTO assay.PlateType (Rows, Columns, Description, Archived) VALUES (0, 0, 'Invalid Plate Type (Plates which were created with non-valid row & column combinations)', TRUE); --- @SkipOnEmptySchemasEnd - --- Rename type column to assayType -ALTER TABLE assay.Plate RENAME COLUMN Type TO AssayType; --- Add plateType as a FK to assay.PlateType -ALTER TABLE assay.Plate ADD COLUMN PlateType INTEGER; -ALTER TABLE assay.Plate ADD CONSTRAINT FK_Plate_PlateType FOREIGN KEY (PlateType) REFERENCES assay.PlateType (RowId); - --- Add ID and description columns to Plate and PlateSet tables -ALTER TABLE assay.Plate ADD COLUMN PlateId VARCHAR(200); -ALTER TABLE assay.Plate ADD COLUMN Description VARCHAR(300); -ALTER TABLE assay.PlateSet ADD COLUMN PlateSetId VARCHAR(200); -ALTER TABLE assay.PlateSet ADD COLUMN Description VARCHAR(300); - --- Most existing plate sets will have a generated name, but mutated ones will get fixed up by the java upgrade script -UPDATE assay.PlateSet SET PlateSetId = Name; - -UPDATE assay.Plate -SET PlateType = - CASE - WHEN (Rows = 3 AND Columns = 4) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 3 AND Columns = 4) - WHEN (Rows = 4 AND Columns = 6) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 4 AND Columns = 6) - WHEN (Rows = 6 AND Columns = 8) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 6 AND Columns = 8) - WHEN (Rows = 8 AND Columns = 12) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 8 AND Columns = 12) - WHEN (Rows = 16 AND Columns = 24) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 16 AND Columns = 24) - WHEN (Rows = 32 AND Columns = 48) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 32 AND Columns = 48) - ELSE (SELECT RowId FROM assay.PlateType WHERE Rows = 0 AND Columns = 0) - END -WHERE PlateType IS NULL; - -ALTER TABLE assay.Plate ALTER COLUMN PlateType SET NOT NULL; -ALTER TABLE assay.Plate DROP COLUMN Rows; -ALTER TABLE assay.Plate DROP COLUMN Columns; - --- upgrade script to initialize plate and plateSet IDs -SELECT core.executeJavaUpgradeCode('initializePlateAndPlateSetIDs'); - --- finalize plate and plateSet ID columns -ALTER TABLE assay.Plate ALTER COLUMN PlateId SET NOT NULL; -ALTER TABLE assay.Plate ADD CONSTRAINT UQ_Plate_PlateId UNIQUE (PlateId); - -ALTER TABLE assay.PlateSet ALTER COLUMN PlateSetId SET NOT NULL; -ALTER TABLE assay.PlateSet ADD CONSTRAINT UQ_PlateSet_PlateSetId UNIQUE (PlateSetId); diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.002-24.003.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.002-24.003.sql deleted file mode 100644 index a3cba9f6605..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.002-24.003.sql +++ /dev/null @@ -1,5 +0,0 @@ --- Provisioned schema used by PlateMetadataDomainKind -CREATE SCHEMA assaywell; - --- upgrade script to initialize plate and plateSet IDs -SELECT core.executeJavaUpgradeCode('deletePlateVocabDomains'); diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.003-24.004.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.003-24.004.sql deleted file mode 100644 index 60ff87df5e4..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.003-24.004.sql +++ /dev/null @@ -1,27 +0,0 @@ -ALTER TABLE assay.PlateSet ADD COLUMN Type VARCHAR(64); -ALTER TABLE assay.PlateSet ADD COLUMN RootPlateSetId INT; -ALTER TABLE assay.PlateSet ADD COLUMN PrimaryPlateSetId INT; -ALTER TABLE assay.PlateSet ADD CONSTRAINT FK_PlateSet_RootPlateSetId FOREIGN KEY (RootPlateSetId) REFERENCES assay.PlateSet (RowId); -ALTER TABLE assay.PlateSet ADD CONSTRAINT FK_PlateSet_PrimaryPlateSetId FOREIGN KEY (PrimaryPlateSetId) REFERENCES assay.PlateSet (RowId); - --- Update all pre-existing plate sets to type "assay" -UPDATE assay.PlateSet SET type = 'assay'; - -ALTER TABLE assay.PlateSet ALTER COLUMN Type SET NOT NULL; - -CREATE TABLE assay.PlateSetEdge -( - FromPlateSetId INT NOT NULL, - ToPlateSetId INT NOT NULL, - RootPlateSetId INT NOT NULL, - - CONSTRAINT FK_PlateSet_FromPlate FOREIGN KEY (FromPlateSetId) REFERENCES assay.PlateSet (RowId), - CONSTRAINT FK_PlateSet_ToPlate FOREIGN KEY (ToPlateSetId) REFERENCES assay.PlateSet (RowId), - CONSTRAINT FK_PlateSet_RootPlate FOREIGN KEY (RootPlateSetId) REFERENCES assay.PlateSet (RowId), - CONSTRAINT UQ_PlateSetEdge_FromPlate_ToPlate UNIQUE (FromPlateSetId, ToPlateSetId) -); - -CREATE INDEX IX_PlateSetEdge_FromPlateSetId ON assay.PlateSetEdge (FromPlateSetId); -CREATE INDEX IX_PlateSetEdge_ToPlateSetId ON assay.PlateSetEdge (ToPlateSetId); -CREATE INDEX IX_PlateSetEdge_RootPlateSetId ON assay.PlateSetEdge (RootPlateSetId); - diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.004-24.005.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.004-24.005.sql deleted file mode 100644 index ce43a9e13b0..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.004-24.005.sql +++ /dev/null @@ -1,16 +0,0 @@ -CREATE TABLE assay.Hit -( - RowId SERIAL, - Container ENTITYID NOT NULL, - ProtocolId INT NOT NULL, - ResultId INT NOT NULL, - RunId INT NOT NULL, - WellLsid VARCHAR(200) NOT NULL, - - CONSTRAINT PK_Hit PRIMARY KEY (RowId), - CONSTRAINT FK_Hit_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId), - CONSTRAINT FK_Protocol_ProtocolId FOREIGN KEY (ProtocolId) REFERENCES exp.Protocol (RowId), - CONSTRAINT FK_Run_RunId FOREIGN KEY (RunId) REFERENCES exp.ExperimentRun (RowId), - CONSTRAINT FK_Well_WellLsid FOREIGN KEY (WellLsid) REFERENCES assay.Well (Lsid), - CONSTRAINT UQ_Hit_RunId_ResultId UNIQUE (RunId, ResultId) -); diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.005-24.006.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.005-24.006.sql deleted file mode 100644 index c165bc5d841..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.005-24.006.sql +++ /dev/null @@ -1,6 +0,0 @@ -ALTER TABLE assay.Hit ADD COLUMN PlateSetPath VARCHAR (4000); - --- Populate paths of pre-existing hits -SELECT core.executeJavaUpgradeCode('populatePlateSetPaths'); - -ALTER TABLE assay.Hit ALTER COLUMN PlateSetPath SET NOT NULL; diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.006-24.007.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.006-24.007.sql deleted file mode 100644 index 2c1f6337fc3..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.006-24.007.sql +++ /dev/null @@ -1,7 +0,0 @@ -ALTER TABLE assay.PlateSet ADD COLUMN Template BOOLEAN NOT NULL DEFAULT FALSE; -UPDATE assay.Plate SET Template = False WHERE Template = True; - -ALTER TABLE assay.Plate ADD COLUMN Archived BOOLEAN NOT NULL DEFAULT FALSE; - -UPDATE assay.Plate SET AssayType = 'Standard' WHERE AssayType IS NULL; -ALTER TABLE assay.Plate ALTER COLUMN AssayType SET NOT NULL; diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.007-24.008.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.007-24.008.sql deleted file mode 100644 index c413b0f4d93..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.007-24.008.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT core.executeJavaUpgradeCode('populatePlateWellTypes'); diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.008-24.009.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.008-24.009.sql deleted file mode 100644 index 60acb08af3b..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.008-24.009.sql +++ /dev/null @@ -1,5 +0,0 @@ --- Add index on assay.Well.SampleId to improve performance of DELETE operation on exp.Material table. -CREATE INDEX IX_Well_SampleId ON assay.Well (SampleId); - --- Add index on assay.WellGroupPositions.WellId to improve performance of DELETE operation on assay.Well table. -CREATE INDEX IX_WellGroupPositions_WellId ON assay.WellGroupPositions (WellId); \ No newline at end of file diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.009-24.010.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.009-24.010.sql deleted file mode 100644 index cbed98e8518..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.009-24.010.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT core.executeJavaUpgradeCode('renameWellMetadataFields'); diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.010-24.011.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.010-24.011.sql deleted file mode 100644 index 7216742b2f4..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.010-24.011.sql +++ /dev/null @@ -1,8 +0,0 @@ -ALTER TABLE assay.plate ADD Barcode VARCHAR(255); -ALTER TABLE assay.plate ADD CONSTRAINT UQ_Barcode UNIQUE (Barcode); - -UPDATE assay.plate SET Barcode = LPAD(rowid::text, 9, '0') WHERE plate.Barcode IS NULL AND plate.template IS FALSE; - -ALTER TABLE assay.plate ADD CONSTRAINT check_template_true_barcode_null CHECK (NOT plate.template OR plate.Barcode IS NULL); - -SELECT core.executeJavaUpgradeCode('updateBarcodeSequence'); diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.011-24.012.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.011-24.012.sql deleted file mode 100644 index 63cef693456..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.011-24.012.sql +++ /dev/null @@ -1,25 +0,0 @@ --- Specify plate metadata columns on the plate set rather than the individual plates -CREATE TABLE assay.PlateSetProperty -( - RowId SERIAL, - PlateSetId INT NOT NULL, - PropertyId INT NOT NULL, - PropertyURI VARCHAR(300) NOT NULL, - - CONSTRAINT PK_PlateSetProperty PRIMARY KEY (RowId), - CONSTRAINT UQ_PlateSetProperty_PlateSetId_PropertyId UNIQUE (PlateSetId, PropertyId), - CONSTRAINT FK_PlateSetProperty_PlateSetId FOREIGN KEY (PlateSetId) REFERENCES assay.PlateSet(RowId) ON DELETE CASCADE, - CONSTRAINT FK_PlateSetProperty_PropertyId FOREIGN KEY (PropertyId) REFERENCES exp.PropertyDescriptor(PropertyId) ON DELETE CASCADE -); - -INSERT INTO assay.PlateSetProperty (PlateSetId, PropertyId, PropertyURI) -SELECT - PL.PlateSet AS PlateSetId, - PP.PropertyId, - PP.PropertyURI -FROM assay.PlateProperty AS PP -INNER JOIN assay.Plate AS PL ON PP.PlateId = PL.RowId -GROUP BY PlateSetId, PropertyId, PropertyURI -ORDER BY PlateSetId, PropertyId; - -DROP TABLE assay.PlateProperty; diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.012-24.013.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.012-24.013.sql deleted file mode 100644 index 614293a5595..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.012-24.013.sql +++ /dev/null @@ -1,11 +0,0 @@ -ALTER TABLE assay.platesetproperty - ADD COLUMN FieldKey VARCHAR(255); - -ALTER TABLE assay.platesetproperty - ADD CONSTRAINT either_identifier - CHECK (PropertyURI IS NOT NULL OR FieldKey IS NOT NULL); - -ALTER TABLE assay.platesetproperty ALTER COLUMN PropertyURI DROP NOT NULL; -ALTER TABLE assay.platesetproperty ALTER COLUMN PropertyId DROP NOT NULL; - -SELECT core.executeJavaUpgradeCode('updateBuiltInColumns'); diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.013-24.014.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.013-24.014.sql deleted file mode 100644 index cfbd66864a5..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.013-24.014.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT core.executeJavaUpgradeCode('initializeWellExclusions'); diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.014-24.015.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.014-24.015.sql deleted file mode 100644 index a6c34330c03..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.014-24.015.sql +++ /dev/null @@ -1,5 +0,0 @@ -ALTER TABLE assay.plateset ADD COLUMN LSID LSIDtype; - -SELECT core.executeJavaUpgradeCode('addLsidToPlateSets'); - -ALTER TABLE assay.plateset ALTER COLUMN LSID SET NOT NULL; diff --git a/assay/resources/schemas/dbscripts/postgresql/assay-24.015-24.016.sql b/assay/resources/schemas/dbscripts/postgresql/assay-24.015-24.016.sql deleted file mode 100644 index fa1a4ccd8a3..00000000000 --- a/assay/resources/schemas/dbscripts/postgresql/assay-24.015-24.016.sql +++ /dev/null @@ -1,16 +0,0 @@ -CREATE TABLE assay.FilterCriteria -( - RowId SERIAL, - PropertyId INT NOT NULL, - ReferencePropertyId INT NOT NULL, - DomainId INT NOT NULL, - Operation VARCHAR(50) NOT NULL, - Value VARCHAR(4000) NULL, - - CONSTRAINT PK_FilterCriteria PRIMARY KEY (RowId), - CONSTRAINT FK_FilterCriteria_PropertyDescriptor FOREIGN KEY (PropertyId) REFERENCES exp.PropertyDescriptor (PropertyId) ON DELETE CASCADE, - CONSTRAINT FK_FilterCriteria_PropertyDescriptor_Reference FOREIGN KEY (ReferencePropertyId) REFERENCES exp.PropertyDescriptor (PropertyId) ON DELETE CASCADE, - CONSTRAINT FK_FilterCriteria_DomainDescriptor FOREIGN KEY (DomainId) REFERENCES exp.DomainDescriptor (DomainId) ON DELETE CASCADE -); - -SELECT core.executeJavaUpgradeCode('initializeHitSelectionCriteria'); diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-0.000-24.000.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-0.000-24.000.sql deleted file mode 100644 index a3207caf9eb..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-0.000-24.000.sql +++ /dev/null @@ -1,119 +0,0 @@ -/* - For LabKey 19.2 and earlier, the assayresult schema and the Plate, WellGroup, and Well tables were managed by the - study module. As of 19.3, the assay module now manages these objects, with the tables moving from the "study" schema - to the new "assay" schema. - */ - -CREATE SCHEMA assay -GO -CREATE SCHEMA assayresult -GO - -CREATE TABLE assay.Plate -( - RowId INT IDENTITY(1,1), - LSID NVARCHAR(200) NOT NULL, - Container ENTITYID NOT NULL, - Name NVARCHAR(200) NULL, - CreatedBy USERID NOT NULL, - Created DATETIME NOT NULL, - Template BIT NOT NULL, - DataFileId ENTITYID, - Rows INT NOT NULL, - Columns INT NOT NULL, - Type NVARCHAR(200), - - CONSTRAINT PK_Plate PRIMARY KEY (RowId) -); - -CREATE INDEX IX_Plate_Container ON assay.Plate(Container); - -ALTER TABLE assay.plate ADD - Modified DATETIME, - ModifiedBy USERID; - -ALTER TABLE assay.plate ALTER COLUMN Modified DATETIME NOT NULL; -ALTER TABLE assay.plate ALTER COLUMN ModifiedBy USERID NOT NULL; - -ALTER TABLE assay.plate - ADD CONSTRAINT uq_plate_lsid UNIQUE (lsid); - --- plate template (not instances) names are unique in each container -CREATE UNIQUE INDEX uq_plate_container_name_template ON assay.plate (container, name) WHERE template=1; - -CREATE TABLE assay.WellGroup -( - RowId INT IDENTITY(1,1), - PlateId INT NOT NULL, - LSID NVARCHAR(200) NOT NULL, - Container ENTITYID NOT NULL, - Name NVARCHAR(200) NULL, - Template BIT NOT NULL, - TypeName NVARCHAR(50) NOT NULL, - - CONSTRAINT PK_WellGroup PRIMARY KEY (RowId), - CONSTRAINT FK_WellGroup_Plate FOREIGN KEY (PlateId) REFERENCES assay.Plate(RowId) -); - -CREATE INDEX IX_WellGroup_PlateId ON assay.WellGroup(PlateId); -CREATE INDEX IX_WellGroup_Container ON assay.WellGroup(Container); - -ALTER TABLE assay.wellgroup - ADD CONSTRAINT uq_wellgroup_lsid UNIQUE (lsid); - --- well group names must be unique within each well group type -ALTER TABLE assay.wellgroup - ADD CONSTRAINT uq_wellgroup_plateid_typename_name UNIQUE (plateid, typename, name); - -CREATE TABLE assay.Well -( - RowId INT IDENTITY(1,1), - LSID NVARCHAR(200) NOT NULL, - Container ENTITYID NOT NULL, - Value FLOAT NULL, - Dilution FLOAT NULL, - PlateId INT NOT NULL, - Row INT NOT NULL, - Col INT NOT NULL, - - CONSTRAINT PK_Well PRIMARY KEY (RowId), - CONSTRAINT FK_Well_Plate FOREIGN KEY (PlateId) REFERENCES assay.Plate(RowId) -); - -CREATE INDEX IX_Well_PlateId ON assay.Well(PlateId); -CREATE INDEX IX_Well_Container ON assay.Well(Container); - -ALTER TABLE assay.well - ADD CONSTRAINT uq_well_lsid UNIQUE (lsid); - --- each well position is unique on the plate -ALTER TABLE assay.well - ADD CONSTRAINT uq_well_plateid_row_col UNIQUE (plateid, row, col); - -ALTER TABLE Assay.Well ADD SampleId INTEGER NULL; -ALTER TABLE Assay.Well ADD CONSTRAINT FK_SampleId_ExpMaterial FOREIGN KEY (SampleId) REFERENCES exp.material (RowId); - -CREATE TABLE assay.WellGroupPositions -( - RowId INT IDENTITY(1,1) NOT NULL, - WellId INT NOT NULL, - WellGroupId INT NOT NULL, - - CONSTRAINT PK_WellGroupPositions PRIMARY KEY (RowId), - CONSTRAINT FK_WellGroupPositions_Well FOREIGN KEY (WellId) REFERENCES assay.Well(RowId), - CONSTRAINT FK_WellGroupPositions_WellGroup FOREIGN KEY (WellGroupId) REFERENCES assay.WellGroup(RowId), - CONSTRAINT UQ_WellGroupPositions_WellGroup_Well UNIQUE (WellGroupId, WellId) -); - -CREATE TABLE assay.PlateProperty -( - RowId INT IDENTITY(1,1), - PlateId INT NOT NULL, - PropertyId INT NOT NULL, - PropertyURI NVARCHAR(300) NOT NULL, - - CONSTRAINT PK_PlateProperty PRIMARY KEY (RowId), - CONSTRAINT UQ_PlateProperty_PlateId_PropertyId UNIQUE (PlateId, PropertyId), - CONSTRAINT FK_PlateProperty_PlateId FOREIGN KEY (PlateId) REFERENCES assay.Plate(RowId), - CONSTRAINT FK_PlateProperty_PropertyId FOREIGN KEY (PropertyId) REFERENCES exp.PropertyDescriptor(PropertyId) -); diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-0.000-25.000.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-0.000-25.000.sql new file mode 100644 index 00000000000..d7d9fc6313f --- /dev/null +++ b/assay/resources/schemas/dbscripts/sqlserver/assay-0.000-25.000.sql @@ -0,0 +1,356 @@ +/* + For LabKey 19.2 and earlier, the assayresult schema and the Plate, WellGroup, and Well tables were managed by the + study module. As of 19.3, the assay module now manages these objects, with the tables moving from the "study" schema + to the new "assay" schema. + */ + +CREATE SCHEMA assay +GO +CREATE SCHEMA assayresult +GO +-- Provisioned schema used by PlateMetadataDomainKind +CREATE SCHEMA assaywell; +GO + +CREATE TABLE assay.Plate +( + RowId INT IDENTITY(1,1), + LSID NVARCHAR(200) NOT NULL, + Container ENTITYID NOT NULL, + Name NVARCHAR(200) NULL, + CreatedBy USERID NOT NULL, + Created DATETIME NOT NULL, + Template BIT NOT NULL, + DataFileId ENTITYID, + Rows INT NOT NULL, + Columns INT NOT NULL, + Type NVARCHAR(200), + + CONSTRAINT PK_Plate PRIMARY KEY (RowId) +); + +CREATE INDEX IX_Plate_Container ON assay.Plate(Container); + +ALTER TABLE assay.plate ADD + Modified DATETIME, + ModifiedBy USERID; + +ALTER TABLE assay.plate ALTER COLUMN Modified DATETIME NOT NULL; +ALTER TABLE assay.plate ALTER COLUMN ModifiedBy USERID NOT NULL; + +ALTER TABLE assay.plate + ADD CONSTRAINT uq_plate_lsid UNIQUE (lsid); + +-- plate template (not instances) names are unique in each container +CREATE UNIQUE INDEX uq_plate_container_name_template ON assay.plate (container, name) WHERE template=1; + +CREATE TABLE assay.WellGroup +( + RowId INT IDENTITY(1,1), + PlateId INT NOT NULL, + LSID NVARCHAR(200) NOT NULL, + Container ENTITYID NOT NULL, + Name NVARCHAR(200) NULL, + Template BIT NOT NULL, + TypeName NVARCHAR(50) NOT NULL, + + CONSTRAINT PK_WellGroup PRIMARY KEY (RowId), + CONSTRAINT FK_WellGroup_Plate FOREIGN KEY (PlateId) REFERENCES assay.Plate(RowId) +); + +CREATE INDEX IX_WellGroup_PlateId ON assay.WellGroup(PlateId); +CREATE INDEX IX_WellGroup_Container ON assay.WellGroup(Container); + +ALTER TABLE assay.wellgroup + ADD CONSTRAINT uq_wellgroup_lsid UNIQUE (lsid); + +-- well group names must be unique within each well group type +ALTER TABLE assay.wellgroup + ADD CONSTRAINT uq_wellgroup_plateid_typename_name UNIQUE (plateid, typename, name); + +CREATE TABLE assay.Well +( + RowId INT IDENTITY(1,1), + LSID NVARCHAR(200) NOT NULL, + Container ENTITYID NOT NULL, + Value FLOAT NULL, + Dilution FLOAT NULL, + PlateId INT NOT NULL, + Row INT NOT NULL, + Col INT NOT NULL, + + CONSTRAINT PK_Well PRIMARY KEY (RowId), + CONSTRAINT FK_Well_Plate FOREIGN KEY (PlateId) REFERENCES assay.Plate(RowId) +); + +CREATE INDEX IX_Well_PlateId ON assay.Well(PlateId); +CREATE INDEX IX_Well_Container ON assay.Well(Container); + +ALTER TABLE assay.well + ADD CONSTRAINT uq_well_lsid UNIQUE (lsid); + +-- each well position is unique on the plate +ALTER TABLE assay.well + ADD CONSTRAINT uq_well_plateid_row_col UNIQUE (plateid, row, col); + +ALTER TABLE Assay.Well ADD SampleId INTEGER NULL; +ALTER TABLE Assay.Well ADD CONSTRAINT FK_SampleId_ExpMaterial FOREIGN KEY (SampleId) REFERENCES exp.material (RowId); + +CREATE TABLE assay.WellGroupPositions +( + RowId INT IDENTITY(1,1) NOT NULL, + WellId INT NOT NULL, + WellGroupId INT NOT NULL, + + CONSTRAINT PK_WellGroupPositions PRIMARY KEY (RowId), + CONSTRAINT FK_WellGroupPositions_Well FOREIGN KEY (WellId) REFERENCES assay.Well(RowId), + CONSTRAINT FK_WellGroupPositions_WellGroup FOREIGN KEY (WellGroupId) REFERENCES assay.WellGroup(RowId), + CONSTRAINT UQ_WellGroupPositions_WellGroup_Well UNIQUE (WellGroupId, WellId) +); + +CREATE TABLE assay.PlateProperty +( + RowId INT IDENTITY(1,1), + PlateId INT NOT NULL, + PropertyId INT NOT NULL, + PropertyURI NVARCHAR(300) NOT NULL, + + CONSTRAINT PK_PlateProperty PRIMARY KEY (RowId), + CONSTRAINT UQ_PlateProperty_PlateId_PropertyId UNIQUE (PlateId, PropertyId), + CONSTRAINT FK_PlateProperty_PlateId FOREIGN KEY (PlateId) REFERENCES assay.Plate(RowId), + CONSTRAINT FK_PlateProperty_PropertyId FOREIGN KEY (PropertyId) REFERENCES exp.PropertyDescriptor(PropertyId) +); + +/* 24.xxx SQL scripts */ + +CREATE TABLE assay.PlateSet +( + RowId INT NOT NULL, + Name NVARCHAR(200) NOT NULL, + Container ENTITYID NOT NULL, + Created DATETIME NOT NULL, + CreatedBy USERID NOT NULL, + Modified DATETIME NOT NULL, + ModifiedBy USERID NOT NULL, + Archived BIT NOT NULL DEFAULT 0, + + CONSTRAINT PK_PlateSet PRIMARY KEY (RowId) +); + +-- Insert a row into the plate set table for every plate in the system, store the plate row ID in the plate set table +-- in order to create the FK from the plate to plate set table +INSERT INTO assay.PlateSet (RowId, Name, Container, Created, CreatedBy, Modified, ModifiedBy) +SELECT RowId, 'TempPlateSet', Container, getdate(), CreatedBy, getdate(), ModifiedBy FROM assay.Plate; + +-- Add the plate set field to the plate table and populate it with the plate set row ID +ALTER TABLE assay.Plate ADD PlateSet INT; +GO + +UPDATE assay.Plate SET PlateSet = Rowid; +ALTER TABLE assay.plate ALTER COLUMN PlateSet INT NOT NULL; +ALTER TABLE assay.Plate ADD CONSTRAINT FK_Plate_PlateSet FOREIGN KEY (PlateSet) REFERENCES assay.PlateSet (RowId); +CREATE INDEX IX_Plate_PlateSet ON assay.Plate (PlateSet); + +CREATE TABLE assay.PlateType +( + RowId INT IDENTITY(1,1), + Rows INT NOT NULL, + Columns INT NOT NULL, + Description NVARCHAR(300) NOT NULL, + Archived BIT NOT NULL DEFAULT 0, + + CONSTRAINT PK_PlateType PRIMARY KEY (RowId), + CONSTRAINT UQ_PlateType_Rows_Cols UNIQUE (Rows, Columns) +); + +INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (3, 4, '12 well (3x4)'); +INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (4, 6, '24 well (4x6)'); +INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (6, 8, '48 well (6x8)'); +INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (8, 12, '96 well (8x12)'); +INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (16, 24, '384 well (16x24)'); +INSERT INTO assay.PlateType (Rows, Columns, Description, Archived) VALUES (32, 48, '1536 well (32x48)', 1); +INSERT INTO assay.PlateType (Rows, Columns, Description, Archived) VALUES (0, 0, 'Invalid Plate Type (Plates which were created with non-valid row & column combinations)', 1); + +-- Rename type column to assayType +EXEC sp_rename 'assay.Plate.Type', 'AssayType', 'COLUMN'; +-- Add type as a FK to assay.PlateType +ALTER TABLE assay.Plate ADD PlateType INT; +GO +ALTER TABLE assay.Plate ADD CONSTRAINT FK_Plate_PlateType FOREIGN KEY (PlateType) REFERENCES assay.PlateType (RowId); + +-- Add ID and description columns to Plate and PlateSet tables +ALTER TABLE assay.Plate ADD PlateId NVARCHAR(200); +ALTER TABLE assay.Plate ADD Description NVARCHAR(300); +ALTER TABLE assay.PlateSet ADD PlateSetId NVARCHAR(200); +ALTER TABLE assay.PlateSet ADD Description NVARCHAR(300); +GO + +-- Most existing plate sets will have a generated name, but mutated ones will get fixed up by the java upgrade script +UPDATE assay.PlateSet SET PlateSetId = Name; + +UPDATE assay.Plate +SET PlateType = + CASE + WHEN (Rows = 3 AND Columns = 4) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 3 AND Columns = 4) + WHEN (Rows = 4 AND Columns = 6) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 4 AND Columns = 6) + WHEN (Rows = 6 AND Columns = 8) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 6 AND Columns = 8) + WHEN (Rows = 8 AND Columns = 12) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 8 AND Columns = 12) + WHEN (Rows = 16 AND Columns = 24) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 16 AND Columns = 24) + WHEN (Rows = 32 AND Columns = 48) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 32 AND Columns = 48) + ELSE (SELECT RowId FROM assay.PlateType WHERE Rows = 0 AND Columns = 0) + END +WHERE PlateType IS NULL; + +ALTER TABLE assay.Plate ALTER COLUMN PlateType INT NOT NULL; +ALTER TABLE assay.Plate DROP COLUMN Rows; +ALTER TABLE assay.Plate DROP COLUMN Columns; + +-- finalize plate and plateSet ID columns +ALTER TABLE assay.Plate ALTER COLUMN PlateId NVARCHAR(200) NOT NULL; +ALTER TABLE assay.Plate ADD CONSTRAINT UQ_Plate_PlateId UNIQUE (PlateId); + +ALTER TABLE assay.PlateSet ALTER COLUMN PlateSetId NVARCHAR(200) NOT NULL; +ALTER TABLE assay.PlateSet ADD CONSTRAINT UQ_PlateSet_PlateSetId UNIQUE (PlateSetId); + +ALTER TABLE assay.PlateSet ADD Type NVARCHAR(64); +ALTER TABLE assay.PlateSet ADD RootPlateSetId INT; +ALTER TABLE assay.PlateSet ADD PrimaryPlateSetId INT; +GO + +ALTER TABLE assay.PlateSet ADD CONSTRAINT FK_PlateSet_RootPlateSetId FOREIGN KEY (RootPlateSetId) REFERENCES assay.PlateSet (RowId); +ALTER TABLE assay.PlateSet ADD CONSTRAINT FK_PlateSet_PrimaryPlateSetId FOREIGN KEY (PrimaryPlateSetId) REFERENCES assay.PlateSet (RowId); + +-- Update all pre-existing plate sets to type "assay" +UPDATE assay.PlateSet SET type = 'assay'; + +ALTER TABLE assay.PlateSet ALTER COLUMN Type NVARCHAR(64) NOT NULL; + +CREATE TABLE assay.PlateSetEdge +( + FromPlateSetId INT NOT NULL, + ToPlateSetId INT NOT NULL, + RootPlateSetId INT NOT NULL, + + CONSTRAINT FK_PlateSet_FromPlate FOREIGN KEY (FromPlateSetId) REFERENCES assay.PlateSet (RowId), + CONSTRAINT FK_PlateSet_ToPlate FOREIGN KEY (ToPlateSetId) REFERENCES assay.PlateSet (RowId), + CONSTRAINT FK_PlateSet_RootPlate FOREIGN KEY (RootPlateSetId) REFERENCES assay.PlateSet (RowId), + CONSTRAINT UQ_PlateSetEdge_FromPlate_ToPlate UNIQUE (FromPlateSetId, ToPlateSetId) +); + +CREATE INDEX IX_PlateSetEdge_FromPlateSetId ON assay.PlateSetEdge (FromPlateSetId); +CREATE INDEX IX_PlateSetEdge_ToPlateSetId ON assay.PlateSetEdge (ToPlateSetId); +CREATE INDEX IX_PlateSetEdge_RootPlateSetId ON assay.PlateSetEdge (RootPlateSetId); + +CREATE TABLE assay.Hit +( + RowId INT IDENTITY(1,1), + Container ENTITYID NOT NULL, + ProtocolId INT NOT NULL, + ResultId INT NOT NULL, + RunId INT NOT NULL, + WellLsid NVARCHAR(200) NOT NULL, + + CONSTRAINT PK_Hit PRIMARY KEY (RowId), + CONSTRAINT FK_Hit_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId), + CONSTRAINT FK_Protocol_ProtocolId FOREIGN KEY (ProtocolId) REFERENCES exp.Protocol (RowId), + CONSTRAINT FK_Run_RunId FOREIGN KEY (RunId) REFERENCES exp.ExperimentRun (RowId), + CONSTRAINT FK_Well_WellLsid FOREIGN KEY (WellLsid) REFERENCES assay.Well (Lsid), + CONSTRAINT UQ_Hit_RunId_ResultId UNIQUE (RunId, ResultId) +); + +ALTER TABLE assay.Hit ADD PlateSetPath NVARCHAR (4000); +GO + +ALTER TABLE assay.Hit ALTER COLUMN PlateSetPath NVARCHAR (4000) NOT NULL; +GO + +ALTER TABLE assay.PlateSet ADD Template BIT NOT NULL DEFAULT 0; +UPDATE assay.Plate SET Template = 0 WHERE Template = 1; + +ALTER TABLE assay.Plate ADD Archived BIT NOT NULL DEFAULT 0; + +UPDATE assay.Plate SET AssayType = 'Standard' WHERE AssayType IS NULL; +ALTER TABLE assay.Plate ALTER COLUMN AssayType NVARCHAR(200) NOT NULL; + +-- Add index on assay.Well.SampleId to improve performance of DELETE operation on exp.Material table. +CREATE INDEX IX_Well_SampleId ON assay.Well (SampleId); + +-- Add index on assay.WellGroupPositions.WellId to improve performance of DELETE operation on assay.Well table. +CREATE INDEX IX_WellGroupPositions_WellId ON assay.WellGroupPositions (WellId); + +ALTER TABLE assay.plate ADD Barcode NVARCHAR(255); +GO +CREATE UNIQUE NONCLUSTERED INDEX UQ_Barcode ON assay.plate(Barcode) WHERE Barcode IS NOT NULL; +GO + +UPDATE assay.plate +SET Barcode = RIGHT(REPLICATE('0', 9) + CAST(rowid AS VARCHAR(9)), 9) +WHERE Barcode IS NULL AND template = 0; + +ALTER TABLE assay.plate ADD CONSTRAINT check_template_true_barcode_null CHECK ((template = 0) OR Barcode IS NULL); + +-- Specify plate metadata columns on the plate set rather than the individual plates +CREATE TABLE assay.PlateSetProperty +( + RowId INT IDENTITY(1,1), + PlateSetId INT NOT NULL, + PropertyId INT NOT NULL, + PropertyURI NVARCHAR(300) NOT NULL, + + CONSTRAINT PK_PlateSetProperty PRIMARY KEY (RowId), + CONSTRAINT UQ_PlateSetProperty_PlateSetId_PropertyId UNIQUE (PlateSetId, PropertyId), + CONSTRAINT FK_PlateSetProperty_PlateSetId FOREIGN KEY (PlateSetId) REFERENCES assay.PlateSet(RowId) ON DELETE CASCADE, + CONSTRAINT FK_PlateSetProperty_PropertyId FOREIGN KEY (PropertyId) REFERENCES exp.PropertyDescriptor(PropertyId) ON DELETE CASCADE +); + +INSERT INTO assay.PlateSetProperty (PlateSetId, PropertyId, PropertyURI) +SELECT + PL.PlateSet AS PlateSetId, + PP.PropertyId, + PP.PropertyURI +FROM assay.PlateProperty AS PP +INNER JOIN assay.Plate AS PL ON PP.PlateId = PL.RowId +GROUP BY PL.PlateSet, PP.PropertyId, PP.PropertyURI +ORDER BY PlateSetId, PropertyId; + +DROP TABLE assay.PlateProperty; +GO + +ALTER TABLE assay.platesetproperty + ADD FieldKey NVARCHAR(255); +GO + +ALTER TABLE assay.platesetproperty + ADD CONSTRAINT either_identifier + CHECK (PropertyURI IS NOT NULL OR FieldKey IS NOT NULL); + +ALTER TABLE assay.platesetproperty ALTER COLUMN PropertyURI NVARCHAR(300) NULL; +ALTER TABLE assay.platesetproperty ALTER COLUMN PropertyId INT NULL; + +ALTER TABLE assay.platesetproperty DROP CONSTRAINT UQ_PlateSetProperty_PlateSetId_PropertyId; +CREATE UNIQUE INDEX UQ_PlateSetProperty_PlateSetId_PropertyId ON assay.platesetproperty (PlateSetId, PropertyId) WHERE PropertyId IS NOT NULL; + +ALTER TABLE assay.plateset ADD LSID LSIDtype; +GO + +ALTER TABLE assay.plateset ALTER COLUMN LSID LSIDType NOT NULL; +GO + +CREATE TABLE assay.FilterCriteria +( + RowId INT IDENTITY(1,1), + PropertyId INT NOT NULL, + ReferencePropertyId INT NOT NULL, + DomainId INT NOT NULL, + Operation NVARCHAR(50) NOT NULL, + Value NVARCHAR(4000) NULL, + + CONSTRAINT PK_FilterCriteria PRIMARY KEY (RowId), + CONSTRAINT FK_FilterCriteria_DomainDescriptor FOREIGN KEY (DomainId) REFERENCES exp.DomainDescriptor (DomainId) ON DELETE CASCADE, + + -- SQL Server does not allow for multiple foreign keys to the same table to utilize ON DELETE CASCADE as it may + -- cause cycles or multiple cascade paths. The solution is to only ON DELETE CASCADE for one foreign key and + -- clean up upon delete of the property for other changes. See AssayResultDomainKind.deletePropertyDescriptor(). + CONSTRAINT FK_FilterCriteria_PropertyDescriptor FOREIGN KEY (PropertyId) REFERENCES exp.PropertyDescriptor (PropertyId) ON DELETE CASCADE, + CONSTRAINT FK_FilterCriteria_PropertyDescriptor_Reference FOREIGN KEY (ReferencePropertyId) REFERENCES exp.PropertyDescriptor (PropertyId) ON DELETE NO ACTION +); diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.000-24.001.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.000-24.001.sql deleted file mode 100644 index d04bc890411..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.000-24.001.sql +++ /dev/null @@ -1,30 +0,0 @@ -CREATE TABLE assay.PlateSet -( - RowId INT NOT NULL, - Name NVARCHAR(200) NOT NULL, - Container ENTITYID NOT NULL, - Created DATETIME NOT NULL, - CreatedBy USERID NOT NULL, - Modified DATETIME NOT NULL, - ModifiedBy USERID NOT NULL, - Archived BIT NOT NULL DEFAULT 0, - - CONSTRAINT PK_PlateSet PRIMARY KEY (RowId) -); - --- Insert a row into the plate set table for every plate in the system, store the plate row ID in the plate set table --- in order to create the FK from the plate to plate set table -INSERT INTO assay.PlateSet (RowId, Name, Container, Created, CreatedBy, Modified, ModifiedBy) -SELECT RowId, 'TempPlateSet', Container, getdate(), CreatedBy, getdate(), ModifiedBy FROM assay.Plate; - --- Add the plate set field to the plate table and populate it with the plate set row ID -ALTER TABLE assay.Plate ADD PlateSet INT; -GO - -UPDATE assay.Plate SET PlateSet = Rowid; -ALTER TABLE assay.plate ALTER COLUMN PlateSet INT NOT NULL; -ALTER TABLE assay.Plate ADD CONSTRAINT FK_Plate_PlateSet FOREIGN KEY (PlateSet) REFERENCES assay.PlateSet (RowId); -CREATE INDEX IX_Plate_PlateSet ON assay.Plate (PlateSet); - --- Run the java upgrade script to update plate set and plate tables to create the name expression based name values -EXEC core.executeJavaUpgradeCode 'updatePlateSetNames'; \ No newline at end of file diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.001-24.002.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.001-24.002.sql deleted file mode 100644 index 7bc1ade63be..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.001-24.002.sql +++ /dev/null @@ -1,63 +0,0 @@ -CREATE TABLE assay.PlateType -( - RowId INT IDENTITY(1,1), - Rows INT NOT NULL, - Columns INT NOT NULL, - Description NVARCHAR(300) NOT NULL, - Archived BIT NOT NULL DEFAULT 0, - - CONSTRAINT PK_PlateType PRIMARY KEY (RowId), - CONSTRAINT UQ_PlateType_Rows_Cols UNIQUE (Rows, Columns) -); - -INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (3, 4, '12 well (3x4)'); -INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (4, 6, '24 well (4x6)'); -INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (6, 8, '48 well (6x8)'); -INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (8, 12, '96 well (8x12)'); -INSERT INTO assay.PlateType (Rows, Columns, Description) VALUES (16, 24, '384 well (16x24)'); -INSERT INTO assay.PlateType (Rows, Columns, Description, Archived) VALUES (32, 48, '1536 well (32x48)', 1); -INSERT INTO assay.PlateType (Rows, Columns, Description, Archived) VALUES (0, 0, 'Invalid Plate Type (Plates which were created with non-valid row & column combinations)', 1); - --- Rename type column to assayType -EXEC sp_rename 'assay.Plate.Type', 'AssayType', 'COLUMN'; --- Add type as a FK to assay.PlateType -ALTER TABLE assay.Plate ADD PlateType INT; -GO -ALTER TABLE assay.Plate ADD CONSTRAINT FK_Plate_PlateType FOREIGN KEY (PlateType) REFERENCES assay.PlateType (RowId); - --- Add ID and description columns to Plate and PlateSet tables -ALTER TABLE assay.Plate ADD PlateId NVARCHAR(200); -ALTER TABLE assay.Plate ADD Description NVARCHAR(300); -ALTER TABLE assay.PlateSet ADD PlateSetId NVARCHAR(200); -ALTER TABLE assay.PlateSet ADD Description NVARCHAR(300); -GO - --- Most existing plate sets will have a generated name, but mutated ones will get fixed up by the java upgrade script -UPDATE assay.PlateSet SET PlateSetId = Name; - -UPDATE assay.Plate -SET PlateType = - CASE - WHEN (Rows = 3 AND Columns = 4) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 3 AND Columns = 4) - WHEN (Rows = 4 AND Columns = 6) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 4 AND Columns = 6) - WHEN (Rows = 6 AND Columns = 8) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 6 AND Columns = 8) - WHEN (Rows = 8 AND Columns = 12) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 8 AND Columns = 12) - WHEN (Rows = 16 AND Columns = 24) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 16 AND Columns = 24) - WHEN (Rows = 32 AND Columns = 48) THEN (SELECT RowId FROM assay.PlateType WHERE Rows = 32 AND Columns = 48) - ELSE (SELECT RowId FROM assay.PlateType WHERE Rows = 0 AND Columns = 0) - END -WHERE PlateType IS NULL; - -ALTER TABLE assay.Plate ALTER COLUMN PlateType INT NOT NULL; -ALTER TABLE assay.Plate DROP COLUMN Rows; -ALTER TABLE assay.Plate DROP COLUMN Columns; - --- upgrade script to set the plate ID value in assay.Plate -EXEC core.executeJavaUpgradeCode 'initializePlateAndPlateSetIDs'; - --- finalize plate and plateSet ID columns -ALTER TABLE assay.Plate ALTER COLUMN PlateId NVARCHAR(200) NOT NULL; -ALTER TABLE assay.Plate ADD CONSTRAINT UQ_Plate_PlateId UNIQUE (PlateId); - -ALTER TABLE assay.PlateSet ALTER COLUMN PlateSetId NVARCHAR(200) NOT NULL; -ALTER TABLE assay.PlateSet ADD CONSTRAINT UQ_PlateSet_PlateSetId UNIQUE (PlateSetId); diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.002-24.003.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.002-24.003.sql deleted file mode 100644 index 231e36fdea4..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.002-24.003.sql +++ /dev/null @@ -1,6 +0,0 @@ --- Provisioned schema used by PlateMetadataDomainKind -CREATE SCHEMA assaywell; -GO - --- upgrade script to set the plate ID value in assay.Plate -EXEC core.executeJavaUpgradeCode 'deletePlateVocabDomains'; diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.003-24.004.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.003-24.004.sql deleted file mode 100644 index 3da4dbaa6c8..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.003-24.004.sql +++ /dev/null @@ -1,28 +0,0 @@ -ALTER TABLE assay.PlateSet ADD Type NVARCHAR(64); -ALTER TABLE assay.PlateSet ADD RootPlateSetId INT; -ALTER TABLE assay.PlateSet ADD PrimaryPlateSetId INT; -GO - -ALTER TABLE assay.PlateSet ADD CONSTRAINT FK_PlateSet_RootPlateSetId FOREIGN KEY (RootPlateSetId) REFERENCES assay.PlateSet (RowId); -ALTER TABLE assay.PlateSet ADD CONSTRAINT FK_PlateSet_PrimaryPlateSetId FOREIGN KEY (PrimaryPlateSetId) REFERENCES assay.PlateSet (RowId); - --- Update all pre-existing plate sets to type "assay" -UPDATE assay.PlateSet SET type = 'assay'; - -ALTER TABLE assay.PlateSet ALTER COLUMN Type NVARCHAR(64) NOT NULL; - -CREATE TABLE assay.PlateSetEdge -( - FromPlateSetId INT NOT NULL, - ToPlateSetId INT NOT NULL, - RootPlateSetId INT NOT NULL, - - CONSTRAINT FK_PlateSet_FromPlate FOREIGN KEY (FromPlateSetId) REFERENCES assay.PlateSet (RowId), - CONSTRAINT FK_PlateSet_ToPlate FOREIGN KEY (ToPlateSetId) REFERENCES assay.PlateSet (RowId), - CONSTRAINT FK_PlateSet_RootPlate FOREIGN KEY (RootPlateSetId) REFERENCES assay.PlateSet (RowId), - CONSTRAINT UQ_PlateSetEdge_FromPlate_ToPlate UNIQUE (FromPlateSetId, ToPlateSetId) -); - -CREATE INDEX IX_PlateSetEdge_FromPlateSetId ON assay.PlateSetEdge (FromPlateSetId); -CREATE INDEX IX_PlateSetEdge_ToPlateSetId ON assay.PlateSetEdge (ToPlateSetId); -CREATE INDEX IX_PlateSetEdge_RootPlateSetId ON assay.PlateSetEdge (RootPlateSetId); diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.004-24.005.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.004-24.005.sql deleted file mode 100644 index f6ffbe21df1..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.004-24.005.sql +++ /dev/null @@ -1,16 +0,0 @@ -CREATE TABLE assay.Hit -( - RowId INT IDENTITY(1,1), - Container ENTITYID NOT NULL, - ProtocolId INT NOT NULL, - ResultId INT NOT NULL, - RunId INT NOT NULL, - WellLsid NVARCHAR(200) NOT NULL, - - CONSTRAINT PK_Hit PRIMARY KEY (RowId), - CONSTRAINT FK_Hit_Container FOREIGN KEY (Container) REFERENCES core.Containers (EntityId), - CONSTRAINT FK_Protocol_ProtocolId FOREIGN KEY (ProtocolId) REFERENCES exp.Protocol (RowId), - CONSTRAINT FK_Run_RunId FOREIGN KEY (RunId) REFERENCES exp.ExperimentRun (RowId), - CONSTRAINT FK_Well_WellLsid FOREIGN KEY (WellLsid) REFERENCES assay.Well (Lsid), - CONSTRAINT UQ_Hit_RunId_ResultId UNIQUE (RunId, ResultId) -); diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.005-24.006.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.005-24.006.sql deleted file mode 100644 index 60b4c333a35..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.005-24.006.sql +++ /dev/null @@ -1,8 +0,0 @@ -ALTER TABLE assay.Hit ADD PlateSetPath NVARCHAR (4000); -GO - --- Populate paths of pre-existing hits -EXEC core.executeJavaUpgradeCode 'populatePlateSetPaths'; - -ALTER TABLE assay.Hit ALTER COLUMN PlateSetPath NVARCHAR (4000) NOT NULL; -GO diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.006-24.007.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.006-24.007.sql deleted file mode 100644 index 0e2d1c99d14..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.006-24.007.sql +++ /dev/null @@ -1,7 +0,0 @@ -ALTER TABLE assay.PlateSet ADD Template BIT NOT NULL DEFAULT 0; -UPDATE assay.Plate SET Template = 0 WHERE Template = 1; - -ALTER TABLE assay.Plate ADD Archived BIT NOT NULL DEFAULT 0; - -UPDATE assay.Plate SET AssayType = 'Standard' WHERE AssayType IS NULL; -ALTER TABLE assay.Plate ALTER COLUMN AssayType NVARCHAR(200) NOT NULL; diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.007-24.008.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.007-24.008.sql deleted file mode 100644 index 20ca47b7647..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.007-24.008.sql +++ /dev/null @@ -1,2 +0,0 @@ --- Biologics is not supported on SQL Server so this upgrade is not applicable --- EXEC core.executeJavaUpgradeCode 'populatePlateWellTypes'; diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.008-24.009.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.008-24.009.sql deleted file mode 100644 index 60acb08af3b..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.008-24.009.sql +++ /dev/null @@ -1,5 +0,0 @@ --- Add index on assay.Well.SampleId to improve performance of DELETE operation on exp.Material table. -CREATE INDEX IX_Well_SampleId ON assay.Well (SampleId); - --- Add index on assay.WellGroupPositions.WellId to improve performance of DELETE operation on assay.Well table. -CREATE INDEX IX_WellGroupPositions_WellId ON assay.WellGroupPositions (WellId); \ No newline at end of file diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.009-24.010.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.009-24.010.sql deleted file mode 100644 index b47165c52d3..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.009-24.010.sql +++ /dev/null @@ -1 +0,0 @@ -EXEC core.executeJavaUpgradeCode 'renameWellMetadataFields'; \ No newline at end of file diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.010-24.011.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.010-24.011.sql deleted file mode 100644 index 7a5697da5a7..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.010-24.011.sql +++ /dev/null @@ -1,12 +0,0 @@ -ALTER TABLE assay.plate ADD Barcode NVARCHAR(255); -GO -CREATE UNIQUE NONCLUSTERED INDEX UQ_Barcode ON assay.plate(Barcode) WHERE Barcode IS NOT NULL; -GO - -UPDATE assay.plate -SET Barcode = RIGHT(REPLICATE('0', 9) + CAST(rowid AS VARCHAR(9)), 9) -WHERE Barcode IS NULL AND template = 0; - -ALTER TABLE assay.plate ADD CONSTRAINT check_template_true_barcode_null CHECK ((template = 0) OR Barcode IS NULL); - -EXEC core.executeJavaUpgradeCode 'updateBarcodeSequence'; diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.011-24.012.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.011-24.012.sql deleted file mode 100644 index 3e5313f81cb..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.011-24.012.sql +++ /dev/null @@ -1,26 +0,0 @@ --- Specify plate metadata columns on the plate set rather than the individual plates -CREATE TABLE assay.PlateSetProperty -( - RowId INT IDENTITY(1,1), - PlateSetId INT NOT NULL, - PropertyId INT NOT NULL, - PropertyURI NVARCHAR(300) NOT NULL, - - CONSTRAINT PK_PlateSetProperty PRIMARY KEY (RowId), - CONSTRAINT UQ_PlateSetProperty_PlateSetId_PropertyId UNIQUE (PlateSetId, PropertyId), - CONSTRAINT FK_PlateSetProperty_PlateSetId FOREIGN KEY (PlateSetId) REFERENCES assay.PlateSet(RowId) ON DELETE CASCADE, - CONSTRAINT FK_PlateSetProperty_PropertyId FOREIGN KEY (PropertyId) REFERENCES exp.PropertyDescriptor(PropertyId) ON DELETE CASCADE -); - -INSERT INTO assay.PlateSetProperty (PlateSetId, PropertyId, PropertyURI) -SELECT - PL.PlateSet AS PlateSetId, - PP.PropertyId, - PP.PropertyURI -FROM assay.PlateProperty AS PP -INNER JOIN assay.Plate AS PL ON PP.PlateId = PL.RowId -GROUP BY PL.PlateSet, PP.PropertyId, PP.PropertyURI -ORDER BY PlateSetId, PropertyId; - -DROP TABLE assay.PlateProperty; -GO diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.012-24.013.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.012-24.013.sql deleted file mode 100644 index 92c302a6854..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.012-24.013.sql +++ /dev/null @@ -1,15 +0,0 @@ -ALTER TABLE assay.platesetproperty - ADD FieldKey NVARCHAR(255); -GO - -ALTER TABLE assay.platesetproperty - ADD CONSTRAINT either_identifier - CHECK (PropertyURI IS NOT NULL OR FieldKey IS NOT NULL); - -ALTER TABLE assay.platesetproperty ALTER COLUMN PropertyURI NVARCHAR(300) NULL; -ALTER TABLE assay.platesetproperty ALTER COLUMN PropertyId INT NULL; - -ALTER TABLE assay.platesetproperty DROP CONSTRAINT UQ_PlateSetProperty_PlateSetId_PropertyId; -CREATE UNIQUE INDEX UQ_PlateSetProperty_PlateSetId_PropertyId ON assay.platesetproperty (PlateSetId, PropertyId) WHERE PropertyId IS NOT NULL; - -EXEC core.executeJavaUpgradeCode 'updateBuiltInColumns'; diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.013-24.014.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.013-24.014.sql deleted file mode 100644 index eac638dab7c..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.013-24.014.sql +++ /dev/null @@ -1 +0,0 @@ -EXEC core.executeJavaUpgradeCode 'initializeWellExclusions'; diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.014-24.015.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.014-24.015.sql deleted file mode 100644 index 93e0e23dba3..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.014-24.015.sql +++ /dev/null @@ -1,7 +0,0 @@ -ALTER TABLE assay.plateset ADD LSID LSIDtype; -GO - -EXEC core.executeJavaUpgradeCode 'addLsidToPlateSets'; - -ALTER TABLE assay.plateset ALTER COLUMN LSID LSIDType NOT NULL; -GO diff --git a/assay/resources/schemas/dbscripts/sqlserver/assay-24.015-24.016.sql b/assay/resources/schemas/dbscripts/sqlserver/assay-24.015-24.016.sql deleted file mode 100644 index 38564102d01..00000000000 --- a/assay/resources/schemas/dbscripts/sqlserver/assay-24.015-24.016.sql +++ /dev/null @@ -1,20 +0,0 @@ -CREATE TABLE assay.FilterCriteria -( - RowId INT IDENTITY(1,1), - PropertyId INT NOT NULL, - ReferencePropertyId INT NOT NULL, - DomainId INT NOT NULL, - Operation NVARCHAR(50) NOT NULL, - Value NVARCHAR(4000) NULL, - - CONSTRAINT PK_FilterCriteria PRIMARY KEY (RowId), - CONSTRAINT FK_FilterCriteria_DomainDescriptor FOREIGN KEY (DomainId) REFERENCES exp.DomainDescriptor (DomainId) ON DELETE CASCADE, - - -- SQL Server does not allow for multiple foreign keys to the same table to utilize ON DELETE CASCADE as it may - -- cause cycles or multiple cascade paths. The solution is to only ON DELETE CASCADE for one foreign key and - -- clean up upon delete of the property for other changes. See AssayResultDomainKind.deletePropertyDescriptor(). - CONSTRAINT FK_FilterCriteria_PropertyDescriptor FOREIGN KEY (PropertyId) REFERENCES exp.PropertyDescriptor (PropertyId) ON DELETE CASCADE, - CONSTRAINT FK_FilterCriteria_PropertyDescriptor_Reference FOREIGN KEY (ReferencePropertyId) REFERENCES exp.PropertyDescriptor (PropertyId) ON DELETE NO ACTION -); - -EXEC core.executeJavaUpgradeCode 'initializeHitSelectionCriteria'; diff --git a/assay/src/org/labkey/assay/AssayUpgradeCode.java b/assay/src/org/labkey/assay/AssayUpgradeCode.java index 6a28e01042e..317f904b206 100644 --- a/assay/src/org/labkey/assay/AssayUpgradeCode.java +++ b/assay/src/org/labkey/assay/AssayUpgradeCode.java @@ -1,822 +1,31 @@ package org.labkey.assay; -import org.apache.commons.collections4.MapUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.Nullable; -import org.labkey.api.assay.AssayProvider; -import org.labkey.api.assay.AssayResultDomainKind; -import org.labkey.api.assay.AssayService; -import org.labkey.api.assay.plate.PlateDataStateManager; -import org.labkey.api.assay.plate.PlateService; -import org.labkey.api.assay.plate.PlateSet; -import org.labkey.api.assay.plate.Position; import org.labkey.api.assay.plate.WellGroup; -import org.labkey.api.collections.CaseInsensitiveHashMap; -import org.labkey.api.collections.CaseInsensitiveHashSet; -import org.labkey.api.collections.IntHashMap; -import org.labkey.api.collections.LongHashMap; import org.labkey.api.data.Container; -import org.labkey.api.data.ContainerFilter; import org.labkey.api.data.ContainerManager; -import org.labkey.api.data.CoreSchema; -import org.labkey.api.data.DbSchema; import org.labkey.api.data.DbScope; -import org.labkey.api.data.DbSequence; -import org.labkey.api.data.DbSequenceManager; -import org.labkey.api.data.DeferredUpgrade; -import org.labkey.api.data.JdbcType; -import org.labkey.api.data.NameGenerator; -import org.labkey.api.data.NameGeneratorState; -import org.labkey.api.data.PropertyStorageSpec; -import org.labkey.api.data.Results; import org.labkey.api.data.SQLFragment; import org.labkey.api.data.SqlExecutor; import org.labkey.api.data.SqlSelector; import org.labkey.api.data.Table; -import org.labkey.api.data.TableInfo; -import org.labkey.api.data.TableSelector; import org.labkey.api.data.UpgradeCode; import org.labkey.api.exp.Lsid; -import org.labkey.api.exp.OntologyManager; -import org.labkey.api.exp.api.ExpProtocol; -import org.labkey.api.exp.property.Domain; -import org.labkey.api.exp.property.DomainKind; -import org.labkey.api.exp.property.DomainProperty; -import org.labkey.api.exp.property.Lookup; -import org.labkey.api.exp.property.PropertyService; import org.labkey.api.module.ModuleContext; -import org.labkey.api.query.SchemaKey; -import org.labkey.api.query.ValidationException; -import org.labkey.api.security.User; -import org.labkey.api.util.Pair; -import org.labkey.assay.plate.PlateImpl; import org.labkey.assay.plate.PlateManager; -import org.labkey.assay.plate.PlateMetadataDomainKind; -import org.labkey.assay.plate.TsvPlateLayoutHandler; -import org.labkey.assay.plate.model.PlateSetLineage; -import org.labkey.assay.plate.query.PlateTable; -import org.labkey.assay.plate.query.WellTable; import org.labkey.assay.query.AssayDbSchema; import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Set; - -import static org.labkey.api.assay.plate.AssayPlateMetadataService.HIT_SELECTION_CRITERIA_COLUMN_NAME; -import static org.labkey.api.util.IntegerUtils.asInteger; -import static org.labkey.assay.plate.PlateMetadataDomainKind.Column; public class AssayUpgradeCode implements UpgradeCode { private static final Logger _log = LogManager.getLogger(AssayUpgradeCode.class); - /** - * Called from assay-24.000-24.001.sql - *

- * The referenced upgrade script creates a new plate set for every plate in the system. We now - * want to iterate over each plate set to set the name using the configured name expression. - */ - @SuppressWarnings({"UnusedDeclaration"}) - public static void updatePlateSetNames(ModuleContext ctx) throws Exception - { - if (ctx.isNewInstall()) - return; - - DbScope scope = AssayDbSchema.getInstance().getSchema().getScope(); - try (DbScope.Transaction tx = scope.ensureTransaction()) - { - TableInfo plateSetTable = AssayDbSchema.getInstance().getTableInfoPlateSet(); - - // Set the DbSequence minimum - { - SQLFragment sql = new SQLFragment("SELECT MAX(rowId) FROM ").append(plateSetTable, ""); - Integer maxRowId = new SqlSelector(AssayDbSchema.getInstance().getSchema(), sql).getObject(Integer.class); - - if (maxRowId != null) - { - DbSequence sequence = DbSequenceManager.get(ContainerManager.getRoot(), plateSetTable.getDbSequenceName("RowId")); - sequence.ensureMinimum(maxRowId); - } - } - - _log.info("Start updating temporary plate set names with the configured name expression"); - List plateSetRowIds = new TableSelector(plateSetTable, Collections.singleton("RowId")).getArrayList(Integer.class); - - // This is a copy of PlateManager.PLATE_SET_NAME_EXPRESSION as set when this script was written. - // Copied here to allow this script to assume that only the Plate Set "RowId" value is needed for the - // generated name. - String PLATE_SET_NAME_EXPRESSION = "PLS-${now:date('yyyyMMdd')}-${RowId}"; - NameGenerator nameGenerator = new NameGenerator(PLATE_SET_NAME_EXPRESSION, plateSetTable, false, null, null, null); - NameGeneratorState state = nameGenerator.createState(false); - - for (Integer plateSetRowId : plateSetRowIds) - { - String name = nameGenerator.generateName(state, CaseInsensitiveHashMap.of("RowId", plateSetRowId)); - state.cleanUp(); - - SQLFragment sql = new SQLFragment("UPDATE ").append(plateSetTable, "") - .append(" SET Name = ?") - .add(name) - .append(" WHERE RowId = ?") - .add(plateSetRowId); - - new SqlExecutor(AssayDbSchema.getInstance().getSchema()).execute(sql); - } - - _log.info("Successfully updated " + plateSetRowIds.size() + " plate set names"); - tx.commit(); - } - } - - /** - * Called from assay-24.001-24.002.sql - *

- * Iterate over each plate and plate set to generate a Plate ID and PlateSet ID based on the - * configured name expression for each. - */ - @SuppressWarnings({"UnusedDeclaration"}) - public static void initializePlateAndPlateSetIDs(ModuleContext ctx) throws Exception - { - if (ctx.isNewInstall()) - return; - - DbScope scope = AssayDbSchema.getInstance().getSchema().getScope(); - try (DbScope.Transaction tx = scope.ensureTransaction()) - { - _log.info("Start initializing Plate IDs"); - - try (Results rs = new TableSelector(AssayDbSchema.getInstance().getTableInfoPlate()).getResults()) - { - int platesUpgraded = 0; - while (rs.next()) - { - Map row = rs.getRowMap(); - // get the plate container - String containerId = String.valueOf(row.get("container")); - Container c = ContainerManager.getForId(containerId); - if (c != null) - { - row.put("name", null); - - NameGenerator nameGenerator = new NameGenerator(PlateManager.get().getPlateNameExpression(), AssayDbSchema.getInstance().getTableInfoPlate(), false, c, null, null); - NameGeneratorState state = nameGenerator.createState(false); - String name = nameGenerator.generateName(state, row); - state.cleanUp(); - - SQLFragment sql = new SQLFragment("UPDATE ").append(AssayDbSchema.getInstance().getTableInfoPlate(), "") - .append(" SET PlateId = ?") - .add(name) - .append(" WHERE RowId = ?") - .add(row.get("rowId")); - new SqlExecutor(AssayDbSchema.getInstance().getSchema()).execute(sql); - platesUpgraded++; - } - else - _log.error("Container for Plate ID : " + row.get("rowId") + " could not be resolved."); - } - _log.info("Successfully updated " + platesUpgraded + " plate IDs"); - } - - _log.info("Start initializing PlateSet IDs"); - try (Results rs = new TableSelector(AssayDbSchema.getInstance().getTableInfoPlateSet()).getResults()) - { - NameGenerator nameGenerator = new NameGenerator(PlateManager.get().getPlateSetNameExpression(), AssayDbSchema.getInstance().getTableInfoPlateSet(), false, null, null, null); - NameGeneratorState state = nameGenerator.createState(false); - int plateSetsUpgraded = 0; - while (rs.next()) - { - Map row = rs.getRowMap(); - // for plate sets, they should have a valid PlateSetId, but if the name was not generated (or mutated), regenerate a new - // plate set id - if (!String.valueOf(row.get("name")).startsWith("PLS-")) - { - row.put("name", null); - String name = nameGenerator.generateName(state, row); - state.cleanUp(); - - SQLFragment sql = new SQLFragment("UPDATE ").append(AssayDbSchema.getInstance().getTableInfoPlateSet(), "") - .append(" SET PlateSetId = ?") - .add(name) - .append(" WHERE RowId = ?") - .add(row.get("rowId")); - new SqlExecutor(AssayDbSchema.getInstance().getSchema()).execute(sql); - plateSetsUpgraded++; - } - } - _log.info("Successfully updated " + plateSetsUpgraded + " plate set IDs"); - } - tx.commit(); - } - } - - /** - * Well metadata has transitioned to a provisioned architecture. - */ - private static @Nullable Domain getPlateMetadataVocabDomain(Container container, User user) - { - DomainKind vocabDomainKind = PropertyService.get().getDomainKindByName("Vocabulary"); - - if (vocabDomainKind == null) - return null; - - // the domain is scoped at the project level (project and subfolder scoping) - Container domainContainer = PlateManager.get().getPlateMetadataDomainContainer(container); - String domainURI = vocabDomainKind.generateDomainURI(null, "PlateMetadataDomain", domainContainer, user); - return PropertyService.get().getDomain(container, domainURI); - } - - /** - * Called from assay-24.002-24.003.sql to delete the vocabulary domains associated with - * plate metadata. This upgrade transitions to using a provisioned table approach. Since the plate features are - * still under an experimental flag we won't worry about upgrading the domains. - */ - @SuppressWarnings({"UnusedDeclaration"}) - public static void deletePlateVocabDomains(ModuleContext ctx) throws Exception - { - if (ctx.isNewInstall()) - return; - - DbScope scope = AssayDbSchema.getInstance().getSchema().getScope(); - try (DbScope.Transaction tx = scope.ensureTransaction()) - { - // just truncate the plate to custom property mappings - Table.truncate(AssayDbSchema.getInstance().getSchema().getTable("PlateProperty")); - List biologicsFolders = new ArrayList<>(); - - for (Container container : ContainerManager.getAllChildren(ContainerManager.getRoot())) - { - if (container != null) - { - Domain domain = getPlateMetadataVocabDomain(container, User.getAdminServiceUser()); - if (domain != null) - { - // delete the plate metadata values - SQLFragment sql = new SQLFragment("SELECT Lsid FROM ") - .append(AssayDbSchema.getInstance().getTableInfoWell(), "") - .append(" WHERE Container = ?") - .add(container); - OntologyManager.deleteOntologyObjects(AssayDbSchema.getInstance().getSchema(), sql, container); - - // delete the domain - domain.delete(User.getAdminServiceUser()); - } - - if (isBiologicsFolder(container.getProject())) - { - // ensure the plate metadata domain for the top level biologics projects - if (container.isProject()) - PlateManager.get().ensurePlateMetadataDomain(container, User.getAdminServiceUser(), false); - biologicsFolders.add(container); - } - } - } - - // for existing plates we also need to populate the new provisioned tables so that wells can be joined - // to the metadata properly - for (Container container : biologicsFolders) - { - TableInfo tinfo = PlateManager.get().getPlateMetadataTable(container, User.getAdminServiceUser()); - if (tinfo != null) - { - SQLFragment sql = new SQLFragment("INSERT INTO ").append(tinfo, "") - .append(" (Lsid) SELECT Lsid FROM ").append(AssayDbSchema.getInstance().getTableInfoWell(), "") - .append(" WHERE Container = ?").add(container); - - new SqlExecutor(AssayDbSchema.getInstance().getScope()).execute(sql); - } - } - tx.commit(); - } - } - - /** - * Called from assay-24.005-24.006.sql - * Populates - */ - @SuppressWarnings({"UnusedDeclaration"}) - public static void populatePlateSetPaths(ModuleContext ctx) throws Exception - { - if (ctx.isNewInstall()) - return; - - DbScope scope = AssayDbSchema.getInstance().getSchema().getScope(); - try (DbScope.Transaction tx = scope.ensureTransaction()) - { - Map plateSetPaths = new IntHashMap<>(); - Map> plateSetsToHits = new IntHashMap<>(); - - SQLFragment sql = new SQLFragment("SELECT Hit.RowId AS HitRowId, PlateSet.RowId AS PlateSetRowId") - .append(" FROM assay.PlateSet") - .append(" INNER JOIN assay.Plate ON Plate.PlateSet = PlateSet.RowId") - .append(" INNER JOIN assay.Well ON Well.PlateId = Plate.RowId") - .append(" INNER JOIN assay.Hit ON Hit.WellLsid = Well.Lsid") - .appendEOS(); - Collection> rows = new SqlSelector(scope, sql).getMapCollection(); - - for (Map row : rows) - { - Integer plateSetRowId = asInteger(row.get("PlateSetRowId")); - Integer hitRowId = asInteger(row.get("HitRowId")); - - if (!plateSetsToHits.containsKey(plateSetRowId)) - { - PlateSetLineage lineage = PlateManager.get().getPlateSetLineage( - ContainerManager.getRoot(), - User.getAdminServiceUser(), - plateSetRowId, - ContainerFilter.getUnsafeEverythingFilter() - ); - String lineagePath = lineage.getSeedPath(); - - plateSetPaths.put(plateSetRowId, lineagePath); - plateSetsToHits.put(plateSetRowId, new ArrayList<>()); - } - - plateSetsToHits.get(plateSetRowId).add(hitRowId); - } - - for (Map.Entry> entry : plateSetsToHits.entrySet()) - { - String plateSetPath = plateSetPaths.get(entry.getKey()); - - SQLFragment updateSql = new SQLFragment("UPDATE assay.Hit") - .append(" SET PlateSetPath = ? ").add(plateSetPath) - .append(" WHERE RowId ").appendInClause(entry.getValue(), scope.getSqlDialect()) - .appendEOS(); - - new SqlExecutor(scope).execute(updateSql); - } - - tx.commit(); - } - } - - /** - * Called from assay-24.007-24.008.sql - * This updates the well type to WellGroup.Type.SAMPLE for all wells in Biologics folders that have a value - * set for Well.SampleId. - */ - @DeferredUpgrade - @SuppressWarnings({"UnusedDeclaration"}) - public static void populatePlateWellTypes(ModuleContext ctx) throws Exception - { - if (ctx.isNewInstall()) - return; - - DbScope scope = AssayDbSchema.getInstance().getSchema().getScope(); - - // Determine all containers that have a Plate where Samples are specified in wells - SQLFragment sql = new SQLFragment(""" - SELECT DISTINCT P.Container - FROM assay.Well AS W - INNER JOIN assay.Plate AS P ON P.RowId = W.PlateId - WHERE P.AssayType = ? AND W.SampleId IS NOT NULL - """).add(TsvPlateLayoutHandler.TYPE); - List containerIds = new SqlSelector(scope, sql).getArrayList(String.class); - - for (String containerId : containerIds) - { - Container container = ContainerManager.getForId(containerId); - if (container == null) - { - _log.error(String.format("Failed to populate plate well types. Unable to resolve container for entityId \"%s\".", containerId)); - continue; - } - - if (!(isBiologicsFolder(container) || isBiologicsFolder(container.getProject()))) - { - _log.info(String.format("Populating plate well types. Skipping \"%s\" plates in \"%s\".", TsvPlateLayoutHandler.TYPE, container.getPath())); - continue; - } - - _log.info(String.format("Populating plate well types in \"%s\".", container.getPath())); - - try (DbScope.Transaction tx = scope.ensureTransaction()) - { - SQLFragment wellSql = new SQLFragment(""" - SELECT W.RowId, W.PlateId - FROM assay.Well AS W - INNER JOIN assay.Plate AS P ON P.RowId = W.PlateId - WHERE P.Container = ? AND P.AssayType = ? AND W.SampleId IS NOT NULL AND W.RowId NOT IN ( - SELECT WellId FROM assay.WellGroupPositions AS WGP WHERE WGP.WellId = W.RowId - ) - """).add(containerId).add(TsvPlateLayoutHandler.TYPE); - - Map> wellGroupChanges = new LongHashMap<>(); - Collection> sampleWellRows = new SqlSelector(scope, wellSql).getMapCollection(); - for (Map sampleWellRow : sampleWellRows) - { - Long plateRowId = MapUtils.getLong(sampleWellRow,"PlateId"); - Long wellRowId = MapUtils.getLong(sampleWellRow,"RowId"); - PlateManager.WellGroupChange change = new PlateManager.WellGroupChange(plateRowId, wellRowId, WellGroup.Type.SAMPLE.name(), null, null); - - wellGroupChanges.computeIfAbsent(plateRowId, (x) -> new HashMap<>()).put(wellRowId, change); - } - - if (wellGroupChanges.isEmpty()) - { - _log.info(String.format("No well group updates for plates in \"%s\".", container.getPath())); - continue; - } - - _log.info(String.format("Updating \"%d\" well groups across \"%d\" plates in \"%s\".", sampleWellRows.size(), wellGroupChanges.entrySet().size(), container.getPath())); - computeWellGroups(container, User.getAdminServiceUser(), wellGroupChanges); - _log.info(String.format("Completed well group update in \"%s\".", container.getPath())); - - tx.commit(); - } - } - } - - // This is a functional copy of PlateManager.computeWellGroups() prior to the replicates refactor - // to represent replicates with the "Replicate Groups" column. When this is removed the methods called on - // PlateManager should be once again made private if possible. - private static void computeWellGroups( - Container container, - User user, - Map> wellGroupChanges - ) throws Exception - { - for (var entry : wellGroupChanges.entrySet()) - { - var plate = (PlateImpl) PlateManager.get().requirePlate(container, entry.getKey(), "Failed to update well groups."); - if (!TsvPlateLayoutHandler.TYPE.equalsIgnoreCase(plate.getAssayType())) - continue; - - var wellChanges = entry.getValue(); - Map, List> wellGroupings = new HashMap<>(); - - for (var wellData : PlateManager.get().getWellData(container, user, plate.getRowId(), false, false)) - { - WellGroup.Type type = wellData.getType(); - String wellGroup = wellData.getWellGroup(); - - Long wellRowId = wellData.getRowId(); - var wellChange = wellChanges.get(wellRowId); - if (wellChange != null) - { - if (wellChange.type() != null) - { - String typeStr = StringUtils.trimToNull(wellChange.type()); - if (typeStr != null) - type = WellGroup.Type.valueOf(typeStr); - else - type = null; - } - if (wellChange.group() != null) - wellGroup = StringUtils.trimToNull(wellChange.group()); - } - - // Type/Group are not set and are not being updated - if (type == null && wellGroup == null) - continue; - - var position = plate.getPosition(wellData.getRow(), wellData.getCol()); - - // Specifying a group requires that a type is also specified - if (type == null) - { - throw new ValidationException(String.format( - "Well %s must specify a \"%s\" when a \"%s\" is specified.", - position.getDescription(), - WellTable.Column.Type.name(), - WellTable.Column.WellGroup.name() - )); - } - - var wellGroupKey = Pair.of(type, wellGroup); - wellGroupings.computeIfAbsent(wellGroupKey, k -> new ArrayList<>()).add(position); - } - - // Mark pre-existing well groups on this plate for deletion - for (WellGroup existingWellGroup : plate.getWellGroups()) - plate.markWellGroupForDeletion(existingWellGroup); - - // Create new well groups for this plate - for (var wellGrouping : wellGroupings.entrySet()) - { - var typeGroup = wellGrouping.getKey(); - plate.addWellGroup(typeGroup.second, typeGroup.first, wellGrouping.getValue()); - } - - PlateManager.get().savePlateImpl(container, user, plate); - } - } - - /** - * Called from assay-24.009-24.010.sql to rename existing plate metadata fields that might collide with - * new concentration and amount fields. - */ - @SuppressWarnings({"UnusedDeclaration"}) - public static void renameWellMetadataFields(ModuleContext ctx) throws Exception - { - if (ctx.isNewInstall()) - return; - - Set reservedNames = new CaseInsensitiveHashSet(Column.Amount.name(), - Column.AmountUnits.name(), - Column.Concentration.name(), - Column.ConcentrationUnits.name()); - - Set metadataContainers = new HashSet<>(); - for (Container container : ContainerManager.getAllChildren(ContainerManager.getRoot())) - { - if (isBiologicsFolder(container)) - metadataContainers.add(PlateManager.get().getPlateMetadataDomainContainer(container)); - } - - DbScope scope = AssayDbSchema.getInstance().getSchema().getScope(); - for (Container container : metadataContainers) - { - Domain domain = PlateManager.get().getPlateMetadataDomain(container, User.getAdminServiceUser(), true); - if (domain != null) - { - try (DbScope.Transaction tx = scope.ensureTransaction()) - { - boolean dirty = false; - for (DomainProperty dp : domain.getProperties()) - { - if (reservedNames.contains(dp.getName())) - { - String newName = ensureNewName(dp, domain); - _log.info(String.format("Renaming plate metadata property %s to %s for folder %s", dp.getName(), newName, container.getPath())); - dp.setName(newName); - dirty = true; - } - } - - if (dirty) - domain.save(User.getAdminServiceUser()); - - // create the new fields in the existing domains - DomainKind domainKind = domain.getDomainKind(); - if (domainKind instanceof PlateMetadataDomainKind pmdk) - { - pmdk.ensureDomainProperties(domain, container); - domain.save(User.getAdminServiceUser()); - } - - tx.commit(); - } - catch (Exception e) - { - _log.error(e); - } - } - } - } - - private static final String METADATA_RENAME_SUFFIX = "_PREV"; - - private static String ensureNewName(DomainProperty dp, Domain domain) - { - String newName = dp.getName() + METADATA_RENAME_SUFFIX; - int ordinal = 1; - - while (domain.getPropertyByName(newName) != null) - { - newName = String.format("%s%s%d", dp.getName(), METADATA_RENAME_SUFFIX, ordinal++); - } - return newName; - } - - /** - * Called from assay-24.010-24.011.sql, which populates the new barcode field with formatted rowid values. - * We then set the barcode DbSequence here to the maximum rowId to ensure subsequently unique values. - */ - @SuppressWarnings({"UnusedDeclaration"}) - public static void updateBarcodeSequence(ModuleContext ctx) throws Exception - { - if (ctx.isNewInstall()) - return; - - DbScope scope = AssayDbSchema.getInstance().getSchema().getScope(); - try (DbScope.Transaction tx = scope.ensureTransaction()) - { - SQLFragment sql = new SQLFragment("SELECT MAX(rowId) FROM ").append(AssayDbSchema.getInstance().getTableInfoPlate(), ""); - Integer maxRowId = new SqlSelector(AssayDbSchema.getInstance().getSchema(), sql).getObject(Integer.class); - - if (maxRowId != null) - { - TableInfo plateTable = AssayDbSchema.getInstance().getTableInfoPlate(); - DbSequence sequence = DbSequenceManager.get(ContainerManager.getRoot(), PlateTable.PLATE_BARCODE_SEQUENCE); - sequence.ensureMinimum(maxRowId); - } - - tx.commit(); - } - } - - /** - * Called from assay-24.013-24.014.sql, which adds an LSID column to plate sets. Here, we populate the LSID values. - */ - @SuppressWarnings({"UnusedDeclaration"}) - public static void addLsidToPlateSets(ModuleContext ctx) throws Exception - { - if (ctx.isNewInstall()) - return; - - DbSchema schema = AssayDbSchema.getInstance().getSchema(); - try (DbScope.Transaction tx = schema.getScope().ensureTransaction()) - { - TableInfo plateSetTable = AssayDbSchema.getInstance().getTableInfoPlateSet(); - try (Results rs = new TableSelector(plateSetTable).getResults()) - { - while (rs.next()) - { - Map row = rs.getRowMap(); - Container container = ContainerManager.getForId(rs.getString("Container")); - Lsid lsid = PlateManager.get().getLsid(PlateSet.class, container); - - SQLFragment sql = new SQLFragment("UPDATE ").append(plateSetTable, "") - .append(" SET LSID = ?") - .add(lsid) - .append(" WHERE RowId = ?") - .add(row.get("rowId")); - new SqlExecutor(schema).execute(sql); - } - } - tx.commit(); - } - } - - private static void addInsertedValues(List> insertedValues, Long rowId, String... types) - { - for (String type : types) - { - insertedValues.add(Arrays.asList(rowId, null, null, type)); - } - } - - /** - * Called from assay-24.012-24.013.sql, in order to support the ability to add or remove 'built-in' columns from - * the plate grid view. - */ - @SuppressWarnings({"UnusedDeclaration"}) - public static void updateBuiltInColumns(ModuleContext ctx) - { - if (ctx.isNewInstall()) - return; - - DbScope scope = AssayDbSchema.getInstance().getSchema().getScope(); - try (DbScope.Transaction tx = scope.ensureTransaction()) - { - SQLFragment sqlFragment = new SQLFragment("SELECT DISTINCT plateset FROM assay.Plate WHERE assaytype = '" + TsvPlateLayoutHandler.TYPE + "'"); - ArrayList plateSetIds = new SqlSelector(AssayDbSchema.getInstance().getSchema(), sqlFragment).getArrayList(Integer.class); - - Set assayPSes = new HashSet<>(); - Set primaryPSes = new HashSet<>(); - Set templatePSes = new HashSet<>(); - - for (Integer plateSetId : plateSetIds) - { - PlateSet plateSet = PlateService.get().getPlateSet(ContainerFilter.getUnsafeEverythingFilter(), plateSetId); - if (plateSet == null) - throw new IllegalStateException("updateBuiltInColumns: Plate Set with plate of id " + plateSetId + " not found."); - - SQLFragment sql = new SQLFragment("SELECT template, type FROM assay.PlateSet WHERE rowid = " + plateSet.getRowId() + ""); - Map result = new SqlSelector(AssayDbSchema.getInstance().getSchema(), sql).getMap(); - - boolean isTemplatePlateSet = (boolean) result.get("template"); - boolean isAssayPlateSet = result.get("type").equals("assay"); - boolean isPrimaryPlateSet = result.get("type").equals("primary"); - - if (isTemplatePlateSet) - templatePSes.add(plateSet.getRowId()); - else if (isAssayPlateSet) - assayPSes.add(plateSet.getRowId()); - else if (isPrimaryPlateSet) - primaryPSes.add(plateSet.getRowId()); - } - - List> insertedValues = new LinkedList<>(); - - assayPSes.forEach(rowId -> addInsertedValues(insertedValues, rowId, "SampleID", "Type", "WellGroup")); - primaryPSes.forEach(rowId -> addInsertedValues(insertedValues, rowId, "SampleID")); - templatePSes.forEach(rowId -> addInsertedValues(insertedValues, rowId, "Type", "WellGroup")); - - String insertSql = "INSERT INTO " + AssayDbSchema.getInstance().getTableInfoPlateSetProperty() + - " (plateSetId, propertyId, propertyURI, FieldKey)" + - " VALUES (?, CAST(? AS INT), CAST(? AS VARCHAR), CAST(? AS VARCHAR))"; - Table.batchExecute(AssayDbSchema.getInstance().getSchema(), insertSql, insertedValues); - - tx.commit(); - } - catch (SQLException e) - { - throw new RuntimeException(e); - } - } - - private static boolean isBiologicsFolder(Container container) - { - return container != null && "Biologics".equals(ContainerManager.getFolderTypeName(container)); - } - - /** - * Called from assay-24.013-24.014.sql, in order to support row level exclusions for plate enabled assays. - * The upgrade ensures the default assay plate data states as well as creates the result domain qc state field. - */ - @DeferredUpgrade - public static void initializeWellExclusions(ModuleContext ctx) throws Exception - { - if (ctx.isNewInstall()) - return; - - DbScope scope = AssayDbSchema.getInstance().getSchema().getScope(); - try (DbScope.Transaction tx = scope.ensureTransaction()) - { - Set protocols = new HashSet<>(); - for (Container container : ContainerManager.getAllChildren(ContainerManager.getRoot())) - { - if (isBiologicsFolder(container)) - { - PlateDataStateManager.get().ensureDefaultStates(container, User.getAdminServiceUser()); - protocols.addAll(AssayService.get().getAssayProtocols(container)); - } - } - - for (ExpProtocol protocol : protocols) - { - AssayProvider provider = AssayService.get().getProvider(protocol); - if (provider != null) - { - if (provider.isPlateMetadataEnabled(protocol)) - { - // ensure the QC state column exists in the result domain - Domain resultDomain = provider.getResultsDomain(protocol, true); - if (resultDomain.getPropertyByName(AssayResultDomainKind.Column.State.name()) == null) - { - _log.info(String.format("Adding the %s field to the results domain for assay : %s", AssayResultDomainKind.Column.State.name(), protocol.getName())); - DomainProperty dp = resultDomain.addProperty(new PropertyStorageSpec(AssayResultDomainKind.Column.State.name(), JdbcType.INTEGER)); - dp.setLabel("QC State"); - dp.setImportAliasSet(Set.of("QCState", "QC State")); - dp.setLookup(new Lookup(null, SchemaKey.fromParts(CoreSchema.getInstance().getSchemaName()), CoreSchema.DATA_STATES_TABLE_NAME)); - dp.setShownInInsertView(false); - dp.setShownInUpdateView(false); - - resultDomain.save(User.getAdminServiceUser()); - } - } - } - } - tx.commit(); - } - } - - /** - * Called from assay-24.015-24.016.sql, in order to support hit selection criteria for plate enabled assays. - * The upgrade creates the run domain hit selection criteria field. - */ - @DeferredUpgrade - public static void initializeHitSelectionCriteria(ModuleContext ctx) throws Exception - { - if (ctx.isNewInstall()) - return; - - try (DbScope.Transaction tx = AssayDbSchema.getInstance().getSchema().getScope().ensureTransaction()) - { - Set protocols = new HashSet<>(); - for (Container container : ContainerManager.getAllChildren(ContainerManager.getRoot())) - { - if (isBiologicsFolder(container)) - protocols.addAll(AssayService.get().getAssayProtocols(container)); - } - - for (ExpProtocol protocol : protocols) - { - AssayProvider provider = AssayService.get().getProvider(protocol); - if (provider != null && provider.isPlateMetadataEnabled(protocol)) - { - // ensure the QC state column exists in the result domain - Domain runDomain = provider.getRunDomain(protocol, true); - if (runDomain != null && runDomain.getPropertyByName(HIT_SELECTION_CRITERIA_COLUMN_NAME) == null) - { - _log.info("Adding the \"{}\" field to the run domain for assay : {}", HIT_SELECTION_CRITERIA_COLUMN_NAME, protocol.getName()); - DomainProperty dp = runDomain.addProperty(new PropertyStorageSpec(HIT_SELECTION_CRITERIA_COLUMN_NAME, JdbcType.VARCHAR)); - dp.setShownInInsertView(false); - dp.setShownInUpdateView(false); - - runDomain.save(User.getAdminServiceUser()); - } - } - } - - tx.commit(); - } - } - /** * Called from assay-25.000-25.001.sql * Migrate replicate well groups to be represented via the "Replicate Group" column. diff --git a/assay/src/org/labkey/assay/plate/PlateManager.java b/assay/src/org/labkey/assay/plate/PlateManager.java index 9c055d795e7..6d32f947f1b 100644 --- a/assay/src/org/labkey/assay/plate/PlateManager.java +++ b/assay/src/org/labkey/assay/plate/PlateManager.java @@ -865,7 +865,7 @@ private Object require(Object object, @NotNull String error, @Nullable String er throw new ValidationException(error); } - public @NotNull Plate requirePlate(Container container, long plateRowId, @Nullable String errorPrefix) throws ValidationException + private @NotNull Plate requirePlate(Container container, long plateRowId, @Nullable String errorPrefix) throws ValidationException { return (Plate) require(getPlate(container, plateRowId), "Plate id \"" + plateRowId + "\" not found.", errorPrefix); } @@ -1134,7 +1134,7 @@ public DbScope.Transaction ensureTransaction(Lock... locks) return AssayDbSchema.getInstance().getSchema().getScope().ensureTransaction(locks); } - public long savePlateImpl(Container container, User user, @NotNull PlateImpl plate) throws Exception + private long savePlateImpl(Container container, User user, @NotNull PlateImpl plate) throws Exception { return savePlateImpl(container, user, plate, false); } diff --git a/core/resources/schemas/dbscripts/postgresql/core-0.000-24.000.sql b/core/resources/schemas/dbscripts/postgresql/core-0.000-25.000.sql similarity index 93% rename from core/resources/schemas/dbscripts/postgresql/core-0.000-24.000.sql rename to core/resources/schemas/dbscripts/postgresql/core-0.000-25.000.sql index 095d3c08490..a8fbea51e10 100644 --- a/core/resources/schemas/dbscripts/postgresql/core-0.000-24.000.sql +++ b/core/resources/schemas/dbscripts/postgresql/core-0.000-25.000.sql @@ -723,3 +723,35 @@ DROP INDEX IF EXISTS core.UQ_Principals_Container_Name_OwnerId; -- COALESCE() works around PostgreSQL behavior that NULL values are not unique CREATE UNIQUE INDEX UQ_Principals_Container_Name_OwnerId ON core.Principals (COALESCE(Container, '00000000-0000-0000-0000-000000000000'), LOWER(Name), COALESCE(OwnerId, '00000000-0000-0000-0000-000000000000')); + +/* 24.xxx SQL scripts */ + +ALTER TABLE core.datastates ADD COLUMN Color VARCHAR(7); + +SELECT core.fn_dropifexists('PrincipalRelations','core','TABLE', NULL); + +ALTER TABLE core.APIKeys ADD COLUMN Description VARCHAR(256); +ALTER TABLE core.APIKeys ADD COLUMN LastUsed TIMESTAMP; + +ALTER TABLE core.Containers ADD FileRootSize BIGINT; +ALTER TABLE core.Containers ADD FileRootLastCrawled TIMESTAMP; +ALTER TABLE core.Containers ADD CONSTRAINT PK_Containers PRIMARY KEY (RowId); +ALTER TABLE core.Containers DROP CONSTRAINT UQ_Containers_RowID; + +-- Adding a PK on RowId seemed like a good idea, but it broke existing lookups to core.Containers and other assumptions. +-- We could add a PK on EntityId, but that column is currently nullable. For now, we'll just live without a PK. +ALTER TABLE core.Containers DROP CONSTRAINT PK_Containers; +ALTER TABLE core.Containers ADD CONSTRAINT UQ_Containers_RowId UNIQUE (RowId); + +-- Shift the core.Logins PK from Email to UserId. Add UserId column as NULLABLE, populate it from core.Principals, +-- delete rows that didn't join (UserId IS NULL), make UserId NOT NULL, drop the old PK, and add the new PK. + +ALTER TABLE core.Logins ADD UserId USERID; +UPDATE core.Logins SET UserId = (SELECT UserId FROM core.Principals p WHERE Name = Email); +DELETE FROM core.Logins WHERE UserId IS NULL; +ALTER TABLE core.Logins ALTER COLUMN UserId DROP NOT NULL; +ALTER TABLE core.Logins DROP CONSTRAINT PK_Logins; +ALTER TABLE core.Logins ADD CONSTRAINT PK_Logins PRIMARY KEY (UserId); + +-- LabKey no longer reads or writes to the Email column. But we'll leave the column in place until 24.12 as a precaution. +ALTER TABLE core.Logins ALTER COLUMN Email DROP NOT NULL; diff --git a/core/resources/schemas/dbscripts/postgresql/core-24.001-24.002.sql b/core/resources/schemas/dbscripts/postgresql/core-24.001-24.002.sql deleted file mode 100644 index ed07a54886e..00000000000 --- a/core/resources/schemas/dbscripts/postgresql/core-24.001-24.002.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT core.executeJavaUpgradeCode('makeWithCounterCaseInsensitive'); \ No newline at end of file diff --git a/core/resources/schemas/dbscripts/postgresql/core-24.002-24.003.sql b/core/resources/schemas/dbscripts/postgresql/core-24.002-24.003.sql deleted file mode 100644 index a9470ab1a09..00000000000 --- a/core/resources/schemas/dbscripts/postgresql/core-24.002-24.003.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE core.datastates ADD COLUMN Color VARCHAR(7); - diff --git a/core/resources/schemas/dbscripts/postgresql/core-24.003-24.004.sql b/core/resources/schemas/dbscripts/postgresql/core-24.003-24.004.sql deleted file mode 100644 index fbe0d87c3fb..00000000000 --- a/core/resources/schemas/dbscripts/postgresql/core-24.003-24.004.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT core.fn_dropifexists('PrincipalRelations','core','TABLE', NULL); diff --git a/core/resources/schemas/dbscripts/postgresql/core-24.004-24.005.sql b/core/resources/schemas/dbscripts/postgresql/core-24.004-24.005.sql deleted file mode 100644 index 6d0d9b7859b..00000000000 --- a/core/resources/schemas/dbscripts/postgresql/core-24.004-24.005.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE core.APIKeys ADD COLUMN Description VARCHAR(256); -ALTER TABLE core.APIKeys ADD COLUMN LastUsed TIMESTAMP; diff --git a/core/resources/schemas/dbscripts/postgresql/core-24.005-24.006.sql b/core/resources/schemas/dbscripts/postgresql/core-24.005-24.006.sql deleted file mode 100644 index 420bf0fc9c5..00000000000 --- a/core/resources/schemas/dbscripts/postgresql/core-24.005-24.006.sql +++ /dev/null @@ -1,4 +0,0 @@ -ALTER TABLE core.Containers ADD FileRootSize BIGINT; -ALTER TABLE core.Containers ADD FileRootLastCrawled TIMESTAMP; -ALTER TABLE core.Containers ADD CONSTRAINT PK_Containers PRIMARY KEY (RowId); -ALTER TABLE core.Containers DROP CONSTRAINT UQ_Containers_RowID; \ No newline at end of file diff --git a/core/resources/schemas/dbscripts/postgresql/core-24.006-24.007.sql b/core/resources/schemas/dbscripts/postgresql/core-24.006-24.007.sql deleted file mode 100644 index 8f4528dbde5..00000000000 --- a/core/resources/schemas/dbscripts/postgresql/core-24.006-24.007.sql +++ /dev/null @@ -1,4 +0,0 @@ --- Adding a PK on RowId seemed like a good idea, but it broke existing lookups to core.Containers and other assumptions. --- We could add a PK on EntityId, but that column is currently nullable. For now, we'll just live without a PK. -ALTER TABLE core.Containers DROP CONSTRAINT PK_Containers; -ALTER TABLE core.Containers ADD CONSTRAINT UQ_Containers_RowId UNIQUE (RowId); \ No newline at end of file diff --git a/core/resources/schemas/dbscripts/postgresql/core-24.007-24.008.sql b/core/resources/schemas/dbscripts/postgresql/core-24.007-24.008.sql deleted file mode 100644 index dea3892290a..00000000000 --- a/core/resources/schemas/dbscripts/postgresql/core-24.007-24.008.sql +++ /dev/null @@ -1,9 +0,0 @@ --- Shift the core.Logins PK from Email to UserId. Add UserId column as NULLABLE, populate it from core.Principals, --- delete rows that didn't join (UserId IS NULL), make UserId NOT NULL, drop the old PK, and add the new PK. - -ALTER TABLE core.Logins ADD UserId USERID; -UPDATE core.Logins SET UserId = (SELECT UserId FROM core.Principals p WHERE Name = Email); -DELETE FROM core.Logins WHERE UserId IS NULL; -ALTER TABLE core.Logins ALTER COLUMN UserId DROP NOT NULL; -ALTER TABLE core.Logins DROP CONSTRAINT PK_Logins; -ALTER TABLE core.Logins ADD CONSTRAINT PK_Logins PRIMARY KEY (UserId); diff --git a/core/resources/schemas/dbscripts/postgresql/core-24.008-24.009.sql b/core/resources/schemas/dbscripts/postgresql/core-24.008-24.009.sql deleted file mode 100644 index b396c5334a6..00000000000 --- a/core/resources/schemas/dbscripts/postgresql/core-24.008-24.009.sql +++ /dev/null @@ -1,2 +0,0 @@ --- LabKey no longer reads or writes to the Email column. But we'll leave the column in place until 24.12 as a precaution. -ALTER TABLE core.Logins ALTER COLUMN Email DROP NOT NULL; diff --git a/core/resources/schemas/dbscripts/postgresql/prop-0.000-24.000.sql b/core/resources/schemas/dbscripts/postgresql/prop-0.000-25.000.sql similarity index 100% rename from core/resources/schemas/dbscripts/postgresql/prop-0.000-24.000.sql rename to core/resources/schemas/dbscripts/postgresql/prop-0.000-25.000.sql diff --git a/core/resources/schemas/dbscripts/postgresql/prop-24.000-24.001.sql b/core/resources/schemas/dbscripts/postgresql/prop-24.000-24.001.sql deleted file mode 100644 index 6e4175cbdaa..00000000000 --- a/core/resources/schemas/dbscripts/postgresql/prop-24.000-24.001.sql +++ /dev/null @@ -1,2 +0,0 @@ --- Migrate "Weak" password strength setting to "Good" -UPDATE prop.Properties SET Value = 'Good' WHERE Set = (SELECT Set FROM prop.propertysets WHERE category = 'DatabaseAuthentication') AND Name = 'Strength' AND Value = 'Weak'; diff --git a/core/resources/schemas/dbscripts/sqlserver/core-0.000-24.000.sql b/core/resources/schemas/dbscripts/sqlserver/core-0.000-25.000.sql similarity index 95% rename from core/resources/schemas/dbscripts/sqlserver/core-0.000-24.000.sql rename to core/resources/schemas/dbscripts/sqlserver/core-0.000-25.000.sql index 8add972adea..c81fea2aec2 100644 --- a/core/resources/schemas/dbscripts/sqlserver/core-0.000-24.000.sql +++ b/core/resources/schemas/dbscripts/sqlserver/core-0.000-25.000.sql @@ -920,3 +920,40 @@ END; GO ALTER TABLE core.UsersData ADD LastActivity DATETIME NULL; + +/* 24.xxx SQL scripts */ + +ALTER TABLE core.datastates ADD Color NVARCHAR(7) NULL; + +DROP TABLE IF EXISTS core.PrincipalRelations; + +ALTER TABLE core.APIKeys ADD Description NVARCHAR(256); +ALTER TABLE core.APIKeys ADD LastUsed DATETIME; + +ALTER TABLE core.Containers ADD FileRootSize BIGINT; +ALTER TABLE core.Containers ADD FileRootLastCrawled DATETIME; +ALTER TABLE core.Containers ADD CONSTRAINT PK_Containers PRIMARY KEY (RowId); +ALTER TABLE core.Containers DROP CONSTRAINT UQ_Containers_RowID; + +-- Adding a PK on RowId seemed like a good idea, but it broke existing lookups to core.Containers and other assumptions. +-- We could add a PK on EntityId, but that column is currently nullable. For now, we'll just live without a PK. +ALTER TABLE core.Containers DROP CONSTRAINT PK_Containers; +ALTER TABLE core.Containers ADD CONSTRAINT UQ_Containers_RowId UNIQUE CLUSTERED (RowId); + +-- Shift the core.Logins PK from Email to UserId. Add UserId column as NULLABLE, populate it from core.Principals, +-- delete rows that didn't join (UserId IS NULL), make UserId NOT NULL, drop the old PK, and add the new PK. + +ALTER TABLE core.Logins ADD UserId USERID; +GO + +UPDATE core.Logins SET UserId = (SELECT UserId FROM core.Principals p WHERE Name = Email); +DELETE FROM core.Logins WHERE UserId IS NULL; +ALTER TABLE core.Logins ALTER COLUMN UserId USERID NOT NULL; +GO + +ALTER TABLE core.Logins DROP CONSTRAINT PK_Logins; +ALTER TABLE core.Logins ADD CONSTRAINT PK_Logins PRIMARY KEY (UserId); + +-- LabKey no longer reads or writes to the Email column. But we'll leave the column in place until 24.12 as a precaution. +ALTER TABLE core.Logins ALTER COLUMN Email VARCHAR(255) NULL; +GO diff --git a/core/resources/schemas/dbscripts/sqlserver/core-24.001-24.002.sql b/core/resources/schemas/dbscripts/sqlserver/core-24.001-24.002.sql deleted file mode 100644 index df5a5e3c731..00000000000 --- a/core/resources/schemas/dbscripts/sqlserver/core-24.001-24.002.sql +++ /dev/null @@ -1 +0,0 @@ -EXEC core.executeJavaUpgradeCode 'makeWithCounterCaseInsensitive'; diff --git a/core/resources/schemas/dbscripts/sqlserver/core-24.002-24.003.sql b/core/resources/schemas/dbscripts/sqlserver/core-24.002-24.003.sql deleted file mode 100644 index 62eeb7031d3..00000000000 --- a/core/resources/schemas/dbscripts/sqlserver/core-24.002-24.003.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE core.datastates ADD Color NVARCHAR(7) NULL; diff --git a/core/resources/schemas/dbscripts/sqlserver/core-24.003-24.004.sql b/core/resources/schemas/dbscripts/sqlserver/core-24.003-24.004.sql deleted file mode 100644 index 541571cf120..00000000000 --- a/core/resources/schemas/dbscripts/sqlserver/core-24.003-24.004.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE IF EXISTS core.PrincipalRelations; diff --git a/core/resources/schemas/dbscripts/sqlserver/core-24.004-24.005.sql b/core/resources/schemas/dbscripts/sqlserver/core-24.004-24.005.sql deleted file mode 100644 index db849dd4ce0..00000000000 --- a/core/resources/schemas/dbscripts/sqlserver/core-24.004-24.005.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE core.APIKeys ADD Description NVARCHAR(256); -ALTER TABLE core.APIKeys ADD LastUsed DATETIME; diff --git a/core/resources/schemas/dbscripts/sqlserver/core-24.005-24.006.sql b/core/resources/schemas/dbscripts/sqlserver/core-24.005-24.006.sql deleted file mode 100644 index 07172e5307e..00000000000 --- a/core/resources/schemas/dbscripts/sqlserver/core-24.005-24.006.sql +++ /dev/null @@ -1,4 +0,0 @@ -ALTER TABLE core.Containers ADD FileRootSize BIGINT; -ALTER TABLE core.Containers ADD FileRootLastCrawled DATETIME; -ALTER TABLE core.Containers ADD CONSTRAINT PK_Containers PRIMARY KEY (RowId); -ALTER TABLE core.Containers DROP CONSTRAINT UQ_Containers_RowID; \ No newline at end of file diff --git a/core/resources/schemas/dbscripts/sqlserver/core-24.006-24.007.sql b/core/resources/schemas/dbscripts/sqlserver/core-24.006-24.007.sql deleted file mode 100644 index c61078ca65a..00000000000 --- a/core/resources/schemas/dbscripts/sqlserver/core-24.006-24.007.sql +++ /dev/null @@ -1,4 +0,0 @@ --- Adding a PK on RowId seemed like a good idea, but it broke existing lookups to core.Containers and other assumptions. --- We could add a PK on EntityId, but that column is currently nullable. For now, we'll just live without a PK. -ALTER TABLE core.Containers DROP CONSTRAINT PK_Containers; -ALTER TABLE core.Containers ADD CONSTRAINT UQ_Containers_RowId UNIQUE CLUSTERED (RowId); \ No newline at end of file diff --git a/core/resources/schemas/dbscripts/sqlserver/core-24.007-24.008.sql b/core/resources/schemas/dbscripts/sqlserver/core-24.007-24.008.sql deleted file mode 100644 index b5fa67958af..00000000000 --- a/core/resources/schemas/dbscripts/sqlserver/core-24.007-24.008.sql +++ /dev/null @@ -1,13 +0,0 @@ --- Shift the core.Logins PK from Email to UserId. Add UserId column as NULLABLE, populate it from core.Principals, --- delete rows that didn't join (UserId IS NULL), make UserId NOT NULL, drop the old PK, and add the new PK. - -ALTER TABLE core.Logins ADD UserId USERID; -GO - -UPDATE core.Logins SET UserId = (SELECT UserId FROM core.Principals p WHERE Name = Email); -DELETE FROM core.Logins WHERE UserId IS NULL; -ALTER TABLE core.Logins ALTER COLUMN UserId USERID NOT NULL; -GO - -ALTER TABLE core.Logins DROP CONSTRAINT PK_Logins; -ALTER TABLE core.Logins ADD CONSTRAINT PK_Logins PRIMARY KEY (UserId); diff --git a/core/resources/schemas/dbscripts/sqlserver/core-24.008-24.009.sql b/core/resources/schemas/dbscripts/sqlserver/core-24.008-24.009.sql deleted file mode 100644 index fe799dd0394..00000000000 --- a/core/resources/schemas/dbscripts/sqlserver/core-24.008-24.009.sql +++ /dev/null @@ -1,3 +0,0 @@ --- LabKey no longer reads or writes to the Email column. But we'll leave the column in place until 24.12 as a precaution. -ALTER TABLE core.Logins ALTER COLUMN Email VARCHAR(255) NULL; -GO diff --git a/core/resources/schemas/dbscripts/sqlserver/prop-0.000-24.000.sql b/core/resources/schemas/dbscripts/sqlserver/prop-0.000-25.000.sql similarity index 100% rename from core/resources/schemas/dbscripts/sqlserver/prop-0.000-24.000.sql rename to core/resources/schemas/dbscripts/sqlserver/prop-0.000-25.000.sql diff --git a/core/resources/schemas/dbscripts/sqlserver/prop-24.000-24.001.sql b/core/resources/schemas/dbscripts/sqlserver/prop-24.000-24.001.sql deleted file mode 100644 index 39c752dd56c..00000000000 --- a/core/resources/schemas/dbscripts/sqlserver/prop-24.000-24.001.sql +++ /dev/null @@ -1,2 +0,0 @@ --- Migrate "Weak" password strength setting to "Good" -UPDATE prop.Properties SET Value = 'Good' WHERE "Set" = (SELECT "Set" FROM prop.propertysets WHERE category = 'DatabaseAuthentication') AND Name = 'Strength' AND Value = 'Weak'; diff --git a/core/src/org/labkey/core/CoreUpgradeCode.java b/core/src/org/labkey/core/CoreUpgradeCode.java index 835ec11d3bf..13e1d93d31e 100644 --- a/core/src/org/labkey/core/CoreUpgradeCode.java +++ b/core/src/org/labkey/core/CoreUpgradeCode.java @@ -16,18 +16,13 @@ package org.labkey.core; import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; import org.labkey.api.attachments.AttachmentService; import org.labkey.api.attachments.AttachmentParentType; -import org.labkey.api.collections.CaseInsensitiveHashSet; -import org.labkey.api.data.Container; -import org.labkey.api.data.ContainerManager; import org.labkey.api.data.CoreSchema; import org.labkey.api.data.DeferredUpgrade; import org.labkey.api.data.SQLFragment; import org.labkey.api.data.SqlExecutor; import org.labkey.api.data.SqlSelector; -import org.labkey.api.data.TableInfo; import org.labkey.api.data.UpgradeCode; import org.labkey.api.data.dialect.TestUpgradeCodeCounter; import org.labkey.api.module.ModuleContext; @@ -38,12 +33,7 @@ import org.labkey.core.security.AllowedExternalResourceHosts; import org.labkey.core.security.AllowedExternalResourceHosts.AllowedHost; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.labkey.api.util.IntegerUtils.asInteger; public class CoreUpgradeCode implements UpgradeCode { @@ -72,99 +62,6 @@ public void upgradeCode(ModuleContext moduleContext) TestUpgradeCodeCounter.incrementCounter(); } - /** - * Remove WithCounter (SampleNameGenCounter-) core.DBSequences records with case-insensitive names, keep the one with the largest Value - */ - private static void removeDuplicateWithCounterSeqs(Container container) - { - TableInfo tableInfo = CoreSchema.getInstance().getTableInfoDbSequences(); - - SQLFragment sql = new SQLFragment() - .append("SELECT RowId, Name, Value \n") - .append("FROM ").append(tableInfo, "seq") - .append(" WHERE seq.NAME LIKE 'SampleNameGenCounter-%' AND seq.Container = ?").add(container) - .append(" ORDER BY Value DESC"); - - @NotNull Map[] results = new SqlSelector(tableInfo.getSchema(), sql).getMapArray(); - if (results.length > 0) - { - Set seqs = new CaseInsensitiveHashSet(); - Set toRemove = new HashSet<>(); - for (Map result : results) - { - String seqName = (String) result.get("Name"); - Long seqValue = (Long) result.get("Value"); - Integer seqRowId = asInteger(result.get("RowId")); - - if (seqs.contains(seqName)) // case-insensitive duplicates found - { - LOG.warn("A duplicate withCounter sequence '" + seqName + "' with value '" + seqValue + "' is removed."); - toRemove.add(seqRowId); - } - else - seqs.add(seqName); - } - - if (!toRemove.isEmpty()) - { - SQLFragment deleteSql = new SQLFragment("DELETE FROM ").append(tableInfo).append(" WHERE RowId"); - deleteSql = tableInfo.getSqlDialect().appendInClauseSql(deleteSql, toRemove); - new SqlExecutor(tableInfo.getSchema()).execute(deleteSql); - } - } - } - - private static void toLowerCaseWithCounterSeqs(Container container) - { - TableInfo tableInfo = CoreSchema.getInstance().getTableInfoDbSequences(); - SQLFragment toLowerSql = new SQLFragment("UPDATE ").append(tableInfo) - .append(" SET Name = LOWER(Name) ") - .append(" WHERE Container = ? AND NAME LIKE 'SampleNameGenCounter-%'") - .add(container); - new SqlExecutor(tableInfo.getSchema()).execute(toLowerSql); - } - - /** - * Called from core-24.001-24.002.sql to make withCounter naming pattern case-insensitive - * - For existing duplicate, only the one with the largest 'Value' is retained, to minimize naming conflict. - * - All withCounter sequence name is then updated to lower case - */ - @SuppressWarnings("unused") - public static void makeWithCounterCaseInsensitive(ModuleContext context) - { - if (context.isNewInstall()) - return; - - TableInfo tableInfo = CoreSchema.getInstance().getTableInfoDbSequences(); - - SQLFragment sql = new SQLFragment() - .append("SELECT DISTINCT Container\n") - .append("FROM ").append(tableInfo, "seq") - .append(" WHERE seq.NAME LIKE 'SampleNameGenCounter-%'"); - - @NotNull List containers = new SqlSelector(tableInfo.getSchema(), sql).getArrayList(String.class); - if (containers.isEmpty()) - return; - - for (String containerId : containers) - { - Container container = ContainerManager.getForId(containerId); - if (container == null) - { - LOG.warn("Container doesn't exist: " + containerId); - continue; - } - - LOG.info("** starting upgrade withCounter DBSequences in container: " + container.getPath()); - - removeDuplicateWithCounterSeqs(container); - - toLowerCaseWithCounterSeqs(container); - - LOG.info("** finished upgrade withCounter DBSequences for container: " + container.getPath()); - } - } - /** * Called from core-25.000-25.001.sql */ diff --git a/experiment/resources/schemas/dbscripts/postgresql/exp-0.000-24.000.sql b/experiment/resources/schemas/dbscripts/postgresql/exp-0.000-25.000.sql similarity index 94% rename from experiment/resources/schemas/dbscripts/postgresql/exp-0.000-24.000.sql rename to experiment/resources/schemas/dbscripts/postgresql/exp-0.000-25.000.sql index 0afad049208..745357a8099 100644 --- a/experiment/resources/schemas/dbscripts/postgresql/exp-0.000-24.000.sql +++ b/experiment/resources/schemas/dbscripts/postgresql/exp-0.000-25.000.sql @@ -901,3 +901,58 @@ CREATE TABLE exp.DataTypeExclusion CONSTRAINT PK_DataTypeExclusion PRIMARY KEY (RowId), CONSTRAINT UQ_DataTypeExclusion UNIQUE (DataTypeRowId, DataType, ExcludedContainer) ); + +/* 24.xxx SQL scripts */ + +CREATE TABLE exp.MaterialIndexed +( + MaterialId INT NOT NULL, + LastIndexed TIMESTAMP NOT NULL, + + CONSTRAINT PK_MaterialIndexing PRIMARY KEY (MaterialId), + CONSTRAINT FK_MaterialId FOREIGN KEY (MaterialId) REFERENCES exp.Material (RowId) ON DELETE CASCADE +); + +INSERT INTO exp.MaterialIndexed (MaterialId, LastIndexed) SELECT RowId, LastIndexed FROM exp.Material WHERE LastIndexed IS NOT NULL; + +ALTER TABLE exp.Material DROP COLUMN LastIndexed; + +CREATE TABLE exp.DataIndexed +( + DataId INT NOT NULL, + LastIndexed TIMESTAMP NOT NULL, + + CONSTRAINT PK_DataIndexing PRIMARY KEY (DataId), + CONSTRAINT FK_DataId FOREIGN KEY (DataId) REFERENCES exp.Data (RowId) ON DELETE CASCADE +); + +INSERT INTO exp.DataIndexed (DataId, LastIndexed) SELECT RowId, LastIndexed FROM exp.Data WHERE LastIndexed IS NOT NULL; + +ALTER TABLE exp.Data DROP COLUMN LastIndexed; + +CREATE TABLE exp.MaterialAncestors +( + RowId INT NOT NULL, + AncestorRowId INT NOT NULL, + AncestorTypeId VARCHAR(11), + + CONSTRAINT FK_MaterialAncestors_MaterialId FOREIGN KEY (RowId) REFERENCES exp.Material (RowId) ON DELETE CASCADE +); + +CREATE UNIQUE INDEX UQ_MaterialAncestors_AncestorTypeId_RowId ON exp.MaterialAncestors (AncestorTypeId, RowId); +CREATE INDEX IDX_MaterialAncestors_AncestorTypeId_RowId_AncestorRowId ON exp.MaterialAncestors (AncestorTypeId, RowId, AncestorRowId); + +CREATE TABLE exp.DataAncestors +( + RowId INT NOT NULL, + AncestorRowId INT NOT NULL, + AncestorTypeId VARCHAR(11), + + CONSTRAINT FK_DataAncestors_DataId FOREIGN KEY (RowId) REFERENCES exp.Data (RowId) ON DELETE CASCADE +); + +CREATE UNIQUE INDEX UQ_DataAncestors_AncestorTypeId_RowId ON exp.DataAncestors (AncestorTypeId, RowId); +CREATE INDEX IDX_DataAncestors_AncestorTypeId_RowId_AncestorRowId ON exp.DataAncestors (AncestorTypeId, RowId, AncestorRowId); + +DROP INDEX IF EXISTS exp.ix_material_cpastype; +CREATE INDEX ix_material_cpastype ON exp.material (cpastype, rowid); diff --git a/experiment/resources/schemas/dbscripts/postgresql/exp-24.000-24.001.sql b/experiment/resources/schemas/dbscripts/postgresql/exp-24.000-24.001.sql deleted file mode 100644 index eb23eb0bf19..00000000000 --- a/experiment/resources/schemas/dbscripts/postgresql/exp-24.000-24.001.sql +++ /dev/null @@ -1,26 +0,0 @@ -CREATE TABLE exp.MaterialIndexed -( - MaterialId INT NOT NULL, - LastIndexed TIMESTAMP NOT NULL, - - CONSTRAINT PK_MaterialIndexing PRIMARY KEY (MaterialId), - CONSTRAINT FK_MaterialId FOREIGN KEY (MaterialId) REFERENCES exp.Material (RowId) ON DELETE CASCADE -); - -INSERT INTO exp.MaterialIndexed (MaterialId, LastIndexed) SELECT RowId, LastIndexed FROM exp.Material WHERE LastIndexed IS NOT NULL; - -ALTER TABLE exp.Material DROP COLUMN LastIndexed; - - -CREATE TABLE exp.DataIndexed -( - DataId INT NOT NULL, - LastIndexed TIMESTAMP NOT NULL, - - CONSTRAINT PK_DataIndexing PRIMARY KEY (DataId), - CONSTRAINT FK_DataId FOREIGN KEY (DataId) REFERENCES exp.Data (RowId) ON DELETE CASCADE -); - -INSERT INTO exp.DataIndexed (DataId, LastIndexed) SELECT RowId, LastIndexed FROM exp.Data WHERE LastIndexed IS NOT NULL; - -ALTER TABLE exp.Data DROP COLUMN LastIndexed; diff --git a/experiment/resources/schemas/dbscripts/postgresql/exp-24.001-24.002.sql b/experiment/resources/schemas/dbscripts/postgresql/exp-24.001-24.002.sql deleted file mode 100644 index 4f3d164a7c5..00000000000 --- a/experiment/resources/schemas/dbscripts/postgresql/exp-24.001-24.002.sql +++ /dev/null @@ -1,2 +0,0 @@ -UPDATE exp.Material SET aliquotcount = 0, aliquotvolume = 0, availablealiquotcount = 0, availablealiquotvolume = 0 -WHERE (aliquotcount IS NULL OR aliquotcount = 0) AND aliquotedfromlsid IS NULL; \ No newline at end of file diff --git a/experiment/resources/schemas/dbscripts/postgresql/exp-24.002-24.003.sql b/experiment/resources/schemas/dbscripts/postgresql/exp-24.002-24.003.sql deleted file mode 100644 index 8497cbff973..00000000000 --- a/experiment/resources/schemas/dbscripts/postgresql/exp-24.002-24.003.sql +++ /dev/null @@ -1,25 +0,0 @@ -CREATE TABLE exp.MaterialAncestors -( - RowId INT NOT NULL, - AncestorRowId INT NOT NULL, - AncestorTypeId VARCHAR(11), - - CONSTRAINT FK_MaterialAncestors_MaterialId FOREIGN KEY (RowId) REFERENCES exp.Material (RowId) ON DELETE CASCADE -); - -CREATE UNIQUE INDEX UQ_MaterialAncestors_AncestorTypeId_RowId ON exp.MaterialAncestors (AncestorTypeId, RowId); -CREATE INDEX IDX_MaterialAncestors_AncestorTypeId_RowId_AncestorRowId ON exp.MaterialAncestors (AncestorTypeId, RowId, AncestorRowId); - - -CREATE TABLE exp.DataAncestors -( - RowId INT NOT NULL, - AncestorRowId INT NOT NULL, - AncestorTypeId VARCHAR(11), - - CONSTRAINT FK_DataAncestors_DataId FOREIGN KEY (RowId) REFERENCES exp.Data (RowId) ON DELETE CASCADE -); - -CREATE UNIQUE INDEX UQ_DataAncestors_AncestorTypeId_RowId ON exp.DataAncestors (AncestorTypeId, RowId); -CREATE INDEX IDX_DataAncestors_AncestorTypeId_RowId_AncestorRowId ON exp.DataAncestors (AncestorTypeId, RowId, AncestorRowId); - diff --git a/experiment/resources/schemas/dbscripts/postgresql/exp-24.003-24.004.sql b/experiment/resources/schemas/dbscripts/postgresql/exp-24.003-24.004.sql deleted file mode 100644 index 8ca031bd8a3..00000000000 --- a/experiment/resources/schemas/dbscripts/postgresql/exp-24.003-24.004.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT core.executeJavaUpgradeCode('addMissingSampleTypeIdsForSampleTimelineAudit'); diff --git a/experiment/resources/schemas/dbscripts/postgresql/exp-24.004-24.005.sql b/experiment/resources/schemas/dbscripts/postgresql/exp-24.004-24.005.sql deleted file mode 100644 index b86348593ae..00000000000 --- a/experiment/resources/schemas/dbscripts/postgresql/exp-24.004-24.005.sql +++ /dev/null @@ -1,2 +0,0 @@ -DROP INDEX IF EXISTS exp.ix_material_cpastype; -CREATE INDEX ix_material_cpastype ON exp.material (cpastype, rowid); \ No newline at end of file diff --git a/experiment/resources/schemas/dbscripts/postgresql/exp-24.005-24.006.sql b/experiment/resources/schemas/dbscripts/postgresql/exp-24.005-24.006.sql deleted file mode 100644 index a905465f002..00000000000 --- a/experiment/resources/schemas/dbscripts/postgresql/exp-24.005-24.006.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT core.executeJavaUpgradeCode('repopulateAncestors'); diff --git a/experiment/resources/schemas/dbscripts/sqlserver/exp-0.000-24.000.sql b/experiment/resources/schemas/dbscripts/sqlserver/exp-0.000-25.000.sql similarity index 95% rename from experiment/resources/schemas/dbscripts/sqlserver/exp-0.000-24.000.sql rename to experiment/resources/schemas/dbscripts/sqlserver/exp-0.000-25.000.sql index 21e68ba0a2e..580506524ba 100644 --- a/experiment/resources/schemas/dbscripts/sqlserver/exp-0.000-24.000.sql +++ b/experiment/resources/schemas/dbscripts/sqlserver/exp-0.000-25.000.sql @@ -1187,3 +1187,59 @@ BEGIN COMMIT END GO + +/* 24.xxx SQL scripts */ + +CREATE TABLE exp.MaterialIndexed +( + MaterialId INT NOT NULL, + LastIndexed DATETIME NOT NULL, + + CONSTRAINT PK_MaterialIndexing PRIMARY KEY (MaterialId), + CONSTRAINT FK_MaterialId FOREIGN KEY (MaterialId) REFERENCES exp.Material (RowId) ON DELETE CASCADE +); + +INSERT INTO exp.MaterialIndexed (MaterialId, LastIndexed) (SELECT RowId, LastIndexed FROM exp.Material WHERE LastIndexed IS NOT NULL); + +ALTER TABLE exp.Material DROP COLUMN LastIndexed; + + +CREATE TABLE exp.DataIndexed +( + DataId INT NOT NULL, + LastIndexed DATETIME NOT NULL, + + CONSTRAINT PK_DataIndexing PRIMARY KEY (DataId), + CONSTRAINT FK_DataId FOREIGN KEY (DataId) REFERENCES exp.Data (RowId) ON DELETE CASCADE +); + +INSERT INTO exp.DataIndexed (DataId, LastIndexed) (SELECT RowId, LastIndexed FROM exp.Data WHERE LastIndexed IS NOT NULL); + +ALTER TABLE exp.Data DROP COLUMN LastIndexed; + +CREATE TABLE exp.MaterialAncestors +( + RowId INT NOT NULL, + AncestorRowId INT NOT NULL, + AncestorTypeId VARCHAR(11), + + CONSTRAINT FK_MaterialAncestors_MaterialId FOREIGN KEY (RowId) REFERENCES exp.Material (RowId) ON DELETE CASCADE +); + +CREATE UNIQUE INDEX UQ_MaterialAncestors_AncestorTypeId_RowId ON exp.MaterialAncestors (AncestorTypeId, RowId); +CREATE INDEX IDX_MaterialAncestors_AncestorTypeId_RowId_AncestorRowId ON exp.MaterialAncestors (AncestorTypeId, RowId, AncestorRowId); + +CREATE TABLE exp.DataAncestors +( + RowId INT NOT NULL, + AncestorRowId INT NOT NULL, + AncestorTypeId VARCHAR(11), + + CONSTRAINT FK_DataAncestors_DataId FOREIGN KEY (RowId) REFERENCES exp.Data (RowId) ON DELETE CASCADE +); + +CREATE UNIQUE INDEX UQ_DataAncestors_AncestorTypeId_RowId ON exp.DataAncestors (AncestorTypeId, RowId); +CREATE INDEX IDX_DataAncestors_AncestorTypeId_RowId_AncestorRowId ON exp.DataAncestors (AncestorTypeId, RowId, AncestorRowId); + +DROP INDEX ix_material_cpastype on exp.material; +CREATE INDEX ix_material_cpastype ON exp.material (cpastype, rowid); diff --git a/experiment/resources/schemas/dbscripts/sqlserver/exp-24.000-24.001.sql b/experiment/resources/schemas/dbscripts/sqlserver/exp-24.000-24.001.sql deleted file mode 100644 index bc02401bada..00000000000 --- a/experiment/resources/schemas/dbscripts/sqlserver/exp-24.000-24.001.sql +++ /dev/null @@ -1,26 +0,0 @@ -CREATE TABLE exp.MaterialIndexed -( - MaterialId INT NOT NULL, - LastIndexed DATETIME NOT NULL, - - CONSTRAINT PK_MaterialIndexing PRIMARY KEY (MaterialId), - CONSTRAINT FK_MaterialId FOREIGN KEY (MaterialId) REFERENCES exp.Material (RowId) ON DELETE CASCADE -); - -INSERT INTO exp.MaterialIndexed (MaterialId, LastIndexed) (SELECT RowId, LastIndexed FROM exp.Material WHERE LastIndexed IS NOT NULL); - -ALTER TABLE exp.Material DROP COLUMN LastIndexed; - - -CREATE TABLE exp.DataIndexed -( - DataId INT NOT NULL, - LastIndexed DATETIME NOT NULL, - - CONSTRAINT PK_DataIndexing PRIMARY KEY (DataId), - CONSTRAINT FK_DataId FOREIGN KEY (DataId) REFERENCES exp.Data (RowId) ON DELETE CASCADE -); - -INSERT INTO exp.DataIndexed (DataId, LastIndexed) (SELECT RowId, LastIndexed FROM exp.Data WHERE LastIndexed IS NOT NULL); - -ALTER TABLE exp.Data DROP COLUMN LastIndexed; diff --git a/experiment/resources/schemas/dbscripts/sqlserver/exp-24.001-24.002.sql b/experiment/resources/schemas/dbscripts/sqlserver/exp-24.001-24.002.sql deleted file mode 100644 index 4f3d164a7c5..00000000000 --- a/experiment/resources/schemas/dbscripts/sqlserver/exp-24.001-24.002.sql +++ /dev/null @@ -1,2 +0,0 @@ -UPDATE exp.Material SET aliquotcount = 0, aliquotvolume = 0, availablealiquotcount = 0, availablealiquotvolume = 0 -WHERE (aliquotcount IS NULL OR aliquotcount = 0) AND aliquotedfromlsid IS NULL; \ No newline at end of file diff --git a/experiment/resources/schemas/dbscripts/sqlserver/exp-24.002-24.003.sql b/experiment/resources/schemas/dbscripts/sqlserver/exp-24.002-24.003.sql deleted file mode 100644 index 54d83082e9b..00000000000 --- a/experiment/resources/schemas/dbscripts/sqlserver/exp-24.002-24.003.sql +++ /dev/null @@ -1,24 +0,0 @@ -CREATE TABLE exp.MaterialAncestors -( - RowId INT NOT NULL, - AncestorRowId INT NOT NULL, - AncestorTypeId VARCHAR(11), - - CONSTRAINT FK_MaterialAncestors_MaterialId FOREIGN KEY (RowId) REFERENCES exp.Material (RowId) ON DELETE CASCADE -); - -CREATE UNIQUE INDEX UQ_MaterialAncestors_AncestorTypeId_RowId ON exp.MaterialAncestors (AncestorTypeId, RowId); -CREATE INDEX IDX_MaterialAncestors_AncestorTypeId_RowId_AncestorRowId ON exp.MaterialAncestors (AncestorTypeId, RowId, AncestorRowId); - -CREATE TABLE exp.DataAncestors -( - RowId INT NOT NULL, - AncestorRowId INT NOT NULL, - AncestorTypeId VARCHAR(11), - - CONSTRAINT FK_DataAncestors_DataId FOREIGN KEY (RowId) REFERENCES exp.Data (RowId) ON DELETE CASCADE -); - -CREATE UNIQUE INDEX UQ_DataAncestors_AncestorTypeId_RowId ON exp.DataAncestors (AncestorTypeId, RowId); -CREATE INDEX IDX_DataAncestors_AncestorTypeId_RowId_AncestorRowId ON exp.DataAncestors (AncestorTypeId, RowId, AncestorRowId); - diff --git a/experiment/resources/schemas/dbscripts/sqlserver/exp-24.003-24.004.sql b/experiment/resources/schemas/dbscripts/sqlserver/exp-24.003-24.004.sql deleted file mode 100644 index 2c39b36af49..00000000000 --- a/experiment/resources/schemas/dbscripts/sqlserver/exp-24.003-24.004.sql +++ /dev/null @@ -1 +0,0 @@ -EXEC core.executeJavaUpgradeCode 'addMissingSampleTypeIdsForSampleTimelineAudit'; diff --git a/experiment/resources/schemas/dbscripts/sqlserver/exp-24.004-24.005.sql b/experiment/resources/schemas/dbscripts/sqlserver/exp-24.004-24.005.sql deleted file mode 100644 index ea97d4dcfa6..00000000000 --- a/experiment/resources/schemas/dbscripts/sqlserver/exp-24.004-24.005.sql +++ /dev/null @@ -1,2 +0,0 @@ -DROP INDEX ix_material_cpastype on exp.material; -CREATE INDEX ix_material_cpastype ON exp.material (cpastype, rowid); \ No newline at end of file diff --git a/experiment/resources/schemas/dbscripts/sqlserver/exp-24.005-24.006.sql b/experiment/resources/schemas/dbscripts/sqlserver/exp-24.005-24.006.sql deleted file mode 100644 index 985a3b9eac8..00000000000 --- a/experiment/resources/schemas/dbscripts/sqlserver/exp-24.005-24.006.sql +++ /dev/null @@ -1 +0,0 @@ -EXEC core.executeJavaUpgradeCode 'repopulateAncestors'; diff --git a/experiment/src/org/labkey/experiment/ExperimentUpgradeCode.java b/experiment/src/org/labkey/experiment/ExperimentUpgradeCode.java index 476b2adde9a..cbfed9e3bb7 100644 --- a/experiment/src/org/labkey/experiment/ExperimentUpgradeCode.java +++ b/experiment/src/org/labkey/experiment/ExperimentUpgradeCode.java @@ -98,83 +98,6 @@ public class ExperimentUpgradeCode implements UpgradeCode { private static final Logger LOG = LogHelper.getLogger(ExperimentUpgradeCode.class, "Experiment upgrade status"); - // called from exp-24.003-24.004.sql - @SuppressWarnings("unused") - public static void addMissingSampleTypeIdsForSampleTimelineAudit(ModuleContext context) - { - if (context.isNewInstall()) - return; - - DbScope scope = ExperimentService.get().getSchema().getScope(); - List tableNames = new SqlSelector(scope, "SELECT StorageTableName FROM exp.domainDescriptor WHERE StorageSchemaName='audit' AND name='" + SampleTimelineAuditProvider.SampleTimelineAuditDomainKind.NAME + "'").getArrayList(String.class); - if (tableNames.size() > 1) - LOG.warn("Found {} tables for " + SampleTimelineAuditProvider.SampleTimelineAuditDomainKind.NAME, tableNames.size()); - - try (DbScope.Transaction transaction = scope.ensureTransaction()) - { - for (String table : tableNames) - { - SQLFragment countSql = new SQLFragment("SELECT COUNT(*) FROM audit.").append(table).append(" WHERE sampleTypeId = 0"); - SqlSelector countSelector = new SqlSelector(scope, countSql); - - long toUpdate = countSelector.getObject(Long.class); - LOG.info("There are {} audit log entries to be updated in audit.{}.", toUpdate, table); - // first update the type id by finding other audit entries that reference the same sample id. - if (toUpdate > 0) - { - LOG.info("Updating table audit.{} via self-join.", table); - SQLFragment updateSql = new SQLFragment("UPDATE audit.").append(table) - .append(" SET sampleTypeId = a3.sampleTypeId\n") - .append(" FROM\n") - .append(" (SELECT sampleId, rowId as rowIdToUpdate FROM audit.").append(table).append(" WHERE sampleTypeId = 0").append(") a2 ") - .append(" LEFT JOIN\n") - .append(" (SELECT MAX(sampleTypeId) as sampleTypeId, sampleId FROM audit.").append(table).append(" GROUP BY sampleId) a3") - .append(" ON a2.sampleId = a3.sampleId") - .append(" WHERE rowId = a2.rowIdToUpdate"); - long start = System.currentTimeMillis(); - SqlExecutor executor = new SqlExecutor(scope); - int numRows = executor.execute(updateSql); - long elapsed = System.currentTimeMillis() - start; - LOG.info("Updated {} rows via self-join for table {} in {} sec", numRows, table, elapsed / 1000); - } - - toUpdate = countSelector.getObject(Long.class); - if (toUpdate > 0) - { - // It may have happened that there's only one audit entry for a sample and that entry has a 0 for the type id, in which case we may be able - // to find the type id from the exp.materials table. Since samples may have been deleted, it isn't sufficient to do only this update - LOG.info("Updating table audit.{} via exp.materials.", table); - SQLFragment updateSql = new SQLFragment("UPDATE audit.").append(table) - .append(" SET sampleTypeId = m.materialSourceId\n") - .append(" FROM\n") - .append(" (SELECT sampleId, rowId as rowIdToUpdate FROM audit.").append(table).append(" WHERE sampleTypeId = 0").append(") a2 ") - .append(" LEFT JOIN\n") - .append(" (SELECT materialSourceId, rowId AS sampleRowId FROM exp.material) m") - .append(" ON a2.sampleId = m.sampleRowId") - .append(" WHERE rowId = a2.rowIdToUpdate"); - long start = System.currentTimeMillis(); - SqlExecutor executor = new SqlExecutor(scope); - int numRows = executor.execute(updateSql); - long elapsed = System.currentTimeMillis() - start; - LOG.info("Updated {} rows from exp.material table join in {} sec", numRows, elapsed / 1000); - } - long remaining = countSelector.getObject(Long.class); - LOG.info("There are {} rows in audit.{} that could not be updated with a proper sample type id.", remaining, table); - } - transaction.commit(); - } - } - - // called from exp-24.005-24.006.sql - @SuppressWarnings("unused") - public static void repopulateAncestors(ModuleContext context) - { - if (context.isNewInstall()) - return; - - ClosureQueryHelper.truncateAndRecreate(LOG); - } - // called from exp-25.006-25.007.sql @SuppressWarnings("unused") public static void ensureBigObjectIds(ModuleContext context) diff --git a/search/resources/schemas/dbscripts/postgresql/search-0.000-21.000.sql b/search/resources/schemas/dbscripts/postgresql/search-0.000-25.000.sql similarity index 100% rename from search/resources/schemas/dbscripts/postgresql/search-0.000-21.000.sql rename to search/resources/schemas/dbscripts/postgresql/search-0.000-25.000.sql diff --git a/search/resources/schemas/dbscripts/postgresql/search-24.000-24.001.sql b/search/resources/schemas/dbscripts/postgresql/search-24.000-24.001.sql deleted file mode 100644 index bfb6815e6ce..00000000000 --- a/search/resources/schemas/dbscripts/postgresql/search-24.000-24.001.sql +++ /dev/null @@ -1,4 +0,0 @@ --- Previously, every search schema bump resulted in aggressive reindexing; now we call the reindex() upgrade method --- explicitly. This upgrade script accommodates a major Lucene upgrade corresponding to an old 24.001 schema bump, --- ensuring that old servers are reindexed on upgrade. Issue #52513 -SELECT core.executeJavaUpgradeCode('reindex'); diff --git a/search/resources/schemas/dbscripts/sqlserver/search-0.000-21.000.sql b/search/resources/schemas/dbscripts/sqlserver/search-0.000-25.000.sql similarity index 98% rename from search/resources/schemas/dbscripts/sqlserver/search-0.000-21.000.sql rename to search/resources/schemas/dbscripts/sqlserver/search-0.000-25.000.sql index e0c7b0b92fc..0d5de49acf0 100644 --- a/search/resources/schemas/dbscripts/sqlserver/search-0.000-21.000.sql +++ b/search/resources/schemas/dbscripts/sqlserver/search-0.000-25.000.sql @@ -14,8 +14,6 @@ * limitations under the License. */ -/* search-0.00-10.10.sql */ - CREATE SCHEMA search; GO diff --git a/search/resources/schemas/dbscripts/sqlserver/search-24.000-24.001.sql b/search/resources/schemas/dbscripts/sqlserver/search-24.000-24.001.sql deleted file mode 100644 index 5570f1ae78d..00000000000 --- a/search/resources/schemas/dbscripts/sqlserver/search-24.000-24.001.sql +++ /dev/null @@ -1,4 +0,0 @@ --- Previously, every search schema bump resulted in aggressive reindexing; now we call the reindex() upgrade method --- explicitly. This upgrade script accommodates a major Lucene upgrade corresponding to an old 24.001 schema bump, --- ensuring that old servers are reindexed on upgrade. Issue #52513 -EXEC core.executeJavaUpgradeCode 'reindex'; From b9b4f07d6b619bb54a9f878a2923a26b7979188b Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Fri, 2 Jan 2026 22:44:48 -0800 Subject: [PATCH 2/3] More descriptive name for test update code method --- core/src/org/labkey/core/CoreUpgradeCode.java | 2 +- .../dialect/PostgreSqlDialectFactory.java | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/core/src/org/labkey/core/CoreUpgradeCode.java b/core/src/org/labkey/core/CoreUpgradeCode.java index 13e1d93d31e..fa78f0f3eaa 100644 --- a/core/src/org/labkey/core/CoreUpgradeCode.java +++ b/core/src/org/labkey/core/CoreUpgradeCode.java @@ -57,7 +57,7 @@ public void handleUnknownModules(ModuleContext context) /** Java upgrade method used for testing purposes (see PG and MSSQL InlineProcedureTestCase) */ @SuppressWarnings({"UnusedDeclaration"}) - public void upgradeCode(ModuleContext moduleContext) + public void testUpgradeCode(ModuleContext moduleContext) { TestUpgradeCodeCounter.incrementCounter(); } diff --git a/core/src/org/labkey/core/dialect/PostgreSqlDialectFactory.java b/core/src/org/labkey/core/dialect/PostgreSqlDialectFactory.java index 9b6bb504155..5e3fa1914f4 100644 --- a/core/src/org/labkey/core/dialect/PostgreSqlDialectFactory.java +++ b/core/src/org/labkey/core/dialect/PostgreSqlDialectFactory.java @@ -172,22 +172,22 @@ public static class InlineProcedureTestCase extends Assert public void testJavaUpgradeCode() { String goodSql = - "SELECT core.executeJavaUpgradeCode('upgradeCode');\n" + // Normal - "SELECT core.executeJavaInitializationCode('upgradeCode');\n" + // executeJavaInitializationCode works as a synonym - " SELECT core.executeJavaUpgradeCode ('upgradeCode') ; \n" + // Lots of whitespace - "select CORE.EXECUTEJAVAUPGRADECODE('upgradeCode');\n" + // Case-insensitive - "SELECT core.executeJavaUpgradeCode('upgradeCode');"; // No line ending + "SELECT core.executeJavaUpgradeCode('testUpgradeCode');\n" + // Normal + "SELECT core.executeJavaInitializationCode('testUpgradeCode');\n" + // executeJavaInitializationCode works as a synonym + " SELECT core.executeJavaUpgradeCode ('testUpgradeCode') ; \n" + // Lots of whitespace + "select CORE.EXECUTEJAVAUPGRADECODE('testUpgradeCode');\n" + // Case-insensitive + "SELECT core.executeJavaUpgradeCode('testUpgradeCode');"; // No line ending String badSql = - "/* SELECT core.executeJavaUpgradeCode('upgradeCode');\n" + // Inside block comment + "/* SELECT core.executeJavaUpgradeCode('testUpgradeCode');\n" + // Inside block comment " more comment\n" + "*/" + - " -- SELECT core.executeJavaUpgradeCode('upgradeCode');\n" + // Inside single-line comment - "SELECTcore.executeJavaUpgradeCode('upgradeCode');\n" + // Bad syntax - "SELECT core. executeJavaUpgradeCode('upgradeCode');\n" + // Bad syntax - "SEECT core.executeJavaUpgradeCode('upgradeCode');\n" + // Misspell SELECT - "SELECT core.executeJaavUpgradeCode('upgradeCode');\n" + // Misspell function name - "SELECT core.executeJavaUpgradeCode('upgradeCode')\n"; // No semicolon + " -- SELECT core.executeJavaUpgradeCode('testUpgradeCode');\n" + // Inside single-line comment + "SELECTcore.executeJavaUpgradeCode('testUpgradeCode');\n" + // Bad syntax + "SELECT core. executeJavaUpgradeCode('testUpgradeCode');\n" + // Bad syntax + "SEECT core.executeJavaUpgradeCode('testUpgradeCode');\n" + // Misspell SELECT + "SELECT core.executeJaavUpgradeCode('testUpgradeCode');\n" + // Misspell function name + "SELECT core.executeJavaUpgradeCode('testUpgradeCode')\n"; // No semicolon SqlDialect dialect = getOldestSupportedDialect(); ModuleContext coreContext = ModuleLoader.getInstance().getModuleContext(ModuleLoader.getInstance().getCoreModule()); @@ -202,7 +202,7 @@ public void testJavaUpgradeCode() assertEquals(0, TestUpgradeCodeCounter.getCount()); // Verify that fallbackHandler() is called if upgrade method doesn't exist - String fallbackTestSql = goodSql.replace("'upgradeCode'", "'bogusUpgradeCode'"); + String fallbackTestSql = goodSql.replace("'testUpgradeCode'", "'bogusUpgradeCode'"); TestUpgradeCodeCounter.resetCounter(); try { From 7830417ed444a38693c77d4b19b4831dff0439c0 Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Fri, 2 Jan 2026 23:52:58 -0800 Subject: [PATCH 3/3] Reorder and clean up core SQL scripts. SQL Server now supports DROP TABLE IF EXISTS. --- .../postgresql/core-0.000-25.000.sql | 139 ++++++------------ .../dbscripts/sqlserver/core-0.000-25.000.sql | 67 ++------- .../core/admin/sql/ScriptReorderer.java | 6 +- 3 files changed, 64 insertions(+), 148 deletions(-) diff --git a/core/resources/schemas/dbscripts/postgresql/core-0.000-25.000.sql b/core/resources/schemas/dbscripts/postgresql/core-0.000-25.000.sql index a8fbea51e10..9da1ced5d39 100644 --- a/core/resources/schemas/dbscripts/postgresql/core-0.000-25.000.sql +++ b/core/resources/schemas/dbscripts/postgresql/core-0.000-25.000.sql @@ -27,22 +27,23 @@ CREATE SCHEMA temp; CREATE TABLE core.Logins ( - Email VARCHAR(255) NOT NULL, - Crypt VARCHAR(64) NOT NULL, - Verification VARCHAR(64), - LastChanged TIMESTAMP NULL, - PreviousCrypts VARCHAR(1000), - RequestedEmail VARCHAR(255), - VerificationTimeout TIMESTAMP, - - CONSTRAINT PK_Logins PRIMARY KEY (Email) + Email VARCHAR(255) NULL, -- No longer used. Has been dropped in a later script. + Crypt VARCHAR(64) NOT NULL, + Verification VARCHAR(64), + LastChanged TIMESTAMP NULL, + PreviousCrypts VARCHAR(1000), + RequestedEmail VARCHAR(255), + VerificationTimeout TIMESTAMP, + UserId USERID NOT NULL, + + CONSTRAINT PK_Logins PRIMARY KEY (UserId) ); -- Principals is used for managing security related information -- It is not used for validating login, that requires an 'external' -- process, either using LDAP, JDBC, etc. (see Logins table) -- --- It does not contain contact info or other generic user visible data +-- It does not contain contact info or other generic user-visible data CREATE TABLE core.Principals ( @@ -53,19 +54,25 @@ CREATE TABLE core.Principals Type CHAR(1), -- 'u'=user 'g'=group 'm'=module-specific Active BOOLEAN NOT NULL DEFAULT TRUE, - CONSTRAINT PK_Principals PRIMARY KEY (UserId), - CONSTRAINT UQ_Principals_Container_Name_OwnerId UNIQUE (Container, Name, OwnerId) + CONSTRAINT PK_Principals PRIMARY KEY (UserId) ); SELECT SETVAL('core.Principals_UserId_Seq', 1000); +-- NULLS NOT DISTINCT syntax was introduced in PostgreSQL 15, so we can't use it yet. Once PostgreSQL 15 is a minimum +-- we could consider switching back to NULLS NOT DISTINCT. + +-- COALESCE() works around PostgreSQL behavior that NULL values are not unique +CREATE UNIQUE INDEX UQ_Principals_Container_Name_OwnerId ON core.Principals + (COALESCE(Container, '00000000-0000-0000-0000-000000000000'), LOWER(Name), COALESCE(OwnerId, '00000000-0000-0000-0000-000000000000')); + -- maps users to groups CREATE TABLE core.Members ( - UserId USERID, - GroupId USERID, + UserId USERID, + GroupId USERID, - CONSTRAINT PK_Members PRIMARY KEY (UserId, GroupId) + CONSTRAINT PK_Members PRIMARY KEY (UserId, GroupId) ); CREATE TABLE core.UsersData @@ -96,9 +103,8 @@ CREATE TABLE core.UsersData CONSTRAINT UQ_DisplayName UNIQUE (DisplayName) ); -/* 22.xxx SQL scripts */ - ALTER TABLE core.UsersData ADD System BOOLEAN NOT NULL DEFAULT FALSE; +ALTER TABLE core.UsersData ADD LastActivity TIMESTAMP NULL; CREATE TABLE core.Containers ( @@ -117,7 +123,6 @@ CREATE TABLE core.Containers Title VARCHAR(1000), Type VARCHAR(16) NOT NULL DEFAULT 'normal', - CONSTRAINT UQ_Containers_RowId UNIQUE (RowId), CONSTRAINT UQ_Containers_EntityId UNIQUE (EntityId), CONSTRAINT UQ_Containers_Parent_Name UNIQUE (Parent, Name), CONSTRAINT FK_Containers_Containers FOREIGN KEY (Parent) REFERENCES core.Containers(EntityId) @@ -127,20 +132,27 @@ CREATE INDEX IX_Containers_Parent_Entity ON core.Containers(Parent, EntityId); ALTER TABLE core.Containers ADD LockState VARCHAR(25) NULL; ALTER TABLE core.Containers ADD ExpirationDate TIMESTAMP NULL; +ALTER TABLE core.Containers ADD FileRootSize BIGINT; +ALTER TABLE core.Containers ADD FileRootLastCrawled TIMESTAMP; + +-- Adding a PK on RowId seemed like a good idea, but it broke existing lookups to core.Containers and other assumptions. +-- We could add a PK on EntityId, but that column is currently nullable. For now, we'll just live without a PK. +ALTER TABLE core.Containers ADD CONSTRAINT UQ_Containers_RowId UNIQUE (RowId); -- table for all modules CREATE TABLE core.Modules ( - Name VARCHAR(255), + Name VARCHAR(255) NOT NULL, ClassName VARCHAR(255), SchemaVersion FLOAT8 NULL, Enabled BOOLEAN DEFAULT '1', AutoUninstall BOOLEAN NOT NULL DEFAULT FALSE, -- TRUE means LabKey should uninstall this module (drop schemas, delete SqlScripts rows, delete Modules rows), if it no longer exists - Schemas VARCHAR(4000) NULL, -- Schemas managed by this module; LabKey will drop these schemas when a module marked AutoUninstall = TRUE is missing - - CONSTRAINT PK_Modules PRIMARY KEY (Name) + Schemas VARCHAR(4000) NULL -- Schemas managed by this module; LabKey will drop these schemas when a module marked AutoUninstall = TRUE is missing ); +-- Create case-insensitive unique constraint instead of a PK +CREATE UNIQUE INDEX UQ_ModuleName ON core.Modules (LOWER(Name)); + -- keep track of sql scripts that have been run in each module CREATE TABLE core.SqlScripts ( @@ -384,17 +396,19 @@ CREATE INDEX IX_Notification_User ON core.Notifications(UserId); CREATE TABLE core.DataStates ( - RowId SERIAL, - Label VARCHAR(64) NULL, - Description VARCHAR(500) NULL, - Container ENTITYID NOT NULL, - PublicData BOOLEAN NOT NULL, - CONSTRAINT PK_QCState PRIMARY KEY (RowId), - CONSTRAINT UQ_QCState_Label UNIQUE(Label, Container) + RowId SERIAL, + Label VARCHAR(64) NULL, + Description VARCHAR(500) NULL, + Container ENTITYID NOT NULL, + PublicData BOOLEAN NOT NULL, + CONSTRAINT PK_QCState PRIMARY KEY (RowId), + CONSTRAINT UQ_QCState_Label UNIQUE(Label, Container) ); ALTER TABLE core.DataStates ADD COLUMN StateType VARCHAR(20); +ALTER TABLE core.datastates ADD COLUMN Color VARCHAR(7); + CREATE TABLE core.APIKeys ( RowId SERIAL, @@ -407,6 +421,9 @@ CREATE TABLE core.APIKeys CONSTRAINT UQ_CRYPT UNIQUE (Crypt) ); +ALTER TABLE core.APIKeys ADD COLUMN Description VARCHAR(256); +ALTER TABLE core.APIKeys ADD COLUMN LastUsed TIMESTAMP; + CREATE TABLE core.ReportEngines ( RowId SERIAL, @@ -435,16 +452,6 @@ CREATE TABLE core.ReportEngineMap CONSTRAINT FK_ReportEngineMap_ReportEngines FOREIGN KEY (EngineId) REFERENCES core.ReportEngines (RowId) ); -CREATE TABLE core.PrincipalRelations -( - userid USERID NOT NULL, - otherid USERID NOT NULL, - relationship VARCHAR(100) NOT NULL, - created TIMESTAMP, - - CONSTRAINT PK_PrincipalRelations PRIMARY KEY (userid, otherid, relationship) -); - CREATE TABLE core.AuthenticationConfigurations ( RowId SERIAL, @@ -701,57 +708,3 @@ END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; - --- Switch Name from PK to case-insensitive unique constraint -ALTER TABLE core.Modules DROP CONSTRAINT PK_Modules; -ALTER TABLE core.Modules ALTER COLUMN Name SET NOT NULL; -CREATE UNIQUE INDEX UQ_ModuleName ON core.Modules (LOWER(Name)); - -ALTER TABLE core.UsersData ADD LastActivity TIMESTAMP NULL; - --- NULLS NOT DISTINCT syntax was introduced in PostgreSQL 15, so we can't use it yet. Next script adds the correct index. ---ALTER TABLE core.Principals DROP CONSTRAINT UQ_Principals_Container_Name_OwnerId; ---CREATE UNIQUE INDEX UQ_Principals_Container_Name_OwnerId ON core.Principals (Container, LOWER(Name), OwnerId) NULLS NOT DISTINCT; - --- Previous script attempted to create a unique index specifying NULLS NOT DISTINCT, but that syntax was just introduced --- in PostgreSQL 15. We want to fix servers that failed to create the new index; we also want to migrate servers that --- created it successfully, for consistency. Once PostgreSQL 15 is a minimum we could consider switching back to NULLS --- NOT DISTINCT. - -ALTER TABLE core.Principals DROP CONSTRAINT IF EXISTS UQ_Principals_Container_Name_OwnerId; -DROP INDEX IF EXISTS core.UQ_Principals_Container_Name_OwnerId; --- COALESCE() works around PostgreSQL behavior that NULL values are not unique -CREATE UNIQUE INDEX UQ_Principals_Container_Name_OwnerId ON core.Principals - (COALESCE(Container, '00000000-0000-0000-0000-000000000000'), LOWER(Name), COALESCE(OwnerId, '00000000-0000-0000-0000-000000000000')); - -/* 24.xxx SQL scripts */ - -ALTER TABLE core.datastates ADD COLUMN Color VARCHAR(7); - -SELECT core.fn_dropifexists('PrincipalRelations','core','TABLE', NULL); - -ALTER TABLE core.APIKeys ADD COLUMN Description VARCHAR(256); -ALTER TABLE core.APIKeys ADD COLUMN LastUsed TIMESTAMP; - -ALTER TABLE core.Containers ADD FileRootSize BIGINT; -ALTER TABLE core.Containers ADD FileRootLastCrawled TIMESTAMP; -ALTER TABLE core.Containers ADD CONSTRAINT PK_Containers PRIMARY KEY (RowId); -ALTER TABLE core.Containers DROP CONSTRAINT UQ_Containers_RowID; - --- Adding a PK on RowId seemed like a good idea, but it broke existing lookups to core.Containers and other assumptions. --- We could add a PK on EntityId, but that column is currently nullable. For now, we'll just live without a PK. -ALTER TABLE core.Containers DROP CONSTRAINT PK_Containers; -ALTER TABLE core.Containers ADD CONSTRAINT UQ_Containers_RowId UNIQUE (RowId); - --- Shift the core.Logins PK from Email to UserId. Add UserId column as NULLABLE, populate it from core.Principals, --- delete rows that didn't join (UserId IS NULL), make UserId NOT NULL, drop the old PK, and add the new PK. - -ALTER TABLE core.Logins ADD UserId USERID; -UPDATE core.Logins SET UserId = (SELECT UserId FROM core.Principals p WHERE Name = Email); -DELETE FROM core.Logins WHERE UserId IS NULL; -ALTER TABLE core.Logins ALTER COLUMN UserId DROP NOT NULL; -ALTER TABLE core.Logins DROP CONSTRAINT PK_Logins; -ALTER TABLE core.Logins ADD CONSTRAINT PK_Logins PRIMARY KEY (UserId); - --- LabKey no longer reads or writes to the Email column. But we'll leave the column in place until 24.12 as a precaution. -ALTER TABLE core.Logins ALTER COLUMN Email DROP NOT NULL; diff --git a/core/resources/schemas/dbscripts/sqlserver/core-0.000-25.000.sql b/core/resources/schemas/dbscripts/sqlserver/core-0.000-25.000.sql index c81fea2aec2..8f60b0ce53d 100644 --- a/core/resources/schemas/dbscripts/sqlserver/core-0.000-25.000.sql +++ b/core/resources/schemas/dbscripts/sqlserver/core-0.000-25.000.sql @@ -29,15 +29,16 @@ GO CREATE TABLE core.Logins ( - Email VARCHAR(255) NOT NULL, + Email VARCHAR(255) NULL, -- No longer used. A later script will drop this column. Crypt VARCHAR(64) NOT NULL, Verification VARCHAR(64), LastChanged DATETIME NULL, PreviousCrypts VARCHAR(1000), RequestedEmail NVARCHAR(255), VerificationTimeout DATETIME, + UserId USERID NOT NULL, - CONSTRAINT PK_Logins PRIMARY KEY (Email) + CONSTRAINT PK_Logins PRIMARY KEY (UserId) ); -- Principals is used for managing security related information @@ -97,6 +98,7 @@ CREATE TABLE core.UsersData ); ALTER TABLE core.UsersData ADD System BIT NOT NULL DEFAULT 0; +ALTER TABLE core.UsersData ADD LastActivity DATETIME NULL; CREATE TABLE core.Containers ( @@ -115,7 +117,6 @@ CREATE TABLE core.Containers Title NVARCHAR(1000), Type VARCHAR(16) CONSTRAINT DF_Container_Type DEFAULT 'normal' NOT NULL, - CONSTRAINT UQ_Containers_RowId UNIQUE CLUSTERED (RowId), CONSTRAINT UQ_Containers_EntityId UNIQUE (EntityId), CONSTRAINT UQ_Containers_Parent_Name UNIQUE (Parent, Name), CONSTRAINT FK_Containers_Containers FOREIGN KEY (Parent) REFERENCES core.Containers(EntityId) @@ -125,6 +126,12 @@ CREATE INDEX IX_Containers_Parent_Entity ON core.Containers(Parent, EntityId); ALTER TABLE core.Containers ADD LockState VARCHAR(25) NULL; ALTER TABLE core.Containers ADD ExpirationDate DATETIME NULL; +ALTER TABLE core.Containers ADD FileRootSize BIGINT; +ALTER TABLE core.Containers ADD FileRootLastCrawled DATETIME; + +-- Adding a PK on RowId seemed like a good idea, but it broke existing lookups to core.Containers and other assumptions. +-- We could add a PK on EntityId, but that column is currently nullable. For now, we'll just live without a PK. +ALTER TABLE core.Containers ADD CONSTRAINT UQ_Containers_RowId UNIQUE CLUSTERED (RowId); -- table for all modules CREATE TABLE core.Modules @@ -217,6 +224,7 @@ CREATE TABLE core.ContainerAliases ); ALTER TABLE core.containeraliases ALTER COLUMN path NVARCHAR(4000); + CREATE TABLE core.MappedDirectories ( EntityId ENTITYID NOT NULL, @@ -389,6 +397,7 @@ CREATE TABLE core.DataStates ); ALTER TABLE core.DataStates ADD StateType NVARCHAR(20); +ALTER TABLE core.datastates ADD Color NVARCHAR(7) NULL; CREATE TABLE core.APIKeys ( @@ -402,6 +411,9 @@ CREATE TABLE core.APIKeys CONSTRAINT UQ_CRYPT UNIQUE (Crypt) ); +ALTER TABLE core.APIKeys ADD Description NVARCHAR(256); +ALTER TABLE core.APIKeys ADD LastUsed DATETIME; + CREATE TABLE core.ReportEngines ( RowId INT IDENTITY(1,1) NOT NULL, @@ -430,16 +442,6 @@ CREATE TABLE core.ReportEngineMap CONSTRAINT FK_ReportEngineMap_ReportEngines FOREIGN KEY (EngineId) REFERENCES core.ReportEngines (RowId) ); -CREATE TABLE core.PrincipalRelations -( - userid USERID NOT NULL, - otherid USERID NOT NULL, - relationship NVARCHAR(100) NOT NULL, - created DATETIME, - - CONSTRAINT PK_PrincipalRelations PRIMARY KEY (userid, otherid, relationship) -); - CREATE TABLE core.AuthenticationConfigurations ( RowId INT IDENTITY(1,1), @@ -918,42 +920,3 @@ BEGIN END; GO - -ALTER TABLE core.UsersData ADD LastActivity DATETIME NULL; - -/* 24.xxx SQL scripts */ - -ALTER TABLE core.datastates ADD Color NVARCHAR(7) NULL; - -DROP TABLE IF EXISTS core.PrincipalRelations; - -ALTER TABLE core.APIKeys ADD Description NVARCHAR(256); -ALTER TABLE core.APIKeys ADD LastUsed DATETIME; - -ALTER TABLE core.Containers ADD FileRootSize BIGINT; -ALTER TABLE core.Containers ADD FileRootLastCrawled DATETIME; -ALTER TABLE core.Containers ADD CONSTRAINT PK_Containers PRIMARY KEY (RowId); -ALTER TABLE core.Containers DROP CONSTRAINT UQ_Containers_RowID; - --- Adding a PK on RowId seemed like a good idea, but it broke existing lookups to core.Containers and other assumptions. --- We could add a PK on EntityId, but that column is currently nullable. For now, we'll just live without a PK. -ALTER TABLE core.Containers DROP CONSTRAINT PK_Containers; -ALTER TABLE core.Containers ADD CONSTRAINT UQ_Containers_RowId UNIQUE CLUSTERED (RowId); - --- Shift the core.Logins PK from Email to UserId. Add UserId column as NULLABLE, populate it from core.Principals, --- delete rows that didn't join (UserId IS NULL), make UserId NOT NULL, drop the old PK, and add the new PK. - -ALTER TABLE core.Logins ADD UserId USERID; -GO - -UPDATE core.Logins SET UserId = (SELECT UserId FROM core.Principals p WHERE Name = Email); -DELETE FROM core.Logins WHERE UserId IS NULL; -ALTER TABLE core.Logins ALTER COLUMN UserId USERID NOT NULL; -GO - -ALTER TABLE core.Logins DROP CONSTRAINT PK_Logins; -ALTER TABLE core.Logins ADD CONSTRAINT PK_Logins PRIMARY KEY (UserId); - --- LabKey no longer reads or writes to the Email column. But we'll leave the column in place until 24.12 as a precaution. -ALTER TABLE core.Logins ALTER COLUMN Email VARCHAR(255) NULL; -GO diff --git a/core/src/org/labkey/core/admin/sql/ScriptReorderer.java b/core/src/org/labkey/core/admin/sql/ScriptReorderer.java index de108a36624..8309dc41e61 100644 --- a/core/src/org/labkey/core/admin/sql/ScriptReorderer.java +++ b/core/src/org/labkey/core/admin/sql/ScriptReorderer.java @@ -93,9 +93,10 @@ public String getReorderedScript(boolean isHtml) patterns.add(new SqlPattern(getRegExWithPrefix("CREATE TABLE "), Type.Table, Operation.Other)); patterns.add(new SqlPattern(getRegExWithPrefix("TRUNCATE( TABLE)? "), Type.Table, Operation.Other)); + patterns.add(new SqlPattern(getRegExWithPrefix("DROP TABLE (IF EXISTS )?"), Type.Table, Operation.Other)); + if (_schema.getSqlDialect().isSqlServer()) { - patterns.add(new SqlPattern(getRegExWithPrefix("DROP TABLE "), Type.Table, Operation.Other)); patterns.add(new SqlPattern(getRegExWithPrefix("CREATE TABLE "), Type.Table, Operation.Other)); // Specific sp_rename pattern for table rename @@ -107,14 +108,13 @@ public String getReorderedScript(boolean isHtml) patterns.add(new SqlPattern("EXEC(UTE)? core\\.fn_dropifexists\\s*'(\\w+)',\\s*'(?\\w+)'.*?" + STATEMENT_ENDING_REGEX, Type.NonTable, Operation.Other)); // Index names are prefixed with their associated table names on SQL Server - patterns.add(new SqlPattern(getRegExWithPrefix("DROP INDEX "), Type.Table, Operation.Other)); + patterns.add(new SqlPattern(getRegExWithPrefix("DROP INDEX (IF EXISTS )?"), Type.Table, Operation.Other)); patterns.add(new SqlPattern("(CREATE|ALTER) PROCEDURE .+?" + STATEMENT_ENDING_REGEX, Type.NonTable, Operation.Other)); } else { patterns.add(new SqlPattern("ALTER TABLE " + TABLE_NAME_REGEX + " RENAME TO " + TABLE_NAME2_REGEX + STATEMENT_ENDING_REGEX, Type.Table, Operation.RenameTable)); - patterns.add(new SqlPattern(getRegExWithPrefix("DROP TABLE (IF EXISTS )?"), Type.Table, Operation.Other)); patterns.add(new SqlPattern(getRegExWithPrefix("CREATE (TEMPORARY )?TABLE "), Type.Table, Operation.Other)); patterns.add(new SqlPattern("SELECT core\\.fn_dropifexists\\s*\\('(?\\w+)',\\s*'(?\\w+)',\\s*'(TABLE|COLUMN|INDEX|DEFAULT|CONSTRAINT)'.+?" + STATEMENT_ENDING_REGEX, Type.Table, Operation.Other)); patterns.add(new SqlPattern("SELECT core\\.fn_dropifexists\\s*\\('(\\w+)',\\s*'(?\\w+)'.+?" + STATEMENT_ENDING_REGEX, Type.NonTable, Operation.Other));