CartoDB/CartoDB-SQL-API

Return exact Pg field type information in JSON return

pramsey opened this issue · 2 comments

Motivation: Right now clients can only infer generic type information (see below) about return fields, and they sometimes need/want more exact type information than we provide. They used to just look at the system tables to figure this stuff out, but now with read-only keys that restrict system table access, they really need to get this information directly from the result set.

End State: Clients should be able to get a fast and precise table column/type definition just by running SELECT * FROM mytable LIMIT 0.

Right now we return loose field information:

   "fields" : {
      "the_geom" : {
         "type" : "geometry"
      },
      "created_at" : {
         "type" : "date"
      },
      "the_geom_webmercator" : {
         "type" : "geometry"
      },
      "id" : {
         "type" : "number"
      },
      "updated_at" : {
         "type" : "date"
      },
      "cartodb_id" : {
         "type" : "number"
      }
   }

But we could return the exact type information, which OGR uses to form the field definitions when creating OGRLayer objects in the CARTO driver. The OGR types distinguish between real/integer, date and datetime. They also distinguish in geometries between the geometry types and the dimensionality of geometries (2d/3d) and the SRS of geometries.

We can extract the type/dim/srid information from the typmod number returned in libpq via PQfmod(const PGresult *res, int field_num), as it all lives in various bitfields of the integer.

The exact postgresql types can be inferred from the Oid, there's probably a lookup for this already behind the fields output. We just need to be a little more exact. Either go for a fields_ogr output list, or add a type_ogr entry to the existing fields or more generically just add a pgtype field.

   "fields" : {
      "the_geom" : {
         "type" : "geometry",
         "wkbtype": "Point",
         "dims": 2,
         "srid": 4326
      },
      "created_at" : {
         "type" : "date",
         "pgtype": "timestamptz"
      },
      "the_geom_webmercator" : {
         "type" : "geometry",
         "wkbtype": "Point",
         "dims": 2,
         "srid": 3857
      },
      "id" : {
         "type" : "number",
         "pgtype": "int4"
      },
      "updated_at" : {
         "type" : "date",
         "pgtype": "timestamptz"
      },
      "cartodb_id" : {
         "type" : "number",
         "pgtype": "int4"
      }
   }

A fair question regarding the type/dims stuff is "why do we need that, it's implied by the column name", and the answer is that it's possible this way to read a table that has not yet been passed through the Cartodbfy() process.

Here's a first step along the way: allow us to read info off the typmod number that we can read using PQfmod(const PGresult *res, int field_num)
CartoDB/node-cartodb-psql#34

Ready in production #592