13
#include <grass/gis.h>
14
#include <grass/dbmi.h>
15
#include <grass/form.h>
17
/* Structure to store column names and values */
25
static char *Drvname, *Dbname, *Tblname, *Key;
27
static COLUMN *Columns = NULL;
28
static int allocatedRows = 0; /* allocated space */
31
/* Start new sql update */
32
int reset_values(ClientData cdata, Tcl_Interp * interp, int argc,
44
int set_value(ClientData cdata, Tcl_Interp * interp, int argc, char *argv[])
46
G_debug(2, "set_value(): %s %s", argv[1], argv[2]);
48
if (strcmp(argv[1], F_DRIVER_FNAME) == 0) {
49
Drvname = G_store(argv[2]);
51
else if (strcmp(argv[1], F_DATABASE_FNAME) == 0) {
52
Dbname = G_store(argv[2]);
54
else if (strcmp(argv[1], F_TABLE_FNAME) == 0) {
55
Tblname = G_store(argv[2]);
57
else if (strcmp(argv[1], F_KEY_FNAME) == 0) {
58
Key = G_store(argv[2]);
61
if (nRows == allocatedRows) {
64
(COLUMN *) G_realloc(Columns,
65
(allocatedRows) * sizeof(COLUMN));
67
Columns[nRows].name = G_store(argv[1]);
68
Columns[nRows].value = G_store(argv[2]);
75
/* Update table, use the data previously stored by set_value() */
76
int submit(ClientData cdata, Tcl_Interp * interp, int argc, char *argv[])
78
int i, first, ncols, found, col, sqltype, keyval = 0, ret;
80
dbString sql, table_name, strval;
86
G_debug(2, "submit()");
89
db_init_string(&table_name);
90
db_init_string(&strval);
92
/* Check if all internal values are set */
93
if (Drvname == NULL || Dbname == NULL || Tblname == NULL || Key == NULL) {
94
G_warning("db connection was not set by form");
95
sprintf(buf, "set submit_msg \"db connection was not set by form.\"");
96
Tcl_Eval(interp, buf);
97
Tcl_Eval(interp, "set submit_result 0");
101
/* Get column types */
102
G_debug(2, "Open driver");
103
driver = db_start_driver(Drvname);
104
if (driver == NULL) {
105
G_warning("Cannot open driver");
106
sprintf(buf, "set submit_msg \"Cannot open driver '%s'\"", Drvname);
107
Tcl_Eval(interp, buf);
108
Tcl_Eval(interp, "set submit_result 0");
111
G_debug(2, "Driver opened");
113
db_init_handle(&handle);
114
db_set_handle(&handle, Dbname, NULL);
115
G_debug(2, "Open database");
116
if (db_open_database(driver, &handle) != DB_OK) {
117
G_warning("Cannot open database");
118
db_shutdown_driver(driver);
120
"set submit_msg \"Cannot open database '%s' by driver '%s'\"",
123
Tcl_Eval(interp, buf);
124
Tcl_Eval(interp, "set submit_result 0");
127
G_debug(2, "Database opened");
129
db_set_string(&table_name, Tblname);
130
if (db_describe_table(driver, &table_name, &table) != DB_OK) {
131
G_warning("Cannot describe table");
132
db_shutdown_driver(driver);
133
db_close_database(driver);
134
sprintf(buf, "set submit_msg \"Cannot describe table '%s'\"",
136
Tcl_Eval(interp, buf);
137
Tcl_Eval(interp, "set submit_result 0");
140
ncols = db_get_table_number_of_columns(table);
142
/* For each column get ctype */
143
for (i = 0; i < nRows; i++) {
145
for (col = 0; col < ncols; col++) {
147
if (G_strcasecmp(Columns[i].name, Key) == 0) {
148
keyval = atoi(Columns[i].value);
150
column = db_get_table_column(table, col);
151
if (G_strcasecmp(db_get_column_name(column), Columns[i].name) ==
153
sqltype = db_get_column_sqltype(column);
154
Columns[i].ctype = db_sqltype_to_Ctype(sqltype);
159
if (!found && (G_strcasecmp(Columns[i].name, F_ENCODING) != 0)) {
160
G_warning("Cannot find column type");
161
db_close_database(driver);
162
db_shutdown_driver(driver);
163
sprintf(buf, "set submit_msg \"Cannot find column type\"");
164
Tcl_Eval(interp, buf);
165
Tcl_Eval(interp, "set submit_result 0");
170
/* Construct update statement */
171
sprintf(buf, "update %s set ", Tblname);
172
db_set_string(&sql, buf);
175
for (i = 0; i < nRows; i++) {
176
G_debug(3, "Index = %d of %d Name = %s, Key = %s", i, nRows,
177
Columns[i].name, Key);
178
if (G_strcasecmp(Columns[i].name, Key) == 0)
181
if (G_strcasecmp(Columns[i].name, F_ENCODING) == 0) {
183
G_debug(3, "GRASS_DB_ENCODING env-var is '%s', col val is '%s'",
184
G__getenv("GRASS_DB_ENCODING"), Columns[i].value);
186
if ((strlen(Columns[i].value) == 0) ||
187
G_strcasecmp(Columns[i].value,
188
G__getenv("GRASS_DB_ENCODING")) == 0)
191
G_setenv("GRASS_DB_ENCODING", Columns[i].value);
192
G_debug(3, "Set env var GRASS_DB_ENCODING to '%s'",
194
if (Tcl_SetSystemEncoding(interp, Columns[i].value) ==
197
("Could not set Tcl system encoding to '%s' (%s)",
198
Columns[i].value, Tcl_GetStringResult(interp));
205
db_append_string(&sql, ", ");
207
if (strlen(Columns[i].value) == 0) {
208
sprintf(buf, "%s = null", Columns[i].name);
211
if (Columns[i].ctype == DB_C_TYPE_INT ||
212
Columns[i].ctype == DB_C_TYPE_DOUBLE) {
213
sprintf(buf, "%s = %s", Columns[i].name, Columns[i].value);
216
memset(buf, '\0', strlen(buf));
217
ret = Tcl_UtfToExternal(interp,
218
Tcl_GetEncoding(interp,
220
("GRASS_DB_ENCODING")),
222
strlen(Columns[i].value), 0, NULL,
223
buf, 2000, NULL, NULL, NULL);
226
G_warning("Could not convert UTF to external.");
227
db_set_string(&strval, Columns[i].value);
230
db_set_string(&strval, buf);
233
db_double_quote_string(&strval);
234
sprintf(buf, "%s = '%s'", Columns[i].name,
235
db_get_string(&strval));
238
db_append_string(&sql, buf);
242
sprintf(buf, " where %s = %d", Key, keyval);
243
db_append_string(&sql, buf);
245
G_debug(2, "SQL: %s", db_get_string(&sql));
248
ret = db_execute_immediate(driver, &sql);
250
db_close_database(driver);
251
db_shutdown_driver(driver);
254
G_warning("Cannot update table");
255
Tcl_VarEval(interp, "set submit_msg \"Cannot update table:\n",
256
db_get_error_msg(), "\"", NULL);
257
Tcl_Eval(interp, "set submit_result 0");
260
Tcl_Eval(interp, "set submit_msg \"Record successfully updated\"");
261
Tcl_Eval(interp, "set submit_result 1");
270
int Tcl_AppInit(Tcl_Interp * interp)
272
if (Tcl_Init(interp) == TCL_ERROR)
275
if (Tk_Init(interp) == TCL_ERROR)
278
Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit);
281
* Call Tcl_CreateCommand for application-specific commands, if
282
* they weren't already created by the init procedures called above.
285
Tcl_CreateCommand(interp, "submit", (Tcl_CmdProc *) submit,
286
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
287
Tcl_CreateCommand(interp, "set_value",
288
(Tcl_CmdProc *) set_value,
289
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
290
Tcl_CreateCommand(interp, "reset_values",
291
(Tcl_CmdProc *) reset_values,
292
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
294
* Specify a user-specific startup file to invoke if the application
295
* is run interactively. Typically the startup file is "~/.apprc"
296
* where "app" is the name of the application. If this line is deleted
297
* then no user-specific startup file will be run under any conditions.
300
Tcl_SetVar(interp, "tcl_rcFileName", "~/.grassformrc", TCL_GLOBAL_ONLY);
304
int main(int argc, char *argv[])
307
G_debug(2, "Form: main()");
309
Tk_Main(argc, argv, Tcl_AppInit);