[GRASS-SVN] r47791 - grass/trunk/lib/vector/Vlib

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Aug 21 07:03:07 EDT 2011


Author: martinl
Date: 2011-08-21 04:03:07 -0700 (Sun, 21 Aug 2011)
New Revision: 47791

Modified:
   grass/trunk/lib/vector/Vlib/write_ogr.c
Log:
vlib: improve writing attributes for OGR


Modified: grass/trunk/lib/vector/Vlib/write_ogr.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_ogr.c	2011-08-21 11:01:07 UTC (rev 47790)
+++ grass/trunk/lib/vector/Vlib/write_ogr.c	2011-08-21 11:03:07 UTC (rev 47791)
@@ -7,8 +7,13 @@
 
    Inspired by v.out.ogr's code.
 
-   (C) 2009-2010 by the GRASS Development Team
+   \todo OGR version of V2__delete_area_cats_from_cidx_nat()
+   \todo function to delete corresponding entry in fidx
+   \todo OGR version of V2__add_area_cats_to_cidx_nat
+   \todo OGR version of V2__add_line_to_topo_nat
 
+   (C) 2009-2011 by the GRASS Development Team
+
    This program is free software under the GNU General Public License
    (>=v2). Read the file COPYING that comes with GRASS for details.
 
@@ -22,20 +27,16 @@
 #ifdef HAVE_OGR
 #include <ogr_api.h>
 
-static int write_attributes(int, const struct field_info *,
+static int sqltype_to_ogrtype(int);
+static dbDriver *create_table(OGRLayerH, const struct field_info *);
+static int write_attributes(dbDriver *, int, const struct field_info *,
 			    OGRLayerH, OGRFeatureH);
 
-/* TODO:
- * OGR version of V2__delete_area_cats_from_cidx_nat()
- * function to delete corresponding entry in fidx
- * OGR version of V2__add_area_cats_to_cidx_nat
- * OGR version of V2__add_line_to_topo_nat
- */
-
 void V2__add_line_to_topo_ogr(struct Map_info *Map, int line,
-			    const struct line_pnts *points, const struct line_cats *cats)
+			      const struct line_pnts *points,
+			      const struct line_cats *cats)
 {
-   /* recycle code from build_ogr */
+    /* recycle code from build_ogr */
     G_warning("feature not yet implemented, coming soon...");
 
     return;
@@ -52,13 +53,16 @@
   \return feature offset into file
   \return -1 on error
 */
-off_t V1_write_line_ogr(struct Map_info *Map,
-			int type, const struct line_pnts *points, const struct line_cats *cats)
+off_t V1_write_line_ogr(struct Map_info *Map, int type,
+			const struct line_pnts *points,
+			const struct line_cats *cats)
 {
     int i, cat, ret;
 
     struct field_info *Fi;
     
+    dbDriver *driver;
+    
     OGRGeometryH       Ogr_geometry;
     OGRFeatureH        Ogr_feature;
     OGRFeatureDefnH    Ogr_featuredefn;
@@ -69,6 +73,20 @@
 	    return -1;
     }
 
+    /* check for attributes */
+    Fi = Vect_get_field(Map, cats->field[0]);
+    driver = NULL;
+    cat = -1;      /* no attributes to be written */
+    if (Fi && cats->n_cats > 0) {
+	cat = cats->cat[0];
+	if (cats->n_cats > 1) {
+	    G_warning(_("Feature has more categories, using "
+			"category %d (from layer %d)"),
+		      cat, cats->field[0]);
+	}
+	driver = create_table(Map->fInfo.ogr.layer, Fi);
+    }
+    
     Ogr_featuredefn = OGR_L_GetLayerDefn(Map->fInfo.ogr.layer);
     Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn);
     
@@ -120,15 +138,9 @@
     OGR_F_SetGeometry(Ogr_feature, Ogr_geometry);
 
     /* write attributes */
-    Fi = Vect_get_field(Map, cats->field[0]);
-    if (Fi && cats->n_cats > 0) {
-	cat = cats->cat[0];
-	if (cats->n_cats > 1) {
-	    G_warning(_("Feature has more categories, using "
-			"category %d (from layer %d)"),
-		      cat, cats->field[0]);
-	}
-	write_attributes(cat, Fi, Map->fInfo.ogr.layer, Ogr_feature);
+    if (driver && cat > -1) {
+	write_attributes(driver, cat, Fi, Map->fInfo.ogr.layer, Ogr_feature);
+	db_close_database_shutdown_driver(driver);
     }
     
     /* write feature into layer */
@@ -348,20 +360,97 @@
     return ret;
 }
 
-int write_attributes(int cat, const struct field_info *Fi,
+dbDriver *create_table(OGRLayerH hLayer, const struct field_info *Fi)
+{
+    int col, ncols;
+    int sqltype, ogrtype;
+    
+    const char *colname;
+    
+    dbDriver *driver;
+    dbHandle handle;
+    dbCursor cursor;
+    dbTable *table;
+    dbColumn *column;
+    dbString sql;
+    
+    OGRFieldDefnH hFieldDefn;
+    OGRFeatureDefnH hFeatureDefn;
+
+    db_init_string(&sql);
+    db_init_handle(&handle);
+    
+    driver = db_start_driver(Fi->driver);
+    if (!driver) {
+	G_warning(_("Unable to start driver <%s>"), Fi->driver);
+	return NULL;
+    }
+    db_set_handle(&handle, Fi->database, NULL);
+    if (db_open_database(driver, &handle) != DB_OK) {
+	G_warning(_("Unable to open database <%s> by driver <%s>"),
+		  Fi->database, Fi->driver);
+	db_close_database_shutdown_driver(driver);
+	return NULL;
+    }
+    
+    /* to get no data */
+    db_set_string(&sql, "select * from ");
+    db_append_string(&sql, Fi->table);
+    db_append_string(&sql, " where 0 = 1");	
+    
+    if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
+	DB_OK) {
+	G_warning(_("Unable to open select cursor: '%s'"),
+		  db_get_string(&sql));
+	db_close_database_shutdown_driver(driver);
+	return NULL;
+    }
+
+    table = db_get_cursor_table(&cursor);
+    ncols = db_get_table_number_of_columns(table);
+
+    hFeatureDefn = OGR_L_GetLayerDefn(hLayer);
+    
+    for (col = 0; col < ncols; col++) {
+	column = db_get_table_column(table, col);
+	colname = db_get_column_name(column);	
+	sqltype = db_get_column_sqltype(column);
+	ogrtype = sqltype_to_ogrtype(sqltype);
+		
+	if (OGR_FD_GetFieldIndex(hFeatureDefn, colname) > -1) {
+	    /* field already exists */
+	    continue;
+	}
+
+	hFieldDefn = OGR_Fld_Create(colname, ogrtype);
+	/* OGR_Fld_SetWidth(hFieldDefn, length); */
+	if (OGR_L_CreateField(hLayer, hFieldDefn, TRUE) != OGRERR_NONE) {
+	    G_warning(_("Creating field <%s> failed\n"), colname);
+	    db_close_database_shutdown_driver(driver);
+	    return NULL;
+	}
+	
+	OGR_Fld_Destroy(hFieldDefn);
+    }
+
+    return driver;
+}
+
+int write_attributes(dbDriver *driver, int cat, const struct field_info *Fi,
 		     OGRLayerH Ogr_layer, OGRFeatureH Ogr_feature)
 {
     int j, ogrfieldnum;
     char buf[2000];
     int ncol, colsqltype, colctype, more;
-    const char *fidcol;
-    dbDriver *Driver;
-    dbTable *Table;
+    const char *fidcol, *colname;
+    dbTable *table;
     dbString dbstring;
-    dbColumn *Column;
+    dbColumn *column;
     dbCursor cursor;
-    dbValue *Value;
+    dbValue *value;
 
+    OGRFieldDefnH hFieldDefn;
+    
     G_debug(3, "write_attributes(): cat = %d", cat);
 
     if (cat < 0) {
@@ -377,12 +466,8 @@
     G_debug(4, "SQL: %s", buf);
     db_set_string(&dbstring, buf);
 
-    /* open driver & select data */
-    Driver = db_start_driver_open_database(Fi->driver, Fi->database);
-    if (!Driver)
-	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
-		      Fi->database, Fi->driver);
-    if (db_open_select_cursor(Driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) {
+    /* select data */
+    if (db_open_select_cursor(driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) {
 	G_fatal_error(_("Unable to select attributes for category %d"),
 		      cat);
     }
@@ -393,57 +478,63 @@
     }
     
     if (!more) {
-	G_warning (_("No database record for category %d - export of 'cat' disabled"),
-		   cat);
+	G_warning(_("No database record for category %d, "
+		    "no attributes will be written"),
+		  cat);
 	return -1;
     }
 
     fidcol = OGR_L_GetFIDColumn(Ogr_layer); 
 
-    Table = db_get_cursor_table(&cursor);
-    ncol = db_get_table_number_of_columns(Table);
+    table = db_get_cursor_table(&cursor);
+    ncol = db_get_table_number_of_columns(table);
     for (j = 0; j < ncol; j++) {
-	Column = db_get_table_column(Table, j);
-	if (fidcol && strcmp(db_get_column_name(Column), fidcol) == 0) {
+	column = db_get_table_column(table, j);
+	colname = db_get_column_name(column);
+	if (fidcol && *fidcol && strcmp(colname, fidcol) == 0) {
 	    /* skip fid column */
 	    continue;
 	}
-	Value = db_get_column_value(Column);
-	db_convert_column_value_to_string(Column, &dbstring);	/* for debug only */
+	value = db_get_column_value(column);
+	/* for debug only */
+	db_convert_column_value_to_string(column, &dbstring);	
 	G_debug(2, "col %d : val = %s", j,
 		db_get_string(&dbstring));
 	
-	colsqltype = db_get_column_sqltype(Column);
+	colsqltype = db_get_column_sqltype(column);
 	colctype = db_sqltype_to_Ctype(colsqltype);
 	G_debug(2, "  colctype = %d", colctype);
 	
-	ogrfieldnum = OGR_F_GetFieldIndex(Ogr_feature,
-					  db_get_column_name(Column));
+	ogrfieldnum = OGR_F_GetFieldIndex(Ogr_feature, colname);
 	if (ogrfieldnum < 0) {
-	    G_warning(_("Uknown column <%s>"),
-		      db_get_column_name(Column));
-	    continue;
+	    /* create field if not exists */
+	    hFieldDefn = OGR_Fld_Create(colname, 
+					sqltype_to_ogrtype(colsqltype));
+	    if (OGR_L_CreateField(Ogr_layer, hFieldDefn, TRUE) != OGRERR_NONE)
+		G_warning(_("Unable to create field <%s>"), colname);
+	    ogrfieldnum = OGR_F_GetFieldIndex(Ogr_feature, colname);
 	}
+	    
 	/* Reset */
 	OGR_F_UnsetField(Ogr_feature, ogrfieldnum);
 	
 	/* prevent writing NULL values */
-	if (!db_test_value_isnull(Value)) {
+	if (!db_test_value_isnull(value)) {
 	    switch (colctype) {
 	    case DB_C_TYPE_INT:
 		OGR_F_SetFieldInteger(Ogr_feature, ogrfieldnum,
-				      db_get_value_int(Value));
+				      db_get_value_int(value));
 		break;
 	    case DB_C_TYPE_DOUBLE:
 		OGR_F_SetFieldDouble(Ogr_feature, ogrfieldnum,
-				     db_get_value_double(Value));
+				     db_get_value_double(value));
 		break;
 	    case DB_C_TYPE_STRING:
 		OGR_F_SetFieldString(Ogr_feature, ogrfieldnum,
-				     db_get_value_string(Value));
+				     db_get_value_string(value));
 		break;
 	    case DB_C_TYPE_DATETIME:
-		db_convert_column_value_to_string(Column,
+		db_convert_column_value_to_string(column,
 						  &dbstring);
 		OGR_F_SetFieldString(Ogr_feature, ogrfieldnum,
 				     db_get_string(&dbstring));
@@ -453,12 +544,38 @@
     }
 
     db_close_cursor (&cursor);
-    db_close_database(Driver);
-    db_shutdown_driver(Driver);
     
     db_free_string(&dbstring);
     
     return 1;
 }
 
+int sqltype_to_ogrtype(int sqltype)
+{
+    switch(sqltype) {
+    case DB_SQL_TYPE_CHARACTER:
+    case DB_SQL_TYPE_TEXT:
+	return OFTString;
+    case DB_SQL_TYPE_SMALLINT:
+    case DB_SQL_TYPE_INTEGER:
+    case DB_SQL_TYPE_SERIAL:
+	return OFTInteger;
+    case DB_SQL_TYPE_REAL:
+    case DB_SQL_TYPE_DOUBLE_PRECISION:
+    case DB_SQL_TYPE_DECIMAL:
+    case DB_SQL_TYPE_NUMERIC:
+	return OFTReal;
+    case DB_SQL_TYPE_DATE:
+	return OFTDate;
+    case DB_SQL_TYPE_TIME:	
+	return OFTTime;
+    case DB_SQL_TYPE_TIMESTAMP:
+	return OFTDateTime;
+    case DB_SQL_TYPE_INTERVAL:
+	return OFTString; /* ??? */
+    }
+
+    return OFTString;
+}
+
 #endif /* HAVE_OGR */



More information about the grass-commit mailing list