[GRASS-SVN] r72209 - grass/trunk/vector/v.in.ogr

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Feb 5 04:52:52 PST 2018


Author: mmetz
Date: 2018-02-05 04:52:52 -0800 (Mon, 05 Feb 2018)
New Revision: 72209

Modified:
   grass/trunk/vector/v.in.ogr/main.c
Log:
v.in.ogr: fix duplicate column names (fixes #3488)

Modified: grass/trunk/vector/v.in.ogr/main.c
===================================================================
--- grass/trunk/vector/v.in.ogr/main.c	2018-02-05 12:51:55 UTC (rev 72208)
+++ grass/trunk/vector/v.in.ogr/main.c	2018-02-05 12:52:52 UTC (rev 72209)
@@ -82,6 +82,31 @@
 OGRFeatureH ogr_getnextfeature(struct OGR_iterator *, int, char *,
 			       OGRGeometryH , const char *);
 
+struct grass_col_info
+{
+    int idx;	/* index for create table */
+    const char *name;
+    const char *type;
+};
+
+/* for qsort: compare columns by name */
+int cmp_col_name(const void *a, const void *b)
+{
+    struct grass_col_info *ca = (struct grass_col_info *)a;
+    struct grass_col_info *cb = (struct grass_col_info *)b;
+
+    return strcmp(ca->name, cb->name);
+}
+
+/* for qsort: compare columns by index */
+int cmp_col_idx(const void *a, const void *b)
+{
+    struct grass_col_info *ca = (struct grass_col_info *)a;
+    struct grass_col_info *cb = (struct grass_col_info *)b;
+
+    return (ca->idx - cb->idx);
+}
+
 int main(int argc, char *argv[])
 {
     struct GModule *module;
@@ -892,6 +917,9 @@
 
 	/* Add DB link and create table */
 	if (!flag.notab->answer) {
+	    int i_out, ncols_out, done;
+	    struct grass_col_info *col_info;
+
 	    G_important_message(_("Creating attribute table for layer <%s>..."),
 				  layer_names[layer]);
 
@@ -913,14 +941,24 @@
 	    ncols = OGR_FD_GetFieldCount(Ogr_featuredefn);
 	    G_debug(2, "%d columns", ncols);
 
+	    ncols_out = ncols;
+	    if (key_idx[layer] < 0)
+		ncols_out++;
+	    
+	    col_info = G_malloc(ncols_out * sizeof(struct grass_col_info));
+
 	    /* Create table */
-	    sprintf(buf, "create table %s (%s integer", Fi->table,
-		    key_column[layer]);
-	    db_set_string(&sql, buf);
+	    i_out = 0;
+	    col_info[i_out].idx = i_out;
+	    col_info[i_out].name = key_column[layer];
+	    col_info[i_out].type = "integer";
+
 	    for (i = 0; i < ncols; i++) {
 
                 if (key_idx[layer] > -1 && key_idx[layer] == i)
                     continue; /* skip defined key (FID column) */
+
+		i_out++;
                 
 		Ogr_field = OGR_FD_GetFieldDefn(Ogr_featuredefn, i);
 		Ogr_ftype = OGR_Fld_GetType(Ogr_field);
@@ -941,8 +979,8 @@
 
 		}
 
-		/* avoid that we get the 'cat' column twice */
-		if (strcmp(Ogr_fieldname, GV_KEY_COLUMN) == 0) {
+		/* avoid that we get the key column twice */
+		if (strcmp(Ogr_fieldname, key_column[layer]) == 0) {
 		    sprintf(namebuf, "%s_", Ogr_fieldname);
 		    Ogr_fieldname = G_store(namebuf);
 		}
@@ -955,6 +993,8 @@
 		    G_important_message(_("Column name <%s> renamed to <%s>"),
 			      OGR_Fld_GetNameRef(Ogr_field), Ogr_fieldname);
 		}
+		col_info[i_out].idx = i_out;
+		col_info[i_out].name = G_store(Ogr_fieldname);
 
 		/** Simple 32bit integer                     OFTInteger = 0        **/
 		/** List of 32bit integers                   OFTIntegerList = 1    **/
@@ -973,14 +1013,14 @@
                 /** List of 64bit integers                   OFTInteger64List = 13 **/
 
 		if (Ogr_ftype == OFTInteger) {
-		    sprintf(buf, ", %s integer", Ogr_fieldname);
+		    col_info[i_out].type = "integer";
 		}
 #if GDAL_VERSION_NUM >= 2000000
 		else if (Ogr_ftype == OFTInteger64) {
                     if (strcmp(Fi->driver, "pg") == 0) 
-                        sprintf(buf, ", %s bigint", Ogr_fieldname);
+			col_info[i_out].type = "bigint";
                     else {
-                        sprintf(buf, ", %s integer", Ogr_fieldname);
+			col_info[i_out].type = "integer";
                         if (strcmp(Fi->driver, "sqlite") != 0) 
                             G_warning(_("Writing column <%s> with integer 64 as integer 32"),
                                       Ogr_fieldname);
@@ -993,23 +1033,24 @@
 #endif
                          ) {
 		    /* hack: treat as string */
-		    sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname,
-			    OFTIntegerListlength);
+		    sprintf(buf, "varchar ( %d )", OFTIntegerListlength);
+		    col_info[i_out].type = G_store(buf);
 		    G_warning(_("Writing column <%s> with fixed length %d chars (may be truncated)"),
 			      Ogr_fieldname, OFTIntegerListlength);
 		}
 		else if (Ogr_ftype == OFTReal) {
-		    sprintf(buf, ", %s double precision", Ogr_fieldname);
+		    col_info[i_out].type = "double precision";
 #if GDAL_VERSION_NUM >= 1320
 		}
 		else if (Ogr_ftype == OFTDate) {
-		    sprintf(buf, ", %s date", Ogr_fieldname);
+		    col_info[i_out].type = "date";
 		}
 		else if (Ogr_ftype == OFTTime) {
-		    sprintf(buf, ", %s time", Ogr_fieldname);
+		    col_info[i_out].type = "time";
 		}
 		else if (Ogr_ftype == OFTDateTime) {
-		    sprintf(buf, ", %s %s", Ogr_fieldname, datetime_type);
+		    sprintf(buf, "%s", datetime_type);
+		    col_info[i_out].type = G_store(buf);
 #endif
 		}
 		else if (Ogr_ftype == OFTString) {
@@ -1023,13 +1064,13 @@
 				  Ogr_fieldname);
 			fwidth = 255;
 		    }
-		    sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname,
-			    fwidth);
+		    sprintf(buf, "varchar ( %d )", fwidth);
+		    col_info[i_out].type = G_store(buf);
 		}
 		else if (Ogr_ftype == OFTStringList) {
 		    /* hack: treat as string */
-		    sprintf(buf, ", %s varchar ( %d )", Ogr_fieldname,
-			    OFTIntegerListlength);
+		    sprintf(buf, "varchar ( %d )", OFTIntegerListlength);
+		    col_info[i_out].type = G_store(buf);
 		    G_warning(_("Writing column %s with fixed length %d chars (may be truncated)"),
 			      Ogr_fieldname, OFTIntegerListlength);
 		}
@@ -1037,10 +1078,48 @@
 		    G_warning(_("Column type (Ogr_ftype: %d) not supported (Ogr_fieldname: %s)"),
 			      Ogr_ftype, Ogr_fieldname);
 		    buf[0] = 0;
+		    col_info[i_out].type = G_store(buf);
 		}
-		db_append_string(&sql, buf);
 		G_free(Ogr_fieldname);
 	    }
+
+	    /* fix duplicate column names */
+	    done = 0;
+
+	    while (!done) {
+		done = 1;
+		qsort(col_info, ncols_out, sizeof(struct grass_col_info),
+		      cmp_col_name);
+		for (i = 0; i < ncols_out - 1; i++) {
+		    int i_a;
+
+		    i_a = 1;
+		    while (i + i_a < ncols_out &&
+			   strcmp(col_info[i].name, col_info[i + i_a].name) == 0) {
+			G_important_message(_("Column name <%s> renamed to <%s_%d>"),
+					    col_info[i + i_a].name, 
+					    col_info[i + i_a].name, i_a);
+			sprintf(buf, "%s_%d", col_info[i + i_a].name, i_a);
+			col_info[i + i_a].name = G_store(buf);
+			i_a++;
+			done = 0;
+		    }
+		}
+	    }
+	    qsort(col_info, ncols_out, sizeof(struct grass_col_info),
+		  cmp_col_idx);
+
+	    /* construct sql from column names and types */
+	    i = 0;
+	    sprintf(buf, "create table %s (%s %s", Fi->table,
+		    col_info[i].name, col_info[i].type);
+	    db_set_string(&sql, buf);
+
+	    for (i = 1; i < ncols_out; i++) {
+		sprintf(buf, ", %s %s", col_info[i].name, col_info[i].type);
+		db_append_string(&sql, buf);
+	    }
+
 	    db_append_string(&sql, ")");
 	    G_debug(3, "%s", db_get_string(&sql));
 
@@ -1067,6 +1146,8 @@
 			      Fi->table);
 
 	    db_close_database_shutdown_driver(driver);
+	    
+	    G_free(col_info);
 	}
     }
 



More information about the grass-commit mailing list