[GRASS-SVN] r73236 - grass/trunk/vector/v.to.db
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Sep 3 13:17:12 PDT 2018
Author: mmetz
Date: 2018-09-03 13:17:12 -0700 (Mon, 03 Sep 2018)
New Revision: 73236
Modified:
grass/trunk/vector/v.to.db/main.c
grass/trunk/vector/v.to.db/query.c
Log:
v.to.db: check if column(s) exist before updating, includes check for correct column type, create column(s) of not existing, see #3466
Modified: grass/trunk/vector/v.to.db/main.c
===================================================================
--- grass/trunk/vector/v.to.db/main.c 2018-09-03 20:04:40 UTC (rev 73235)
+++ grass/trunk/vector/v.to.db/main.c 2018-09-03 20:17:12 UTC (rev 73236)
@@ -16,6 +16,7 @@
*****************************************************************************/
#include <stdlib.h>
+#include <grass/dbmi.h>
#include <grass/glocale.h>
#include "global.h"
@@ -28,7 +29,8 @@
int n, i, j, cat, lastcat, type, id, findex;
struct Map_info Map;
struct GModule *module;
- struct field_info *Fi;
+ struct field_info *Fi, *qFi;
+ int ncols;
G_gisinit(argv[0]);
@@ -73,6 +75,206 @@
options.field);
}
+ qFi = Vect_get_field(&Map, options.qfield);
+ if (options.option == O_QUERY && qFi == NULL)
+ G_fatal_error(_("Database connection not defined for layer %d. Use v.db.connect first."),
+ options.qfield);
+
+ if (!options.print) {
+ dbDriver *driver = NULL;
+ dbString table_name;
+ dbTable *table;
+ dbColumn *column;
+ const char *colname;
+ int col, fncols, icol;
+ int col_sqltype[4];
+ int create_col[4], create_cols;
+ int qlength;
+
+ /* get required column types */
+ col_sqltype[0] = col_sqltype[1] = col_sqltype[2] = col_sqltype[3] = -1;
+ ncols = 1;
+ qlength = 0;
+
+ switch (options.option) {
+ case O_CAT:
+ case O_COUNT:
+ col_sqltype[0] = DB_SQL_TYPE_INTEGER;
+ break;
+
+ case O_LENGTH:
+ case O_AREA:
+ case O_PERIMETER:
+ case O_SLOPE:
+ case O_SINUOUS:
+ case O_AZIMUTH:
+ case O_COMPACT:
+ case O_FD:
+ col_sqltype[0] = DB_SQL_TYPE_DOUBLE_PRECISION;
+ break;
+
+ case O_BBOX:
+ col_sqltype[0] = col_sqltype[1] = col_sqltype[2] = col_sqltype[3] = DB_SQL_TYPE_DOUBLE_PRECISION;
+ ncols = 4;
+ break;
+
+ case O_COOR:
+ case O_START:
+ case O_END:
+ col_sqltype[0] = col_sqltype[1] = col_sqltype[2] = DB_SQL_TYPE_DOUBLE_PRECISION;
+ ncols = 2;
+ if (options.col[2])
+ ncols = 3;
+ break;
+
+ case O_SIDES:
+ col_sqltype[0] = col_sqltype[1] = DB_SQL_TYPE_INTEGER;
+ ncols = 2;
+ break;
+
+ case O_QUERY:
+ driver = db_start_driver_open_database(qFi->driver, qFi->database);
+ db_init_string(&table_name);
+ db_set_string(&table_name, qFi->table);
+ if (db_describe_table(driver, &table_name, &table) != DB_OK)
+ G_fatal_error(_("Unable to describe table <%s>"),
+ qFi->table);
+
+ fncols = db_get_table_number_of_columns(table);
+ for (col = 0; col < fncols; col++) {
+ column = db_get_table_column(table, col);
+ colname = db_get_column_name(column);
+ if (strcmp(options.qcol, colname) == 0) {
+ col_sqltype[0] = db_get_column_sqltype(column);
+ qlength = db_get_column_length(column);
+ break;
+ }
+ }
+ db_close_database_shutdown_driver(driver);
+ driver = NULL;
+ db_free_string(&table_name);
+ break;
+ }
+
+ /* check if columns exist */
+ create_col[0] = create_col[1] = create_col[2] = create_col[3] = 0;
+ create_cols = 0;
+ driver = db_start_driver_open_database(Fi->driver, Fi->database);
+ db_init_string(&table_name);
+ db_set_string(&table_name, Fi->table);
+ if (db_describe_table(driver, &table_name, &table) != DB_OK)
+ G_fatal_error(_("Unable to describe table <%s>"),
+ qFi->table);
+
+ fncols = db_get_table_number_of_columns(table);
+ for (col = 0; col < ncols; col++) {
+ int col_exists = 0;
+
+ if (options.col[col] == NULL)
+ G_fatal_error(_("Missing column name for input column number %d"), col + 1);
+
+ for (icol = 0; icol < fncols; icol++) {
+ column = db_get_table_column(table, icol);
+ colname = db_get_column_name(column);
+ if (colname == NULL)
+ G_fatal_error(_("Missing column name for table column number %d"), col + 1);
+ if (strcmp(options.col[col], colname) == 0) {
+ int isqltype;
+
+ col_exists = 1;
+ isqltype = db_get_column_sqltype(column);
+
+ if (isqltype != col_sqltype[col]) {
+ int ctype1, ctype2;
+
+ ctype1 = db_sqltype_to_Ctype(isqltype);
+ ctype2 = db_sqltype_to_Ctype(col_sqltype[col]);
+
+ if (ctype1 == ctype2) {
+ G_warning(_("Existing column <%s> has a different but maybe compatible type"),
+ options.col[col]);
+ }
+ else {
+ G_fatal_error(_("Existing column <%s> has the wrong type"),
+ options.col[col]);
+ }
+ }
+
+ G_warning(_("Values in column <%s> will be overwritten"),
+ options.col[col]);
+
+ break;
+ }
+ }
+ if (!col_exists) {
+ create_col[col] = 1;
+ create_cols = 1;
+ }
+ }
+ db_close_database_shutdown_driver(driver);
+ driver = NULL;
+ db_free_string(&table_name);
+
+ /* create columns if not existing */
+ if (create_cols) {
+ char sqlbuf[4096];
+ dbString stmt;
+
+ db_init_string(&stmt);
+ driver = db_start_driver_open_database(Fi->driver, Fi->database);
+ db_begin_transaction(driver);
+ for (col = 0; col < ncols; col++) {
+ if (!create_col[col])
+ continue;
+
+ if (col_sqltype[col] == DB_SQL_TYPE_INTEGER) {
+ sprintf(sqlbuf, "ALTER TABLE %s ADD COLUMN %s integer",
+ Fi->table, options.col[col]);
+ }
+ else if (col_sqltype[col] == DB_SQL_TYPE_DOUBLE_PRECISION ||
+ col_sqltype[col] == DB_SQL_TYPE_REAL) {
+ sprintf(sqlbuf, "ALTER TABLE %s ADD COLUMN %s double precision",
+ Fi->table, options.col[col]);
+ }
+ else if (col_sqltype[col] == DB_SQL_TYPE_CHARACTER) {
+ if (qlength > 0) {
+ sprintf(sqlbuf, "ALTER TABLE %s ADD COLUMN %s varchar(%d)",
+ Fi->table, options.col[col], qlength);
+ }
+ else {
+ sprintf(sqlbuf, "ALTER TABLE %s ADD COLUMN %s text",
+ Fi->table, options.col[col]);
+ }
+ }
+ else if (col_sqltype[col] == DB_SQL_TYPE_TEXT) {
+ sprintf(sqlbuf, "ALTER TABLE %s ADD COLUMN %s text",
+ Fi->table, options.col[col]);
+ }
+ else if (col_sqltype[col] == DB_SQL_TYPE_DATE) {
+ sprintf(sqlbuf, "ALTER TABLE %s ADD COLUMN %s date",
+ Fi->table, options.col[col]);
+ }
+ else if (col_sqltype[col] == DB_SQL_TYPE_TIME) {
+ sprintf(sqlbuf, "ALTER TABLE %s ADD COLUMN %s time",
+ Fi->table, options.col[col]);
+ }
+ else {
+ sprintf(sqlbuf, "ALTER TABLE %s ADD COLUMN %s %s",
+ Fi->table, options.col[col],
+ db_sqltype_name(col_sqltype[col]));
+ }
+ db_set_string(&stmt, sqlbuf);
+ if (db_execute_immediate(driver, &stmt) != DB_OK) {
+ G_fatal_error(_("Unable to create column <%s>"),
+ options.col[col]);
+ }
+ }
+ db_commit_transaction(driver);
+ db_close_database_shutdown_driver(driver);
+ db_free_string(&stmt);
+ }
+ }
+
/* allocate array for values */
/* (+1 is for cat -1 (no category) reported at the end ) */
findex = Vect_cidx_get_field_index(&Map, options.field);
Modified: grass/trunk/vector/v.to.db/query.c
===================================================================
--- grass/trunk/vector/v.to.db/query.c 2018-09-03 20:04:40 UTC (rev 73235)
+++ grass/trunk/vector/v.to.db/query.c 2018-09-03 20:17:12 UTC (rev 73236)
@@ -92,7 +92,7 @@
/* Query the database for each category */
G_message(_("Querying database... "));
for (i = 0; i < vstat.rcat; i++) {
- int j, ctype, nrows, more;
+ int ctype, nrows, more;
char buf[2000];
dbCursor cursor;
dbTable *table;
More information about the grass-commit
mailing list