GLE-Postgis-BLPS: Unterschied zwischen den Versionen

Aus kvwmap
Wechseln zu: Navigation, Suche
(Die Seite wurde neu angelegt: „ #!/bin/bash DOCKER='docker exec -i pgsql' PGHOST='-h pgsql' PGPORT='-p 5432' PGDATABASE='-d xxxxxx' PGUSER='-U xxxxxx' PGOPTIONS='-v ON_ERROR_STOP=ON'…“)
(kein Unterschied)

Version vom 23. Oktober 2023, 09:38 Uhr

#!/bin/bash

DOCKER='docker exec -i pgsql'
PGHOST='-h pgsql'
PGPORT='-p 5432'
PGDATABASE='-d xxxxxx'
PGUSER='-U xxxxxx'
PGOPTIONS='-v ON_ERROR_STOP=ON'

PSQL="${DOCKER} psql ${PGHOST} ${PGPORT} ${PGDATABASE} ${PGUSER} ${PGOPTIONS}"

pgConnection="PG:host='pgsql' port='5432' user='xxxxxx' dbname='xxxxxx' password='xxxxxx'"
schema="xplan"

# 17000 = User-ID im gdal-Container
OGR2OGR="docker exec --user 17000 -i gdal ogr2ogr"

wfsURL="https://bauleitplaene-mv.de/dienste/basic?version=2.0.0&"
getFeature="service=WFS&request=GetFeature&srsname=EPSG:25833&typename="
featureTypes=("B_Plan" "F_Plan")

xplanURL="https://xleitstelle.de/downloads/xplanung/releases/"
xPlanV="${xplanURL}XPlanung Version 5.4/XPlanGML_5_4_Enumerationen_XML-Dictionary.XML"
blpMVURL="https://bauleitplaene-mv.de/codelist/"


################################################################################
############################## Schema-Definition ###############################
################################################################################
${PSQL} <<-SQL
		SELECT to_regnamespace('${schema}') IS NULL AS createschema

		\gset

		\if :createschema

			BEGIN;

			CREATE SCHEMA "${schema}";
  
			/*
			 *  Data Type xplan:...
			 */
			CREATE TYPE "${schema}".xp_begruendungabschnitt AS (
			  schluessel text,
			  "text" text);

			CREATE TYPE "${schema}".xp_gemeinde AS (
			  ags text,
			  rs text,
			  gemeindename text,
			  ortsteilname text);

			CREATE TYPE "${schema}".xp_generattribut AS (
			  "name" text);

			CREATE TYPE "${schema}".xp_plangeber AS (
			  "name" text,
			  kennziffer text);

			CREATE TYPE "${schema}".xp_spezexternereferenz AS (
			  georefurl text,
			  art text,
			  referenzname text,
			  referenzurl text,
			  beschreibung text,
			  datum date,
			  typ text);

			CREATE TYPE "${schema}".xp_textabschnitt AS (
			  schluessel text,
			  gesetzlichegrundlage text,
			  "text" text);

			CREATE TYPE "${schema}".xp_verbundenerplan AS (
			  planname text,
			  rechtscharakter text,
			  nummer text,
			  verbundenerplan text);

			CREATE TYPE "${schema}".xp_verfahrensmerkmal AS (
			  vermerk text,
			  datum date,
			  signatur text,
			  signiert bool);

			/*
			 *  Feature Type xplan:...
			 */
			CREATE TABLE "${schema}".bp_plan (
			  gml_id text NOT NULL,
			  "name" text NULL,
			  nummer text NULL,
			  planart text[] NULL,
			  sonstplanart text NULL,
			  gemeinde "${schema}".xp_gemeinde[] NULL,
			  rechtsstand text NULL,
			  verfahren text NULL,
			  externereferenz "${schema}".xp_spezexternereferenz[] NULL,
			  texte "${schema}".xp_textabschnitt[] NULL,
			  begruendungstexte "${schema}".xp_begruendungabschnitt[] NULL,
			  beschreibung text NULL,
			  kommentar text NULL,
			  plangeber "${schema}".xp_plangeber NULL,
			  planaufstellendegemeinde "${schema}".xp_gemeinde[] NULL,
			  internalid text NULL,
			  status text NULL,
			  aufstellungsbeschlussdatum date NULL,
			  technherstelldatum date NULL,
			  ausfertigungsdatum date NULL,
			  traegerbeteiligungsstartdatum date[] NULL,
			  traegerbeteiligungsenddatum date[] NULL,
			  auslegungsstartdatum date[] NULL,
			  auslegungsenddatum date[] NULL,
			  aenderungenbisdatum date NULL,
			  genehmigungsdatum date NULL,
			  inkrafttretensdatum date NULL,
			  rechtsverordnungsdatum date NULL,
			  satzungsbeschlussdatum date NULL,
			  veraenderungssperre bool NULL,
			  veraenderungssperredatum date NULL,
			  untergangsdatum date NULL,
			  erschliessungsvertrag bool NULL,
			  durchfuehrungsvertrag bool NULL,
			  staedtebaulichervertrag bool NULL,
			  gruenordnungsplan bool NULL,
			  erstellungsmassstab int NULL,
			  bezugshoehe numeric NULL,
			  hoehenbezug text NULL,
			  verfahrensmerkmale "${schema}".xp_verfahrensmerkmal[] NULL,
			  hatgenerattribut "${schema}".xp_generattribut[] NULL,
			  aendert "${schema}".xp_verbundenerplan[] NULL,
			  wurdegeaendertvon "${schema}".xp_verbundenerplan[] NULL,
			  raeumlichergeltungsbereich geometry(multipolygon, 25833) NOT NULL);
  
			CREATE TABLE "${schema}".fp_plan (
			  gml_id text NOT NULL,
			  "name" text NULL,
			  nummer text NULL,
			  planart text NOT NULL,
			  sonstplanart text NULL,
			  gemeinde "${schema}".xp_gemeinde[] NOT NULL,
			  rechtsstand text NULL,
			  verfahren text NULL,
			  externereferenz "${schema}".xp_spezexternereferenz[] NULL,
			  texte "${schema}".xp_textabschnitt[] NULL,
			  begruendungstexte "${schema}".xp_begruendungabschnitt[] NULL,
			  beschreibung text NULL,
			  kommentar text NULL,
			  plangeber "${schema}".xp_plangeber NULL,
			  planaufstellendegemeinde "${schema}".xp_gemeinde[] NULL,
			  internalid text NULL,
			  status text NULL,
			  entwurfsbeschlussdatum date NULL,
			  aufstellungsbeschlussdatum date NULL,
			  technherstelldatum date NULL,
			  traegerbeteiligungsstartdatum date[] NULL,
			  traegerbeteiligungsenddatum date[] NULL,
			  auslegungsstartdatum date[] NULL,
			  auslegungsenddatum date[] NULL,
			  aenderungenbisdatum date NULL,
			  planbeschlussdatum date NULL,
			  genehmigungsdatum date NULL,
			  wirksamkeitsdatum date NULL,
			  untergangsdatum date NULL,
			  erstellungsmassstab int NULL,
			  bezugshoehe numeric NULL,
			  verfahrensmerkmale "${schema}".xp_verfahrensmerkmal[] NULL,
			  sachgebiet text NULL,
			  hatgenerattribut "${schema}".xp_generattribut[] NULL,
			  aendert "${schema}".xp_verbundenerplan[] NULL,
			  wurdegeaendertvon "${schema}".xp_verbundenerplan[] NULL,
			  raeumlichergeltungsbereich geometry(multipolygon, 25833) NOT NULL);
  
			/*
			 *  Enumerationen xplan:...
			 */
			SELECT format(
			         'CREATE TABLE %I.%I (wert text, beschreibung text, dokumentation text);',
			         '${schema}',
			         relname
			       )
			  FROM (
			        VALUES ('bp_planart'::text), ('bp_rechtsstand'), ('bp_verfahren'),
			               ('fp_planart'), ('fp_rechtsstand'), ('fp_verfahren'),
			               ('xp_externerefernztyp'), ('xp_rechtscharakterplanaenderung')
			        ) AS v (relname)

			\gexec

			/*
			 *  Enumerationen externe Codelisten
			 */
			SELECT format(
			         'CREATE TABLE %I.%I (wert text, beschreibung text);',
			         '${schema}',
			         relname
			       )
			  FROM (
			        VALUES ('bp_sonstplanart'::text),
			               ('bp_status'),
			               -- ('fp_sonstplanart'),
			               ('fp_status')
			       ) AS v (relname)

			\gexec
			
			COMMIT;
			
		\else
			
			\q
			
		\endif
	SQL
################################################################################
###################### Download der Pläne und Codelisten #######################
################################################################################
${OGR2OGR} -f PostgreSQL \
			  "${pgConnection}" \
			  "WFS:${wfsURL}${getFeature}ms:B_Plan" \
			  -oo EXPOSE_GML_ID=NO \
			  -nln "${schema}.bp_plan_tmp" \
			  -lco UNLOGGED=ON \
			  -lco OVERWRITE=YES \
			  -lco GEOMETRY_NAME=wkb_geometry \
			  -lco SPATIAL_INDEX=GIST \
			  -forceNullable \
			  --config PG_USE_COPY YES \
			  --config OGR_TRUNCATE YES &

${OGR2OGR} -f PostgreSQL \
			  "${pgConnection}" \
			  "WFS:${wfsURL}${getFeature}ms:F_Plan" \
			  -oo EXPOSE_GML_ID=NO \
			  -nln "${schema}.fp_plan_tmp" \
			  -lco UNLOGGED=ON \
			  -lco OVERWRITE=YES \
			  -lco GEOMETRY_NAME=wkb_geometry \
			  -lco SPATIAL_INDEX=GIST \
			  -forceNullable \
			  --config PG_USE_COPY YES \
			  --config OGR_TRUNCATE YES &

wait

xplanDict=$(wget -q -O "-" "${xPlanV}" | tail -n +2)
bp_sonstplanartDict=$(wget -q -O "-" "${blpMVURL}BP_SonstPlanArt/BP_SonstPlanArt.xml" | tail -n +2)
bp_statusDict=$(wget -q -O "-" "${blpMVURL}BP_Status/BP_Status.xml" | tail -n +2)
#fp_sonstplanartDict=$(wget -q -O "-" "${blpMVURL}FP_SonstPlanArt/FP_SonstPlanArt.xml" | tail -n +2)
fp_statusDict=$(wget -q -O "-" "${blpMVURL}FP_Status/FP_Status.xml" | tail -n +2)
################################################################################
######################### Daten einlesen und bereinigen ########################
################################################################################
formString1=$( cat <<-SQL
		INSERT INTO "${schema}".%I
		SELECT split_part(xt.wert, ':', 2) AS wert,
		       xt.beschreibung,
		       trim(xt.dokumentation, E'\n') AS dokumentation
		  FROM xp_dictionary,
		       xmltable(
		         xmlnamespaces(
		           'http://www.opengis.net/gml/3.2' AS xmlns,
		           'http://www.w3.org/2001/XMLSchema-instance' AS xsi,
		           'http://www.opengis.net/gml/3.2' AS gml
		         ),
		         '/xmlns:Dictionary/xmlns:dictionaryEntry/xmlns:DefinitionCollection[@gml:id="%s"]/xmlns:definitionMember'
		         PASSING d
		         COLUMNS wert text PATH 'xmlns:Definition/xmlns:identifier',
		                 beschreibung text PATH 'xmlns:Definition/xmlns:name',
		                 dokumentation text PATH 'xmlns:Definition/xmlns:description'
		       ) xt;
	SQL
)

formString2=$( cat <<-SQL
		INSERT INTO "${schema}".%I
		SELECT xt.*
		  FROM xmltable(
		         xmlnamespaces(
		           'http://www.opengis.net/gml/3.1.1' AS xmlns,
		           'http://www.opengis.net/gml/3.1.1' AS gml
		         ),
		         '/xmlns:Dictionary/gml:DictionaryEntry'
		         PASSING xmlparse(document %L)
		         COLUMNS wert text PATH 'gml:Definition/gml:identifier',
		                 beschreibung text PATH 'gml:Definition/gml:name'
		       ) xt;
	SQL
)

${PSQL} <<-SQL
		BEGIN;
		
		-- Tabellen leeren (außer die zuvor importierten)
		SELECT 'TRUNCATE TABLE '
		       || string_agg(format('%I.%I', '${schema}', relname), ', ')
		       || ';'
		  FROM pg_catalog.pg_class
		 WHERE (relnamespace, relkind, relpersistence) = ('${schema}'::regnamespace, 'r', 'p')
		
		\gexec
		
		-- Indizes löschen (außer die zuvor importierten)
		SELECT format('DROP INDEX IF EXISTS %I.%I', relnamespace::regnamespace, relname)
		  FROM pg_catalog.pg_class
		 WHERE (relnamespace, relkind, relpersistence) = ('${schema}'::regnamespace, 'i', 'p')
		
		\gexec
		
		-- Enumerations-Tabellen füllen
		CREATE TEMP TABLE xp_dictionary AS
		SELECT xmlparse(document \$\$${xplanDict}\$\$) AS d\;
		
		SELECT format(\$\$${formString1}\$\$, relname, enumeration)
		  FROM (
		        VALUES ('bp_planart'::text, 'BP_PlanArt'::text),
		               ('bp_rechtsstand', 'BP_Rechtsstand'),
		               ('bp_verfahren', 'BP_Verfahren'),
		               ('fp_planart', 'FP_PlanArt'),
		               ('fp_rechtsstand', 'FP_Rechtsstand'),
		               ('fp_verfahren', 'FP_Verfahren'),
		               ('xp_externerefernztyp', 'XP_ExterneReferenzTyp'),
		               ('xp_rechtscharakterplanaenderung', 'XP_RechtscharakterPlanaenderung')
		       ) AS v (relname, enumeration)
		
		\gexec
		
		-- Codelisten-Tabellen füllen
		SELECT format(\$\$${formString2}\$\$, relname, enumeration)
		  FROM (
		        VALUES ('bp_sonstplanart'::text, \$\$${bp_sonstplanartDict}\$\$::text),
		               ('bp_status', \$\$${bp_statusDict}\$\$),
		               --('fp_sonstplanart'::text, \$\$${fp_sonstplanartDict}\$\$),
		               ('fp_status', \$\$${fp_statusDict}\$\$)
		       ) AS v (relname, enumeration)
		
		\gexec
		
		/*
		 *  BP_Plan
		 */
		CREATE TEMP TABLE bp_plan_13073 AS
		SELECT DISTINCT ON (a.gml_id)
		       a.*
		  FROM "${schema}".bp_plan_tmp a
		       JOIN alkis_eigen.pp_kreis AS b
		         ON ST_Intersects(b.wkb_geometry, a.wkb_geometry);
		
		CREATE TEMP TABLE bp_verbundenerplan AS
		SELECT DISTINCT ON (gml_id, verbundenerplan)
		       gml_id,
		       verbundenerplan,
		       rechtscharakter
		  FROM (
		        SELECT b.gml_id, j.verbundenerplan, j.rechtscharakter
		          FROM bp_plan_13073 b,
		               json_populate_recordset(NULL::"${schema}".xp_verbundenerplan, b.aendert::json) j
		         WHERE j.verbundenerplan IS NOT NULL AND j.rechtscharakter IS NOT NULL
		         UNION
		        SELECT j.verbundenerplan, b.gml_id, j.rechtscharakter
		          FROM bp_plan_13073 b,
		               json_populate_recordset(NULL::"${schema}".xp_verbundenerplan, b.wurdegeaendertvon::json) j
		         WHERE j.verbundenerplan IS NOT NULL AND j.rechtscharakter IS NOT NULL
		       ) foo
		 ORDER BY 1, 2, 3;
		
		-- Lösche Verweise auf nicht existierende Pläne
		DELETE FROM bp_verbundenerplan v
		 WHERE NOT EXISTS (SELECT FROM bp_plan_13073 b
		                    WHERE b.gml_id = v.gml_id);
		
		-- Lösche Verweise auf nicht existierende Pläne
		DELETE FROM bp_verbundenerplan v
		 WHERE NOT EXISTS (SELECT FROM bp_plan_13073 b
		                    WHERE b.gml_id = v.verbundenerplan);
		
		INSERT INTO "${schema}".bp_plan
		SELECT gml_id,
		       name,
		       nummer,
		       planart::text[],
		       sonstplanart,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_gemeinde
		           FROM json_populate_recordset(NULL::"${schema}".xp_gemeinde, gemeinde::json) j
		       ), '{}') AS gemeinde,
		       rechtsstand,
		       verfahren,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_spezexternereferenz
		           FROM json_populate_recordset(NULL::"${schema}".xp_spezexternereferenz, externereferenz::json) j
		       ), '{}') AS externereferenz,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_textabschnitt
		           FROM json_populate_recordset(NULL::"${schema}".xp_textabschnitt, texte::json) j
		       ), '{}') AS texte,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_begruendungabschnitt
		           FROM json_populate_recordset(NULL::"${schema}".xp_begruendungabschnitt, begruendungstexte::json) j
		       ), '{}') AS begruendungstexte,
		       beschreibung,
		       kommentar,
		       json_populate_record(NULL::"${schema}".xp_plangeber, plangeber::json)::"${schema}".xp_plangeber AS plangeber,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_gemeinde
		           FROM json_populate_recordset(NULL::"${schema}".xp_gemeinde, planaufstellendegemeinde::json) j
		       ), '{}') AS planaufstellendegemeinde,
		       internalid,
		       (status::json->>'id') AS status,
		       aufstellungsbeschlussdatum::date,
		       technherstelldatum::date,
		       ausfertigungsdatum::date,
		       traegerbeteiligungsstartdatum::date[],
		       traegerbeteiligungsenddatum::date[],
		       auslegungsstartdatum::date[],
		       auslegungsenddatum::date[],
		       aenderungenbisdatum::date,
		       genehmigungsdatum::date,
		       inkrafttretensdatum::date,
		       rechtsverordnungsdatum::date,
		       satzungsbeschlussdatum::date,
		       veraenderungssperre::bool,
		       veraenderungssperredatum::date,
		       untergangsdatum::date,
		       erschliessungsvertrag::bool,
		       durchfuehrungsvertrag::bool,
		       staedtebaulichervertrag::bool,
		       gruenordnungsplan::bool,
		       erstellungsmassstab::int,
		       bezugshoehe::numeric,
		       hoehenbezug::text,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_verfahrensmerkmal
		           FROM json_populate_recordset(NULL::"${schema}".xp_verfahrensmerkmal, verfahrensmerkmale::json) j
		       ), '{}') AS verfahrensmerkmale,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_generattribut
		           FROM json_populate_recordset(NULL::"${schema}".xp_generattribut, hatgenerattribut::json) j
		       ), '{}') AS hatgenerattribut,
		       nullif(ARRAY(
		         SELECT ROW(tp.name, v.rechtscharakter, tp.nummer, tp.gml_id)::"${schema}".xp_verbundenerplan
		           FROM bp_verbundenerplan v
		                JOIN bp_plan_13073 tp
		                  ON tp.gml_id = v.verbundenerplan
		          WHERE v.gml_id = p.gml_id
		       ), '{}') AS aendert,
		       nullif(ARRAY(
		         SELECT ROW(tp.name, v.rechtscharakter, tp.nummer, tp.gml_id)::"${schema}".xp_verbundenerplan
		           FROM bp_verbundenerplan v
		                JOIN bp_plan_13073 tp
		                  ON tp.gml_id = v.gml_id
		          WHERE v.verbundenerplan = p.gml_id
		       ), '{}') AS wurdegeaendertvon,
		       ST_Multi(wkb_geometry)::geometry('MultiPolygon', 25833) AS raeumlichergeltungsbereich
		FROM bp_plan_13073 p
		ORDER BY gml_id;
		
		DROP TABLE "${schema}".bp_plan_tmp;
		
		CREATE UNIQUE INDEX bp_plan_gml_id
		    ON "${schema}".bp_plan
		 USING btree (gml_id);
		
		CREATE INDEX bp_plan_raeumlichergeltungsbereich
		   ON "${schema}".bp_plan
		 USING gist (raeumlichergeltungsbereich);
		
		/*
		 *  FP_Plan
		 */
		CREATE TEMP TABLE fp_plan_13073 AS
		SELECT DISTINCT ON (a.gml_id)
		       a.*
		  FROM "${schema}".fp_plan_tmp a
		       JOIN alkis_eigen.pp_kreis AS b
		         ON ST_Intersects(b.wkb_geometry, a.wkb_geometry);
		
		CREATE TEMP TABLE fp_verbundenerplan AS
		SELECT DISTINCT ON (gml_id, verbundenerplan)
		       gml_id,
		       verbundenerplan,
		       rechtscharakter
		  FROM (
		        SELECT b.gml_id, j.verbundenerplan, j.rechtscharakter
		          FROM fp_plan_13073 b,
		               json_populate_recordset(NULL::"${schema}".xp_verbundenerplan, b.aendert::json) j
		         WHERE j.verbundenerplan IS NOT NULL AND j.rechtscharakter IS NOT NULL
		         UNION
		        SELECT j.verbundenerplan, b.gml_id, j.rechtscharakter
		          FROM fp_plan_13073 b,
		               json_populate_recordset(NULL::"${schema}".xp_verbundenerplan, b.wurdegeaendertvon::json) j
		         WHERE j.verbundenerplan IS NOT NULL AND j.rechtscharakter IS NOT NULL
		       ) foo
		 ORDER BY 1, 2, 3;
		
		-- Lösche Verweise auf nicht existierende Pläne
		DELETE FROM fp_verbundenerplan v
		 WHERE NOT EXISTS (SELECT FROM fp_plan_13073 b
		                    WHERE b.gml_id = v.gml_id);
		
		-- Lösche Verweise auf nicht existierende Pläne
		DELETE FROM fp_verbundenerplan v
		 WHERE NOT EXISTS (SELECT FROM fp_plan_13073 b
		                    WHERE b.gml_id = v.verbundenerplan);
		
		INSERT INTO "${schema}".fp_plan
		SELECT gml_id,
		       name,
		       nummer,
		       planart::text,
		       sonstplanart,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_gemeinde
		           FROM json_populate_recordset(NULL::"${schema}".xp_gemeinde, gemeinde::json) j
		       ), '{}') AS gemeinde,
		       rechtsstand,
		       verfahren,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_spezexternereferenz
		           FROM json_populate_recordset(NULL::"${schema}".xp_spezexternereferenz, externereferenz::json) j
		       ), '{}') AS externereferenz,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_textabschnitt
		           FROM json_populate_recordset(NULL::"${schema}".xp_textabschnitt, texte::json) j
		       ), '{}') AS texte,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_begruendungabschnitt
		           FROM json_populate_recordset(NULL::"${schema}".xp_begruendungabschnitt, begruendungstexte::json) j
		       ), '{}') AS begruendungstexte,
		       beschreibung,
		       kommentar,
		       json_populate_record(NULL::"${schema}".xp_plangeber, plangeber::json)::"${schema}".xp_plangeber AS plangeber,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_gemeinde
		           FROM json_populate_recordset(NULL::"${schema}".xp_gemeinde, planaufstellendegemeinde::json) j
		       ), '{}') AS planaufstellendegemeinde,
		       internalid,
		       (status::json->>'id') AS status,
				 entwurfsbeschlussdatum::date,
		       aufstellungsbeschlussdatum::date,
		       technherstelldatum::date,
		       traegerbeteiligungsstartdatum::date[],
		       traegerbeteiligungsenddatum::date[],
		       auslegungsstartdatum::date[],
		       auslegungsenddatum::date[],
		       aenderungenbisdatum::date,
				 planbeschlussdatum::date,
		       genehmigungsdatum::date,
		       wirksamkeitsdatum::date,
		       untergangsdatum::date,
		       erstellungsmassstab::int,
		       bezugshoehe::numeric,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_verfahrensmerkmal
		           FROM json_populate_recordset(NULL::"${schema}".xp_verfahrensmerkmal, verfahrensmerkmale::json) j
		       ), '{}') AS verfahrensmerkmale,
				 sachgebiet,
		       nullif(ARRAY(
		         SELECT ROW(j.*)::"${schema}".xp_generattribut
		           FROM json_populate_recordset(NULL::"${schema}".xp_generattribut, hatgenerattribut::json) j
		       ), '{}') AS hatgenerattribut,
		       nullif(ARRAY(
		         SELECT ROW(tp.name, v.rechtscharakter, tp.nummer, tp.gml_id)::"${schema}".xp_verbundenerplan
		           FROM fp_verbundenerplan v
		                JOIN fp_plan_13073 tp
		                  ON tp.gml_id = v.verbundenerplan
		          WHERE v.gml_id = p.gml_id
		       ), '{}') AS aendert,
		       nullif(ARRAY(
		         SELECT ROW(tp.name, v.rechtscharakter, tp.nummer, tp.gml_id)::"${schema}".xp_verbundenerplan
		           FROM fp_verbundenerplan v
		                JOIN fp_plan_13073 tp
		                  ON tp.gml_id = v.gml_id
		          WHERE v.verbundenerplan = p.gml_id
		       ), '{}') AS wurdegeaendertvon,
		       ST_Multi(wkb_geometry)::geometry('MultiPolygon', 25833) AS raeumlichergeltungsbereich
		FROM fp_plan_13073 p
		ORDER BY gml_id;
		
		DROP TABLE "${schema}".fp_plan_tmp;
		
		CREATE UNIQUE INDEX fp_plan_gml_id
		    ON "${schema}".fp_plan
		 USING btree (gml_id);
		
		CREATE INDEX fp_plan_raeumlichergeltungsbereich
		   ON "${schema}".fp_plan
		 USING gist (raeumlichergeltungsbereich);
		
		-- Tabellen analysieren
		SELECT format('ANALYZE %I.%I', relnamespace::regnamespace, relname)
		  FROM pg_catalog.pg_class
		 WHERE (relnamespace, relkind) = ('${schema}'::regnamespace, 'r')
		
		\gexec
		
		COMMENT ON SCHEMA "${schema}" IS
		\$\$Wird über ${0} gefüllt. Zuletzt am $(date +%d.%m.%Y)\$\$;
		
		COMMIT;
	SQL

echo $SECONDS

exit