copy_tab.c 15 KB

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