scooterw / ffi-ogr

Convenient Ruby wrapper for OGR
MIT License
13 stars 5 forks source link

Add PostGIS support #12

Open beechnut opened 9 years ago

beechnut commented 9 years ago

My primary use case is exporting PostGIS files to Shapefiles, GeoJSON, KML, etc.

I am going to start in on writing tests for creating a datasource from PostGIS configuration options, and from a database config file.

My goal is to enable syntax like:

pg = OGR.read host: 'localhost', dbname: 'gisdata', user: 'myname', password: 'secret'

pg = OGR.read 'database.yml'

pg = OGR.read( File.expand_path 'database.yml' )
beechnut commented 9 years ago

Got a decent way along in reading from PostGIS. Progress is on my fork: https://github.com/beechnut/ffi-ogr/tree/postgis

I'm now facing a C-related error I don't know how to address, looking for help. How do I get through this Null Pointer error?

Failures:
1) OGR::Reader should create datasource from PostgreSQL configuration YAML file
   Failure/Error: pg = OGR::Reader.new('PostgreSQL').read './spec/data/database.yml'
   RuntimeError:
     Data Source pointer is NULL
   # ./lib/ffi-ogr/tools.rb:15:in `cast_data_source'
   # ./lib/ffi-ogr/reader.rb:23:in `read'
   # ./spec/reader_spec.rb:28:in `block (2 levels) in <top (required)>'

But if I run it in IRB, I get what looks like not a null pointer, but again, I don't know C, so.

2.1.1> OGR::FFIOGR::OGRGetDriverByName('PostgreSQL').inspect  
=> "#<FFI::Pointer address=0x00000102a77a40>"

EDIT Realized what's going on: in reader.rb:22, it reads the data file in, so here it's trying to consume database.yml. I think I need to be using the C wrappers to connect to the database. I'm not sure how to read from the database, but OGR_DS_ExecuteSQL looks like a promising start.

scooterw commented 9 years ago

Let me take a look at this over the weekend. The thing about ffi-ogr is that the real work is done by OGR, so it's going to be C. You could read database.yml to get any config settings to pass to the C function(s). I add the C function signatures as they are used (or I think I'll need them), so those that pertain to dealing with SQL are likely to be missing at this time. We also need to make sure that any function signatures added in more recent versions of OGR and/or the C API have associated checks for compatibility with the installed OGR version.

As for checking for null pointers with FFI, you can use FFI::Pointer#null? to check and guard for them.

beechnut commented 9 years ago

What are you using for OGR C documentation? Do you have a link?

scooterw commented 9 years ago

@beechnut: Sorry for the LONG delay in response. Regarding C documentation, I have simply been referencing http://www.gdal.org/ogr__api_8h.html

I have been looking into this issue, and playing around with a postgis branch of my own. You have to pass the PostGIS connection string in the call to OGR_Dr_Open, and you can then call OGR_DS_ExecuteSQL using the resulting data store.

Based on this, I have created what seems to be a fairly usable workflow assuming you adhere to the yaml format for the really naive parser that you'll see in lib/ffi-ogr/postgis_reader.rb (example below) ...

---
dbname:my_db
host:localhost
port:5432
user:myuser
password:mypassword

This YAML file is converted to a connection string that is understood by OGR in the initialization of the PostgisReader object.

postgis_reader = OGR::PostgisReader.new '/path/to/database.yml'
data = postgis_reader.execute_query 'SELECT * FROM schools;'

An OGR Layer is returned, and I am currently working through how best to pull the geometry and attributes out of the result set. I hope this helps.

beechnut commented 8 years ago

@scooterw: Sorry for the EVEN LONGER delay in response. Any progress on this item?

scooterw commented 8 years ago

Not since last December when I hacked out that bit that returns a layer. It'll take a couple of days to dust it off, but I will take a look at getting usable geometries out of it in the coming days. I tend to use other tools for accessing PostGIS, so this has not gotten as much love from me as it probably should have.