QDAirPortBackend0122/sql/geofence_schema_update.sql
2026-01-22 13:19:47 +08:00

361 lines
14 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- ================================================================
-- 电子围栏功能数据库表结构更新脚本
-- 用于支持无人车电子围栏准入检测功能
-- 版本1.0
-- 创建时间2025-07-12
-- ================================================================
-- 1. 更新 airport_areas 表结构
-- 先删除旧表(如果存在)
DROP TABLE IF EXISTS "public"."airport_areas" CASCADE;
-- 创建新的机场区域表匹配Java实体类AirportArea
CREATE TABLE "public"."airport_areas" (
"id" BIGSERIAL NOT NULL,
"area_id" varchar(50) NOT NULL UNIQUE,
"name" varchar(100) NOT NULL,
"type" varchar(30) NOT NULL,
"boundary" geometry(POLYGON, 4326) NOT NULL,
"description" varchar(500),
"active_time" timestamptz,
"expiry_time" timestamptz,
"enabled" boolean DEFAULT true,
"priority" int4 DEFAULT 1,
"area_sqm" float8,
"functional_category" varchar(50),
"parent_area_id" varchar(50),
"created_at" timestamp(6) DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamp(6) DEFAULT CURRENT_TIMESTAMP,
"version" bigint DEFAULT 0,
CONSTRAINT "airport_areas_pkey" PRIMARY KEY ("id")
);
-- 表注释
COMMENT ON TABLE "public"."airport_areas" IS '机场区域信息表 - 支持电子围栏功能';
COMMENT ON COLUMN "public"."airport_areas"."id" IS '主键ID';
COMMENT ON COLUMN "public"."airport_areas"."area_id" IS '区域标识符';
COMMENT ON COLUMN "public"."airport_areas"."name" IS '区域名称';
COMMENT ON COLUMN "public"."airport_areas"."type" IS '区域类型RUNWAY、TAXIWAY、APRON等';
COMMENT ON COLUMN "public"."airport_areas"."boundary" IS '区域几何边界PostGIS多边形';
COMMENT ON COLUMN "public"."airport_areas"."description" IS '区域描述';
COMMENT ON COLUMN "public"."airport_areas"."active_time" IS '生效时间(用于临时区域)';
COMMENT ON COLUMN "public"."airport_areas"."expiry_time" IS '失效时间(用于临时区域)';
COMMENT ON COLUMN "public"."airport_areas"."enabled" IS '是否启用';
COMMENT ON COLUMN "public"."airport_areas"."priority" IS '优先级(数值越高优先级越高)';
COMMENT ON COLUMN "public"."airport_areas"."area_sqm" IS '区域面积(平方米)';
COMMENT ON COLUMN "public"."airport_areas"."functional_category" IS '功能分类';
COMMENT ON COLUMN "public"."airport_areas"."parent_area_id" IS '父区域ID';
COMMENT ON COLUMN "public"."airport_areas"."version" IS '数据版本号(用于乐观锁)';
-- 创建索引
CREATE INDEX "idx_airport_areas_area_id" ON "public"."airport_areas" ("area_id");
CREATE INDEX "idx_airport_areas_type" ON "public"."airport_areas" ("type");
CREATE INDEX "idx_airport_areas_enabled" ON "public"."airport_areas" ("enabled");
CREATE INDEX "idx_airport_areas_functional_category" ON "public"."airport_areas" ("functional_category");
CREATE INDEX "idx_airport_areas_parent_area_id" ON "public"."airport_areas" ("parent_area_id");
CREATE INDEX "idx_airport_areas_geom" ON "public"."airport_areas" USING GIST ("boundary");
-- 2. 创建空间规则表
DROP TABLE IF EXISTS "public"."spatial_rules" CASCADE;
DROP TABLE IF EXISTS "public"."spatial_rule_vehicle_types" CASCADE;
CREATE TABLE "public"."spatial_rules" (
"rule_id" varchar(50) NOT NULL,
"rule_name" varchar(200) NOT NULL,
"description" text,
"rule_category" varchar(50) NOT NULL,
"status" varchar(20) NOT NULL,
"priority" int4 NOT NULL,
"spatial_object_type" varchar(30) NOT NULL,
"spatial_object_id" varchar(50),
"rule_parameters" jsonb,
"alert_level" varchar(20) NOT NULL,
"alert_message" varchar(500),
"effective_start_time" timestamp(6),
"effective_end_time" timestamp(6),
"daily_start_time" time,
"daily_end_time" time,
"weekday_pattern" int4,
"time_patterns" jsonb,
"created_at" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" varchar(100),
"updated_by" varchar(100),
"version" bigint DEFAULT 0,
"custom_geometry" geometry,
CONSTRAINT "spatial_rules_pkey" PRIMARY KEY ("rule_id")
);
-- 创建车辆类型关联表
CREATE TABLE "public"."spatial_rule_vehicle_types" (
"rule_id" varchar(50) NOT NULL,
"vehicle_type" varchar(30) NOT NULL,
CONSTRAINT "spatial_rule_vehicle_types_pkey" PRIMARY KEY ("rule_id", "vehicle_type"),
CONSTRAINT "fk_spatial_rule_vehicle_types_rule" FOREIGN KEY ("rule_id") REFERENCES "public"."spatial_rules" ("rule_id") ON DELETE CASCADE
);
-- 表注释
COMMENT ON TABLE "public"."spatial_rules" IS '空间安全规则表';
COMMENT ON TABLE "public"."spatial_rule_vehicle_types" IS '空间规则允许的车辆类型表';
-- 创建索引
CREATE INDEX "idx_spatial_rules_status" ON "public"."spatial_rules" ("status");
CREATE INDEX "idx_spatial_rules_category" ON "public"."spatial_rules" ("rule_category");
CREATE INDEX "idx_spatial_rules_object_type" ON "public"."spatial_rules" ("spatial_object_type");
CREATE INDEX "idx_spatial_rules_priority" ON "public"."spatial_rules" ("priority");
CREATE INDEX "idx_spatial_rules_object_id" ON "public"."spatial_rules" ("spatial_object_id");
-- 3. 插入测试电子围栏区域
-- 基于route.md中两辆无人车的运行路线创建测试区域
-- 无人车A测试区域 (基于路线: 经度120.083084,纬度36.369696 到 经度120.084637,纬度36.365617)
INSERT INTO "public"."airport_areas" (
"area_id", "name", "type", "boundary", "description", "enabled", "priority",
"functional_category"
) VALUES (
'UV_TEST_AREA_A',
'无人车A测试区域',
'UNMANNED_VEHICLE_ZONE',
ST_GeomFromText('POLYGON((120.082584 36.370196, 120.085137 36.370196, 120.085137 36.365117, 120.082584 36.365117, 120.082584 36.370196))', 4326),
'无人车A运行测试区域包含起点和终点的矩形区域',
true,
5,
'UNMANNED_VEHICLE_OPERATIONS'
);
-- 无人车B测试区域 (基于路线: 经度120.086965,纬度36.368599 到 经度120.086263,纬度36.370484)
INSERT INTO "public"."airport_areas" (
"area_id", "name", "type", "boundary", "description", "enabled", "priority",
"functional_category"
) VALUES (
'UV_TEST_AREA_B',
'无人车B测试区域',
'UNMANNED_VEHICLE_ZONE',
ST_GeomFromText('POLYGON((120.085765 36.371484, 120.087465 36.371484, 120.087465 36.368099, 120.085765 36.368099, 120.085765 36.371484))', 4326),
'无人车B运行测试区域包含起点和终点的矩形区域',
true,
5,
'UNMANNED_VEHICLE_OPERATIONS'
);
-- 共同测试区域 (两辆无人车路径可能相交的区域)
INSERT INTO "public"."airport_areas" (
"area_id", "name", "type", "boundary", "description", "enabled", "priority",
"functional_category"
) VALUES (
'UV_INTERSECTION_ZONE',
'无人车交汇测试区域',
'INTERSECTION_ZONE',
ST_GeomFromText('POLYGON((120.083000 36.371000, 120.087000 36.371000, 120.087000 36.365000, 120.083000 36.365000, 120.083000 36.371000))', 4326),
'无人车路径可能相交的大型测试区域,用于测试电子围栏功能',
true,
10,
'UNMANNED_VEHICLE_OPERATIONS'
);
-- 4. 插入测试规则
-- 无人车A测试区域的准入控制规则
INSERT INTO "public"."spatial_rules" (
"rule_id", "rule_name", "description", "rule_category", "status", "priority",
"spatial_object_type", "spatial_object_id", "alert_level", "alert_message",
"rule_parameters", "created_by"
) VALUES (
'GEOFENCE_UV_AREA_A_ACCESS',
'无人车A区域准入控制',
'限制无人车A测试区域的访问权限',
'ACCESS_CONTROL',
'ACTIVE',
1,
'AREA',
'UV_TEST_AREA_A',
'WARNING',
'进入无人车A测试区域需要授权',
'{"accessControl":{"requiresPermission":true,"allowedOperationModes":["AUTONOMOUS","MANUAL"]},"physicalLimits":{"maxSpeed":20.0},"safetyRequirements":{"minBatteryLevel":30}}',
'system'
);
-- 无人车B测试区域的准入控制规则
INSERT INTO "public"."spatial_rules" (
"rule_id", "rule_name", "description", "rule_category", "status", "priority",
"spatial_object_type", "spatial_object_id", "alert_level", "alert_message",
"rule_parameters", "created_by"
) VALUES (
'GEOFENCE_UV_AREA_B_ACCESS',
'无人车B区域准入控制',
'限制无人车B测试区域的访问权限',
'ACCESS_CONTROL',
'ACTIVE',
1,
'AREA',
'UV_TEST_AREA_B',
'WARNING',
'进入无人车B测试区域需要授权',
'{"accessControl":{"requiresPermission":true,"allowedOperationModes":["AUTONOMOUS","MANUAL"]},"physicalLimits":{"maxSpeed":20.0},"safetyRequirements":{"minBatteryLevel":30}}',
'system'
);
-- 交汇区域的严格控制规则
INSERT INTO "public"."spatial_rules" (
"rule_id", "rule_name", "description", "rule_category", "status", "priority",
"spatial_object_type", "spatial_object_id", "alert_level", "alert_message",
"rule_parameters", "created_by"
) VALUES (
'GEOFENCE_INTERSECTION_CRITICAL',
'交汇区域严格控制',
'交汇区域需要严格的安全控制',
'ACCESS_CONTROL',
'ACTIVE',
10,
'AREA',
'UV_INTERSECTION_ZONE',
'CRITICAL',
'进入交汇区域需要最高级别授权',
'{"accessControl":{"requiresPermission":true,"allowedOperationModes":["MANUAL"]},"physicalLimits":{"maxSpeed":15.0},"safetyRequirements":{"minBatteryLevel":50,"requiresOperatorPresence":true}}',
'system'
);
-- 5. 插入规则允许的车辆类型
INSERT INTO "public"."spatial_rule_vehicle_types" ("rule_id", "vehicle_type") VALUES
('GEOFENCE_UV_AREA_A_ACCESS', 'UNMANNED_VEHICLE'),
('GEOFENCE_UV_AREA_B_ACCESS', 'UNMANNED_VEHICLE'),
('GEOFENCE_INTERSECTION_CRITICAL', 'UNMANNED_VEHICLE');
-- 6. 添加APRON停机坪区域和限速规则兼容原有限速检测系统
-- APRON区域
INSERT INTO "public"."airport_areas" (
"area_id", "name", "type", "boundary", "description", "enabled", "priority",
"functional_category"
) VALUES (
'APRON_01',
'停机坪区域01',
'APRON',
ST_GeomFromText('POLYGON((120.080000 36.372000, 120.088000 36.372000, 120.088000 36.366000, 120.080000 36.366000, 120.080000 36.372000))', 4326),
'主要停机坪区域覆盖无人车和航空器活动区域包含route.md中所有测试路线',
true,
8,
'AIRCRAFT_OPERATIONS'
);
-- 停机坪限速规则
INSERT INTO "public"."spatial_rules" (
"rule_id", "rule_name", "description", "rule_category", "status", "priority",
"spatial_object_type", "spatial_object_id", "alert_level", "alert_message",
"rule_parameters", "created_by"
) VALUES (
'SPEED_LIMIT_APRON',
'停机坪限速规则',
'停机坪区域内所有车辆的限速控制规则',
'SPEED_LIMIT',
'ACTIVE',
1,
'AREA',
'APRON_01',
'WARNING',
'停机坪内超速行驶',
'{"maxSpeed":15.0,"unit":"kmh","warningThreshold":0.8,"strictMode":true}',
'system'
);
-- 停机坪限速规则的车辆类型(所有类型车辆都受限速规则约束)
INSERT INTO "public"."spatial_rule_vehicle_types" ("rule_id", "vehicle_type") VALUES
('SPEED_LIMIT_APRON', 'UNMANNED_VEHICLE'),
('SPEED_LIMIT_APRON', 'AIRCRAFT'),
('SPEED_LIMIT_APRON', 'SPECIAL_VEHICLE'),
('SPEED_LIMIT_APRON', 'AIRPORT_VEHICLE'),
('SPEED_LIMIT_APRON', 'NORMAL_VEHICLE');
-- 7. 添加滑行道区域和限速规则
INSERT INTO "public"."airport_areas" (
"area_id", "name", "type", "boundary", "description", "enabled", "priority",
"functional_category"
) VALUES (
'TAXIWAY_ALPHA',
'滑行道Alpha',
'TAXIWAY',
ST_GeomFromText('POLYGON((120.082000 36.370000, 120.086000 36.370000, 120.086000 36.368000, 120.082000 36.368000, 120.082000 36.370000))', 4326),
'主要滑行道,连接停机坪和跑道',
true,
7,
'AIRCRAFT_OPERATIONS'
);
-- 滑行道限速规则
INSERT INTO "public"."spatial_rules" (
"rule_id", "rule_name", "description", "rule_category", "status", "priority",
"spatial_object_type", "spatial_object_id", "alert_level", "alert_message",
"rule_parameters", "created_by"
) VALUES (
'SPEED_LIMIT_TAXIWAY',
'滑行道限速规则',
'滑行道区域内的限速控制',
'SPEED_LIMIT',
'ACTIVE',
2,
'AREA',
'TAXIWAY_ALPHA',
'WARNING',
'滑行道内超速行驶',
'{"maxSpeed":25.0,"unit":"kmh","warningThreshold":0.9}',
'system'
);
-- 滑行道限速规则的车辆类型
INSERT INTO "public"."spatial_rule_vehicle_types" ("rule_id", "vehicle_type") VALUES
('SPEED_LIMIT_TAXIWAY', 'UNMANNED_VEHICLE'),
('SPEED_LIMIT_TAXIWAY', 'AIRCRAFT'),
('SPEED_LIMIT_TAXIWAY', 'SPECIAL_VEHICLE'),
('SPEED_LIMIT_TAXIWAY', 'AIRPORT_VEHICLE');
-- 8. 创建限速检测视图
CREATE OR REPLACE VIEW speed_limit_areas AS
SELECT
aa.area_id,
aa.name as area_name,
aa.type as area_type,
aa.boundary,
sr.rule_id,
sr.rule_name,
(sr.rule_parameters->>'maxSpeed')::float as max_speed_kmh,
(sr.rule_parameters->>'warningThreshold')::float as warning_threshold,
sr.alert_level,
array_agg(DISTINCT vt.vehicle_type) as applicable_vehicle_types
FROM airport_areas aa
JOIN spatial_rules sr ON aa.area_id = sr.spatial_object_id
JOIN spatial_rule_vehicle_types vt ON sr.rule_id = vt.rule_id
WHERE sr.rule_category = 'SPEED_LIMIT' AND sr.status = 'ACTIVE' AND aa.enabled = true
GROUP BY aa.area_id, aa.name, aa.type, aa.boundary, sr.rule_id, sr.rule_name,
sr.rule_parameters, sr.alert_level;
-- 9. 更新序列值(如果需要)
SELECT setval('airport_areas_id_seq', (SELECT COALESCE(MAX(id), 1) FROM airport_areas));
-- 10. 验证数据插入
SELECT
area_id,
name,
type,
enabled,
priority,
ST_AsText(boundary) as boundary_wkt,
created_at
FROM airport_areas
WHERE area_id IN ('UV_TEST_AREA_A', 'UV_TEST_AREA_B', 'UV_INTERSECTION_ZONE', 'APRON_01', 'TAXIWAY_ALPHA')
ORDER BY priority DESC;
SELECT
rule_id,
rule_name,
rule_category,
status,
spatial_object_id,
alert_level,
created_at
FROM spatial_rules
WHERE rule_id LIKE 'GEOFENCE_%' OR rule_id LIKE 'SPEED_LIMIT_%'
ORDER BY rule_category, rule_id;
-- 11. 验证限速检测视图
SELECT * FROM speed_limit_areas ORDER BY max_speed_kmh;
-- 完成
SELECT 'Database schema updated successfully for geofence functionality!' as status;