123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- /****************************************************************************
- *
- * MODULE: db.select
- * AUTHOR(S): Radim Blazek <radim.blazek gmail.com> (original contributor)
- * Huidae Cho <grass4u gmail.com>,
- * Glynn Clements <glynn gclements.plus.com>,
- * Jachym Cepicky <jachym les-ejk.cz>,
- * Markus Neteler <neteler itc.it>
- * Stephan Holl
- * PURPOSE: Process one sql select statement
- * COPYRIGHT: (C) 2002-2010, 2013 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 <string.h>
- #include <errno.h>
- #include <grass/gis.h>
- #include <grass/dbmi.h>
- #include <grass/glocale.h>
- #include "local_proto.h"
- struct {
- char *driver, *database, *table, *sql, *fs, *vs, *nv, *input, *output;
- int c, d, h, test_only;
- } parms;
- /* function prototypes */
- static void parse_command_line(int, char **);
- static int sel(dbDriver *, dbString *);
- static int get_stmt(FILE *, dbString *);
- static int stmt_is_empty(dbString *);
- int main(int argc, char **argv)
- {
- dbString stmt;
- dbDriver *driver;
- dbHandle handle;
- int stat;
- FILE *fd;
- parse_command_line(argc, argv);
- if (parms.table) {
- if (!db_table_exists(parms.driver, parms.database, parms.table)) {
- G_warning(_("Table <%s> not found in database <%s> using driver <%s>"),
- parms.table, parms.database, parms.driver);
- exit(EXIT_FAILURE);
- }
- }
- /* read from file or stdin ? */
- if (parms.input && strcmp(parms.input, "-") != 0) {
- fd = fopen(parms.input, "r");
- if (fd == NULL) {
- G_fatal_error(_("Unable to open file <%s>: %s"),
- parms.input, strerror(errno));
- }
- }
- else
- fd = stdin;
- /* open DB connection */
- db_init_string(&stmt);
- driver = db_start_driver(parms.driver);
- if (driver == NULL) {
- G_fatal_error(_("Unable to start driver <%s>"), parms.driver);
- }
- db_init_handle(&handle);
- db_set_handle(&handle, parms.database, NULL);
- if (db_open_database(driver, &handle) != DB_OK)
- G_fatal_error(_("Unable to open database <%s>"), parms.database);
- db_set_error_handler_driver(driver);
-
- /* check for sql, table, and input */
- if (parms.sql) {
- /* parms.sql */
- db_set_string(&stmt, parms.sql);
- stat = sel(driver, &stmt);
- }
- else if (parms.table) {
- /* parms.table */
- db_set_string(&stmt, "SELECT * FROM ");
- db_append_string(&stmt, parms.table);
- stat = sel(driver, &stmt);
- }
- else { /* -> parms.input */
- stat = DB_OK;
- while (stat == DB_OK && get_stmt(fd, &stmt)) {
- if (!stmt_is_empty(&stmt))
- stat = sel(driver, &stmt);
- }
- }
- if (parms.test_only)
- G_verbose_message(_("Test %s."), stat ? _("failed") : _("succeeded"));
- db_close_database(driver);
- db_shutdown_driver(driver);
- exit(stat == DB_OK ? EXIT_SUCCESS : EXIT_FAILURE);
- }
- int sel(dbDriver * driver, dbString * stmt)
- {
- dbCursor cursor;
- dbTable *table;
- dbColumn *column;
- dbValue *value;
- dbString value_string;
- int col, ncols;
- int more;
- if (db_open_select_cursor(driver, stmt, &cursor, DB_SEQUENTIAL) != DB_OK)
- return DB_FAILED;
- if (parms.test_only)
- return DB_OK;
- table = db_get_cursor_table(&cursor);
- ncols = db_get_table_number_of_columns(table);
- if (parms.d) {
- for (col = 0; col < ncols; col++) {
- column = db_get_table_column(table, col);
- print_column_definition(column);
- }
- return DB_OK;
- }
- if (parms.output && strcmp(parms.output, "-") != 0) {
- if (NULL == freopen(parms.output, "w", stdout)) {
- G_fatal_error(_("Unable to open file <%s> for writing"), parms.output);
- }
- }
-
- db_init_string(&value_string);
- /* column names if horizontal output */
- if (parms.h && parms.c) {
- for (col = 0; col < ncols; col++) {
- column = db_get_table_column(table, col);
- if (col)
- fprintf(stdout, "%s", parms.fs);
- fprintf(stdout, "%s", db_get_column_name(column));
- }
- fprintf(stdout, "\n");
- }
- /* fetch the data */
- while (TRUE) {
- if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
- return DB_FAILED;
- if (!more)
- break;
- for (col = 0; col < ncols; col++) {
- column = db_get_table_column(table, col);
- value = db_get_column_value(column);
- db_convert_column_value_to_string(column, &value_string);
- if (parms.c && !parms.h)
- fprintf(stdout, "%s%s", db_get_column_name(column), parms.fs);
- if (col && parms.h)
- fprintf(stdout, "%s", parms.fs);
- if (parms.nv && db_test_value_isnull(value))
- fprintf(stdout, "%s", parms.nv);
- else
- fprintf(stdout, "%s", db_get_string(&value_string));
- if (!parms.h)
- fprintf(stdout, "\n");
- }
- if (parms.h)
- fprintf(stdout, "\n");
- else if (parms.vs)
- fprintf(stdout, "%s\n", parms.vs);
- }
- return DB_OK;
- }
- void parse_command_line(int argc, char **argv)
- {
- struct Option *driver, *database, *table, *sql,
- *fs, *vs, *nv, *input, *output;
- struct Flag *c, *d, *v, *flag_test;
- struct GModule *module;
- const char *drv, *db;
- /* Initialize the GIS calls */
- G_gisinit(argv[0]);
- sql = G_define_standard_option(G_OPT_DB_SQL);
- sql->guisection = _("Query");
- input = G_define_standard_option(G_OPT_F_INPUT);
- input->required = NO;
- input->label = _("Name of file containing SQL select statement(s)");
- input->description = _("'-' for standard input");
- input->guisection = _("Query");
-
- table = G_define_standard_option(G_OPT_DB_TABLE);
- table->description = _("Name of table to query");
- table->guisection = _("Query");
- driver = G_define_standard_option(G_OPT_DB_DRIVER);
- driver->options = db_list_drivers();
- if ((drv = db_get_default_driver_name()))
- driver->answer = (char *) drv;
- driver->guisection = _("Connection");
- database = G_define_standard_option(G_OPT_DB_DATABASE);
- if ((db = db_get_default_database_name()))
- database->answer = (char *) db;
- database->guisection = _("Connection");
-
- fs = G_define_standard_option(G_OPT_F_SEP);
- fs->guisection = _("Format");
- vs = G_define_standard_option(G_OPT_F_SEP);
- vs->key = "vertical_separator";
- vs->label = _("Vertical record separator (requires -v flag)");
- vs->answer = NULL;
- vs->guisection = _("Format");
- nv = G_define_standard_option(G_OPT_M_NULL_VALUE);
- nv->guisection = _("Format");
- output = G_define_standard_option(G_OPT_F_OUTPUT);
- output->required = NO;
- output->description =
- _("Name for output file (if omitted or \"-\" output to stdout)");
-
- c = G_define_flag();
- c->key = 'c';
- c->description = _("Do not include column names in output");
- c->guisection = _("Format");
- d = G_define_flag();
- d->key = 'd';
- d->description = _("Describe query only (don't run it)");
- d->guisection = _("Query");
- v = G_define_flag();
- v->key = 'v';
- v->description = _("Vertical output (instead of horizontal)");
- v->guisection = _("Format");
- flag_test = G_define_flag();
- flag_test->key = 't';
- flag_test->description = _("Only test query, do not execute");
- flag_test->guisection = _("Query");
- /* Set description */
- module = G_define_module();
- G_add_keyword(_("database"));
- G_add_keyword(_("attribute table"));
- G_add_keyword(_("SQL"));
- module->label = _("Selects data from attribute table.");
- module->description = _("Performs SQL query statement(s).");
- if (G_parser(argc, argv))
- exit(EXIT_FAILURE);
- parms.driver = driver->answer;
- parms.database = database->answer;
- parms.table = table->answer;
- parms.sql = sql->answer;
- parms.fs = G_option_to_separator(fs);
- parms.vs = '\0';
- if (vs->answer)
- parms.vs = G_option_to_separator(vs);
- parms.nv = nv->answer;
- parms.input = input->answer;
- parms.output = output->answer;
- if (!c->answer)
- parms.c = TRUE;
- else
- parms.c = FALSE;
- parms.d = d->answer;
- if (!v->answer)
- parms.h = TRUE;
- else
- parms.h = FALSE;
- parms.test_only = flag_test->answer;
-
- if (parms.input && *parms.input == 0) {
- G_usage();
- exit(EXIT_FAILURE);
- }
-
- if (!parms.input && !parms.sql && !parms.table)
- G_fatal_error(_("You must provide one of these options: <%s>, <%s>, or <%s>"),
- sql->key, input->key, table->key);
- }
- int get_stmt(FILE * fd, dbString * stmt)
- {
- char buf[DB_SQL_MAX], buf2[DB_SQL_MAX];
- size_t len;
-
- db_zero_string(stmt);
-
- if (G_getl2(buf, sizeof(buf), fd) == 0)
- return 0;
-
- strcpy(buf2, buf);
- G_chop(buf2);
- len = strlen(buf2);
-
- if (buf2[len - 1] == ';') { /* end of statement */
- buf2[len - 1] = 0; /* truncate ';' */
- }
-
- db_set_string(stmt, buf);
-
- return 1;
- }
- int stmt_is_empty(dbString * stmt)
- {
- char dummy[2];
- return (sscanf(db_get_string(stmt), "%1s", dummy) != 1);
- }
|