bool OGRGRASSLayer::SetAttributes ( OGRFeature *poFeature, dbTable *table )
{
    CPLDebug ( "GRASS", "OGRGRASSLayer::SetAttributes" );

    for ( int i = 0; i < nFields; i++) 
    {
	dbColumn *column = db_get_table_column ( table, i );
	dbValue *value = db_get_column_value ( column );

	int ctype = db_sqltype_to_Ctype ( db_get_column_sqltype(column) );

	if ( !db_test_value_isnull(value) )
	{
	    switch ( ctype ) {
		case DB_C_TYPE_INT:
		    poFeature->SetField( i, db_get_value_int ( value ));
		    break; 
		case DB_C_TYPE_DOUBLE:
		    poFeature->SetField( i, db_get_value_double ( value ));
		    break; 
		case DB_C_TYPE_STRING:
		    poFeature->SetField( i, db_get_value_string ( value ));
		    break; 
		case DB_C_TYPE_DATETIME:
		    db_convert_column_value_to_string ( column, poDbString );
		    poFeature->SetField( i, db_get_string ( poDbString ));
		    break; 
	    }
	}
	
	db_convert_column_value_to_string ( column, poDbString );
	//CPLDebug ( "GRASS", "val = %s", db_get_string ( poDbString ));
    }
    return true;
}
Exemple #2
0
/*!
   \fn 
   \brief 
   \return 
   \param 
 */
int
db_convert_value_to_string(dbValue * value, int sqltype, dbString * string)
{
    char buf[64];
    const char *bp = buf;

    if (db_test_value_isnull(value)) {
	*buf = 0;
    }
    else {
	switch (db_sqltype_to_Ctype(sqltype)) {
	case DB_C_TYPE_INT:
	    sprintf(buf, "%d", db_get_value_int(value));
	    break;
	case DB_C_TYPE_DOUBLE:
	    sprintf(buf, "%.15g", db_get_value_double(value));
	    G_trim_decimal(buf);
	    break;
	case DB_C_TYPE_STRING:
	    bp = db_get_value_string(value);
	    break;
	case DB_C_TYPE_DATETIME:
	    return db_convert_value_datetime_into_string(value, sqltype,
							 string);
	default:
	    db_error
		("db_convert_value_into_string(): unrecongized sqltype-type");
	    return DB_FAILED;
	}
    }
    return db_set_string(string, bp);
}
void QgsGrassVectorMapLayer::load()
{
  clear();

  if ( !mMap )
  {
    return;
  }

  // Attributes are not loaded for topo layers in which case field == 0
  if ( mField == 0 )
  {
    return;
  }

  QgsDebugMsg( QString( "cidxFieldIndex() = %1 cidxFieldNumCats() = %2" ).arg( cidxFieldIndex() ).arg( cidxFieldNumCats() ) );

  mFieldInfo = Vect_get_field( mMap->map(), mField ); // should work also with field = 0

  if ( !mFieldInfo )
  {
    QgsDebugMsg( "No field info -> no attribute table" );
  }
  else
  {
    QgsDebugMsg( "Field info found -> open database" );

    QFileInfo di( mMap->grassObject().mapsetPath() + "/vector/" + mMap->grassObject().name() + "/dbln" );
    mLastLoaded = di.lastModified();

    QString error;
    dbDriver *databaseDriver = openDriver( error );

    if ( !databaseDriver || !error.isEmpty() )
    {
      QgsDebugMsg( error );
    }
    else
    {
      QgsDebugMsg( "Database opened -> open select cursor" );
      QgsGrass::lock(); // not sure if lock is necessary
      dbString dbstr;
      db_init_string( &dbstr );
      db_set_string( &dbstr, ( char * )"select * from " );
      db_append_string( &dbstr, mFieldInfo->table );

      QgsDebugMsg( QString( "SQL: %1" ).arg( db_get_string( &dbstr ) ) );
      dbCursor databaseCursor;
      if ( db_open_select_cursor( databaseDriver, &dbstr, &databaseCursor, DB_SCROLL ) != DB_OK )
      {
        db_close_database_shutdown_driver( databaseDriver );
        QgsGrass::warning( "Cannot select attributes from table '" + QString( mFieldInfo->table ) + "'" );
      }
      else
      {
#ifdef QGISDEBUG
        int nRecords = db_get_num_rows( &databaseCursor );
        QgsDebugMsg( QString( "Number of records: %1" ).arg( nRecords ) );
#endif

        dbTable  *databaseTable = db_get_cursor_table( &databaseCursor );
        int nColumns = db_get_table_number_of_columns( databaseTable );

        // Read columns' description
        for ( int i = 0; i < nColumns; i++ )
        {
          QPair<double, double> minMax( DBL_MAX, -DBL_MAX );

          dbColumn *column = db_get_table_column( databaseTable, i );

          int ctype = db_sqltype_to_Ctype( db_get_column_sqltype( column ) );
          QVariant::Type qtype = QVariant::String; //default to string
          QgsDebugMsg( QString( "column = %1 ctype = %2" ).arg( db_get_column_name( column ) ).arg( ctype ) );

          QString ctypeStr;
          switch ( ctype )
          {
            case DB_C_TYPE_INT:
              ctypeStr = QStringLiteral( "integer" );
              qtype = QVariant::Int;
              break;
            case DB_C_TYPE_DOUBLE:
              ctypeStr = QStringLiteral( "double" );
              qtype = QVariant::Double;
              break;
            case DB_C_TYPE_STRING:
              ctypeStr = QStringLiteral( "string" );
              qtype = QVariant::String;
              break;
            case DB_C_TYPE_DATETIME:
              ctypeStr = QStringLiteral( "datetime" );
              qtype = QVariant::String;
              break;
          }
          mTableFields.append( QgsField( db_get_column_name( column ), qtype, ctypeStr,
                                         db_get_column_length( column ), db_get_column_precision( column ) ) );
          mMinMax << minMax;
          if ( G_strcasecmp( db_get_column_name( column ), mFieldInfo->key ) == 0 )
          {
            mKeyColumn = i;
          }
        }

        if ( mKeyColumn < 0 )
        {
          mTableFields.clear();
          QgsGrass::warning( QObject::tr( "Key column '%1' not found in the table '%2'" ).arg( mFieldInfo->key, mFieldInfo->table ) );
        }
        else
        {
          mHasTable = true;
          // Read attributes to the memory
          for ( ;; )
          {
            int more;

            if ( db_fetch( &databaseCursor, DB_NEXT, &more ) != DB_OK )
            {
              QgsDebugMsg( "Cannot fetch DB record" );
              break;
            }
            if ( !more )
            {
              break; // no more records
            }

            // Check cat value
            dbColumn *column = db_get_table_column( databaseTable, mKeyColumn );
            dbValue *value = db_get_column_value( column );

            if ( db_test_value_isnull( value ) )
            {
              continue;
            }
            int cat = db_get_value_int( value );
            if ( cat < 0 )
            {
              continue;
            }

            QList<QVariant> values;
            for ( int i = 0; i < nColumns; i++ )
            {
              column = db_get_table_column( databaseTable, i );
              int sqltype = db_get_column_sqltype( column );
              int ctype = db_sqltype_to_Ctype( sqltype );
              value = db_get_column_value( column );
              db_convert_value_to_string( value, sqltype, &dbstr );

              QgsDebugMsgLevel( QString( "column = %1 value = %2" ).arg( db_get_column_name( column ), db_get_string( &dbstr ) ), 3 );

              QVariant variant;
              if ( !db_test_value_isnull( value ) )
              {
                int iv;
                double dv;
                //layer.mAttributes[layer.nAttributes].values[i] = strdup( db_get_string( &dbstr ) );
                switch ( ctype )
                {
                  case DB_C_TYPE_INT:
                    iv = db_get_value_int( value );
                    variant = QVariant( iv );
                    mMinMax[i].first = std::min( mMinMax[i].first, ( double )iv );
                    mMinMax[i].second = std::min( mMinMax[i].second, ( double )iv );
                    break;
                  case DB_C_TYPE_DOUBLE:
                    dv = db_get_value_double( value );
                    variant = QVariant( dv );
                    mMinMax[i].first = std::min( mMinMax[i].first, dv );
                    mMinMax[i].second = std::min( mMinMax[i].second, dv );
                    break;
                  case DB_C_TYPE_STRING:
                    // Store as byte array so that codec may be used later
                    variant = QVariant( QByteArray( db_get_value_string( value ) ) );
                    break;
                  case DB_C_TYPE_DATETIME:
                    variant = QVariant( QByteArray( db_get_string( &dbstr ) ) );
                    break;
                  default:
                    variant = QVariant( QByteArray( db_get_string( &dbstr ) ) );
                }
              }
              QgsDebugMsgLevel( QString( "column = %1 variant = %2" ).arg( db_get_column_name( column ), variant.toString() ), 3 );
              values << variant;
            }
            mAttributes.insert( cat, values );
          }
        }
        mValid = true;
        db_close_cursor( &databaseCursor );
        db_close_database_shutdown_driver( databaseDriver );
        db_free_string( &dbstr );

        QgsDebugMsg( QString( "mTableFields.size = %1" ).arg( mTableFields.size() ) );
        QgsDebugMsg( QString( "number of attributes = %1" ).arg( mAttributes.size() ) );
      }
      QgsGrass::unlock();
    }
  }

  // Add cat if no attribute fields exist (otherwise qgis crashes)
  if ( mTableFields.size() == 0 )
  {
    mKeyColumn = 0;
    mTableFields.append( QgsField( QStringLiteral( "cat" ), QVariant::Int, QStringLiteral( "integer" ) ) );
    QPair<double, double> minMax( 0, 0 );

    if ( cidxFieldIndex() >= 0 )
    {
      int ncats, cat, type, id;

      ncats = Vect_cidx_get_num_cats_by_index( mMap->map(), cidxFieldIndex() );

      if ( ncats > 0 )
      {
        Vect_cidx_get_cat_by_index( mMap->map(), cidxFieldIndex(), 0, &cat, &type, &id );
        minMax.first = cat;

        Vect_cidx_get_cat_by_index( mMap->map(), cidxFieldIndex(), ncats - 1, &cat, &type, &id );
        minMax.second = cat;
      }
    }
    mMinMax << minMax;
  }
  mFields = mTableFields;
  mAttributeFields = mTableFields;

  QgsDebugMsg( QString( "layer loaded mTableFields.size() = %1 mAttributes.size() = %2" ).arg( mTableFields.size() ).arg( mAttributes.size() ) );
  mValid = true;
}
Exemple #4
0
/*!
  \brief Select pairs key/value to array, values are sorted by key (must be integer)

  \param driver DB driver
  \param tab table name
  \param key key column name
  \param col value column name
  \param[out] cvarr dbCatValArray to store within

  \return number of selected values
  \return -1 on error
 */
int db_select_CatValArray(dbDriver * driver, const char *tab, const char *key,
			  const char *col, const char *where,
			  dbCatValArray * cvarr)
{
    int i, type, more, nrows;
    char buf[1024];
    dbString stmt;
    dbCursor cursor;
    dbColumn *column;
    dbValue *value;
    dbTable *table;

    G_debug(3, "db_select_CatValArray ()");

    if (key == NULL || strlen(key) == 0) {
	G_warning(_("Missing key column name"));
	return -1;
    }

    if (col == NULL || strlen(col) == 0) {
	G_warning(_("Missing column name"));
	return -1;
    }
    db_init_string(&stmt);

    sprintf(buf, "SELECT %s, %s FROM %s", key, col, tab);
    db_set_string(&stmt, buf);

    if (where != NULL && strlen(where) > 0) {
	db_append_string(&stmt, " WHERE ");
	db_append_string(&stmt, where);
    }

    G_debug(3, "  SQL: %s", db_get_string(&stmt));

    if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK)
	return (-1);

    nrows = db_get_num_rows(&cursor);
    G_debug(3, "  %d rows selected", nrows);
    if (nrows < 0) {
	G_warning(_("Unable select records from table <%s>"), tab);
	db_close_cursor(&cursor);
	db_free_string(&stmt);
	return -1;
    }

    db_CatValArray_alloc(cvarr, nrows);

    table = db_get_cursor_table(&cursor);

    /* Check if key column is integer */
    column = db_get_table_column(table, 0);
    type = db_sqltype_to_Ctype(db_get_column_sqltype(column));
    G_debug(3, "  key type = %d", type);

    if (type != DB_C_TYPE_INT) {
	G_warning(_("Key column type is not integer"));
	db_close_cursor(&cursor);
	db_free_string(&stmt);
	return -1;
    }

    column = db_get_table_column(table, 1);
    type = db_sqltype_to_Ctype(db_get_column_sqltype(column));
    G_debug(3, "  col type = %d", type);

    /*
       if ( type != DB_C_TYPE_INT && type != DB_C_TYPE_DOUBLE ) {
       G_fatal_error ( "Column type not supported by db_select_to_array()" );
       }
     */

    cvarr->ctype = type;

    /* fetch the data */
    for (i = 0; i < nrows; i++) {
	if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
	    return (-1);

	column = db_get_table_column(table, 0);	/* first column */
	value = db_get_column_value(column);
	cvarr->value[i].cat = db_get_value_int(value);

	column = db_get_table_column(table, 1);
	value = db_get_column_value(column);
	cvarr->value[i].isNull = value->isNull;
	switch (type) {
	case (DB_C_TYPE_INT):
	    if (value->isNull)
		cvarr->value[i].val.i = 0;
	    else
		cvarr->value[i].val.i = db_get_value_int(value);
	    break;

	case (DB_C_TYPE_DOUBLE):
	    if (value->isNull)
		cvarr->value[i].val.d = 0.0;
	    else
		cvarr->value[i].val.d = db_get_value_double(value);
	    break;

	case (DB_C_TYPE_STRING):
	    cvarr->value[i].val.s = (dbString *) malloc(sizeof(dbString));
	    db_init_string(cvarr->value[i].val.s);

	    if (!(value->isNull))
		db_set_string(cvarr->value[i].val.s,
			      db_get_value_string(value));
	    break;

	case (DB_C_TYPE_DATETIME):
	    cvarr->value[i].val.t =
		(dbDateTime *) calloc(1, sizeof(dbDateTime));

	    if (!(value->isNull))
		memcpy(cvarr->value[i].val.t, &(value->t),
		       sizeof(dbDateTime));
	    break;

	default:
	    return (-1);
	}
    }
    cvarr->n_values = nrows;

    db_close_cursor(&cursor);
    db_free_string(&stmt);

    db_CatValArray_sort(cvarr);

    return (nrows);
}
Exemple #5
0
/*!
  \brief Select array of ordered integers from table/column

  \param driver DB driver
  \param tab table name
  \param col column name
  \param where where statement
  \param[out] pval array of ordered integer values

  \return number of selected values
  \return -1 on error
*/
int db_select_int(dbDriver * driver, const char *tab, const char *col,
		  const char *where, int **pval)
{
    int type, more, alloc, count;
    int *val;
    char buf[1024];
    const char *sval;
    dbString stmt;
    dbCursor cursor;
    dbColumn *column;
    dbValue *value;
    dbTable *table;

    G_debug(3, "db_select_int()");

    if (col == NULL || strlen(col) == 0) {
	G_warning(_("Missing column name"));
	return -1;
    }

    /* allocate */
    alloc = 1000;
    val = (int *)G_malloc(alloc * sizeof(int));

    if (where == NULL || strlen(where) == 0)
	G_snprintf(buf, 1023, "SELECT %s FROM %s", col, tab);
    else
	G_snprintf(buf, 1023, "SELECT %s FROM %s WHERE %s", col, tab, where);

    G_debug(3, "  SQL: %s", buf);

    db_init_string(&stmt);
    db_append_string(&stmt, buf);

    if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK)
	return (-1);

    table = db_get_cursor_table(&cursor);
    column = db_get_table_column(table, 0);	/* first column */
    if (column == NULL) {
	return -1;
    }
    value = db_get_column_value(column);
    type = db_get_column_sqltype(column);
    type = db_sqltype_to_Ctype(type);

    /* fetch the data */
    count = 0;
    while (1) {
	if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
	    return (-1);

	if (!more)
	    break;

	if (count == alloc) {
	    alloc += 1000;
	    val = (int *)G_realloc(val, alloc * sizeof(int));
	}

	switch (type) {
	case (DB_C_TYPE_INT):
	    val[count] = db_get_value_int(value);
	    break;
	case (DB_C_TYPE_STRING):
	    sval = db_get_value_string(value);
	    val[count] = atoi(sval);
	    break;
	case (DB_C_TYPE_DOUBLE):
	    val[count] = (int)db_get_value_double(value);
	    break;
	default:
	    return (-1);
	}
	count++;
    }

    db_close_cursor(&cursor);
    db_free_string(&stmt);

    qsort((void *)val, count, sizeof(int), cmp);

    *pval = val;

    return (count);
}
Exemple #6
0
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, sqltype, ctype, ogrtype, more;
    const char *fidcol, *colname;
    dbTable *table;
    dbString dbstring;
    dbColumn *column;
    dbCursor cursor;
    dbValue *value;

    OGRFieldDefnH hFieldDefn;

    G_debug(3, "write_attributes(): cat = %d", cat);

    if (cat < 0) {
        G_warning(_("Feature without category of layer %d"), Fi->number);
        return 0;
    }

    db_init_string(&dbstring);

    /* read & set attributes */
    sprintf(buf, "SELECT * FROM %s WHERE %s = %d", Fi->table, Fi->key,
            cat);
    G_debug(4, "SQL: %s", buf);
    db_set_string(&dbstring, buf);

    /* 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);
    }

    if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
        G_fatal_error(_("Unable to fetch data from table <%s>"),
                      Fi->table);
    }

    if (!more) {
        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);
    for (j = 0; j < ncol; j++) {
        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);
        /* for debug only */
        db_convert_column_value_to_string(column, &dbstring);
        G_debug(2, "col %d : val = %s", j,
                db_get_string(&dbstring));

        sqltype = db_get_column_sqltype(column);
        ctype = db_sqltype_to_Ctype(sqltype);
        ogrtype = sqltype_to_ogrtype(sqltype);
        G_debug(2, "  colctype = %d", ctype);

        ogrfieldnum = OGR_F_GetFieldIndex(Ogr_feature, colname);
        if (ogrfieldnum < 0) {
            /* create field if not exists */
            hFieldDefn = OGR_Fld_Create(colname, ogrtype);
            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)) {
            switch (ctype) {
            case DB_C_TYPE_INT:
                OGR_F_SetFieldInteger(Ogr_feature, ogrfieldnum,
                                      db_get_value_int(value));
                break;
            case DB_C_TYPE_DOUBLE:
                OGR_F_SetFieldDouble(Ogr_feature, ogrfieldnum,
                                     db_get_value_double(value));
                break;
            case DB_C_TYPE_STRING:
                OGR_F_SetFieldString(Ogr_feature, ogrfieldnum,
                                     db_get_value_string(value));
                break;
            case DB_C_TYPE_DATETIME:
                db_convert_column_value_to_string(column,
                                                  &dbstring);
                OGR_F_SetFieldString(Ogr_feature, ogrfieldnum,
                                     db_get_string(&dbstring));
                break;
            }
        }
    }

    db_close_cursor (&cursor);

    db_free_string(&dbstring);

    return 1;
}
Exemple #7
0
int query(struct Map_info *Map)
{
    int i, j, idx, cat_no, nlines, type;
    register int line_num;
    struct line_pnts *Points;
    struct line_cats *Cats;
    struct field_info *Fi;
    dbString stmt, value_string;
    dbDriver *driver;

    /* Initialize the Point struct */
    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();

    G_message(_("Reading features..."));

    /* Cycle through all lines and make a list of categories of 'qfield' for each category given by 'field' */
    nlines = Vect_get_num_lines(Map);
    for (line_num = 1; line_num <= nlines; line_num++) {
	type = Vect_read_line(Map, Points, Cats, line_num);
	if (!(type & options.type))
	    continue;

	for (i = 0; i < Cats->n_cats; i++) {
	    if (Cats->field[i] == options.field) {

		cat_no = Cats->cat[i];

		idx = find_cat(cat_no, 1);

		for (j = 0; j < Cats->n_cats; j++) {
		    if (Cats->field[j] == options.qfield) {	/* Add to list */
			if (Values[idx].nqcats == Values[idx].aqcats) {	/* Alloc space */
			    Values[idx].aqcats += 2;
			    Values[idx].qcat =
				(int *)G_realloc(Values[idx].qcat,
						 Values[idx].aqcats *
						 sizeof(int));
			}
			Values[idx].qcat[Values[idx].nqcats] = Cats->cat[j];
			Values[idx].nqcats++;
		    }
		}
	    }
	}

	/* If there is no field cat add cat -1, values for cat -1 are reported at the end  */
	Vect_cat_get(Cats, options.field, &cat_no);

	if (cat_no == -1) {
	    idx = find_cat(cat_no, 1);

	    for (j = 0; j < Cats->n_cats; j++) {
		if (Cats->field[j] == options.qfield) {	/* Add to list */
		    if (Values[idx].nqcats == Values[idx].aqcats) {	/* Alloc space */
			Values[idx].aqcats += 2;
			Values[idx].qcat =
			    (int *)G_realloc(Values[idx].qcat,
					     Values[idx].aqcats *
					     sizeof(int));
		    }
		    Values[idx].qcat[Values[idx].nqcats] = Cats->cat[j];
		    Values[idx].nqcats++;
		}
	    }
	}

	G_percent(line_num, nlines, 2);
    }

    db_init_string(&stmt);
    db_init_string(&value_string);

    if ((Fi = Vect_get_field(Map, options.qfield)) == NULL)
	G_fatal_error(_("Database connection not defined for layer %d. Use v.db.connect first."),
		      options.qfield);

    /* Open driver */
    driver = db_start_driver_open_database(Fi->driver, Fi->database);
    if (driver == NULL)
	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
		      Fi->database, Fi->driver);

    /* Query the database for each category */
    G_message(_("Querying database... "));
    for (i = 0; i < vstat.rcat; i++) {
	int j, ctype, nrows, more;
	char buf[2000];
	dbCursor cursor;
	dbTable *table;
	dbColumn *column;
	dbValue *value;

	G_debug(3, "cat %d", Values[i].cat);
	G_percent(i + 1, vstat.rcat, 1);

	/* Skip if cat is zero and large number of query categories (many features without category).
	 * It would cause problems on server side and take long time. Postgres limit is 10000 */
	/* TODO: verify because no category is encoded as cat = -1, not cat = zero */
	if (Values[i].cat == 0 && Values[i].nqcats > 1000) {
	    G_warning(_("Query for category '0' (no category) was not executed because of too many "
		       "(%d) query categories. All later reported values for cat 0 are not valid."),
		      Values[i].nqcats);
	    continue;
	}

	if (Values[i].nqcats > 0) {
	    sprintf(buf, "SELECT %s FROM %s WHERE", options.qcol, Fi->table);
	    db_set_string(&stmt, buf);

	    for (j = 0; j < Values[i].nqcats; j++) {
		G_debug(4, "  qcat %d", Values[i].qcat[j]);

		if (j > 0)
		    db_append_string(&stmt, " OR");

		sprintf(buf, " %s = %d", Fi->key, Values[i].qcat[j]);
		db_append_string(&stmt, buf);
	    }
	    G_debug(4, "  SQL: '%s'", db_get_string(&stmt));

	    if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL)
		!= DB_OK)
		G_fatal_error("Cannot open cursor: '%s'",
			      db_get_string(&stmt));

	    table = db_get_cursor_table(&cursor);
	    column = db_get_table_column(table, 0);	/* first column */
	    value = db_get_column_value(column);
	    ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
	    vstat.qtype = ctype;
	    nrows = db_get_num_rows(&cursor);

	    G_debug(4, "  nrows = %d, columnt type = %d", nrows, ctype);

	    if (nrows != 1) {
		if (nrows > 1) {
		    G_warning(_("Multiple query results, output value set to NULL (category [%d])"),
			      Values[i].cat);
		}
		Values[i].null = 1;
	    }
	    else {
		if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
		    G_fatal_error(_("Unable to fetch record"));

		db_convert_column_value_to_string(column, &stmt);
		G_debug(4, "  value = %s", db_get_string(&stmt));

		if (db_test_value_isnull(value)) {
		    Values[i].null = 1;
		}
		else {
		    switch (ctype) {
		    case (DB_C_TYPE_INT):
			Values[i].i1 = db_get_value_int(value);
			break;
		    case (DB_C_TYPE_DOUBLE):
			Values[i].d1 = db_get_value_double(value);
			break;
		    case (DB_C_TYPE_STRING):
			Values[i].str1 = G_store(db_get_value_string(value));
			break;
		    case (DB_C_TYPE_DATETIME):
			db_convert_column_value_to_string(column,
							  &value_string);
			Values[i].str1 =
			    G_store(db_get_string(&value_string));
		    }
		    Values[i].null = 0;
		}
	    }
	    db_close_cursor(&cursor);
	}
	else {			/* no qcats -> upload NULL */
	    Values[i].null = 1;
	}
    }

    db_close_database_shutdown_driver(driver);

    return 0;
}
Exemple #8
0
/*!
  \brief Load styles for geolines based on thematic mapping

  \param gv pointer to geovect structure
  \param colors pointer to Colors structure or NULL

  \return number of features defined by thematic mapping
  \return -1 on error
*/
int Gv_load_vect_thematic(geovect *gv, struct Colors *colors)
{
    geoline *gvt;

    struct Map_info Map;
    struct field_info *Fi;
    
    int nvals, cat, nlines, nskipped;
    int red, blu, grn;
    const char *str;
    const char *mapset;

    dbDriver *driver;
    dbValue value;
    
    if(!gv || !gv->tstyle || !gv->filename)
	return -1;

    mapset = G_find_vector2(gv->filename, "");
    if (!mapset) {
	G_fatal_error(_("Vector map <%s> not found"), gv->filename);
    }
    
    Vect_set_open_level(1);
    if (Vect_open_old(&Map, gv->filename, "") == -1) {
	G_fatal_error(_("Unable to open vector map <%s>"),
		      G_fully_qualified_name(gv->filename, mapset));
    }
    
    Fi = Vect_get_field(&Map, gv->tstyle->layer);
    if (!Fi) {
	G_warning(_("Database connection not defined for layer %d"),
		  gv->tstyle->layer);
    }
    else {
      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);
    }
    G_message(_("Loading thematic vector layer <%s>..."),
	      G_fully_qualified_name(gv->filename, mapset));
    nlines = nskipped = 0;
    for(gvt = gv->lines; gvt; gvt = gvt->next) {
	gvt->style = (gvstyle *) G_malloc(sizeof(gvstyle));
	G_zero(gvt->style, sizeof(gvstyle));
	
	/* use default style */
	gvt->style->color  = gv->style->color;
	gvt->style->symbol = gv->style->symbol;
	gvt->style->size   = gv->style->size;
	gvt->style->width  = gv->style->width;

	cat = -1;
	if (gvt->cats)
	    Vect_cat_get(gvt->cats, gv->tstyle->layer, &cat);
	if (cat < 0) {
	    nskipped++;
	    continue;
	}
	
	/* color */
	if (colors) {
	    if (!Rast_get_c_color((const CELL *) &cat, &red, &grn, &blu, colors)) {
		G_warning(_("No color rule defined for category %d"), cat);
		gvt->style->color = gv->style->color;
	    }
	    gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
		((int)((blu) << 16) & BLU_MASK);
	}
	
	if (gv->tstyle->color_column) {
	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->color_column, &value);
	    if (nvals < 1)
		continue;
	    str = db_get_value_string(&value);
	    if (!str)
		continue;
	    if (G_str_to_color(str, &red, &grn, &blu) != 1) {
		G_warning(_("Invalid color definition (%s)"),
			  str);
		gvt->style->color = gv->style->color;
	    }
	    else {
		gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
		    ((int)((blu) << 16) & BLU_MASK);
	    }
	}
	
	/* width */
	if (gv->tstyle->width_column) {
	    nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->width_column, &value);
	    if (nvals < 1)
		continue;
	    gvt->style->width = db_get_value_int(&value);
	}

	nlines++;
    }

    if (nskipped > 0)
	G_warning(_("%d features without category. "
		    "Unable to determine color rules for features without category."),
		  nskipped);
    
    return nlines;
}
Exemple #9
0
struct Map_info *G_sites_open_old(const char *name, const char *mapset)
{
    struct Map_info *Map;
    struct field_info *fi;
    int more, nrows, row, ncols, col, ndbl, nstr, adbl, astr, ctype;
    SITE_ATT *sa;

    dbDriver *driver;
    dbString stmt;
    dbCursor cursor;
    dbTable *table;
    dbColumn *column;
    dbValue *value;

    G_message(
	_("Dev note: Adapted sites library used for vector points. "
	  "(module should be updated to GRASS 6 vector library)"));

    Map = (struct Map_info *)G_malloc(sizeof(struct Map_info));

    Vect_set_open_level(1);
    Vect_open_old(Map, name, mapset);

    G_debug(1, "Vector map opened");

    /* Load attributes */
    Map->site_att = NULL;
    Map->n_site_att = 0;
    Map->n_site_dbl = 0;
    Map->n_site_str = 0;

    fi = Vect_get_field(Map, 1);
    if (fi == NULL) {		/* not attribute table */
	G_debug(1, "No attribute table");
	return Map;
    }

    driver = db_start_driver_open_database(fi->driver, fi->database);
    if (driver == NULL)
	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
		      fi->database,
		      fi->driver);

    db_init_string(&stmt);
    db_set_string(&stmt, "select * from ");
    db_append_string(&stmt, fi->table);

    if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK)
	G_fatal_error(_("Unable to open select cursor: '%s'"),
		      db_get_string(&stmt));

    nrows = db_get_num_rows(&cursor);
    G_debug(1, "%d rows selected from vector attribute table", nrows);

    Map->site_att = (SITE_ATT *) malloc(nrows * sizeof(SITE_ATT));
    Map->n_site_att = nrows;

    table = db_get_cursor_table(&cursor);
    ncols = db_get_table_number_of_columns(table);

    row = 0;
    adbl = astr = 0;
    while (1) {
	if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
	    G_fatal_error(_("Cannot fetch row"));

	if (!more)
	    break;

	/* Get number of each type */
	if (row == 0) {
	    for (col = 0; col < ncols; col++) {
		column = db_get_table_column(table, col);
		ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));

		if (strcmp(db_get_column_name(column), fi->key) == 0)
		    continue;

		switch (ctype) {
		case DB_C_TYPE_INT:
		case DB_C_TYPE_DOUBLE:
		    adbl++;
		    break;
		case DB_C_TYPE_STRING:
		case DB_C_TYPE_DATETIME:
		    astr++;
		    break;
		}
	    }
	    Map->n_site_dbl = adbl;
	    Map->n_site_str = astr;
	    G_debug(1, "adbl = %d astr = %d", adbl, astr);
	}

	sa = &(Map->site_att[row]);
	sa->dbl = (double *)malloc(adbl * sizeof(double));
	sa->str = (char **)malloc(astr * sizeof(char *));

	ndbl = nstr = 0;
	for (col = 0; col < ncols; col++) {
	    column = db_get_table_column(table, col);
	    ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
	    value = db_get_column_value(column);

	    if (strcmp(db_get_column_name(column), fi->key) == 0) {
		sa->cat = db_get_value_int(value);
	    }
	    else {
		switch (ctype) {
		case DB_C_TYPE_INT:
		    sa->dbl[ndbl] = db_get_value_int(value);
		    ndbl++;
		    break;
		case DB_C_TYPE_DOUBLE:
		    sa->dbl[ndbl] = db_get_value_double(value);
		    ndbl++;
		    break;
		case DB_C_TYPE_STRING:
		    sa->str[nstr] = G_store(db_get_value_string(value));
		    nstr++;
		    break;
		case DB_C_TYPE_DATETIME:
		    sa->str[nstr] = "";	/* TODO */
		    nstr++;
		    break;
		}
	    }
	}
	row++;
    }
    db_close_database_shutdown_driver(driver);

    /* sort attributes */
    qsort((void *)Map->site_att, Map->n_site_att, sizeof(SITE_ATT),
	  site_att_cmp);

    return Map;
}
Exemple #10
0
/*!
  \brief Write data to GRASS ASCII vector format

  Prints message if some features without category are skipped.

  \param[out] ascii  pointer to the output ASCII file
  \param[out] att    att file (< version 5 only)
  \param Map    pointer to Map_info structure
  \param ver    version number 4 or 5
  \param format format GV_ASCII_FORMAT_POINT or GV_ASCII_FORMAT_STD
  \param dp     number of significant digits
  \param fs     field separator
  \param region_flag check region
  \param type   feature type filter
  \param field  field number
  \param Clist  list of categories to filter features or NULL
  \param where  SQL select where statement to filter features or NULL
  \param column_names array of columns to be included to the output or NULL
                 "*" as the first item in the array indicates all columns
  \param header TRUE to print also header

  \return number of written features
  \return -1 on error
*/
int Vect_write_ascii(FILE *ascii,
		     FILE *att, struct Map_info *Map, int ver,
		     int format, int dp, char *fs, int region_flag, int type,
		     int field, const struct cat_list *Clist, const char* where,
		     const char **column_names, int header)
{
    int ltype, ctype, i, cat, line, left, right, found;
    double *xptr, *yptr, *zptr, x, y;
    static struct line_pnts *Points;
    struct line_cats *Cats, *ACats;
    char *xstring, *ystring, *zstring;
    size_t xsize, ysize, zsize;
    struct Cell_head window;
    struct ilist *fcats;
    int count, n_skipped;

    /* where || columns */
    struct field_info *Fi;
    dbDriver *driver;
    dbValue value;
    dbHandle handle;
    int *cats, ncats, more;
    dbTable *Table;
    dbString dbstring;
    dbColumn *Column;
    dbValue *Value;
    char *buf;
    size_t bufsize;
    dbCursor cursor;
    /* columns */
    char **columns;
    int *coltypes;
    char *all_columns;
    
    Fi = NULL;
    driver = NULL;
    columns = NULL;
    coltypes = NULL;
    all_columns = NULL;
    
    G_zero(&value, sizeof(dbValue));
    db_init_string(&dbstring);

    xstring = NULL;
    ystring = NULL;
    zstring = NULL;
    xsize = 0;
    ysize = 0;
    zsize = 0;
    buf = NULL;
    bufsize = 0;

    /* get the region */
    G_get_window(&window);

    count = ncats = 0;
    xstring = ystring = zstring = NULL;
    cats = NULL;
    
    if (field > 0 && (where || column_names)) {
	Fi = Vect_get_field(Map, field);
	if (!Fi) {
	    G_fatal_error(_("Database connection not defined for layer %d"),
			  field);
	}

	driver = db_start_driver(Fi->driver);
	if (!driver)
	    G_fatal_error(_("Unable to start driver <%s>"), Fi->driver);
	
	db_init_handle(&handle);
	db_set_handle(&handle, Fi->database, NULL);
	
	if (db_open_database(driver, &handle) != DB_OK)
	    G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
			  Fi->database, Fi->driver);
	
	/* select cats (sorted array) */
	ncats = db_select_int(driver, Fi->table, Fi->key, where, &cats);
	G_debug(3, "%d categories selected from table <%s>", ncats, Fi->table);

	if (!column_names) {
	    db_close_database(driver);
	    db_shutdown_driver(driver);
	}
	else {
	    int icol, ncols;
	    const char *col_name;
            int len_all = 0;
            
	    db_set_string(&dbstring, Fi->table);
	    if (db_describe_table(driver, &dbstring, &Table) != DB_OK) {
		G_warning(_("Unable to describe table <%s>"), Fi->table);
		return -1;
	    }
	    
	    ncols = db_get_table_number_of_columns(Table);
	    columns = (char **) G_malloc((ncols + 1) * sizeof(char *));

            if (column_names[0] && strcmp(column_names[0], "*") == 0) {
                
                /* all columns */
                icol = 0;
                for (i = 0; i < ncols; i++) {
                    col_name = db_get_column_name(db_get_table_column(Table, i));
		    /* key column skipped */
                    if (strcmp(Fi->key, col_name) != 0)
			columns[icol++] = G_store(col_name);
                }
                columns[icol] = NULL;
            }
            else {
		int j;

		icol = 0;
		i = 0;
		while (column_names[i]) {
		    /* key column skipped */
                    if (strcmp(Fi->key, column_names[i]) != 0) {
			found = 0;
			for (j = 0; j < ncols; j++) {
			    col_name = db_get_column_name(db_get_table_column(Table, j));
			    if (strcmp(col_name, column_names[i]) == 0) {
				columns[icol++] = G_store(col_name);
				found = 1;
				break;
			    }
			}
			if (!found) {
			    G_warning(_("Column <%s> does not exist"),
				      column_names[i]);
			    G_important_message(_("Available columns:"));
			    for (j = 0; j < ncols; j++) {
				col_name = db_get_column_name(db_get_table_column(Table, j));
				G_important_message("%s", col_name);
			    }
			    G_warning(_("Export cancelled"));
			    db_close_database(driver);
			    db_shutdown_driver(driver);
			    return -1;
			}
		    }
		    i++;
                }
                columns[icol] = NULL;
            }

	    db_zero_string(&dbstring);
	    db_free_table(Table);
	    Table = NULL;
            
	    if (columns[0]) {
		/* selected columns only */
		i = 0;
		while (columns[i])
		    len_all += strlen(columns[i++]);
		
		coltypes = G_malloc(i * sizeof(int));
		
		all_columns = G_malloc(len_all + i + 2);

		i = 0;
		strcpy(all_columns, columns[0]);
		while (columns[i]) {
		    /* get column types */
		    coltypes[i] = db_column_Ctype(driver, Fi->table, columns[i]);
		    if (coltypes[i] < 0) {
			db_close_database(driver);
			db_shutdown_driver(driver);
			G_warning(_("Unknown type of column <%s>, export cancelled"),
				  columns[i]);
			return -1;
		    }
		    if (i > 0) {
			strcat(all_columns, ",");
			strcat(all_columns, columns[i]);
		    }
		    i++;
		}
	    }
	    else {
		/* no column or only key column selected */
		G_free(columns);
		columns = NULL;

		db_close_database(driver);
		db_shutdown_driver(driver);
	    }
	}
    }

    if (format == GV_ASCII_FORMAT_POINT && header) {

	/* print header */
	if (Map->head.with_z)
	    fprintf(ascii, "east%snorth%sheight%scat", fs, fs, fs);
	else
	    fprintf(ascii, "east%snorth%scat", fs, fs);
	if (columns) {
	    for (i = 0; columns[i]; i++) {
		if (db_select_value
		    (driver, Fi->table, Fi->key, cat,
		     columns[i], &value) < 0)
		    G_fatal_error(_("Unable to select record from table <%s> (key %s, column %s)"),
				  Fi->table, Fi->key, columns[i]);
		if (columns[i])
		    fprintf(ascii, "%s%s", fs, columns[i]);
		else
		    fprintf(ascii, "%s", columns[i]); /* can not happen */
	    }
	}
	fprintf(ascii, "%s", HOST_NEWLINE);
    }

    Points = Vect_new_line_struct();
    Cats = Vect_new_cats_struct();
    ACats = Vect_new_cats_struct();
    fcats = Vect_new_list();

    /* by default, read_next_line will NOT read Dead lines */
    /* but we can override that (in Level I only) by specifying */
    /* the type  -1, which means match all line types */

    Vect_rewind(Map);

    count = n_skipped = line = 0;
    while (TRUE) {
	ltype = Vect_read_next_line(Map, Points, Cats);
	if (ltype == -1 ) {      /* failure */
	    if (columns) {
		db_close_database(driver);
		db_shutdown_driver(driver);

                free_col_arrays(coltypes, all_columns,
                                column_names && strcmp(column_names[0], "*") == 0 ? columns : NULL);
	    }
	    
	    return -1;
	}

	if (ltype == -2)	{	/* EOF */
	    if (columns) {
		db_close_database(driver);
		db_shutdown_driver(driver);
                
                free_col_arrays(coltypes, all_columns,
                                column_names && strcmp(column_names[0], "*") == 0 ? columns : NULL);
	    }
	    break;
	}

	line++;

	if (!(ltype & type))
	    continue;

	if (format == GV_ASCII_FORMAT_POINT && !(ltype & GV_POINTS))
	    continue;

	found = get_cat(Cats, Clist, cats, ncats, field, &cat);

	if (!found && field > 0 && ltype == GV_BOUNDARY &&
	    type & GV_AREA && Vect_level(Map) > 1) {
	    Vect_get_line_areas(Map, line, &left, &right);
	    if (left < 0)
		left = Vect_get_isle_area(Map, abs(left));
	    if (left > 0) {
		Vect_get_area_cats(Map, left, ACats);
		found = get_cat(ACats, Clist, cats, ncats, field, &cat);
	    }
	    if (right < 0)
		right = Vect_get_isle_area(Map, abs(right));
	    if (!found && right > 0) {
		Vect_get_area_cats(Map, right, ACats);
		found = get_cat(ACats, Clist, cats, ncats, field, &cat);
	    }
	}
	
	if (!found) {
            if (Cats->n_cats < 1)
                n_skipped++;
            
	    continue;
	}

	if (ver < 5) {
	    Vect_cat_get(Cats, 1, &cat);
	}

	switch (ltype) {
	case GV_BOUNDARY:
	    if (ver == 5)
		ctype = 'B';
	    else
		ctype = 'A';
	    break;
	case GV_CENTROID:
	    if (ver < 5) {
		if (att != NULL) {
		    if (cat > 0) {
			G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]);
			G_trim_decimal(xstring);
			G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]);
			G_trim_decimal(ystring);
			fprintf(att, "A %s %s %d%s", xstring, ystring, cat, HOST_NEWLINE);
		    }
		}
		continue;
	    }
	    ctype = 'C';
	    break;
	case GV_LINE:
	    ctype = 'L';
	    break;
	case GV_POINT:
	    ctype = 'P';
	    break;
	case GV_FACE:
	    ctype = 'F';
	    break;
	case GV_KERNEL:
	    ctype = 'K';
	    break;
	default:
	    ctype = 'X';
	    G_warning(_("Unknown feature type %d"), (int)ltype);
	    break;
	}

	if (format == GV_ASCII_FORMAT_POINT) {
	    if (region_flag) {
		if ((window.east < Points->x[0]) ||
		    (window.west > Points->x[0]))
		    continue;
	    }
	    G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]);
	    G_trim_decimal(xstring);

	    if (region_flag) {
		if ((window.north < Points->y[0]) ||
		    (window.south > Points->y[0]))
		    continue;
	    }
	    G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]);
	    G_trim_decimal(ystring);

	    Vect_field_cat_get(Cats, field, fcats);

	    if (Map->head.with_z && ver == 5) {
		if (region_flag) {
		    if ((window.top < Points->z[0]) ||
			(window.bottom > Points->z[0]))
			continue;
		}
		G_rasprintf(&zstring, &zsize, "%.*f", dp, Points->z[0]);
		G_trim_decimal(zstring);
		fprintf(ascii, "%s%s%s%s%s", xstring, fs, ystring, fs,
			zstring);
	    }
	    else {
		fprintf(ascii, "%s%s%s", xstring, fs, ystring);
	    }

	    if (fcats->n_values > 0 && cat > -1) {
		if (fcats->n_values > 1) {
		    G_warning(_("Feature has more categories. Only one category (%d) "
				"is exported."), cat);
		}
		fprintf(ascii, "%s%d", fs, cat);
		
		/* print attributes */
		if (columns) {

		    G_rasprintf(&buf, &bufsize, "SELECT %s FROM %s WHERE %s = %d",
			    all_columns, Fi->table, Fi->key, cat);
		    G_debug(2, "SQL: %s", buf);
		    db_set_string(&dbstring, buf);

		    if (db_open_select_cursor
				    (driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) {
			db_close_database(driver);
			db_shutdown_driver(driver);
			G_fatal_error(_("Cannot select attributes for cat = %d"),
			  cat);
		    }
		    if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
			db_close_database(driver);
			db_shutdown_driver(driver);
			G_fatal_error(_("Unable to fetch data from table"));
		    }

		    Table = db_get_cursor_table(&cursor);


		    for (i = 0; columns[i]; i++) {
			Column = db_get_table_column(Table, i);
			Value = db_get_column_value(Column);

			if (db_test_value_isnull(Value)) {
			    fprintf(ascii, "%s", fs);
			}
			else {
			    switch(coltypes[i])
			    {
			    case DB_C_TYPE_INT: {
				fprintf(ascii, "%s%d", fs, db_get_value_int(Value));
				break;
			    }
			    case DB_C_TYPE_DOUBLE: {
				fprintf(ascii, "%s%.*f", fs, dp, db_get_value_double(Value));
				break;
			    }
			    case DB_C_TYPE_STRING: {
				fprintf(ascii, "%s%s", fs, db_get_value_string(Value));
				break;
			    }
			    case DB_C_TYPE_DATETIME: {
				break;
			    }
			    case -1:
				G_fatal_error(_("Column <%s> not found in table <%s>"),
					      columns[i], Fi->table);
			    default: G_fatal_error(_("Column <%s>: unsupported data type"),
						   columns[i]);
			    }
			}
		    }
		    db_close_cursor(&cursor);
		}
	    }

	    fprintf(ascii, "%s", HOST_NEWLINE);
	}
	else if (format == GV_ASCII_FORMAT_STD) {
	    /* FORMAT_STANDARD */
	    if (ver == 5 && Cats->n_cats > 0)
		fprintf(ascii, "%c  %d %d%s", ctype, Points->n_points,
			Cats->n_cats, HOST_NEWLINE);
	    else
              fprintf(ascii, "%c  %d%s", ctype, Points->n_points, HOST_NEWLINE);

	    xptr = Points->x;
	    yptr = Points->y;
	    zptr = Points->z;

	    while (Points->n_points--) {

		G_rasprintf(&xstring, &xsize, "%.*f", dp, *xptr++);
		G_trim_decimal(xstring);
		G_rasprintf(&ystring, &ysize, "%.*f", dp, *yptr++);
		G_trim_decimal(ystring);

		if (ver == 5) {
		    if (Map->head.with_z) {
			G_rasprintf(&zstring, &zsize, "%.*f", dp, *zptr++);
			G_trim_decimal(zstring);
			fprintf(ascii, " %-12s %-12s %-12s%s", xstring,
				ystring, zstring, HOST_NEWLINE);
		    }
		    else {
                      fprintf(ascii, " %-12s %-12s%s", xstring, ystring, HOST_NEWLINE);
		    }
		}		/*Version 4 */
		else {
                    fprintf(ascii, " %-12s %-12s%s", ystring, xstring, HOST_NEWLINE);
		}
	    }

	    if (ver == 5) {
		for (i = 0; i < Cats->n_cats; i++) {
		    fprintf(ascii, " %-5d %-10d%s", Cats->field[i],
			    Cats->cat[i], HOST_NEWLINE);
		}
	    }
	    else {
		if (cat > -1) {
		    if (ltype == GV_POINT) {
			G_rasprintf(&xstring, &xsize, "%.*f", dp, Points->x[0]);
			G_trim_decimal(xstring);
			G_rasprintf(&ystring, &ysize, "%.*f", dp, Points->y[0]);
			G_trim_decimal(ystring);
			fprintf(att, "P %s %s %d%s", xstring, ystring, cat, HOST_NEWLINE);
		    }
		    else {
			x = (Points->x[1] + Points->x[0]) / 2;
			y = (Points->y[1] + Points->y[0]) / 2;

			G_rasprintf(&xstring, &xsize, "%.*f", dp, x);
			G_trim_decimal(xstring);
			G_rasprintf(&ystring, &ysize, "%.*f", dp, y);
			G_trim_decimal(ystring);
			fprintf(att, "L %s %s %d%s", xstring, ystring, cat, HOST_NEWLINE);
		    }
		}
	    }
	}
	else if (format == GV_ASCII_FORMAT_WKT) {
	    if (ltype & (GV_BOUNDARY | GV_CENTROID | GV_FACE | GV_KERNEL))
		continue;
	    /* Well-Known Text */
	    Vect_sfa_line_astext(Points, ltype, Vect_is_3d(Map), dp, ascii);
	    count++;
	}
	else {
	    G_fatal_error(_("Unknown format"));
	}
	count++;
    }

    if (format == GV_ASCII_FORMAT_WKT) {
	/* process areas - topology required */
	int i, area, nareas, isle, nisles;

	if (Vect_level(Map) < 2) {
	    G_warning(_("Topology not available, unable to process areas"));
	    nareas = 0;
	}
	else {
	    nareas = Vect_get_num_areas(Map);
	}
	for (area = 1; area <= nareas; area++) {
	    if (!Vect_area_alive(Map, area)) /* skip dead areas */
		continue;
	    if (Vect_get_area_cat(Map, area, field) < 0)
		continue;
	    /* get boundary -> linearring */
	    if (Vect_get_area_points(Map, area, Points) < 0) {
		G_warning(_("Unable to get boundary of area id %d"), area);
		continue;
	    }
	    fprintf(ascii, "POLYGON(");
	    /* write outter ring */
	    Vect_sfa_line_astext(Points, GV_BOUNDARY, 0, dp, ascii); /* boundary is always 2D */
	    /* get isles (holes) -> inner rings */
	    nisles = Vect_get_area_num_isles(Map, area);
	    for (i = 0; i < nisles; i++) {
		/* get isle boundary -> linearring */
		isle = Vect_get_area_isle(Map, area, i);
		if (Vect_get_isle_points(Map, isle, Points) < 0) {
		    G_warning(_("Unable to get boundary of isle id %d (area id %d)"), isle, area);
		    continue;
		}
		fprintf(ascii, ", ");
		/* write inner ring */
		Vect_sfa_line_astext(Points, GV_BOUNDARY, 0, dp, ascii); /* boundary is always 2D */
	    }
	    fprintf(ascii, ")%s", HOST_NEWLINE);
	    
	    count++;
	}
    }

    if (n_skipped > 0)
        G_important_message(_("%d features without category skipped. To export also "
                              "features without category use '%s=-1'."), n_skipped, "layer");
    
    Vect_destroy_line_struct(Points);
    Vect_destroy_cats_struct(Cats);
    Vect_destroy_cats_struct(ACats);
    
    return count;
}