227 lines
9.3 KiB
SQL
227 lines
9.3 KiB
SQL
CREATE EXTENSION IF NOT EXISTS postgis;
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_dataset (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
source_type VARCHAR(16) NOT NULL DEFAULT 'CM93',
|
|
name VARCHAR(255) NOT NULL,
|
|
source_root TEXT NOT NULL,
|
|
source_fingerprint CHAR(64),
|
|
parser_version VARCHAR(32) NOT NULL,
|
|
normalized_srid INTEGER NOT NULL DEFAULT 4326,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_dataset_source_type ON chart_dataset(source_type);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_dictionary_object (
|
|
dataset_id BIGINT NOT NULL REFERENCES chart_dataset(id) ON DELETE CASCADE,
|
|
object_class_id SMALLINT NOT NULL,
|
|
object_class VARCHAR(16) NOT NULL,
|
|
geometry_code VARCHAR(8),
|
|
display_code VARCHAR(8),
|
|
description VARCHAR(255),
|
|
raw_line TEXT NOT NULL,
|
|
PRIMARY KEY (dataset_id, object_class_id)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_dict_object_class ON chart_dictionary_object(object_class);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_dictionary_attribute (
|
|
dataset_id BIGINT NOT NULL REFERENCES chart_dataset(id) ON DELETE CASCADE,
|
|
attribute_id SMALLINT NOT NULL,
|
|
attribute_name VARCHAR(16) NOT NULL,
|
|
source_type_name VARCHAR(32) NOT NULL,
|
|
decoder_type CHAR(1) NOT NULL,
|
|
min_value DOUBLE PRECISION,
|
|
max_value DOUBLE PRECISION,
|
|
raw_line TEXT NOT NULL,
|
|
PRIMARY KEY (dataset_id, attribute_id)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_dict_attribute_name ON chart_dictionary_attribute(attribute_name);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_cell (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
dataset_id BIGINT NOT NULL REFERENCES chart_dataset(id) ON DELETE CASCADE,
|
|
source_relative_path VARCHAR(1024) NOT NULL,
|
|
source_file_name VARCHAR(255) NOT NULL,
|
|
source_size BIGINT NOT NULL,
|
|
source_sha256 CHAR(64),
|
|
scale_code CHAR(1) NOT NULL,
|
|
native_scale INTEGER NOT NULL,
|
|
cell_name VARCHAR(64) NOT NULL,
|
|
prolog_word0 INTEGER,
|
|
table1_length BIGINT,
|
|
table2_length BIGINT,
|
|
easting_min DOUBLE PRECISION,
|
|
northing_min DOUBLE PRECISION,
|
|
easting_max DOUBLE PRECISION,
|
|
northing_max DOUBLE PRECISION,
|
|
bbox_min_lon DOUBLE PRECISION,
|
|
bbox_min_lat DOUBLE PRECISION,
|
|
bbox_max_lon DOUBLE PRECISION,
|
|
bbox_max_lat DOUBLE PRECISION,
|
|
vector_record_count INTEGER,
|
|
vector_point_count BIGINT,
|
|
point2d_count INTEGER,
|
|
point3d_count INTEGER,
|
|
feature_count INTEGER,
|
|
attribute_count BIGINT,
|
|
import_status VARCHAR(16) NOT NULL DEFAULT 'DISCOVERED'
|
|
CHECK (import_status IN ('DISCOVERED','IMPORTING','DONE','FAILED')),
|
|
error_message TEXT,
|
|
imported_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE (dataset_id, source_relative_path)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_cell_scale ON chart_cell(dataset_id, scale_code);
|
|
CREATE INDEX IF NOT EXISTS idx_cell_status ON chart_cell(dataset_id, import_status);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_coverage (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
dataset_id BIGINT NOT NULL REFERENCES chart_dataset(id) ON DELETE CASCADE,
|
|
cell_id BIGINT NOT NULL REFERENCES chart_cell(id) ON DELETE CASCADE,
|
|
source_record_index INTEGER NOT NULL,
|
|
object_class_id SMALLINT NOT NULL,
|
|
compilation_scale INTEGER,
|
|
horizontal_datum INTEGER,
|
|
vertical_datum INTEGER,
|
|
wgsox DOUBLE PRECISION,
|
|
wgsoy DOUBLE PRECISION,
|
|
attributes_json JSONB,
|
|
geom geometry(Geometry,4326) NOT NULL,
|
|
geometry_repaired BOOLEAN NOT NULL DEFAULT FALSE,
|
|
geometry_issue VARCHAR(255),
|
|
UNIQUE (cell_id, source_record_index)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_cov_cell ON chart_coverage(cell_id);
|
|
CREATE INDEX IF NOT EXISTS spx_cov_geom ON chart_coverage USING GIST(geom);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_feature (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
dataset_id BIGINT NOT NULL REFERENCES chart_dataset(id) ON DELETE CASCADE,
|
|
cell_id BIGINT NOT NULL REFERENCES chart_cell(id) ON DELETE CASCADE,
|
|
coverage_id BIGINT REFERENCES chart_coverage(id) ON DELETE SET NULL,
|
|
source_record_index INTEGER NOT NULL,
|
|
object_class_id SMALLINT,
|
|
object_class VARCHAR(16) NOT NULL,
|
|
geometry_type VARCHAR(16) NOT NULL
|
|
CHECK (geometry_type IN ('POINT','LINE','AREA','SOUNDING','META','UNKNOWN')),
|
|
scale_code CHAR(1) NOT NULL,
|
|
native_scale INTEGER NOT NULL,
|
|
raw_geotype SMALLINT,
|
|
normalized_srid INTEGER NOT NULL DEFAULT 4326,
|
|
bbox_min_lon DOUBLE PRECISION,
|
|
bbox_min_lat DOUBLE PRECISION,
|
|
bbox_max_lon DOUBLE PRECISION,
|
|
bbox_max_lat DOUBLE PRECISION,
|
|
attributes_json JSONB,
|
|
raw_feature_blob BYTEA,
|
|
raw_attribute_blob BYTEA,
|
|
geometry_repaired BOOLEAN NOT NULL DEFAULT FALSE,
|
|
geometry_issue VARCHAR(255),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE (cell_id, source_record_index)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_feature_class ON chart_feature(dataset_id, object_class);
|
|
CREATE INDEX IF NOT EXISTS idx_feature_scale ON chart_feature(dataset_id, native_scale);
|
|
CREATE INDEX IF NOT EXISTS idx_feature_cell ON chart_feature(cell_id);
|
|
CREATE INDEX IF NOT EXISTS idx_feature_coverage ON chart_feature(coverage_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_feature_attribute (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
feature_id BIGINT NOT NULL REFERENCES chart_feature(id) ON DELETE CASCADE,
|
|
ordinal_no SMALLINT NOT NULL,
|
|
attribute_id SMALLINT NOT NULL,
|
|
attribute_name VARCHAR(16) NOT NULL,
|
|
value_type VARCHAR(16) NOT NULL
|
|
CHECK (value_type IN ('BYTE','INT','LONG','REAL','WORD10','STRING','LIST','COMPLEX','UNKNOWN')),
|
|
value_int BIGINT,
|
|
value_real DOUBLE PRECISION,
|
|
value_text TEXT,
|
|
value_json JSONB,
|
|
raw_value_blob BYTEA,
|
|
UNIQUE (feature_id, ordinal_no)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_feature_attr_name ON chart_feature_attribute(attribute_name);
|
|
CREATE INDEX IF NOT EXISTS idx_feature_attr_id ON chart_feature_attribute(attribute_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_point_geometry (
|
|
feature_id BIGINT PRIMARY KEY REFERENCES chart_feature(id) ON DELETE CASCADE,
|
|
geom geometry(Point,4326) NOT NULL
|
|
);
|
|
CREATE INDEX IF NOT EXISTS spx_point_geom ON chart_point_geometry USING GIST(geom);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_line_geometry (
|
|
feature_id BIGINT PRIMARY KEY REFERENCES chart_feature(id) ON DELETE CASCADE,
|
|
geom geometry(Geometry,4326) NOT NULL
|
|
);
|
|
CREATE INDEX IF NOT EXISTS spx_line_geom ON chart_line_geometry USING GIST(geom);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_area_geometry (
|
|
feature_id BIGINT PRIMARY KEY REFERENCES chart_feature(id) ON DELETE CASCADE,
|
|
geom geometry(Geometry,4326) NOT NULL
|
|
);
|
|
CREATE INDEX IF NOT EXISTS spx_area_geom ON chart_area_geometry USING GIST(geom);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_sounding_point (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
feature_id BIGINT NOT NULL REFERENCES chart_feature(id) ON DELETE CASCADE,
|
|
point_index INTEGER NOT NULL,
|
|
raw_x BIGINT NOT NULL,
|
|
raw_y BIGINT NOT NULL,
|
|
raw_z BIGINT NOT NULL,
|
|
depth DOUBLE PRECISION NOT NULL,
|
|
geom geometry(Point,4326) NOT NULL,
|
|
UNIQUE (feature_id, point_index)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_sounding_depth ON chart_sounding_point(depth);
|
|
CREATE INDEX IF NOT EXISTS spx_sounding_geom ON chart_sounding_point USING GIST(geom);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_raw_record (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
cell_id BIGINT NOT NULL REFERENCES chart_cell(id) ON DELETE CASCADE,
|
|
record_kind VARCHAR(16) NOT NULL
|
|
CHECK (record_kind IN ('HEADER','VECTOR','POINT2D','POINT3D','FEATURE','ATTRIBUTE','OTHER')),
|
|
source_record_index INTEGER NOT NULL DEFAULT 0,
|
|
raw_blob BYTEA NOT NULL,
|
|
raw_metadata_json JSONB
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_raw_cell_kind
|
|
ON chart_raw_record(cell_id, record_kind, source_record_index);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_import_job (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
dataset_id BIGINT NOT NULL REFERENCES chart_dataset(id) ON DELETE CASCADE,
|
|
status VARCHAR(16) NOT NULL DEFAULT 'RUNNING'
|
|
CHECK (status IN ('RUNNING','DONE','FAILED','CANCELLED')),
|
|
started_at TIMESTAMPTZ NOT NULL,
|
|
finished_at TIMESTAMPTZ,
|
|
cells_discovered INTEGER NOT NULL DEFAULT 0,
|
|
cells_done INTEGER NOT NULL DEFAULT 0,
|
|
cells_failed INTEGER NOT NULL DEFAULT 0,
|
|
features_source BIGINT NOT NULL DEFAULT 0,
|
|
features_imported BIGINT NOT NULL DEFAULT 0,
|
|
attributes_source BIGINT NOT NULL DEFAULT 0,
|
|
attributes_imported BIGINT NOT NULL DEFAULT 0,
|
|
unknown_object_count BIGINT NOT NULL DEFAULT 0,
|
|
unknown_attribute_count BIGINT NOT NULL DEFAULT 0,
|
|
geometry_invalid_count BIGINT NOT NULL DEFAULT 0,
|
|
geometry_repaired_count BIGINT NOT NULL DEFAULT 0,
|
|
summary_json JSONB
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_job_dataset ON chart_import_job(dataset_id, started_at);
|
|
|
|
CREATE TABLE IF NOT EXISTS chart_import_event (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
job_id BIGINT REFERENCES chart_import_job(id) ON DELETE CASCADE,
|
|
cell_id BIGINT REFERENCES chart_cell(id) ON DELETE CASCADE,
|
|
level VARCHAR(16) NOT NULL CHECK (level IN ('DEBUG','INFO','WARNING','ERROR')),
|
|
event_code VARCHAR(64) NOT NULL,
|
|
message TEXT NOT NULL,
|
|
details_json JSONB,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_event_job ON chart_import_event(job_id, id);
|
|
CREATE INDEX IF NOT EXISTS idx_event_cell ON chart_import_event(cell_id, id);
|
|
CREATE INDEX IF NOT EXISTS idx_event_code ON chart_import_event(event_code);
|