main.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /****************************************************************************
  2. *
  3. * MODULE: db.select
  4. * AUTHOR(S): Radim Blazek <radim.blazek gmail.com> (original contributor)
  5. * Huidae Cho <grass4u gmail.com>,
  6. * Glynn Clements <glynn gclements.plus.com>,
  7. * Jachym Cepicky <jachym les-ejk.cz>,
  8. * Markus Neteler <neteler itc.it>
  9. * Stephan Holl
  10. * PURPOSE: Process one sql select statement
  11. * COPYRIGHT: (C) 2002-2010, 2013 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General Public
  14. * License (>=v2). Read the file COPYING that comes with GRASS
  15. * for details.
  16. *
  17. *****************************************************************************/
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <errno.h>
  21. #include <grass/gis.h>
  22. #include <grass/dbmi.h>
  23. #include <grass/glocale.h>
  24. #include "local_proto.h"
  25. struct {
  26. char *driver, *database, *table, *sql, *fs, *vs, *nv, *input, *output;
  27. int c, d, h, test_only;
  28. } parms;
  29. /* function prototypes */
  30. static void parse_command_line(int, char **);
  31. static int sel(dbDriver *, dbString *);
  32. static int get_stmt(FILE *, dbString *);
  33. static int stmt_is_empty(dbString *);
  34. int main(int argc, char **argv)
  35. {
  36. dbString stmt;
  37. dbDriver *driver;
  38. dbHandle handle;
  39. int stat;
  40. FILE *fd;
  41. parse_command_line(argc, argv);
  42. if (parms.table) {
  43. if (!db_table_exists(parms.driver, parms.database, parms.table)) {
  44. G_warning(_("Table <%s> not found in database <%s> using driver <%s>"),
  45. parms.table, parms.database, parms.driver);
  46. exit(EXIT_FAILURE);
  47. }
  48. }
  49. /* read from file or stdin ? */
  50. if (parms.input && strcmp(parms.input, "-") != 0) {
  51. fd = fopen(parms.input, "r");
  52. if (fd == NULL) {
  53. G_fatal_error(_("Unable to open file <%s>: %s"),
  54. parms.input, strerror(errno));
  55. }
  56. }
  57. else
  58. fd = stdin;
  59. /* open DB connection */
  60. db_init_string(&stmt);
  61. driver = db_start_driver(parms.driver);
  62. if (driver == NULL) {
  63. G_fatal_error(_("Unable to start driver <%s>"), parms.driver);
  64. }
  65. db_init_handle(&handle);
  66. db_set_handle(&handle, parms.database, NULL);
  67. if (db_open_database(driver, &handle) != DB_OK)
  68. G_fatal_error(_("Unable to open database <%s>"), parms.database);
  69. db_set_error_handler_driver(driver);
  70. /* check for sql, table, and input */
  71. if (parms.sql) {
  72. /* parms.sql */
  73. db_set_string(&stmt, parms.sql);
  74. stat = sel(driver, &stmt);
  75. }
  76. else if (parms.table) {
  77. /* parms.table */
  78. db_set_string(&stmt, "SELECT * FROM ");
  79. db_append_string(&stmt, parms.table);
  80. stat = sel(driver, &stmt);
  81. }
  82. else { /* -> parms.input */
  83. stat = DB_OK;
  84. while (stat == DB_OK && get_stmt(fd, &stmt)) {
  85. if (!stmt_is_empty(&stmt))
  86. stat = sel(driver, &stmt);
  87. }
  88. }
  89. if (parms.test_only)
  90. G_verbose_message(_("Test %s."), stat ? _("failed") : _("succeeded"));
  91. db_close_database(driver);
  92. db_shutdown_driver(driver);
  93. exit(stat == DB_OK ? EXIT_SUCCESS : EXIT_FAILURE);
  94. }
  95. int sel(dbDriver * driver, dbString * stmt)
  96. {
  97. dbCursor cursor;
  98. dbTable *table;
  99. dbColumn *column;
  100. dbValue *value;
  101. dbString value_string;
  102. int col, ncols;
  103. int more;
  104. if (db_open_select_cursor(driver, stmt, &cursor, DB_SEQUENTIAL) != DB_OK)
  105. return DB_FAILED;
  106. if (parms.test_only)
  107. return DB_OK;
  108. table = db_get_cursor_table(&cursor);
  109. ncols = db_get_table_number_of_columns(table);
  110. if (parms.d) {
  111. for (col = 0; col < ncols; col++) {
  112. column = db_get_table_column(table, col);
  113. print_column_definition(column);
  114. }
  115. return DB_OK;
  116. }
  117. if (parms.output && strcmp(parms.output, "-") != 0) {
  118. if (NULL == freopen(parms.output, "w", stdout)) {
  119. G_fatal_error(_("Unable to open file <%s> for writing"), parms.output);
  120. }
  121. }
  122. db_init_string(&value_string);
  123. /* column names if horizontal output */
  124. if (parms.h && parms.c) {
  125. for (col = 0; col < ncols; col++) {
  126. column = db_get_table_column(table, col);
  127. if (col)
  128. fprintf(stdout, "%s", parms.fs);
  129. fprintf(stdout, "%s", db_get_column_name(column));
  130. }
  131. fprintf(stdout, "\n");
  132. }
  133. /* fetch the data */
  134. while (TRUE) {
  135. if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
  136. return DB_FAILED;
  137. if (!more)
  138. break;
  139. for (col = 0; col < ncols; col++) {
  140. column = db_get_table_column(table, col);
  141. value = db_get_column_value(column);
  142. db_convert_column_value_to_string(column, &value_string);
  143. if (parms.c && !parms.h)
  144. fprintf(stdout, "%s%s", db_get_column_name(column), parms.fs);
  145. if (col && parms.h)
  146. fprintf(stdout, "%s", parms.fs);
  147. if (parms.nv && db_test_value_isnull(value))
  148. fprintf(stdout, "%s", parms.nv);
  149. else
  150. fprintf(stdout, "%s", db_get_string(&value_string));
  151. if (!parms.h)
  152. fprintf(stdout, "\n");
  153. }
  154. if (parms.h)
  155. fprintf(stdout, "\n");
  156. else if (parms.vs)
  157. fprintf(stdout, "%s\n", parms.vs);
  158. }
  159. return DB_OK;
  160. }
  161. void parse_command_line(int argc, char **argv)
  162. {
  163. struct Option *driver, *database, *table, *sql,
  164. *fs, *vs, *nv, *input, *output;
  165. struct Flag *c, *d, *v, *flag_test;
  166. struct GModule *module;
  167. const char *drv, *db;
  168. /* Initialize the GIS calls */
  169. G_gisinit(argv[0]);
  170. sql = G_define_standard_option(G_OPT_DB_SQL);
  171. sql->guisection = _("Query");
  172. input = G_define_standard_option(G_OPT_F_INPUT);
  173. input->required = NO;
  174. input->label = _("Name of file containing SQL select statement(s)");
  175. input->description = _("'-' for standard input");
  176. input->guisection = _("Query");
  177. table = G_define_standard_option(G_OPT_DB_TABLE);
  178. table->description = _("Name of table to query");
  179. table->guisection = _("Query");
  180. driver = G_define_standard_option(G_OPT_DB_DRIVER);
  181. driver->options = db_list_drivers();
  182. if ((drv = db_get_default_driver_name()))
  183. driver->answer = (char *) drv;
  184. driver->guisection = _("Connection");
  185. database = G_define_standard_option(G_OPT_DB_DATABASE);
  186. if ((db = db_get_default_database_name()))
  187. database->answer = (char *) db;
  188. database->guisection = _("Connection");
  189. fs = G_define_standard_option(G_OPT_F_SEP);
  190. fs->guisection = _("Format");
  191. vs = G_define_standard_option(G_OPT_F_SEP);
  192. vs->key = "vertical_separator";
  193. vs->label = _("Vertical record separator (requires -v flag)");
  194. vs->answer = NULL;
  195. vs->guisection = _("Format");
  196. nv = G_define_standard_option(G_OPT_M_NULL_VALUE);
  197. nv->guisection = _("Format");
  198. output = G_define_standard_option(G_OPT_F_OUTPUT);
  199. output->required = NO;
  200. output->description =
  201. _("Name for output file (if omitted or \"-\" output to stdout)");
  202. c = G_define_flag();
  203. c->key = 'c';
  204. c->description = _("Do not include column names in output");
  205. c->guisection = _("Format");
  206. d = G_define_flag();
  207. d->key = 'd';
  208. d->description = _("Describe query only (don't run it)");
  209. d->guisection = _("Query");
  210. v = G_define_flag();
  211. v->key = 'v';
  212. v->description = _("Vertical output (instead of horizontal)");
  213. v->guisection = _("Format");
  214. flag_test = G_define_flag();
  215. flag_test->key = 't';
  216. flag_test->description = _("Only test query, do not execute");
  217. flag_test->guisection = _("Query");
  218. /* Set description */
  219. module = G_define_module();
  220. G_add_keyword(_("database"));
  221. G_add_keyword(_("attribute table"));
  222. G_add_keyword(_("SQL"));
  223. module->label = _("Selects data from attribute table.");
  224. module->description = _("Performs SQL query statement(s).");
  225. if (G_parser(argc, argv))
  226. exit(EXIT_FAILURE);
  227. parms.driver = driver->answer;
  228. parms.database = database->answer;
  229. parms.table = table->answer;
  230. parms.sql = sql->answer;
  231. parms.fs = G_option_to_separator(fs);
  232. parms.vs = '\0';
  233. if (vs->answer)
  234. parms.vs = G_option_to_separator(vs);
  235. parms.nv = nv->answer;
  236. parms.input = input->answer;
  237. parms.output = output->answer;
  238. if (!c->answer)
  239. parms.c = TRUE;
  240. else
  241. parms.c = FALSE;
  242. parms.d = d->answer;
  243. if (!v->answer)
  244. parms.h = TRUE;
  245. else
  246. parms.h = FALSE;
  247. parms.test_only = flag_test->answer;
  248. if (parms.input && *parms.input == 0) {
  249. G_usage();
  250. exit(EXIT_FAILURE);
  251. }
  252. if (!parms.input && !parms.sql && !parms.table)
  253. G_fatal_error(_("You must provide one of these options: <%s>, <%s>, or <%s>"),
  254. sql->key, input->key, table->key);
  255. }
  256. int get_stmt(FILE * fd, dbString * stmt)
  257. {
  258. char buf[DB_SQL_MAX], buf2[DB_SQL_MAX];
  259. size_t len;
  260. db_zero_string(stmt);
  261. if (G_getl2(buf, sizeof(buf), fd) == 0)
  262. return 0;
  263. strcpy(buf2, buf);
  264. G_chop(buf2);
  265. len = strlen(buf2);
  266. if (buf2[len - 1] == ';') { /* end of statement */
  267. buf2[len - 1] = 0; /* truncate ';' */
  268. }
  269. db_set_string(stmt, buf);
  270. return 1;
  271. }
  272. int stmt_is_empty(dbString * stmt)
  273. {
  274. char dummy[2];
  275. return (sscanf(db_get_string(stmt), "%1s", dummy) != 1);
  276. }