[gdal-dev] OGR2OGR seem lost the field with primary key . ex [OGR2OGR seem last ...]

Even Rouault even.rouault at mines-paris.org
Sat Jan 21 06:28:08 EST 2012


Andrea,

Several points :
1) in the OGR data model, there is the concept of feature ID. According to 
http://gdal.org/ogr/ogr_arch.html :
"""The feature id (FID) of a feature is intended to be a unique identifier for 
the feature within the layer it is a member of. Freestanding features, or 
features not yet written to a layer may have a null (OGRNullFID) feature id. 
The feature ids are modelled in OGR as a long integer; however, this is not 
sufficiently expressive to model the natural feature ids in some formats. For 
instance, the GML feature id is a string, and the row id in Oracle is larger 
than 4 bytes."""

In the case of the PG driver, 
* when examining a OGR layer resulting from a PG table (which is the case when 
you only pass the name of the PG datasource to ogrinfo/ogr2ogr, or pass the 
name of one or several of its layers directly, i.e *without* a -sql 
statement), it will query the PG system tables to look for a primary key 
column of type int2, int4 or serial for the table. If found, this will be 
considered as the FID column. If it's of another type (like varchar), the 
column will be seen as a regular column.
* when examining a  OGRlayer resulting from the result of a -sql request, it 
will only identify a FID column if the column is named "ogc_fid".

All the above explains what you observe on the below samples :

* table1 has a integer primary key.

If you try :

ogrinfo PG:dbname=xxxx testing.table1

you'll see : FID Column = id  and the id column will not be listed as a 
regular field. The values of the FID are given at the end of each of the lines 
beginning by OGRFeature(testing.table1), like OGRFeature(testing.table1):1

If you try :

ogrinfo PG:dbname=xxxx -sql "select * from testing.table1"

you won't see a FID Column line, but the id column will be listed as a regular 
field (its name is not ogc_fid). In the case, OGR will create a fake FID, and 
you'll see OGRFeature(sql_statement):0

* table2 has a varchar primary key. In both cases (directly providing 
testing.table2 or via a -sql statement), this will be considered as a regular 
field by OGR.

When translating to shapefiles, FIDs cannot be preserved directly (the FID of a 
shapefile is a sequential number). You must transform the FID column as a 
regular column with a -sql statement.

But when translating to sqlite DBs, they can be preserved with the -
preserve_fid option of ogr2ogr.

For example :

1) Create a table with a feature whose primary key is 10

drop schema if exists testing cascade;
create schema testing;
create table testing.table1 (id integer primary key, field_2 varchar(10), 
field_3 integer, geometry geometry(Point,4326));
insert into testing.table1 (id, field_2, field_3,geometry) values(10,'aaa',3, 
ST_GeomFromText('POINT(1 1)',4326));

2) Check with ogrinfo that the FID is correctly identified :

$ ogrinfo pg:dbname=autotest-postgis2.0 testing.table1
INFO: Open of `pg:dbname=autotest-postgis2.0'
      using driver `PostgreSQL' successful.

Layer name: testing.table1
Geometry: Point
Feature Count: 1
Extent: (1.000000, 1.000000) - (1.000000, 1.000000)
Layer SRS WKT:
GEOGCS["WGS 84",
    DATUM["WGS_1984",
        SPHEROID["WGS 84",6378137,298.257223563,
            AUTHORITY["EPSG","7030"]],
        AUTHORITY["EPSG","6326"]],
    PRIMEM["Greenwich",0,
        AUTHORITY["EPSG","8901"]],
    UNIT["degree",0.01745329251994328,
        AUTHORITY["EPSG","9122"]],
    AUTHORITY["EPSG","4326"]]
FID Column = id
Geometry Column = geometry
field_2: String (10.0)
field_3: Integer (0.0)
OGRFeature(testing.table1):10
  field_2 (String) = aaa
  field_3 (Integer) = 3
  POINT (1 1)

3) Translate to SQLite db with -preserve_fid option :

$ ogr2ogr table1.sqlite pg:dbname=autotest-postgis2.0 testing.table1 -f sqlite 
-preserve_fid -nln table1 -dsco SPATIALITE=YES

4) Check the DB with ogrinfo :

INFO: Open of `table1.sqlite'
      using driver `SQLite' successful.

Layer name: table1
Geometry: Point
Feature Count: 1
Extent: (1.000000, 1.000000) - (1.000000, 1.000000)
Layer SRS WKT:
GEOGCS["WGS 84",
    DATUM["WGS_1984",
        SPHEROID["WGS 84",6378137,298.257223563,
            AUTHORITY["EPSG","7030"]],
        AUTHORITY["EPSG","6326"]],
    PRIMEM["Greenwich",0,
        AUTHORITY["EPSG","8901"]],
    UNIT["degree",0.0174532925199433,
        AUTHORITY["EPSG","9122"]],
    AUTHORITY["EPSG","4326"]]
FID Column = OGC_FID
Geometry Column = GEOMETRY
field_2: String (0.0)
field_3: Integer (0.0)
OGRFeature(table1):10
  field_2 (String) = aaa
  field_3 (Integer) = 3
  POINT (1 1)

5) You can retrieve it as a regular field with :
$ ogrinfo table1.sqlite -sql "select *, ogc_fid as id from table1"
INFO: Open of `table1.sqlite'
      using driver `SQLite' successful.

Layer name: SELECT
Geometry: Unknown (any)
Feature Count: 1
Extent: (1.000000, 1.000000) - (1.000000, 1.000000)
Layer SRS WKT:
(unknown)
Geometry Column = GEOMETRY
field_2: String (0.0)
field_3: Integer (0.0)
id: Integer (0.0)
OGRFeature(SELECT):0
  field_2 (String) = aaa
  field_3 (Integer) = 3
  id (Integer) = 10
  POINT (1 1)



Best regards,

Even


More information about the gdal-dev mailing list