123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784 |
- /****************************************************************
- *
- * MODULE: v.random (based on s.rand)
- *
- * AUTHOR(S): James Darrell McCauley darrell@mccauley-usa.com
- * http://mccauley-usa.com/
- * OGR support by Martin Landa <landa.martin gmail.com>
- * Area support by Markus Metz
- *
- * PURPOSE: Randomly generate a 2D/3D GRASS vector points map.
- *
- * Modification History:
- *
- * s.rand v 0.5B <25 Jun 1995> Copyright (c) 1993-1995. James Darrell McCauley
- * <?? ??? 1993> - began coding and released test version (jdm)
- * <10 Jan 1994> - changed RAND_MAX for rand(), since it is different for
- * SunOS 4.1.x and Solaris 2.3. stdlib.h in the latter defines
- * RAND_MAX, but it doesn't in the former. v0.2B (jdm)
- * <02 Jan 1995> - clean Gmakefile, man page. added html v0.3B (jdm)
- * <25 Feb 1995> - cleaned 'gcc -Wall' warnings (jdm)
- * <25 Jun 1995> - new site API (jdm)
- * <13 Sep 2000> - released under GPL
- *
- * COPYRIGHT: (C) 2003-2018 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.
- *
- **************************************************************/
- #include <stdlib.h>
- #include <math.h>
- #include <string.h>
- #include <grass/gis.h>
- #include <grass/vector.h>
- #include <grass/dbmi.h>
- #include <grass/glocale.h>
- /* for qsort */
- typedef struct {
- int i;
- double size;
- struct bound_box box;
- } BOX_SIZE;
- static int sort_by_size(const void *a, const void *b)
- {
- BOX_SIZE *as = (BOX_SIZE *)a;
- BOX_SIZE *bs = (BOX_SIZE *)b;
-
- if (as->size < bs->size)
- return -1;
- return (as->size > bs->size);
- }
- int main(int argc, char *argv[])
- {
- char *output, buf[DB_SQL_MAX];
- double (*rng)(void) = G_drand48;
- double zmin, zmax;
- int seed;
- unsigned long i, n, total_n;
- int j, k, type, usefloat;
- int area, nareas, field, cat_area;
- int cat, icol, ncols;
- struct boxlist *List = NULL;
- BOX_SIZE *size_list = NULL;
- int alloc_size_list = 0;
- struct Map_info In, Out;
- struct line_pnts *Points;
- struct line_cats *Cats;
- struct cat_list *cat_list;
- struct bound_box box;
- struct Cell_head window;
- struct GModule *module;
- struct
- {
- struct Option *input, *field, *cats, *where, *output, *nsites,
- *zmin, *zmax, *zcol, *ztype, *seed;
- } parm;
- struct
- {
- struct Flag *z, *notopo, *a;
- } flag;
- int notable;
- struct field_info *Fi, *Fi_input;
- dbDriver *driver, *driver_input;
- dbString sql;
- dbTable *table;
- dbCatValI *cats_array = NULL;
-
- G_gisinit(argv[0]);
- module = G_define_module();
- G_add_keyword(_("vector"));
- G_add_keyword(_("sampling"));
- G_add_keyword(_("statistics"));
- G_add_keyword(_("random"));
- G_add_keyword(_("point pattern"));
- G_add_keyword(_("stratified random sampling"));
- G_add_keyword(_("level1"));
- module->description = _("Generates random 2D/3D vector points.");
- parm.output = G_define_standard_option(G_OPT_V_OUTPUT);
- parm.nsites = G_define_option();
- parm.nsites->key = "npoints";
- parm.nsites->type = TYPE_INTEGER;
- parm.nsites->required = YES;
- parm.nsites->description = _("Number of points to be created");
- parm.input = G_define_standard_option(G_OPT_V_INPUT);
- parm.input->key = "restrict";
- parm.input->required = NO;
- parm.input->description = _("Restrict points to areas in input vector");
- parm.input->guisection = _("Selection");
- parm.input->guisection = _("Restrict");
-
- parm.field = G_define_standard_option(G_OPT_V_FIELD_ALL);
- parm.field->guisection = _("Selection");
- parm.cats = G_define_standard_option(G_OPT_V_CATS);
- parm.cats->guisection = _("Selection");
-
- parm.where = G_define_standard_option(G_OPT_DB_WHERE);
- parm.where->guisection = _("Selection");
- parm.zmin = G_define_option();
- parm.zmin->key = "zmin";
- parm.zmin->type = TYPE_DOUBLE;
- parm.zmin->required = NO;
- parm.zmin->description =
- _("Minimum z height (needs -z flag or column name)");
- parm.zmin->answer = "0.0";
- parm.zmin->guisection = _("3D output");
- parm.zmax = G_define_option();
- parm.zmax->key = "zmax";
- parm.zmax->type = TYPE_DOUBLE;
- parm.zmax->required = NO;
- parm.zmax->description =
- _("Maximum z height (needs -z flag or column name)");
- parm.zmax->answer = "0.0";
- parm.zmax->guisection = _("3D output");
- parm.seed = G_define_option();
- parm.seed->key = "seed";
- parm.seed->type = TYPE_INTEGER;
- parm.seed->required = NO;
- parm.seed->description =
- _("The seed to initialize the random generator. If not set the process ID is used");
- parm.zcol = G_define_standard_option(G_OPT_DB_COLUMN);
- parm.zcol->label = _("Name of column for z values");
- parm.zcol->description =
- _("Writes z values to column");
- parm.zcol->guisection = _("3D output");
- parm.ztype = G_define_option();
- parm.ztype->key = "column_type";
- parm.ztype->type = TYPE_STRING;
- parm.ztype->required = NO;
- parm.ztype->multiple = NO;
- parm.ztype->description = _("Type of column for z values");
- parm.ztype->options = "integer,double precision";
- parm.ztype->answer = "double precision";
- parm.ztype->guisection = _("3D output");
- flag.z = G_define_flag();
- flag.z->key = 'z';
- flag.z->description = _("Create 3D output");
- flag.z->guisection = _("3D output");
- flag.a = G_define_flag();
- flag.a->key = 'a';
- flag.a->description = _("Generate n points for each individual area (requires restrict parameter)");
- flag.a->guisection = _("Restrict");
-
- flag.notopo = G_define_standard_flag(G_FLG_V_TOPO);
- G_option_requires(flag.a, parm.input, NULL);
-
- if (G_parser(argc, argv))
- exit(EXIT_FAILURE);
- output = parm.output->answer;
- n = strtoul(parm.nsites->answer, NULL, 10);
- seed = 0;
- if(parm.seed->answer)
- seed = atoi(parm.seed->answer);
- if (n <= 0) {
- G_fatal_error(_("Number of points must be > 0 (%ld given)"), n);
- }
- nareas = 0;
- cat_list = NULL;
- field = -1;
- if (parm.input->answer) {
- Vect_set_open_level(2); /* topology required */
- if (2 > Vect_open_old2(&In, parm.input->answer, "", parm.field->answer))
- G_fatal_error(_("Unable to open vector map <%s>"),
- parm.input->answer);
- if (parm.field->answer)
- field = Vect_get_field_number(&In, parm.field->answer);
- if ((parm.cats->answer || parm.where->answer) && field == -1) {
- G_warning(_("Invalid layer number (%d). Parameter '%s' or '%s' specified, assuming layer '1'."),
- field, parm.cats->key, parm.where->key);
- field = 1;
- }
- if (field > 0)
- cat_list = Vect_cats_set_constraint(&In, field, parm.where->answer,
- parm.cats->answer);
- nareas = Vect_get_num_areas(&In);
- if (nareas == 0) {
- Vect_close(&In);
- G_fatal_error(_("No areas in vector map <%s>"), parm.input->answer);
- }
- }
- /* create new vector map */
- if (-1 == Vect_open_new(&Out, output, flag.z->answer ? WITH_Z : WITHOUT_Z))
- G_fatal_error(_("Unable to create vector map <%s>"), output);
- Vect_set_error_handler_io(NULL, &Out);
- /* Do we need to write random values into attribute table? */
- usefloat = -1;
- notable = !(parm.zcol->answer || (parm.input -> answer && field > 0));
- driver = NULL;
- driver_input = NULL;
- Fi = NULL;
- Fi_input = NULL;
- ncols = 0;
- if (!notable) {
- Fi = Vect_default_field_info(&Out, 1, NULL, GV_1TABLE);
- driver =
- db_start_driver_open_database(Fi->driver,
- Vect_subst_var(Fi->database, &Out));
- if (driver == NULL) {
- G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
- Vect_subst_var(Fi->database, &Out), Fi->driver);
- }
- db_set_error_handler_driver(driver);
-
- db_begin_transaction(driver);
- db_init_string(&sql);
- /* Create table */
- sprintf(buf, "create table %s (%s integer", Fi->table, GV_KEY_COLUMN);
- db_set_string(&sql, buf);
- if (parm.zcol->answer) {
- sprintf(buf, ", %s %s", parm.zcol->answer, parm.ztype->answer);
- db_append_string(&sql, buf);
- }
- if (parm.input->answer && field > 0) {
- dbString table_name;
- dbColumn *col;
-
- Fi_input = Vect_get_field2(&In, parm.field->answer);
- if (Fi_input == NULL)
- G_fatal_error(_("Database connection not defined for layer <%s>"),
- parm.field->answer);
- driver_input = db_start_driver_open_database(
- Fi_input->driver,
- Vect_subst_var(Fi_input->database, &In));
- if (driver_input == NULL) {
- G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
- Vect_subst_var(Fi_input->database, &In), Fi_input->driver);
- }
- db_set_error_handler_driver(driver_input);
-
- db_init_string(&table_name);
- db_set_string(&table_name, Fi_input->table);
- if (db_describe_table(driver_input, &table_name, &table) != DB_OK)
- G_fatal_error(_("Unable to describe table <%s>"),
- Fi_input->table);
- ncols = db_get_table_number_of_columns(table);
- for (icol = 0; icol < ncols; icol++) {
- col = db_get_table_column(table, icol);
- sprintf(buf, ",%s_%s %s", parm.input->answer,
- db_get_column_name(col),
- db_sqltype_name(db_get_column_sqltype(col)));
- db_append_string(&sql, buf);
- }
- }
- db_append_string(&sql, ")");
-
- if (db_execute_immediate(driver, &sql) != DB_OK) {
- G_fatal_error(_("Unable to create table: %s"),
- db_get_string(&sql));
- }
- /* Create index */
- if (db_create_index2(driver, Fi->table, Fi->key) != DB_OK)
- G_warning(_("Unable to create index"));
- /* Grant */
- if (db_grant_on_table
- (driver, Fi->table, DB_PRIV_SELECT,
- DB_GROUP | DB_PUBLIC) != DB_OK) {
- G_fatal_error(_("Unable to grant privileges on table <%s>"),
- Fi->table);
- }
- /* OK. Let's check what type of column user has created */
- db_set_string(&sql, Fi->table);
- if (db_describe_table(driver, &sql, &table) != DB_OK) {
- G_fatal_error(_("Unable to describe table <%s>"), Fi->table);
- }
- if (parm.zcol->answer) {
- type = db_get_column_sqltype(db_get_table_column(table, 1));
- if (type == DB_SQL_TYPE_SMALLINT || type == DB_SQL_TYPE_INTEGER)
- usefloat = 0;
- if (type == DB_SQL_TYPE_REAL || type == DB_SQL_TYPE_DOUBLE_PRECISION)
- usefloat = 1;
- if (usefloat < 0) {
- G_fatal_error(_("You have created unsupported column type. This module supports only INTEGER"
- " and DOUBLE PRECISION column types."));
- }
- }
- Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
- Fi->driver);
- }
- Vect_hist_command(&Out);
- /* Init the random seed */
- if(parm.seed->answer)
- G_srand48(seed);
- else
- G_srand48_auto();
- G_get_window(&window);
- Points = Vect_new_line_struct();
- Cats = Vect_new_cats_struct();
- if (nareas > 0) {
- int first = 1, count;
- struct bound_box abox, bbox;
- box.W = window.west;
- box.E = window.east;
- box.S = window.south;
- box.N = window.north;
- box.B = -PORT_DOUBLE_MAX;
- box.T = PORT_DOUBLE_MAX;
- count = 0;
- for (i = 1; i <= nareas; i++) {
-
- if (!Vect_get_area_centroid(&In, i))
- continue;
- if (field > 0) {
- if (Vect_get_area_cats(&In, i, Cats))
- continue;
- if (!Vect_cats_in_constraint(Cats, field, cat_list))
- continue;
- }
- Vect_get_area_box(&In, i, &abox);
- if (!Vect_box_overlap(&abox, &box))
- continue;
- if (first) {
- Vect_box_copy(&bbox, &abox);
- first = 0;
- }
- else
- Vect_box_extend(&bbox, &abox);
- count++;
- }
- if (count == 0) {
- Vect_close(&In);
- Vect_close(&Out);
- Vect_delete(output);
- G_fatal_error(_("Selected areas in input vector <%s> do not overlap with the current region"),
- parm.input->answer);
- }
- Vect_box_copy(&box, &bbox);
- /* does the vector overlap with the current region ? */
- if (box.W >= window.east || box.E <= window.west ||
- box.S >= window.north || box.N <= window.south) {
- Vect_close(&In);
- Vect_close(&Out);
- Vect_delete(output);
- G_fatal_error(_("Input vector <%s> does not overlap with the current region"),
- parm.input->answer);
- }
- /* try to reduce the current region */
- if (window.east > box.E)
- window.east = box.E;
- if (window.west < box.W)
- window.west = box.W;
- if (window.north > box.N)
- window.north = box.N;
- if (window.south < box.S)
- window.south = box.S;
- List = Vect_new_boxlist(1);
- alloc_size_list = 10;
- size_list = G_malloc(alloc_size_list * sizeof(BOX_SIZE));
- }
- zmin = zmax = 0;
- if (flag.z->answer || parm.zcol->answer) {
- zmax = atof(parm.zmax->answer);
- zmin = atof(parm.zmin->answer);
- }
- G_message(_("Generating points..."));
- if (flag.a->answer && nareas > 0) {
- struct bound_box abox, bbox;
- cat = 1;
- /* n points for each area */
- nareas = Vect_get_num_areas(&In);
-
- /* init cat/cat_area array */
- total_n = n * nareas;
- cats_array = G_malloc(total_n * sizeof(dbCatValI));
- G_percent(0, nareas, 1);
- for (area = 1; area <= nareas; area++) {
- G_percent(area, nareas, 1);
- if (!Vect_get_area_centroid(&In, area))
- continue;
- if (field > 0) {
- if (Vect_get_area_cats(&In, area, Cats))
- continue;
- if (!Vect_cats_in_constraint(Cats, field, cat_list)) {
- continue;
- }
- }
- box.W = window.west;
- box.E = window.east;
- box.S = window.south;
- box.N = window.north;
- box.B = -PORT_DOUBLE_MAX;
- box.T = PORT_DOUBLE_MAX;
-
- Vect_get_area_box(&In, area, &abox);
- if (!Vect_box_overlap(&box, &abox))
- continue;
-
- bbox = abox;
- if (bbox.W < box.W)
- bbox.W = box.W;
- if (bbox.E > box.E)
- bbox.E = box.E;
- if (bbox.S < box.S)
- bbox.S = box.S;
- if (bbox.N > box.N)
- bbox.N = box.N;
- cat_area = -1;
- if (field > 0) {
- if (cat_list) {
- for (i = 0; i < Cats->n_cats; i++) {
- if (Cats->field[i] == field &&
- Vect_cat_in_cat_list(Cats->cat[i], cat_list)) {
- cat_area = Cats->cat[i];
- break;
- }
- }
- }
- else {
- Vect_cat_get(Cats, field, &cat_area);
- }
- if (cat_area < 0)
- continue;
- }
- for (i = 0; i < n; ++i) {
- double x, y, z;
- int outside = 1;
- int ret;
- if (field > 0) {
- cats_array[cat-1].cat = cat;
- cats_array[cat-1].val = cat_area;
- }
- Vect_reset_line(Points);
- Vect_reset_cats(Cats);
- while (outside) {
- x = rng() * (bbox.W - bbox.E) + bbox.E;
- y = rng() * (bbox.N - bbox.S) + bbox.S;
- z = rng() * (zmax - zmin) + zmin;
- ret = Vect_point_in_area(x, y, &In, area, &abox);
- G_debug(3, " area = %d Vect_point_in_area() = %d", area, ret);
- if (ret >= 1) {
- outside = 0;
- }
- }
- if (flag.z->answer)
- Vect_append_point(Points, x, y, z);
- else
- Vect_append_point(Points, x, y, 0.0);
- if (!notable) {
- sprintf(buf, "insert into %s (%s", Fi->table, Fi->key);
- db_set_string(&sql, buf);
- if (parm.zcol->answer) {
- sprintf(buf, ", %s", parm.zcol->answer);
- db_append_string(&sql, buf);
- }
- sprintf(buf, ") values ( %d", cat);
- db_append_string(&sql, buf);
- if (parm.zcol->answer) {
- /* Round random value if column is integer type */
- if (usefloat)
- sprintf(buf, ", %f", z);
- else
- sprintf(buf, ", %.0f", z);
- db_append_string(&sql, buf);
- }
- db_append_string(&sql, ")");
-
- G_debug(3, "%s", db_get_string(&sql));
- if (db_execute_immediate(driver, &sql) != DB_OK) {
- G_fatal_error(_("Unable to insert new row: %s"),
- db_get_string(&sql));
- }
- }
- Vect_cat_set(Cats, 1, cat++);
- Vect_write_line(&Out, GV_POINT, Points, Cats);
- }
- }
- }
- else {
- total_n = n;
- if (parm.input->answer && field > 0)
- cats_array = G_malloc(n * sizeof(dbCatValI));
- /* n points in total */
- for (i = 0; i < n; ++i) {
- double x, y, z;
- G_percent(i, n, 4);
- Vect_reset_line(Points);
- Vect_reset_cats(Cats);
- x = rng() * (window.west - window.east) + window.east;
- y = rng() * (window.north - window.south) + window.south;
- z = rng() * (zmax - zmin) + zmin;
-
- if (nareas) {
- int outside = 1;
- do {
- /* select areas by box */
- box.E = x;
- box.W = x;
- box.N = y;
- box.S = y;
- box.T = PORT_DOUBLE_MAX;
- box.B = -PORT_DOUBLE_MAX;
- Vect_select_areas_by_box(&In, &box, List);
- G_debug(3, " %d areas selected by box", List->n_values);
- /* sort areas by size, the smallest is likely to be the nearest */
- if (alloc_size_list < List->n_values) {
- alloc_size_list = List->n_values;
- size_list = G_realloc(size_list, alloc_size_list * sizeof(BOX_SIZE));
- }
- k = 0;
- for (j = 0; j < List->n_values; j++) {
- area = List->id[j];
- if (!Vect_get_area_centroid(&In, area))
- continue;
- if (field > 0) {
- if (Vect_get_area_cats(&In, area, Cats))
- continue;
- if (!Vect_cats_in_constraint(Cats, field, cat_list)) {
- continue;
- }
- }
-
- List->id[k] = List->id[j];
- List->box[k] = List->box[j];
- size_list[k].i = List->id[k];
- box = List->box[k];
- size_list[k].box = List->box[k];
- size_list[k].size = (box.N - box.S) * (box.E - box.W);
- k++;
- }
- List->n_values = k;
-
- if (List->n_values == 2) {
- /* simple swap */
- if (size_list[1].size < size_list[0].size) {
- size_list[0].i = List->id[1];
- size_list[1].i = List->id[0];
- size_list[0].box = List->box[1];
- size_list[1].box = List->box[0];
- }
- }
- else if (List->n_values > 2)
- qsort(size_list, List->n_values, sizeof(BOX_SIZE), sort_by_size);
- for (j = 0; j < List->n_values; j++) {
- int ret;
- area = size_list[j].i;
- ret = Vect_point_in_area(x, y, &In, area, &size_list[j].box);
- G_debug(3, " area = %d Vect_point_in_area() = %d", area, ret);
- if (ret >= 1) {
- if (field > 0) {
- /* read categories for matched area */
- Vect_get_area_cats(&In, area, Cats);
- }
- outside = 0;
- break;
- }
- }
- if (outside) {
- x = rng() * (window.west - window.east) + window.east;
- y = rng() * (window.north - window.south) + window.south;
- z = rng() * (zmax - zmin) + zmin;
- }
- } while (outside);
- }
- if (flag.z->answer)
- Vect_append_point(Points, x, y, z);
- else
- Vect_append_point(Points, x, y, 0.0);
- cat = i + 1;
-
- if (!notable) {
- if (parm.input->answer && field > 0) {
- Vect_cat_get(Cats, field, &cat_area);
- cats_array[i].cat = cat;
- cats_array[i].val = cat_area;
-
- }
-
- sprintf(buf, "insert into %s (%s", Fi->table, Fi->key);
- db_set_string(&sql, buf);
- if (parm.zcol->answer) {
- sprintf(buf, ", %s", parm.zcol->answer);
- db_append_string(&sql, buf);
- }
- sprintf(buf, ") values ( %ld", i + 1);
- db_append_string(&sql, buf);
- if (parm.zcol->answer) {
- /* Round random value if column is integer type */
- if (usefloat)
- sprintf(buf, ", %f", z);
- else
- sprintf(buf, ", %.0f", z);
- db_append_string(&sql, buf);
- }
- db_append_string(&sql, ")");
-
- G_debug(3, "%s", db_get_string(&sql));
- if (db_execute_immediate(driver, &sql) != DB_OK) {
- G_fatal_error(_("Unable to insert new row: %s"),
- db_get_string(&sql));
- }
- }
- Vect_cat_set(Cats, 1, cat);
- Vect_write_line(&Out, GV_POINT, Points, Cats);
- }
- G_percent(1, 1, 1);
- }
-
- if (parm.input->answer && field > 0) {
- int more, ctype;
- const char *column_name;
- dbColumn *column;
- dbValue *value;
- dbString value_str, update_str;
- dbCursor cursor;
-
- db_init_string(&value_str);
- db_init_string(&update_str);
- sprintf(buf, "select * from %s", Fi_input->table);
- db_set_string(&sql, buf);
- if (db_open_select_cursor(driver_input, &sql,
- &cursor, DB_SEQUENTIAL) != DB_OK)
- G_fatal_error(_("Unable to open select cursor"));
- table = db_get_cursor_table(&cursor);
- while (TRUE) {
- if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
- G_fatal_error(_("Unable to fetch data from table <%s>"),
- Fi_input->table);
-
- if (!more) {
- break;
- }
- sprintf(buf, "update %s set ", Fi->table);
- db_set_string(&update_str, buf);
- for (icol = 0; icol < ncols; icol++) {
- column = db_get_table_column(table, icol);
- column_name = db_get_column_name(column);
- value = db_get_column_value(column);
- if (strcmp(column_name, Fi_input->key) == 0)
- cat_area = db_get_value_int(value);
-
- if (icol > 0)
- db_append_string(&update_str, ", ");
- sprintf(buf, "%s_%s = ", parm.input->answer, column_name);
- db_append_string(&update_str, buf);
- ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
- db_convert_value_to_string(value, ctype, &value_str);
- if (ctype == DB_C_TYPE_INT || ctype == DB_C_TYPE_DOUBLE)
- sprintf(buf, "%s", db_get_string(&value_str));
- else
- sprintf(buf, "'%s'", db_get_string(&value_str));
- db_append_string(&update_str, buf);
- }
- for (i = 0; i < total_n; i++) {
- if (cat_area == cats_array[i].val) {
- db_copy_string(&sql, &update_str);
- sprintf(buf, " where %s = %d", Fi->key, cats_array[i].cat);
- db_append_string(&sql, buf);
- G_debug(3, "%s", db_get_string(&sql));
- if (db_execute_immediate(driver, &sql) != DB_OK) {
- G_fatal_error(_("Unable to update row: %s"),
- db_get_string(&sql));
- }
- }
- }
- }
- G_free(cats_array);
- }
- if (!notable) {
- db_commit_transaction(driver);
- db_close_database_shutdown_driver(driver);
- }
- if (!flag.notopo->answer) {
- Vect_build(&Out);
- }
- Vect_close(&Out);
- exit(EXIT_SUCCESS);
- }
|