[Git][debian-gis-team/pgsql-ogr-fdw][upstream] New upstream version 1.0.8

Bas Couwenberg gitlab at salsa.debian.org
Thu May 2 06:28:04 BST 2019



Bas Couwenberg pushed to branch upstream at Debian GIS Project / pgsql-ogr-fdw


Commits:
6f4a8c53 by Bas Couwenberg at 2019-05-02T05:03:22Z
New upstream version 1.0.8
- - - - -


15 changed files:

- + .astylerc
- .editorconfig
- .travis.yml
- README.md
- + data/poly.dbf
- + data/poly.shp
- + data/poly.shx
- input/file.source
- ogr_fdw.c
- ogr_fdw.h
- ogr_fdw_common.c
- ogr_fdw_deparse.c
- ogr_fdw_gdal.h
- output/file.source
- output/import.source


Changes:

=====================================
.astylerc
=====================================
@@ -0,0 +1,14 @@
+--style=allman
+--indent=tab=4
+--max-code-length=120
+--lineend=linux
+--unpad-paren
+--pad-oper
+--pad-header
+--align-pointer=type
+--align-reference=type
+--break-closing-braces
+--add-braces
+--break-return-type
+--break-after-logical
+


=====================================
.editorconfig
=====================================
@@ -7,10 +7,19 @@ root = true
 [*]
 charset = utf-8
 end_of_line = lf
-trim_trailing_whitespace = true
 insert_final_newline = true
+trim_trailing_whitespace = true
+
+# Test files need kid gloves
+[*.source]
+insert_final_newline = false
+trim_trailing_whitespace = false
 
 # C files want tab indentation
-[*.{c,h}]
+[*.{c,h,md}]
 indent_style = tab
+indent_size = 4
 
+# Makefiles want tab indentation
+[Makefile]
+indent_style = tab


=====================================
.travis.yml
=====================================
@@ -9,15 +9,16 @@ addons:
     - curl
     - libcurl4-gnutls-dev
     - ca-certificates
-    - software-properties-common 
+    - software-properties-common
     - python-software-properties
     - gnupg-curl
 
 env:
-  - PG_VERSION=9.6 GDAL_VERSION=1.1
+  - PG_VERSION=9.6 GDAL_VERSION=1.11
   - PG_VERSION=9.6 GDAL_VERSION=2.2.4
-  - PG_VERSION=9.6 GDAL_VERSION=2.3.1
-  - PG_VERSION=10 GDAL_VERSION=2.3.1
+  - PG_VERSION=10 GDAL_VERSION=2.3.3
+  - PG_VERSION=10 GDAL_VERSION=2.4.1
+  - PG_VERSION=11 GDAL_VERSION=2.4.1
 
 before_script:
   - sudo /etc/init.d/postgresql stop
@@ -27,21 +28,22 @@ before_script:
   - sudo apt-get -y --purge remove postgresql-9.4
   - sudo apt-get -y --purge remove postgresql-9.5
   - sudo apt-get -y --purge remove postgresql-9.6
+  - sudo apt-get -y --purge remove postgresql-10
+  - sudo apt-get -y --purge remove postgresql-11
+  - sudo apt-get -y --purge remove postgresql-common
   - sudo apt-get -y autoremove
   - sudo rm -rf /var/lib/postgresql
   - apt-key adv --fetch-keys https://www.postgresql.org/media/keys/ACCC4CF8.asc
-  - sudo add-apt-repository "deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main $PG_VERSION"    
+  - sudo add-apt-repository "deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main $PG_VERSION"
   - sudo apt-get update -qq
   - sudo apt-get -y install postgresql-$PG_VERSION postgresql-server-dev-$PG_VERSION
   - sudo cp ci/pg_hba.conf /etc/postgresql/$PG_VERSION/main/pg_hba.conf
   - sudo /etc/init.d/postgresql reload
-  
+
   - if [[ $GDAL_VERSION == 1* ]]; then sudo apt-get install libgdal1h libgdal-dev; fi
   - if [[ $GDAL_VERSION == 2* ]]; then wget http://download.osgeo.org/gdal/$GDAL_VERSION/gdal-$GDAL_VERSION.tar.xz; tar xJf gdal-$GDAL_VERSION.tar.xz; cd gdal-$GDAL_VERSION; ./configure --prefix=/usr --enable-debug --without-libtool; make -j4 >/dev/null; sudo make install >/dev/null; cd ..; gdalinfo --version; fi
-  
+
 script:
-  - make
-  - sudo make install
-  - sudo chmod 755 $HOME
-  - PGUSER=postgres make installcheck || (cat regression.diffs && /bin/false)
+  - make && sudo make install && sudo chmod 755 $HOME && (PGUSER=postgres make installcheck || (cat regression.diffs && /bin/false))
+
 


=====================================
README.md
=====================================
@@ -100,40 +100,41 @@ Since we can access any OGR data source as a table, how about a public WFS serve
     CREATE EXTENSION postgis;
     CREATE EXTENSION ogr_fdw;
 
-    CREATE SERVER opengeo
+    CREATE SERVER geoserver
       FOREIGN DATA WRAPPER ogr_fdw
       OPTIONS (
-        datasource 'WFS:http://demo.opengeo.org/geoserver/wfs',
-        format 'WFS' );
+	datasource 'WFS:https://demo.geo-solutions.it/geoserver/wfs',
+	format 'WFS' );
 
     CREATE FOREIGN TABLE topp_states (
-      fid integer,
-      geom geometry,
+      fid bigint,
+      the_geom Geometry(MultiSurface,4326),
       gml_id varchar,
       state_name varchar,
       state_fips varchar,
       sub_region varchar,
       state_abbr varchar,
-      land_km real,
-      water_km real,
-      persons real,
-      families real,
-      houshold real,
-      male real,
-      female real,
-      workers real,
-      drvalone real,
-      carpool real,
-      pubtrans real,
-      employed real,
-      unemploy real,
-      service real,
-      manual real,
-      p_male real,
-      p_female real,
-      samp_pop real )
-      SERVER opengeo
-      OPTIONS (layer 'topp:states');
+      land_km double precision,
+      water_km double precision,
+      persons double precision,
+      families double precision,
+      houshold double precision,
+      male double precision,
+      female double precision,
+      workers double precision,
+      drvalone double precision,
+      carpool double precision,
+      pubtrans double precision,
+      employed double precision,
+      unemploy double precision,
+      service double precision,
+      manual double precision,
+      p_male double precision,
+      p_female double precision,
+      samp_pop double precision
+    ) SERVER "geoserver"
+    OPTIONS (layer 'topp:states');
+
 
 ### FGDB FDW
 


=====================================
data/poly.dbf
=====================================
Binary files /dev/null and b/data/poly.dbf differ


=====================================
data/poly.shp
=====================================
Binary files /dev/null and b/data/poly.shp differ


=====================================
data/poly.shx
=====================================
Binary files /dev/null and b/data/poly.shx differ


=====================================
input/file.source
=====================================
@@ -14,7 +14,7 @@ CREATE FOREIGN TABLE pt_1 (
   geom bytea,
   name varchar,
   age integer,
-  height real,
+  height double precision,
   birthdate date )
   SERVER myserver
   OPTIONS ( layer 'pt_two' );
@@ -41,6 +41,19 @@ CREATE FOREIGN TABLE pt_3 (
 
 SELECT * FROM pt_3 ORDER BY name;
 
+
+------------------------------------------------
+
+CREATE FOREIGN TABLE poly_1 (
+  fid bigint,
+  geom bytea,
+  id double precision,
+  name varchar(5)
+) SERVER myserver
+OPTIONS (layer 'poly');
+
+SELECT length(geom) FROM poly_1 WHERE name = 'Three';
+
 ------------------------------------------------
 -- Laundering and explicit column naming test
 
@@ -77,9 +90,9 @@ CREATE FOREIGN TABLE e_1 (
   SERVER myserver_latin1
   OPTIONS ( layer 'enc' );
 
-SET client_min_messages = debug1;  
+SET client_min_messages = debug1;
 SELECT * FROM e_1 WHERE fid = 1;
-SET client_min_messages = notice;  
+SET client_min_messages = notice;
 
 ------------------------------------------------
 -- Geometryless test
@@ -98,9 +111,9 @@ CREATE FOREIGN TABLE no_geom (
 ) SERVER csvserver
 OPTIONS (layer 'no_geom');
 
-SELECT c.* 
-  FROM generate_series(1,4) g 
-  JOIN no_geom c 
+SELECT c.*
+  FROM generate_series(1,4) g
+  JOIN no_geom c
   ON (c.fid = g.g);
 
 ------------------------------------------------


=====================================
ogr_fdw.c
=====================================
@@ -43,7 +43,7 @@ PG_MODULE_MAGIC;
  */
 struct OgrFdwOption
 {
-	const char *optname;
+	const char* optname;
 	Oid optcontext;     /* Oid of catalog in which option may appear */
 	bool optrequired;   /* Flag mandatory options */
 	bool optfound;      /* Flag whether options was specified by user */
@@ -67,7 +67,8 @@ struct OgrFdwOption
  * UserMappingRelationId (CREATE USER MAPPING options)
  * ForeignTableRelationId (CREATE FOREIGN TABLE options)
  */
-static struct OgrFdwOption valid_options[] = {
+static struct OgrFdwOption valid_options[] =
+{
 
 	/* OGR column mapping */
 	{OPT_COLUMN, AttributeRelationId, false, false},
@@ -101,98 +102,134 @@ void _PG_init(void);
 /*
  * FDW query callback routines
  */
-static void ogrGetForeignRelSize(PlannerInfo *root,
-					RelOptInfo *baserel,
-					Oid foreigntableid);
-static void ogrGetForeignPaths(PlannerInfo *root,
-					RelOptInfo *baserel,
-					Oid foreigntableid);
-static ForeignScan *ogrGetForeignPlan(PlannerInfo *root,
-				 	RelOptInfo *baserel,
-				 	Oid foreigntableid,
-				 	ForeignPath *best_path,
-				 	List *tlist,
-				 	List *scan_clauses
+static void ogrGetForeignRelSize(PlannerInfo* root,
+                                 RelOptInfo* baserel,
+                                 Oid foreigntableid);
+static void ogrGetForeignPaths(PlannerInfo* root,
+                               RelOptInfo* baserel,
+                               Oid foreigntableid);
+static ForeignScan* ogrGetForeignPlan(PlannerInfo* root,
+                                      RelOptInfo* baserel,
+                                      Oid foreigntableid,
+                                      ForeignPath* best_path,
+                                      List* tlist,
+                                      List* scan_clauses
 #if PG_VERSION_NUM >= 90500
-					,Plan *outer_plan
+                                      , Plan* outer_plan
 #endif
-);
-static void ogrBeginForeignScan(ForeignScanState *node, int eflags);
-static TupleTableSlot *ogrIterateForeignScan(ForeignScanState *node);
-static void ogrReScanForeignScan(ForeignScanState *node);
-static void ogrEndForeignScan(ForeignScanState *node);
+                                     );
+static void ogrBeginForeignScan(ForeignScanState* node, int eflags);
+static TupleTableSlot* ogrIterateForeignScan(ForeignScanState* node);
+static void ogrReScanForeignScan(ForeignScanState* node);
+static void ogrEndForeignScan(ForeignScanState* node);
 
 /*
  * FDW modify callback routines
  */
-static void ogrAddForeignUpdateTargets (Query *parsetree,
-					RangeTblEntry *target_rte,
-					Relation target_relation);
-static void ogrBeginForeignModify (ModifyTableState *mtstate,
-					ResultRelInfo *rinfo,
-					List *fdw_private,
-					int subplan_index,
-					int eflags);
-static TupleTableSlot *ogrExecForeignInsert (EState *estate,
-					ResultRelInfo *rinfo,
-					TupleTableSlot *slot,
-					TupleTableSlot *planSlot);
-static TupleTableSlot *ogrExecForeignUpdate (EState *estate,
-					ResultRelInfo *rinfo,
-					TupleTableSlot *slot,
-					TupleTableSlot *planSlot);
-static TupleTableSlot *ogrExecForeignDelete (EState *estate,
-					ResultRelInfo *rinfo,
-					TupleTableSlot *slot,
-					TupleTableSlot *planSlot);
-static void ogrEndForeignModify (EState *estate,
-					ResultRelInfo *rinfo);
-static int ogrIsForeignRelUpdatable (Relation rel);
+static void ogrAddForeignUpdateTargets(Query* parsetree,
+                                       RangeTblEntry* target_rte,
+                                       Relation target_relation);
+static void ogrBeginForeignModify(ModifyTableState* mtstate,
+                                  ResultRelInfo* rinfo,
+                                  List* fdw_private,
+                                  int subplan_index,
+                                  int eflags);
+static TupleTableSlot* ogrExecForeignInsert(EState* estate,
+        ResultRelInfo* rinfo,
+        TupleTableSlot* slot,
+        TupleTableSlot* planSlot);
+static TupleTableSlot* ogrExecForeignUpdate(EState* estate,
+        ResultRelInfo* rinfo,
+        TupleTableSlot* slot,
+        TupleTableSlot* planSlot);
+static TupleTableSlot* ogrExecForeignDelete(EState* estate,
+        ResultRelInfo* rinfo,
+        TupleTableSlot* slot,
+        TupleTableSlot* planSlot);
+static void ogrEndForeignModify(EState* estate,
+                                ResultRelInfo* rinfo);
+static int ogrIsForeignRelUpdatable(Relation rel);
 
 
 #if PG_VERSION_NUM >= 90500
-static List *ogrImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid);
+static List* ogrImportForeignSchema(ImportForeignSchemaStmt* stmt, Oid serverOid);
 #endif
 
 /*
  * Helper functions
  */
-static OgrConnection ogrGetConnectionFromTable(Oid foreigntableid, bool updateable);
+static OgrConnection ogrGetConnectionFromTable(Oid foreigntableid, OgrUpdateable updateable);
 static void ogr_fdw_exit(int code, Datum arg);
-static void ogrReadColumnData(OgrFdwState *state);
+static void ogrReadColumnData(OgrFdwState* state);
 
 /* Global to hold GEOMETRYOID */
 Oid GEOMETRYOID = InvalidOid;
 
+
 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,1,0)
+
+const char* const gdalErrorTypes[] =
+{
+	"None",
+	"AppDefined",
+	"OutOfMemory",
+	"FileIO",
+	"OpenFailed",
+	"IllegalArg",
+	"NotSupported",
+	"AssertionFailed",
+	"NoWriteAccess",
+	"UserInterrupt",
+	"ObjectNull",
+	"HttpResponse",
+	"AWSBucketNotFound",
+	"AWSObjectNotFound",
+	"AWSAccessDenied",
+	"AWSInvalidCredentials",
+	"AWSSignatureDoesNotMatch"
+};
+
+/* In theory this function should be declared "static void CPL_STDCALL" */
+/* since this is the official signature of error handler callbacks. */
+/* That would be needed if both GDAL and ogr_fdw were compiled with Visual */
+/* Studio, but with non-Visual Studio compilers, the macro expands to empty, */
+/* so if both GDAL and ogr_fdw are compiled with gcc things are fine. In case */
+/* of mixes, crashes may occur but there is no clean fix... So let this as a note */
+/* in case of future issue... */
 static void
-ogrErrorHandler(CPLErr eErrClass, int err_no, const char *msg)
+ogrErrorHandler(CPLErr eErrClass, int err_no, const char* msg)
 {
+	const char* gdalErrType = "unknown type";
+	if (err_no >= 0 && err_no <
+	    (int)sizeof(gdalErrorTypes)/sizeof(gdalErrorTypes[0]))
+	{
+		gdalErrType = gdalErrorTypes[err_no];
+	}
 	switch (eErrClass)
 	{
-		case CE_None:
-			elog(NOTICE, "[%d] %s", err_no, msg);
-			break;
-		case CE_Debug:
-			elog(DEBUG2, "[%d] %s", err_no, msg);
-			break;
-		case CE_Warning:
-			elog(WARNING, "[%d] %s", err_no, msg);
-			break;
-		case CE_Failure:
-		case CE_Fatal:
-		default:
-			elog(ERROR, "[%d] %s", err_no, msg);
-			break;
+	case CE_None:
+		elog(NOTICE, "GDAL %s [%d] %s", gdalErrType, err_no, msg);
+		break;
+	case CE_Debug:
+		elog(DEBUG2, "GDAL %s [%d] %s", gdalErrType, err_no, msg);
+		break;
+	case CE_Warning:
+		elog(WARNING, "GDAL %s [%d] %s", gdalErrType, err_no, msg);
+		break;
+	case CE_Failure:
+	case CE_Fatal:
+	default:
+		elog(ERROR, "GDAL %s [%d] %s", gdalErrType, err_no, msg);
+		break;
 	}
 	return;
 }
-#endif
+
+#endif /* GDAL 2.1.0+ */
 
 void
 _PG_init(void)
 {
-
 	on_proc_exit(&ogr_fdw_exit, PointerGetDatum(NULL));
 
 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,1,0)
@@ -214,9 +251,11 @@ ogr_fdw_exit(int code, Datum arg)
 /*
  * Function to get the geometry OID if required
  */
-Oid ogrGetGeometryOid(void)
+Oid
+ogrGetGeometryOid(void)
 {
-	if (GEOMETRYOID == InvalidOid) {
+	if (GEOMETRYOID == InvalidOid)
+	{
 		Oid typoid = TypenameGetTypid("geometry");
 		if (OidIsValid(typoid) && get_typisdefined(typoid))
 		{
@@ -238,7 +277,7 @@ Oid ogrGetGeometryOid(void)
 Datum
 ogr_fdw_handler(PG_FUNCTION_ARGS)
 {
-	FdwRoutine *fdwroutine = makeNode(FdwRoutine);
+	FdwRoutine* fdwroutine = makeNode(FdwRoutine);
 
 	/* Read support */
 	fdwroutine->GetForeignRelSize = ogrGetForeignRelSize;
@@ -267,125 +306,163 @@ ogr_fdw_handler(PG_FUNCTION_ARGS)
 }
 
 /*
- * Given a connection string and (optional) driver string, try to connect
- * with appropriate error handling and reporting. Used in query startup,
- * and in FDW options validation.
- */
-static GDALDatasetH
-ogrGetDataSource(const char *source, const char *driver, bool updateable,
-                 const char *config_options, const char *open_options)
+* When attempting a soft open (allowing for failure and retry),
+* we might need to call the opening
+* routines twice, so all the opening machinery is placed here
+* for convenient re-calling.
+*/
+static OGRErr
+ogrGetDataSourceAttempt(OgrConnection* ogr, bool bUpdateable, char** open_option_list)
 {
-	GDALDatasetH ogr_ds = NULL;
 	GDALDriverH ogr_dr = NULL;
-	char **open_option_list = NULL;
 #if GDAL_VERSION_MAJOR >= 2
 	unsigned int open_flags = GDAL_OF_VECTOR;
 
-	if ( updateable )
+	if (bUpdateable)
+	{
 		open_flags |= GDAL_OF_UPDATE;
+	}
 	else
+	{
 		open_flags |= GDAL_OF_READONLY;
+	}
+#endif
+
+	if (ogr->dr_str)
+	{
+		ogr_dr = GDALGetDriverByName(ogr->dr_str);
+		if (!ogr_dr)
+		{
+			ereport(ERROR,
+			        (errcode(ERRCODE_FDW_UNABLE_TO_ESTABLISH_CONNECTION),
+			         errmsg("unable to find format \"%s\"", ogr->dr_str),
+			         errhint("See the formats list at http://www.gdal.org/ogr_formats.html")));
+		}
+#if GDAL_VERSION_MAJOR < 2
+		ogr->ds = OGR_Dr_Open(ogr_dr, ogr->ds_str, bUpdateable);
+#else
+		{
+			char** driver_list = CSLAddString(NULL, ogr->dr_str);
+			ogr->ds = GDALOpenEx(ogr->ds_str,                  /* file/data source */
+			                     open_flags,                            /* open flags */
+			                     (const char* const*)driver_list,       /* driver */
+			                     (const char* const*)open_option_list,  /* open options */
+			                     NULL);                                 /* sibling files */
+			CSLDestroy(driver_list);
+		}
+#endif
+	}
+	/* No driver, try a blind open... */
+	else
+	{
+#if GDAL_VERSION_MAJOR < 2
+		ogr->ds = OGROpen(ogr->ds_str, bUpdateable, &ogr_dr);
+#else
+		ogr->ds = GDALOpenEx(ogr->ds_str,
+		                     open_flags,
+		                     NULL,
+		                     (const char* const*)open_option_list,
+		                     NULL);
 #endif
+	}
+	return ogr->ds ? OGRERR_NONE : OGRERR_FAILURE;
+}
 
-	if ( config_options )
+/*
+ * Given a connection string and (optional) driver string, try to connect
+ * with appropriate error handling and reporting. Used in query startup,
+ * and in FDW options validation.
+ */
+static OGRErr
+ogrGetDataSource(OgrConnection* ogr, OgrUpdateable updateable)
+{
+	char** open_option_list = NULL;
+	bool bUpdateable = (updateable == OGR_UPDATEABLE_TRUE || updateable == OGR_UPDATEABLE_TRY);
+	OGRErr err;
+
+	/* Set the GDAL config options into the environment */
+	if (ogr->config_options)
 	{
-		char **option_iter;
-		char **option_list = CSLTokenizeString(config_options);
+		char** option_iter;
+		char** option_list = CSLTokenizeString(ogr->config_options);
 
-		for ( option_iter = option_list; option_iter && *option_iter; option_iter++ )
+		for (option_iter = option_list; option_iter && *option_iter; option_iter++)
 		{
-			char *key;
-			const char *value;
+			char* key;
+			const char* value;
 			value = CPLParseNameValue(*option_iter, &key);
-			if ( ! (key && value) )
-				elog(ERROR, "bad config option string '%s'", config_options);
+			if (!(key && value))
+			{
+				elog(ERROR, "bad config option string '%s'", ogr->config_options);
+			}
 
 			elog(DEBUG1, "GDAL config option '%s' set to '%s'", key, value);
 			CPLSetConfigOption(key, value);
 			CPLFree(key);
 		}
-		CSLDestroy( option_list );
+		CSLDestroy(option_list);
 	}
 
-	if ( open_options )
-		open_option_list = CSLTokenizeString(open_options);
+	/* Parse the GDAL layer open options */
+	if (ogr->open_options)
+	{
+		open_option_list = CSLTokenizeString(ogr->open_options);
+	}
 
-	/* Cannot search for drivers if they aren't registered */
-	/* But don't call for registration if we already have drivers */
-	if ( GDALGetDriverCount() <= 0 )
+	/* Cannot search for drivers if they aren't registered, */
+	/* but don't do registration if we already have drivers loaded */
+	if (GDALGetDriverCount() <= 0)
+	{
 		GDALAllRegister();
+	}
 
-	if ( driver )
+	/* First attempt at connection */
+	err = ogrGetDataSourceAttempt(ogr, bUpdateable, open_option_list);
+
+	/* Failed on soft updateable attempt, try and fall back to readonly */
+	if ((!ogr->ds) && updateable == OGR_UPDATEABLE_TRY)
 	{
-		ogr_dr = GDALGetDriverByName(driver);
-		if ( ! ogr_dr )
+		err = ogrGetDataSourceAttempt(ogr, false, open_option_list);
+		/* Succeeded with readonly connection */
+		if (ogr->ds)
 		{
-			ereport(ERROR,
-				(errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
-					errmsg("unable to find format \"%s\"", driver),
-					errhint("See the formats list at http://www.gdal.org/ogr_formats.html")));
+			ogr->ds_updateable = ogr->lyr_updateable = OGR_UPDATEABLE_FALSE;
 		}
-#if GDAL_VERSION_MAJOR < 2
-		ogr_ds = OGR_Dr_Open(ogr_dr, source, updateable);
-#else
-		{
-			char** driver_list = CSLAddString(NULL, driver);
-			ogr_ds = GDALOpenEx(source,                                         /* file/data source */
-					    open_flags,                /* open flags */
-					    (const char* const*)driver_list, /* driver */
-					    (const char *const *)open_option_list,          /* open options */
-					    NULL);                                          /* sibling files */
-			CSLDestroy( driver_list );
-		}
-#endif
-	}
-	/* No driver, try a blind open... */
-	else
-	{
-#if GDAL_VERSION_MAJOR < 2
-		ogr_ds = OGROpen(source, updateable, &ogr_dr);
-#else
-		ogr_ds = GDALOpenEx(source,
-		                    open_flags,
-		                    NULL,
-		                    (const char *const *)open_option_list,
-		                    NULL);
-#endif
 	}
 
 	/* Open failed, provide error hint if OGR gives us one. */
-	if ( ! ogr_ds )
+	if (!ogr->ds)
 	{
-		const char *ogrerr = CPLGetLastErrorMsg();
-		if ( ogrerr && ! streq(ogrerr, "") )
+		const char* ogrerrmsg = CPLGetLastErrorMsg();
+		if (ogrerrmsg && !streq(ogrerrmsg, ""))
 		{
 			ereport(ERROR,
-				(errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
-				 errmsg("unable to connect to data source \"%s\"", source),
-				 errhint("%s", ogrerr)));
+			        (errcode(ERRCODE_FDW_UNABLE_TO_ESTABLISH_CONNECTION),
+			         errmsg("unable to connect to data source \"%s\"", ogr->ds_str),
+			         errhint("%s", ogrerrmsg)));
 		}
 		else
 		{
- 			ereport(ERROR,
- 				(errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
- 				 errmsg("unable to connect to data source \"%s\"", source)));
+			ereport(ERROR,
+			        (errcode(ERRCODE_FDW_UNABLE_TO_ESTABLISH_CONNECTION),
+			         errmsg("unable to connect to data source \"%s\"", ogr->ds_str)));
 		}
 	}
 
-	CSLDestroy( open_option_list );
+	CSLDestroy(open_option_list);
 
-	return ogr_ds;
+	return err;
 }
 
 static bool
-ogrCanReallyCountFast(const OgrConnection *con)
+ogrCanReallyCountFast(const OgrConnection* con)
 {
 	GDALDriverH dr = GDALGetDatasetDriver(con->ds);
-	const char *dr_str = GDALGetDriverShortName(dr);
+	const char* dr_str = GDALGetDriverShortName(dr);
 
-	if ( streq(dr_str, "ESRI Shapefile" ) ||
-   	     streq(dr_str, "FileGDB" ) ||
-	     streq(dr_str, "OpenFileGDB" ) )
+	if (streq(dr_str, "ESRI Shapefile") ||
+	    streq(dr_str, "FileGDB") ||
+	    streq(dr_str, "OpenFileGDB"))
 	{
 		return true;
 	}
@@ -393,21 +470,21 @@ ogrCanReallyCountFast(const OgrConnection *con)
 }
 
 static void
-ogrEreportError(const char *errstr)
+ogrEreportError(const char* errstr)
 {
-	const char *ogrerr = CPLGetLastErrorMsg();
-	if ( ogrerr && ! streq(ogrerr,"") )
+	const char* ogrerrmsg = CPLGetLastErrorMsg();
+	if (ogrerrmsg && !streq(ogrerrmsg, ""))
 	{
 		ereport(ERROR,
-			(errcode(ERRCODE_FDW_ERROR),
-			 errmsg("%s", errstr),
-			 errhint("%s", ogrerr)));
+		        (errcode(ERRCODE_FDW_ERROR),
+		         errmsg("%s", errstr),
+		         errhint("%s", ogrerrmsg)));
 	}
 	else
 	{
 		ereport(ERROR,
-			(errcode(ERRCODE_FDW_ERROR),
-			 errmsg("%s", errstr)));
+		        (errcode(ERRCODE_FDW_ERROR),
+		         errmsg("%s", errstr)));
 	}
 }
 
@@ -416,23 +493,28 @@ ogrEreportError(const char *errstr)
  * with a connection.
  */
 static void
-ogrFinishConnection(OgrConnection *ogr)
+ogrFinishConnection(OgrConnection* ogr)
 {
-	if ( ogr->lyr && OGR_L_SyncToDisk(ogr->lyr) != OGRERR_NONE )
+	if (ogr->lyr && OGR_L_SyncToDisk(ogr->lyr) != OGRERR_NONE)
+	{
 		elog(NOTICE, "failed to flush writes to OGR data source");
+	}
 
-	if ( ogr->ds )
+	if (ogr->ds)
+	{
 		GDALClose(ogr->ds);
+	}
 
 	ogr->ds = NULL;
 }
 
 static OgrConnection
-ogrGetConnectionFromServer(Oid foreignserverid, bool updateable)
+ogrGetConnectionFromServer(Oid foreignserverid, OgrUpdateable updateable)
 {
-	ForeignServer *server;
+	ForeignServer* server;
 	OgrConnection ogr;
-	ListCell *cell;
+	ListCell* cell;
+	OGRErr err;
 
 	/* Null all values */
 	memset(&ogr, 0, sizeof(OgrConnection));
@@ -441,34 +523,44 @@ ogrGetConnectionFromServer(Oid foreignserverid, bool updateable)
 
 	server = GetForeignServer(foreignserverid);
 
-	foreach(cell, server->options)
+	foreach (cell, server->options)
 	{
-		DefElem *def = (DefElem *) lfirst(cell);
+		DefElem* def = (DefElem*) lfirst(cell);
 		if (streq(def->defname, OPT_SOURCE))
+		{
 			ogr.ds_str = defGetString(def);
+		}
 		if (streq(def->defname, OPT_DRIVER))
+		{
 			ogr.dr_str = defGetString(def);
+		}
 		if (streq(def->defname, OPT_CONFIG_OPTIONS))
+		{
 			ogr.config_options = defGetString(def);
+		}
 		if (streq(def->defname, OPT_OPEN_OPTIONS))
+		{
 			ogr.open_options = defGetString(def);
+		}
 		if (streq(def->defname, OPT_UPDATEABLE))
 		{
-			if ( defGetBoolean(def) )
+			if (defGetBoolean(def))
+			{
 				ogr.ds_updateable = OGR_UPDATEABLE_TRUE;
+			}
 			else
+			{
 				ogr.ds_updateable = OGR_UPDATEABLE_FALSE;
+				/* Over-ride the open mode to favour user-defined mode */
+				updateable = OGR_UPDATEABLE_FALSE;
+			}
 		}
 	}
 
-	if ( ! ogr.ds_str )
+	if (!ogr.ds_str)
+	{
 		elog(ERROR, "FDW table '%s' option is missing", OPT_SOURCE);
-
-	if ( updateable && ogr.ds_updateable == OGR_UPDATEABLE_FALSE )
-		ereport(ERROR,
-			(errcode(ERRCODE_FDW_ERROR),
-			 errmsg("updates are not allowed on foreign server '%s'", server->servername),
-			 errhint("ALTER FOREIGN SERVER %s OPTIONS (SET updatable 'true')", server->servername)));
+	}
 
 	/*
 	 * TODO: Connections happen twice for each query, having a
@@ -476,8 +568,7 @@ ogrGetConnectionFromServer(Oid foreignserverid, bool updateable)
 	 */
 
 	/*  Connect! */
-	ogr.ds = ogrGetDataSource(ogr.ds_str, ogr.dr_str, updateable, ogr.config_options, ogr.open_options);
-
+	err = ogrGetDataSource(&ogr, updateable);
 	return ogr;
 }
 
@@ -489,12 +580,12 @@ ogrGetConnectionFromServer(Oid foreignserverid, bool updateable)
  * has handles for both the datasource and layer.
  */
 static OgrConnection
-ogrGetConnectionFromTable(Oid foreigntableid, bool updateable)
+ogrGetConnectionFromTable(Oid foreigntableid, OgrUpdateable updateable)
 {
-	ForeignTable *table;
+	ForeignTable* table;
 	/* UserMapping *mapping; */
 	/* ForeignDataWrapper *wrapper; */
-	ListCell *cell;
+	ListCell* cell;
 	OgrConnection ogr;
 
 	/* Gather all data for the foreign table. */
@@ -503,41 +594,51 @@ ogrGetConnectionFromTable(Oid foreigntableid, bool updateable)
 
 	ogr = ogrGetConnectionFromServer(table->serverid, updateable);
 
-	foreach(cell, table->options)
+	foreach (cell, table->options)
 	{
-		DefElem *def = (DefElem *) lfirst(cell);
+		DefElem* def = (DefElem*) lfirst(cell);
 		if (streq(def->defname, OPT_LAYER))
+		{
 			ogr.lyr_str = defGetString(def);
+		}
 		if (streq(def->defname, OPT_UPDATEABLE))
 		{
-			if ( defGetBoolean(def) )
+			if (defGetBoolean(def))
+			{
+				if (ogr.ds_updateable == OGR_UPDATEABLE_FALSE)
+				{
+					ereport(ERROR, (
+					        errcode(ERRCODE_FDW_ERROR),
+					        errmsg("data source \"%s\" is not updateable", ogr.ds_str),
+					        errhint("cannot set table '%s' option to true", OPT_UPDATEABLE)
+					        ));
+				}
 				ogr.lyr_updateable = OGR_UPDATEABLE_TRUE;
+			}
 			else
+			{
 				ogr.lyr_updateable = OGR_UPDATEABLE_FALSE;
+			}
 		}
 	}
 
-	if ( ! ogr.lyr_str )
+	if (!ogr.lyr_str)
+	{
 		elog(ERROR, "FDW table '%s' option is missing", OPT_LAYER);
-
-	if ( updateable && ogr.lyr_updateable == OGR_UPDATEABLE_FALSE )
-		ereport(ERROR,
-			(errcode(ERRCODE_FDW_ERROR),
-			 errmsg("updates are not allowed on foreign table '%s'", get_rel_name(table->relid)),
-			 errhint("ALTER FOREIGN TABLE %s OPTIONS (SET updatable 'true')", get_rel_name(table->relid))));
+	}
 
 	/* Does the layer exist in the data source? */
 	ogr.lyr = GDALDatasetGetLayerByName(ogr.ds, ogr.lyr_str);
-	if ( ! ogr.lyr )
+	if (!ogr.lyr)
 	{
-		const char *ogrerr = CPLGetLastErrorMsg();
+		const char* ogrerr = CPLGetLastErrorMsg();
 		ereport(ERROR, (
-				errcode(ERRCODE_FDW_OPTION_NAME_NOT_FOUND),
-				errmsg("unable to connect to %s to \"%s\"", OPT_LAYER, ogr.lyr_str),
-				(ogrerr && ! streq(ogrerr, ""))
-				? errhint("%s", ogrerr)
-				: errhint("Does the layer exist?")
-				));
+		        errcode(ERRCODE_FDW_TABLE_NOT_FOUND),
+		        errmsg("unable to connect to %s to \"%s\"", OPT_LAYER, ogr.lyr_str),
+		        (ogrerr && ! streq(ogrerr, ""))
+		            ? errhint("%s", ogrerr)
+		            : errhint("Does the layer exist?")
+		        ));
 	}
 	ogr.lyr_utf8 = OGR_L_TestCapability(ogr.lyr, OLCStringsAsUTF8);
 
@@ -553,23 +654,23 @@ ogrGetConnectionFromTable(Oid foreigntableid, bool updateable)
 Datum
 ogr_fdw_validator(PG_FUNCTION_ARGS)
 {
-	List *options_list = untransformRelOptions(PG_GETARG_DATUM(0));
+	List* options_list = untransformRelOptions(PG_GETARG_DATUM(0));
 	Oid catalog = PG_GETARG_OID(1);
-	ListCell *cell;
-	struct OgrFdwOption *opt;
-	const char *source = NULL, *driver = NULL;
-	const char *config_options = NULL, *open_options = NULL;
-	bool updateable = false;
+	ListCell* cell;
+	struct OgrFdwOption* opt;
+	const char* source = NULL, *driver = NULL;
+	const char* config_options = NULL, *open_options = NULL;
+	OgrUpdateable updateable = OGR_UPDATEABLE_FALSE;
 
 	/* Check that the database encoding is UTF8, to match OGR internals */
-	if ( GetDatabaseEncoding() != PG_UTF8 )
+	if (GetDatabaseEncoding() != PG_UTF8)
 	{
 		elog(ERROR, "OGR FDW only works with UTF-8 databases");
 		PG_RETURN_VOID();
 	}
 
 	/* Initialize found state to not found */
-	for ( opt = valid_options; opt->optname; opt++ )
+	for (opt = valid_options; opt->optname; opt++)
 	{
 		opt->optfound = false;
 	}
@@ -578,41 +679,54 @@ ogr_fdw_validator(PG_FUNCTION_ARGS)
 	 * Check that only options supported by ogr_fdw, and allowed for the
 	 * current object type, are given.
 	 */
-	foreach(cell, options_list)
+	foreach (cell, options_list)
 	{
-		DefElem *def = (DefElem *) lfirst(cell);
+		DefElem* def = (DefElem*) lfirst(cell);
 		bool optfound = false;
 
-		for ( opt = valid_options; opt->optname; opt++ )
+		for (opt = valid_options; opt->optname; opt++)
 		{
-			if ( catalog == opt->optcontext && streq(opt->optname, def->defname) )
+			if (catalog == opt->optcontext && streq(opt->optname, def->defname))
 			{
 				/* Mark that this user option was found */
 				opt->optfound = optfound = true;
 
 				/* Store some options for testing later */
-				if ( streq(opt->optname, OPT_SOURCE) )
+				if (streq(opt->optname, OPT_SOURCE))
+				{
 					source = defGetString(def);
-				if ( streq(opt->optname, OPT_DRIVER) )
+				}
+				if (streq(opt->optname, OPT_DRIVER))
+				{
 					driver = defGetString(def);
-				if ( streq(opt->optname, OPT_CONFIG_OPTIONS) )
+				}
+				if (streq(opt->optname, OPT_CONFIG_OPTIONS))
+				{
 					config_options = defGetString(def);
-				if ( streq(opt->optname, OPT_OPEN_OPTIONS) )
+				}
+				if (streq(opt->optname, OPT_OPEN_OPTIONS))
+				{
 					open_options = defGetString(def);
-				if ( streq(opt->optname, OPT_UPDATEABLE) )
-					updateable = defGetBoolean(def);
+				}
+				if (streq(opt->optname, OPT_UPDATEABLE))
+				{
+					if (defGetBoolean(def))
+					{
+						updateable = OGR_UPDATEABLE_TRY;
+					}
+				}
 
 				break;
 			}
 		}
 
-		if ( ! optfound )
+		if (!optfound)
 		{
 			/*
 			 * Unknown option specified, complain about it. Provide a hint
 			 * with list of valid options for the object.
 			 */
-			const struct OgrFdwOption *opt;
+			const struct OgrFdwOption* opt;
 			StringInfoData buf;
 
 			initStringInfo(&buf);
@@ -620,38 +734,45 @@ ogr_fdw_validator(PG_FUNCTION_ARGS)
 			{
 				if (catalog == opt->optcontext)
 					appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "",
-									 opt->optname);
+					                 opt->optname);
 			}
 
 			ereport(ERROR, (
-				errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
-				errmsg("invalid option \"%s\"", def->defname),
-				buf.len > 0
-				? errhint("Valid options in this context are: %s", buf.data)
-				: errhint("There are no valid options in this context.")));
+			            errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
+			            errmsg("invalid option \"%s\"", def->defname),
+			            buf.len > 0
+			            ? errhint("Valid options in this context are: %s", buf.data)
+			            : errhint("There are no valid options in this context.")));
 		}
 	}
 
 	/* Check that all the mandatory options were found */
-	for ( opt = valid_options; opt->optname; opt++ )
+	for (opt = valid_options; opt->optname; opt++)
 	{
 		/* Required option for this catalog type is missing? */
-		if ( catalog == opt->optcontext && opt->optrequired && ! opt->optfound )
+		if (catalog == opt->optcontext && opt->optrequired && ! opt->optfound)
 		{
 			ereport(ERROR, (
-					errcode(ERRCODE_FDW_DYNAMIC_PARAMETER_VALUE_NEEDED),
-					errmsg("required option \"%s\" is missing", opt->optname)));
+			            errcode(ERRCODE_FDW_DYNAMIC_PARAMETER_VALUE_NEEDED),
+			            errmsg("required option \"%s\" is missing", opt->optname)));
 		}
 	}
 
 	/* Make sure server connection can actually be established */
-	if ( catalog == ForeignServerRelationId && source )
+	if (catalog == ForeignServerRelationId && source)
 	{
-		OGRDataSourceH ogr_ds;
-		ogr_ds = ogrGetDataSource(source, driver, updateable, config_options, open_options);
-		if ( ogr_ds )
+		OgrConnection ogr;
+		OGRErr err;
+
+		ogr.ds_str = source;
+		ogr.dr_str = driver;
+		ogr.config_options = config_options;
+		ogr.open_options = open_options;
+
+		err = ogrGetDataSource(&ogr, updateable);
+		if (ogr.ds)
 		{
-			GDALClose(ogr_ds);
+			GDALClose(ogr.ds);
 		}
 	}
 
@@ -664,26 +785,26 @@ ogr_fdw_validator(PG_FUNCTION_ARGS)
 static OgrFdwState*
 getOgrFdwState(Oid foreigntableid, OgrFdwStateType state_type)
 {
-	OgrFdwState *state;
+	OgrFdwState* state;
 	size_t size;
-	bool updateable = false;
+	OgrUpdateable updateable = OGR_UPDATEABLE_FALSE;
 
 	switch (state_type)
 	{
-		case OGR_PLAN_STATE:
-			size = sizeof(OgrFdwPlanState);
-			updateable = false;
-			break;
-		case OGR_EXEC_STATE:
-			size = sizeof(OgrFdwExecState);
-			updateable = false;
-			break;
-		case OGR_MODIFY_STATE:
-			updateable = true;
-			size = sizeof(OgrFdwModifyState);
-			break;
-		default:
-			elog(ERROR, "invalid state type");
+	case OGR_PLAN_STATE:
+		size = sizeof(OgrFdwPlanState);
+		updateable = OGR_UPDATEABLE_FALSE;
+		break;
+	case OGR_EXEC_STATE:
+		size = sizeof(OgrFdwExecState);
+		updateable = OGR_UPDATEABLE_FALSE;
+		break;
+	case OGR_MODIFY_STATE:
+		updateable = OGR_UPDATEABLE_TRUE;
+		size = sizeof(OgrFdwModifyState);
+		break;
+	default:
+		elog(ERROR, "invalid state type");
 	}
 
 	state = palloc0(size);
@@ -703,14 +824,14 @@ getOgrFdwState(Oid foreigntableid, OgrFdwStateType state_type)
  *		Obtain relation size estimates for a foreign table
  */
 static void
-ogrGetForeignRelSize(PlannerInfo *root,
-                     RelOptInfo *baserel,
+ogrGetForeignRelSize(PlannerInfo* root,
+                     RelOptInfo* baserel,
                      Oid foreigntableid)
 {
 	/* Initialize the OGR connection */
-	OgrFdwState *state = (OgrFdwState *)getOgrFdwState(foreigntableid, OGR_PLAN_STATE);
-	OgrFdwPlanState *planstate = (OgrFdwPlanState *)state;
-	List *scan_clauses = baserel->baserestrictinfo;
+	OgrFdwState* state = (OgrFdwState*)getOgrFdwState(foreigntableid, OGR_PLAN_STATE);
+	OgrFdwPlanState* planstate = (OgrFdwPlanState*)state;
+	List* scan_clauses = baserel->baserestrictinfo;
 
 	/* Set to NULL to clear the restriction clauses in OGR */
 	OGR_L_SetIgnoredFields(planstate->ogr.lyr, NULL);
@@ -733,14 +854,14 @@ ogrGetForeignRelSize(PlannerInfo *root,
 	*/
 
 	/* If we can quickly figure how many rows this layer has, then do so */
-	if ( scan_clauses == NIL &&
-	     OGR_L_TestCapability(planstate->ogr.lyr, OLCFastFeatureCount) == TRUE &&
-	     ogrCanReallyCountFast(&(planstate->ogr)) )
+	if (scan_clauses == NIL &&
+	        OGR_L_TestCapability(planstate->ogr.lyr, OLCFastFeatureCount) == TRUE &&
+	        ogrCanReallyCountFast(&(planstate->ogr)))
 	{
 		/* Count rows, but don't force a slow count */
 		int rows = OGR_L_GetFeatureCount(planstate->ogr.lyr, false);
 		/* Only use row count if return is valid (>0) */
-		if ( rows >= 0 )
+		if (rows >= 0)
 		{
 			planstate->nrows = rows;
 			baserel->rows = rows;
@@ -748,7 +869,7 @@ ogrGetForeignRelSize(PlannerInfo *root,
 	}
 
 	/* Save connection state for next calls */
-	baserel->fdw_private = (void *) planstate;
+	baserel->fdw_private = (void*) planstate;
 
 	return;
 }
@@ -764,11 +885,11 @@ ogrGetForeignRelSize(PlannerInfo *root,
  *		the data file.
  */
 static void
-ogrGetForeignPaths(PlannerInfo *root,
-                   RelOptInfo *baserel,
+ogrGetForeignPaths(PlannerInfo* root,
+                   RelOptInfo* baserel,
                    Oid foreigntableid)
 {
-	OgrFdwPlanState *planstate = (OgrFdwPlanState *)(baserel->fdw_private);
+	OgrFdwPlanState* planstate = (OgrFdwPlanState*)(baserel->fdw_private);
 
 	/* TODO: replace this with something that looks at the OGRDriver and */
 	/* makes a determination based on that? Better: add connection caching */
@@ -784,21 +905,21 @@ ogrGetForeignPaths(PlannerInfo *root,
 	/* explain info on how they complete the query, not for something as */
 	/* obtuse as OGR. (So far, have only seen it w/ the postgres_fdw */
 	add_path(baserel,
-		(Path *) create_foreignscan_path(root, baserel,
+	         (Path*) create_foreignscan_path(root, baserel,
 #if PG_VERSION_NUM >= 90600
-					NULL, /* PathTarget */
+	                 NULL, /* PathTarget */
 #endif
-					baserel->rows,
-					planstate->startup_cost,
-					planstate->total_cost,
-					NIL,     /* no pathkeys */
-					NULL,    /* no outer rel either */
-					NULL  /* no extra plan */
+	                 baserel->rows,
+	                 planstate->startup_cost,
+	                 planstate->total_cost,
+	                 NIL,     /* no pathkeys */
+	                 NULL,    /* no outer rel either */
+	                 NULL  /* no extra plan */
 #if PG_VERSION_NUM >= 90500
-					,NIL /* no fdw_private list */
+	                 , NIL /* no fdw_private list */
 #endif
-					)
-		);   /* no fdw_private data */
+	                                        )
+	        );   /* no fdw_private data */
 }
 
 
@@ -808,25 +929,25 @@ ogrGetForeignPaths(PlannerInfo *root,
  * fileGetForeignPlan
  *		Create a ForeignScan plan node for scanning the foreign table
  */
-static ForeignScan *
-ogrGetForeignPlan(PlannerInfo *root,
-                  RelOptInfo *baserel,
+static ForeignScan*
+ogrGetForeignPlan(PlannerInfo* root,
+                  RelOptInfo* baserel,
                   Oid foreigntableid,
-                  ForeignPath *best_path,
-                  List *tlist,
-                  List *scan_clauses
+                  ForeignPath* best_path,
+                  List* tlist,
+                  List* scan_clauses
 #if PG_VERSION_NUM >= 90500
-                  ,Plan *outer_plan
+                  , Plan* outer_plan
 #endif
-                  )
+                 )
 {
 	Index scan_relid = baserel->relid;
 	bool sql_generated;
 	StringInfoData sql;
-	List *params_list = NULL;
-	List *fdw_private;
-	OgrFdwPlanState *planstate = (OgrFdwPlanState *)(baserel->fdw_private);
-	OgrFdwState *state = (OgrFdwState *)(baserel->fdw_private);
+	List* params_list = NULL;
+	List* fdw_private;
+	OgrFdwPlanState* planstate = (OgrFdwPlanState*)(baserel->fdw_private);
+	OgrFdwState* state = (OgrFdwState*)(baserel->fdw_private);
 
 	/* Add in column mapping data to build SQL with the right OGR column names */
 	ogrReadColumnData(state);
@@ -838,7 +959,7 @@ ogrGetForeignPlan(PlannerInfo *root,
 	 */
 	initStringInfo(&sql);
 	sql_generated = ogrDeparse(&sql, root, baserel, scan_clauses, state, &params_list);
-	elog(DEBUG1,"OGR SQL: %s", sql.data);
+	elog(DEBUG1, "OGR SQL: %s", sql.data);
 
 	/*
 	 * Here we strip RestrictInfo
@@ -860,10 +981,14 @@ ogrGetForeignPlan(PlannerInfo *root,
 	 *
 	 * TODO: Pass a spatial filter down also.
 	 */
-	if ( sql_generated )
+	if (sql_generated)
+	{
 		fdw_private = list_make2(makeString(sql.data), params_list);
+	}
 	else
+	{
 		fdw_private = list_make2(NULL, params_list);
+	}
 
 	/*
 	 * Clean up our connection
@@ -872,165 +997,219 @@ ogrGetForeignPlan(PlannerInfo *root,
 
 	/* Create the ForeignScan node */
 	return make_foreignscan(tlist,
-							scan_clauses,
-							scan_relid,
-							NIL,	/* no expressions to evaluate */
-							fdw_private
+	                        scan_clauses,
+	                        scan_relid,
+	                        NIL,	/* no expressions to evaluate */
+	                        fdw_private
 #if PG_VERSION_NUM >= 90500
-							,NIL  /* no scan_tlist */
-							,NIL   /* no remote quals */
-							,outer_plan
+	                        , NIL /* no scan_tlist */
+	                        , NIL  /* no remote quals */
+	                        , outer_plan
 #endif
-);
+	                       );
 
 
 }
 
 static void
-pgCanConvertToOgr(Oid pg_type, OGRFieldType ogr_type, const char *colname, const char *tblname)
+pgCanConvertToOgr(Oid pg_type, OGRFieldType ogr_type, const char* colname, const char* tblname)
 {
-	if ( pg_type == BOOLOID && ogr_type == OFTInteger )
+	if (pg_type == BOOLOID && ogr_type == OFTInteger)
+	{
 		return;
-	else if ( pg_type == INT2OID && ogr_type == OFTInteger )
+	}
+	else if (pg_type == INT2OID && ogr_type == OFTInteger)
+	{
 		return;
-	else if ( pg_type == INT4OID && ogr_type == OFTInteger )
+	}
+	else if (pg_type == INT4OID && ogr_type == OFTInteger)
+	{
 		return;
-	else if ( pg_type == INT8OID )
+	}
+	else if (pg_type == INT8OID)
 	{
 #if GDAL_VERSION_MAJOR >= 2
-		if ( ogr_type == OFTInteger64 )
+		if (ogr_type == OFTInteger64)
+		{
 			return;
+		}
 #else
-		if ( ogr_type == OFTInteger )
+		if (ogr_type == OFTInteger)
+		{
 			return;
+		}
 #endif
 	}
-	else if ( pg_type == NUMERICOID && ogr_type == OFTReal )
+	else if (pg_type == NUMERICOID && ogr_type == OFTReal)
+	{
 		return;
-	else if ( pg_type == FLOAT4OID && ogr_type == OFTReal )
+	}
+	else if (pg_type == FLOAT4OID && ogr_type == OFTReal)
+	{
 		return;
-	else if ( pg_type == FLOAT8OID && ogr_type == OFTReal )
+	}
+	else if (pg_type == FLOAT8OID && ogr_type == OFTReal)
+	{
 		return;
-	else if ( pg_type == TEXTOID && ogr_type == OFTString )
+	}
+	else if (pg_type == TEXTOID && ogr_type == OFTString)
+	{
 		return;
-	else if ( pg_type == VARCHAROID && ogr_type == OFTString )
+	}
+	else if (pg_type == VARCHAROID && ogr_type == OFTString)
+	{
 		return;
-	else if ( pg_type == CHAROID && ogr_type == OFTString )
+	}
+	else if (pg_type == CHAROID && ogr_type == OFTString)
+	{
 		return;
-	else if ( pg_type == BPCHAROID && ogr_type == OFTString )
+	}
+	else if (pg_type == BPCHAROID && ogr_type == OFTString)
+	{
 		return;
-	else if ( pg_type == NAMEOID && ogr_type == OFTString )
+	}
+	else if (pg_type == NAMEOID && ogr_type == OFTString)
+	{
 		return;
-	else if ( pg_type == BYTEAOID && ogr_type == OFTBinary )
+	}
+	else if (pg_type == BYTEAOID && ogr_type == OFTBinary)
+	{
 		return;
-	else if ( pg_type == DATEOID && ogr_type == OFTDate )
+	}
+	else if (pg_type == DATEOID && ogr_type == OFTDate)
+	{
 		return;
-	else if ( pg_type == TIMEOID && ogr_type == OFTTime )
+	}
+	else if (pg_type == TIMEOID && ogr_type == OFTTime)
+	{
 		return;
-	else if ( pg_type == TIMESTAMPOID && ogr_type == OFTDateTime )
+	}
+	else if (pg_type == TIMESTAMPOID && ogr_type == OFTDateTime)
+	{
 		return;
+	}
 
 	ereport(ERROR, (
-			errcode(ERRCODE_FDW_INVALID_DATA_TYPE),
-			errmsg("column \"%s\" of foreign table \"%s\" converts \"%s\" to OGR \"%s\"",
-				colname, tblname,
-				format_type_be(pg_type), OGR_GetFieldTypeName(ogr_type))
-			));
+	            errcode(ERRCODE_FDW_INVALID_DATA_TYPE),
+	            errmsg("column \"%s\" of foreign table \"%s\" converts \"%s\" to OGR \"%s\"",
+	                   colname, tblname,
+	                   format_type_be(pg_type), OGR_GetFieldTypeName(ogr_type))
+	        ));
 }
 
 static void
-ogrCanConvertToPg(OGRFieldType ogr_type, Oid pg_type, const char *colname, const char *tblname)
+ogrCanConvertToPg(OGRFieldType ogr_type, Oid pg_type, const char* colname, const char* tblname)
 {
 	switch (ogr_type)
 	{
-		case OFTInteger:
-			if ( pg_type == BOOLOID ||  pg_type == INT4OID || pg_type == INT8OID || pg_type == NUMERICOID || pg_type == FLOAT4OID || pg_type == FLOAT8OID || pg_type == TEXTOID || pg_type == VARCHAROID )
-				return;
-			break;
-
-		case OFTReal:
-			if ( pg_type == NUMERICOID || pg_type == FLOAT4OID || pg_type == FLOAT8OID || pg_type == TEXTOID || pg_type == VARCHAROID )
-				return;
-			break;
-
-		case OFTBinary:
-			if ( pg_type == BYTEAOID )
-				return;
-			break;
-
-		case OFTString:
-			if ( pg_type == TEXTOID || pg_type == VARCHAROID || pg_type == CHAROID || pg_type == BPCHAROID )
-				return;
-			break;
-
-		case OFTDate:
-			if ( pg_type == DATEOID || pg_type == TIMESTAMPOID || pg_type == TEXTOID || pg_type == VARCHAROID )
-				return;
-			break;
-
-		case OFTTime:
-			if ( pg_type == TIMEOID || pg_type == TEXTOID || pg_type == VARCHAROID )
-				return;
-			break;
-
-		case OFTDateTime:
-			if ( pg_type == TIMESTAMPOID || pg_type == TEXTOID || pg_type == VARCHAROID )
-				return;
-			break;
+	case OFTInteger:
+		if (pg_type == BOOLOID ||  pg_type == INT4OID || pg_type == INT8OID ||
+		    pg_type == NUMERICOID || pg_type == FLOAT4OID ||
+		    pg_type == FLOAT8OID || pg_type == TEXTOID || pg_type == VARCHAROID)
+		{
+			return;
+		}
+		break;
+
+	case OFTReal:
+		if (pg_type == NUMERICOID || pg_type == FLOAT4OID || pg_type == FLOAT8OID ||
+		    pg_type == TEXTOID || pg_type == VARCHAROID)
+		{
+			return;
+		}
+		break;
+
+	case OFTBinary:
+		if (pg_type == BYTEAOID)
+		{
+			return;
+		}
+		break;
+
+	case OFTString:
+		if (pg_type == TEXTOID || pg_type == VARCHAROID || pg_type == CHAROID || pg_type == BPCHAROID)
+		{
+			return;
+		}
+		break;
+
+	case OFTDate:
+		if (pg_type == DATEOID || pg_type == TIMESTAMPOID || pg_type == TEXTOID || pg_type == VARCHAROID)
+		{
+			return;
+		}
+		break;
+
+	case OFTTime:
+		if (pg_type == TIMEOID || pg_type == TEXTOID || pg_type == VARCHAROID)
+		{
+			return;
+		}
+		break;
+
+	case OFTDateTime:
+		if (pg_type == TIMESTAMPOID || pg_type == TEXTOID || pg_type == VARCHAROID)
+		{
+			return;
+		}
+		break;
 
 #if GDAL_VERSION_MAJOR >= 2
-		case OFTInteger64:
-			if ( pg_type == INT8OID || pg_type == NUMERICOID || pg_type == FLOAT8OID || pg_type == TEXTOID || pg_type == VARCHAROID )
-				return;
-			break;
+	case OFTInteger64:
+		if (pg_type == INT8OID || pg_type == NUMERICOID || pg_type == FLOAT8OID ||
+		    pg_type == TEXTOID || pg_type == VARCHAROID)
+		{
+			return;
+		}
+		break;
 #endif
 
-		case OFTWideString:
-		case OFTIntegerList:
+	case OFTWideString:
+	case OFTIntegerList:
 #if GDAL_VERSION_MAJOR >= 2
-		case OFTInteger64List:
+	case OFTInteger64List:
 #endif
-		case OFTRealList:
-		case OFTStringList:
-		case OFTWideStringList:
-		{
-			ereport(ERROR, (
-					errcode(ERRCODE_FDW_INVALID_DATA_TYPE),
-					errmsg("column \"%s\" of foreign table \"%s\" uses an OGR array, currently unsupported", colname, tblname)
-					));
-			break;
-		}
+	case OFTRealList:
+	case OFTStringList:
+	case OFTWideStringList:
+	{
+		ereport(ERROR, (
+		        errcode(ERRCODE_FDW_INVALID_DATA_TYPE),
+		        errmsg("column \"%s\" of foreign table \"%s\" uses an OGR array, currently unsupported", colname, tblname)
+		        ));
+		break;
+	}
 	}
 	ereport(ERROR, (
-			errcode(ERRCODE_FDW_INVALID_DATA_TYPE),
-			errmsg("column \"%s\" of foreign table \"%s\" converts OGR \"%s\" to \"%s\"",
-				colname, tblname,
-				OGR_GetFieldTypeName(ogr_type), format_type_be(pg_type))
-			));
+	        errcode(ERRCODE_FDW_INVALID_DATA_TYPE),
+	        errmsg("column \"%s\" of foreign table \"%s\" converts OGR \"%s\" to \"%s\"",
+	               colname, tblname,
+	               OGR_GetFieldTypeName(ogr_type), format_type_be(pg_type))
+	        ));
 }
 
 #ifdef OGR_FDW_HEXWKB
 
-static char *hexchr = "0123456789ABCDEF";
+static char* hexchr = "0123456789ABCDEF";
 
-static char *
-ogrBytesToHex(unsigned char *bytes, size_t size)
+static char*
+ogrBytesToHex(unsigned char* bytes, size_t size)
 {
-	char *hex;
+	char* hex;
 	int i;
-	if ( ! bytes || ! size )
+	if (! bytes || ! size)
 	{
 		elog(ERROR, "hexbytes_from_bytes: invalid input");
 		return NULL;
 	}
 	hex = palloc(size * 2 + 1);
-	hex[2*size] = '\0';
-	for( i = 0; i < size; i++ )
+	hex[2 * size] = '\0';
+	for (i = 0; i < size; i++)
 	{
 		/* Top four bits to 0-F */
-		hex[2*i] = hexchr[bytes[i] >> 4];
+		hex[2 * i] = hexchr[bytes[i] >> 4];
 		/* Bottom four bits to 0-F */
-		hex[2*i+1] = hexchr[bytes[i] & 0x0F];
+		hex[2 * i + 1] = hexchr[bytes[i] & 0x0F];
 	}
 	return hex;
 }
@@ -1038,26 +1217,33 @@ ogrBytesToHex(unsigned char *bytes, size_t size)
 #endif
 
 static void
-freeOgrFdwTable(OgrFdwTable *table)
+freeOgrFdwTable(OgrFdwTable* table)
 {
-	if ( table )
+	if (table)
 	{
-		if ( table->tblname ) pfree(table->tblname);
-		if ( table->cols ) pfree(table->cols);
+		if (table->tblname)
+		{
+			pfree(table->tblname);
+		}
+		if (table->cols)
+		{
+			pfree(table->cols);
+		}
 		pfree(table);
 	}
 }
 
 typedef struct
 {
-	char *fldname;
+	char* fldname;
 	int fldnum;
 } OgrFieldEntry;
 
-static int ogrFieldEntryCmpFunc(const void * a, const void * b)
+static int
+ogrFieldEntryCmpFunc(const void* a, const void* b)
 {
-	const char *a_name = ((OgrFieldEntry*)a)->fldname;
-	const char *b_name = ((OgrFieldEntry*)b)->fldname;
+	const char* a_name = ((OgrFieldEntry*)a)->fldname;
+	const char* b_name = ((OgrFieldEntry*)b)->fldname;
 
 	return strcasecmp(a_name, b_name);
 }
@@ -1072,24 +1258,24 @@ static int ogrFieldEntryCmpFunc(const void * a, const void * b)
  * returns.
  */
 static void
-ogrReadColumnData(OgrFdwState *state)
+ogrReadColumnData(OgrFdwState* state)
 {
 	Relation rel;
 	TupleDesc tupdesc;
 	int i;
-	OgrFdwTable *tbl;
+	OgrFdwTable* tbl;
 	OGRFeatureDefnH dfn;
 	int ogr_ncols;
 	int fid_count = 0;
 	int geom_count = 0;
 	int ogr_geom_count = 0;
 	int field_count = 0;
-	OgrFieldEntry *ogr_fields;
+	OgrFieldEntry* ogr_fields;
 	int ogr_fields_count = 0;
-	char *tblname = get_rel_name(state->foreigntableid);
+	char* tblname = get_rel_name(state->foreigntableid);
 
 	/* Blow away any existing table in the state */
-	if ( state->table )
+	if (state->table)
 	{
 		freeOgrFdwTable(state->table);
 		state->table = NULL;
@@ -1112,7 +1298,7 @@ ogrReadColumnData(OgrFdwState *state)
 #if (GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0))
 	ogr_geom_count = OGR_FD_GetGeomFieldCount(dfn);
 #else
-	ogr_geom_count = ( OGR_FD_GetGeomType(dfn) != wkbNone ) ? 1 : 0;
+	ogr_geom_count = (OGR_FD_GetGeomType(dfn) != wkbNone) ? 1 : 0;
 #endif
 
 
@@ -1121,26 +1307,26 @@ ogrReadColumnData(OgrFdwState *state)
 	/* We will search both the original and laundered OGR field names for matches */
 	ogr_fields_count = 2 * ogr_ncols;
 	ogr_fields = palloc0(ogr_fields_count * sizeof(OgrFieldEntry));
-	for ( i = 0; i < ogr_ncols; i++ )
+	for (i = 0; i < ogr_ncols; i++)
 	{
-		char *fldname = pstrdup(OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(dfn, i)));
-		char *fldname_laundered = palloc(STR_MAX_LEN);
+		char* fldname = pstrdup(OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(dfn, i)));
+		char* fldname_laundered = palloc(STR_MAX_LEN);
 		strncpy(fldname_laundered, fldname, STR_MAX_LEN);
 		ogrStringLaunder(fldname_laundered);
-		ogr_fields[2*i].fldname = fldname;
-		ogr_fields[2*i].fldnum = i;
-		ogr_fields[2*i+1].fldname = fldname_laundered;
-		ogr_fields[2*i+1].fldnum = i;
+		ogr_fields[2 * i].fldname = fldname;
+		ogr_fields[2 * i].fldnum = i;
+		ogr_fields[2 * i + 1].fldname = fldname_laundered;
+		ogr_fields[2 * i + 1].fldnum = i;
 	}
 	qsort(ogr_fields, ogr_fields_count, sizeof(OgrFieldEntry), ogrFieldEntryCmpFunc);
 
 
 	/* loop through foreign table columns */
-	for ( i = 0; i < tbl->ncols; i++ )
+	for (i = 0; i < tbl->ncols; i++)
 	{
-		List *options;
-		ListCell *lc;
-		OgrFieldEntry *found_entry;
+		List* options;
+		ListCell* lc;
+		OgrFieldEntry* found_entry;
 		OgrFieldEntry entry;
 
 #if PG_VERSION_NUM >= 110000
@@ -1155,8 +1341,10 @@ ogrReadColumnData(OgrFdwState *state)
 		col.pgattisdropped = att_tuple->attisdropped;
 
 		/* Skip filling in any further metadata about dropped columns */
-		if ( col.pgattisdropped )
+		if (col.pgattisdropped)
+		{
 			continue;
+		}
 
 		/* Find the appropriate conversion functions */
 		getTypeInputInfo(col.pgtype, &col.pginputfunc, &col.pginputioparam);
@@ -1172,10 +1360,13 @@ ogrReadColumnData(OgrFdwState *state)
 #endif
 
 		/* Handle FID first */
-		if ( strcaseeq(col.pgname, "fid") && (col.pgtype == INT4OID || col.pgtype == INT8OID) )
+		if (strcaseeq(col.pgname, "fid") &&
+		    (col.pgtype == INT4OID || col.pgtype == INT8OID))
 		{
-			if ( fid_count >= 1 )
+			if (fid_count >= 1)
+			{
 				elog(ERROR, "FDW table '%s' includes more than one FID column", tblname);
+			}
 
 			col.ogrvariant = OGR_FID;
 			col.ogrfldnum = fid_count++;
@@ -1185,7 +1376,7 @@ ogrReadColumnData(OgrFdwState *state)
 
 		/* If the OGR source has geometries, can we match them to Pg columns? */
 		/* We'll match to the first ones we find, irrespective of name */
-		if ( geom_count < ogr_geom_count && col.pgtype == ogrGetGeometryOid() )
+		if (geom_count < ogr_geom_count && col.pgtype == ogrGetGeometryOid())
 		{
 			col.ogrvariant = OGR_GEOMETRY;
 			col.ogrfldtype = OFTBinary;
@@ -1205,11 +1396,11 @@ ogrReadColumnData(OgrFdwState *state)
 		 * want to search for *that* in the OGR layer.
 		 */
 		options = GetForeignColumnOptions(state->foreigntableid, i + 1);
-		foreach(lc, options)
+		foreach (lc, options)
 		{
-			DefElem    *def = (DefElem *) lfirst(lc);
+			DefElem*    def = (DefElem*) lfirst(lc);
 
-			if ( streq(def->defname, OPT_COLUMN) )
+			if (streq(def->defname, OPT_COLUMN))
 			{
 				entry.fldname = defGetString(def);
 				break;
@@ -1220,7 +1411,7 @@ ogrReadColumnData(OgrFdwState *state)
 		found_entry = bsearch(&entry, ogr_fields, ogr_fields_count, sizeof(OgrFieldEntry), ogrFieldEntryCmpFunc);
 
 		/* Column name matched, so save this entry, if the types are consistent */
-		if ( found_entry )
+		if (found_entry)
 		{
 			OGRFieldDefnH fld = OGR_FD_GetFieldDefn(dfn, found_entry->fldnum);
 			OGRFieldType fldtype = OGR_Fld_GetType(fld);
@@ -1240,13 +1431,19 @@ ogrReadColumnData(OgrFdwState *state)
 		tbl->cols[i] = col;
 	}
 
-	elog(DEBUG2, "ogrReadColumnData matched %d FID, %d GEOM, %d FIELDS out of %d PGSQL COLUMNS", fid_count, geom_count, field_count, tbl->ncols);
+	elog(DEBUG2, "ogrReadColumnData matched %d FID, %d GEOM, %d FIELDS out of %d PGSQL COLUMNS", fid_count, geom_count,
+	     field_count, tbl->ncols);
 
 	/* Clean up */
 
 	state->table = tbl;
-	for( i = 0; i < 2*ogr_ncols; i++ )
-		if ( ogr_fields[i].fldname ) pfree(ogr_fields[i].fldname);
+	for (i = 0; i < 2 * ogr_ncols; i++)
+	{
+		if (ogr_fields[i].fldname)
+		{
+			pfree(ogr_fields[i].fldname);
+		}
+	}
 	pfree(ogr_fields);
 	heap_close(rel, NoLock);
 
@@ -1260,14 +1457,16 @@ ogrReadColumnData(OgrFdwState *state)
  * them later.
  */
 static Oid
-ogrLookupGeometryFunctionOid(const char *proname)
+ogrLookupGeometryFunctionOid(const char* proname)
 {
-	List *names;
+	List* names;
 	FuncCandidateList clist;
 
 	/* This only works if PostGIS is installed */
-	if ( ogrGetGeometryOid() == InvalidOid || ogrGetGeometryOid() == BYTEAOID )
+	if (ogrGetGeometryOid() == InvalidOid || ogrGetGeometryOid() == BYTEAOID)
+	{
 		return InvalidOid;
+	}
 
 	names = stringToQualifiedNameList(proname);
 #if PG_VERSION_NUM < 90400
@@ -1275,20 +1474,22 @@ ogrLookupGeometryFunctionOid(const char *proname)
 #else
 	clist = FuncnameGetCandidates(names, -1, NIL, false, false, false);
 #endif
-	if ( streq(proname, "st_setsrid") )
+	if (streq(proname, "st_setsrid"))
 	{
 		do
 		{
 			int i;
-			for ( i = 0; i < clist->nargs; i++ )
+			for (i = 0; i < clist->nargs; i++)
 			{
-				if ( clist->args[i] == ogrGetGeometryOid() )
+				if (clist->args[i] == ogrGetGeometryOid())
+				{
 					return clist->oid;
+				}
 			}
 		}
-		while( (clist = clist->next) );
+		while ((clist = clist->next));
 	}
-	else if ( streq(proname, "postgis_typmod_srid") )
+	else if (streq(proname, "postgis_typmod_srid"))
 	{
 		return clist->oid;
 	}
@@ -1300,14 +1501,14 @@ ogrLookupGeometryFunctionOid(const char *proname)
  * ogrBeginForeignScan
  */
 static void
-ogrBeginForeignScan(ForeignScanState *node, int eflags)
+ogrBeginForeignScan(ForeignScanState* node, int eflags)
 {
 	Oid foreigntableid = RelationGetRelid(node->ss.ss_currentRelation);
-	ForeignScan *fsplan = (ForeignScan *)node->ss.ps.plan;
+	ForeignScan* fsplan = (ForeignScan*)node->ss.ps.plan;
 
 	/* Initialize OGR connection */
-	OgrFdwState *state = getOgrFdwState(foreigntableid, OGR_EXEC_STATE);
-	OgrFdwExecState *execstate = (OgrFdwExecState *)state;
+	OgrFdwState* state = getOgrFdwState(foreigntableid, OGR_EXEC_STATE);
+	OgrFdwExecState* execstate = (OgrFdwExecState*)state;
 
 	/* Read the OGR layer definition and PgSQL foreign table definitions */
 	ogrReadColumnData(state);
@@ -1320,25 +1521,25 @@ ogrBeginForeignScan(ForeignScanState *node, int eflags)
 	execstate->sql = strVal(list_nth(fsplan->fdw_private, 0));
 	// execstate->retrieved_attrs = (List *) list_nth(fsplan->fdw_private, 1);
 
-	if ( execstate->sql && strlen(execstate->sql) > 0 )
+	if (execstate->sql && strlen(execstate->sql) > 0)
 	{
 		OGRErr err = OGR_L_SetAttributeFilter(execstate->ogr.lyr, execstate->sql);
-		if ( err != OGRERR_NONE )
+		if (err != OGRERR_NONE)
 		{
-			const char *ogrerr = CPLGetLastErrorMsg();
+			const char* ogrerr = CPLGetLastErrorMsg();
 
-			if ( ogrerr && ! streq(ogrerr,"") )
+			if (ogrerr && ! streq(ogrerr, ""))
 			{
 				ereport(NOTICE,
-					(errcode(ERRCODE_FDW_ERROR),
-					 errmsg("unable to set OGR SQL '%s' on layer", execstate->sql),
-					 errhint("%s", ogrerr)));
+				        (errcode(ERRCODE_FDW_ERROR),
+				         errmsg("unable to set OGR SQL '%s' on layer", execstate->sql),
+				         errhint("%s", ogrerr)));
 			}
 			else
 			{
 				ereport(NOTICE,
-					(errcode(ERRCODE_FDW_ERROR),
-					 errmsg("unable to set OGR SQL '%s' on layer", execstate->sql)));
+				        (errcode(ERRCODE_FDW_ERROR),
+				         errmsg("unable to set OGR SQL '%s' on layer", execstate->sql)));
 			}
 		}
 	}
@@ -1348,7 +1549,7 @@ ogrBeginForeignScan(ForeignScanState *node, int eflags)
 	}
 
 	/* Save the state for the next call */
-	node->fdw_state = (void *) execstate;
+	node->fdw_state = (void*) execstate;
 
 	return;
 }
@@ -1360,20 +1561,20 @@ ogrBeginForeignScan(ForeignScanState *node, int eflags)
  * each column in the foreign table.
  */
 static Datum
-pgDatumFromCString(const char *cstr, Oid pgtype, int pgtypmod, Oid pginputfunc)
+pgDatumFromCString(const char* cstr, Oid pgtype, int pgtypmod, Oid pginputfunc)
 {
 	Datum value;
 	Datum cdata = CStringGetDatum(cstr);
 
 	value = OidFunctionCall3(pginputfunc, cdata,
-		ObjectIdGetDatum(InvalidOid),
-		Int32GetDatum(pgtypmod));
+	                         ObjectIdGetDatum(InvalidOid),
+	                         Int32GetDatum(pgtypmod));
 
 	return value;
 }
 
 static inline void
-ogrNullSlot(Datum *values, bool *nulls, int i)
+ogrNullSlot(Datum* values, bool* nulls, int i)
 {
 	values[i] = PointerGetDatum(NULL);
 	nulls[i] = true;
@@ -1394,27 +1595,27 @@ ogrNullSlot(Datum *values, bool *nulls, int i)
 * the type, then everything else.
 */
 static OGRErr
-ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecState *execstate)
+ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot* slot, const OgrFdwExecState* execstate)
 {
-	const OgrFdwTable *tbl = execstate->table;
+	const OgrFdwTable* tbl = execstate->table;
 	int i;
-	Datum *values = slot->tts_values;
-	bool *nulls = slot->tts_isnull;
+	Datum* values = slot->tts_values;
+	bool* nulls = slot->tts_isnull;
 	TupleDesc tupdesc = slot->tts_tupleDescriptor;
 	int have_typmod_funcs = (execstate->setsridfunc && execstate->typmodsridfunc);
 
 	/* Check our assumption that slot and setup data match */
-	if ( tbl->ncols != tupdesc->natts )
+	if (tbl->ncols != tupdesc->natts)
 	{
 		elog(ERROR, "FDW metadata table and exec table have mismatching number of columns");
 		return OGRERR_FAILURE;
 	}
 
 	/* For each pgtable column, get a value from OGR */
-	for ( i = 0; i < tbl->ncols; i++ )
+	for (i = 0; i < tbl->ncols; i++)
 	{
 		OgrFdwColumn col = tbl->cols[i];
-		const char *pgname = col.pgname;
+		const char* pgname = col.pgname;
 		Oid pgtype = col.pgtype;
 		int pgtypmod = col.pgtypmod;
 		Oid pginputfunc = col.pginputfunc;
@@ -1425,17 +1626,17 @@ ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecS
 		/*
 		 * Fill in dropped attributes with NULL
 		 */
-		if ( col.pgattisdropped )
+		if (col.pgattisdropped)
 		{
 			ogrNullSlot(values, nulls, i);
 			continue;
 		}
 
-		if ( ogrvariant == OGR_FID )
+		if (ogrvariant == OGR_FID)
 		{
 			GIntBig fid = OGR_F_GetFID(feat);
 
-			if ( fid == OGRNullFID )
+			if (fid == OGRNullFID)
 			{
 				ogrNullSlot(values, nulls, i);
 			}
@@ -1448,12 +1649,12 @@ ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecS
 				values[i] = pgDatumFromCString(fidstr, pgtype, pgtypmod, pginputfunc);
 			}
 		}
-		else if ( ogrvariant == OGR_GEOMETRY )
+		else if (ogrvariant == OGR_GEOMETRY)
 		{
 			int wkbsize;
 			int varsize;
-			bytea *varlena;
-			unsigned char *wkb;
+			bytea* varlena;
+			unsigned char* wkb;
 			OGRErr err;
 
 #if (GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0))
@@ -1463,7 +1664,7 @@ ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecS
 #endif
 
 			/* No geometry ? NULL */
-			if ( ! geom )
+			if (! geom)
 			{
 				/* No geometry column, so make the output null */
 				ogrNullSlot(values, nulls, i);
@@ -1477,17 +1678,17 @@ ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecS
 			wkbsize = OGR_G_WkbSize(geom);
 			varsize = wkbsize + VARHDRSZ;
 			varlena = palloc(varsize);
-			wkb = (unsigned char *)VARDATA(varlena);
+			wkb = (unsigned char*)VARDATA(varlena);
 			err = OGR_G_ExportToWkb(geom, wkbNDR, wkb);
 			SET_VARSIZE(varlena, varsize);
 
 			/* Couldn't create WKB from OGR geometry? error */
-			if ( err != OGRERR_NONE )
+			if (err != OGRERR_NONE)
 			{
 				return err;
 			}
 
-			if ( pgtype == BYTEAOID )
+			if (pgtype == BYTEAOID)
 			{
 				/*
 				 * Nothing special to do for bytea, just send the varlena data through!
@@ -1495,7 +1696,7 @@ ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecS
 				nulls[i] = false;
 				values[i] = PointerGetDatum(varlena);
 			}
-			else if ( pgtype == ogrGetGeometryOid() )
+			else if (pgtype == ogrGetGeometryOid())
 			{
 				/*
 				 * For geometry we need to convert the varlena WKB data into a serialized
@@ -1505,7 +1706,7 @@ ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecS
 				 * structure errors (unclosed polys, etc).
 				 */
 #ifdef OGR_FDW_HEXWKB
-				char *hexwkb = ogrBytesToHex(wkb, wkbsize);
+				char* hexwkb = ogrBytesToHex(wkb, wkbsize);
 				/*
 				 * Use the input function to convert the WKB from OGR into
 				 * a PostGIS internal format.
@@ -1524,7 +1725,7 @@ ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecS
 				 * things like polygon closure, etc. So don't feed it junk.
 				 */
 				StringInfoData strinfo;
-				strinfo.data = (char *)wkb;
+				strinfo.data = (char*)wkb;
 				strinfo.len = wkbsize;
 				strinfo.maxlen = strinfo.len;
 				strinfo.cursor = 0;
@@ -1545,7 +1746,7 @@ ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecS
 				 * it is, we should actually apply *that* and let the restriction run
 				 * its usual course.
 				 */
-				if ( have_typmod_funcs && col.pgtypmod >= 0 )
+				if (have_typmod_funcs && col.pgtypmod >= 0)
 				{
 					Datum srid = OidFunctionCall1(execstate->typmodsridfunc, Int32GetDatum(col.pgtypmod));
 					values[i] = OidFunctionCall2(execstate->setsridfunc, values[i], srid);
@@ -1558,7 +1759,7 @@ ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecS
 			}
 
 		}
-		else if ( ogrvariant == OGR_FIELD )
+		else if (ogrvariant == OGR_FIELD)
 		{
 #if (GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,2,0))
 			int field_not_null = OGR_F_IsFieldSet(feat, ogrfldnum) && ! OGR_F_IsFieldNull(feat, ogrfldnum);
@@ -1570,101 +1771,105 @@ ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecS
 			ogrCanConvertToPg(ogrfldtype, pgtype, pgname, tbl->tblname);
 
 			/* Only convert non-null fields */
-			if ( field_not_null )
+			if (field_not_null)
 			{
-				switch(ogrfldtype)
+				switch (ogrfldtype)
 				{
-					case OFTBinary:
-					{
-						/*
-						 * Convert binary fields to bytea directly
-						 */
-						int bufsize;
-						GByte *buf = OGR_F_GetFieldAsBinary(feat, ogrfldnum, &bufsize);
-						int varsize = bufsize + VARHDRSZ;
-						bytea *varlena = palloc(varsize);
-						memcpy(VARDATA(varlena), buf, bufsize);
-						SET_VARSIZE(varlena, varsize);
-						nulls[i] = false;
-						values[i] = PointerGetDatum(varlena);
-						break;
-					}
-					case OFTInteger:
-					case OFTReal:
-					case OFTString:
+				case OFTBinary:
+				{
+					/*
+					 * Convert binary fields to bytea directly
+					 */
+					int bufsize;
+					GByte* buf = OGR_F_GetFieldAsBinary(feat, ogrfldnum, &bufsize);
+					int varsize = bufsize + VARHDRSZ;
+					bytea* varlena = palloc(varsize);
+					memcpy(VARDATA(varlena), buf, bufsize);
+					SET_VARSIZE(varlena, varsize);
+					nulls[i] = false;
+					values[i] = PointerGetDatum(varlena);
+					break;
+				}
+				case OFTInteger:
+				case OFTReal:
+				case OFTString:
 #if GDAL_VERSION_MAJOR >= 2
-					case OFTInteger64:
+				case OFTInteger64:
 #endif
+				{
+					/*
+					 * Convert numbers and strings via a string representation.
+					 * Handling numbers directly would be faster, but require a lot of extra code.
+					 * For now, we go via text.
+					 */
+					const char* cstr_in = OGR_F_GetFieldAsString(feat, ogrfldnum);
+					size_t cstr_len = cstr_in ? strlen(cstr_in) : 0;
+					if (cstr_in && cstr_len > 0)
 					{
-						/*
-						 * Convert numbers and strings via a string representation.
-						 * Handling numbers directly would be faster, but require a lot of extra code.
-						 * For now, we go via text.
-						 */
-						const char *cstr_in = OGR_F_GetFieldAsString(feat, ogrfldnum);
-						size_t cstr_len = cstr_in ? strlen(cstr_in) : 0;
-						if ( cstr_in && cstr_len > 0 )
+						char* cstr_decoded;
+						if (execstate->ogr.lyr_utf8)
 						{
-							char *cstr_decoded;
-							if(execstate->ogr.lyr_utf8)
-								cstr_decoded = pg_any_to_server(cstr_in, cstr_len, PG_UTF8);
-							else
-								cstr_decoded = pstrdup(cstr_in);
-							nulls[i] = false;
-							values[i] = pgDatumFromCString(cstr_decoded, pgtype, pgtypmod, pginputfunc);
+							cstr_decoded = pg_any_to_server(cstr_in, cstr_len, PG_UTF8);
 						}
 						else
 						{
-							ogrNullSlot(values, nulls, i);
+							cstr_decoded = pstrdup(cstr_in);
 						}
-						break;
+						nulls[i] = false;
+						values[i] = pgDatumFromCString(cstr_decoded, pgtype, pgtypmod, pginputfunc);
 					}
-					case OFTDate:
-					case OFTTime:
-					case OFTDateTime:
+					else
 					{
-						/*
-						 * OGR date/times have a weird access method, so we use that to pull
-						 * out the raw data and turn it into a string for PgSQL's (very
-						 * sophisticated) date/time parsing routines to handle.
-						 */
-						int year, month, day, hour, minute, second, tz;
-						char cstr[256];
-
-						OGR_F_GetFieldAsDateTime(feat, ogrfldnum,
-						                         &year, &month, &day,
-						                         &hour, &minute, &second, &tz);
-
-						if ( ogrfldtype == OFTDate )
-						{
-							snprintf(cstr, 256, "%d-%02d-%02d", year, month, day);
-						}
-						else if ( ogrfldtype == OFTTime )
-						{
-							snprintf(cstr, 256, "%02d:%02d:%02d", hour, minute, second);
-						}
-						else
-						{
-							snprintf(cstr, 256, "%d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
-						}
-						nulls[i] = false;
-						values[i] = pgDatumFromCString(cstr, pgtype, pgtypmod, pginputfunc);
-						break;
-
+						ogrNullSlot(values, nulls, i);
+					}
+					break;
+				}
+				case OFTDate:
+				case OFTTime:
+				case OFTDateTime:
+				{
+					/*
+					 * OGR date/times have a weird access method, so we use that to pull
+					 * out the raw data and turn it into a string for PgSQL's (very
+					 * sophisticated) date/time parsing routines to handle.
+					 */
+					int year, month, day, hour, minute, second, tz;
+					char cstr[256];
+
+					OGR_F_GetFieldAsDateTime(feat, ogrfldnum,
+					                         &year, &month, &day,
+					                         &hour, &minute, &second, &tz);
+
+					if (ogrfldtype == OFTDate)
+					{
+						snprintf(cstr, 256, "%d-%02d-%02d", year, month, day);
 					}
-					case OFTIntegerList:
-					case OFTRealList:
-					case OFTStringList:
+					else if (ogrfldtype == OFTTime)
 					{
-						/* TODO, map these OGR array types into PgSQL arrays (fun!) */
-						elog(ERROR, "unsupported OGR array type \"%s\"", OGR_GetFieldTypeName(ogrfldtype));
-						break;
+						snprintf(cstr, 256, "%02d:%02d:%02d", hour, minute, second);
 					}
-					default:
+					else
 					{
-						elog(ERROR, "unsupported OGR type \"%s\"", OGR_GetFieldTypeName(ogrfldtype));
-						break;
+						snprintf(cstr, 256, "%d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
 					}
+					nulls[i] = false;
+					values[i] = pgDatumFromCString(cstr, pgtype, pgtypmod, pginputfunc);
+					break;
+
+				}
+				case OFTIntegerList:
+				case OFTRealList:
+				case OFTStringList:
+				{
+					/* TODO, map these OGR array types into PgSQL arrays (fun!) */
+					elog(ERROR, "unsupported OGR array type \"%s\"", OGR_GetFieldTypeName(ogrfldtype));
+					break;
+				}
+				default:
+				{
+					elog(ERROR, "unsupported OGR type \"%s\"", OGR_GetFieldTypeName(ogrfldtype));
+					break;
+				}
 
 				}
 			}
@@ -1674,7 +1879,7 @@ ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecS
 			}
 		}
 		/* Fill in unmatched columns with NULL */
-		else if ( ogrvariant == OGR_UNMATCHED )
+		else if (ogrvariant == OGR_UNMATCHED)
 		{
 			ogrNullSlot(values, nulls, i);
 		}
@@ -1690,7 +1895,8 @@ ogrFeatureToSlot(const OGRFeatureH feat, TupleTableSlot *slot, const OgrFdwExecS
 	return OGRERR_NONE;
 }
 
-static void ogrStaticText(char *text, const char *str)
+static void
+ogrStaticText(char* text, const char* str)
 {
 	size_t len = strlen(str);
 	memcpy(VARDATA(text), str, len);
@@ -1706,36 +1912,36 @@ static void ogrStaticText(char *text, const char *str)
  * generate more "standard" WKB for OGR to consume.
  */
 static size_t
-ogrEwkbStripSrid(unsigned char *wkb, size_t wkbsize)
+ogrEwkbStripSrid(unsigned char* wkb, size_t wkbsize)
 {
 	unsigned int type = 0;
 	int has_srid = 0;
 	size_t newwkbsize = wkbsize;
-	memcpy(&type, wkb+1, 4);
+	memcpy(&type, wkb + 1, 4);
 	/* has_z = type & 0x80000000; */
 	/* has_m = type & 0x40000000; */
 	has_srid = type & 0x20000000;
 
 	/* Flatten SRID flag away */
 	type &= 0xDFFFFFFF;
-	memcpy(wkb+1, &type, 4);
+	memcpy(wkb + 1, &type, 4);
 
 	/* If there was an SRID number embedded, overwrite it */
-	if ( has_srid )
+	if (has_srid)
 	{
 		newwkbsize -= 4; /* no space for SRID number needed */
-		memmove(wkb+5, wkb+9, newwkbsize - 5);
+		memmove(wkb + 5, wkb + 9, newwkbsize - 5);
 	}
 
 	return newwkbsize;
 }
 
 static OGRErr
-ogrSlotToFeature(const TupleTableSlot *slot, OGRFeatureH feat, const OgrFdwTable *tbl)
+ogrSlotToFeature(const TupleTableSlot* slot, OGRFeatureH feat, const OgrFdwTable* tbl)
 {
 	int i;
-	Datum *values = slot->tts_values;
-	bool *nulls = slot->tts_isnull;
+	Datum* values = slot->tts_values;
+	bool* nulls = slot->tts_isnull;
 	TupleDesc tupdesc = slot->tts_tupleDescriptor;
 
 	int year, month, day, hour, minute, second;
@@ -1756,17 +1962,17 @@ ogrSlotToFeature(const TupleTableSlot *slot, OGRFeatureH feat, const OgrFdwTable
 	ogrStaticText(txtsecond, "second");
 
 	/* Check our assumption that slot and setup data match */
-	if ( tbl->ncols != tupdesc->natts )
+	if (tbl->ncols != tupdesc->natts)
 	{
 		elog(ERROR, "FDW metadata table and slot table have mismatching number of columns");
 		return OGRERR_FAILURE;
 	}
 
 	/* For each pgtable column, set a value on the feature OGR */
-	for ( i = 0; i < tbl->ncols; i++ )
+	for (i = 0; i < tbl->ncols; i++)
 	{
 		OgrFdwColumn col = tbl->cols[i];
-		const char *pgname = col.pgname;
+		const char* pgname = col.pgname;
 		Oid pgtype = col.pgtype;
 		Oid pgoutputfunc = col.pgoutputfunc;
 		int ogrfldnum = col.ogrfldnum;
@@ -1774,24 +1980,26 @@ ogrSlotToFeature(const TupleTableSlot *slot, OGRFeatureH feat, const OgrFdwTable
 		OgrColumnVariant ogrvariant = col.ogrvariant;
 
 		/* Skip dropped attributes */
-		if ( col.pgattisdropped )
+		if (col.pgattisdropped)
+		{
 			continue;
+		}
 
 		/* Skip the FID, we have to treat it as immutable anyways */
-		if ( ogrvariant == OGR_FID )
+		if (ogrvariant == OGR_FID)
 		{
-			if ( nulls[i] )
+			if (nulls[i])
 			{
 				OGR_F_SetFID(feat, OGRNullFID);
 			}
 			else
 			{
-				if ( pgtype == INT4OID )
+				if (pgtype == INT4OID)
 				{
 					int32 val = DatumGetInt32(values[i]);
 					OGR_F_SetFID(feat, val);
 				}
-				else if ( pgtype == INT8OID )
+				else if (pgtype == INT8OID)
 				{
 					int64 val = DatumGetInt64(values[i]);
 					OGR_F_SetFID(feat, val);
@@ -1806,10 +2014,10 @@ ogrSlotToFeature(const TupleTableSlot *slot, OGRFeatureH feat, const OgrFdwTable
 
 		/* TODO: For updates, we should only set the fields that are */
 		/*       in the target list, and flag the others as unchanged */
-		if ( ogrvariant == OGR_GEOMETRY )
+		if (ogrvariant == OGR_GEOMETRY)
 		{
 			OGRErr err;
-			if ( nulls[i] )
+			if (nulls[i])
 			{
 #if (GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0))
 				err = OGR_F_SetGeomFieldDirectly(feat, ogrfldnum, NULL);
@@ -1821,16 +2029,21 @@ ogrSlotToFeature(const TupleTableSlot *slot, OGRFeatureH feat, const OgrFdwTable
 			else
 			{
 				OGRGeometryH geom;
-				bytea *wkb_bytea = DatumGetByteaP(OidFunctionCall1(col.pgsendfunc, values[i]));
-				unsigned char *wkb = (unsigned char *)VARDATA(wkb_bytea);
-				int wkbsize = VARSIZE(wkb_bytea) - VARHDRSZ;
+				bytea* wkb_bytea = DatumGetByteaP(OidFunctionCall1(col.pgsendfunc, values[i]));
+				unsigned char* wkb = (unsigned char*)VARDATA_ANY(wkb_bytea);
+				int wkbsize = VARSIZE_ANY_EXHDR(wkb_bytea);
 				wkbsize = ogrEwkbStripSrid(wkb, wkbsize);
 
 				/* TODO, create geometry with SRS of table? */
 				err = OGR_G_CreateFromWkb(wkb, NULL, &geom, wkbsize);
-				if ( wkb_bytea ) pfree(wkb_bytea);
-				if ( err != OGRERR_NONE )
+				if (wkb_bytea)
+				{
+					pfree(wkb_bytea);
+				}
+				if (err != OGRERR_NONE)
+				{
 					return err;
+				}
 
 #if (GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0))
 				err = OGR_F_SetGeomFieldDirectly(feat, ogrfldnum, geom);
@@ -1839,160 +2052,164 @@ ogrSlotToFeature(const TupleTableSlot *slot, OGRFeatureH feat, const OgrFdwTable
 #endif
 			}
 		}
-		else if ( ogrvariant == OGR_FIELD )
+		else if (ogrvariant == OGR_FIELD)
 		{
 			/* Ensure that the OGR data type fits the destination Pg column */
 			pgCanConvertToOgr(pgtype, ogrfldtype, pgname, tbl->tblname);
 
 			/* Skip NULL case */
-			if ( nulls[i] )
+			if (nulls[i])
 			{
-				OGR_F_UnsetField (feat, ogrfldnum);
+				OGR_F_UnsetField(feat, ogrfldnum);
 				continue;
 			}
 
-			switch(pgtype)
+			switch (pgtype)
 			{
-				case BOOLOID:
-				{
-					int8 val = DatumGetBool(values[i]);
-					OGR_F_SetFieldInteger(feat, ogrfldnum, val);
-					break;
-				}
-				case INT2OID:
+			case BOOLOID:
+			{
+				int8 val = DatumGetBool(values[i]);
+				OGR_F_SetFieldInteger(feat, ogrfldnum, val);
+				break;
+			}
+			case INT2OID:
+			{
+				int16 val = DatumGetInt16(values[i]);
+				OGR_F_SetFieldInteger(feat, ogrfldnum, val);
+				break;
+			}
+			case INT4OID:
+			{
+				int32 val = DatumGetInt32(values[i]);
+				OGR_F_SetFieldInteger(feat, ogrfldnum, val);
+				break;
+			}
+			case INT8OID:
+			{
+				int64 val = DatumGetInt64(values[i]);
+#if GDAL_VERSION_MAJOR >= 2
+				OGR_F_SetFieldInteger64(feat, ogrfldnum, val);
+#else
+				if (val < INT_MAX)
 				{
-					int16 val = DatumGetInt16(values[i]);
-					OGR_F_SetFieldInteger(feat, ogrfldnum, val);
-					break;
+					OGR_F_SetFieldInteger(feat, ogrfldnum, (int32)val);
 				}
-				case INT4OID:
+				else
 				{
-					int32 val = DatumGetInt32(values[i]);
-					OGR_F_SetFieldInteger(feat, ogrfldnum, val);
-					break;
+					elog(ERROR, "unable to coerce int64 into int32 OGR field");
 				}
-				case INT8OID:
-				{
-					int64 val = DatumGetInt64(values[i]);
-#if GDAL_VERSION_MAJOR >= 2
-					OGR_F_SetFieldInteger64(feat, ogrfldnum, val);
-#else
-					if ( val < INT_MAX )
-						OGR_F_SetFieldInteger(feat, ogrfldnum, (int32)val);
-					else
-						elog(ERROR, "unable to coerce int64 into int32 OGR field");
 #endif
-					break;
+				break;
 
-				}
+			}
 
-				case NUMERICOID:
-				{
-					Datum d;
-					float8 f;
+			case NUMERICOID:
+			{
+				Datum d;
+				float8 f;
 
-					/* Convert to string */
-					d = OidFunctionCall1(pgoutputfunc, values[i]);
-					/* Convert back to float8 */
-					f = DatumGetFloat8(DirectFunctionCall1(float8in, d));
+				/* Convert to string */
+				d = OidFunctionCall1(pgoutputfunc, values[i]);
+				/* Convert back to float8 */
+				f = DatumGetFloat8(DirectFunctionCall1(float8in, d));
 
-					OGR_F_SetFieldDouble(feat, ogrfldnum, f);
-					break;
-				}
-				case FLOAT4OID:
-				{
-					OGR_F_SetFieldDouble(feat, ogrfldnum, DatumGetFloat4(values[i]));
-					break;
-				}
-				case FLOAT8OID:
-				{
-					OGR_F_SetFieldDouble(feat, ogrfldnum, DatumGetFloat8(values[i]));
-					break;
-				}
+				OGR_F_SetFieldDouble(feat, ogrfldnum, f);
+				break;
+			}
+			case FLOAT4OID:
+			{
+				OGR_F_SetFieldDouble(feat, ogrfldnum, DatumGetFloat4(values[i]));
+				break;
+			}
+			case FLOAT8OID:
+			{
+				OGR_F_SetFieldDouble(feat, ogrfldnum, DatumGetFloat8(values[i]));
+				break;
+			}
 
-				case TEXTOID:
-				case VARCHAROID:
-				case NAMEOID:
-				case BPCHAROID: /* char(n) */
-				{
-					char *varlena = (char *)DatumGetPointer(values[i]);
-					size_t varsize = VARSIZE(varlena)-VARHDRSZ;
-					char *str = palloc0(varsize+1);
-					memcpy(str, VARDATA(varlena), varsize);
-					OGR_F_SetFieldString(feat, ogrfldnum, str);
-					pfree(str);
-					break;
-				}
+			case TEXTOID:
+			case VARCHAROID:
+			case NAMEOID:
+			case BPCHAROID: /* char(n) */
+			{
+				bytea* varlena = (bytea*)DatumGetPointer(values[i]);
+				size_t varsize = VARSIZE_ANY_EXHDR(varlena);
+				char* str = palloc0(varsize + 1);
+				memcpy(str, VARDATA_ANY(varlena), varsize);
+				OGR_F_SetFieldString(feat, ogrfldnum, str);
+				pfree(str);
+				break;
+			}
 
-				case CHAROID: /* char */
-				{
-					char str[2];
-					str[0] = DatumGetChar(values[i]);
-					str[1] = '\0';
-					OGR_F_SetFieldString(feat, ogrfldnum, str);
-					break;
-				}
+			case CHAROID: /* char */
+			{
+				char str[2];
+				str[0] = DatumGetChar(values[i]);
+				str[1] = '\0';
+				OGR_F_SetFieldString(feat, ogrfldnum, str);
+				break;
+			}
 
-				case BYTEAOID:
-				{
-					bytea *varlena = PG_DETOAST_DATUM(values[i]);
-					size_t varsize = VARSIZE(varlena) - VARHDRSZ;
-					OGR_F_SetFieldBinary(feat, ogrfldnum, varsize, (GByte *)VARDATA(varlena));
-					break;
-				}
+			case BYTEAOID:
+			{
+				bytea* varlena = PG_DETOAST_DATUM(values[i]);
+				size_t varsize = VARSIZE_ANY_EXHDR(varlena);
+				OGR_F_SetFieldBinary(feat, ogrfldnum, varsize, (GByte*)VARDATA_ANY(varlena));
+				break;
+			}
 
-				case DATEOID:
-				{
-					/* Convert date to timestamp */
-					Datum d = DirectFunctionCall1(date_timestamp, values[i]);
-
-					/* Read out the parts */
-					year = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtyear), d)));
-					month = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtmonth), d)));
-					day = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtday), d)));
-					OGR_F_SetFieldDateTime(feat, ogrfldnum, year, month, day, 0, 0, 0, 0);
-					break;
-				}
+			case DATEOID:
+			{
+				/* Convert date to timestamp */
+				Datum d = DirectFunctionCall1(date_timestamp, values[i]);
+
+				/* Read out the parts */
+				year = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtyear), d)));
+				month = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtmonth), d)));
+				day = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtday), d)));
+				OGR_F_SetFieldDateTime(feat, ogrfldnum, year, month, day, 0, 0, 0, 0);
+				break;
+			}
 
-				/* TODO: handle time zones explicitly */
-				case TIMEOID:
-				case TIMETZOID:
-				{
-					/* Read the parts of the time */
-					hour = lround(DatumGetFloat8(DirectFunctionCall2(time_part, PointerGetDatum(txthour), values[i])));
-					minute = lround(DatumGetFloat8(DirectFunctionCall2(time_part, PointerGetDatum(txtminute), values[i])));
-					second = lround(DatumGetFloat8(DirectFunctionCall2(time_part, PointerGetDatum(txtsecond), values[i])));
-					OGR_F_SetFieldDateTime(feat, ogrfldnum, 0, 0, 0, hour, minute, second, 0);
-					break;
-				}
+			/* TODO: handle time zones explicitly */
+			case TIMEOID:
+			case TIMETZOID:
+			{
+				/* Read the parts of the time */
+				hour = lround(DatumGetFloat8(DirectFunctionCall2(time_part, PointerGetDatum(txthour), values[i])));
+				minute = lround(DatumGetFloat8(DirectFunctionCall2(time_part, PointerGetDatum(txtminute), values[i])));
+				second = lround(DatumGetFloat8(DirectFunctionCall2(time_part, PointerGetDatum(txtsecond), values[i])));
+				OGR_F_SetFieldDateTime(feat, ogrfldnum, 0, 0, 0, hour, minute, second, 0);
+				break;
+			}
 
 
-				case TIMESTAMPOID:
-				case TIMESTAMPTZOID:
-				{
-					Datum d = values[i];
-					year = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtyear), d)));
-					month = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtmonth), d)));
-					day = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtday), d)));
-					hour = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txthour), d)));
-					minute = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtminute), d)));
-					second = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtsecond), d)));
-					OGR_F_SetFieldDateTime(feat, ogrfldnum, year, month, day, hour, minute, second, 0);
-					break;
-				}
+			case TIMESTAMPOID:
+			case TIMESTAMPTZOID:
+			{
+				Datum d = values[i];
+				year = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtyear), d)));
+				month = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtmonth), d)));
+				day = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtday), d)));
+				hour = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txthour), d)));
+				minute = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtminute), d)));
+				second = lround(DatumGetFloat8(DirectFunctionCall2(timestamp_part, PointerGetDatum(txtsecond), d)));
+				OGR_F_SetFieldDateTime(feat, ogrfldnum, year, month, day, hour, minute, second, 0);
+				break;
+			}
 
-				/* TODO: array types for string, integer, float */
-				default:
-				{
-					elog(ERROR, "OGR FDW unsupported PgSQL column type in \"%s\", %d", pgname, pgtype);
-					return OGRERR_FAILURE;
-				}
+			/* TODO: array types for string, integer, float */
+			default:
+			{
+				elog(ERROR, "OGR FDW unsupported PgSQL column type in \"%s\", %d", pgname, pgtype);
+				return OGRERR_FAILURE;
+			}
 			}
 		}
 		/* Fill in unmatched columns with NULL */
-		else if ( ogrvariant == OGR_UNMATCHED )
+		else if (ogrvariant == OGR_UNMATCHED)
 		{
-			OGR_F_UnsetField (feat, ogrfldnum);
+			OGR_F_UnsetField(feat, ogrfldnum);
 		}
 		else
 		{
@@ -2011,11 +2228,11 @@ ogrSlotToFeature(const TupleTableSlot *slot, OGRFeatureH feat, const OgrFdwTable
  *		Read next record from OGR and store it into the
  *		ScanTupleSlot as a virtual tuple
  */
-static TupleTableSlot *
-ogrIterateForeignScan(ForeignScanState *node)
+static TupleTableSlot*
+ogrIterateForeignScan(ForeignScanState* node)
 {
-	OgrFdwExecState *execstate = (OgrFdwExecState *) node->fdw_state;
-	TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
+	OgrFdwExecState* execstate = (OgrFdwExecState*) node->fdw_state;
+	TupleTableSlot* slot = node->ss.ss_ScanTupleSlot;
 	OGRFeatureH feat;
 
 	/*
@@ -2029,18 +2246,20 @@ ogrIterateForeignScan(ForeignScanState *node)
 	 * we run out of records, then return a cleared (NULL) slot, to
 	 * notify the core we're done.
 	 */
-	if ( execstate->rownum == 0 )
+	if (execstate->rownum == 0)
 	{
 		OGR_L_ResetReading(execstate->ogr.lyr);
 	}
 
 	/* If we rectreive a feature from OGR, copy it over into the slot */
 	feat = OGR_L_GetNextFeature(execstate->ogr.lyr);
-	if ( feat )
+	if (feat)
 	{
 		/* convert result to arrays of values and null indicators */
-		if ( OGRERR_NONE != ogrFeatureToSlot(feat, slot, execstate) )
+		if (OGRERR_NONE != ogrFeatureToSlot(feat, slot, execstate))
+		{
 			ogrEreportError("failure reading OGR data source");
+		}
 
 		/* store the virtual tuple */
 		ExecStoreVirtualTuple(slot);
@@ -2060,9 +2279,9 @@ ogrIterateForeignScan(ForeignScanState *node)
  *		Rescan table, possibly with new parameters
  */
 static void
-ogrReScanForeignScan(ForeignScanState *node)
+ogrReScanForeignScan(ForeignScanState* node)
 {
-	OgrFdwExecState *execstate = (OgrFdwExecState *) node->fdw_state;
+	OgrFdwExecState* execstate = (OgrFdwExecState*) node->fdw_state;
 
 	OGR_L_ResetReading(execstate->ogr.lyr);
 	execstate->rownum = 0;
@@ -2075,13 +2294,13 @@ ogrReScanForeignScan(ForeignScanState *node)
  *		Finish scanning foreign table and dispose objects used for this scan
  */
 static void
-ogrEndForeignScan(ForeignScanState *node)
+ogrEndForeignScan(ForeignScanState* node)
 {
-	OgrFdwExecState *execstate = (OgrFdwExecState *) node->fdw_state;
+	OgrFdwExecState* execstate = (OgrFdwExecState*) node->fdw_state;
 
 	elog(DEBUG2, "processed %d rows from OGR", execstate->rownum);
 
-	ogrFinishConnection( &(execstate->ogr) );
+	ogrFinishConnection(&(execstate->ogr));
 
 	return;
 }
@@ -2090,8 +2309,6 @@ ogrEndForeignScan(ForeignScanState *node)
 /* WRITE SUPPORT */
 /* ======================================================== */
 
-// OgrFdwTable *tbl;
-
 /* if the scanning functions above respected the targetlist,
 we would only be getting back the SET target=foo columns in the slots below,
 so we would need to add the "fid" to all targetlists (and also disallow fid changing
@@ -2113,10 +2330,11 @@ in ogrGetForeignPlan we get a tlist that includes just the attributes we
 are interested in, can use that to pare down the request perhaps
 */
 
-static int ogrGetFidColumn(const TupleDesc td)
+static int
+ogrGetFidColumn(const TupleDesc td)
 {
 	int i;
-	for ( i = 0; i < td->natts; i++ )
+	for (i = 0; i < td->natts; i++)
 	{
 #if PG_VERSION_NUM >= 110000
 		NameData attname = td->attrs[i].attname;
@@ -2125,8 +2343,8 @@ static int ogrGetFidColumn(const TupleDesc td)
 		NameData attname = td->attrs[i]->attname;
 		Oid atttypeid = td->attrs[i]->atttypid;
 #endif
-		if ( (atttypeid == INT4OID || atttypeid == INT8OID) &&
-		     strcaseeq("fid", attname.data) )
+		if ((atttypeid == INT4OID || atttypeid == INT8OID) &&
+		        strcaseeq("fid", attname.data))
 		{
 			return i;
 		}
@@ -2143,21 +2361,24 @@ static int ogrGetFidColumn(const TupleDesc td)
  * there could always be a virtual fid travelling with the queries,
  * and the FDW table itself wouldn't need such a column?
  */
-static void ogrAddForeignUpdateTargets (Query *parsetree,
-					RangeTblEntry *target_rte,
-					Relation target_relation)
+static void
+ogrAddForeignUpdateTargets(Query* parsetree,
+                           RangeTblEntry* target_rte,
+                           Relation target_relation)
 {
-	ListCell *cell;
+	ListCell* cell;
 	Form_pg_attribute att;
-	Var *var;
-	TargetEntry *tle;
+	Var* var;
+	TargetEntry* tle;
 	TupleDesc tupdesc = target_relation->rd_att;
 	int fid_column = ogrGetFidColumn(tupdesc);
 
 	elog(DEBUG2, "ogrAddForeignUpdateTargets");
 
-	if ( fid_column < 0 )
-		elog(ERROR,"table '%s' does not have a 'fid' column", RelationGetRelationName(target_relation));
+	if (fid_column < 0)
+	{
+		elog(ERROR, "table '%s' does not have a 'fid' column", RelationGetRelationName(target_relation));
+	}
 
 #if PG_VERSION_NUM >= 110000
 	att = &tupdesc->attrs[fid_column];
@@ -2166,23 +2387,23 @@ static void ogrAddForeignUpdateTargets (Query *parsetree,
 #endif
 	/* Make a Var representing the desired value */
 	var = makeVar(parsetree->resultRelation,
-			att->attnum,
-			att->atttypid,
-			att->atttypmod,
-			att->attcollation,
-			0);
+	              att->attnum,
+	              att->atttypid,
+	              att->atttypmod,
+	              att->attcollation,
+	              0);
 
 	/* Wrap it in a resjunk TLE with the right name ... */
-	tle = makeTargetEntry((Expr *)var,
-			list_length(parsetree->targetList) + 1,
-			pstrdup(NameStr(att->attname)),
-			true);
+	tle = makeTargetEntry((Expr*)var,
+	                      list_length(parsetree->targetList) + 1,
+	                      pstrdup(NameStr(att->attname)),
+	                      true);
 
 	parsetree->targetList = lappend(parsetree->targetList, tle);
 
-	foreach(cell, parsetree->targetList)
+	foreach (cell, parsetree->targetList)
 	{
-		TargetEntry *target = (TargetEntry *) lfirst(cell);
+		TargetEntry* target = (TargetEntry*) lfirst(cell);
 		elog(DEBUG4, "parsetree->targetList %s:%d", target->resname, target->resno);
 	}
 
@@ -2195,14 +2416,15 @@ static void ogrAddForeignUpdateTargets (Query *parsetree,
  * For now the only thing we'll do here is set up the connection
  * and pass that on to the next functions.
  */
-static void ogrBeginForeignModify (ModifyTableState *mtstate,
-					ResultRelInfo *rinfo,
-					List *fdw_private,
-					int subplan_index,
-					int eflags)
+static void
+ogrBeginForeignModify(ModifyTableState* mtstate,
+                      ResultRelInfo* rinfo,
+                      List* fdw_private,
+                      int subplan_index,
+                      int eflags)
 {
 	Oid foreigntableid;
-	OgrFdwState *state;
+	OgrFdwState* state;
 
 	elog(DEBUG2, "ogrBeginForeignModify");
 
@@ -2222,12 +2444,13 @@ static void ogrBeginForeignModify (ModifyTableState *mtstate,
  * Find out what the fid is, get the OGR feature for that FID,
  * and then update the values on that feature.
  */
-static TupleTableSlot *ogrExecForeignUpdate (EState *estate,
-					ResultRelInfo *rinfo,
-					TupleTableSlot *slot,
-					TupleTableSlot *planSlot)
+static TupleTableSlot*
+ogrExecForeignUpdate(EState* estate,
+                     ResultRelInfo* rinfo,
+                     TupleTableSlot* slot,
+                     TupleTableSlot* planSlot)
 {
-	OgrFdwModifyState *modstate = rinfo->ri_FdwState;
+	OgrFdwModifyState* modstate = rinfo->ri_FdwState;
 	TupleDesc td = slot->tts_tupleDescriptor;
 	Relation rel = rinfo->ri_RelationDesc;
 	Oid foreigntableid = RelationGetRelid(rel);
@@ -2240,8 +2463,14 @@ static TupleTableSlot *ogrExecForeignUpdate (EState *estate,
 
 	/* Is there a fid column? */
 	fid_column = ogrGetFidColumn(td);
-	if ( fid_column < 0 )
+	if (fid_column < 0)
+	{
 		elog(ERROR, "cannot find 'fid' column in table '%s'", get_rel_name(foreigntableid));
+	}
+
+#if PG_VERSION_NUM >= 120000
+	slot_getallattrs(slot);
+#endif
 
 	/* What is the value of the FID for this record? */
 	fid_datum = slot->tts_values[fid_column];
@@ -2250,28 +2479,38 @@ static TupleTableSlot *ogrExecForeignUpdate (EState *estate,
 #else
 	fid_type = td->attrs[fid_column]->atttypid;
 #endif
-	if ( fid_type == INT8OID )
+	if (fid_type == INT8OID)
+	{
 		fid = DatumGetInt64(fid_datum);
+	}
 	else
+	{
 		fid = DatumGetInt32(fid_datum);
+	}
 
 	elog(DEBUG2, "ogrExecForeignUpdate fid=" OGR_FDW_FRMT_INT64, OGR_FDW_CAST_INT64(fid));
 
 	/* Get the OGR feature for this fid */
-	feat = OGR_L_GetFeature (modstate->ogr.lyr, fid);
+	feat = OGR_L_GetFeature(modstate->ogr.lyr, fid);
 
 	/* If we found a feature, then copy data from the slot onto the feature */
 	/* and then back into the layer */
-	if ( ! feat )
+	if (! feat)
+	{
 		ogrEreportError("failure reading OGR feature");
+	}
 
 	err = ogrSlotToFeature(slot, feat, modstate->table);
-	if ( err != OGRERR_NONE )
+	if (err != OGRERR_NONE)
+	{
 		ogrEreportError("failure populating OGR feature");
+	}
 
 	err = OGR_L_SetFeature(modstate->ogr.lyr, feat);
-	if ( err != OGRERR_NONE )
+	if (err != OGRERR_NONE)
+	{
 		ogrEreportError("failure writing back OGR feature");
+	}
 
 	OGR_F_Destroy(feat);
 
@@ -2381,39 +2620,55 @@ static TupleTableSlot *ogrExecForeignUpdate (EState *estate,
 //     int         location;       /* token location, or -1 if unknown */
 // } Var;
 
-static TupleTableSlot *ogrExecForeignInsert (EState *estate,
-					ResultRelInfo *rinfo,
-					TupleTableSlot *slot,
-					TupleTableSlot *planSlot)
+static TupleTableSlot*
+ogrExecForeignInsert(EState* estate,
+                     ResultRelInfo* rinfo,
+                     TupleTableSlot* slot,
+                     TupleTableSlot* planSlot)
 {
-	OgrFdwModifyState *modstate = rinfo->ri_FdwState;
+	OgrFdwModifyState* modstate = rinfo->ri_FdwState;
 	OGRFeatureDefnH ogr_fd = OGR_L_GetLayerDefn(modstate->ogr.lyr);
 	OGRFeatureH feat = OGR_F_Create(ogr_fd);
-	TupleDesc td = slot->tts_tupleDescriptor;
 	int fid_column;
 	OGRErr err;
 	GIntBig fid;
 
 	elog(DEBUG2, "ogrExecForeignInsert");
 
+#if PG_VERSION_NUM >= 120000
+	/*
+	* PgSQL 12 passes an unpopulated slot to us, and for now
+	* we force it to populate itself and then read directly
+	* from it. For future, using the slot_getattr() infra
+	* would be cleaner, but version dependent.
+	*/
+	slot_getallattrs(slot);
+#endif
+
 	/* Copy the data from the slot onto the feature */
-	if ( ! feat )
+	if (!feat)
+	{
 		ogrEreportError("failure creating OGR feature");
+	}
 
 	err = ogrSlotToFeature(slot, feat, modstate->table);
-	if ( err != OGRERR_NONE )
+	if (err != OGRERR_NONE)
+	{
 		ogrEreportError("failure populating OGR feature");
+	}
 
 	err = OGR_L_CreateFeature(modstate->ogr.lyr, feat);
-	if ( err != OGRERR_NONE )
+	if (err != OGRERR_NONE)
+	{
 		ogrEreportError("failure writing OGR feature");
+	}
 
 	fid = OGR_F_GetFID(feat);
 	OGR_F_Destroy(feat);
 
 	/* Update the FID for RETURNING slot */
-	fid_column = ogrGetFidColumn(td);
-	if ( fid_column >= 0 )
+	fid_column = ogrGetFidColumn(slot->tts_tupleDescriptor);
+	if (fid_column >= 0)
 	{
 		slot->tts_values[fid_column] = Int64GetDatum(fid);
 		slot->tts_isnull[fid_column] = false;
@@ -2425,12 +2680,13 @@ static TupleTableSlot *ogrExecForeignInsert (EState *estate,
 
 
 
-static TupleTableSlot *ogrExecForeignDelete (EState *estate,
-					ResultRelInfo *rinfo,
-					TupleTableSlot *slot,
-					TupleTableSlot *planSlot)
+static TupleTableSlot*
+ogrExecForeignDelete(EState* estate,
+                     ResultRelInfo* rinfo,
+                     TupleTableSlot* slot,
+                     TupleTableSlot* planSlot)
 {
-	OgrFdwModifyState *modstate = rinfo->ri_FdwState;
+	OgrFdwModifyState* modstate = rinfo->ri_FdwState;
 	TupleDesc td = planSlot->tts_tupleDescriptor;
 	Relation rel = rinfo->ri_RelationDesc;
 	Oid foreigntableid = RelationGetRelid(rel);
@@ -2442,8 +2698,14 @@ static TupleTableSlot *ogrExecForeignDelete (EState *estate,
 
 	/* Is there a fid column? */
 	fid_column = ogrGetFidColumn(td);
-	if ( fid_column < 0 )
+	if (fid_column < 0)
+	{
 		elog(ERROR, "cannot find 'fid' column in table '%s'", get_rel_name(foreigntableid));
+	}
+
+#if PG_VERSION_NUM >= 120000
+	slot_getallattrs(planSlot);
+#endif
 
 	/* What is the value of the FID for this record? */
 	fid_datum = planSlot->tts_values[fid_column];
@@ -2453,37 +2715,47 @@ static TupleTableSlot *ogrExecForeignDelete (EState *estate,
 	fid_type = td->attrs[fid_column]->atttypid;
 #endif
 
-	if ( fid_type == INT8OID )
+	if (fid_type == INT8OID)
+	{
 		fid = DatumGetInt64(fid_datum);
+	}
 	else
+	{
 		fid = DatumGetInt32(fid_datum);
+	}
 
 	elog(DEBUG2, "ogrExecForeignDelete fid=" OGR_FDW_FRMT_INT64, OGR_FDW_CAST_INT64(fid));
 
 	/* Delete the OGR feature for this fid */
 	err = OGR_L_DeleteFeature(modstate->ogr.lyr, fid);
 
-	if ( err != OGRERR_NONE )
+	if (err != OGRERR_NONE)
+	{
 		return NULL;
+	}
 	else
+	{
 		return slot;
+	}
 }
 
-static void ogrEndForeignModify (EState *estate, ResultRelInfo *rinfo)
+static void
+ogrEndForeignModify(EState* estate, ResultRelInfo* rinfo)
 {
-	OgrFdwModifyState *modstate = rinfo->ri_FdwState;
+	OgrFdwModifyState* modstate = rinfo->ri_FdwState;
 
 	elog(DEBUG2, "ogrEndForeignModify");
 
-	ogrFinishConnection( &(modstate->ogr) );
+	ogrFinishConnection(&(modstate->ogr));
 
 	return;
 }
 
-static int ogrIsForeignRelUpdatable (Relation rel)
+static int
+ogrIsForeignRelUpdatable(Relation rel)
 {
-	static int readonly = 0;
-	static int updateable = 0;
+	const int readonly = 0;
+	int foreign_rel_updateable = 0;
 	TupleDesc td = RelationGetDescr(rel);
 	OgrConnection ogr;
 	Oid foreigntableid = RelationGetRelid(rel);
@@ -2493,7 +2765,7 @@ static int ogrIsForeignRelUpdatable (Relation rel)
 	/* Before we say "yes"... */
 	/*  Does the foreign relation have a "fid" column? */
 	/* Is that column an integer? */
-	if ( ogrGetFidColumn(td) < 0 )
+	if (ogrGetFidColumn(td) < 0)
 	{
 		elog(NOTICE, "no \"fid\" column in foreign table '%s'", get_rel_name(foreigntableid));
 		return readonly;
@@ -2501,23 +2773,40 @@ static int ogrIsForeignRelUpdatable (Relation rel)
 
 	/*   Is it backed by a writable OGR driver? */
 	/*   Can we open the relation in read/write mode? */
-	ogr = ogrGetConnectionFromTable(foreigntableid, true);
-	if ( ! (ogr.ds && ogr.lyr) )
+	ogr = ogrGetConnectionFromTable(foreigntableid, OGR_UPDATEABLE_TRY);
+
+	/* Something in the open process set the readonly flags */
+	/* Perhaps user has manually set the foreign table option to readonly */
+	if (ogr.ds_updateable == OGR_UPDATEABLE_FALSE ||
+	        ogr.lyr_updateable == OGR_UPDATEABLE_FALSE)
+	{
 		return readonly;
+	}
 
-	if ( OGR_L_TestCapability(ogr.lyr, OLCRandomWrite) )
-		updateable |= (1 << CMD_UPDATE);
+	/* No data source or layer objects? Readonly */
+	if (!(ogr.ds && ogr.lyr))
+	{
+		return readonly;
+	}
 
-	if ( OGR_L_TestCapability(ogr.lyr, OLCSequentialWrite) )
-		updateable |= (1 << CMD_INSERT);
+	if (OGR_L_TestCapability(ogr.lyr, OLCRandomWrite))
+	{
+		foreign_rel_updateable |= (1 << CMD_UPDATE);
+	}
 
-	if ( OGR_L_TestCapability(ogr.lyr, OLCDeleteFeature) )
-		updateable |= (1 << CMD_DELETE);
+	if (OGR_L_TestCapability(ogr.lyr, OLCSequentialWrite))
+	{
+		foreign_rel_updateable |= (1 << CMD_INSERT);
+	}
 
-	ogrFinishConnection(&ogr);
+	if (OGR_L_TestCapability(ogr.lyr, OLCDeleteFeature))
+	{
+		foreign_rel_updateable |= (1 << CMD_DELETE);
+	}
 
-	return updateable;
+	ogrFinishConnection(&ogr);
 
+	return foreign_rel_updateable;
 }
 
 #if PG_VERSION_NUM >= 90500
@@ -2525,12 +2814,12 @@ static int ogrIsForeignRelUpdatable (Relation rel)
 /*
  * PostgreSQL 9.5 or above.  Import a foreign schema
  */
-static List *
-ogrImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
+static List*
+ogrImportForeignSchema(ImportForeignSchemaStmt* stmt, Oid serverOid)
 {
-	List *commands = NIL;
-	ForeignServer *server;
-	ListCell *lc;
+	List* commands = NIL;
+	ForeignServer* server;
+	ListCell* lc;
 	bool import_all = false;
 	bool launder_column_names, launder_table_names;
 	OgrConnection ogr;
@@ -2543,32 +2832,36 @@ ogrImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
 
 	/* Make connection to server */
 	server = GetForeignServer(serverOid);
-	ogr = ogrGetConnectionFromServer(serverOid, false);
+	ogr = ogrGetConnectionFromServer(serverOid, OGR_UPDATEABLE_FALSE);
 
 	/* Launder by default */
 	launder_column_names = launder_table_names = true;
 
 	/* Read user-provided statement laundering options */
-	foreach(lc, stmt->options)
+	foreach (lc, stmt->options)
 	{
-		DefElem *def = (DefElem *) lfirst(lc);
+		DefElem* def = (DefElem*) lfirst(lc);
 
 		if (streq(def->defname, "launder_column_names"))
+		{
 			launder_column_names = defGetBoolean(def);
+		}
 		else if (streq(def->defname, "launder_table_names"))
+		{
 			launder_table_names = defGetBoolean(def);
+		}
 		else
 			ereport(ERROR,
-					(errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
-					 errmsg("invalid option \"%s\"", def->defname)));
+			        (errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
+			         errmsg("invalid option \"%s\"", def->defname)));
 	}
 
-	for ( i = 0; i < GDALDatasetGetLayerCount(ogr.ds); i++ )
+	for (i = 0; i < GDALDatasetGetLayerCount(ogr.ds); i++)
 	{
 		bool import_layer = false;
 		OGRLayerH ogr_lyr = GDALDatasetGetLayer(ogr.ds, i);
 
-		if ( ! ogr_lyr )
+		if (! ogr_lyr)
 		{
 			elog(DEBUG1, "Skipping OGR layer %d, unable to read layer", i);
 			continue;
@@ -2583,35 +2876,43 @@ ogrImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
 		*/
 		strncpy(table_name, layer_name, STR_MAX_LEN);
 		if (launder_table_names)
+		{
 			ogrStringLaunder(table_name);
+		}
 
 		/*
 		* Only include if we are importing "ogr_all" or
 		* the layer prefix starts with the remote schema
 		*/
 		import_layer = import_all ||
-				( strncmp(layer_name, stmt->remote_schema, strlen(stmt->remote_schema) ) == 0 );
+		               (strncmp(layer_name, stmt->remote_schema, strlen(stmt->remote_schema)) == 0);
 
 		/* Apply restrictions for LIMIT TO and EXCEPT */
 		if (import_layer && (
-		    stmt->list_type == FDW_IMPORT_SCHEMA_LIMIT_TO ||
-		    stmt->list_type == FDW_IMPORT_SCHEMA_EXCEPT ) )
+		            stmt->list_type == FDW_IMPORT_SCHEMA_LIMIT_TO ||
+		            stmt->list_type == FDW_IMPORT_SCHEMA_EXCEPT))
 		{
 			/* Limited list? Assume we are taking no items */
 			if (stmt->list_type == FDW_IMPORT_SCHEMA_LIMIT_TO)
+			{
 				import_layer = false;
+			}
 
 			/* Check the list for our items */
-			foreach(lc, stmt->table_list)
+			foreach (lc, stmt->table_list)
 			{
-				RangeVar *rv = (RangeVar *) lfirst(lc);
+				RangeVar* rv = (RangeVar*) lfirst(lc);
 				/* Found one! */
-				if ( streq(rv->relname, table_name) )
+				if (streq(rv->relname, table_name))
 				{
 					if (stmt->list_type == FDW_IMPORT_SCHEMA_LIMIT_TO)
+					{
 						import_layer = true;
+					}
 					else
+					{
 						import_layer = false;
+					}
 
 					break;
 				}
@@ -2626,12 +2927,12 @@ ogrImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
 			stringbuffer_init(&buf);
 
 			err = ogrLayerToSQL(ogr_lyr,
-			         quote_identifier(server->servername),
-			         launder_table_names,
-			         launder_column_names,
-			         ogrGetGeometryOid() != BYTEAOID,
-			         &buf
-			      );
+			                    quote_identifier(server->servername),
+			                    launder_table_names,
+			                    launder_column_names,
+			                    ogrGetGeometryOid() != BYTEAOID,
+			                    &buf
+			                   );
 
 			if (err != OGRERR_NONE)
 			{
@@ -2643,14 +2944,14 @@ ogrImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
 		}
 	}
 
-	elog(NOTICE, "Number of tables to be created %d", list_length(commands) );
+	elog(NOTICE, "Number of tables to be created %d", list_length(commands));
 
 	ogrFinishConnection(&ogr);
 
 	return commands;
 }
 
-#endif /* PostgreSQL 9.5+ */
+#endif /* PostgreSQL 9.5+ for ogrImportForeignSchema */
 
 
 


=====================================
ogr_fdw.h
=====================================
@@ -14,6 +14,7 @@
 /*
  * PostgreSQL
  */
+#include "postgres.h"
 #include "access/heapam.h"
 #include "access/htup_details.h"
 #include "access/reloptions.h"
@@ -37,13 +38,11 @@
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
-#include "nodes/relation.h"
 #include "optimizer/clauses.h"
 #include "optimizer/cost.h"
 #include "optimizer/pathnode.h"
 #include "optimizer/planmain.h"
 #include "optimizer/restrictinfo.h"
-#include "optimizer/var.h"
 #include "parser/parsetree.h"
 #include "storage/ipc.h"
 #include "utils/builtins.h"
@@ -55,6 +54,13 @@
 #include "utils/syscache.h"
 #include "utils/timestamp.h"
 
+#if PG_VERSION_NUM < 120000
+#include "nodes/relation.h"
+#include "optimizer/var.h"
+#else
+#include "executor/tuptable.h"
+#endif
+
 /* GDAL/OGR includes and compat */
 #include "ogr_fdw_gdal.h"
 #include "ogr_fdw_common.h"
@@ -78,7 +84,8 @@ typedef enum
 typedef enum {
 	OGR_UPDATEABLE_FALSE,
 	OGR_UPDATEABLE_TRUE,
-	OGR_UPDATEABLE_UNSET
+	OGR_UPDATEABLE_UNSET,
+	OGR_UPDATEABLE_TRY
 } OgrUpdateable;
 
 typedef struct OgrFdwColumn
@@ -117,13 +124,13 @@ typedef struct OgrFdwTable
 
 typedef struct OgrConnection
 {
-	char *ds_str;         /* datasource connection string */
-	char *dr_str;         /* driver (format) name */
+	const char *ds_str;         /* datasource connection string */
+	const char *dr_str;         /* driver (format) name */
 	char *lyr_str;        /* layer name */
-	char *config_options; /* GDAL config options */
-	char *open_options;   /* GDAL open options */
-	bool ds_updateable;
-	bool lyr_updateable;
+	const char *config_options; /* GDAL config options */
+	const char *open_options;   /* GDAL open options */
+	OgrUpdateable ds_updateable;
+	OgrUpdateable lyr_updateable;
 	bool lyr_utf8;        /* OGR layer will return UTF8 strings */
 	GDALDatasetH ds;      /* GDAL datasource handle */
 	OGRLayerH lyr;        /* OGR layer handle */


=====================================
ogr_fdw_common.c
=====================================
@@ -54,7 +54,7 @@ ogrStringLaunder(char *str)
 	int i, j = 0;
 	char tmp[STR_MAX_LEN];
 	memset(tmp, 0, STR_MAX_LEN);
-	
+
 	for(i = 0; str[i]; i++)
 	{
 		char c = tolower(str[i]);
@@ -83,11 +83,11 @@ ogrStringLaunder(char *str)
 			j = STR_MAX_LEN - 1;
 	}
 	strncpy(str, tmp, STR_MAX_LEN);
-	
+
 }
 
-static char *
-ogrTypeToPgType(OGRFieldDefnH ogr_fld)
+static void
+ogrTypeToPgType(OGRFieldDefnH ogr_fld, char *pgtype, size_t width)
 {
 	OGRFieldType ogr_type = OGR_Fld_GetType(ogr_fld);
 	switch(ogr_type)
@@ -95,39 +95,59 @@ ogrTypeToPgType(OGRFieldDefnH ogr_fld)
 		case OFTInteger:
 #if GDAL_VERSION_MAJOR >= 2
 			if( OGR_Fld_GetSubType(ogr_fld) == OFSTBoolean )
-				return "boolean";
+			{
+				snprintf(pgtype, width, "boolean");
+				break;
+			}
 			else
 #endif
-				return "integer";
+			snprintf(pgtype, width, "integer");
+			break;
 		case OFTReal:
-			return "real";
+			snprintf(pgtype, width, "double precision");
+			break;
 		case OFTString:
-			return "varchar";
+		{
+			int ogr_fld_width = OGR_Fld_GetWidth(ogr_fld);
+			if (ogr_fld_width > 0)
+				snprintf(pgtype, width, "varchar(%d)", ogr_fld_width);
+			else
+				snprintf(pgtype, width, "varchar");
+			break;
+		}
 		case OFTBinary:
-			return "bytea";
+			snprintf(pgtype, width, "bytea");
+			break;
 		case OFTDate:
-			return "date";
+			snprintf(pgtype, width, "date");
+			break;
 		case OFTTime:
-			return "time";
+			snprintf(pgtype, width, "time");
+			break;
 		case OFTDateTime:
-			return "timestamp";
+			snprintf(pgtype, width, "timestamp");
+			break;
 		case OFTIntegerList:
-			return "integer[]";
+			snprintf(pgtype, width, "integer[]");
+			break;
 		case OFTRealList:
-			return "real[]";
+			snprintf(pgtype, width, "double precision[]");
+			break;
 		case OFTStringList:
-			return "varchar[]";
+			snprintf(pgtype, width, "varchar[]");
+			break;
 #if GDAL_VERSION_MAJOR >= 2
 		case OFTInteger64:
-			return "bigint";
+			snprintf(pgtype, width, "bigint");
+			break;
 #endif
 		default:
-			CPLError(CE_Failure, CPLE_AssertionFailed, 
-			         "unsupported GDAL type '%s'", 
+			CPLError(CE_Failure, CPLE_AssertionFailed,
+			         "unsupported GDAL type '%s'",
 			         OGR_GetFieldTypeName(ogr_type));
-			return NULL;
+			return;
 	}
-	return NULL;
+	return;
 }
 
 static void
@@ -182,13 +202,13 @@ ogrGeomTypeToPgGeomType(stringbuffer_t *buf, OGRwkbGeometryType gtype)
 			CPLError(CE_Failure, CPLE_AssertionFailed, "Cannot handle OGR geometry type '%d'", gtype);
 	}
 
-#if GDAL_VERSION_MAJOR >= 2 
+#if GDAL_VERSION_MAJOR >= 2
 	if ( wkbHasZ(gtype) )
 #else
 	if ( gtype & wkb25DBit )
 #endif
 		stringbuffer_append(buf, "Z");
-	
+
 #if GDAL_VERSION_MAJOR >= 2 && GDAL_VERSION_MINOR >= 1
 	if ( wkbHasM(gtype) )
 		stringbuffer_append(buf, "M");
@@ -226,8 +246,9 @@ ogrColumnNameToSQL (const char *ogrcolname, const char *pgtype, int launder_colu
 	return OGRERR_NONE;
 }
 
+
 OGRErr
-ogrLayerToSQL (const OGRLayerH ogr_lyr, const char *fdw_server, 
+ogrLayerToSQL (const OGRLayerH ogr_lyr, const char *fdw_server,
 			   int launder_table_names, int launder_column_names,
 			   int use_postgis_geometry, stringbuffer_t *buf)
 {
@@ -235,7 +256,7 @@ ogrLayerToSQL (const OGRLayerH ogr_lyr, const char *fdw_server,
 	char table_name[STR_MAX_LEN];
 	OGRFeatureDefnH ogr_fd = OGR_L_GetLayerDefn(ogr_lyr);
 	stringbuffer_t gbuf;
-	
+
 	stringbuffer_init(&gbuf);
 
 	if ( ! ogr_fd )
@@ -249,18 +270,18 @@ ogrLayerToSQL (const OGRLayerH ogr_lyr, const char *fdw_server,
 #else
 	geom_field_count = (OGR_L_GetGeomType(ogr_lyr) != wkbNone);
 #endif
-	
+
 	/* Process table name */
 	strncpy(table_name, OGR_L_GetName(ogr_lyr), STR_MAX_LEN);
 	if (launder_table_names)
 		ogrStringLaunder(table_name);
-	
+
 	/* Create table */
 	stringbuffer_aprintf(buf, "CREATE FOREIGN TABLE %s (\n", quote_identifier(table_name));
-	
+
 	/* For now, every table we auto-create will have a FID */
 	stringbuffer_append(buf, "  fid bigint");
-	
+
 	/* Handle all geometry columns in the OGR source */
 	for ( i = 0; i < geom_field_count; i++ )
 	{
@@ -284,11 +305,11 @@ ogrLayerToSQL (const OGRLayerH ogr_lyr, const char *fdw_server,
 
 		/* PostGIS geometry type has lots of complex stuff */
 		if ( use_postgis_geometry )
-		{	
+		{
 			/* Add geometry type info */
 			stringbuffer_append(&gbuf, "Geometry(");
 			ogrGeomTypeToPgGeomType(&gbuf, gtype);
-			
+
 			/* See if we have an EPSG code to work with */
 			if ( gsrs )
 			{
@@ -303,7 +324,7 @@ ogrLayerToSQL (const OGRLayerH ogr_lyr, const char *fdw_server,
 					srid = atoi(charSrsCode);
 				}
 			}
-		
+
 			/* Add EPSG number, if figured it out */
 			if ( srid )
 			{
@@ -319,7 +340,7 @@ ogrLayerToSQL (const OGRLayerH ogr_lyr, const char *fdw_server,
 		{
 			stringbuffer_append(&gbuf, "bytea");
 		}
-	
+
 		/* Use geom field name if we have it */
 		if ( geomfldname && strlen(geomfldname) > 0 )
 		{
@@ -340,21 +361,21 @@ ogrLayerToSQL (const OGRLayerH ogr_lyr, const char *fdw_server,
 	/* Write out attribute fields */
 	for ( i = 0; i < OGR_FD_GetFieldCount(ogr_fd); i++ )
 	{
+		char pgtype[128];
 		OGRFieldDefnH ogr_fld = OGR_FD_GetFieldDefn(ogr_fd, i);
-		ogrColumnNameToSQL(OGR_Fld_GetNameRef(ogr_fld), 
-		                   ogrTypeToPgType(ogr_fld), 
-		                   launder_column_names, buf);
+		ogrTypeToPgType(ogr_fld, pgtype, 128);
+		ogrColumnNameToSQL(OGR_Fld_GetNameRef(ogr_fld), pgtype, launder_column_names, buf);
 	}
 
 	/*
 	 * Add server name and layer-level options.  We specify remote
 	 * layer name as option
 	 */
-	stringbuffer_aprintf(buf, "\n) SERVER %s\nOPTIONS (", quote_identifier(fdw_server));
+	stringbuffer_aprintf(buf, "\n) SERVER \"%s\"\nOPTIONS (", quote_identifier(fdw_server));
 	stringbuffer_append(buf, "layer ");
 	ogrDeparseStringLiteral(buf, OGR_L_GetName(ogr_lyr));
 	stringbuffer_append(buf, ");\n");
-	
+
 	return OGRERR_NONE;
 }
 


=====================================
ogr_fdw_deparse.c
=====================================
@@ -5,14 +5,12 @@
  *
  * Copyright (c) 2014-2015, Paul Ramsey <pramsey at cleverelephant.ca>
  *
- * Convert parse tree to a QueryExpression as described at 
+ * Convert parse tree to a QueryExpression as described at
  * http://gdal.org/ogr_sql.html
  *-------------------------------------------------------------------------
  */
 
 
-#include "postgres.h"
-
 /*
  * Local structures
  */
@@ -131,7 +129,7 @@ ogrDeparseConst(Const* constant, OgrDeparseCtx *context)
 	else if ( constant->consttype == ogrGetGeometryOid() )
 	{
 		/*
-		 * For geometry we need to convert the gserialized constant into 
+		 * For geometry we need to convert the gserialized constant into
 		 * an OGRGeometry for the OGR spatial filter.
 		 * For that, we can use the type's "send" function
 		 * which takes in gserialized and spits out EWKB.
@@ -152,16 +150,16 @@ ogrDeparseConst(Const* constant, OgrDeparseCtx *context)
 		 */
 		getTypeBinaryOutputInfo(constant->consttype, &sendfunction, &typeIsVarlena);
 		wkbdatum = OidFunctionCall1(sendfunction, constant->constvalue);
-		
-		/* 
-		 * Convert the WKB into an OGR geometry 
+
+		/*
+		 * Convert the WKB into an OGR geometry
 		 */
 		gser = DatumGetPointer(wkbdatum);
 		wkb = VARDATA(gser);
 		wkb_size = VARSIZE(gser) - VARHDRSZ;
 		err = OGR_G_CreateFromWkb((unsigned char *)wkb, NULL, &ogrgeom, wkb_size);
-		
-		/* 
+
+		/*
 		 * Save the result
 		 */
 		if ( err != OGRERR_NONE )
@@ -171,8 +169,8 @@ ogrDeparseConst(Const* constant, OgrDeparseCtx *context)
 			else
 				elog(WARNING, "got two geometries in OGR FDW query, only using the first");
 		}
-		/* 
-		 * geometry doesn't play a role in the deparsed SQL 
+		/*
+		 * geometry doesn't play a role in the deparsed SQL
 		 */
 		return false;
 	}
@@ -205,15 +203,15 @@ ogrIsLegalVarName(const char *varname)
 {
 	size_t len = strlen(varname);
 	int i;
-		
+
 	for ( i = 0; i < len; i++ )
 	{
 		char c = varname[i];
-			
+
 		/* First char must be a-zA-Z */
 		if ( i == 0 && ! ((c>=97&&c<=122)||(c>=65&&c<=90)) )
 			return false;
-		
+
 		/* All other chars must be 0-9a-zA-Z_ */
 		if ( ! ((c>=97&&c<=122)||(c>=65&&c<=90)||(c>=48&&c<=59)||(c==96)) )
 			return false;
@@ -226,7 +224,7 @@ static bool
 ogrDeparseVar(Var *node, OgrDeparseCtx *context)
 {
 	StringInfoData *buf = context->buf;
-	
+
 	if (node->varno == context->foreignrel->relid && node->varlevelsup == 0)
 	{
 		/* Var belongs to foreign table */
@@ -246,7 +244,7 @@ ogrDeparseVar(Var *node, OgrDeparseCtx *context)
 			if ( table->cols[i].pgattnum == node->varattno )
 			{
 				const char *fldname = NULL;
-				
+
 				if ( table->cols[i].ogrvariant == OGR_FID )
 				{
 					fldname = OGR_L_GetFIDColumn(lyr);
@@ -259,19 +257,19 @@ ogrDeparseVar(Var *node, OgrDeparseCtx *context)
 					OGRFieldDefnH fld = OGR_FD_GetFieldDefn(fd, table->cols[i].ogrfldnum);
 					fldname = OGR_Fld_GetNameRef(fld);
 				}
-				
+
 				if ( fldname )
 				{
 					if ( ogrIsLegalVarName(fldname) )
 						appendStringInfoString(buf, fldname);
 					else
 						appendStringInfo(buf, "\"%s\"", fldname);
-					
+
 					done = true;
 				}
 			}
 		}
-		
+
 		return done;
 	}
 	else
@@ -279,7 +277,7 @@ ogrDeparseVar(Var *node, OgrDeparseCtx *context)
 		elog(ERROR, "got to param handling section of ogrDeparseVar");
 		return false;
 	}
-	
+
 	return true;
 }
 
@@ -288,7 +286,7 @@ static int ogrOperatorCmpFunc(const void * a, const void * b)
 	return strcasecmp(*(const char**)a, *(const char**)b);
 }
 
-static bool 
+static bool
 ogrOperatorIsSupported(const char *opname)
 {
 	/* IMPORTANT */
@@ -296,7 +294,7 @@ ogrOperatorIsSupported(const char *opname)
 	static const char * ogrOperators[10] = { "!=", "&&", "<", "<=", "<>", "=", ">", ">=", "~~", "~~*" };
 
 	elog(DEBUG3, "ogrOperatorIsSupported got operator '%s'", opname);
-	
+
 	if ( bsearch(&opname, ogrOperators, 10, sizeof(char*), ogrOperatorCmpFunc) )
 		return true;
 	else
@@ -354,7 +352,7 @@ ogrDeparseOpExpr(OpExpr* node, OgrDeparseCtx *context)
 		// 	constant = (Const*)l_arg;
 		// else
 		// 	return false;
-		
+
 		// if ( constant->consttype != ogrGetGeometryOid() )
 
 		ReleaseSysCache(tuple);
@@ -385,10 +383,10 @@ ogrDeparseOpExpr(OpExpr* node, OgrDeparseCtx *context)
 	/* use 'ILIKE' all the time. */
 	if ( streq(opname, "~~") || streq(opname, "~~*") )
 		opname = "ILIKE";
-	
+
 	/* Operator symbol */
 	appendStringInfoString(buf, opname);
-	
+
 	/* Deparse right operand. */
 	if (oprkind == 'l' || oprkind == 'b')
 	{
@@ -402,7 +400,7 @@ ogrDeparseOpExpr(OpExpr* node, OgrDeparseCtx *context)
 
 	ReleaseSysCache(tuple);
 	return result;
-	
+
 }
 
 static bool
@@ -436,9 +434,9 @@ ogrDeparseBoolExpr(BoolExpr *node, OgrDeparseCtx *context)
 	appendStringInfoChar(buf, '(');
 	foreach(lc, node->args)
 	{
-		
+
 		len_save_part = buf->len;
-		
+
 		/* Connect expressions and parenthesize each condition */
 		if ( ! first )
 			appendStringInfo(buf, " %s ", op);
@@ -446,7 +444,7 @@ ogrDeparseBoolExpr(BoolExpr *node, OgrDeparseCtx *context)
 		/* Unparse the expression, if possible */
 		result = ogrDeparseExpr((Expr *) lfirst(lc), context);
 		result_total += result;
-		
+
 		/* We can backtrack just this term for AND expressions */
 		if ( boolop == AND_EXPR && ! result )
 			setStringInfoLength(buf, len_save_part);
@@ -454,17 +452,17 @@ ogrDeparseBoolExpr(BoolExpr *node, OgrDeparseCtx *context)
 		/* We have to drop the whole thing if we can't get every part of an OR expression */
 		if ( boolop == OR_EXPR && ! result )
 			break;
-		
+
 		/* Don't flip the "first" bit until we get a good expression */
 		if ( first && result )
 			first = false;
 	}
 	appendStringInfoChar(buf, ')');
-	
+
 	/* We have to drop the whole thing if we can't get every part of an OR expression */
 	if ( boolop == OR_EXPR && ! result )
 		setStringInfoLength(buf, len_save_all);
-	
+
 	return result_total > 0;
 }
 
@@ -521,9 +519,15 @@ ogrDeparseExpr(Expr *node, OgrDeparseCtx *context)
 			/* TODO: Handle this to support the "IN" operator */
 			elog(NOTICE, "unsupported OGR FDW expression type, T_ScalarArrayOpExpr");
 			return false;
+#if PG_VERSION_NUM < 120000
 		case T_ArrayRef:
 			elog(NOTICE, "unsupported OGR FDW expression type, T_ArrayRef");
 			return false;
+#else
+		case T_SubscriptingRef:
+			elog(NOTICE, "unsupported OGR FDW expression type, T_SubscriptingRef");
+			return false;
+#endif
 		case T_ArrayExpr:
 			elog(NOTICE, "unsupported OGR FDW expression type, T_ArrayExpr");
 			return false;
@@ -537,7 +541,7 @@ ogrDeparseExpr(Expr *node, OgrDeparseCtx *context)
 			elog(NOTICE, "unsupported OGR FDW expression type for deparse: %d", (int) nodeTag(node));
 			return false;
 	}
-	
+
 }
 
 
@@ -584,13 +588,13 @@ ogrDeparse(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, List *expr
 			/* Couldn't unparse some portion of the expression, so rewind the stringinfo */
 			setStringInfoLength(buf, len_save);
 		}
-		
+
 		/* Don't flip the "first" bit until we get a good expression */
 		if ( first && result )
 			first = false;
-	}	
-	
-	return true;	
+	}
+
+	return true;
 }
 
 


=====================================
ogr_fdw_gdal.h
=====================================
@@ -2,6 +2,34 @@
 #ifndef _OGR_FDW_GDAL_H
 #define _OGR_FDW_GDAL_H 1
 
+/*
+ * Quiet warnings due to double use of
+ * pkgconfig macros in GDAL and PgSQL
+ */
+#ifdef PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#endif
+
+#ifdef PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#endif
+
+#ifdef PACKAGE_STRING
+#undef PACKAGE_STRING
+#endif
+
+#ifdef PACKAGE_NAME
+#undef PACKAGE_NAME
+#endif
+
+#ifdef PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#endif
+
+#ifdef PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#endif
+
 /*
  * OGR library API
  */
@@ -11,11 +39,11 @@
 #include "cpl_error.h"
 #include "cpl_string.h"
 
-/* 
+/*
  * As far as possible code is GDAL2 compliant, and these
  * mappings are used to convert to GDAL1-style function
  * names. For GDALDatasetH opening, there are specific
- * code blocks to handle version differences between 
+ * code blocks to handle version differences between
  * GDALOpenEx() and OGROpen()
  */
 #if GDAL_VERSION_MAJOR < 2
@@ -39,4 +67,4 @@
 
 #endif /* GDAL 1 support */
 
-#endif /* _OGR_FDW_GDAL_H */
\ No newline at end of file
+#endif /* _OGR_FDW_GDAL_H */


=====================================
output/file.source
=====================================
@@ -10,7 +10,7 @@ CREATE FOREIGN TABLE pt_1 (
   geom bytea,
   name varchar,
   age integer,
-  height real,
+  height double precision,
   birthdate date )
   SERVER myserver
   OPTIONS ( layer 'pt_two' );
@@ -46,6 +46,20 @@ SELECT * FROM pt_3 ORDER BY name;
  \x0101000000c00497d1162cb93f8cbaef08a080e63f | Peter
 (2 rows)
 
+------------------------------------------------
+CREATE FOREIGN TABLE poly_1 (
+  fid bigint,
+  geom bytea,
+  id double precision,
+  name varchar(5)
+) SERVER myserver
+OPTIONS (layer 'poly');
+SELECT length(geom) FROM poly_1 WHERE name = 'Three';
+ length 
+--------
+    307
+(1 row)
+
 ------------------------------------------------
 -- Laundering and explicit column naming test
 CREATE FOREIGN TABLE column_name_test (
@@ -87,7 +101,7 @@ CREATE FOREIGN TABLE e_1 (
   name varchar )
   SERVER myserver_latin1
   OPTIONS ( layer 'enc' );
-SET client_min_messages = debug1;  
+SET client_min_messages = debug1;
 SELECT * FROM e_1 WHERE fid = 1;
 DEBUG:  GDAL config option 'SHAPE_ENCODING' set to 'LATIN1'
 DEBUG:  OGR SQL: (fid = 1)
@@ -97,7 +111,7 @@ DEBUG:  GDAL config option 'SHAPE_ENCODING' set to 'LATIN1'
    1 | Pàul
 (1 row)
 
-SET client_min_messages = notice;  
+SET client_min_messages = notice;
 ------------------------------------------------
 -- Geometryless test
 CREATE SERVER csvserver
@@ -112,9 +126,9 @@ CREATE FOREIGN TABLE no_geom (
   value varchar
 ) SERVER csvserver
 OPTIONS (layer 'no_geom');
-SELECT c.* 
-  FROM generate_series(1,4) g 
-  JOIN no_geom c 
+SELECT c.*
+  FROM generate_series(1,4) g
+  JOIN no_geom c
   ON (c.fid = g.g);
  fid |  name   | age | value 
 -----+---------+-----+-------


=====================================
output/import.source
=====================================
@@ -19,7 +19,7 @@ ORDER BY c.ordinal_position;
  geom        | bytea             | 
  n2ame       | character varying | {column_name=2ame}
  age         | integer           | 
- height      | real              | 
+ height      | double precision  | 
  b_rthdate   | date              | {column_name=b-rthdate}
 (6 rows)
 
@@ -46,7 +46,7 @@ ORDER BY c.ordinal_position;
  column_name |     data_type     | attfdwoptions 
 -------------+-------------------+---------------
  fid         | bigint            | 
- id          | real              | 
+ id          | double precision  | 
  natural     | character varying | 
 (3 rows)
 



View it on GitLab: https://salsa.debian.org/debian-gis-team/pgsql-ogr-fdw/commit/6f4a8c53f0e0d33d2c6580f43e55da5264bee605

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/pgsql-ogr-fdw/commit/6f4a8c53f0e0d33d2c6580f43e55da5264bee605
You're receiving this email because of your account on salsa.debian.org.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20190502/d32cf199/attachment-0001.html>


More information about the Pkg-grass-devel mailing list