diff --git a/frontend/app/(hub)/layout.tsx b/frontend/app/(hub)/layout.tsx
index 56684504..33f168b3 100644
--- a/frontend/app/(hub)/layout.tsx
+++ b/frontend/app/(hub)/layout.tsx
@@ -122,7 +122,7 @@ export default function HubLayout({ children }: { children: React.ReactNode }) {
setLoading(true, 'Converting raw census data...');
const censusList = await createAndUpdateCensusList(censusRDSLoad);
if (censusListDispatch) {
- censusListDispatch({ censusList });
+ await censusListDispatch({censusList});
}
setLoading(false);
setCensusListLoaded(true);
@@ -322,7 +322,7 @@ export default function HubLayout({ children }: { children: React.ReactNode }) {
paddingBottom: '20px',
flexDirection: 'column',
}}>
- {renderSwitch(usePathname())}
+ {renderSwitch(pathname)}
;
+}
\ No newline at end of file
diff --git a/frontend/app/api/fixeddata/[dataType]/[[...slugs]]/route.ts b/frontend/app/api/fixeddata/[dataType]/[[...slugs]]/route.ts
index 2c28f360..7ec87ed7 100644
--- a/frontend/app/api/fixeddata/[dataType]/[[...slugs]]/route.ts
+++ b/frontend/app/api/fixeddata/[dataType]/[[...slugs]]/route.ts
@@ -1,13 +1,19 @@
-import { getConn, runQuery } from "@/components/processors/processormacros";
+import {getConn, runQuery} from "@/components/processors/processormacros";
import MapperFactory from "@/config/datamapper";
-import { handleError } from "@/utils/errorhandler";
-import { PoolConnection, format } from "mysql2/promise";
-import { NextRequest, NextResponse } from "next/server";
-import { generateInsertOperations, generateUpdateOperations, StemDimensionsViewQueryConfig, AllTaxonomiesViewQueryConfig, StemTaxonomiesViewQueryConfig } from '@/components/processors/processorhelperfunctions';
-import { HTTPResponses } from "@/config/macros";
+import {handleError} from "@/utils/errorhandler";
+import {PoolConnection, format} from "mysql2/promise";
+import {NextRequest, NextResponse} from "next/server";
+import {
+ generateInsertOperations,
+ generateUpdateOperations,
+ StemDimensionsViewQueryConfig,
+ AllTaxonomiesViewQueryConfig,
+ StemTaxonomiesViewQueryConfig
+} from '@/components/processors/processorhelperfunctions';
+import {HTTPResponses} from "@/config/macros";
// slugs SHOULD CONTAIN AT MINIMUM: schema, page, pageSize, plotID, plotCensusNumber, (optional) quadratID
-export async function GET(request: NextRequest, { params }: {
+export async function GET(request: NextRequest, {params}: {
params: { dataType: string, slugs?: string[] }
}): Promise> {
if (!params.slugs || params.slugs.length < 5) throw new Error("slugs not received.");
@@ -57,6 +63,8 @@ export async function GET(request: NextRequest, { params }: {
LIMIT ?, ?`;
queryParams.push(plotID, plotCensusNumber, page * pageSize, pageSize);
break;
+ case 'measurementssummaryview':
+ case 'viewfulltableview':
case 'quadrats':
paginatedQuery = `
SELECT SQL_CALC_FOUND_ROWS q.*
@@ -68,7 +76,6 @@ export async function GET(request: NextRequest, { params }: {
WHERE c.PlotID = ?
AND c.PlotCensusNumber = ?
)
- GROUP BY q.QuadratID
LIMIT ?, ?`;
queryParams.push(plotID, plotID, plotCensusNumber, page * pageSize, pageSize);
break;
@@ -100,9 +107,6 @@ export async function GET(request: NextRequest, { params }: {
queryParams.push(plotID, page * pageSize, pageSize);
break;
case 'coremeasurements':
- case 'measurementssummaryview':
- case 'viewfulltableview':
- case 'stemdimensionsview':
// Retrieve multiple past CensusID for the given PlotCensusNumber
const censusQuery = `
SELECT CensusID
@@ -155,9 +159,12 @@ export async function GET(request: NextRequest, { params }: {
}
const paginatedResults = await runQuery(conn, format(paginatedQuery, queryParams));
+ console.log('formatted query: ', format(paginatedQuery, queryParams));
+ console.log('paginated results: ', paginatedResults);
const totalRowsQuery = "SELECT FOUND_ROWS() as totalRows";
const totalRowsResult = await runQuery(conn, totalRowsQuery);
+ console.log('total rows results: ', totalRowsResult);
const totalRows = totalRowsResult[0].totalRows;
if (updatedMeasurementsExist) {
@@ -180,7 +187,7 @@ export async function GET(request: NextRequest, { params }: {
output: rows,
deprecated: deprecatedRows,
totalCount: totalRows
- }), { status: HTTPResponses.OK });
+ }), {status: HTTPResponses.OK});
} else {
const mapper = MapperFactory.getMapper(params.dataType);
const rows = mapper.mapData(paginatedResults);
@@ -188,7 +195,7 @@ export async function GET(request: NextRequest, { params }: {
output: rows,
deprecated: undefined,
totalCount: totalRows
- }), { status: HTTPResponses.OK });
+ }), {status: HTTPResponses.OK});
}
} catch (error: any) {
if (conn) await conn.rollback();
@@ -199,12 +206,12 @@ export async function GET(request: NextRequest, { params }: {
}
// required dynamic parameters: dataType (fixed),[ schema, gridID value] -> slugs
-export async function POST(request: NextRequest, { params }: { params: { dataType: string, slugs?: string[] } }) {
+export async function POST(request: NextRequest, {params}: { params: { dataType: string, slugs?: string[] } }) {
if (!params.slugs) throw new Error("slugs not provided");
const [schema, gridID] = params.slugs;
if (!schema || !gridID) throw new Error("no schema or gridID provided");
let conn: PoolConnection | null = null;
- const { newRow } = await request.json();
+ const {newRow} = await request.json();
let insertID: number | undefined = undefined;
try {
conn = await getConn();
@@ -245,7 +252,7 @@ export async function POST(request: NextRequest, { params }: { params: { dataTyp
insertID = results.insertId;
}
await conn.commit();
- return NextResponse.json({ message: "Insert successful", createdID: insertID}, { status: HTTPResponses.OK });
+ return NextResponse.json({message: "Insert successful", createdID: insertID}, {status: HTTPResponses.OK});
} catch (error: any) {
return handleError(error, conn, newRow);
} finally {
@@ -254,21 +261,23 @@ export async function POST(request: NextRequest, { params }: { params: { dataTyp
}
// slugs: schema, gridID
-export async function PATCH(request: NextRequest, { params }: { params: { dataType: string, slugs?: string[] } }) {
+export async function PATCH(request: NextRequest, {params}: { params: { dataType: string, slugs?: string[] } }) {
if (!params.slugs) throw new Error("slugs not provided");
const [schema, gridID] = params.slugs;
if (!schema || !gridID) throw new Error("no schema or gridID provided");
let conn: PoolConnection | null = null;
const demappedGridID = gridID.charAt(0).toUpperCase() + gridID.substring(1);
- const { newRow, oldRow } = await request.json();
+ const {newRow, oldRow} = await request.json();
try {
conn = await getConn();
await conn.beginTransaction();
if (!['alltaxonomiesview', 'stemdimensionsview', 'stemtaxonomiesview', 'measurementssummaryview'].includes(params.dataType)) {
const mapper = MapperFactory.getMapper(params.dataType);
const newRowData = mapper.demapData([newRow])[0];
- const { [demappedGridID]: gridIDKey, ...remainingProperties } = newRowData;
- const updateQuery = format(`UPDATE ?? SET ? WHERE ?? = ?`, [`${schema}.${params.dataType}`, remainingProperties, demappedGridID, gridIDKey]);
+ const {[demappedGridID]: gridIDKey, ...remainingProperties} = newRowData;
+ const updateQuery = format(`UPDATE ??
+ SET ?
+ WHERE ?? = ?`, [`${schema}.${params.dataType}`, remainingProperties, demappedGridID, gridIDKey]);
await runQuery(conn, updateQuery);
await conn.commit();
} else {
@@ -292,7 +301,7 @@ export async function PATCH(request: NextRequest, { params }: { params: { dataTy
}
await conn.commit();
}
- return NextResponse.json({ message: "Update successful" }, { status: HTTPResponses.OK });
+ return NextResponse.json({message: "Update successful"}, {status: HTTPResponses.OK});
} catch (error: any) {
return handleError(error, conn, newRow);
} finally {
@@ -302,21 +311,21 @@ export async function PATCH(request: NextRequest, { params }: { params: { dataTy
// Define mappings for views to base tables and primary keys
const viewToTableMappings: Record = {
- 'alltaxonomiesview': { table: 'species', primaryKey: 'SpeciesID' },
- 'stemdimensionsview': { table: 'stems', primaryKey: 'StemID' },
- 'stemtaxonomiesview': { table: 'stems', primaryKey: 'StemID' },
- 'measurementssummaryview': { table: 'coremeasurements', primaryKey: 'CoreMeasurementID' },
+ 'alltaxonomiesview': {table: 'species', primaryKey: 'SpeciesID'},
+ 'stemdimensionsview': {table: 'stems', primaryKey: 'StemID'},
+ 'stemtaxonomiesview': {table: 'stems', primaryKey: 'StemID'},
+ 'measurementssummaryview': {table: 'coremeasurements', primaryKey: 'CoreMeasurementID'},
};
// slugs: schema, gridID
// body: full data row, only need first item from it this time though
-export async function DELETE(request: NextRequest, { params }: { params: { dataType: string, slugs?: string[] } }) {
+export async function DELETE(request: NextRequest, {params}: { params: { dataType: string, slugs?: string[] } }) {
if (!params.slugs) throw new Error("slugs not provided");
const [schema, gridID] = params.slugs;
if (!schema || !gridID) throw new Error("no schema or gridID provided");
let conn: PoolConnection | null = null;
const demappedGridID = gridID.charAt(0).toUpperCase() + gridID.substring(1);
- const { newRow } = await request.json();
+ const {newRow} = await request.json();
try {
conn = await getConn();
await conn.beginTransaction();
@@ -328,27 +337,30 @@ export async function DELETE(request: NextRequest, { params }: { params: { dataT
const viewConfig = viewToTableMappings[params.dataType];
if (!viewConfig) throw new Error(`No table mapping found for view ${params.dataType}`);
- const { [viewConfig.primaryKey]: primaryKeyValue } = deleteRowData;
+ const {[viewConfig.primaryKey]: primaryKeyValue} = deleteRowData;
if (!primaryKeyValue) throw new Error(`Primary key value missing for ${viewConfig.primaryKey} in view ${params.dataType}`);
const deleteQuery = format(`DELETE FROM ?? WHERE ?? = ?`, [`${schema}.${viewConfig.table}`, viewConfig.primaryKey, primaryKeyValue]);
await runQuery(conn, deleteQuery);
await conn.commit();
- return NextResponse.json({ message: "Delete successful" }, { status: HTTPResponses.OK });
+ return NextResponse.json({message: "Delete successful"}, {status: HTTPResponses.OK});
}
// Handle deletion for tables
const mapper = MapperFactory.getMapper(params.dataType);
const deleteRowData = mapper.demapData([newRow])[0];
- const { [demappedGridID]: gridIDKey, ...remainingProperties } = deleteRowData;
+ const {[demappedGridID]: gridIDKey, ...remainingProperties} = deleteRowData;
const deleteQuery = format(`DELETE FROM ?? WHERE ?? = ?`, [`${schema}.${params.dataType}`, demappedGridID, gridIDKey]);
await runQuery(conn, deleteQuery);
await conn.commit();
- return NextResponse.json({ message: "Delete successful" }, { status: HTTPResponses.OK });
+ return NextResponse.json({message: "Delete successful"}, {status: HTTPResponses.OK});
} catch (error: any) {
if (error.code === 'ER_ROW_IS_REFERENCED_2') {
const referencingTableMatch = error.message.match(/CONSTRAINT `(.*?)` FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)`/);
const referencingTable = referencingTableMatch ? referencingTableMatch[3] : 'unknown';
- return NextResponse.json({ message: "Foreign key conflict detected", referencingTable }, { status: HTTPResponses.FOREIGN_KEY_CONFLICT });
+ return NextResponse.json({
+ message: "Foreign key conflict detected",
+ referencingTable
+ }, {status: HTTPResponses.FOREIGN_KEY_CONFLICT});
}
return handleError(error, conn, newRow);
} finally {
diff --git a/frontend/components/client/datagridcolumns.tsx b/frontend/components/client/datagridcolumns.tsx
index 9061f03e..21833cde 100644
--- a/frontend/components/client/datagridcolumns.tsx
+++ b/frontend/components/client/datagridcolumns.tsx
@@ -101,6 +101,7 @@ export const msvGridColumns: GridColDef[] = [
{
field: 'measuredDBH', headerName: 'DBH', headerClassName: 'header', flex: 0.8, align: 'left', editable: true,
valueFormatter: (params: any) => {
+ if (!params || !params.value) return 0;
const value = Number(params.value);
return value.toFixed(2); // limit trailing decimals to 2 places
}
@@ -109,6 +110,7 @@ export const msvGridColumns: GridColDef[] = [
{
field: 'measuredHOM', headerName: 'HOM', headerClassName: 'header', flex: 0.5, align: 'left', editable: true,
valueFormatter: (params: any) => {
+ if (!params || !params.value) return 0;
const value = Number(params.value);
return value.toFixed(2); // limit trailing decimals to 2 places
}
@@ -152,7 +154,7 @@ export const CoreMeasurementsGridColumns: GridColDef[] = [
{
field: 'measurementDate', headerName: 'MeasurementDate', type: "date", headerClassName: 'header', flex: 1,
valueGetter: (params: any) => {
- if (!params.value) return null;
+ if (!params || !params.value) return null;
return new Date(params.value);
}, editable: true
},
diff --git a/frontend/components/datagrids/applications/viewfulltableviewdatagrid.tsx b/frontend/components/datagrids/applications/viewfulltableviewdatagrid.tsx
index e6654334..f106536e 100644
--- a/frontend/components/datagrids/applications/viewfulltableviewdatagrid.tsx
+++ b/frontend/components/datagrids/applications/viewfulltableviewdatagrid.tsx
@@ -2,7 +2,7 @@
"use client";
import { useOrgCensusContext } from "@/app/contexts/userselectionprovider";
-import { initialViewFullTableViewRDS } from "@/config/sqlrdsdefinitions/views/viewfulltablerds";
+import { initialViewFullTableViewRDS } from "@/config/sqlrdsdefinitions/views/viewfulltableviewrds";
import { Box, Typography } from "@mui/joy";
import { AlertProps } from "@mui/material";
import { GridRowsProp } from "@mui/x-data-grid";
@@ -42,7 +42,7 @@ export default function ViewFullTableViewDataGrid() {
return (
<>
-
+
{
- fetchValidationErrors()
- .catch(console.error)
- .then(() => setRefresh(false));
- }, [refresh]);
-
useEffect(() => {
if (errorRowCount > 0) {
setSnackbar({
@@ -463,6 +457,7 @@ export default function MeasurementSummaryGrid(props: Readonly {
await fetchPaginatedData(paginationModel.page);
+ await fetchValidationErrors();
};
const handleError = (error: any, message: string) => {
diff --git a/frontend/components/sidebar.tsx b/frontend/components/sidebar.tsx
index b1d43f05..a5de1441 100644
--- a/frontend/components/sidebar.tsx
+++ b/frontend/components/sidebar.tsx
@@ -758,7 +758,7 @@ export default function Sidebar(props: SidebarProps) {
{site !== undefined && plot !== undefined && census !== undefined ? (
- {
+ {
if (!isLinkDisabled) {
router.push(item.href);
}
@@ -821,12 +821,9 @@ export default function Sidebar(props: SidebarProps) {
{
+ disabled={isLinkDisabled} onClick={() => {
if (!isLinkDisabled) {
router.push(item.href + link.href);
- if (setToggle) {
- setToggle(false); // Close the menu
- }
}
}}>
({
id: index + indexOffset,
coreMeasurementID: item.CoreMeasurementID != null ? Number(item.CoreMeasurementID) : undefined,
+ censusID: item.CensusID !== null ? Number(item.CoreMeasurementID) : undefined,
stemID: item.StemID != null ? Number(item.StemID) : undefined,
isValidated: item.IsValidated != null ? bitToBoolean(item.IsValidated) : undefined,
measurementDate: parseDate(item.MeasurementDate),
@@ -49,6 +52,7 @@ export class CoreMeasurementsMapper implements IDataMapper ({
CoreMeasurementID: item.coreMeasurementID != undefined ? Number(item.coreMeasurementID) : null,
+ CensusID: item.censusID !== undefined ? Number(item.coreMeasurementID) : null,
StemID: item.stemID != undefined ? Number(item.stemID) : null,
IsValidated: item.isValidated != undefined ? booleanToBit(item.isValidated) : null,
MeasurementDate: parseDate(item.measurementDate),
diff --git a/frontend/config/sqlrdsdefinitions/views/viewfulltablerds.ts b/frontend/config/sqlrdsdefinitions/views/viewfulltableviewrds.ts
similarity index 77%
rename from frontend/config/sqlrdsdefinitions/views/viewfulltablerds.ts
rename to frontend/config/sqlrdsdefinitions/views/viewfulltableviewrds.ts
index 4712b3f8..4a374d2f 100644
--- a/frontend/config/sqlrdsdefinitions/views/viewfulltablerds.ts
+++ b/frontend/config/sqlrdsdefinitions/views/viewfulltableviewrds.ts
@@ -1,15 +1,24 @@
// viewfulltableview custom data type
-import { ColumnStates, Common, Unique } from "@/config/macros";
-import { MeasurementsSummaryMapper, MeasurementsSummaryRDS, MeasurementsSummaryResult } from "./measurementssummaryviewrds";
-import { StemTaxonomiesMapper, StemTaxonomiesViewRDS, StemTaxonomiesViewResult } from "./stemtaxonomiesviewrds";
-import { IDataMapper } from "@/config/datamapper";
+import {ColumnStates, Common, Unique} from "@/config/macros";
+import {
+ MeasurementsSummaryMapper,
+ MeasurementsSummaryRDS,
+ MeasurementsSummaryResult
+} from "./measurementssummaryviewrds";
+import {StemTaxonomiesMapper, StemTaxonomiesViewRDS, StemTaxonomiesViewResult} from "./stemtaxonomiesviewrds";
+import {IDataMapper} from "@/config/datamapper";
-export type ViewFullTableViewRDS = Common & Unique;
-export type ViewFullTableViewResult = Common & Unique;
+export type ViewFullTableViewRDS =
+ Common
+ & Unique;
+export type ViewFullTableViewResult =
+ Common
+ & Unique;
export class ViewFullTableMapper implements IDataMapper {
private measurementsSummaryMapper = new MeasurementsSummaryMapper();
private stemTaxonomiesMapper = new StemTaxonomiesMapper();
+
demapData(results: ViewFullTableViewRDS[]): ViewFullTableViewResult[] {
const measurementsResults = this.measurementsSummaryMapper.demapData(results as MeasurementsSummaryRDS[]);
const stemTaxonomiesResults = this.stemTaxonomiesMapper.demapData(results as StemTaxonomiesViewRDS[]);
@@ -90,5 +99,6 @@ export function getAllViewFullTableViewsHCs(): ColumnStates {
personnelID: false,
familyID: false,
genusID: false,
+ subquadratName: false,
};
-};
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/frontend/sqlscripting/migration_no_mapping.sql b/frontend/sqlscripting/migration_no_mapping.sql
index 7d98e175..0ac40888 100644
--- a/frontend/sqlscripting/migration_no_mapping.sql
+++ b/frontend/sqlscripting/migration_no_mapping.sql
@@ -1,9 +1,49 @@
SET foreign_key_checks = 0;
--- stable_sinharaja: old ctfsweb schema
+-- stable_mpala: old ctfsweb schema
-- forestgeo_scbi: new schema.
-- make sure you replace this for each new schema you pull/push from/to.
+truncate attributes;
+truncate census;
+truncate cmattributes;
+truncate cmverrors;
+truncate coremeasurements;
+truncate family;
+truncate genus;
+truncate personnel;
+truncate plots;
+truncate quadratpersonnel;
+truncate quadrats;
+truncate reference;
+truncate roles;
+truncate species;
+truncate specieslimits;
+truncate specimens;
+truncate stems;
+truncate subquadrats;
+truncate unifiedchangelog;
+truncate validationchangelog;
+
+DROP VIEW IF EXISTS `alltaxonomiesview`;
+DROP VIEW IF EXISTS `measurementssummaryview`;
+DROP VIEW IF EXISTS `stemtaxonomiesview`;
+DROP VIEW IF EXISTS `viewfulltableview`;
+
+DROP PROCEDURE IF EXISTS `UpdateValidationStatus`;
+DROP PROCEDURE IF EXISTS `ValidateDBHGrowthExceedsMax`;
+DROP PROCEDURE IF EXISTS `ValidateDBHShrinkageExceedsMax`;
+DROP PROCEDURE IF EXISTS `ValidateFindAllInvalidSpeciesCodes`;
+DROP PROCEDURE IF EXISTS `ValidateFindDuplicatedQuadratsByName`;
+DROP PROCEDURE IF EXISTS `ValidateFindDuplicateStemTreeTagCombinationsPerCensus`;
+DROP PROCEDURE IF EXISTS `ValidateFindMeasurementsOutsideCensusDateBoundsGroupByQuadrat`;
+DROP PROCEDURE IF EXISTS `ValidateFindStemsInTreeWithDifferentSpecies`;
+DROP PROCEDURE IF EXISTS `ValidateFindStemsOutsidePlots`;
+DROP PROCEDURE IF EXISTS `ValidateFindTreeStemsInDifferentQuadrats`;
+DROP PROCEDURE IF EXISTS `ValidateHOMUpperAndLowerBounds`;
+DROP PROCEDURE IF EXISTS `ValidateScreenMeasuredDiameterMinMax`;
+DROP PROCEDURE IF EXISTS `ValidateScreenStemsWithMeasurementsButDeadAttributes`;
+
# attributes
DROP TRIGGER IF EXISTS after_insert_attributes;
DROP TRIGGER IF EXISTS after_update_attributes;
@@ -122,9 +162,9 @@ SELECT s.PlotID,
IF(s.GUOM IN ('km', 'hm', 'dam', 'm', 'dm', 'cm', 'mm'), s.GUOM, 'm'),
s.ShapeOfSite,
LEFT(s.DescriptionOfSite, 65535)
-FROM stable_sinharaja.Site s
- LEFT JOIN stable_sinharaja.Country c ON s.CountryID = c.CountryID
- LEFT JOIN stable_sinharaja.Coordinates co ON s.PlotID = co.PlotID
+FROM stable_mpala.Site s
+ LEFT JOIN stable_mpala.Country c ON s.CountryID = c.CountryID
+ LEFT JOIN stable_mpala.Coordinates co ON s.PlotID = co.PlotID
GROUP BY s.PlotID, s.PlotName, s.LocationName, c.CountryName, s.QDimX, s.QDimY, s.PUOM, s.Area, s.GUOM, co.GX, co.GY,
co.GZ, s.ShapeOfSite, s.DescriptionOfSite
ON DUPLICATE KEY UPDATE PlotName = IF(VALUES(PlotName) != '', VALUES(PlotName), plots.PlotName),
@@ -150,7 +190,7 @@ SELECT r.ReferenceID,
r.FullReference,
IF(CAST(r.DateofPublication AS CHAR) = '0000-00-00', NULL, r.DateofPublication) AS DateOfPublication,
NULL
-FROM stable_sinharaja.reference r
+FROM stable_mpala.reference r
ON DUPLICATE KEY UPDATE PublicationTitle = IF(VALUES(PublicationTitle) != '', VALUES(PublicationTitle),
reference.PublicationTitle),
FullReference = IF(VALUES(FullReference) != '', VALUES(FullReference),
@@ -160,14 +200,14 @@ ON DUPLICATE KEY UPDATE PublicationTitle = IF(VALUES(PublicationTitle
-- Insert into family with ON DUPLICATE KEY UPDATE
INSERT INTO family (FamilyID, Family, ReferenceID)
SELECT f.FamilyID, f.Family, f.ReferenceID
-FROM stable_sinharaja.family f
+FROM stable_mpala.family f
ON DUPLICATE KEY UPDATE Family = IF(VALUES(Family) != '', VALUES(Family), family.Family),
ReferenceID = VALUES(ReferenceID);
-- Insert into genus with ON DUPLICATE KEY UPDATE
INSERT INTO genus (GenusID, FamilyID, Genus, ReferenceID, GenusAuthority)
SELECT g.GenusID, g.FamilyID, g.Genus, g.ReferenceID, g.Authority
-FROM stable_sinharaja.genus g
+FROM stable_mpala.genus g
ON DUPLICATE KEY UPDATE FamilyID = VALUES(FamilyID),
Genus = IF(VALUES(Genus) != '', VALUES(Genus), genus.Genus),
ReferenceID = VALUES(ReferenceID),
@@ -188,9 +228,9 @@ SELECT sp.SpeciesID,
LEFT(sp.Description, 65535),
NULL,
sp.ReferenceID
-FROM stable_sinharaja.species sp
- LEFT JOIN stable_sinharaja.subspecies subs ON sp.SpeciesID = subs.SpeciesID
- LEFT JOIN stable_sinharaja.reference ref ON sp.ReferenceID = ref.ReferenceID
+FROM stable_mpala.species sp
+ LEFT JOIN stable_mpala.subspecies subs ON sp.SpeciesID = subs.SpeciesID
+ LEFT JOIN stable_mpala.reference ref ON sp.ReferenceID = ref.ReferenceID
GROUP BY sp.SpeciesID, sp.GenusID, sp.Mnemonic, sp.IDLevel, sp.Authority, sp.FieldFamily, sp.Description, sp.ReferenceID
ON DUPLICATE KEY UPDATE GenusID = VALUES(GenusID),
SpeciesCode = VALUES(SpeciesCode),
@@ -207,40 +247,68 @@ ON DUPLICATE KEY UPDATE GenusID = VALUES(GenusID),
ValidCode = VALUES(ValidCode),
ReferenceID = VALUES(ReferenceID);
-UPDATE stable_sinharaja.census
+UPDATE stable_mpala.census
SET StartDate = NULL
WHERE CAST(StartDate AS CHAR(10)) = '0000-00-00';
-- Insert into census with ON DUPLICATE KEY UPDATE
INSERT INTO census (CensusID, PlotID, StartDate, EndDate, Description, PlotCensusNumber)
-SELECT c.CensusID, c.PlotID, c.StartDate, c.EndDate, LEFT(c.Description, 65535), c.PlotCensusNumber
-FROM stable_sinharaja.census c
-ON DUPLICATE KEY UPDATE PlotID = VALUES(PlotID),
- StartDate = VALUES(StartDate),
- EndDate = VALUES(EndDate),
- Description = IF(VALUES(Description) != '', VALUES(Description), census.Description),
- PlotCensusNumber = VALUES(PlotCensusNumber);
+SELECT
+ c.CensusID,
+ c.PlotID,
+ COALESCE(MIN(d.ExactDate), c.StartDate) AS StartDate,
+ COALESCE(MAX(d.ExactDate), c.EndDate) AS EndDate,
+ LEFT(c.Description, 65535),
+ c.PlotCensusNumber
+FROM
+ stable_mpala.census c
+LEFT JOIN
+ stable_mpala.dbh d ON c.CensusID = d.CensusID
+GROUP BY
+ c.CensusID
+ON DUPLICATE KEY UPDATE
+ PlotID = VALUES(PlotID),
+ StartDate = VALUES(StartDate),
+ EndDate = VALUES(EndDate),
+ Description = IF(VALUES(Description) != '', VALUES(Description), census.Description),
+ PlotCensusNumber = VALUES(PlotCensusNumber);
-- Insert into roles table
INSERT INTO roles (RoleID, RoleName, RoleDescription)
SELECT RoleID, Description, NULL
-FROM stable_sinharaja.rolereference
+FROM stable_mpala.rolereference
ON DUPLICATE KEY UPDATE RoleName = VALUES(RoleName),
RoleDescription = VALUES(RoleDescription);
-- Insert into personnel, ensuring each personnel is re-added for each CensusID with new PersonnelID
-INSERT INTO personnel (CensusID, FirstName, LastName, RoleID)
+-- Step 1: Create a temporary table to hold the intermediate results
+CREATE TEMPORARY TABLE tmp_personnel
SELECT
c.CensusID,
p.FirstName,
p.LastName,
pr.RoleID
FROM
- stable_sinharaja.personnel p
+ stable_mpala.personnel p
CROSS JOIN
- stable_sinharaja.census c
+ stable_mpala.census c
JOIN
- stable_sinharaja.personnelrole pr ON p.PersonnelID = pr.PersonnelID;
+ stable_mpala.personnelrole pr ON p.PersonnelID = pr.PersonnelID;
+
+-- Step 2: Insert into personnel from the temporary table, handling duplicates
+INSERT INTO personnel (CensusID, FirstName, LastName, RoleID)
+SELECT
+ CensusID,
+ FirstName,
+ LastName,
+ RoleID
+FROM
+ tmp_personnel
+ON DUPLICATE KEY UPDATE
+ RoleID = VALUES(RoleID);
+
+-- Step 3: Drop the temporary table
+DROP TEMPORARY TABLE tmp_personnel;
-- Insert into quadrats with ON DUPLICATE KEY UPDATE
INSERT INTO quadrats (QuadratID, PlotID, CensusID, QuadratName, StartX, StartY, DimensionX, DimensionY, DimensionUnits,
@@ -258,10 +326,10 @@ SELECT q.QuadratID,
IF(s.QUOM IN ('km2', 'hm2', 'dam2', 'm2', 'dm2', 'cm2', 'mm2'), s.QUOM, 'm2'),
IF(q.IsStandardShape = 'Y', 'standard', 'not standard'),
IF(s.GUOM IN ('km', 'hm', 'dam', 'm', 'dm', 'cm', 'mm'), s.GUOM, 'm')
-FROM stable_sinharaja.quadrat q
- LEFT JOIN stable_sinharaja.censusquadrat cq ON q.QuadratID = cq.QuadratID
- LEFT JOIN stable_sinharaja.Coordinates co ON q.QuadratID = co.QuadratID
- LEFT JOIN stable_sinharaja.Site s ON q.PlotID = s.PlotID
+FROM stable_mpala.quadrat q
+ LEFT JOIN stable_mpala.censusquadrat cq ON q.QuadratID = cq.QuadratID
+ LEFT JOIN stable_mpala.Coordinates co ON q.QuadratID = co.QuadratID
+ LEFT JOIN stable_mpala.Site s ON q.PlotID = s.PlotID
GROUP BY q.QuadratID, q.PlotID, cq.CensusID, q.QuadratName, s.QDimX, s.QDimY, s.QUOM, q.Area, q.IsStandardShape, s.GUOM
ON DUPLICATE KEY UPDATE PlotID = VALUES(PlotID),
CensusID = VALUES(CensusID),
@@ -279,7 +347,7 @@ ON DUPLICATE KEY UPDATE PlotID = VALUES(PlotID),
-- Insert into trees with ON DUPLICATE KEY UPDATE
INSERT INTO trees (TreeID, TreeTag, SpeciesID)
SELECT t.TreeID, t.Tag, t.SpeciesID
-FROM stable_sinharaja.tree t
+FROM stable_mpala.tree t
ON DUPLICATE KEY UPDATE TreeTag = IF(VALUES(TreeTag) != '', VALUES(TreeTag), trees.TreeTag),
SpeciesID = VALUES(SpeciesID);
@@ -296,9 +364,9 @@ SELECT s.StemID,
IF(si.QUOM IN ('km', 'hm', 'dam', 'm', 'dm', 'cm', 'mm'), si.QUOM, 'm') AS CoordinateUnits,
IF(s.Moved = 'Y', 1, 0) AS Moved,
LEFT(s.StemDescription, 65535)
-FROM stable_sinharaja.stem s
- LEFT JOIN stable_sinharaja.quadrat q ON q.QuadratID = s.QuadratID
- LEFT JOIN stable_sinharaja.Site si ON q.PlotID = si.PlotID
+FROM stable_mpala.stem s
+ LEFT JOIN stable_mpala.quadrat q ON q.QuadratID = s.QuadratID
+ LEFT JOIN stable_mpala.Site si ON q.PlotID = si.PlotID
GROUP BY s.StemID, s.TreeID, s.QuadratID, s.StemNumber, s.StemTag, s.Moved, s.StemDescription, si.QUOM
ON DUPLICATE KEY UPDATE TreeID = VALUES(TreeID),
QuadratID = VALUES(QuadratID),
@@ -312,19 +380,20 @@ ON DUPLICATE KEY UPDATE TreeID = VALUES(TreeID),
stems.StemDescription);
-- Insert into coremeasurements with ON DUPLICATE KEY UPDATE
-INSERT INTO coremeasurements (CoreMeasurementID, StemID, IsValidated, MeasurementDate, MeasuredDBH, DBHUnit,
+INSERT INTO coremeasurements (CoreMeasurementID, CensusID, StemID, IsValidated, MeasurementDate, MeasuredDBH, DBHUnit,
MeasuredHOM, HOMUnit, Description, UserDefinedFields)
SELECT dbh.DBHID,
+ dbh.CensusID,
dbh.StemID,
NULL,
dbh.ExactDate,
- dbh.DBH,
+ CAST(dbh.DBH AS DECIMAL(10, 6)),
'cm',
- dbh.HOM,
+ CAST(dbh.HOM AS DECIMAL(10, 6)),
'm',
LEFT(dbh.Comments, 65535),
NULL
-FROM stable_sinharaja.dbh dbh
+FROM stable_mpala.dbh dbh
ON DUPLICATE KEY UPDATE StemID = VALUES(StemID),
IsValidated = VALUES(IsValidated),
MeasurementDate = VALUES(MeasurementDate),
@@ -339,8 +408,8 @@ ON DUPLICATE KEY UPDATE StemID = VALUES(StemID),
-- Insert into quadratpersonnel with ON DUPLICATE KEY UPDATE
INSERT INTO quadratpersonnel (QuadratPersonnelID, QuadratID, PersonnelID, CensusID)
SELECT dc.DataCollectionID, dc.QuadratID, pr.PersonnelID, dc.CensusID
-FROM stable_sinharaja.datacollection dc
- JOIN stable_sinharaja.personnelrole pr ON dc.PersonnelRoleID = pr.PersonnelRoleID
+FROM stable_mpala.datacollection dc
+ JOIN stable_mpala.personnelrole pr ON dc.PersonnelRoleID = pr.PersonnelRoleID
ON DUPLICATE KEY UPDATE QuadratID = VALUES(QuadratID),
PersonnelID = VALUES(PersonnelID),
CensusID = VALUES(CensusID);
@@ -351,7 +420,7 @@ SELECT ta.TSMCode,
LEFT(ta.Description, 65535),
IF(ta.Status IN ('alive', 'alive-not measured', 'dead', 'stem dead', 'broken below', 'omitted', 'missing'),
ta.Status, NULL)
-FROM stable_sinharaja.tsmattributes ta
+FROM stable_mpala.tsmattributes ta
GROUP BY ta.TSMCode, ta.Description, ta.Status
ON DUPLICATE KEY UPDATE Description = IF(VALUES(Description) != '', VALUES(Description), attributes.Description),
Status = VALUES(Status);
@@ -359,8 +428,8 @@ ON DUPLICATE KEY UPDATE Description = IF(VALUES(Description) != '', VALUES(Descr
-- Insert into cmattributes with ON DUPLICATE KEY UPDATE
INSERT INTO cmattributes (CMAID, CoreMeasurementID, Code)
SELECT dbha.DBHAttID, dbha.DBHID, ta.TSMCode
-FROM stable_sinharaja.dbhattributes dbha
- JOIN stable_sinharaja.tsmattributes ta ON dbha.TSMID = ta.TSMID
+FROM stable_mpala.dbhattributes dbha
+ JOIN stable_mpala.tsmattributes ta ON dbha.TSMID = ta.TSMID
ON DUPLICATE KEY UPDATE CoreMeasurementID = VALUES(CoreMeasurementID),
Code = VALUES(Code);
@@ -377,9 +446,9 @@ SELECT sp.SpecimenID,
sp.CollectionDate,
sp.DeterminedBy,
LEFT(sp.Description, 65535)
-FROM stable_sinharaja.specimen sp
- LEFT JOIN stable_sinharaja.stem st ON st.TreeID = sp.TreeID
- LEFT JOIN stable_sinharaja.personnel pr ON sp.Collector = CONCAT(pr.FirstName, ' ', pr.LastName)
+FROM stable_mpala.specimen sp
+ LEFT JOIN stable_mpala.stem st ON st.TreeID = sp.TreeID
+ LEFT JOIN stable_mpala.personnel pr ON sp.Collector = CONCAT(pr.FirstName, ' ', pr.LastName)
ON DUPLICATE KEY UPDATE StemID = VALUES(StemID),
PersonnelID = VALUES(PersonnelID),
SpecimenNumber = VALUES(SpecimenNumber),
@@ -1532,7 +1601,6 @@ BEGIN
SET new_json = JSON_OBJECT(
'SpeciesID', NEW.SpeciesID,
'GenusID', NEW.GenusID,
- 'CensusID', NEW.CensusID,
'SpeciesCode', NEW.SpeciesCode,
'SpeciesName', NEW.SpeciesName,
'SubspeciesName', NEW.SubspeciesName,
@@ -1573,7 +1641,6 @@ BEGIN
SET old_json = JSON_OBJECT(
'SpeciesID', OLD.SpeciesID,
'GenusID', OLD.GenusID,
- 'CensusID', OLD.CensusID,
'SpeciesCode', OLD.SpeciesCode,
'SpeciesName', OLD.SpeciesName,
'SubspeciesName', OLD.SubspeciesName,
@@ -1590,7 +1657,6 @@ BEGIN
SET new_json = JSON_OBJECT(
'SpeciesID', NEW.SpeciesID,
'GenusID', NEW.GenusID,
- 'CensusID', NEW.CensusID,
'SpeciesCode', NEW.SpeciesCode,
'SpeciesName', NEW.SpeciesName,
'SubspeciesName', NEW.SubspeciesName,
@@ -1631,7 +1697,6 @@ BEGIN
SET old_json = JSON_OBJECT(
'SpeciesID', OLD.SpeciesID,
'GenusID', OLD.GenusID,
- 'CensusID', OLD.CensusID,
'SpeciesCode', OLD.SpeciesCode,
'SpeciesName', OLD.SpeciesName,
'SubspeciesName', OLD.SubspeciesName,
@@ -2712,3 +2777,1712 @@ BEGIN
END //
DELIMITER ;
+
+CREATE VIEW alltaxonomiesview AS
+SELECT
+ s.SpeciesID AS SpeciesID,
+ f.FamilyID AS FamilyID,
+ g.GenusID AS GenusID,
+ r.ReferenceID AS ReferenceID,
+ s.SpeciesCode AS SpeciesCode,
+ f.Family AS Family,
+ g.Genus AS Genus,
+ g.GenusAuthority AS GenusAuthority,
+ s.SpeciesName AS SpeciesName,
+ s.SubspeciesName AS SubSpeciesName,
+ s.IDLevel AS SpeciesIDLevel,
+ s.SpeciesAuthority AS SpeciesAuthority,
+ s.SubspeciesAuthority AS SubspeciesAuthority,
+ s.ValidCode AS ValidCode,
+ s.FieldFamily AS FieldFamily,
+ s.Description AS SpeciesDescription,
+ r.PublicationTitle AS PublicationTitle,
+ r.FullReference AS FullReference,
+ r.DateOfPublication AS DateOfPublication,
+ r.Citation AS Citation
+FROM
+ family f
+ JOIN genus g ON f.FamilyID = g.FamilyID
+ JOIN species s ON g.GenusID = s.GenusID
+ LEFT JOIN reference r ON s.ReferenceID = r.ReferenceID;
+
+
+CREATE VIEW measurementssummaryview AS
+SELECT
+ cm.CoreMeasurementID AS CoreMeasurementID,
+ p.PlotID AS PlotID,
+ cm.CensusID AS CensusID,
+ q.QuadratID AS QuadratID,
+ s.SpeciesID AS SpeciesID,
+ t.TreeID AS TreeID,
+ st.StemID AS StemID,
+ qp.PersonnelID AS PersonnelID,
+ p.PlotName AS PlotName,
+ q.QuadratName AS QuadratName,
+ s.SpeciesCode AS SpeciesCode,
+ t.TreeTag AS TreeTag,
+ st.StemTag AS StemTag,
+ st.LocalX AS StemLocalX,
+ st.LocalY AS StemLocalY,
+ st.CoordinateUnits AS StemUnits,
+ COALESCE(CONCAT(pe.FirstName, ' ', pe.LastName), 'Unknown') AS PersonnelName,
+ cm.MeasurementDate AS MeasurementDate,
+ cm.MeasuredDBH AS MeasuredDBH,
+ cm.DBHUnit AS DBHUnits,
+ cm.MeasuredHOM AS MeasuredHOM,
+ cm.HOMUnit AS HOMUnits,
+ cm.IsValidated AS IsValidated,
+ cm.Description AS Description,
+ (SELECT GROUP_CONCAT(ca.Code SEPARATOR '; ')
+ FROM cmattributes ca
+ WHERE ca.CoreMeasurementID = cm.CoreMeasurementID) AS Attributes
+FROM
+ coremeasurements cm
+ LEFT JOIN stems st ON cm.StemID = st.StemID
+ LEFT JOIN trees t ON st.TreeID = t.TreeID
+ LEFT JOIN species s ON t.SpeciesID = s.SpeciesID
+ LEFT JOIN genus g ON s.GenusID = g.GenusID
+ LEFT JOIN family f ON g.FamilyID = f.FamilyID
+ LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
+ LEFT JOIN plots p ON q.PlotID = p.PlotID
+ LEFT JOIN census c ON cm.CensusID = c.CensusID
+ LEFT JOIN quadratpersonnel qp ON q.QuadratID = qp.QuadratID
+ LEFT JOIN personnel pe ON qp.PersonnelID = pe.PersonnelID
+GROUP BY
+ cm.CoreMeasurementID, p.PlotID, cm.CensusID, q.QuadratID, s.SpeciesID, t.TreeID, st.StemID, qp.PersonnelID,
+ p.PlotName, q.QuadratName, s.SpeciesCode, t.TreeTag, st.StemTag, st.LocalX, st.LocalY, st.CoordinateUnits,
+ pe.FirstName, pe.LastName, cm.MeasurementDate, cm.MeasuredDBH, cm.DBHUnit, cm.MeasuredHOM, cm.HOMUnit,
+ cm.IsValidated, cm.Description;
+
+
+CREATE VIEW stemtaxonomiesview AS
+SELECT
+ s.StemID AS StemID,
+ t.TreeID AS TreeID,
+ q.QuadratID AS QuadratID,
+ c.CensusID AS CensusID,
+ p.PlotID AS PlotID,
+ f.FamilyID AS FamilyID,
+ g.GenusID AS GenusID,
+ sp.SpeciesID AS SpeciesID,
+ s.StemTag AS StemTag,
+ t.TreeTag AS TreeTag,
+ sp.SpeciesCode AS SpeciesCode,
+ f.Family AS Family,
+ g.Genus AS Genus,
+ sp.SpeciesName AS SpeciesName,
+ sp.SubspeciesName AS SubspeciesName,
+ sp.ValidCode AS ValidCode,
+ g.GenusAuthority AS GenusAuthority,
+ sp.SpeciesAuthority AS SpeciesAuthority,
+ sp.SubspeciesAuthority AS SubspeciesAuthority,
+ sp.IDLevel AS SpeciesIDLevel,
+ sp.FieldFamily AS SpeciesFieldFamily
+FROM
+ stems s
+ JOIN trees t ON s.TreeID = t.TreeID
+ JOIN quadrats q ON s.QuadratID = q.QuadratID
+ JOIN census c ON q.CensusID = c.CensusID
+ JOIN plots p ON c.PlotID = p.PlotID
+ JOIN species sp ON t.SpeciesID = sp.SpeciesID
+ JOIN genus g ON sp.GenusID = g.GenusID
+ LEFT JOIN family f ON g.FamilyID = f.FamilyID;
+
+
+CREATE VIEW viewfulltableview AS
+SELECT
+ cm.CoreMeasurementID AS CoreMeasurementID,
+ cm.MeasurementDate AS MeasurementDate,
+ cm.MeasuredDBH AS MeasuredDBH,
+ cm.DBHUnit AS DBHUnits,
+ cm.MeasuredHOM AS MeasuredHOM,
+ cm.HOMUnit AS HOMUnits,
+ cm.Description AS Description,
+ cm.IsValidated AS IsValidated,
+ p.PlotID AS PlotID,
+ p.PlotName AS PlotName,
+ p.LocationName AS LocationName,
+ p.CountryName AS CountryName,
+ p.DimensionX AS DimensionX,
+ p.DimensionY AS DimensionY,
+ p.Area AS PlotArea,
+ p.GlobalX AS GlobalX,
+ p.GlobalY AS GlobalY,
+ p.GlobalZ AS GlobalZ,
+ p.DimensionUnits AS PlotUnit,
+ p.PlotShape AS PlotShape,
+ p.PlotDescription AS PlotDescription,
+ c.CensusID AS CensusID,
+ c.StartDate AS CensusStartDate,
+ c.EndDate AS CensusEndDate,
+ c.Description AS CensusDescription,
+ c.PlotCensusNumber AS PlotCensusNumber,
+ q.QuadratID AS QuadratID,
+ q.QuadratName AS QuadratName,
+ q.DimensionX AS QuadratDimensionX,
+ q.DimensionY AS QuadratDimensionY,
+ q.Area AS QuadratArea,
+ q.QuadratShape AS QuadratShape,
+ q.DimensionUnits AS QuadratUnit,
+ sq.SubquadratID AS SubquadratID,
+ sq.SubquadratName AS SubquadratName,
+ sq.DimensionX AS SubquadratDimensionX,
+ sq.DimensionY AS SubquadratDimensionY,
+ sq.QX AS QX,
+ sq.QY AS QY,
+ sq.CoordinateUnits AS SubquadratUnit,
+ t.TreeID AS TreeID,
+ t.TreeTag AS TreeTag,
+ s.StemID AS StemID,
+ s.StemTag AS StemTag,
+ s.LocalX AS StemLocalX,
+ s.LocalY AS StemLocalY,
+ s.CoordinateUnits AS StemUnits,
+ per.PersonnelID AS PersonnelID,
+ per.FirstName AS FirstName,
+ per.LastName AS LastName,
+ r.RoleName AS PersonnelRoles,
+ sp.SpeciesID AS SpeciesID,
+ sp.SpeciesCode AS SpeciesCode,
+ sp.SpeciesName AS SpeciesName,
+ sp.SubspeciesName AS SubspeciesName,
+ sp.SubspeciesAuthority AS SubspeciesAuthority,
+ sp.IDLevel AS SpeciesIDLevel,
+ g.GenusID AS GenusID,
+ g.Genus AS Genus,
+ g.GenusAuthority AS GenusAuthority,
+ fam.FamilyID AS FamilyID,
+ fam.Family AS Family,
+ attr.Code AS AttributeCode,
+ attr.Description AS AttributeDescription,
+ attr.Status AS AttributeStatus
+FROM
+ coremeasurements cm
+ LEFT JOIN stems s ON cm.StemID = s.StemID
+ LEFT JOIN trees t ON s.TreeID = t.TreeID
+ LEFT JOIN species sp ON t.SpeciesID = sp.SpeciesID
+ LEFT JOIN genus g ON sp.GenusID = g.GenusID
+ LEFT JOIN family fam ON g.FamilyID = fam.FamilyID
+ LEFT JOIN specieslimits sl ON sp.SpeciesCode = sl.SpeciesCode
+ LEFT JOIN quadrats q ON s.QuadratID = q.QuadratID
+ LEFT JOIN quadratpersonnel qp ON q.QuadratID = qp.QuadratID
+ LEFT JOIN personnel per ON qp.PersonnelID = per.PersonnelID
+ LEFT JOIN plots p ON q.PlotID = p.PlotID
+ LEFT JOIN subquadrats sq ON q.QuadratID = sq.QuadratID
+ LEFT JOIN census c ON cm.CensusID = c.CensusID
+ LEFT JOIN roles r ON per.RoleID = r.RoleID
+ LEFT JOIN attributes attr ON cm.CoreMeasurementID = attr.Code
+ LEFT JOIN cmattributes cma ON cm.CoreMeasurementID = cma.CoreMeasurementID AND attr.Code = cma.Code;
+
+create
+ definer = azureroot@`%` procedure UpdateValidationStatus(IN p_PlotID int, IN p_CensusID int, OUT RowsValidated int)
+BEGIN
+ -- Create a temporary table to store CoreMeasurementIDs
+ CREATE TEMPORARY TABLE IF NOT EXISTS TempUpdatedIDs (CoreMeasurementID INT);
+
+ -- Clear the temporary table
+ TRUNCATE TABLE TempUpdatedIDs;
+
+ -- Insert the CoreMeasurementIDs of the rows to be updated into the temporary table
+ INSERT INTO TempUpdatedIDs (CoreMeasurementID)
+ SELECT cm.CoreMeasurementID
+ FROM coremeasurements cm
+ LEFT JOIN cmverrors cme ON cm.CoreMeasurementID = cme.CoreMeasurementID
+ LEFT JOIN stems s on cm.StemID = s.StemID
+ LEFT JOIN quadrats q on s.QuadratID = q.QuadratID
+ WHERE cm.IsValidated = FALSE
+ AND (q.PlotID = p_PlotID OR p_PlotID IS NULL)
+ AND (q.CensusID = p_CensusID OR p_CensusID IS NULL)
+ AND cme.CoreMeasurementID IS NULL;
+
+ -- Update the IsValidated column
+ UPDATE coremeasurements cm
+ INNER JOIN TempUpdatedIDs tmp ON cm.CoreMeasurementID = tmp.CoreMeasurementID
+ SET cm.IsValidated = TRUE;
+
+ -- Get the count of rows that have been updated
+ SET RowsValidated = ROW_COUNT();
+
+ -- Select the CoreMeasurementIDs from the temporary table
+ SELECT CoreMeasurementID FROM TempUpdatedIDs;
+
+ -- Optionally, drop the temporary table
+ DROP TEMPORARY TABLE IF EXISTS TempUpdatedIDs;
+END;
+
+create
+ definer = azureroot@`%` procedure ValidateDBHGrowthExceedsMax(IN p_CensusID int, IN p_PlotID int)
+BEGIN
+ DECLARE vCoreMeasurementID INT;
+ DECLARE vPrevDBH DECIMAL(10, 2);
+ DECLARE vCurrDBH DECIMAL(10, 2);
+ DECLARE validationResult BIT;
+ DECLARE errorMessage VARCHAR(255);
+ DECLARE validationCriteria TEXT;
+ DECLARE measuredValue VARCHAR(255);
+ DECLARE expectedValueRange VARCHAR(255);
+ DECLARE additionalDetails TEXT;
+ DECLARE insertCount INT DEFAULT 0;
+ DECLARE expectedCount INT;
+ DECLARE successMessage VARCHAR(255);
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE veID INT;
+ DECLARE cur CURSOR FOR
+ SELECT cm2.CoreMeasurementID, cm1.MeasuredDBH, cm2.MeasuredDBH
+ FROM coremeasurements cm1
+ JOIN coremeasurements cm2
+ ON cm1.StemID = cm2.StemID
+ AND YEAR(cm2.MeasurementDate) = YEAR(cm1.MeasurementDate) + 1
+ LEFT JOIN stems st2 ON cm2.StemID = st2.StemID
+ LEFT JOIN quadrats q ON st2.QuadratID = q.QuadratID
+ LEFT JOIN cmattributes cma
+ ON cm1.CoreMeasurementID = cma.CoreMeasurementID
+ LEFT JOIN attributes a
+ ON cma.Code = a.Code
+ WHERE (a.Status NOT IN ('dead', 'stem dead', 'broken below', 'missing', 'omitted') OR a.Status IS NULL)
+ AND cm1.MeasuredDBH IS NOT NULL
+ AND cm2.MeasuredDBH IS NOT NULL
+ AND (cm2.MeasuredDBH - cm1.MeasuredDBH > 65)
+ AND cm1.IsValidated IS TRUE
+ AND cm2.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
+ (
+ CoreMeasurementID INT
+ );
+
+ IF p_CensusID IS NULL THEN
+ SET p_CensusID = -1;
+ END IF;
+ IF p_PlotID IS NULL THEN
+ SET p_PlotID = -1;
+ END IF;
+
+ SELECT COUNT(*)
+ INTO expectedCount
+ FROM coremeasurements cm1
+ JOIN coremeasurements cm2
+ ON cm1.StemID = cm2.StemID
+ AND YEAR(cm2.MeasurementDate) = YEAR(cm1.MeasurementDate) + 1
+ LEFT JOIN stems st2 ON cm2.StemID = st2.StemID
+ LEFT JOIN quadrats q ON st2.QuadratID = q.QuadratID
+ LEFT JOIN cmattributes cma
+ ON cm1.CoreMeasurementID = cma.CoreMeasurementID
+ LEFT JOIN attributes a
+ ON cma.Code = a.Code
+ WHERE (a.Status NOT IN ('dead', 'stem dead', 'broken below', 'missing', 'omitted') OR a.Status IS NULL)
+ AND cm1.MeasuredDBH IS NOT NULL
+ AND cm2.MeasuredDBH IS NOT NULL
+ AND (cm2.MeasuredDBH - cm1.MeasuredDBH > 65)
+ AND cm1.IsValidated IS TRUE
+ AND cm2.IsValidated IS FALSE
+ AND (p_CensusID = -1 OR q.CensusID = p_CensusID)
+ AND (p_PlotID = -1 OR q.PlotID = p_PlotID);
+
+ -- Fetch the ValidationErrorID for this stored procedure
+ SELECT ValidationID
+ INTO veID
+ FROM catalog.validationprocedures
+ WHERE ProcedureName = 'ValidateDBHGrowthExceedsMax';
+
+ OPEN cur;
+ loop1:
+ LOOP
+ FETCH cur INTO vCoreMeasurementID, vPrevDBH, vCurrDBH;
+ IF done THEN
+ LEAVE loop1;
+ END IF;
+
+ SET validationCriteria = 'Annual DBH Growth';
+ SET measuredValue = CONCAT('Previous DBH: ', vPrevDBH, ', Current DBH: ', vCurrDBH);
+ SET expectedValueRange = 'Growth <= 65';
+ SET additionalDetails = 'Checked for excessive DBH growth over a year';
+
+ IF vCurrDBH - vPrevDBH > 65 THEN
+ SET validationResult = 0;
+ SET errorMessage = 'Growth exceeds max threshold.';
+ IF NOT EXISTS (SELECT 1
+ FROM cmverrors
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND ValidationErrorID = veID) THEN
+ INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
+ VALUES (vCoreMeasurementID, veID);
+ END IF;
+ INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
+ SET insertCount = insertCount + 1;
+ ELSE
+ SET validationResult = 1;
+ SET errorMessage = NULL;
+ END IF;
+
+ INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
+ ValidationOutcome, ErrorMessage,
+ ValidationCriteria, MeasuredValue, ExpectedValueRange,
+ AdditionalDetails)
+ VALUES ('ValidateDBHGrowthExceedsMax', NOW(), vCoreMeasurementID,
+ IF(validationResult, 'Passed', 'Failed'), errorMessage,
+ validationCriteria, measuredValue, expectedValueRange,
+ additionalDetails);
+ END LOOP;
+ CLOSE cur;
+
+ SET successMessage =
+ CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
+ SELECT expectedCount AS TotalRows,
+ insertCount AS FailedRows,
+ successMessage AS Message;
+
+ SELECT CoreMeasurementID FROM FailedValidations;
+
+ DROP TEMPORARY TABLE IF EXISTS FailedValidations;
+END;
+
+create
+ definer = azureroot@`%` procedure ValidateDBHShrinkageExceedsMax(IN p_CensusID int, IN p_PlotID int)
+BEGIN
+ DECLARE vCoreMeasurementID INT;
+ DECLARE vPrevDBH DECIMAL(10, 2);
+ DECLARE vCurrDBH DECIMAL(10, 2);
+ DECLARE validationResult BIT;
+ DECLARE errorMessage VARCHAR(255);
+ DECLARE validationCriteria TEXT;
+ DECLARE measuredValue VARCHAR(255);
+ DECLARE expectedValueRange VARCHAR(255);
+ DECLARE additionalDetails TEXT;
+ DECLARE insertCount INT DEFAULT 0;
+ DECLARE expectedCount INT;
+ DECLARE successMessage VARCHAR(255);
+ DECLARE veID INT;
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE cur CURSOR FOR
+ SELECT cm2.CoreMeasurementID, cm1.MeasuredDBH, cm2.MeasuredDBH
+ FROM coremeasurements cm1
+ JOIN coremeasurements cm2
+ ON cm1.StemID = cm2.StemID
+ AND YEAR(cm2.MeasurementDate) = YEAR(cm1.MeasurementDate) + 1
+ LEFT JOIN stems st ON cm2.StemID = st.StemID
+ LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
+ LEFT JOIN cmattributes cma
+ ON cm1.CoreMeasurementID = cma.CoreMeasurementID
+ LEFT JOIN attributes a
+ ON cma.Code = a.Code
+ WHERE (a.Status NOT IN ('dead', 'stem dead', 'broken below', 'missing', 'omitted') OR a.Status IS NULL)
+ AND cm1.MeasuredDBH IS NOT NULL
+ AND cm2.MeasuredDBH IS NOT NULL
+ AND cm1.IsValidated IS TRUE
+ AND cm2.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
+ (
+ CoreMeasurementID INT
+ );
+
+ IF p_CensusID IS NULL THEN
+ SET p_CensusID = -1;
+ END IF;
+ IF p_PlotID IS NULL THEN
+ SET p_PlotID = -1;
+ END IF;
+
+ SELECT COUNT(*)
+ INTO expectedCount
+ FROM coremeasurements cm1
+ JOIN coremeasurements cm2
+ ON cm1.StemID = cm2.StemID
+ AND YEAR(cm2.MeasurementDate) = YEAR(cm1.MeasurementDate) + 1
+ LEFT JOIN stems st ON cm2.StemID = st.StemID
+ LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
+ LEFT JOIN cmattributes cma
+ ON cm1.CoreMeasurementID = cma.CoreMeasurementID
+ LEFT JOIN attributes a
+ ON cma.Code = a.Code
+ WHERE (a.Status NOT IN ('dead', 'stem dead', 'broken below', 'missing', 'omitted') OR a.Status IS NULL)
+ AND cm1.MeasuredDBH IS NOT NULL
+ AND cm2.MeasuredDBH IS NOT NULL
+ AND cm1.IsValidated IS TRUE
+ AND cm2.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
+
+ SELECT ValidationID
+ INTO veID
+ FROM catalog.validationprocedures
+ WHERE ProcedureName = 'ValidateDBHShrinkageExceedsMax';
+
+ OPEN cur;
+ loop1:
+ LOOP
+ FETCH cur INTO vCoreMeasurementID, vPrevDBH, vCurrDBH;
+ IF done THEN
+ LEAVE loop1;
+ END IF;
+
+ SET validationCriteria = 'Annual DBH Shrinkage';
+ SET measuredValue = CONCAT('Previous DBH: ', vPrevDBH, ', Current DBH: ', vCurrDBH);
+ SET expectedValueRange = 'Shrinkage < 5% of previous DBH';
+ SET additionalDetails = 'Checked for excessive DBH shrinkage over a year';
+
+ IF vCurrDBH < vPrevDBH * 0.95 THEN
+ SET validationResult = 0;
+ SET errorMessage = 'Shrinkage exceeds maximum allowed threshold.';
+ -- Check if the error record already exists before inserting
+ IF NOT EXISTS (SELECT 1
+ FROM cmverrors
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND ValidationErrorID = veID) THEN
+ INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
+ VALUES (vCoreMeasurementID, veID);
+ END IF;
+ INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
+ SET insertCount = insertCount + 1;
+ ELSE
+ SET validationResult = 1;
+ SET errorMessage = NULL;
+ END IF;
+
+ INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
+ ValidationOutcome, ErrorMessage,
+ ValidationCriteria, MeasuredValue, ExpectedValueRange,
+ AdditionalDetails)
+ VALUES ('ValidateDBHShrinkageExceedsMax', NOW(), vCoreMeasurementID,
+ IF(validationResult, 'Passed', 'Failed'), errorMessage,
+ validationCriteria, measuredValue, expectedValueRange,
+ additionalDetails);
+ END LOOP;
+ CLOSE cur;
+
+ SET successMessage =
+ CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
+ SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
+
+ SELECT CoreMeasurementID FROM FailedValidations;
+
+ DROP TEMPORARY TABLE IF EXISTS FailedValidations;
+END;
+
+create
+ definer = azureroot@`%` procedure ValidateFindAllInvalidSpeciesCodes(IN p_CensusID int, IN p_PlotID int)
+BEGIN
+ DECLARE vCoreMeasurementID INT;
+ DECLARE vSpeciesID INT;
+ DECLARE validationResult BIT;
+ DECLARE errorMessage VARCHAR(255);
+ DECLARE validationCriteria TEXT;
+ DECLARE measuredValue VARCHAR(255);
+ DECLARE expectedValueRange VARCHAR(255);
+ DECLARE additionalDetails TEXT;
+ DECLARE insertCount INT DEFAULT 0;
+ DECLARE expectedCount INT;
+ DECLARE successMessage VARCHAR(255);
+ DECLARE veID INT;
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE cur CURSOR FOR
+ SELECT cm.CoreMeasurementID, sp.SpeciesID
+ FROM stems s
+ JOIN trees t ON s.TreeID = t.TreeID
+ LEFT JOIN species sp ON t.SpeciesID = sp.SpeciesID
+ JOIN coremeasurements cm ON s.StemID = cm.StemID
+ LEFT JOIN quadrats q ON s.QuadratID = q.QuadratID
+ WHERE sp.SpeciesID IS NULL
+ AND cm.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
+ GROUP BY cm.CoreMeasurementID;
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
+ (
+ CoreMeasurementID INT
+ );
+
+ IF p_CensusID IS NULL THEN
+ SET p_CensusID = -1;
+ END IF;
+ IF p_PlotID IS NULL THEN
+ SET p_PlotID = -1;
+ END IF;
+
+ SELECT COUNT(*)
+ INTO expectedCount
+ FROM stems s
+ JOIN trees t ON s.TreeID = t.TreeID
+ LEFT JOIN species sp ON t.SpeciesID = sp.SpeciesID
+ JOIN coremeasurements cm ON s.StemID = cm.StemID
+ LEFT JOIN quadrats q ON s.QuadratID = q.QuadratID
+ WHERE sp.SpeciesID IS NULL
+ AND cm.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
+ GROUP BY cm.CoreMeasurementID;
+
+ SELECT ValidationID
+ INTO veID
+ FROM catalog.validationprocedures
+ WHERE ProcedureName = 'ValidateFindAllInvalidSpeciesCodes';
+
+ OPEN cur;
+ loop1:
+ LOOP
+ FETCH cur INTO vCoreMeasurementID, vSpeciesID;
+ IF done THEN
+ LEAVE loop1;
+ END IF;
+
+ SET validationCriteria = 'Species Code Validation';
+ SET measuredValue = CONCAT('Species ID: ', IFNULL(vSpeciesID, 'NULL'));
+ SET expectedValueRange = 'Non-null and valid Species ID';
+ SET additionalDetails = 'Checking for the existence of valid species codes for each measurement.';
+
+ IF vSpeciesID IS NULL THEN
+ SET validationResult = 0;
+ SET errorMessage = 'Invalid species code detected.';
+ -- Check if the error record already exists before inserting
+ IF NOT EXISTS (SELECT 1
+ FROM cmverrors
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND ValidationErrorID = veID) THEN
+ INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
+ VALUES (vCoreMeasurementID, veID);
+ END IF;
+ INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
+ SET insertCount = insertCount + 1;
+ ELSE
+ SET validationResult = 1;
+ SET errorMessage = NULL;
+ END IF;
+
+ INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
+ ValidationOutcome, ErrorMessage,
+ ValidationCriteria, MeasuredValue, ExpectedValueRange,
+ AdditionalDetails)
+ VALUES ('ValidateFindAllInvalidSpeciesCodes', NOW(), vCoreMeasurementID,
+ IF(validationResult, 'Passed', 'Failed'), errorMessage,
+ validationCriteria, measuredValue, expectedValueRange,
+ additionalDetails);
+ END LOOP;
+ CLOSE cur;
+
+ SET successMessage =
+ CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
+ SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
+
+ SELECT CoreMeasurementID FROM FailedValidations;
+
+ DROP TEMPORARY TABLE IF EXISTS FailedValidations;
+END;
+
+create
+ definer = azureroot@`%` procedure ValidateFindDuplicateStemTreeTagCombinationsPerCensus(IN p_CensusID int, IN p_PlotID int)
+BEGIN
+ DECLARE vCoreMeasurementID INT;
+ DECLARE validationResult BIT;
+ DECLARE errorMessage VARCHAR(255);
+ DECLARE validationCriteria TEXT;
+ DECLARE measuredValue VARCHAR(255);
+ DECLARE expectedValueRange VARCHAR(255);
+ DECLARE additionalDetails TEXT;
+ DECLARE insertCount INT DEFAULT 0;
+ DECLARE expectedCount INT;
+ DECLARE successMessage VARCHAR(255);
+ DECLARE veID INT;
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE cur CURSOR FOR
+ SELECT SubQuery.CoreMeasurementID
+ FROM (SELECT cm.CoreMeasurementID
+ FROM coremeasurements cm
+ INNER JOIN stems s ON cm.StemID = s.StemID
+ INNER JOIN trees t ON s.TreeID = t.TreeID
+ INNER JOIN quadrats q ON s.QuadratID = q.QuadratID
+ WHERE (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
+ AND cm.IsValidated = FALSE
+ GROUP BY q.CensusID, s.StemTag, t.TreeTag, cm.CoreMeasurementID
+ HAVING COUNT(*) > 1) AS SubQuery;
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
+ (
+ CoreMeasurementID INT
+ );
+
+ IF p_CensusID IS NULL THEN
+ SET p_CensusID = -1;
+ END IF;
+ IF p_PlotID IS NULL THEN
+ SET p_PlotID = -1;
+ END IF;
+
+ SELECT COUNT(*)
+ INTO expectedCount
+ FROM (SELECT cm.CoreMeasurementID
+ FROM coremeasurements cm
+ INNER JOIN stems s ON cm.StemID = s.StemID
+ INNER JOIN trees t ON s.TreeID = t.TreeID
+ INNER JOIN quadrats q ON s.QuadratID = q.QuadratID
+ WHERE (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
+ AND cm.IsValidated = FALSE
+ GROUP BY q.CensusID, s.StemTag, t.TreeTag, cm.CoreMeasurementID
+ HAVING COUNT(*) > 1) AS DuplicationCheck;
+
+ SELECT ValidationID
+ INTO veID
+ FROM catalog.validationprocedures
+ WHERE ProcedureName = 'ValidateFindDuplicateStemTreeTagCombinationsPerCensus';
+
+
+ OPEN cur;
+ loop1:
+ LOOP
+ FETCH cur INTO vCoreMeasurementID;
+ IF done THEN
+ LEAVE loop1;
+ END IF;
+
+ SET validationCriteria = 'Duplicate Stem-Tree Tag Combinations per Census';
+ SET measuredValue = 'N/A';
+ SET expectedValueRange = 'Unique Stem-Tree Tag Combinations';
+ SET additionalDetails = 'Checking for duplicate stem and tree tag combinations in each census.';
+
+ IF EXISTS (SELECT 1
+ FROM coremeasurements cm
+ INNER JOIN stems s ON cm.StemID = s.StemID
+ INNER JOIN trees t ON s.TreeID = t.TreeID
+ INNER JOIN quadrats q ON s.QuadratID = q.QuadratID
+ WHERE cm.CoreMeasurementID = vCoreMeasurementID
+ GROUP BY q.CensusID, s.StemTag, t.TreeTag
+ HAVING COUNT(cm.CoreMeasurementID) > 1) THEN
+ SET validationResult = 0;
+ SET errorMessage = 'Duplicate stem and tree tag combination detected.';
+ -- Check if the error record already exists before inserting
+ IF NOT EXISTS (SELECT 1
+ FROM cmverrors
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND ValidationErrorID = veID) THEN
+ INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
+ VALUES (vCoreMeasurementID, veID);
+ END IF;
+ INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
+ SET insertCount = insertCount + 1;
+ ELSE
+ SET validationResult = 1;
+ SET errorMessage = NULL;
+ END IF;
+
+ INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
+ ValidationOutcome, ErrorMessage,
+ ValidationCriteria, MeasuredValue, ExpectedValueRange,
+ AdditionalDetails)
+ VALUES ('ValidateFindDuplicateStemTreeTagCombinationsPerCensus', NOW(), vCoreMeasurementID,
+ IF(validationResult, 'Passed', 'Failed'), errorMessage,
+ validationCriteria, measuredValue, expectedValueRange,
+ additionalDetails);
+ END LOOP;
+ CLOSE cur;
+
+ SET successMessage =
+ CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
+ SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
+
+ SELECT CoreMeasurementID FROM FailedValidations;
+
+ DROP TEMPORARY TABLE IF EXISTS FailedValidations;
+END;
+
+create
+ definer = azureroot@`%` procedure ValidateFindDuplicatedQuadratsByName(IN p_CensusID int, IN p_PlotID int)
+BEGIN
+ DECLARE vCoreMeasurementID INT;
+ DECLARE validationResult BIT;
+ DECLARE errorMessage VARCHAR(255);
+ DECLARE validationCriteria TEXT;
+ DECLARE measuredValue VARCHAR(255);
+ DECLARE expectedValueRange VARCHAR(255);
+ DECLARE additionalDetails TEXT;
+ DECLARE insertCount INT DEFAULT 0;
+ DECLARE expectedCount INT;
+ DECLARE successMessage VARCHAR(255);
+ DECLARE veID INT;
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE cur CURSOR FOR
+ SELECT cm.CoreMeasurementID
+ FROM quadrats q
+ LEFT JOIN stems st ON q.QuadratID = st.QuadratID
+ JOIN coremeasurements cm ON st.StemID = cm.StemID
+ WHERE cm.IsValidated IS FALSE
+ AND (q.PlotID, q.QuadratName) IN (SELECT PlotID, QuadratName
+ FROM quadrats
+ GROUP BY PlotID, QuadratName
+ HAVING COUNT(*) > 1)
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
+ GROUP BY cm.CoreMeasurementID;
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
+ (
+ CoreMeasurementID INT
+ );
+
+ IF p_CensusID IS NULL THEN
+ SET p_CensusID = -1;
+ END IF;
+ IF p_PlotID IS NULL THEN
+ SET p_PlotID = -1;
+ END IF;
+
+ SELECT COUNT(*)
+ INTO expectedCount
+ FROM quadrats q
+ LEFT JOIN stems st ON q.QuadratID = st.QuadratID
+ JOIN coremeasurements cm ON st.StemID = cm.StemID
+ WHERE cm.IsValidated IS FALSE
+ AND (q.PlotID, q.QuadratName) IN (SELECT PlotID, QuadratName
+ FROM quadrats
+ GROUP BY PlotID, QuadratName
+ HAVING COUNT(*) > 1)
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
+ GROUP BY cm.CoreMeasurementID;
+
+ SELECT ValidationID
+ INTO veID
+ FROM catalog.validationprocedures
+ WHERE ProcedureName = 'ValidateFindDuplicatedQuadratsByName';
+
+ OPEN cur;
+ loop1:
+ LOOP
+ FETCH cur INTO vCoreMeasurementID;
+ IF done THEN
+ LEAVE loop1;
+ END IF;
+
+ SET validationCriteria = 'Quadrat Name Duplication';
+ SET measuredValue = 'N/A';
+ SET expectedValueRange = 'Unique Quadrat Names per Plot';
+ SET additionalDetails = 'Checking for duplicated quadrat names within the same plot.';
+
+ IF EXISTS (SELECT 1
+ FROM quadrats q
+ WHERE q.QuadratID = vCoreMeasurementID
+ AND (q.PlotID, q.QuadratName) IN (SELECT PlotID, QuadratName
+ FROM quadrats
+ GROUP BY PlotID, QuadratName
+ HAVING COUNT(*) > 1)) THEN
+ SET validationResult = 0;
+ SET errorMessage = 'Duplicated quadrat name detected.';
+ -- Check if the error record already exists before inserting
+ IF NOT EXISTS (SELECT 1
+ FROM cmverrors
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND ValidationErrorID = veID) THEN
+ INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
+ VALUES (vCoreMeasurementID, veID);
+ END IF;
+ INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
+ SET insertCount = insertCount + 1;
+ ELSE
+ SET validationResult = 1;
+ SET errorMessage = NULL;
+ END IF;
+
+ INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
+ ValidationOutcome, ErrorMessage,
+ ValidationCriteria, MeasuredValue, ExpectedValueRange,
+ AdditionalDetails)
+ VALUES ('ValidateFindDuplicatedQuadratsByName', NOW(), vCoreMeasurementID,
+ IF(validationResult, 'Passed', 'Failed'), errorMessage,
+ validationCriteria, measuredValue, expectedValueRange,
+ additionalDetails);
+ END LOOP;
+ CLOSE cur;
+
+ SET successMessage =
+ CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
+ SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
+
+ SELECT CoreMeasurementID FROM FailedValidations;
+
+ DROP TEMPORARY TABLE IF EXISTS FailedValidations;
+END;
+
+create
+ definer = azureroot@`%` procedure ValidateFindMeasurementsOutsideCensusDateBoundsGroupByQuadrat(IN p_CensusID int, IN p_PlotID int)
+BEGIN
+ DECLARE vCoreMeasurementID INT;
+ DECLARE validationResult BIT;
+ DECLARE errorMessage VARCHAR(255);
+ DECLARE validationCriteria TEXT;
+ DECLARE measuredValue VARCHAR(255);
+ DECLARE expectedValueRange VARCHAR(255);
+ DECLARE additionalDetails TEXT;
+ DECLARE insertCount INT DEFAULT 0;
+ DECLARE expectedCount INT;
+ DECLARE successMessage VARCHAR(255);
+ DECLARE veID INT;
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE cur CURSOR FOR
+ SELECT MIN(cm.CoreMeasurementID) AS CoreMeasurementID
+ FROM coremeasurements cm
+ JOIN stems st ON cm.StemID = st.StemID
+ JOIN quadrats q ON st.QuadratID = q.QuadratID
+ JOIN census c ON q.CensusID = c.CensusID
+ WHERE (cm.MeasurementDate < c.StartDate OR cm.MeasurementDate > c.EndDate)
+ AND cm.MeasurementDate IS NOT NULL
+ AND cm.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR c.PlotID = p_PlotID)
+ GROUP BY q.QuadratID, c.CensusID, c.StartDate, c.EndDate;
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
+ (
+ CoreMeasurementID INT
+ );
+
+ IF p_CensusID IS NULL THEN
+ SET p_CensusID = -1;
+ END IF;
+ IF p_PlotID IS NULL THEN
+ SET p_PlotID = -1;
+ END IF;
+
+ SELECT COUNT(*)
+ INTO expectedCount
+ FROM coremeasurements cm
+ JOIN stems st ON cm.StemID = st.StemID
+ JOIN quadrats q ON st.QuadratID = q.QuadratID
+ JOIN census c ON q.CensusID = c.CensusID
+ WHERE (cm.MeasurementDate < c.StartDate OR cm.MeasurementDate > c.EndDate)
+ AND cm.MeasurementDate IS NOT NULL
+ AND cm.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR c.PlotID = p_PlotID);
+
+ SELECT ValidationID
+ INTO veID
+ FROM catalog.validationprocedures
+ WHERE ProcedureName = 'ValidateFindMeasurementsOutsideCensusDateBoundsGroupByQuadrat';
+
+
+ OPEN cur;
+ loop1:
+ LOOP
+ FETCH cur INTO vCoreMeasurementID;
+ IF done THEN
+ LEAVE loop1;
+ END IF;
+
+ SET validationCriteria = 'Measurement Date vs Census Date Bounds';
+ SET measuredValue = 'Measurement Date';
+ SET expectedValueRange = 'Within Census Start and End Dates';
+ SET additionalDetails =
+ 'Checking if measurement dates fall within the start and end dates of their respective censuses.';
+
+ IF EXISTS (SELECT 1
+ FROM coremeasurements cm
+ JOIN stems st ON cm.StemID = st.StemID
+ JOIN quadrats q ON st.QuadratID = q.QuadratID
+ JOIN census c ON q.CensusID = c.CensusID
+ WHERE cm.CoreMeasurementID = vCoreMeasurementID
+ AND (cm.MeasurementDate < c.StartDate OR cm.MeasurementDate > c.EndDate)) THEN
+ SET validationResult = 0;
+ SET errorMessage = 'Measurement outside census date bounds.';
+ -- Check if the error record already exists before inserting
+ IF NOT EXISTS (SELECT 1
+ FROM cmverrors
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND ValidationErrorID = veID) THEN
+ INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
+ VALUES (vCoreMeasurementID, veID);
+ END IF;
+ INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
+ SET insertCount = insertCount + 1;
+ ELSE
+ SET validationResult = 1;
+ SET errorMessage = NULL;
+ END IF;
+
+ INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
+ ValidationOutcome, ErrorMessage,
+ ValidationCriteria, MeasuredValue, ExpectedValueRange,
+ AdditionalDetails)
+ VALUES ('ValidateFindMeasurementsOutsideCensusDateBoundsGroupByQuadrat', NOW(), vCoreMeasurementID,
+ IF(validationResult, 'Passed', 'Failed'), errorMessage,
+ validationCriteria, measuredValue, expectedValueRange,
+ additionalDetails);
+ END LOOP;
+ CLOSE cur;
+
+ SET successMessage =
+ CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
+ SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
+
+ SELECT CoreMeasurementID FROM FailedValidations;
+
+ DROP TEMPORARY TABLE IF EXISTS FailedValidations;
+END;
+
+create
+ definer = azureroot@`%` procedure ValidateFindStemsInTreeWithDifferentSpecies(IN p_CensusID int, IN p_PlotID int)
+BEGIN
+ DECLARE vCoreMeasurementID INT;
+ DECLARE validationResult BIT;
+ DECLARE errorMessage VARCHAR(255);
+ DECLARE validationCriteria TEXT;
+ DECLARE measuredValue VARCHAR(255);
+ DECLARE expectedValueRange VARCHAR(255);
+ DECLARE additionalDetails TEXT;
+ DECLARE insertCount INT DEFAULT 0;
+ DECLARE expectedCount INT;
+ DECLARE successMessage VARCHAR(255);
+ DECLARE veID INT;
+ DECLARE done INT DEFAULT FALSE;
+
+ DECLARE cur CURSOR FOR
+ SELECT cm.CoreMeasurementID
+ FROM coremeasurements cm
+ JOIN stems s ON cm.StemID = s.StemID
+ JOIN trees t ON s.TreeID = t.TreeID
+ JOIN quadrats q ON s.QuadratID = q.QuadratID
+ WHERE cm.IsValidated = FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
+ GROUP BY t.TreeID, cm.CoreMeasurementID
+ HAVING COUNT(DISTINCT t.SpeciesID) > 1;
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
+ (
+ CoreMeasurementID INT
+ );
+
+ IF p_CensusID IS NULL THEN
+ SET p_CensusID = -1;
+ END IF;
+ IF p_PlotID IS NULL THEN
+ SET p_PlotID = -1;
+ END IF;
+
+ SELECT COUNT(*)
+ INTO expectedCount
+ FROM coremeasurements cm
+ JOIN stems s ON cm.StemID = s.StemID
+ JOIN trees t ON s.TreeID = t.TreeID
+ JOIN quadrats q ON s.QuadratID = q.QuadratID
+ WHERE cm.IsValidated = FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
+ GROUP BY t.TreeID
+ HAVING COUNT(DISTINCT t.SpeciesID) > 1;
+
+ SELECT ValidationID
+ INTO veID
+ FROM catalog.validationprocedures
+ WHERE ProcedureName = 'ValidateFindStemsInTreeWithDifferentSpecies';
+
+
+ OPEN cur;
+ loop1:
+ LOOP
+ FETCH cur INTO vCoreMeasurementID;
+ IF done THEN
+ LEAVE loop1;
+ END IF;
+
+ SET validationCriteria = 'Each tree should have a consistent species across all its stems.';
+ SET measuredValue = 'Species consistency across tree stems';
+ SET expectedValueRange = 'One species per tree';
+ SET additionalDetails = 'Checking if stems belonging to the same tree have different species IDs.';
+
+ IF EXISTS (SELECT 1
+ FROM stems s
+ JOIN trees t ON s.TreeID = t.TreeID
+ WHERE t.TreeID IN (SELECT TreeID
+ FROM stems
+ WHERE StemID IN
+ (SELECT StemID
+ FROM coremeasurements
+ WHERE CoreMeasurementID = vCoreMeasurementID))
+ GROUP BY t.TreeID
+ HAVING COUNT(DISTINCT t.SpeciesID) > 1) THEN
+ SET validationResult = 0;
+ SET errorMessage = 'Stems in the same tree have different species.';
+
+ -- Check if the error record already exists before inserting
+ IF NOT EXISTS (SELECT 1
+ FROM cmverrors
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND ValidationErrorID = veID) THEN
+ INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
+ VALUES (vCoreMeasurementID, veID);
+ END IF;
+ INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
+ SET insertCount = insertCount + 1;
+ ELSE
+ SET validationResult = 1;
+ SET errorMessage = NULL;
+ END IF;
+
+ INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
+ ValidationOutcome, ErrorMessage,
+ ValidationCriteria, MeasuredValue, ExpectedValueRange,
+ AdditionalDetails)
+ VALUES ('ValidateFindStemsInTreeWithDifferentSpecies', NOW(), vCoreMeasurementID,
+ IF(validationResult, 'Passed', 'Failed'), errorMessage,
+ validationCriteria, measuredValue, expectedValueRange,
+ additionalDetails);
+ END LOOP;
+ CLOSE cur;
+
+ SET successMessage = CONCAT('Validation completed. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
+ SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
+
+ SELECT CoreMeasurementID FROM FailedValidations;
+
+ DROP TEMPORARY TABLE IF EXISTS FailedValidations;
+END;
+
+create
+ definer = azureroot@`%` procedure ValidateFindStemsOutsidePlots(IN p_CensusID int, IN p_PlotID int)
+BEGIN
+ DECLARE vCoreMeasurementID INT;
+ DECLARE validationResult BIT;
+ DECLARE errorMessage VARCHAR(255);
+ DECLARE validationCriteria TEXT;
+ DECLARE measuredValue VARCHAR(255);
+ DECLARE expectedValueRange VARCHAR(255);
+ DECLARE additionalDetails TEXT;
+ DECLARE insertCount INT DEFAULT 0;
+ DECLARE expectedCount INT;
+ DECLARE successMessage VARCHAR(255);
+ DECLARE veID INT;
+ DECLARE done INT DEFAULT FALSE;
+
+ DECLARE cur CURSOR FOR
+ SELECT cm.CoreMeasurementID
+ FROM stems s
+ INNER JOIN coremeasurements cm ON s.StemID = cm.StemID
+ INNER JOIN quadrats q ON s.QuadratID = q.QuadratID
+ INNER JOIN plots p ON q.PlotID = p.PlotID
+ WHERE (s.LocalX > p.DimensionX OR s.LocalX > p.DimensionY)
+ AND s.LocalX IS NOT NULL
+ AND s.LocalY IS NOT NULL
+ AND (p.DimensionX > 0 AND p.DimensionY > 0)
+ AND cm.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
+ GROUP BY cm.CoreMeasurementID;
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
+ (
+ CoreMeasurementID INT
+ );
+
+ IF p_CensusID IS NULL THEN
+ SET p_CensusID = -1;
+ END IF;
+ IF p_PlotID IS NULL THEN
+ SET p_PlotID = -1;
+ END IF;
+
+ SELECT COUNT(*)
+ INTO expectedCount
+ FROM stems s
+ INNER JOIN quadrats q ON s.QuadratID = q.QuadratID
+ INNER JOIN plots p ON q.PlotID = p.PlotID
+ INNER JOIN coremeasurements cm ON s.StemID = cm.StemID
+ WHERE (s.LocalX > p.DimensionX OR s.LocalX > p.DimensionY)
+ AND s.LocalX IS NOT NULL
+ AND s.LocalY IS NOT NULL
+ AND (p.DimensionX > 0 AND p.DimensionY > 0)
+ AND cm.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
+
+ SELECT ValidationID
+ INTO veID
+ FROM catalog.validationprocedures
+ WHERE ProcedureName = 'ValidateFindStemsOutsidePlots';
+
+
+ OPEN cur;
+ loop1:
+ LOOP
+ FETCH cur INTO vCoreMeasurementID;
+ IF done THEN
+ LEAVE loop1;
+ END IF;
+
+ SET validationCriteria = 'Stem Placement within Plot Boundaries';
+ SET measuredValue = 'Stem Plot Coordinates';
+ SET expectedValueRange = 'Within Plot Dimensions';
+ SET additionalDetails = 'Validating whether stems are located within the specified plot dimensions.';
+
+ IF EXISTS (SELECT 1
+ FROM stems s
+ INNER JOIN quadrats q ON s.QuadratID = q.QuadratID
+ INNER JOIN plots p ON q.PlotID = p.PlotID
+ WHERE s.StemID IN
+ (SELECT StemID
+ FROM coremeasurements
+ WHERE CoreMeasurementID = vCoreMeasurementID)
+ AND (s.LocalX > p.DimensionX OR s.LocalY > p.DimensionY)) THEN
+ SET validationResult = 0;
+ SET errorMessage = 'Stem is outside plot dimensions.';
+ -- Check if the error record already exists before inserting
+ IF NOT EXISTS (SELECT 1
+ FROM cmverrors
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND ValidationErrorID = veID) THEN
+ INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
+ VALUES (vCoreMeasurementID, veID);
+ END IF;
+ INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
+ SET insertCount = insertCount + 1;
+ ELSE
+ SET validationResult = 1;
+ SET errorMessage = NULL;
+ END IF;
+
+ INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
+ ValidationOutcome, ErrorMessage,
+ ValidationCriteria, MeasuredValue, ExpectedValueRange,
+ AdditionalDetails)
+ VALUES ('ValidateFindStemsOutsidePlots', NOW(), vCoreMeasurementID,
+ IF(validationResult, 'Passed', 'Failed'), errorMessage,
+ validationCriteria, measuredValue, expectedValueRange,
+ additionalDetails);
+ END LOOP;
+ CLOSE cur;
+
+ SET successMessage = CONCAT('Validation completed. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
+ SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
+
+ SELECT CoreMeasurementID FROM FailedValidations;
+
+ DROP TEMPORARY TABLE IF EXISTS FailedValidations;
+END;
+
+create
+ definer = azureroot@`%` procedure ValidateFindTreeStemsInDifferentQuadrats(IN p_CensusID int, IN p_PlotID int)
+BEGIN
+ DECLARE vCoreMeasurementID INT;
+ DECLARE validationResult BIT;
+ DECLARE errorMessage VARCHAR(255);
+ DECLARE validationCriteria TEXT;
+ DECLARE measuredValue VARCHAR(255);
+ DECLARE expectedValueRange VARCHAR(255);
+ DECLARE additionalDetails TEXT;
+ DECLARE insertCount INT DEFAULT 0;
+ DECLARE expectedCount INT;
+ DECLARE successMessage VARCHAR(255);
+ DECLARE veID INT;
+ DECLARE done INT DEFAULT FALSE;
+
+ DECLARE cur CURSOR FOR
+ SELECT cm1.CoreMeasurementID
+ FROM stems s1
+ JOIN stems s2 ON s1.TreeID = s2.TreeID AND s1.StemID != s2.StemID
+ JOIN quadrats q1 ON s1.QuadratID = q1.QuadratID
+ JOIN quadrats q2 ON s2.QuadratID = q2.QuadratID
+ JOIN coremeasurements cm1 ON s1.StemID = cm1.StemID
+ WHERE q1.QuadratID != q2.QuadratID
+ AND cm1.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q1.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q1.PlotID = p_PlotID)
+ GROUP BY cm1.CoreMeasurementID;
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
+ (
+ CoreMeasurementID INT
+ );
+
+ IF p_CensusID IS NULL THEN
+ SET p_CensusID = -1;
+ END IF;
+ IF p_PlotID IS NULL THEN
+ SET p_PlotID = -1;
+ END IF;
+
+ SELECT COUNT(*)
+ INTO expectedCount
+ FROM stems s1
+ JOIN stems s2 ON s1.TreeID = s2.TreeID AND s1.StemID != s2.StemID
+ JOIN quadrats q1 ON s1.QuadratID = q1.QuadratID
+ JOIN quadrats q2 ON s2.QuadratID = q2.QuadratID
+ JOIN coremeasurements cm1 ON s1.StemID = cm1.StemID
+ WHERE q1.QuadratID != q2.QuadratID
+ AND cm1.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q1.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q1.PlotID = p_PlotID)
+ GROUP BY cm1.CoreMeasurementID;
+
+ SELECT ValidationID
+ INTO veID
+ FROM catalog.validationprocedures
+ WHERE ProcedureName = 'ValidateFindTreeStemsInDifferentQuadrats';
+
+
+ OPEN cur;
+ loop1:
+ LOOP
+ FETCH cur INTO vCoreMeasurementID;
+ IF done THEN
+ LEAVE loop1;
+ END IF;
+
+ SET validationCriteria = 'Stem Quadrat Consistency within Trees';
+ SET measuredValue = 'Quadrat IDs of Stems';
+ SET expectedValueRange = 'Consistent Quadrat IDs for all Stems in a Tree';
+ SET additionalDetails = 'Validating that all stems within the same tree are located in the same quadrat.';
+
+ IF EXISTS (SELECT 1
+ FROM stems s1
+ JOIN stems s2 ON s1.TreeID = s2.TreeID AND s1.StemID != s2.StemID
+ JOIN quadrats q1 on q1.QuadratID = s2.QuadratID
+ JOIN quadrats q2 on q2.QuadratID = s2.QuadratID
+ WHERE s1.StemID IN
+ (SELECT StemID
+ FROM coremeasurements
+ WHERE CoreMeasurementID = vCoreMeasurementID)
+ AND q1.QuadratID != q2.QuadratID) THEN
+ SET validationResult = 0;
+ SET errorMessage = 'Stems in the same tree are in different quadrats.';
+ -- Check if the error record already exists before inserting
+ IF NOT EXISTS (SELECT 1
+ FROM cmverrors
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND ValidationErrorID = veID) THEN
+ INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
+ VALUES (vCoreMeasurementID, veID);
+ END IF;
+ INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
+ SET insertCount = insertCount + 1;
+ ELSE
+ SET validationResult = 1;
+ SET errorMessage = NULL;
+ END IF;
+
+ INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
+ ValidationOutcome, ErrorMessage,
+ ValidationCriteria, MeasuredValue, ExpectedValueRange,
+ AdditionalDetails)
+ VALUES ('ValidateFindTreeStemsInDifferentQuadrats', NOW(), vCoreMeasurementID,
+ IF(validationResult, 'Passed', 'Failed'), errorMessage,
+ validationCriteria, measuredValue, expectedValueRange,
+ additionalDetails);
+ END LOOP;
+ CLOSE cur;
+
+ SET successMessage = CONCAT('Validation completed. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
+ SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
+
+ SELECT CoreMeasurementID FROM FailedValidations;
+
+ DROP TEMPORARY TABLE IF EXISTS FailedValidations;
+END;
+
+create
+ definer = azureroot@`%` procedure ValidateHOMUpperAndLowerBounds(IN p_CensusID int, IN p_PlotID int,
+ IN minHOM decimal(10, 2), IN maxHOM decimal(10, 2))
+BEGIN
+ DECLARE defaultMinHOM DECIMAL(10, 2);
+ DECLARE defaultMaxHOM DECIMAL(10, 2);
+ DECLARE vCoreMeasurementID INT;
+ DECLARE validationResult BIT;
+ DECLARE errorMessage VARCHAR(255);
+ DECLARE validationCriteria TEXT;
+ DECLARE measuredValue VARCHAR(255);
+ DECLARE expectedValueRange VARCHAR(255);
+ DECLARE additionalDetails TEXT;
+ DECLARE insertCount INT DEFAULT 0;
+ DECLARE expectedCount INT;
+ DECLARE successMessage VARCHAR(255);
+ DECLARE veID INT;
+ DECLARE done INT DEFAULT FALSE;
+
+ DECLARE cur CURSOR FOR
+ SELECT cm.CoreMeasurementID
+ FROM coremeasurements cm
+ LEFT JOIN stems st ON cm.StemID = st.StemID
+ LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
+ WHERE (
+ (minHOM IS NOT NULL AND MeasuredHOM < minHOM) OR
+ (maxHOM IS NOT NULL AND MeasuredHOM > maxHOM) OR
+ (minHOM IS NULL AND maxHOM IS NULL)
+ )
+ AND IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
+ (
+ CoreMeasurementID INT
+ );
+
+ SELECT COUNT(*)
+ INTO expectedCount
+ FROM coremeasurements cm
+ LEFT JOIN stems st ON cm.StemID = st.StemID
+ LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
+ WHERE (
+ (minHOM IS NOT NULL AND MeasuredHOM < minHOM) OR
+ (maxHOM IS NOT NULL AND MeasuredHOM > maxHOM) OR
+ (minHOM IS NULL AND maxHOM IS NULL)
+ )
+ AND IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
+
+ SELECT ValidationID
+ INTO veID
+ FROM catalog.validationprocedures
+ WHERE ProcedureName = 'ValidateHOMUpperAndLowerBounds';
+
+
+ OPEN cur;
+ loop1:
+ LOOP
+ FETCH cur INTO vCoreMeasurementID;
+
+ IF done THEN
+ LEAVE loop1;
+ END IF;
+
+ IF minHOM IS NULL OR maxHOM IS NULL THEN
+ SELECT COALESCE(sl.LowerBound, 0) AS defaultMinHOM,
+ COALESCE(sl.UpperBound, 9999) AS defaultMaxHOM
+ INTO defaultMinHOM, defaultMaxHOM
+ FROM specieslimits sl
+ JOIN species s ON sl.SpeciesCode = s.SpeciesCode
+ JOIN trees t ON s.SpeciesID = t.SpeciesID
+ JOIN stems st ON t.TreeID = st.TreeID
+ JOIN coremeasurements cm ON st.StemID = cm.StemID
+ WHERE cm.CoreMeasurementID = vCoreMeasurementID
+ AND sl.LimitType = 'HOM';
+
+ SET minHOM = COALESCE(minHOM, defaultMinHOM);
+ SET maxHOM = COALESCE(maxHOM, defaultMaxHOM);
+ END IF;
+
+ SET validationCriteria = 'HOM Measurement Range Validation';
+ SET measuredValue = CONCAT('Measured HOM: ', (SELECT MeasuredHOM
+ FROM coremeasurements
+ WHERE CoreMeasurementID = vCoreMeasurementID));
+ SET expectedValueRange = CONCAT('Expected HOM Range: ', minHOM, ' - ', maxHOM);
+ SET additionalDetails = 'Checks if the measured HOM falls within the specified minimum and maximum range.';
+
+ IF (SELECT MeasuredHOM
+ FROM coremeasurements
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND (
+ (minHOM IS NOT NULL AND MeasuredHOM < minHOM) OR
+ (maxHOM IS NOT NULL AND MeasuredHOM > maxHOM) OR
+ (minHOM IS NULL AND maxHOM IS NULL)
+ )) THEN
+ SET validationResult = 0;
+ SET errorMessage = CONCAT('HOM outside bounds: ', minHOM, ' - ', maxHOM);
+ INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
+ SET insertCount = insertCount + 1;
+ -- Check if the error record already exists before inserting
+ IF NOT EXISTS (SELECT 1
+ FROM cmverrors
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND ValidationErrorID = veID) THEN
+ INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
+ VALUES (vCoreMeasurementID, veID);
+ END IF;
+ ELSE
+ SET validationResult = 1;
+ SET errorMessage = NULL;
+ END IF;
+
+ INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
+ ValidationOutcome, ErrorMessage,
+ ValidationCriteria, MeasuredValue, ExpectedValueRange,
+ AdditionalDetails)
+ VALUES ('ValidateHOMUpperAndLowerBounds', NOW(), vCoreMeasurementID,
+ IF(validationResult, 'Passed', 'Failed'), errorMessage,
+ validationCriteria, measuredValue, expectedValueRange,
+ additionalDetails);
+ END LOOP;
+ CLOSE cur;
+
+ SET successMessage =
+ CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
+ SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
+
+ SELECT CoreMeasurementID FROM FailedValidations;
+
+ DROP TEMPORARY TABLE IF EXISTS FailedValidations;
+END;
+
+create
+ definer = azureroot@`%` procedure ValidateScreenMeasuredDiameterMinMax(IN p_CensusID int, IN p_PlotID int,
+ IN minDBH decimal(10, 2),
+ IN maxDBH decimal(10, 2))
+BEGIN
+ DECLARE defaultMinDBH DECIMAL(10, 2);
+ DECLARE defaultMaxDBH DECIMAL(10, 2);
+ DECLARE vCoreMeasurementID INT;
+ DECLARE validationResult BIT;
+ DECLARE errorMessage VARCHAR(255);
+ DECLARE validationCriteria TEXT;
+ DECLARE measuredValue VARCHAR(255);
+ DECLARE expectedValueRange VARCHAR(255);
+ DECLARE additionalDetails TEXT;
+ DECLARE insertCount INT DEFAULT 0;
+ DECLARE expectedCount INT;
+ DECLARE successMessage VARCHAR(255);
+ DECLARE veID INT;
+ DECLARE done INT DEFAULT FALSE;
+
+ DECLARE cur CURSOR FOR
+ SELECT cm.CoreMeasurementID
+ FROM coremeasurements cm
+ LEFT JOIN stems st ON cm.StemID = st.StemID
+ LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
+ WHERE (
+ (MeasuredDBH < 0) OR
+ (maxDBH IS NOT NULL AND MeasuredDBH > maxDBH) OR
+ (minDBH IS NULL AND maxDBH IS NULL)
+ )
+ AND IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
+ (
+ CoreMeasurementID INT
+ );
+
+ SELECT COUNT(*)
+ INTO expectedCount
+ FROM coremeasurements cm
+ LEFT JOIN stems st ON cm.StemID = st.StemID
+ LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
+ WHERE (
+ (MeasuredDBH < 0) OR
+ (maxDBH IS NOT NULL AND MeasuredDBH > maxDBH) OR
+ (minDBH IS NULL AND maxDBH IS NULL)
+ )
+ AND IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
+
+ SELECT ValidationID
+ INTO veID
+ FROM catalog.validationprocedures
+ WHERE ProcedureName = 'ValidateScreenMeasuredDiameterMinMax';
+
+
+ OPEN cur;
+ loop1:
+ LOOP
+ FETCH cur INTO vCoreMeasurementID;
+
+ IF done THEN
+ LEAVE loop1;
+ END IF;
+
+ IF minDBH IS NULL OR maxDBH IS NULL THEN
+ SELECT COALESCE(sl.LowerBound, 0) AS defaultMinDBH,
+ COALESCE(sl.UpperBound, 9999) AS defaultMaxDBH
+ INTO defaultMinDBH, defaultMaxDBH
+ FROM specieslimits sl
+ JOIN species s ON sl.SpeciesCode = s.SpeciesCode
+ JOIN trees t ON s.SpeciesID = t.SpeciesID
+ JOIN stems st ON t.TreeID = st.TreeID
+ JOIN coremeasurements cm ON st.StemID = cm.StemID
+ WHERE cm.CoreMeasurementID = vCoreMeasurementID
+ AND sl.LimitType = 'DBH';
+
+ SET minDBH = COALESCE(minDBH, defaultMinDBH);
+ SET maxDBH = COALESCE(maxDBH, defaultMaxDBH);
+ END IF;
+
+ SET validationCriteria = 'DBH Measurement Range Validation';
+ SET measuredValue = CONCAT('Measured DBH: ', (SELECT MeasuredDBH
+ FROM coremeasurements
+ WHERE CoreMeasurementID = vCoreMeasurementID));
+ SET expectedValueRange = CONCAT('Expected DBH Range: ', minDBH, ' - ', maxDBH);
+ SET additionalDetails = 'Checks if the measured DBH falls within the specified minimum and maximum range.';
+
+ IF (SELECT MeasuredDBH
+ FROM coremeasurements
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND (
+ (MeasuredDBH < 0) OR
+ (maxDBH IS NOT NULL AND MeasuredDBH > maxDBH) OR
+ (minDBH IS NULL AND maxDBH IS NULL)
+ )) THEN
+ SET validationResult = 0;
+ SET errorMessage = CONCAT('DBH outside bounds: ', minDBH, ' - ', maxDBH);
+ INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
+ SET insertCount = insertCount + 1;
+ -- Check if the error record already exists before inserting
+ IF NOT EXISTS (SELECT 1
+ FROM cmverrors
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND ValidationErrorID = veID) THEN
+ INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
+ VALUES (vCoreMeasurementID, veID);
+ END IF;
+ ELSE
+ SET validationResult = 1;
+ SET errorMessage = NULL;
+ END IF;
+
+ INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
+ ValidationOutcome, ErrorMessage,
+ ValidationCriteria, MeasuredValue, ExpectedValueRange,
+ AdditionalDetails)
+ VALUES ('ValidateScreenMeasuredDiameterMinMax', NOW(), vCoreMeasurementID,
+ IF(validationResult, 'Passed', 'Failed'), errorMessage,
+ validationCriteria, measuredValue, expectedValueRange,
+ additionalDetails);
+ END LOOP;
+ CLOSE cur;
+
+ SET successMessage =
+ CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
+ SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
+
+ SELECT CoreMeasurementID FROM FailedValidations;
+
+ DROP TEMPORARY TABLE IF EXISTS FailedValidations;
+END;
+
+create
+ definer = azureroot@`%` procedure ValidateScreenStemsWithMeasurementsButDeadAttributes(IN p_CensusID int, IN p_PlotID int)
+BEGIN
+ DECLARE vCoreMeasurementID INT;
+ DECLARE validationResult BIT;
+ DECLARE errorMessage VARCHAR(255);
+ DECLARE validationCriteria TEXT;
+ DECLARE additionalDetails TEXT;
+ DECLARE insertCount INT DEFAULT 0;
+ DECLARE expectedCount INT;
+ DECLARE successMessage VARCHAR(255);
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE veID INT;
+ DECLARE vExistingErrorID INT;
+
+ DECLARE cur CURSOR FOR
+ SELECT cm.CoreMeasurementID
+ FROM coremeasurements cm
+ JOIN cmattributes cma ON cm.CoreMeasurementID = cma.CoreMeasurementID
+ JOIN attributes a ON cma.Code = a.Code
+ JOIN stems st ON cm.StemID = st.StemID
+ JOIN quadrats q ON st.QuadratID = q.QuadratID
+ WHERE ((cm.MeasuredDBH IS NOT NULL AND cm.MeasuredDBH > 0) OR
+ (cm.MeasuredHOM IS NOT NULL AND cm.MeasuredHOM > 0))
+ AND a.Status IN ('dead', 'stem dead', 'missing', 'broken below', 'omitted')
+ AND cm.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
+ (
+ CoreMeasurementID INT
+ );
+
+ SELECT COUNT(*)
+ INTO expectedCount
+ FROM coremeasurements cm
+ JOIN cmattributes cma ON cm.CoreMeasurementID = cma.CoreMeasurementID
+ JOIN attributes a ON cma.Code = a.Code
+ JOIN stems st ON cm.StemID = st.StemID
+ JOIN quadrats q ON st.QuadratID = q.QuadratID
+ WHERE ((cm.MeasuredDBH IS NOT NULL AND cm.MeasuredDBH > 0) OR
+ (cm.MeasuredHOM IS NOT NULL AND cm.MeasuredHOM > 0))
+ AND a.Status IN ('dead', 'stem dead', 'missing', 'broken below', 'omitted')
+ AND cm.IsValidated IS FALSE
+ AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
+ AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
+
+ SELECT ValidationID
+ INTO veID
+ FROM catalog.validationprocedures
+ WHERE ProcedureName = 'ValidateScreenStemsWithMeasurementsButDeadAttributes';
+
+
+ OPEN cur;
+ loop1:
+ LOOP
+ FETCH cur INTO vCoreMeasurementID;
+ IF done THEN
+ LEAVE loop1;
+ END IF;
+
+ SET validationCriteria = 'Stem Measurements with Dead Attributes Validation';
+ SET additionalDetails = 'Verifies that stems marked as dead do not have active measurements.';
+
+ IF EXISTS (SELECT 1
+ FROM cmattributes cma
+ JOIN attributes a ON cma.Code = a.Code
+ JOIN coremeasurements cm on cma.CoreMeasurementID = cm.CoreMeasurementID
+ WHERE cma.CoreMeasurementID = vCoreMeasurementID
+ AND a.Status IN ('dead', 'stem dead', 'missing', 'broken below', 'omitted')
+ AND ((cm.MeasuredDBH IS NOT NULL AND cm.MeasuredDBH > 0) OR
+ (cm.MeasuredHOM IS NOT NULL AND cm.MeasuredHOM > 0))) THEN
+ SET validationResult = 0;
+ SET errorMessage = 'Stem with measurements but dead attributes detected.';
+ -- Check if the error record already exists before inserting
+ IF NOT EXISTS (SELECT 1
+ FROM cmverrors
+ WHERE CoreMeasurementID = vCoreMeasurementID
+ AND ValidationErrorID = veID) THEN
+ INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
+ VALUES (vCoreMeasurementID, veID);
+ END IF;
+ INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
+ SET insertCount = insertCount + 1;
+ ELSE
+ SET validationResult = 1;
+ SET errorMessage = NULL;
+ END IF;
+
+ INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
+ ValidationOutcome, ErrorMessage,
+ ValidationCriteria, AdditionalDetails)
+ VALUES ('ValidateScreenStemsWithMeasurementsButDeadAttributes', NOW(), vCoreMeasurementID,
+ IF(validationResult, 'Passed', 'Failed'), errorMessage,
+ validationCriteria, additionalDetails);
+ END LOOP;
+ CLOSE cur;
+
+ SET successMessage =
+ CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
+ SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
+
+ SELECT CoreMeasurementID FROM FailedValidations;
+
+ DROP TEMPORARY TABLE IF EXISTS FailedValidations;
+END;
+
diff --git a/frontend/sqlscripting/resetschema.sql b/frontend/sqlscripting/resetschema.sql
index 07315457..be5b483d 100644
--- a/frontend/sqlscripting/resetschema.sql
+++ b/frontend/sqlscripting/resetschema.sql
@@ -19,4 +19,21 @@ truncate stems;
truncate subquadrats;
truncate unifiedchangelog;
truncate validationchangelog;
+DROP VIEW IF EXISTS `alltaxonomiesview`;
+DROP VIEW IF EXISTS `measurementssummaryview`;
+DROP VIEW IF EXISTS `stemtaxonomiesview`;
+DROP VIEW IF EXISTS `viewfulltableview`;
+DROP PROCEDURE IF EXISTS `UpdateValidationStatus`;
+DROP PROCEDURE IF EXISTS `ValidateDBHGrowthExceedsMax`;
+DROP PROCEDURE IF EXISTS `ValidateDBHShrinkageExceedsMax`;
+DROP PROCEDURE IF EXISTS `ValidateFindAllInvalidSpeciesCodes`;
+DROP PROCEDURE IF EXISTS `ValidateFindDuplicatedQuadratsByName`;
+DROP PROCEDURE IF EXISTS `ValidateFindDuplicateStemTreeTagCombinationsPerCensus`;
+DROP PROCEDURE IF EXISTS `ValidateFindMeasurementsOutsideCensusDateBoundsGroupByQuadrat`;
+DROP PROCEDURE IF EXISTS `ValidateFindStemsInTreeWithDifferentSpecies`;
+DROP PROCEDURE IF EXISTS `ValidateFindStemsOutsidePlots`;
+DROP PROCEDURE IF EXISTS `ValidateFindTreeStemsInDifferentQuadrats`;
+DROP PROCEDURE IF EXISTS `ValidateHOMUpperAndLowerBounds`;
+DROP PROCEDURE IF EXISTS `ValidateScreenMeasuredDiameterMinMax`;
+DROP PROCEDURE IF EXISTS `ValidateScreenStemsWithMeasurementsButDeadAttributes`;
set foreign_key_checks = 1;
\ No newline at end of file
diff --git a/frontend/sqlscripting/tablestructures.sql b/frontend/sqlscripting/tablestructures.sql
index 2c9c381c..7447f5e4 100644
--- a/frontend/sqlscripting/tablestructures.sql
+++ b/frontend/sqlscripting/tablestructures.sql
@@ -145,7 +145,6 @@ create table species
SpeciesID int auto_increment
primary key,
GenusID int null,
- CensusID int null,
SpeciesCode varchar(25) null,
SpeciesName varchar(64) null,
SubspeciesName varchar(255) null,
@@ -163,9 +162,7 @@ create table species
constraint Species_Genus_GenusID_fk
foreign key (GenusID) references genus (GenusID),
constraint Species_Reference_ReferenceID_fk
- foreign key (ReferenceID) references reference (ReferenceID),
- constraint species_census_CensusID_fk
- foreign key (CensusID) references census (CensusID)
+ foreign key (ReferenceID) references reference (ReferenceID)
);
create table specieslimits
diff --git a/frontend/sqlscripting/updated_triggers_7-3-24.sql b/frontend/sqlscripting/updated_triggers_7-3-24.sql
index 5734760b..04846b99 100644
--- a/frontend/sqlscripting/updated_triggers_7-3-24.sql
+++ b/frontend/sqlscripting/updated_triggers_7-3-24.sql
@@ -44,7 +44,7 @@ BEGIN
'Code', OLD.Code,
'Description', OLD.Description,
'Status', OLD.Status
- );
+ );
-- Construct the JSON object for the new row
SET new_json = JSON_OBJECT(
@@ -76,12 +76,12 @@ CREATE TRIGGER after_delete_attributes
BEGIN
DECLARE old_json JSON;
- -- Construct the JSON object for the new row
+ -- Construct the JSON object for the new row
SET old_json = JSON_OBJECT(
'Code', OLD.Code,
'Description', OLD.Description,
'Status', OLD.Status
- );
+ );
-- Insert the change log entry into unifiedchangelog
INSERT INTO unifiedchangelog (TableName, RecordID, Operation, OldRowState, ChangeTimestamp, ChangedBy)
@@ -1138,7 +1138,6 @@ BEGIN
SET new_json = JSON_OBJECT(
'SpeciesID', NEW.SpeciesID,
'GenusID', NEW.GenusID,
- 'CensusID', NEW.CensusID,
'SpeciesCode', NEW.SpeciesCode,
'SpeciesName', NEW.SpeciesName,
'SubspeciesName', NEW.SubspeciesName,
@@ -1179,7 +1178,6 @@ BEGIN
SET old_json = JSON_OBJECT(
'SpeciesID', OLD.SpeciesID,
'GenusID', OLD.GenusID,
- 'CensusID', OLD.CensusID,
'SpeciesCode', OLD.SpeciesCode,
'SpeciesName', OLD.SpeciesName,
'SubspeciesName', OLD.SubspeciesName,
@@ -1196,7 +1194,6 @@ BEGIN
SET new_json = JSON_OBJECT(
'SpeciesID', NEW.SpeciesID,
'GenusID', NEW.GenusID,
- 'CensusID', NEW.CensusID,
'SpeciesCode', NEW.SpeciesCode,
'SpeciesName', NEW.SpeciesName,
'SubspeciesName', NEW.SubspeciesName,
@@ -1237,7 +1234,6 @@ BEGIN
SET old_json = JSON_OBJECT(
'SpeciesID', OLD.SpeciesID,
'GenusID', OLD.GenusID,
- 'CensusID', OLD.CensusID,
'SpeciesCode', OLD.SpeciesCode,
'SpeciesName', OLD.SpeciesName,
'SubspeciesName', OLD.SubspeciesName,
@@ -1394,8 +1390,8 @@ BEGIN
'DimensionX', NEW.DimensionX,
'DimensionY', NEW.DimensionY,
'DimensionUnits', NEW.DimensionUnits,
- 'X', NEW.X,
- 'Y', NEW.Y,
+ 'QX', NEW.QX,
+ 'QY', NEW.QY,
'CoordinateUnits', NEW.CoordinateUnits,
'Ordering', NEW.Ordering
);
@@ -1432,8 +1428,8 @@ BEGIN
'DimensionX', OLD.DimensionX,
'DimensionY', OLD.DimensionY,
'DimensionUnits', OLD.DimensionUnits,
- 'X', OLD.X,
- 'Y', OLD.Y,
+ 'QX', OLD.QX,
+ 'QY', OLD.QY,
'CoordinateUnits', OLD.CoordinateUnits,
'Ordering', OLD.Ordering
);
@@ -1446,8 +1442,8 @@ BEGIN
'DimensionX', NEW.DimensionX,
'DimensionY', NEW.DimensionY,
'DimensionUnits', NEW.DimensionUnits,
- 'X', NEW.X,
- 'Y', NEW.Y,
+ 'QX', NEW.QX,
+ 'QY', NEW.QY,
'CoordinateUnits', NEW.CoordinateUnits,
'Ordering', NEW.Ordering
);
@@ -1483,8 +1479,8 @@ BEGIN
'DimensionX', OLD.DimensionX,
'DimensionY', OLD.DimensionY,
'DimensionUnits', OLD.DimensionUnits,
- 'X', OLD.X,
- 'Y', OLD.Y,
+ 'QX', OLD.QX,
+ 'QY', OLD.QY,
'CoordinateUnits', OLD.CoordinateUnits,
'Ordering', OLD.Ordering
);
diff --git a/frontend/sqlscripting/updatedviews.sql b/frontend/sqlscripting/updatedviews.sql
new file mode 100644
index 00000000..825d7e2f
--- /dev/null
+++ b/frontend/sqlscripting/updatedviews.sql
@@ -0,0 +1,195 @@
+CREATE VIEW alltaxonomiesview AS
+SELECT
+ s.SpeciesID AS SpeciesID,
+ f.FamilyID AS FamilyID,
+ g.GenusID AS GenusID,
+ r.ReferenceID AS ReferenceID,
+ s.SpeciesCode AS SpeciesCode,
+ f.Family AS Family,
+ g.Genus AS Genus,
+ g.GenusAuthority AS GenusAuthority,
+ s.SpeciesName AS SpeciesName,
+ s.SubspeciesName AS SubSpeciesName,
+ s.IDLevel AS SpeciesIDLevel,
+ s.SpeciesAuthority AS SpeciesAuthority,
+ s.SubspeciesAuthority AS SubspeciesAuthority,
+ s.ValidCode AS ValidCode,
+ s.FieldFamily AS FieldFamily,
+ s.Description AS SpeciesDescription,
+ r.PublicationTitle AS PublicationTitle,
+ r.FullReference AS FullReference,
+ r.DateOfPublication AS DateOfPublication,
+ r.Citation AS Citation
+FROM
+ family f
+ JOIN genus g ON f.FamilyID = g.FamilyID
+ JOIN species s ON g.GenusID = s.GenusID
+ LEFT JOIN reference r ON s.ReferenceID = r.ReferenceID;
+
+
+CREATE VIEW measurementssummaryview AS
+SELECT
+ cm.CoreMeasurementID AS CoreMeasurementID,
+ p.PlotID AS PlotID,
+ cm.CensusID AS CensusID,
+ q.QuadratID AS QuadratID,
+ s.SpeciesID AS SpeciesID,
+ t.TreeID AS TreeID,
+ st.StemID AS StemID,
+ qp.PersonnelID AS PersonnelID,
+ p.PlotName AS PlotName,
+ q.QuadratName AS QuadratName,
+ s.SpeciesCode AS SpeciesCode,
+ t.TreeTag AS TreeTag,
+ st.StemTag AS StemTag,
+ st.LocalX AS StemLocalX,
+ st.LocalY AS StemLocalY,
+ st.CoordinateUnits AS StemUnits,
+ COALESCE(CONCAT(pe.FirstName, ' ', pe.LastName), 'Unknown') AS PersonnelName,
+ cm.MeasurementDate AS MeasurementDate,
+ cm.MeasuredDBH AS MeasuredDBH,
+ cm.DBHUnit AS DBHUnits,
+ cm.MeasuredHOM AS MeasuredHOM,
+ cm.HOMUnit AS HOMUnits,
+ cm.IsValidated AS IsValidated,
+ cm.Description AS Description,
+ (SELECT GROUP_CONCAT(ca.Code SEPARATOR '; ')
+ FROM cmattributes ca
+ WHERE ca.CoreMeasurementID = cm.CoreMeasurementID) AS Attributes
+FROM
+ coremeasurements cm
+ LEFT JOIN stems st ON cm.StemID = st.StemID
+ LEFT JOIN trees t ON st.TreeID = t.TreeID
+ LEFT JOIN species s ON t.SpeciesID = s.SpeciesID
+ LEFT JOIN genus g ON s.GenusID = g.GenusID
+ LEFT JOIN family f ON g.FamilyID = f.FamilyID
+ LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
+ LEFT JOIN plots p ON q.PlotID = p.PlotID
+ LEFT JOIN census c ON cm.CensusID = c.CensusID
+ LEFT JOIN quadratpersonnel qp ON q.QuadratID = qp.QuadratID
+ LEFT JOIN personnel pe ON qp.PersonnelID = pe.PersonnelID
+GROUP BY
+ cm.CoreMeasurementID, p.PlotID, cm.CensusID, q.QuadratID, s.SpeciesID, t.TreeID, st.StemID, qp.PersonnelID,
+ p.PlotName, q.QuadratName, s.SpeciesCode, t.TreeTag, st.StemTag, st.LocalX, st.LocalY, st.CoordinateUnits,
+ pe.FirstName, pe.LastName, cm.MeasurementDate, cm.MeasuredDBH, cm.DBHUnit, cm.MeasuredHOM, cm.HOMUnit,
+ cm.IsValidated, cm.Description;
+
+
+CREATE VIEW stemtaxonomiesview AS
+SELECT
+ s.StemID AS StemID,
+ t.TreeID AS TreeID,
+ q.QuadratID AS QuadratID,
+ c.CensusID AS CensusID,
+ p.PlotID AS PlotID,
+ f.FamilyID AS FamilyID,
+ g.GenusID AS GenusID,
+ sp.SpeciesID AS SpeciesID,
+ s.StemTag AS StemTag,
+ t.TreeTag AS TreeTag,
+ sp.SpeciesCode AS SpeciesCode,
+ f.Family AS Family,
+ g.Genus AS Genus,
+ sp.SpeciesName AS SpeciesName,
+ sp.SubspeciesName AS SubspeciesName,
+ sp.ValidCode AS ValidCode,
+ g.GenusAuthority AS GenusAuthority,
+ sp.SpeciesAuthority AS SpeciesAuthority,
+ sp.SubspeciesAuthority AS SubspeciesAuthority,
+ sp.IDLevel AS SpeciesIDLevel,
+ sp.FieldFamily AS SpeciesFieldFamily
+FROM
+ stems s
+ JOIN trees t ON s.TreeID = t.TreeID
+ JOIN quadrats q ON s.QuadratID = q.QuadratID
+ JOIN census c ON q.CensusID = c.CensusID
+ JOIN plots p ON c.PlotID = p.PlotID
+ JOIN species sp ON t.SpeciesID = sp.SpeciesID
+ JOIN genus g ON sp.GenusID = g.GenusID
+ LEFT JOIN family f ON g.FamilyID = f.FamilyID;
+
+
+CREATE VIEW viewfulltableview AS
+SELECT
+ cm.CoreMeasurementID AS CoreMeasurementID,
+ cm.MeasurementDate AS MeasurementDate,
+ cm.MeasuredDBH AS MeasuredDBH,
+ cm.DBHUnit AS DBHUnits,
+ cm.MeasuredHOM AS MeasuredHOM,
+ cm.HOMUnit AS HOMUnits,
+ cm.Description AS Description,
+ cm.IsValidated AS IsValidated,
+ p.PlotID AS PlotID,
+ p.PlotName AS PlotName,
+ p.LocationName AS LocationName,
+ p.CountryName AS CountryName,
+ p.DimensionX AS DimensionX,
+ p.DimensionY AS DimensionY,
+ p.Area AS PlotArea,
+ p.GlobalX AS GlobalX,
+ p.GlobalY AS GlobalY,
+ p.GlobalZ AS GlobalZ,
+ p.DimensionUnits AS PlotUnit,
+ p.PlotShape AS PlotShape,
+ p.PlotDescription AS PlotDescription,
+ c.CensusID AS CensusID,
+ c.StartDate AS CensusStartDate,
+ c.EndDate AS CensusEndDate,
+ c.Description AS CensusDescription,
+ c.PlotCensusNumber AS PlotCensusNumber,
+ q.QuadratID AS QuadratID,
+ q.QuadratName AS QuadratName,
+ q.DimensionX AS QuadratDimensionX,
+ q.DimensionY AS QuadratDimensionY,
+ q.Area AS QuadratArea,
+ q.QuadratShape AS QuadratShape,
+ q.DimensionUnits AS QuadratUnit,
+ sq.SubquadratID AS SubquadratID,
+ sq.SubquadratName AS SubquadratName,
+ sq.DimensionX AS SubquadratDimensionX,
+ sq.DimensionY AS SubquadratDimensionY,
+ sq.QX AS QX,
+ sq.QY AS QY,
+ sq.CoordinateUnits AS SubquadratUnit,
+ t.TreeID AS TreeID,
+ t.TreeTag AS TreeTag,
+ s.StemID AS StemID,
+ s.StemTag AS StemTag,
+ s.LocalX AS StemLocalX,
+ s.LocalY AS StemLocalY,
+ s.CoordinateUnits AS StemUnits,
+ per.PersonnelID AS PersonnelID,
+ per.FirstName AS FirstName,
+ per.LastName AS LastName,
+ r.RoleName AS PersonnelRoles,
+ sp.SpeciesID AS SpeciesID,
+ sp.SpeciesCode AS SpeciesCode,
+ sp.SpeciesName AS SpeciesName,
+ sp.SubspeciesName AS SubspeciesName,
+ sp.SubspeciesAuthority AS SubspeciesAuthority,
+ sp.IDLevel AS SpeciesIDLevel,
+ g.GenusID AS GenusID,
+ g.Genus AS Genus,
+ g.GenusAuthority AS GenusAuthority,
+ fam.FamilyID AS FamilyID,
+ fam.Family AS Family,
+ attr.Code AS AttributeCode,
+ attr.Description AS AttributeDescription,
+ attr.Status AS AttributeStatus
+FROM
+ coremeasurements cm
+ LEFT JOIN stems s ON cm.StemID = s.StemID
+ LEFT JOIN trees t ON s.TreeID = t.TreeID
+ LEFT JOIN species sp ON t.SpeciesID = sp.SpeciesID
+ LEFT JOIN genus g ON sp.GenusID = g.GenusID
+ LEFT JOIN family fam ON g.FamilyID = fam.FamilyID
+ LEFT JOIN specieslimits sl ON sp.SpeciesCode = sl.SpeciesCode
+ LEFT JOIN quadrats q ON s.QuadratID = q.QuadratID
+ LEFT JOIN quadratpersonnel qp ON q.QuadratID = qp.QuadratID
+ LEFT JOIN personnel per ON qp.PersonnelID = per.PersonnelID
+ LEFT JOIN plots p ON q.PlotID = p.PlotID
+ LEFT JOIN subquadrats sq ON q.QuadratID = sq.QuadratID
+ LEFT JOIN census c ON cm.CensusID = c.CensusID
+ LEFT JOIN roles r ON per.RoleID = r.RoleID
+ LEFT JOIN attributes attr ON cm.CoreMeasurementID = attr.Code
+ LEFT JOIN cmattributes cma ON cm.CoreMeasurementID = cma.CoreMeasurementID AND attr.Code = cma.Code;
diff --git a/frontend/sqlscripting/views.sql b/frontend/sqlscripting/views.sql
deleted file mode 100644
index 6c04c8d2..00000000
--- a/frontend/sqlscripting/views.sql
+++ /dev/null
@@ -1,1512 +0,0 @@
-create
- definer = azureroot@`%` procedure UpdateValidationStatus(IN p_PlotID int, IN p_CensusID int, OUT RowsValidated int)
-BEGIN
- -- Create a temporary table to store CoreMeasurementIDs
- CREATE TEMPORARY TABLE IF NOT EXISTS TempUpdatedIDs (CoreMeasurementID INT);
-
- -- Clear the temporary table
- TRUNCATE TABLE TempUpdatedIDs;
-
- -- Insert the CoreMeasurementIDs of the rows to be updated into the temporary table
- INSERT INTO TempUpdatedIDs (CoreMeasurementID)
- SELECT cm.CoreMeasurementID
- FROM coremeasurements cm
- LEFT JOIN cmverrors cme ON cm.CoreMeasurementID = cme.CoreMeasurementID
- LEFT JOIN stems s on cm.StemID = s.StemID
- LEFT JOIN quadrats q on s.QuadratID = q.QuadratID
- WHERE cm.IsValidated = FALSE
- AND (q.PlotID = p_PlotID OR p_PlotID IS NULL)
- AND (q.CensusID = p_CensusID OR p_CensusID IS NULL)
- AND cme.CoreMeasurementID IS NULL;
-
- -- Update the IsValidated column
- UPDATE coremeasurements cm
- INNER JOIN TempUpdatedIDs tmp ON cm.CoreMeasurementID = tmp.CoreMeasurementID
- SET cm.IsValidated = TRUE;
-
- -- Get the count of rows that have been updated
- SET RowsValidated = ROW_COUNT();
-
- -- Select the CoreMeasurementIDs from the temporary table
- SELECT CoreMeasurementID FROM TempUpdatedIDs;
-
- -- Optionally, drop the temporary table
- DROP TEMPORARY TABLE IF EXISTS TempUpdatedIDs;
-END;
-
-create
- definer = azureroot@`%` procedure ValidateDBHGrowthExceedsMax(IN p_CensusID int, IN p_PlotID int)
-BEGIN
- DECLARE vCoreMeasurementID INT;
- DECLARE vPrevDBH DECIMAL(10, 2);
- DECLARE vCurrDBH DECIMAL(10, 2);
- DECLARE validationResult BIT;
- DECLARE errorMessage VARCHAR(255);
- DECLARE validationCriteria TEXT;
- DECLARE measuredValue VARCHAR(255);
- DECLARE expectedValueRange VARCHAR(255);
- DECLARE additionalDetails TEXT;
- DECLARE insertCount INT DEFAULT 0;
- DECLARE expectedCount INT;
- DECLARE successMessage VARCHAR(255);
- DECLARE done INT DEFAULT FALSE;
- DECLARE veID INT;
- DECLARE cur CURSOR FOR
- SELECT cm2.CoreMeasurementID, cm1.MeasuredDBH, cm2.MeasuredDBH
- FROM coremeasurements cm1
- JOIN coremeasurements cm2
- ON cm1.StemID = cm2.StemID
- AND YEAR(cm2.MeasurementDate) = YEAR(cm1.MeasurementDate) + 1
- LEFT JOIN stems st2 ON cm2.StemID = st2.StemID
- LEFT JOIN quadrats q ON st2.QuadratID = q.QuadratID
- LEFT JOIN cmattributes cma
- ON cm1.CoreMeasurementID = cma.CoreMeasurementID
- LEFT JOIN attributes a
- ON cma.Code = a.Code
- WHERE (a.Status NOT IN ('dead', 'stem dead', 'broken below', 'missing', 'omitted') OR a.Status IS NULL)
- AND cm1.MeasuredDBH IS NOT NULL
- AND cm2.MeasuredDBH IS NOT NULL
- AND (cm2.MeasuredDBH - cm1.MeasuredDBH > 65)
- AND cm1.IsValidated IS TRUE
- AND cm2.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
-
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
- (
- CoreMeasurementID INT
- );
-
- IF p_CensusID IS NULL THEN
- SET p_CensusID = -1;
- END IF;
- IF p_PlotID IS NULL THEN
- SET p_PlotID = -1;
- END IF;
-
- SELECT COUNT(*)
- INTO expectedCount
- FROM coremeasurements cm1
- JOIN coremeasurements cm2
- ON cm1.StemID = cm2.StemID
- AND YEAR(cm2.MeasurementDate) = YEAR(cm1.MeasurementDate) + 1
- LEFT JOIN stems st2 ON cm2.StemID = st2.StemID
- LEFT JOIN quadrats q ON st2.QuadratID = q.QuadratID
- LEFT JOIN cmattributes cma
- ON cm1.CoreMeasurementID = cma.CoreMeasurementID
- LEFT JOIN attributes a
- ON cma.Code = a.Code
- WHERE (a.Status NOT IN ('dead', 'stem dead', 'broken below', 'missing', 'omitted') OR a.Status IS NULL)
- AND cm1.MeasuredDBH IS NOT NULL
- AND cm2.MeasuredDBH IS NOT NULL
- AND (cm2.MeasuredDBH - cm1.MeasuredDBH > 65)
- AND cm1.IsValidated IS TRUE
- AND cm2.IsValidated IS FALSE
- AND (p_CensusID = -1 OR q.CensusID = p_CensusID)
- AND (p_PlotID = -1 OR q.PlotID = p_PlotID);
-
- -- Fetch the ValidationErrorID for this stored procedure
- SELECT ValidationID
- INTO veID
- FROM catalog.validationprocedures
- WHERE ProcedureName = 'ValidateDBHGrowthExceedsMax';
-
- OPEN cur;
- loop1:
- LOOP
- FETCH cur INTO vCoreMeasurementID, vPrevDBH, vCurrDBH;
- IF done THEN
- LEAVE loop1;
- END IF;
-
- SET validationCriteria = 'Annual DBH Growth';
- SET measuredValue = CONCAT('Previous DBH: ', vPrevDBH, ', Current DBH: ', vCurrDBH);
- SET expectedValueRange = 'Growth <= 65';
- SET additionalDetails = 'Checked for excessive DBH growth over a year';
-
- IF vCurrDBH - vPrevDBH > 65 THEN
- SET validationResult = 0;
- SET errorMessage = 'Growth exceeds max threshold.';
- IF NOT EXISTS (SELECT 1
- FROM cmverrors
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND ValidationErrorID = veID) THEN
- INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
- VALUES (vCoreMeasurementID, veID);
- END IF;
- INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
- SET insertCount = insertCount + 1;
- ELSE
- SET validationResult = 1;
- SET errorMessage = NULL;
- END IF;
-
- INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
- ValidationOutcome, ErrorMessage,
- ValidationCriteria, MeasuredValue, ExpectedValueRange,
- AdditionalDetails)
- VALUES ('ValidateDBHGrowthExceedsMax', NOW(), vCoreMeasurementID,
- IF(validationResult, 'Passed', 'Failed'), errorMessage,
- validationCriteria, measuredValue, expectedValueRange,
- additionalDetails);
- END LOOP;
- CLOSE cur;
-
- SET successMessage =
- CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
- SELECT expectedCount AS TotalRows,
- insertCount AS FailedRows,
- successMessage AS Message;
-
- SELECT CoreMeasurementID FROM FailedValidations;
-
- DROP TEMPORARY TABLE IF EXISTS FailedValidations;
-END;
-
-create
- definer = azureroot@`%` procedure ValidateDBHShrinkageExceedsMax(IN p_CensusID int, IN p_PlotID int)
-BEGIN
- DECLARE vCoreMeasurementID INT;
- DECLARE vPrevDBH DECIMAL(10, 2);
- DECLARE vCurrDBH DECIMAL(10, 2);
- DECLARE validationResult BIT;
- DECLARE errorMessage VARCHAR(255);
- DECLARE validationCriteria TEXT;
- DECLARE measuredValue VARCHAR(255);
- DECLARE expectedValueRange VARCHAR(255);
- DECLARE additionalDetails TEXT;
- DECLARE insertCount INT DEFAULT 0;
- DECLARE expectedCount INT;
- DECLARE successMessage VARCHAR(255);
- DECLARE veID INT;
- DECLARE done INT DEFAULT FALSE;
- DECLARE cur CURSOR FOR
- SELECT cm2.CoreMeasurementID, cm1.MeasuredDBH, cm2.MeasuredDBH
- FROM coremeasurements cm1
- JOIN coremeasurements cm2
- ON cm1.StemID = cm2.StemID
- AND YEAR(cm2.MeasurementDate) = YEAR(cm1.MeasurementDate) + 1
- LEFT JOIN stems st ON cm2.StemID = st.StemID
- LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
- LEFT JOIN cmattributes cma
- ON cm1.CoreMeasurementID = cma.CoreMeasurementID
- LEFT JOIN attributes a
- ON cma.Code = a.Code
- WHERE (a.Status NOT IN ('dead', 'stem dead', 'broken below', 'missing', 'omitted') OR a.Status IS NULL)
- AND cm1.MeasuredDBH IS NOT NULL
- AND cm2.MeasuredDBH IS NOT NULL
- AND cm1.IsValidated IS TRUE
- AND cm2.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
-
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
- (
- CoreMeasurementID INT
- );
-
- IF p_CensusID IS NULL THEN
- SET p_CensusID = -1;
- END IF;
- IF p_PlotID IS NULL THEN
- SET p_PlotID = -1;
- END IF;
-
- SELECT COUNT(*)
- INTO expectedCount
- FROM coremeasurements cm1
- JOIN coremeasurements cm2
- ON cm1.StemID = cm2.StemID
- AND YEAR(cm2.MeasurementDate) = YEAR(cm1.MeasurementDate) + 1
- LEFT JOIN stems st ON cm2.StemID = st.StemID
- LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
- LEFT JOIN cmattributes cma
- ON cm1.CoreMeasurementID = cma.CoreMeasurementID
- LEFT JOIN attributes a
- ON cma.Code = a.Code
- WHERE (a.Status NOT IN ('dead', 'stem dead', 'broken below', 'missing', 'omitted') OR a.Status IS NULL)
- AND cm1.MeasuredDBH IS NOT NULL
- AND cm2.MeasuredDBH IS NOT NULL
- AND cm1.IsValidated IS TRUE
- AND cm2.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
-
- SELECT ValidationID
- INTO veID
- FROM catalog.validationprocedures
- WHERE ProcedureName = 'ValidateDBHShrinkageExceedsMax';
-
- OPEN cur;
- loop1:
- LOOP
- FETCH cur INTO vCoreMeasurementID, vPrevDBH, vCurrDBH;
- IF done THEN
- LEAVE loop1;
- END IF;
-
- SET validationCriteria = 'Annual DBH Shrinkage';
- SET measuredValue = CONCAT('Previous DBH: ', vPrevDBH, ', Current DBH: ', vCurrDBH);
- SET expectedValueRange = 'Shrinkage < 5% of previous DBH';
- SET additionalDetails = 'Checked for excessive DBH shrinkage over a year';
-
- IF vCurrDBH < vPrevDBH * 0.95 THEN
- SET validationResult = 0;
- SET errorMessage = 'Shrinkage exceeds maximum allowed threshold.';
- -- Check if the error record already exists before inserting
- IF NOT EXISTS (SELECT 1
- FROM cmverrors
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND ValidationErrorID = veID) THEN
- INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
- VALUES (vCoreMeasurementID, veID);
- END IF;
- INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
- SET insertCount = insertCount + 1;
- ELSE
- SET validationResult = 1;
- SET errorMessage = NULL;
- END IF;
-
- INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
- ValidationOutcome, ErrorMessage,
- ValidationCriteria, MeasuredValue, ExpectedValueRange,
- AdditionalDetails)
- VALUES ('ValidateDBHShrinkageExceedsMax', NOW(), vCoreMeasurementID,
- IF(validationResult, 'Passed', 'Failed'), errorMessage,
- validationCriteria, measuredValue, expectedValueRange,
- additionalDetails);
- END LOOP;
- CLOSE cur;
-
- SET successMessage =
- CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
- SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
-
- SELECT CoreMeasurementID FROM FailedValidations;
-
- DROP TEMPORARY TABLE IF EXISTS FailedValidations;
-END;
-
-create
- definer = azureroot@`%` procedure ValidateFindAllInvalidSpeciesCodes(IN p_CensusID int, IN p_PlotID int)
-BEGIN
- DECLARE vCoreMeasurementID INT;
- DECLARE vSpeciesID INT;
- DECLARE validationResult BIT;
- DECLARE errorMessage VARCHAR(255);
- DECLARE validationCriteria TEXT;
- DECLARE measuredValue VARCHAR(255);
- DECLARE expectedValueRange VARCHAR(255);
- DECLARE additionalDetails TEXT;
- DECLARE insertCount INT DEFAULT 0;
- DECLARE expectedCount INT;
- DECLARE successMessage VARCHAR(255);
- DECLARE veID INT;
- DECLARE done INT DEFAULT FALSE;
- DECLARE cur CURSOR FOR
- SELECT cm.CoreMeasurementID, sp.SpeciesID
- FROM stems s
- JOIN trees t ON s.TreeID = t.TreeID
- LEFT JOIN species sp ON t.SpeciesID = sp.SpeciesID
- JOIN coremeasurements cm ON s.StemID = cm.StemID
- LEFT JOIN quadrats q ON s.QuadratID = q.QuadratID
- WHERE sp.SpeciesID IS NULL
- AND cm.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
- GROUP BY cm.CoreMeasurementID;
-
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
- (
- CoreMeasurementID INT
- );
-
- IF p_CensusID IS NULL THEN
- SET p_CensusID = -1;
- END IF;
- IF p_PlotID IS NULL THEN
- SET p_PlotID = -1;
- END IF;
-
- SELECT COUNT(*)
- INTO expectedCount
- FROM stems s
- JOIN trees t ON s.TreeID = t.TreeID
- LEFT JOIN species sp ON t.SpeciesID = sp.SpeciesID
- JOIN coremeasurements cm ON s.StemID = cm.StemID
- LEFT JOIN quadrats q ON s.QuadratID = q.QuadratID
- WHERE sp.SpeciesID IS NULL
- AND cm.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
- GROUP BY cm.CoreMeasurementID;
-
- SELECT ValidationID
- INTO veID
- FROM catalog.validationprocedures
- WHERE ProcedureName = 'ValidateFindAllInvalidSpeciesCodes';
-
- OPEN cur;
- loop1:
- LOOP
- FETCH cur INTO vCoreMeasurementID, vSpeciesID;
- IF done THEN
- LEAVE loop1;
- END IF;
-
- SET validationCriteria = 'Species Code Validation';
- SET measuredValue = CONCAT('Species ID: ', IFNULL(vSpeciesID, 'NULL'));
- SET expectedValueRange = 'Non-null and valid Species ID';
- SET additionalDetails = 'Checking for the existence of valid species codes for each measurement.';
-
- IF vSpeciesID IS NULL THEN
- SET validationResult = 0;
- SET errorMessage = 'Invalid species code detected.';
- -- Check if the error record already exists before inserting
- IF NOT EXISTS (SELECT 1
- FROM cmverrors
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND ValidationErrorID = veID) THEN
- INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
- VALUES (vCoreMeasurementID, veID);
- END IF;
- INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
- SET insertCount = insertCount + 1;
- ELSE
- SET validationResult = 1;
- SET errorMessage = NULL;
- END IF;
-
- INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
- ValidationOutcome, ErrorMessage,
- ValidationCriteria, MeasuredValue, ExpectedValueRange,
- AdditionalDetails)
- VALUES ('ValidateFindAllInvalidSpeciesCodes', NOW(), vCoreMeasurementID,
- IF(validationResult, 'Passed', 'Failed'), errorMessage,
- validationCriteria, measuredValue, expectedValueRange,
- additionalDetails);
- END LOOP;
- CLOSE cur;
-
- SET successMessage =
- CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
- SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
-
- SELECT CoreMeasurementID FROM FailedValidations;
-
- DROP TEMPORARY TABLE IF EXISTS FailedValidations;
-END;
-
-create
- definer = azureroot@`%` procedure ValidateFindDuplicateStemTreeTagCombinationsPerCensus(IN p_CensusID int, IN p_PlotID int)
-BEGIN
- DECLARE vCoreMeasurementID INT;
- DECLARE validationResult BIT;
- DECLARE errorMessage VARCHAR(255);
- DECLARE validationCriteria TEXT;
- DECLARE measuredValue VARCHAR(255);
- DECLARE expectedValueRange VARCHAR(255);
- DECLARE additionalDetails TEXT;
- DECLARE insertCount INT DEFAULT 0;
- DECLARE expectedCount INT;
- DECLARE successMessage VARCHAR(255);
- DECLARE veID INT;
- DECLARE done INT DEFAULT FALSE;
- DECLARE cur CURSOR FOR
- SELECT SubQuery.CoreMeasurementID
- FROM (SELECT cm.CoreMeasurementID
- FROM coremeasurements cm
- INNER JOIN stems s ON cm.StemID = s.StemID
- INNER JOIN trees t ON s.TreeID = t.TreeID
- INNER JOIN quadrats q ON s.QuadratID = q.QuadratID
- WHERE (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
- AND cm.IsValidated = FALSE
- GROUP BY q.CensusID, s.StemTag, t.TreeTag, cm.CoreMeasurementID
- HAVING COUNT(*) > 1) AS SubQuery;
-
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
- (
- CoreMeasurementID INT
- );
-
- IF p_CensusID IS NULL THEN
- SET p_CensusID = -1;
- END IF;
- IF p_PlotID IS NULL THEN
- SET p_PlotID = -1;
- END IF;
-
- SELECT COUNT(*)
- INTO expectedCount
- FROM (SELECT cm.CoreMeasurementID
- FROM coremeasurements cm
- INNER JOIN stems s ON cm.StemID = s.StemID
- INNER JOIN trees t ON s.TreeID = t.TreeID
- INNER JOIN quadrats q ON s.QuadratID = q.QuadratID
- WHERE (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
- AND cm.IsValidated = FALSE
- GROUP BY q.CensusID, s.StemTag, t.TreeTag, cm.CoreMeasurementID
- HAVING COUNT(*) > 1) AS DuplicationCheck;
-
- SELECT ValidationID
- INTO veID
- FROM catalog.validationprocedures
- WHERE ProcedureName = 'ValidateFindDuplicateStemTreeTagCombinationsPerCensus';
-
-
- OPEN cur;
- loop1:
- LOOP
- FETCH cur INTO vCoreMeasurementID;
- IF done THEN
- LEAVE loop1;
- END IF;
-
- SET validationCriteria = 'Duplicate Stem-Tree Tag Combinations per Census';
- SET measuredValue = 'N/A';
- SET expectedValueRange = 'Unique Stem-Tree Tag Combinations';
- SET additionalDetails = 'Checking for duplicate stem and tree tag combinations in each census.';
-
- IF EXISTS (SELECT 1
- FROM coremeasurements cm
- INNER JOIN stems s ON cm.StemID = s.StemID
- INNER JOIN trees t ON s.TreeID = t.TreeID
- INNER JOIN quadrats q ON s.QuadratID = q.QuadratID
- WHERE cm.CoreMeasurementID = vCoreMeasurementID
- GROUP BY q.CensusID, s.StemTag, t.TreeTag
- HAVING COUNT(cm.CoreMeasurementID) > 1) THEN
- SET validationResult = 0;
- SET errorMessage = 'Duplicate stem and tree tag combination detected.';
- -- Check if the error record already exists before inserting
- IF NOT EXISTS (SELECT 1
- FROM cmverrors
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND ValidationErrorID = veID) THEN
- INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
- VALUES (vCoreMeasurementID, veID);
- END IF;
- INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
- SET insertCount = insertCount + 1;
- ELSE
- SET validationResult = 1;
- SET errorMessage = NULL;
- END IF;
-
- INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
- ValidationOutcome, ErrorMessage,
- ValidationCriteria, MeasuredValue, ExpectedValueRange,
- AdditionalDetails)
- VALUES ('ValidateFindDuplicateStemTreeTagCombinationsPerCensus', NOW(), vCoreMeasurementID,
- IF(validationResult, 'Passed', 'Failed'), errorMessage,
- validationCriteria, measuredValue, expectedValueRange,
- additionalDetails);
- END LOOP;
- CLOSE cur;
-
- SET successMessage =
- CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
- SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
-
- SELECT CoreMeasurementID FROM FailedValidations;
-
- DROP TEMPORARY TABLE IF EXISTS FailedValidations;
-END;
-
-create
- definer = azureroot@`%` procedure ValidateFindDuplicatedQuadratsByName(IN p_CensusID int, IN p_PlotID int)
-BEGIN
- DECLARE vCoreMeasurementID INT;
- DECLARE validationResult BIT;
- DECLARE errorMessage VARCHAR(255);
- DECLARE validationCriteria TEXT;
- DECLARE measuredValue VARCHAR(255);
- DECLARE expectedValueRange VARCHAR(255);
- DECLARE additionalDetails TEXT;
- DECLARE insertCount INT DEFAULT 0;
- DECLARE expectedCount INT;
- DECLARE successMessage VARCHAR(255);
- DECLARE veID INT;
- DECLARE done INT DEFAULT FALSE;
- DECLARE cur CURSOR FOR
- SELECT cm.CoreMeasurementID
- FROM quadrats q
- LEFT JOIN stems st ON q.QuadratID = st.QuadratID
- JOIN coremeasurements cm ON st.StemID = cm.StemID
- WHERE cm.IsValidated IS FALSE
- AND (q.PlotID, q.QuadratName) IN (SELECT PlotID, QuadratName
- FROM quadrats
- GROUP BY PlotID, QuadratName
- HAVING COUNT(*) > 1)
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
- GROUP BY cm.CoreMeasurementID;
-
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
- (
- CoreMeasurementID INT
- );
-
- IF p_CensusID IS NULL THEN
- SET p_CensusID = -1;
- END IF;
- IF p_PlotID IS NULL THEN
- SET p_PlotID = -1;
- END IF;
-
- SELECT COUNT(*)
- INTO expectedCount
- FROM quadrats q
- LEFT JOIN stems st ON q.QuadratID = st.QuadratID
- JOIN coremeasurements cm ON st.StemID = cm.StemID
- WHERE cm.IsValidated IS FALSE
- AND (q.PlotID, q.QuadratName) IN (SELECT PlotID, QuadratName
- FROM quadrats
- GROUP BY PlotID, QuadratName
- HAVING COUNT(*) > 1)
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
- GROUP BY cm.CoreMeasurementID;
-
- SELECT ValidationID
- INTO veID
- FROM catalog.validationprocedures
- WHERE ProcedureName = 'ValidateFindDuplicatedQuadratsByName';
-
- OPEN cur;
- loop1:
- LOOP
- FETCH cur INTO vCoreMeasurementID;
- IF done THEN
- LEAVE loop1;
- END IF;
-
- SET validationCriteria = 'Quadrat Name Duplication';
- SET measuredValue = 'N/A';
- SET expectedValueRange = 'Unique Quadrat Names per Plot';
- SET additionalDetails = 'Checking for duplicated quadrat names within the same plot.';
-
- IF EXISTS (SELECT 1
- FROM quadrats q
- WHERE q.QuadratID = vCoreMeasurementID
- AND (q.PlotID, q.QuadratName) IN (SELECT PlotID, QuadratName
- FROM quadrats
- GROUP BY PlotID, QuadratName
- HAVING COUNT(*) > 1)) THEN
- SET validationResult = 0;
- SET errorMessage = 'Duplicated quadrat name detected.';
- -- Check if the error record already exists before inserting
- IF NOT EXISTS (SELECT 1
- FROM cmverrors
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND ValidationErrorID = veID) THEN
- INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
- VALUES (vCoreMeasurementID, veID);
- END IF;
- INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
- SET insertCount = insertCount + 1;
- ELSE
- SET validationResult = 1;
- SET errorMessage = NULL;
- END IF;
-
- INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
- ValidationOutcome, ErrorMessage,
- ValidationCriteria, MeasuredValue, ExpectedValueRange,
- AdditionalDetails)
- VALUES ('ValidateFindDuplicatedQuadratsByName', NOW(), vCoreMeasurementID,
- IF(validationResult, 'Passed', 'Failed'), errorMessage,
- validationCriteria, measuredValue, expectedValueRange,
- additionalDetails);
- END LOOP;
- CLOSE cur;
-
- SET successMessage =
- CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
- SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
-
- SELECT CoreMeasurementID FROM FailedValidations;
-
- DROP TEMPORARY TABLE IF EXISTS FailedValidations;
-END;
-
-create
- definer = azureroot@`%` procedure ValidateFindMeasurementsOutsideCensusDateBoundsGroupByQuadrat(IN p_CensusID int, IN p_PlotID int)
-BEGIN
- DECLARE vCoreMeasurementID INT;
- DECLARE validationResult BIT;
- DECLARE errorMessage VARCHAR(255);
- DECLARE validationCriteria TEXT;
- DECLARE measuredValue VARCHAR(255);
- DECLARE expectedValueRange VARCHAR(255);
- DECLARE additionalDetails TEXT;
- DECLARE insertCount INT DEFAULT 0;
- DECLARE expectedCount INT;
- DECLARE successMessage VARCHAR(255);
- DECLARE veID INT;
- DECLARE done INT DEFAULT FALSE;
- DECLARE cur CURSOR FOR
- SELECT MIN(cm.CoreMeasurementID) AS CoreMeasurementID
- FROM coremeasurements cm
- JOIN stems st ON cm.StemID = st.StemID
- JOIN quadrats q ON st.QuadratID = q.QuadratID
- JOIN census c ON q.CensusID = c.CensusID
- WHERE (cm.MeasurementDate < c.StartDate OR cm.MeasurementDate > c.EndDate)
- AND cm.MeasurementDate IS NOT NULL
- AND cm.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR c.PlotID = p_PlotID)
- GROUP BY q.QuadratID, c.CensusID, c.StartDate, c.EndDate;
-
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
- (
- CoreMeasurementID INT
- );
-
- IF p_CensusID IS NULL THEN
- SET p_CensusID = -1;
- END IF;
- IF p_PlotID IS NULL THEN
- SET p_PlotID = -1;
- END IF;
-
- SELECT COUNT(*)
- INTO expectedCount
- FROM coremeasurements cm
- JOIN stems st ON cm.StemID = st.StemID
- JOIN quadrats q ON st.QuadratID = q.QuadratID
- JOIN census c ON q.CensusID = c.CensusID
- WHERE (cm.MeasurementDate < c.StartDate OR cm.MeasurementDate > c.EndDate)
- AND cm.MeasurementDate IS NOT NULL
- AND cm.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR c.PlotID = p_PlotID);
-
- SELECT ValidationID
- INTO veID
- FROM catalog.validationprocedures
- WHERE ProcedureName = 'ValidateFindMeasurementsOutsideCensusDateBoundsGroupByQuadrat';
-
-
- OPEN cur;
- loop1:
- LOOP
- FETCH cur INTO vCoreMeasurementID;
- IF done THEN
- LEAVE loop1;
- END IF;
-
- SET validationCriteria = 'Measurement Date vs Census Date Bounds';
- SET measuredValue = 'Measurement Date';
- SET expectedValueRange = 'Within Census Start and End Dates';
- SET additionalDetails =
- 'Checking if measurement dates fall within the start and end dates of their respective censuses.';
-
- IF EXISTS (SELECT 1
- FROM coremeasurements cm
- JOIN stems st ON cm.StemID = st.StemID
- JOIN quadrats q ON st.QuadratID = q.QuadratID
- JOIN census c ON q.CensusID = c.CensusID
- WHERE cm.CoreMeasurementID = vCoreMeasurementID
- AND (cm.MeasurementDate < c.StartDate OR cm.MeasurementDate > c.EndDate)) THEN
- SET validationResult = 0;
- SET errorMessage = 'Measurement outside census date bounds.';
- -- Check if the error record already exists before inserting
- IF NOT EXISTS (SELECT 1
- FROM cmverrors
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND ValidationErrorID = veID) THEN
- INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
- VALUES (vCoreMeasurementID, veID);
- END IF;
- INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
- SET insertCount = insertCount + 1;
- ELSE
- SET validationResult = 1;
- SET errorMessage = NULL;
- END IF;
-
- INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
- ValidationOutcome, ErrorMessage,
- ValidationCriteria, MeasuredValue, ExpectedValueRange,
- AdditionalDetails)
- VALUES ('ValidateFindMeasurementsOutsideCensusDateBoundsGroupByQuadrat', NOW(), vCoreMeasurementID,
- IF(validationResult, 'Passed', 'Failed'), errorMessage,
- validationCriteria, measuredValue, expectedValueRange,
- additionalDetails);
- END LOOP;
- CLOSE cur;
-
- SET successMessage =
- CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
- SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
-
- SELECT CoreMeasurementID FROM FailedValidations;
-
- DROP TEMPORARY TABLE IF EXISTS FailedValidations;
-END;
-
-create
- definer = azureroot@`%` procedure ValidateFindStemsInTreeWithDifferentSpecies(IN p_CensusID int, IN p_PlotID int)
-BEGIN
- DECLARE vCoreMeasurementID INT;
- DECLARE validationResult BIT;
- DECLARE errorMessage VARCHAR(255);
- DECLARE validationCriteria TEXT;
- DECLARE measuredValue VARCHAR(255);
- DECLARE expectedValueRange VARCHAR(255);
- DECLARE additionalDetails TEXT;
- DECLARE insertCount INT DEFAULT 0;
- DECLARE expectedCount INT;
- DECLARE successMessage VARCHAR(255);
- DECLARE veID INT;
- DECLARE done INT DEFAULT FALSE;
-
- DECLARE cur CURSOR FOR
- SELECT cm.CoreMeasurementID
- FROM coremeasurements cm
- JOIN stems s ON cm.StemID = s.StemID
- JOIN trees t ON s.TreeID = t.TreeID
- JOIN quadrats q ON s.QuadratID = q.QuadratID
- WHERE cm.IsValidated = FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
- GROUP BY t.TreeID, cm.CoreMeasurementID
- HAVING COUNT(DISTINCT t.SpeciesID) > 1;
-
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
- (
- CoreMeasurementID INT
- );
-
- IF p_CensusID IS NULL THEN
- SET p_CensusID = -1;
- END IF;
- IF p_PlotID IS NULL THEN
- SET p_PlotID = -1;
- END IF;
-
- SELECT COUNT(*)
- INTO expectedCount
- FROM coremeasurements cm
- JOIN stems s ON cm.StemID = s.StemID
- JOIN trees t ON s.TreeID = t.TreeID
- JOIN quadrats q ON s.QuadratID = q.QuadratID
- WHERE cm.IsValidated = FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
- GROUP BY t.TreeID
- HAVING COUNT(DISTINCT t.SpeciesID) > 1;
-
- SELECT ValidationID
- INTO veID
- FROM catalog.validationprocedures
- WHERE ProcedureName = 'ValidateFindStemsInTreeWithDifferentSpecies';
-
-
- OPEN cur;
- loop1:
- LOOP
- FETCH cur INTO vCoreMeasurementID;
- IF done THEN
- LEAVE loop1;
- END IF;
-
- SET validationCriteria = 'Each tree should have a consistent species across all its stems.';
- SET measuredValue = 'Species consistency across tree stems';
- SET expectedValueRange = 'One species per tree';
- SET additionalDetails = 'Checking if stems belonging to the same tree have different species IDs.';
-
- IF EXISTS (SELECT 1
- FROM stems s
- JOIN trees t ON s.TreeID = t.TreeID
- WHERE t.TreeID IN (SELECT TreeID
- FROM stems
- WHERE StemID IN
- (SELECT StemID
- FROM coremeasurements
- WHERE CoreMeasurementID = vCoreMeasurementID))
- GROUP BY t.TreeID
- HAVING COUNT(DISTINCT t.SpeciesID) > 1) THEN
- SET validationResult = 0;
- SET errorMessage = 'Stems in the same tree have different species.';
-
- -- Check if the error record already exists before inserting
- IF NOT EXISTS (SELECT 1
- FROM cmverrors
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND ValidationErrorID = veID) THEN
- INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
- VALUES (vCoreMeasurementID, veID);
- END IF;
- INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
- SET insertCount = insertCount + 1;
- ELSE
- SET validationResult = 1;
- SET errorMessage = NULL;
- END IF;
-
- INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
- ValidationOutcome, ErrorMessage,
- ValidationCriteria, MeasuredValue, ExpectedValueRange,
- AdditionalDetails)
- VALUES ('ValidateFindStemsInTreeWithDifferentSpecies', NOW(), vCoreMeasurementID,
- IF(validationResult, 'Passed', 'Failed'), errorMessage,
- validationCriteria, measuredValue, expectedValueRange,
- additionalDetails);
- END LOOP;
- CLOSE cur;
-
- SET successMessage = CONCAT('Validation completed. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
- SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
-
- SELECT CoreMeasurementID FROM FailedValidations;
-
- DROP TEMPORARY TABLE IF EXISTS FailedValidations;
-END;
-
-create
- definer = azureroot@`%` procedure ValidateFindStemsOutsidePlots(IN p_CensusID int, IN p_PlotID int)
-BEGIN
- DECLARE vCoreMeasurementID INT;
- DECLARE validationResult BIT;
- DECLARE errorMessage VARCHAR(255);
- DECLARE validationCriteria TEXT;
- DECLARE measuredValue VARCHAR(255);
- DECLARE expectedValueRange VARCHAR(255);
- DECLARE additionalDetails TEXT;
- DECLARE insertCount INT DEFAULT 0;
- DECLARE expectedCount INT;
- DECLARE successMessage VARCHAR(255);
- DECLARE veID INT;
- DECLARE done INT DEFAULT FALSE;
-
- DECLARE cur CURSOR FOR
- SELECT cm.CoreMeasurementID
- FROM stems s
- INNER JOIN coremeasurements cm ON s.StemID = cm.StemID
- INNER JOIN quadrats q ON s.QuadratID = q.QuadratID
- INNER JOIN plots p ON q.PlotID = p.PlotID
- WHERE (s.LocalX > p.DimensionX OR s.LocalX > p.DimensionY)
- AND s.LocalX IS NOT NULL
- AND s.LocalY IS NOT NULL
- AND (p.DimensionX > 0 AND p.DimensionY > 0)
- AND cm.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID)
- GROUP BY cm.CoreMeasurementID;
-
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
- (
- CoreMeasurementID INT
- );
-
- IF p_CensusID IS NULL THEN
- SET p_CensusID = -1;
- END IF;
- IF p_PlotID IS NULL THEN
- SET p_PlotID = -1;
- END IF;
-
- SELECT COUNT(*)
- INTO expectedCount
- FROM stems s
- INNER JOIN quadrats q ON s.QuadratID = q.QuadratID
- INNER JOIN plots p ON q.PlotID = p.PlotID
- INNER JOIN coremeasurements cm ON s.StemID = cm.StemID
- WHERE (s.LocalX > p.DimensionX OR s.LocalX > p.DimensionY)
- AND s.LocalX IS NOT NULL
- AND s.LocalY IS NOT NULL
- AND (p.DimensionX > 0 AND p.DimensionY > 0)
- AND cm.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
-
- SELECT ValidationID
- INTO veID
- FROM catalog.validationprocedures
- WHERE ProcedureName = 'ValidateFindStemsOutsidePlots';
-
-
- OPEN cur;
- loop1:
- LOOP
- FETCH cur INTO vCoreMeasurementID;
- IF done THEN
- LEAVE loop1;
- END IF;
-
- SET validationCriteria = 'Stem Placement within Plot Boundaries';
- SET measuredValue = 'Stem Plot Coordinates';
- SET expectedValueRange = 'Within Plot Dimensions';
- SET additionalDetails = 'Validating whether stems are located within the specified plot dimensions.';
-
- IF EXISTS (SELECT 1
- FROM stems s
- INNER JOIN quadrats q ON s.QuadratID = q.QuadratID
- INNER JOIN plots p ON q.PlotID = p.PlotID
- WHERE s.StemID IN
- (SELECT StemID
- FROM coremeasurements
- WHERE CoreMeasurementID = vCoreMeasurementID)
- AND (s.LocalX > p.DimensionX OR s.LocalY > p.DimensionY)) THEN
- SET validationResult = 0;
- SET errorMessage = 'Stem is outside plot dimensions.';
- -- Check if the error record already exists before inserting
- IF NOT EXISTS (SELECT 1
- FROM cmverrors
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND ValidationErrorID = veID) THEN
- INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
- VALUES (vCoreMeasurementID, veID);
- END IF;
- INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
- SET insertCount = insertCount + 1;
- ELSE
- SET validationResult = 1;
- SET errorMessage = NULL;
- END IF;
-
- INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
- ValidationOutcome, ErrorMessage,
- ValidationCriteria, MeasuredValue, ExpectedValueRange,
- AdditionalDetails)
- VALUES ('ValidateFindStemsOutsidePlots', NOW(), vCoreMeasurementID,
- IF(validationResult, 'Passed', 'Failed'), errorMessage,
- validationCriteria, measuredValue, expectedValueRange,
- additionalDetails);
- END LOOP;
- CLOSE cur;
-
- SET successMessage = CONCAT('Validation completed. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
- SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
-
- SELECT CoreMeasurementID FROM FailedValidations;
-
- DROP TEMPORARY TABLE IF EXISTS FailedValidations;
-END;
-
-create
- definer = azureroot@`%` procedure ValidateFindTreeStemsInDifferentQuadrats(IN p_CensusID int, IN p_PlotID int)
-BEGIN
- DECLARE vCoreMeasurementID INT;
- DECLARE validationResult BIT;
- DECLARE errorMessage VARCHAR(255);
- DECLARE validationCriteria TEXT;
- DECLARE measuredValue VARCHAR(255);
- DECLARE expectedValueRange VARCHAR(255);
- DECLARE additionalDetails TEXT;
- DECLARE insertCount INT DEFAULT 0;
- DECLARE expectedCount INT;
- DECLARE successMessage VARCHAR(255);
- DECLARE veID INT;
- DECLARE done INT DEFAULT FALSE;
-
- DECLARE cur CURSOR FOR
- SELECT cm1.CoreMeasurementID
- FROM stems s1
- JOIN stems s2 ON s1.TreeID = s2.TreeID AND s1.StemID != s2.StemID
- JOIN quadrats q1 ON s1.QuadratID = q1.QuadratID
- JOIN quadrats q2 ON s2.QuadratID = q2.QuadratID
- JOIN coremeasurements cm1 ON s1.StemID = cm1.StemID
- WHERE q1.QuadratID != q2.QuadratID
- AND cm1.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q1.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q1.PlotID = p_PlotID)
- GROUP BY cm1.CoreMeasurementID;
-
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
- (
- CoreMeasurementID INT
- );
-
- IF p_CensusID IS NULL THEN
- SET p_CensusID = -1;
- END IF;
- IF p_PlotID IS NULL THEN
- SET p_PlotID = -1;
- END IF;
-
- SELECT COUNT(*)
- INTO expectedCount
- FROM stems s1
- JOIN stems s2 ON s1.TreeID = s2.TreeID AND s1.StemID != s2.StemID
- JOIN quadrats q1 ON s1.QuadratID = q1.QuadratID
- JOIN quadrats q2 ON s2.QuadratID = q2.QuadratID
- JOIN coremeasurements cm1 ON s1.StemID = cm1.StemID
- WHERE q1.QuadratID != q2.QuadratID
- AND cm1.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q1.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q1.PlotID = p_PlotID)
- GROUP BY cm1.CoreMeasurementID;
-
- SELECT ValidationID
- INTO veID
- FROM catalog.validationprocedures
- WHERE ProcedureName = 'ValidateFindTreeStemsInDifferentQuadrats';
-
-
- OPEN cur;
- loop1:
- LOOP
- FETCH cur INTO vCoreMeasurementID;
- IF done THEN
- LEAVE loop1;
- END IF;
-
- SET validationCriteria = 'Stem Quadrat Consistency within Trees';
- SET measuredValue = 'Quadrat IDs of Stems';
- SET expectedValueRange = 'Consistent Quadrat IDs for all Stems in a Tree';
- SET additionalDetails = 'Validating that all stems within the same tree are located in the same quadrat.';
-
- IF EXISTS (SELECT 1
- FROM stems s1
- JOIN stems s2 ON s1.TreeID = s2.TreeID AND s1.StemID != s2.StemID
- JOIN quadrats q1 on q1.QuadratID = s2.QuadratID
- JOIN quadrats q2 on q2.QuadratID = s2.QuadratID
- WHERE s1.StemID IN
- (SELECT StemID
- FROM coremeasurements
- WHERE CoreMeasurementID = vCoreMeasurementID)
- AND q1.QuadratID != q2.QuadratID) THEN
- SET validationResult = 0;
- SET errorMessage = 'Stems in the same tree are in different quadrats.';
- -- Check if the error record already exists before inserting
- IF NOT EXISTS (SELECT 1
- FROM cmverrors
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND ValidationErrorID = veID) THEN
- INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
- VALUES (vCoreMeasurementID, veID);
- END IF;
- INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
- SET insertCount = insertCount + 1;
- ELSE
- SET validationResult = 1;
- SET errorMessage = NULL;
- END IF;
-
- INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
- ValidationOutcome, ErrorMessage,
- ValidationCriteria, MeasuredValue, ExpectedValueRange,
- AdditionalDetails)
- VALUES ('ValidateFindTreeStemsInDifferentQuadrats', NOW(), vCoreMeasurementID,
- IF(validationResult, 'Passed', 'Failed'), errorMessage,
- validationCriteria, measuredValue, expectedValueRange,
- additionalDetails);
- END LOOP;
- CLOSE cur;
-
- SET successMessage = CONCAT('Validation completed. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
- SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
-
- SELECT CoreMeasurementID FROM FailedValidations;
-
- DROP TEMPORARY TABLE IF EXISTS FailedValidations;
-END;
-
-create
- definer = azureroot@`%` procedure ValidateHOMUpperAndLowerBounds(IN p_CensusID int, IN p_PlotID int,
- IN minHOM decimal(10, 2), IN maxHOM decimal(10, 2))
-BEGIN
- DECLARE defaultMinHOM DECIMAL(10, 2);
- DECLARE defaultMaxHOM DECIMAL(10, 2);
- DECLARE vCoreMeasurementID INT;
- DECLARE validationResult BIT;
- DECLARE errorMessage VARCHAR(255);
- DECLARE validationCriteria TEXT;
- DECLARE measuredValue VARCHAR(255);
- DECLARE expectedValueRange VARCHAR(255);
- DECLARE additionalDetails TEXT;
- DECLARE insertCount INT DEFAULT 0;
- DECLARE expectedCount INT;
- DECLARE successMessage VARCHAR(255);
- DECLARE veID INT;
- DECLARE done INT DEFAULT FALSE;
-
- DECLARE cur CURSOR FOR
- SELECT cm.CoreMeasurementID
- FROM coremeasurements cm
- LEFT JOIN stems st ON cm.StemID = st.StemID
- LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
- WHERE (
- (minHOM IS NOT NULL AND MeasuredHOM < minHOM) OR
- (maxHOM IS NOT NULL AND MeasuredHOM > maxHOM) OR
- (minHOM IS NULL AND maxHOM IS NULL)
- )
- AND IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
-
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
- (
- CoreMeasurementID INT
- );
-
- SELECT COUNT(*)
- INTO expectedCount
- FROM coremeasurements cm
- LEFT JOIN stems st ON cm.StemID = st.StemID
- LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
- WHERE (
- (minHOM IS NOT NULL AND MeasuredHOM < minHOM) OR
- (maxHOM IS NOT NULL AND MeasuredHOM > maxHOM) OR
- (minHOM IS NULL AND maxHOM IS NULL)
- )
- AND IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
-
- SELECT ValidationID
- INTO veID
- FROM catalog.validationprocedures
- WHERE ProcedureName = 'ValidateHOMUpperAndLowerBounds';
-
-
- OPEN cur;
- loop1:
- LOOP
- FETCH cur INTO vCoreMeasurementID;
-
- IF done THEN
- LEAVE loop1;
- END IF;
-
- IF minHOM IS NULL OR maxHOM IS NULL THEN
- SELECT COALESCE(sl.LowerBound, 0) AS defaultMinHOM,
- COALESCE(sl.UpperBound, 9999) AS defaultMaxHOM
- INTO defaultMinHOM, defaultMaxHOM
- FROM specieslimits sl
- JOIN species s ON sl.SpeciesCode = s.SpeciesCode
- JOIN trees t ON s.SpeciesID = t.SpeciesID
- JOIN stems st ON t.TreeID = st.TreeID
- JOIN coremeasurements cm ON st.StemID = cm.StemID
- WHERE cm.CoreMeasurementID = vCoreMeasurementID
- AND sl.LimitType = 'HOM';
-
- SET minHOM = COALESCE(minHOM, defaultMinHOM);
- SET maxHOM = COALESCE(maxHOM, defaultMaxHOM);
- END IF;
-
- SET validationCriteria = 'HOM Measurement Range Validation';
- SET measuredValue = CONCAT('Measured HOM: ', (SELECT MeasuredHOM
- FROM coremeasurements
- WHERE CoreMeasurementID = vCoreMeasurementID));
- SET expectedValueRange = CONCAT('Expected HOM Range: ', minHOM, ' - ', maxHOM);
- SET additionalDetails = 'Checks if the measured HOM falls within the specified minimum and maximum range.';
-
- IF (SELECT MeasuredHOM
- FROM coremeasurements
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND (
- (minHOM IS NOT NULL AND MeasuredHOM < minHOM) OR
- (maxHOM IS NOT NULL AND MeasuredHOM > maxHOM) OR
- (minHOM IS NULL AND maxHOM IS NULL)
- )) THEN
- SET validationResult = 0;
- SET errorMessage = CONCAT('HOM outside bounds: ', minHOM, ' - ', maxHOM);
- INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
- SET insertCount = insertCount + 1;
- -- Check if the error record already exists before inserting
- IF NOT EXISTS (SELECT 1
- FROM cmverrors
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND ValidationErrorID = veID) THEN
- INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
- VALUES (vCoreMeasurementID, veID);
- END IF;
- ELSE
- SET validationResult = 1;
- SET errorMessage = NULL;
- END IF;
-
- INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
- ValidationOutcome, ErrorMessage,
- ValidationCriteria, MeasuredValue, ExpectedValueRange,
- AdditionalDetails)
- VALUES ('ValidateHOMUpperAndLowerBounds', NOW(), vCoreMeasurementID,
- IF(validationResult, 'Passed', 'Failed'), errorMessage,
- validationCriteria, measuredValue, expectedValueRange,
- additionalDetails);
- END LOOP;
- CLOSE cur;
-
- SET successMessage =
- CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
- SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
-
- SELECT CoreMeasurementID FROM FailedValidations;
-
- DROP TEMPORARY TABLE IF EXISTS FailedValidations;
-END;
-
-create
- definer = azureroot@`%` procedure ValidateScreenMeasuredDiameterMinMax(IN p_CensusID int, IN p_PlotID int,
- IN minDBH decimal(10, 2),
- IN maxDBH decimal(10, 2))
-BEGIN
- DECLARE defaultMinDBH DECIMAL(10, 2);
- DECLARE defaultMaxDBH DECIMAL(10, 2);
- DECLARE vCoreMeasurementID INT;
- DECLARE validationResult BIT;
- DECLARE errorMessage VARCHAR(255);
- DECLARE validationCriteria TEXT;
- DECLARE measuredValue VARCHAR(255);
- DECLARE expectedValueRange VARCHAR(255);
- DECLARE additionalDetails TEXT;
- DECLARE insertCount INT DEFAULT 0;
- DECLARE expectedCount INT;
- DECLARE successMessage VARCHAR(255);
- DECLARE veID INT;
- DECLARE done INT DEFAULT FALSE;
-
- DECLARE cur CURSOR FOR
- SELECT cm.CoreMeasurementID
- FROM coremeasurements cm
- LEFT JOIN stems st ON cm.StemID = st.StemID
- LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
- WHERE (
- (MeasuredDBH < 0) OR
- (maxDBH IS NOT NULL AND MeasuredDBH > maxDBH) OR
- (minDBH IS NULL AND maxDBH IS NULL)
- )
- AND IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
-
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
- (
- CoreMeasurementID INT
- );
-
- SELECT COUNT(*)
- INTO expectedCount
- FROM coremeasurements cm
- LEFT JOIN stems st ON cm.StemID = st.StemID
- LEFT JOIN quadrats q ON st.QuadratID = q.QuadratID
- WHERE (
- (MeasuredDBH < 0) OR
- (maxDBH IS NOT NULL AND MeasuredDBH > maxDBH) OR
- (minDBH IS NULL AND maxDBH IS NULL)
- )
- AND IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
-
- SELECT ValidationID
- INTO veID
- FROM catalog.validationprocedures
- WHERE ProcedureName = 'ValidateScreenMeasuredDiameterMinMax';
-
-
- OPEN cur;
- loop1:
- LOOP
- FETCH cur INTO vCoreMeasurementID;
-
- IF done THEN
- LEAVE loop1;
- END IF;
-
- IF minDBH IS NULL OR maxDBH IS NULL THEN
- SELECT COALESCE(sl.LowerBound, 0) AS defaultMinDBH,
- COALESCE(sl.UpperBound, 9999) AS defaultMaxDBH
- INTO defaultMinDBH, defaultMaxDBH
- FROM specieslimits sl
- JOIN species s ON sl.SpeciesCode = s.SpeciesCode
- JOIN trees t ON s.SpeciesID = t.SpeciesID
- JOIN stems st ON t.TreeID = st.TreeID
- JOIN coremeasurements cm ON st.StemID = cm.StemID
- WHERE cm.CoreMeasurementID = vCoreMeasurementID
- AND sl.LimitType = 'DBH';
-
- SET minDBH = COALESCE(minDBH, defaultMinDBH);
- SET maxDBH = COALESCE(maxDBH, defaultMaxDBH);
- END IF;
-
- SET validationCriteria = 'DBH Measurement Range Validation';
- SET measuredValue = CONCAT('Measured DBH: ', (SELECT MeasuredDBH
- FROM coremeasurements
- WHERE CoreMeasurementID = vCoreMeasurementID));
- SET expectedValueRange = CONCAT('Expected DBH Range: ', minDBH, ' - ', maxDBH);
- SET additionalDetails = 'Checks if the measured DBH falls within the specified minimum and maximum range.';
-
- IF (SELECT MeasuredDBH
- FROM coremeasurements
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND (
- (MeasuredDBH < 0) OR
- (maxDBH IS NOT NULL AND MeasuredDBH > maxDBH) OR
- (minDBH IS NULL AND maxDBH IS NULL)
- )) THEN
- SET validationResult = 0;
- SET errorMessage = CONCAT('DBH outside bounds: ', minDBH, ' - ', maxDBH);
- INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
- SET insertCount = insertCount + 1;
- -- Check if the error record already exists before inserting
- IF NOT EXISTS (SELECT 1
- FROM cmverrors
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND ValidationErrorID = veID) THEN
- INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
- VALUES (vCoreMeasurementID, veID);
- END IF;
- ELSE
- SET validationResult = 1;
- SET errorMessage = NULL;
- END IF;
-
- INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
- ValidationOutcome, ErrorMessage,
- ValidationCriteria, MeasuredValue, ExpectedValueRange,
- AdditionalDetails)
- VALUES ('ValidateScreenMeasuredDiameterMinMax', NOW(), vCoreMeasurementID,
- IF(validationResult, 'Passed', 'Failed'), errorMessage,
- validationCriteria, measuredValue, expectedValueRange,
- additionalDetails);
- END LOOP;
- CLOSE cur;
-
- SET successMessage =
- CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
- SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
-
- SELECT CoreMeasurementID FROM FailedValidations;
-
- DROP TEMPORARY TABLE IF EXISTS FailedValidations;
-END;
-
-create
- definer = azureroot@`%` procedure ValidateScreenStemsWithMeasurementsButDeadAttributes(IN p_CensusID int, IN p_PlotID int)
-BEGIN
- DECLARE vCoreMeasurementID INT;
- DECLARE validationResult BIT;
- DECLARE errorMessage VARCHAR(255);
- DECLARE validationCriteria TEXT;
- DECLARE additionalDetails TEXT;
- DECLARE insertCount INT DEFAULT 0;
- DECLARE expectedCount INT;
- DECLARE successMessage VARCHAR(255);
- DECLARE done INT DEFAULT FALSE;
- DECLARE veID INT;
- DECLARE vExistingErrorID INT;
-
- DECLARE cur CURSOR FOR
- SELECT cm.CoreMeasurementID
- FROM coremeasurements cm
- JOIN cmattributes cma ON cm.CoreMeasurementID = cma.CoreMeasurementID
- JOIN attributes a ON cma.Code = a.Code
- JOIN stems st ON cm.StemID = st.StemID
- JOIN quadrats q ON st.QuadratID = q.QuadratID
- WHERE ((cm.MeasuredDBH IS NOT NULL AND cm.MeasuredDBH > 0) OR
- (cm.MeasuredHOM IS NOT NULL AND cm.MeasuredHOM > 0))
- AND a.Status IN ('dead', 'stem dead', 'missing', 'broken below', 'omitted')
- AND cm.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
-
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- CREATE TEMPORARY TABLE IF NOT EXISTS FailedValidations
- (
- CoreMeasurementID INT
- );
-
- SELECT COUNT(*)
- INTO expectedCount
- FROM coremeasurements cm
- JOIN cmattributes cma ON cm.CoreMeasurementID = cma.CoreMeasurementID
- JOIN attributes a ON cma.Code = a.Code
- JOIN stems st ON cm.StemID = st.StemID
- JOIN quadrats q ON st.QuadratID = q.QuadratID
- WHERE ((cm.MeasuredDBH IS NOT NULL AND cm.MeasuredDBH > 0) OR
- (cm.MeasuredHOM IS NOT NULL AND cm.MeasuredHOM > 0))
- AND a.Status IN ('dead', 'stem dead', 'missing', 'broken below', 'omitted')
- AND cm.IsValidated IS FALSE
- AND (p_CensusID IS NULL OR q.CensusID = p_CensusID)
- AND (p_PlotID IS NULL OR q.PlotID = p_PlotID);
-
- SELECT ValidationID
- INTO veID
- FROM catalog.validationprocedures
- WHERE ProcedureName = 'ValidateScreenStemsWithMeasurementsButDeadAttributes';
-
-
- OPEN cur;
- loop1:
- LOOP
- FETCH cur INTO vCoreMeasurementID;
- IF done THEN
- LEAVE loop1;
- END IF;
-
- SET validationCriteria = 'Stem Measurements with Dead Attributes Validation';
- SET additionalDetails = 'Verifies that stems marked as dead do not have active measurements.';
-
- IF EXISTS (SELECT 1
- FROM cmattributes cma
- JOIN attributes a ON cma.Code = a.Code
- JOIN coremeasurements cm on cma.CoreMeasurementID = cm.CoreMeasurementID
- WHERE cma.CoreMeasurementID = vCoreMeasurementID
- AND a.Status IN ('dead', 'stem dead', 'missing', 'broken below', 'omitted')
- AND ((cm.MeasuredDBH IS NOT NULL AND cm.MeasuredDBH > 0) OR
- (cm.MeasuredHOM IS NOT NULL AND cm.MeasuredHOM > 0))) THEN
- SET validationResult = 0;
- SET errorMessage = 'Stem with measurements but dead attributes detected.';
- -- Check if the error record already exists before inserting
- IF NOT EXISTS (SELECT 1
- FROM cmverrors
- WHERE CoreMeasurementID = vCoreMeasurementID
- AND ValidationErrorID = veID) THEN
- INSERT INTO cmverrors (CoreMeasurementID, ValidationErrorID)
- VALUES (vCoreMeasurementID, veID);
- END IF;
- INSERT INTO FailedValidations (CoreMeasurementID) VALUES (vCoreMeasurementID);
- SET insertCount = insertCount + 1;
- ELSE
- SET validationResult = 1;
- SET errorMessage = NULL;
- END IF;
-
- INSERT INTO validationchangelog (ProcedureName, RunDateTime, TargetRowID,
- ValidationOutcome, ErrorMessage,
- ValidationCriteria, AdditionalDetails)
- VALUES ('ValidateScreenStemsWithMeasurementsButDeadAttributes', NOW(), vCoreMeasurementID,
- IF(validationResult, 'Passed', 'Failed'), errorMessage,
- validationCriteria, additionalDetails);
- END LOOP;
- CLOSE cur;
-
- SET successMessage =
- CONCAT('Validation completed successfully. Total rows: ', expectedCount, ', Failed rows: ', insertCount);
- SELECT expectedCount AS TotalRows, insertCount AS FailedRows, successMessage AS Message;
-
- SELECT CoreMeasurementID FROM FailedValidations;
-
- DROP TEMPORARY TABLE IF EXISTS FailedValidations;
-END;
-