Problema ao carregar o shapefile do sistema operacional OpenData no PostGIS

8

Estou tentando carregar o conjunto de dados do shapefile do SO OpenData Strategi em um banco de dados PostGIS. Não tive problemas com os shapefiles de polilinha e polígono, mas não consigo carregar os shapefiles de ponto.

Estou usando a seguinte linha de comando shp2pgsql para criar a tabela e carregar os dados:

shp2pgsql -c -I -s 27700 admin_font_point strategi_point | psql -d opendata

O erro que recebo é:

Shapefile type: MultiPoint
Postgis type: MULTIPOINT[2]
SET
SET
BEGIN
NOTICE:  CREATE TABLE will create implicit sequence "strategi_point_gid_seq" for serial column "strategi_point.gid"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "strategi_point_pkey" for table "strategi_point"
CREATE TABLE
                         addgeometrycolumn                         
-------------------------------------------------------------------
public.strategi_point.the_geom SRID:27700 TYPE:MULTIPOINT DIMS:2 
(1 row)

ERROR:  new row for relation "strategi_point" violates check constraint "enforce_geotype_the_geom"
ERROR:  current transaction is aborted, commands ignored until end of transaction block

O último erro apenas se repete para cada inserção. O SQL gerado se parece com:

SET CLIENT_ENCODING TO UTF8;
SET STANDARD_CONFORMING_STRINGS TO ON;
BEGIN;
CREATE TABLE "strategi_point" (gid serial PRIMARY KEY,
"code" int4,
"legend" varchar(42),
"file_name" varchar(16),
"number" numeric(11,0),
"name" varchar(180),
"number0" varchar(64),
"admin_name" varchar(50),
"type" varchar(40),
"ferry_from" varchar(50),
"ferry_to" varchar(50),
"ferry_time" varchar(10),
"ferry_type" varchar(20),
"restrictio" varchar(20),
"access" varchar(30),
"amended" date,
"usage" varchar(64),
"location" varchar(30),
"gis" varchar(80),
"owner" varchar(60),
"north" varchar(60),
"south" varchar(60),
"east" varchar(60),
"west" varchar(60),
"clockwise" varchar(60),
"anticlockw" varchar(60),
"imperial" int4,
"metric" int4);
SELECT AddGeometryColumn('','strategi_point','the_geom','27700','MULTIPOINT',2);
INSERT INTO "strategi_point" ("code","legend","file_name","number","name","number0","admin_name","type","ferry_from","ferry_to","ferry_time","ferry_type","restrictio","access","amended","usage","location","gis","owner","north","south","east","west","clockwise","anticlockw","imperial","metric",the_geom) VALUES ('5734','Administrative Detached Attribute Point','gb_north','5307',NULL,NULL,'ISLE OF MAN',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'20000413',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'-9999','-9999','0101000020346C000000000000302A0A4100000000304F1C41');

e muito mais inserções, todas parecendo iguais.

Eu tentei todos os tipos de variações; com e sem SRID; com e sem arquivo .prj; criou um novo banco de dados de teste sem outros dados; usando geometrias simples; mas tudo sem efeito.

Disponibilizei o arquivo zip do shapefile se alguém tiver tempo para tentar isso sozinho:

http://www.passback.org.uk/tmp/admin_font_point.zip

Estou usando um Fedora 14 totalmente atualizado, Postgres 8.4.6, PostGIS 1.5.1.

Algumas notas atualizadas com base na sugestão de uso do SPIT:

Se eu usar shp2pgsql no modo "criar apenas tabela", recebo uma tabela com as seguintes restrições:

Check constraints:
    "enforce_dims_the_geom" CHECK (st_ndims(the_geom) = 2)
    "enforce_geotype_the_geom" CHECK (geometrytype(the_geom) = 'MULTIPOINT'::text OR the_geom IS NULL)
    "enforce_srid_the_geom" CHECK (st_srid(the_geom) = 27700)

Olhando para a tabela criada pelo SPIT, recebo restrições ligeiramente diferentes:

Check constraints:
    "enforce_dims_the_geom" CHECK (st_ndims(the_geom) = 2)
    "enforce_srid_the_geom" CHECK (st_srid(the_geom) = 27700)

Acho que eu poderia usar shp2pgsql -p para criar a tabela e, em seguida, usar o psql para remover a restrição enforce_geotype_the_geom e minha importação em massa da linha de comando usando shp2pgsql -a deve funcionar.

Eu ainda gostaria de entender por que essa restrição está causando um problema?

Obrigado,

Keith.

Keith Sharp
fonte

Respostas:

6

Conforme sugerido por outras respostas, o problema está relacionado aos tipos POINT e MULTIPOINT. shp2pgsql (e ogrinfo) detecta o tipo de geometria como MULTIPOINT, mas, ao criar a representação EWKB da geometria (o valor a ser inserido na coluna_geom), parece estar gerando uma geometria POINT:

select geometrytype('0101000020346C000000000000302A0A4100000000304F1C41');
--POINT

(Tirei o primeiro registro gerado)

De acordo com a página do manual shp2pgsql, existe um sinalizador que deve forçar a criação de novas geometrias simples, mas, aparentemente, ele não funciona nos pontos:

   -S     Generate simple Geometries instead of MULTIgeometries. Shape files don't differ between LINESTRINGs and MULTILINESTRINGs, so shp2pgsql generates MUL
          TILINESTRINGs  by  default. This switch will produce LINESTRINGs instead, but shp2pgsql will fail when it hits a real MULTILINESTRING. The same works
          for POLYGONs vs. MULTIPOLYGONs.

Em vez de eliminar a restrição ofensiva, sugerirei alterar a coluna geometry no script SQL gerado antes de executá-lo com o psql:

SELECT AddGeometryColumn('','strategi_point','the_geom','27700','POINT',2);

Dessa forma, você terá seus registros carregados e, ao mesmo tempo, manterá uma restrição que pode garantir a integridade dos dados no futuro.

amercader
fonte
3

Não sei por que você está recebendo esse erro, mas tentei carregar seu shapefile compactado usando o plug-in SPIT no QGIS, e ele foi importado. Isso me surpreendeu, pois eu assumi que o SPIT era apenas uma interface gráfica para o shp2pgsql! Estou usando o QGIS 1.6 no Windows, mas deve funcionar tão bem no fedora.

Espero que isto ajude

Jo

Archaeogeek
fonte
O plugin PostGIS Manager certamente usa shp2pgsql e falha com o erro mostrado acima. O SPIT também funcionou bem para mim. Agora, a parte interessante seria o que faz de diferente.
Subterrâneo
O SPIT também funciona no Fedora, versão QGIS 1.6.0. Atualizei algumas informações sobre as estruturas da tabela com base no ponto do @ underdark acima.
Keith afiada
2
Bem, o SPIT não usa shp2pgsql. Faz tudo por si só. (Código fonte: svn.osgeo.org/qgis/trunk/qgis/src/plugins/spit )
underdark
2

Com base nos indicadores de @Archaogeek e @underdark, criei uma solução.

Use shp2pgsql para criar a estrutura básica da tabela:

shp2pgsql -p -s 27700 admin_font_point strategi_point | psql -d opendata

Inicie o psql e remova a restrição incorreta:

$ psql -d opendata
psql (8.4.6)
Type "help" for help.

opendata=# ALTER TABLE strategi_point DROP CONSTRAINT enforce_geotype_the_geom;
ALTER TABLE

Depois, volte a usar o shp2pgsql para carregar em massa todos os meus dados de ponto (conduzidos por um script de shell):

shp2pgsql -a -s 27700 admin_font_point strategi_point | psql -d opendata

Eu ainda gostaria de entender o problema com essa restrição.

Keith.

Keith Sharp
fonte
Gostaria de saber se o problema poderia ser que todos os MULTIPOINTS realmente contêm apenas um par de coordenadas. Talvez em algum momento os pontos sejam reconhecidos apenas como PONTOS em vez de MULTIPOINT.
Subterrâneo
2

Agora isso está corrigido no tronco do PostGIS, embora não tenha certeza de qual versão ele terminará.

-S agora funciona para MULTIPOINT -> POINT (http://trac.osgeo.org/postgis/ticket/779)

Agora, os pontos de vértice único em um arquivo de forma multiponto agora são carregados corretamente como multiponto de vértice único em vez de tentar inserir um PONTO. (http://trac.osgeo.org/postgis/ticket/864)

Jeff
fonte
1

Acho que o problema é que provavelmente existem alguns recursos do MULTIPOINT na forma e, por isso, o shp2pgsql precisa usar o MULTIPOINT em vez do POINT. Então, quando um PONTO chega em vez de MULTIPOINT, ocorre um problema de restrição.

Eu esperava uma opção para forçar todos os pontos ao MULTIPOINT, e pensei lá onde, mas não consigo encontrá-lo na documentação. Existe uma função para fazê-lo nos itens carregados no banco de dados: ST_Multi , mas isso é de pouca ajuda ao tentar carregá-lo.

Acho que isso deve ter sido discutido nas listas do PostGIS, mas não consegui encontrá-lo facilmente.

/ Nicklas

Nicklas Avén
fonte