|
@@ -25,12 +25,11 @@
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
{
|
|
|
- int i, cat, with_z, more, ctype, ret, nrows;
|
|
|
- char buf[2000];
|
|
|
+ int i, cat, with_z, more, ctype, nrows;
|
|
|
+ char buf[DB_SQL_MAX];
|
|
|
int count;
|
|
|
double coor[3];
|
|
|
int ncoor;
|
|
|
- int coltype;
|
|
|
struct Option *driver_opt, *database_opt, *table_opt;
|
|
|
struct Option *xcol_opt, *ycol_opt, *zcol_opt, *keycol_opt, *where_opt,
|
|
|
*outvect;
|
|
@@ -64,11 +63,11 @@ int main(int argc, char *argv[])
|
|
|
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 = _("Connection");
|
|
|
+ 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 = _("Connection");
|
|
|
+ database_opt->guisection = _("Input DB");
|
|
|
|
|
|
xcol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
|
|
|
xcol_opt->key = "x";
|
|
@@ -87,7 +86,7 @@ int main(int argc, char *argv[])
|
|
|
|
|
|
keycol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
|
|
|
keycol_opt->key = "key";
|
|
|
- keycol_opt->required = YES;
|
|
|
+ keycol_opt->required = NO;
|
|
|
keycol_opt->label = _("Name of column containing category number");
|
|
|
keycol_opt->description = _("Must refer to an integer column");
|
|
|
|
|
@@ -131,7 +130,8 @@ int main(int argc, char *argv[])
|
|
|
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(),
|
|
@@ -144,27 +144,42 @@ int main(int argc, char *argv[])
|
|
|
db_get_default_driver_name(),
|
|
|
db_get_default_database_name());
|
|
|
|
|
|
- coltype = db_column_Ctype(driver, table_opt->answer, keycol_opt->answer);
|
|
|
+ if (keycol_opt->answer) {
|
|
|
+ int coltype;
|
|
|
+ coltype = db_column_Ctype(driver, table_opt->answer, keycol_opt->answer);
|
|
|
|
|
|
- if (coltype == -1)
|
|
|
- G_fatal_error(_("Missing column <%s> 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"));
|
|
|
+ if (coltype == -1)
|
|
|
+ G_fatal_error(_("Missing column <%s> 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, %s", keycol_opt->answer, xcol_opt->answer,
|
|
|
- ycol_opt->answer);
|
|
|
+ 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);
|
|
|
}
|
|
|
-
|
|
|
- sprintf(buf, " from %s", table_opt->answer);
|
|
|
+ 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);
|
|
@@ -181,20 +196,26 @@ int main(int argc, char *argv[])
|
|
|
|
|
|
G_debug(2, "%d points selected", nrows);
|
|
|
|
|
|
- count = 0;
|
|
|
+ count = cat = 0;
|
|
|
G_message(_("Writing features..."));
|
|
|
while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
|
|
|
G_percent(count, nrows, 2);
|
|
|
/* key column */
|
|
|
- column = db_get_table_column(table, 0);
|
|
|
- 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);
|
|
|
-
|
|
|
+ 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 + 1);
|
|
|
+ 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"));
|
|
@@ -218,34 +239,63 @@ int main(int argc, char *argv[])
|
|
|
}
|
|
|
G_percent(1, 1, 1);
|
|
|
|
|
|
+ /* close connection to input DB before copying attributes */
|
|
|
db_close_database_shutdown_driver(driver);
|
|
|
|
|
|
/* Copy table */
|
|
|
- G_message(_("Copying attributes..."));
|
|
|
if (!same_table_flag->answer) {
|
|
|
- if (where_opt->answer)
|
|
|
- ret =
|
|
|
- db_copy_table_where(driver_opt->answer, database_opt->answer,
|
|
|
- table_opt->answer, fi->driver,
|
|
|
- fi->database, fi->table,
|
|
|
- where_opt->answer);
|
|
|
- else
|
|
|
- ret =
|
|
|
- db_copy_table(driver_opt->answer, database_opt->answer,
|
|
|
- table_opt->answer, fi->driver, fi->database,
|
|
|
- fi->table);
|
|
|
- if (ret == DB_FAILED) {
|
|
|
- G_warning(_("Unable to copy table"));
|
|
|
+ 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,
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 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, database_opt->answer,
|
|
|
- driver_opt->answer);
|
|
|
+ keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN,
|
|
|
+ database_opt->answer, driver_opt->answer);
|
|
|
}
|
|
|
|
|
|
Vect_build(&Map);
|