copy_tab.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /*!
  2. * \file db/dbmi_client/copy_tab.c
  3. *
  4. * \brief DBMI Library (client) - copy table
  5. *
  6. * (C) 1999-2008 by the GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public
  9. * License (>=v2). Read the file COPYING that comes with GRASS
  10. * for details.
  11. *
  12. * \author Joel Jones (CERL/UIUC), Radim Blazek
  13. */
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <grass/dbmi.h>
  17. #include <grass/glocale.h>
  18. #include "macros.h"
  19. static int cmp(const void *pa, const void *pb)
  20. {
  21. int *p1 = (int *)pa;
  22. int *p2 = (int *)pb;
  23. if (*p1 < *p2)
  24. return -1;
  25. if (*p1 > *p2)
  26. return 1;
  27. return 0;
  28. }
  29. /*!
  30. \brief Copy table, used by various db_copy_table*
  31. Use either 'where' or 'select' or 'selcol'+'ivals'+'nvals' but
  32. never more than one.
  33. Warning: driver opened as second must be closed as first, otherwise
  34. it hangs, not sure why.
  35. \param from_dvrname name of driver from table is copied
  36. \param from_dbname name of database from table is copied
  37. \param from_tbl_name name of table to be copied
  38. \param to_dvrname name of driver to - where table is copied to
  39. \param to_dbname name of database to - where table is copied to
  40. \param to_dbname name of copied table
  41. \param where WHERE SQL condition (without where key word) or NULL
  42. \param select full select statement
  43. \param selcol name of column used to select records by values in ivals or NULL
  44. \param ivals pointer to array of integer values or NULL
  45. \param nvals number of values in ivals
  46. \return DB_OK on success
  47. \return DB_FAILED on failure
  48. */
  49. int db__copy_table(const char *from_drvname, const char *from_dbname,
  50. const char *from_tblname, const char *to_drvname,
  51. const char *to_dbname, const char *to_tblname,
  52. const char *where, const char *select, const char *selcol,
  53. int *ivals, int nvals)
  54. {
  55. int col, ncols, sqltype, ctype, more, selcol_found;
  56. char buf[1000];
  57. int *ivalues;
  58. dbHandle from_handle, to_handle;
  59. dbString tblname, sql;
  60. dbString value_string;
  61. dbString *tblnames;
  62. dbTable *table, *out_table;
  63. dbCursor cursor;
  64. dbColumn *column;
  65. dbValue *value;
  66. const char *colname;
  67. dbDriver *from_driver, *to_driver;
  68. int count, i;
  69. G_debug(3, "db_copy_table():\n from driver = %s, db = %s, table = %s\n"
  70. " to driver = %s, db = %s, table = %s, where = %s, select = %s",
  71. from_drvname, from_dbname, from_tblname, to_drvname, to_dbname,
  72. to_tblname, where, select);
  73. db_init_handle(&from_handle);
  74. db_init_handle(&to_handle);
  75. db_init_string(&tblname);
  76. db_init_string(&sql);
  77. db_init_string(&value_string);
  78. /* Make a copy of input values and sort it */
  79. if (ivals) {
  80. ivalues = (int *)G_malloc(nvals * sizeof(int));
  81. memcpy(ivalues, ivals, nvals * sizeof(int));
  82. qsort((void *)ivalues, nvals, sizeof(int), cmp);
  83. }
  84. /* Open input driver and database */
  85. from_driver = db_start_driver(from_drvname);
  86. if (from_driver == NULL) {
  87. G_warning(_("Unable to start driver <%s>"), from_drvname);
  88. return DB_FAILED;
  89. }
  90. db_set_handle(&from_handle, from_dbname, NULL);
  91. if (db_open_database(from_driver, &from_handle) != DB_OK) {
  92. G_warning(_("Unable to open database <%s> by driver <%s>"),
  93. from_drvname, from_dbname);
  94. db_close_database_shutdown_driver(from_driver);
  95. return DB_FAILED;
  96. }
  97. /* Open output driver and database */
  98. if (strcmp(from_drvname, to_drvname) == 0
  99. && strcmp(from_dbname, to_dbname) == 0) {
  100. G_debug(3, "Use the same driver");
  101. to_driver = from_driver;
  102. }
  103. else {
  104. to_driver = db_start_driver(to_drvname);
  105. if (to_driver == NULL) {
  106. G_warning(_("Unable to start driver <%s>"), to_drvname);
  107. db_close_database_shutdown_driver(from_driver);
  108. return DB_FAILED;
  109. }
  110. db_set_handle(&to_handle, to_dbname, NULL);
  111. if (db_open_database(to_driver, &to_handle) != DB_OK) {
  112. G_warning(_("Unable to open database <%s> by driver <%s>"),
  113. to_drvname, to_dbname);
  114. db_close_database_shutdown_driver(to_driver);
  115. if (from_driver != to_driver) {
  116. db_close_database_shutdown_driver(from_driver);
  117. }
  118. return DB_FAILED;
  119. }
  120. }
  121. db_begin_transaction(to_driver);
  122. /* Because in SQLite3 an opened cursor is no more valid
  123. if 'schema' is modified (create table), we have to open
  124. cursor twice */
  125. /* test if the table exists */
  126. if (db_list_tables(to_driver, &tblnames, &count, 0) != DB_OK) {
  127. G_warning(_("Unable to get list tables in database <%s>"),
  128. to_dbname);
  129. db_close_database_shutdown_driver(to_driver);
  130. if (from_driver != to_driver)
  131. db_close_database_shutdown_driver(from_driver);
  132. return DB_FAILED;
  133. }
  134. for (i = 0; i < count; i++) {
  135. const char *tblname = db_get_string(&tblnames[i]);
  136. if (strcmp(to_tblname, tblname) == 0) {
  137. G_warning(_("Table <%s> already exists in database <%s>"),
  138. to_tblname, to_dbname);
  139. db_close_database_shutdown_driver(to_driver);
  140. if (from_driver != to_driver)
  141. db_close_database_shutdown_driver(from_driver);
  142. return DB_FAILED;
  143. }
  144. }
  145. /* Create new table */
  146. /* Open cursor for data structure */
  147. if (select) {
  148. db_set_string(&sql, select);
  149. /* TODO!: cannot use this because it will not work if a query
  150. * ends with 'group by' for example */
  151. /*
  152. tmp = strdup ( select );
  153. G_tolcase ( tmp );
  154. if ( !strstr( tmp,"where") )
  155. {
  156. db_append_string ( &sql, " where 0 = 1");
  157. }
  158. else
  159. {
  160. db_append_string ( &sql, " and 0 = 1");
  161. }
  162. free (tmp);
  163. */
  164. }
  165. else {
  166. db_set_string(&sql, "select * from ");
  167. db_append_string(&sql, from_tblname);
  168. db_append_string(&sql, " where 0 = 1"); /* to get no data */
  169. }
  170. G_debug(3, db_get_string(&sql));
  171. if (db_open_select_cursor(from_driver, &sql, &cursor, DB_SEQUENTIAL) !=
  172. DB_OK) {
  173. G_warning(_("Unable to open select cursor: '%s'"),
  174. db_get_string(&sql));
  175. db_close_database_shutdown_driver(to_driver);
  176. if (from_driver != to_driver) {
  177. db_close_database_shutdown_driver(from_driver);
  178. }
  179. return DB_FAILED;
  180. }
  181. G_debug(3, "Select cursor opened");
  182. table = db_get_cursor_table(&cursor);
  183. ncols = db_get_table_number_of_columns(table);
  184. G_debug(3, "ncols = %d", ncols);
  185. out_table = db_alloc_table(ncols);
  186. db_set_table_name(out_table, to_tblname);
  187. selcol_found = 0;
  188. for (col = 0; col < ncols; col++) {
  189. dbColumn *out_column;
  190. column = db_get_table_column(table, col);
  191. colname = db_get_column_name(column);
  192. sqltype = db_get_column_sqltype(column);
  193. ctype = db_sqltype_to_Ctype(sqltype);
  194. G_debug(3, "%s (%s)", colname, db_sqltype_name(sqltype));
  195. out_column = db_get_table_column(out_table, col);
  196. if (selcol && G_strcasecmp(colname, selcol) == 0) {
  197. if (ctype != DB_C_TYPE_INT)
  198. G_fatal_error(_("Column <%s> is not integer"),
  199. colname);
  200. selcol_found = 1;
  201. }
  202. db_set_column_name(out_column, db_get_column_name(column));
  203. db_set_column_description(out_column,
  204. db_get_column_description(column));
  205. db_set_column_sqltype(out_column, db_get_column_sqltype(column));
  206. db_set_column_length(out_column, db_get_column_length(column));
  207. db_set_column_precision(out_column, db_get_column_precision(column));
  208. db_set_column_scale(out_column, db_get_column_scale(column));
  209. }
  210. db_close_cursor(&cursor);
  211. if (selcol && !selcol_found)
  212. G_fatal_error(_("Column <%s> not found"), selcol);
  213. if (db_create_table(to_driver, out_table) != DB_OK) {
  214. G_warning(_("Unable to create table <%s>"),
  215. to_tblname);
  216. db_close_database_shutdown_driver(to_driver);
  217. if (from_driver != to_driver) {
  218. db_close_database_shutdown_driver(from_driver);
  219. }
  220. return DB_FAILED;
  221. }
  222. /* Open cursor with data */
  223. if (select) {
  224. db_set_string(&sql, select);
  225. }
  226. else {
  227. db_set_string(&sql, "select * from ");
  228. db_append_string(&sql, from_tblname);
  229. if (where) {
  230. db_append_string(&sql, " where ");
  231. db_append_string(&sql, where);
  232. }
  233. }
  234. G_debug(3, db_get_string(&sql));
  235. if (db_open_select_cursor(from_driver, &sql, &cursor, DB_SEQUENTIAL) !=
  236. DB_OK) {
  237. G_warning(_("Unable to open select cursor: '%s'"),
  238. db_get_string(&sql));
  239. db_close_database_shutdown_driver(to_driver);
  240. if (from_driver != to_driver) {
  241. db_close_database_shutdown_driver(from_driver);
  242. }
  243. return DB_FAILED;
  244. }
  245. G_debug(3, "Select cursor opened");
  246. table = db_get_cursor_table(&cursor);
  247. ncols = db_get_table_number_of_columns(table);
  248. G_debug(3, "ncols = %d", ncols);
  249. /* Copy all rows */
  250. while (1) {
  251. int select;
  252. if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
  253. G_warning(_("Unable to fetch data from table <%s>"),
  254. from_tblname);
  255. db_close_cursor(&cursor);
  256. db_close_database_shutdown_driver(to_driver);
  257. if (from_driver != to_driver) {
  258. db_close_database_shutdown_driver(from_driver);
  259. }
  260. return DB_FAILED;
  261. }
  262. if (!more)
  263. break;
  264. sprintf(buf, "insert into %s values ( ", to_tblname);
  265. db_set_string(&sql, buf);
  266. select = 1;
  267. for (col = 0; col < ncols; col++) {
  268. column = db_get_table_column(table, col);
  269. colname = db_get_column_name(column);
  270. sqltype = db_get_column_sqltype(column);
  271. ctype = db_sqltype_to_Ctype(sqltype);
  272. value = db_get_column_value(column);
  273. if (selcol && G_strcasecmp(colname, selcol) == 0) {
  274. if (db_test_value_isnull(value))
  275. continue;
  276. if (!bsearch(&(value->i), ivalues, nvals, sizeof(int), cmp)) {
  277. select = 0;
  278. break;
  279. }
  280. }
  281. if (col > 0)
  282. db_append_string(&sql, ", ");
  283. db_convert_value_to_string(value, sqltype, &value_string);
  284. switch (ctype) {
  285. case DB_C_TYPE_STRING:
  286. case DB_C_TYPE_DATETIME:
  287. if (db_test_value_isnull(value)) {
  288. db_append_string(&sql, "null");
  289. }
  290. else {
  291. db_double_quote_string(&value_string);
  292. db_append_string(&sql, "'");
  293. db_append_string(&sql, db_get_string(&value_string));
  294. db_append_string(&sql, "'");
  295. }
  296. break;
  297. case DB_C_TYPE_INT:
  298. case DB_C_TYPE_DOUBLE:
  299. if (db_test_value_isnull(value)) {
  300. db_append_string(&sql, "null");
  301. }
  302. else {
  303. db_append_string(&sql, db_get_string(&value_string));
  304. }
  305. break;
  306. default:
  307. G_warning(_("Unknown column type (column <%s>)"),
  308. colname);
  309. db_close_cursor(&cursor);
  310. db_close_database_shutdown_driver(to_driver);
  311. if (from_driver != to_driver) {
  312. db_close_database_shutdown_driver(from_driver);
  313. }
  314. return DB_FAILED;
  315. }
  316. }
  317. if (!select)
  318. continue;
  319. db_append_string(&sql, ")");
  320. G_debug(3, db_get_string(&sql));
  321. if (db_execute_immediate(to_driver, &sql) != DB_OK) {
  322. G_warning("Unable to insert new record: '%s'",
  323. db_get_string(&sql));
  324. db_close_cursor(&cursor);
  325. db_close_database_shutdown_driver(to_driver);
  326. if (from_driver != to_driver) {
  327. db_close_database_shutdown_driver(from_driver);
  328. }
  329. return DB_FAILED;
  330. }
  331. }
  332. if (selcol)
  333. free(ivalues);
  334. G_debug(3, "Table copy OK");
  335. db_close_cursor(&cursor);
  336. db_commit_transaction(to_driver);
  337. db_close_database_shutdown_driver(to_driver);
  338. if (from_driver != to_driver) {
  339. db_close_database_shutdown_driver(from_driver);
  340. }
  341. return DB_OK;
  342. }
  343. /*!
  344. \brief Copy a table
  345. \param from_dvrname name of driver from table is copied
  346. \param from_dbname name of database from table is copied
  347. \param from_tbl_name name of table to be copied
  348. \param to_dvrname name of driver to - where table is copied to
  349. \param to_dbname name of database to - where table is copied to
  350. \param to_dbname name of copied table
  351. \return DB_OK on success
  352. \return DB_FAILED on failure
  353. */
  354. int db_copy_table(const char *from_drvname, const char *from_dbname,
  355. const char *from_tblname, const char *to_drvname,
  356. const char *to_dbname, const char *to_tblname)
  357. {
  358. return db__copy_table(from_drvname, from_dbname, from_tblname,
  359. to_drvname, to_dbname, to_tblname,
  360. NULL, NULL, NULL, NULL, 0);
  361. }
  362. /*!
  363. \brief Copy a table (by where statement)
  364. \param from_dvrname name of driver from table is copied
  365. \param from_dbname name of database from table is copied
  366. \param from_tbl_name name of table to be copied
  367. \param to_dvrname name of driver to - where table is copied to
  368. \param to_dbname name of database to - where table is copied to
  369. \param to_dbname name of copied table
  370. \param where WHERE SQL condition (without where key word)
  371. \return DB_OK on success
  372. \return DB_FAILED on failure
  373. */
  374. int db_copy_table_where(const char *from_drvname, const char *from_dbname,
  375. const char *from_tblname, const char *to_drvname,
  376. const char *to_dbname, const char *to_tblname,
  377. const char *where)
  378. {
  379. return db__copy_table(from_drvname, from_dbname, from_tblname,
  380. to_drvname, to_dbname, to_tblname,
  381. where, NULL, NULL, NULL, 0);
  382. }
  383. /*!
  384. \brief Copy a table (by select statement)
  385. \param from_dvrname name of driver from table is copied
  386. \param from_dbname name of database from table is copied
  387. \param from_tbl_name name of table to be copied
  388. \param to_dvrname name of driver to - where table is copied to
  389. \param to_dbname name of database to - where table is copied to
  390. \param to_dbname name of copied table
  391. \param select full select statement
  392. \return DB_OK on success
  393. \return DB_FAILED on failure
  394. */
  395. int db_copy_table_select(const char *from_drvname, const char *from_dbname,
  396. const char *from_tblname, const char *to_drvname,
  397. const char *to_dbname, const char *to_tblname,
  398. const char *select)
  399. {
  400. return db__copy_table(from_drvname, from_dbname, from_tblname,
  401. to_drvname, to_dbname, to_tblname,
  402. NULL, select, NULL, NULL, 0);
  403. }
  404. /*!
  405. \brief Copy a table (by keys)
  406. \param from_dvrname name of driver from table is copied
  407. \param from_dbname name of database from table is copied
  408. \param from_tbl_name name of table to be copied
  409. \param to_dvrname name of driver to - where table is copied to
  410. \param to_dbname name of database to - where table is copied to
  411. \param to_dbname name of copied table
  412. \param selcol name of column used to select records by values in ivals or NULL
  413. \param ivals pointer to array of integer values or NULL
  414. \param nvals number of values in ivals
  415. \return DB_OK on success
  416. \return DB_FAILED on failure
  417. */
  418. int db_copy_table_by_ints(const char *from_drvname, const char *from_dbname,
  419. const char *from_tblname, const char *to_drvname,
  420. const char *to_dbname, const char *to_tblname,
  421. const char *selcol, int *ivals, int nvals)
  422. {
  423. return db__copy_table(from_drvname, from_dbname, from_tblname,
  424. to_drvname, to_dbname, to_tblname,
  425. NULL, NULL, selcol, ivals, nvals);
  426. }