bool OGRGRASSLayer::OpenSequentialCursor() { CPLDebug ( "GRASS", "OpenSequentialCursor: %s", pszQuery ); if ( !poDriver ) { CPLError( CE_Failure, CPLE_AppDefined, "Driver not opened."); return false; } if ( bCursorOpened ) { db_close_cursor ( poCursor ); bCursorOpened = false; } char buf[2000]; sprintf ( buf, "SELECT * FROM %s ", poLink->table ); db_set_string ( poDbString, buf); if ( pszQuery ) { sprintf ( buf, "WHERE %s ", pszQuery ); db_append_string ( poDbString, buf); } sprintf ( buf, "ORDER BY %s", poLink->key); db_append_string ( poDbString, buf); CPLDebug ( "GRASS", "Query: %s", db_get_string(poDbString) ); if ( db_open_select_cursor ( poDriver, poDbString, poCursor, DB_SCROLL) == DB_OK ) { iCurrentCat = -1; bCursorOpened = true; CPLDebug ( "GRASS", "num rows = %d", db_get_num_rows ( poCursor ) ); } else { CPLError( CE_Failure, CPLE_AppDefined, "Cannot open cursor."); return false; } return true; }
int main(int argc, char *argv[]) { int i, cat, with_z, more, ctype, nrows; char buf[DB_SQL_MAX]; int count; double coor[3]; int ncoor; struct Option *driver_opt, *database_opt, *table_opt; struct Option *xcol_opt, *ycol_opt, *zcol_opt, *keycol_opt, *where_opt, *outvect; struct Flag *same_table_flag; struct GModule *module; struct Map_info Map; struct line_pnts *Points; struct line_cats *Cats; dbString sql; dbDriver *driver; dbCursor cursor; dbTable *table; dbColumn *column; dbValue *value; struct field_info *fi; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("import")); G_add_keyword(_("database")); G_add_keyword(_("points")); module->description = _("Creates new vector (points) map from database table containing coordinates."); table_opt = G_define_standard_option(G_OPT_DB_TABLE); table_opt->required = YES; table_opt->description = _("Input table name"); driver_opt = G_define_standard_option(G_OPT_DB_DRIVER); driver_opt->options = db_list_drivers(); driver_opt->answer = (char *)db_get_default_driver_name(); driver_opt->guisection = _("Input DB"); database_opt = G_define_standard_option(G_OPT_DB_DATABASE); database_opt->answer = (char *)db_get_default_database_name(); database_opt->guisection = _("Input DB"); xcol_opt = G_define_standard_option(G_OPT_DB_COLUMN); xcol_opt->key = "x"; xcol_opt->required = YES; xcol_opt->description = _("Name of column containing x coordinate"); ycol_opt = G_define_standard_option(G_OPT_DB_COLUMN); ycol_opt->key = "y"; ycol_opt->required = YES; ycol_opt->description = _("Name of column containing y coordinate"); zcol_opt = G_define_standard_option(G_OPT_DB_COLUMN); zcol_opt->key = "z"; zcol_opt->description = _("Name of column containing z coordinate"); zcol_opt->guisection = _("3D output"); keycol_opt = G_define_standard_option(G_OPT_DB_COLUMN); keycol_opt->key = "key"; keycol_opt->required = NO; keycol_opt->label = _("Name of column containing category number"); keycol_opt->description = _("Must refer to an integer column"); where_opt = G_define_standard_option(G_OPT_DB_WHERE); where_opt->guisection = _("Selection"); outvect = G_define_standard_option(G_OPT_V_OUTPUT); same_table_flag = G_define_flag(); same_table_flag->key = 't'; same_table_flag->description = _("Use imported table as attribute table for new map"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); if (zcol_opt->answer) { with_z = WITH_Z; ncoor = 3; } else { with_z = WITHOUT_Z; ncoor = 2; } Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); db_init_string(&sql); if (G_get_overwrite()) { /* We don't want to delete the input table when overwriting the output * vector. */ char name[GNAME_MAX], mapset[GMAPSET_MAX]; if (!G_name_is_fully_qualified(outvect->answer, name, mapset)) { strcpy(name, outvect->answer); strcpy(mapset, G_mapset()); } Vect_set_open_level(1); /* no topo needed */ if (strcmp(mapset, G_mapset()) == 0 && G_find_vector2(name, mapset) && Vect_open_old(&Map, name, mapset) >= 0) { int num_dblinks; num_dblinks = Vect_get_num_dblinks(&Map); for (i = 0; i < num_dblinks; i++) { if ((fi = Vect_get_dblink(&Map, i)) != NULL && strcmp(fi->driver, driver_opt->answer) == 0 && strcmp(fi->database, database_opt->answer) == 0 && strcmp(fi->table, table_opt->answer) == 0) G_fatal_error(_("Vector map <%s> cannot be overwritten " "because input table <%s> is linked to " "this map."), outvect->answer, table_opt->answer); } Vect_close(&Map); } } if (Vect_open_new(&Map, outvect->answer, with_z) < 0) G_fatal_error(_("Unable to create vector map <%s>"), outvect->answer); Vect_set_error_handler_io(NULL, &Map); Vect_hist_command(&Map); fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE); /* Open driver */ driver = db_start_driver_open_database(driver_opt->answer, database_opt->answer); if (driver == NULL) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), fi->database, fi->driver); } db_set_error_handler_driver(driver); /* check if target table already exists */ G_debug(3, "Output vector table <%s>, driver: <%s>, database: <%s>", outvect->answer, db_get_default_driver_name(), db_get_default_database_name()); if (!same_table_flag->answer && db_table_exists(db_get_default_driver_name(), db_get_default_database_name(), outvect->answer) == 1) G_fatal_error(_("Output vector map, table <%s> (driver: <%s>, database: <%s>) " "already exists"), outvect->answer, db_get_default_driver_name(), db_get_default_database_name()); if (keycol_opt->answer) { int coltype; coltype = db_column_Ctype(driver, table_opt->answer, keycol_opt->answer); if (coltype == -1) G_fatal_error(_("Column <%s> not found in table <%s>"), keycol_opt->answer, table_opt->answer); if (coltype != DB_C_TYPE_INT) G_fatal_error(_("Data type of key column must be integer")); } else { if (same_table_flag->answer) { G_fatal_error(_("Option <%s> must be specified when -%c flag is given"), keycol_opt->key, same_table_flag->key); } if (strcmp(db_get_default_driver_name(), "sqlite") != 0) G_fatal_error(_("Unable to define key column. This operation is not supported " "by <%s> driver. You need to define <%s> option."), fi->driver, keycol_opt->key); } /* Open select cursor */ sprintf(buf, "SELECT %s, %s", xcol_opt->answer, ycol_opt->answer); db_set_string(&sql, buf); if (with_z) { sprintf(buf, ", %s", zcol_opt->answer); db_append_string(&sql, buf); } if (keycol_opt->answer) { sprintf(buf, ", %s", keycol_opt->answer); db_append_string(&sql, buf); } sprintf(buf, " FROM %s", table_opt->answer); db_append_string(&sql, buf); if (where_opt->answer) { sprintf(buf, " WHERE %s", where_opt->answer); db_append_string(&sql, buf); } G_debug(2, "SQL: %s", db_get_string(&sql)); if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) { G_fatal_error(_("Unable to open select cursor: '%s'"), db_get_string(&sql)); } table = db_get_cursor_table(&cursor); nrows = db_get_num_rows(&cursor); G_debug(2, "%d points selected", nrows); count = cat = 0; G_message(_("Writing features...")); while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) { G_percent(count, nrows, 2); /* key column */ if (keycol_opt->answer) { column = db_get_table_column(table, with_z ? 3 : 2); ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column)); if (ctype != DB_C_TYPE_INT) G_fatal_error(_("Key column must be integer")); value = db_get_column_value(column); cat = db_get_value_int(value); } else { cat++; } /* coordinates */ for (i = 0; i < ncoor; i++) { column = db_get_table_column(table, i); ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column)); if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE) G_fatal_error(_("x/y/z column must be integer or double")); value = db_get_column_value(column); if (ctype == DB_C_TYPE_INT) coor[i] = (double)db_get_value_int(value); else coor[i] = db_get_value_double(value); } Vect_reset_line(Points); Vect_reset_cats(Cats); Vect_append_point(Points, coor[0], coor[1], coor[2]); Vect_cat_set(Cats, 1, cat); Vect_write_line(&Map, GV_POINT, Points, Cats); count++; } G_percent(1, 1, 1); /* close connection to input DB before copying attributes */ db_close_database_shutdown_driver(driver); /* Copy table */ if (!same_table_flag->answer) { G_message(_("Copying attributes...")); if (DB_FAILED == db_copy_table_where(driver_opt->answer, database_opt->answer, table_opt->answer, fi->driver, fi->database, fi->table, where_opt->answer)) { /* where can be NULL */ G_warning(_("Unable to copy table")); } else { Vect_map_add_dblink(&Map, 1, NULL, fi->table, keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN, fi->database, fi->driver); } if (!keycol_opt->answer) { /* TODO: implement for all DB drivers in generic way if * possible */ 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_set_error_handler_driver(driver); /* add key column */ sprintf(buf, "ALTER TABLE %s ADD COLUMN %s INTEGER", fi->table, GV_KEY_COLUMN); db_set_string(&sql, buf); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Unable to add key column <%s>: " "SERIAL type is not supported by <%s>"), GV_KEY_COLUMN, fi->driver); } /* update key column */ sprintf(buf, "UPDATE %s SET %s = _ROWID_", fi->table, GV_KEY_COLUMN); db_set_string(&sql, buf); if (db_execute_immediate(driver, &sql) != DB_OK) { G_fatal_error(_("Failed to update key column <%s>"), GV_KEY_COLUMN); } } } else { /* do not copy attributes, link original table */ Vect_map_add_dblink(&Map, 1, NULL, table_opt->answer, keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN, database_opt->answer, driver_opt->answer); } Vect_build(&Map); Vect_close(&Map); G_done_msg(_n("%d point written to vector map.", "%d points written to vector map.", count), count); return (EXIT_SUCCESS); }
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; }
int display_attr(struct Map_info *Map, int type, char *attrcol, struct cat_list *Clist, LATTR *lattr, int chcat) { int i, ltype, more; struct line_pnts *Points; struct line_cats *Cats; int cat; char buf[2000]; struct field_info *fi; dbDriver *driver; dbString stmt, valstr, text; dbCursor cursor; dbTable *table; dbColumn *column; G_debug(2, "attr()"); if (attrcol == NULL || *attrcol == '\0') { G_fatal_error(_("attrcol not specified, cannot display attributes")); } Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); db_init_string(&stmt); db_init_string(&valstr); db_init_string(&text); fi = Vect_get_field(Map, lattr->field); if (fi == NULL) return 1; 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); Vect_rewind(Map); while (1) { ltype = Vect_read_next_line(Map, Points, Cats); if (ltype == -1) G_fatal_error(_("Unable to read vector map")); else if (ltype == -2) /* EOF */ break; if (!(type & ltype) && !((type & GV_AREA) && (ltype & GV_CENTROID))) continue; /* used for both lines and labels */ D_RGB_color(lattr->color.R, lattr->color.G, lattr->color.B); D_text_size(lattr->size, lattr->size); if (lattr->font) D_font(lattr->font); if (lattr->enc) D_encoding(lattr->enc); if (chcat) { int found = 0; for (i = 0; i < Cats->n_cats; i++) { if (Cats->field[i] == Clist->field && Vect_cat_in_cat_list(Cats->cat[i], Clist)) { found = 1; break; } } if (!found) continue; } else if (Clist->field > 0) { int found = 0; for (i = 0; i < Cats->n_cats; i++) { if (Cats->field[i] == Clist->field) { found = 1; break; } } /* lines with no category will be displayed */ if (Cats->n_cats > 0 && !found) continue; } if (Vect_cat_get(Cats, lattr->field, &cat)) { int ncats = 0; /* Read attribute from db */ db_free_string(&text); for (i = 0; i < Cats->n_cats; i++) { int nrows; if (Cats->field[i] != lattr->field) continue; db_init_string(&stmt); sprintf(buf, "select %s from %s where %s = %d", attrcol, fi->table, fi->key, Cats->cat[i]); G_debug(2, "SQL: %s", buf); db_append_string(&stmt, buf); 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); if (ncats > 0) db_append_string(&text, "/"); if (nrows > 0) { table = db_get_cursor_table(&cursor); column = db_get_table_column(table, 0); /* first column */ if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) continue; db_convert_column_value_to_string(column, &valstr); db_append_string(&text, db_get_string(&valstr)); } else { G_warning(_("No attribute found for cat %d: %s"), cat, db_get_string(&stmt)); } db_close_cursor(&cursor); ncats++; } show_label_line(Points, ltype, lattr, db_get_string(&text)); } } db_close_database_shutdown_driver(driver); Vect_destroy_line_struct(Points); Vect_destroy_cats_struct(Cats); return 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); }
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; }
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; }
/* Returns field names, types and indexes in double and string Map_info arrays WARNING: user is responsible to free allocated memory, directly or calling G_sites_free_fields() */ int G_sites_get_fields(struct Map_info *Map, char ***cnames, int **ctypes, int **ndx) { struct field_info *fi; int nrows, row, ncols, col, ndbl, nstr, ctype; const char *name; dbDriver *driver; dbString stmt; dbCursor cursor; dbTable *table; dbColumn *column; /*dbValue *value; */ /* warning: we are using "1" as cat field in Vect_get_field because G_sites_open_old (in lib/sites/sites.c), that we use here to open sites, does the same and then queries the db in the same way we do here. Should it be not true in the future, maybe we'll have to change this by choosing appropriate fields and multiple categories */ fi = (struct field_info *)Vect_get_field(Map, 1); if (fi == NULL) { /* not attribute table */ G_debug(1, "No attribute table"); return -1; } driver = db_start_driver_open_database(fi->driver, fi->database); if (driver == NULL) G_fatal_error(_("Cannot 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(_("Cannot select attributes")); nrows = db_get_num_rows(&cursor); G_debug(1, "%d rows selected from vector attribute table", nrows); table = db_get_cursor_table(&cursor); ncols = db_get_table_number_of_columns(table); if (ncols <= 0) return ncols; row = 0; /* Get number of each type */ ndbl = nstr = 0; *cnames = (char **)malloc(ncols * sizeof(char *)); *ctypes = (int *)malloc(ncols * sizeof(int)); *ndx = (int *)malloc(ncols * sizeof(int)); for (col = 0; col < ncols; col++) { column = db_get_table_column(table, col); ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column)); name = db_get_column_name(column); *(*cnames + col) = (char *)malloc(strlen(name) + 1); strcpy(*(*cnames + col), db_get_column_name(column)); /* ctypes is 'c' for cat, 'd' for double, 's' for string */ if (strcmp(name, fi->key) == 0) { *(*ctypes + col) = 'c'; *(*ndx + col) = -1; } else { switch (ctype) { case DB_C_TYPE_INT: case DB_C_TYPE_DOUBLE: *(*ctypes + col) = 'd'; *(*ndx + col) = ndbl; ndbl++; break; case DB_C_TYPE_STRING: case DB_C_TYPE_DATETIME: *(*ctypes + col) = 's'; *(*ndx + col) = nstr; nstr++; break; } } } db_close_database_shutdown_driver(driver); return ncols; }