write_ogr.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. /*!
  2. \file lib/vector/Vlib/write_ogr.c
  3. \brief Vector library - write vector feature (OGR format)
  4. Higher level functions for reading/writing/manipulating vectors.
  5. Inspired by v.out.ogr's code.
  6. \todo OGR version of V2__delete_area_cats_from_cidx_nat()
  7. \todo function to delete corresponding entry in fidx
  8. \todo OGR version of V2__add_area_cats_to_cidx_nat
  9. \todo OGR version of V2__add_line_to_topo_nat
  10. (C) 2009-2011 by the GRASS Development Team
  11. This program is free software under the GNU General Public License
  12. (>=v2). Read the file COPYING that comes with GRASS for details.
  13. \author Martin Landa <landa.martin gmail.com>
  14. */
  15. #include <grass/vector.h>
  16. #include <grass/dbmi.h>
  17. #include <grass/glocale.h>
  18. #ifdef HAVE_OGR
  19. #include <ogr_api.h>
  20. static int sqltype_to_ogrtype(int);
  21. static int write_attributes(dbDriver *, int, const struct field_info *,
  22. OGRLayerH, OGRFeatureH);
  23. static void V2__add_line_to_topo_ogr(struct Map_info *Map, int line,
  24. const struct line_pnts *points,
  25. const struct line_cats *cats)
  26. {
  27. int first, s, i;
  28. int type, area, side;
  29. struct Plus_head *plus;
  30. struct P_line *Line;
  31. struct bound_box box, abox;
  32. G_debug(3, "V2__add_line_to_topo_ogr(): line = %d npoints = %d", line,
  33. points->n_points);
  34. plus = &(Map->plus);
  35. Line = plus->Line[line];
  36. type = Line->type;
  37. if (plus->built >= GV_BUILD_AREAS &&
  38. type == GV_BOUNDARY) {
  39. struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
  40. if (topo->N1 != topo->N2) {
  41. G_warning(_("Boundary is not closed. Skipping."));
  42. return;
  43. }
  44. /* Build new areas/isles */
  45. for (s = 0; s < 2; s++) {
  46. side = (s == 0 ? GV_LEFT : GV_RIGHT);
  47. area = Vect_build_line_area(Map, line, side);
  48. if (area > 0) { /* area */
  49. Vect_get_area_box(Map, area, &box);
  50. if (first) {
  51. Vect_box_copy(&abox, &box);
  52. first = FALSE;
  53. }
  54. else
  55. Vect_box_extend(&abox, &box);
  56. }
  57. else if (area < 0) {
  58. /* isle -> must be attached -> add to abox */
  59. Vect_get_isle_box(Map, -area, &box);
  60. if (first) {
  61. Vect_box_copy(&abox, &box);
  62. first = FALSE;
  63. }
  64. else
  65. Vect_box_extend(&abox, &box);
  66. }
  67. G_debug(4, "Vect_build_line_area(): -> area = %d", area);
  68. }
  69. /* Attach centroid/isle to the new area */
  70. if (plus->built >= GV_BUILD_ATTACH_ISLES)
  71. Vect_attach_isles(Map, &abox);
  72. if (plus->built >= GV_BUILD_CENTROIDS)
  73. Vect_attach_centroids(Map, &abox);
  74. }
  75. /* Add category index */
  76. for (i = 0; i < cats->n_cats; i++) {
  77. dig_cidx_add_cat_sorted(plus, cats->field[i], cats->cat[i], line,
  78. type);
  79. }
  80. return;
  81. }
  82. #endif
  83. /*!
  84. \brief Writes feature on level 1 (OGR interface)
  85. Note:
  86. - centroids are not supported in OGR, pseudotopo holds virtual
  87. centroids
  88. - boundaries are not supported in OGR, pseudotopo treats polygons
  89. as boundaries
  90. \todo How to deal with OGRNullFID ?
  91. \param Map pointer to Map_info structure
  92. \param type feature type
  93. \param points pointer to line_pnts structure (feature geometry)
  94. \param cats pointer to line_cats structure (feature categories)
  95. \return feature offset into file
  96. \return -1 on error
  97. */
  98. off_t V1_write_line_ogr(struct Map_info *Map, int type,
  99. const struct line_pnts *points,
  100. const struct line_cats *cats)
  101. {
  102. #ifdef HAVE_OGR
  103. int i, cat, ret;
  104. struct field_info *Fi;
  105. struct Format_info_ogr *fInfo;
  106. off_t offset;
  107. OGRGeometryH Ogr_geometry;
  108. OGRFeatureH Ogr_feature;
  109. OGRFeatureDefnH Ogr_featuredefn;
  110. OGRwkbGeometryType Ogr_geom_type;
  111. if (!Map->fInfo.ogr.layer) {
  112. /* create OGR layer if doesn't exist */
  113. if (V2_open_new_ogr(Map, type) < 0)
  114. return -1;
  115. }
  116. cat = -1; /* no attributes to be written */
  117. if (cats->n_cats > 0 && Vect_get_num_dblinks(Map) > 0) {
  118. /* check for attributes */
  119. Fi = Vect_get_dblink(Map, 0);
  120. if (Fi) {
  121. if (!Vect_cat_get(cats, Fi->number, &cat))
  122. G_warning(_("No category defined for layer %d"), Fi->number);
  123. if (cats->n_cats > 1) {
  124. G_warning(_("Feature has more categories, using "
  125. "category %d (from layer %d)"),
  126. cat, cats->field[0]);
  127. }
  128. }
  129. }
  130. fInfo = &(Map->fInfo.ogr);
  131. Ogr_featuredefn = OGR_L_GetLayerDefn(fInfo->layer);
  132. Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn);
  133. /* determine matching OGR feature geometry type */
  134. if (type & (GV_POINT | GV_KERNEL)) {
  135. if (Ogr_geom_type != wkbPoint &&
  136. Ogr_geom_type != wkbPoint25D) {
  137. G_warning(_("Feature is not a point. Skipping."));
  138. return -1;
  139. }
  140. Ogr_geometry = OGR_G_CreateGeometry(wkbPoint);
  141. }
  142. else if (type & GV_LINE) {
  143. if (Ogr_geom_type != wkbLineString &&
  144. Ogr_geom_type != wkbLineString25D) {
  145. G_warning(_("Feature is not a line. Skipping."));
  146. return -1;
  147. }
  148. Ogr_geometry = OGR_G_CreateGeometry(wkbLineString);
  149. }
  150. else if (type & GV_BOUNDARY) {
  151. if (Ogr_geom_type != wkbPolygon) {
  152. G_warning(_("Feature is not a polygon. Skipping."));
  153. return -1;
  154. }
  155. Ogr_geometry = OGR_G_CreateGeometry(wkbPolygon);
  156. }
  157. else if (type & GV_FACE) {
  158. if (Ogr_geom_type != wkbPolygon25D) {
  159. G_warning(_("Feature is not a face. Skipping."));
  160. return -1;
  161. }
  162. Ogr_geometry = OGR_G_CreateGeometry(wkbPolygon25D);
  163. }
  164. else {
  165. G_warning(_("Unsupported feature type (%d)"), type);
  166. return -1;
  167. }
  168. G_debug(3, "V1_write_line_ogr(): type = %d", type);
  169. if (Ogr_geom_type == wkbPolygon || Ogr_geom_type == wkbPolygon25D) {
  170. /* create exterior ring */
  171. OGRGeometryH Ogr_ring;
  172. int npoints;
  173. npoints = points->n_points - 1;
  174. Ogr_ring = OGR_G_CreateGeometry(wkbLinearRing);
  175. if (points->x[0] != points->x[npoints] ||
  176. points->y[0] != points->y[npoints] ||
  177. points->z[0] != points->z[npoints]) {
  178. G_warning(_("Boundary is not closed. Skipping."));
  179. return -1;
  180. }
  181. /* add points */
  182. for (i = 0; i < points->n_points; i++) {
  183. OGR_G_AddPoint(Ogr_ring, points->x[i], points->y[i],
  184. points->z[i]);
  185. }
  186. OGR_G_AddGeometry(Ogr_geometry, Ogr_ring);
  187. }
  188. else {
  189. for (i = 0; i < points->n_points; i++) {
  190. OGR_G_AddPoint(Ogr_geometry, points->x[i], points->y[i],
  191. points->z[i]);
  192. }
  193. }
  194. G_debug(4, " n_points = %d", points->n_points);
  195. /* create feature & set geometry */
  196. Ogr_feature = OGR_F_Create(Ogr_featuredefn);
  197. OGR_F_SetGeometry(Ogr_feature, Ogr_geometry);
  198. /* write attributes */
  199. if (cat > -1 && fInfo->dbdriver) {
  200. write_attributes(fInfo->dbdriver,
  201. cat, Fi, fInfo->layer, Ogr_feature);
  202. G_free(Fi);
  203. }
  204. /* write feature into layer */
  205. ret = OGR_L_CreateFeature(fInfo->layer, Ogr_feature);
  206. /* update offset array */
  207. if (fInfo->offset.array_num >= fInfo->offset.array_alloc) {
  208. fInfo->offset.array_alloc += 1000;
  209. fInfo->offset.array = (int *) G_realloc(fInfo->offset.array,
  210. fInfo->offset.array_alloc *
  211. sizeof(int));
  212. }
  213. offset = fInfo->offset.array_num;
  214. fInfo->offset.array[fInfo->offset.array_num++] = (int) OGR_F_GetFID(Ogr_feature);
  215. if (Ogr_geom_type == wkbPolygon || Ogr_geom_type == wkbPolygon25D) {
  216. /* register exterior ring in offset array */
  217. fInfo->offset.array[fInfo->offset.array_num++] = 0;
  218. }
  219. /* destroy */
  220. OGR_G_DestroyGeometry(Ogr_geometry);
  221. OGR_F_Destroy(Ogr_feature);
  222. if (ret != OGRERR_NONE)
  223. return -1;
  224. G_debug(3, "V1_write_line_ogr(): -> offset = %lu", (unsigned long) offset);
  225. return offset;
  226. #else
  227. G_fatal_error(_("GRASS is not compiled with OGR support"));
  228. return -1;
  229. #endif
  230. }
  231. /*!
  232. \brief Writes feature on level 2
  233. \param Map pointer to Map_info structure
  234. \param type feature type
  235. \param points pointer to line_pnts structure (feature geometry)
  236. \param cats pointer to line_cats structure (feature categories)
  237. \return feature offset into file
  238. \return -1 on error
  239. */
  240. off_t V2_write_line_ogr(struct Map_info *Map, int type,
  241. const struct line_pnts *points, const struct line_cats *cats)
  242. {
  243. #ifdef HAVE_OGR
  244. int line;
  245. off_t offset;
  246. struct Plus_head *plus;
  247. struct bound_box box;
  248. line = 0;
  249. plus = &(Map->plus);
  250. G_debug(3, "V2_write_line_ogr()");
  251. offset = V1_write_line_ogr(Map, type, points, cats);
  252. if (offset < 0)
  253. return -1;
  254. /* Update topology */
  255. if (plus->built >= GV_BUILD_BASE) {
  256. dig_line_box(points, &box);
  257. line = dig_add_line(plus, type, points, &box, offset);
  258. G_debug(3, "\tline added to topo with line = %d", line);
  259. if (line == 1)
  260. Vect_box_copy(&(plus->box), &box);
  261. else
  262. Vect_box_extend(&(plus->box), &box);
  263. if (type == GV_BOUNDARY) {
  264. int ret, cline;
  265. long FID;
  266. double x, y;
  267. struct bound_box box;
  268. struct line_pnts *CPoints;
  269. /* add virtual centroid to pseudo-topology */
  270. ret = Vect_get_point_in_poly(points, &x, &y);
  271. if (ret == 0) {
  272. CPoints = Vect_new_line_struct();
  273. Vect_append_point(CPoints, x, y, 0.0);
  274. FID = Map->fInfo.ogr.offset.array[offset];
  275. dig_line_box(CPoints, &box);
  276. cline = dig_add_line(plus, GV_CENTROID,
  277. CPoints, &box, FID);
  278. G_debug(4, "\tCentroid: x = %f, y = %f, cat = %lu, line = %d",
  279. x, y, FID, cline);
  280. dig_cidx_add_cat(plus, 1, (int) FID,
  281. cline, GV_CENTROID);
  282. Vect_destroy_line_struct(CPoints);
  283. }
  284. else {
  285. G_warning(_("Unable to calculate centroid for area"));
  286. }
  287. }
  288. V2__add_line_to_topo_ogr(Map, line, points, cats);
  289. }
  290. G_debug(3, "updated lines : %d , updated nodes : %d", plus->uplist.n_uplines,
  291. plus->uplist.n_upnodes);
  292. /* returns int line, but is defined as off_t for compatibility with
  293. * Write_line_array in write.c */
  294. return line;
  295. #else
  296. G_fatal_error(_("GRASS is not compiled with OGR support"));
  297. return -1;
  298. #endif
  299. }
  300. /*!
  301. \brief Rewrites feature at the given offset (level 1)
  302. \param Map pointer to Map_info structure
  303. \param offset feature offset
  304. \param type feature type
  305. \param points feature geometry
  306. \param cats feature categories
  307. \return feature offset (rewriten feature)
  308. \return -1 on error
  309. */
  310. off_t V1_rewrite_line_ogr(struct Map_info *Map,
  311. int line,
  312. int type,
  313. off_t offset,
  314. const struct line_pnts *points, const struct line_cats *cats)
  315. {
  316. G_debug(3, "V1_rewrite_line_ogr(): line=%d type=%d offset=%llu",
  317. line, type, offset);
  318. #ifdef HAVE_OGR
  319. if (type != V1_read_line_ogr(Map, NULL, NULL, offset)) {
  320. G_warning(_("Unable to rewrite feature (incompatible feature types)"));
  321. return -1;
  322. }
  323. /* delete old */
  324. V1_delete_line_ogr(Map, offset);
  325. return V1_write_line_ogr(Map, type, points, cats);
  326. #else
  327. G_fatal_error(_("GRASS is not compiled with OGR support"));
  328. return -1;
  329. #endif
  330. }
  331. /*!
  332. \brief Rewrites feature to 'coor' file (topology level) - internal use only
  333. \param Map pointer to Map_info structure
  334. \param line feature id
  335. \param type feature type
  336. \param offset unused
  337. \param points feature geometry
  338. \param cats feature categories
  339. \return offset where line was rewritten
  340. \return -1 on error
  341. */
  342. off_t V2_rewrite_line_ogr(struct Map_info *Map, int line, int type, off_t offset,
  343. const struct line_pnts *points, const struct line_cats *cats)
  344. {
  345. G_debug(3, "V2_rewrite_line_ogr(): line=%d type=%d offset=%llu",
  346. line, type, offset);
  347. #ifdef HAVE_OGR
  348. if (type != V2_read_line_ogr(Map, NULL, NULL, line)) {
  349. G_warning(_("Unable to rewrite feature (incompatible feature types)"));
  350. return -1;
  351. }
  352. V2_delete_line_ogr(Map, line);
  353. return V2_write_line_ogr(Map, type, points, cats);
  354. #else
  355. G_fatal_error(_("GRASS is not compiled with OGR support"));
  356. return -1;
  357. #endif
  358. }
  359. /*!
  360. \brief Deletes feature at the given offset (level 1)
  361. \param Map pointer Map_info structure
  362. \param offset feature offset
  363. \return 0 on success
  364. \return -1 on error
  365. */
  366. int V1_delete_line_ogr(struct Map_info *Map, off_t offset)
  367. {
  368. #ifdef HAVE_OGR
  369. G_debug(3, "V1_delete_line_ogr(), offset = %lu", (unsigned long) offset);
  370. if (!Map->fInfo.ogr.layer) {
  371. G_warning(_("OGR layer not defined"));
  372. return -1;
  373. }
  374. if (offset >= Map->fInfo.ogr.offset.array_num)
  375. return -1;
  376. if (OGR_L_DeleteFeature(Map->fInfo.ogr.layer,
  377. Map->fInfo.ogr.offset.array[offset]) != OGRERR_NONE)
  378. return -1;
  379. return 0;
  380. #else
  381. G_fatal_error(_("GRASS is not compiled with OGR support"));
  382. return -1;
  383. #endif
  384. }
  385. /*!
  386. \brief Deletes feature (topology level) -- internal use only
  387. \param pointer to Map_info structure
  388. \param line feature id
  389. \return 0 on success
  390. \return -1 on error
  391. */
  392. int V2_delete_line_ogr(struct Map_info *Map, int line)
  393. {
  394. #ifdef HAVE_OGR
  395. int ret, i, type, first;
  396. struct P_line *Line;
  397. struct Plus_head *plus;
  398. static struct line_cats *Cats = NULL;
  399. static struct line_pnts *Points = NULL;
  400. G_debug(3, "V2_delete_line_ogr(), line = %d", line);
  401. type = first = 0;
  402. Line = NULL;
  403. plus = &(Map->plus);
  404. if (plus->built >= GV_BUILD_BASE) {
  405. Line = Map->plus.Line[line];
  406. if (Line == NULL)
  407. G_fatal_error(_("Attempt to delete dead feature"));
  408. type = Line->type;
  409. }
  410. if (!Cats) {
  411. Cats = Vect_new_cats_struct();
  412. }
  413. if (!Points) {
  414. Points = Vect_new_line_struct();
  415. }
  416. type = V2_read_line_ogr(Map, Points, Cats, line);
  417. /* Update category index */
  418. if (plus->update_cidx) {
  419. for (i = 0; i < Cats->n_cats; i++) {
  420. dig_cidx_del_cat(plus, Cats->field[i], Cats->cat[i], line, type);
  421. }
  422. }
  423. /* Update fidx */
  424. /* delete the line from coor */
  425. ret = V1_delete_line_ogr(Map, Line->offset);
  426. if (ret == -1) {
  427. return ret;
  428. }
  429. /* Update topology */
  430. if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
  431. /* TODO */
  432. /* remove centroid together with boundary (is really an OGR polygon) */
  433. }
  434. /* Delete reference from area */
  435. if (plus->built >= GV_BUILD_CENTROIDS && type == GV_CENTROID) {
  436. /* for OGR mapsets, virtual centroid will be removed when polygon is removed */
  437. }
  438. /* delete the line from topo */
  439. dig_del_line(plus, line, Points->x[0], Points->y[0], Points->z[0]);
  440. /* Rebuild areas/isles and attach centroids and isles */
  441. if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
  442. /* maybe not needed VERIFY */
  443. }
  444. return ret;
  445. #else
  446. G_fatal_error(_("GRASS is not compiled with OGR support"));
  447. return -1;
  448. #endif
  449. }
  450. #ifdef HAVE_OGR
  451. int write_attributes(dbDriver *driver, int cat, const struct field_info *Fi,
  452. OGRLayerH Ogr_layer, OGRFeatureH Ogr_feature)
  453. {
  454. int j, ogrfieldnum;
  455. char buf[2000];
  456. int ncol, sqltype, ctype, ogrtype, more;
  457. const char *fidcol, *colname;
  458. dbTable *table;
  459. dbString dbstring;
  460. dbColumn *column;
  461. dbCursor cursor;
  462. dbValue *value;
  463. OGRFieldDefnH hFieldDefn;
  464. G_debug(3, "write_attributes(): cat = %d", cat);
  465. if (cat < 0) {
  466. G_warning(_("Feature without category of layer %d"), Fi->number);
  467. return 0;
  468. }
  469. db_init_string(&dbstring);
  470. /* read & set attributes */
  471. sprintf(buf, "SELECT * FROM %s WHERE %s = %d", Fi->table, Fi->key,
  472. cat);
  473. G_debug(4, "SQL: %s", buf);
  474. db_set_string(&dbstring, buf);
  475. /* select data */
  476. if (db_open_select_cursor(driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) {
  477. G_fatal_error(_("Unable to select attributes for category %d"),
  478. cat);
  479. }
  480. if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
  481. G_fatal_error(_("Unable to fetch data from table <%s>"),
  482. Fi->table);
  483. }
  484. if (!more) {
  485. G_warning(_("No database record for category %d, "
  486. "no attributes will be written"),
  487. cat);
  488. return -1;
  489. }
  490. fidcol = OGR_L_GetFIDColumn(Ogr_layer);
  491. table = db_get_cursor_table(&cursor);
  492. ncol = db_get_table_number_of_columns(table);
  493. for (j = 0; j < ncol; j++) {
  494. column = db_get_table_column(table, j);
  495. colname = db_get_column_name(column);
  496. if (fidcol && *fidcol && strcmp(colname, fidcol) == 0) {
  497. /* skip fid column */
  498. continue;
  499. }
  500. value = db_get_column_value(column);
  501. /* for debug only */
  502. db_convert_column_value_to_string(column, &dbstring);
  503. G_debug(2, "col %d : val = %s", j,
  504. db_get_string(&dbstring));
  505. sqltype = db_get_column_sqltype(column);
  506. ctype = db_sqltype_to_Ctype(sqltype);
  507. ogrtype = sqltype_to_ogrtype(sqltype);
  508. G_debug(2, " colctype = %d", ctype);
  509. ogrfieldnum = OGR_F_GetFieldIndex(Ogr_feature, colname);
  510. if (ogrfieldnum < 0) {
  511. /* create field if not exists */
  512. hFieldDefn = OGR_Fld_Create(colname, ogrtype);
  513. if (OGR_L_CreateField(Ogr_layer, hFieldDefn, TRUE) != OGRERR_NONE)
  514. G_warning(_("Unable to create field <%s>"), colname);
  515. ogrfieldnum = OGR_F_GetFieldIndex(Ogr_feature, colname);
  516. }
  517. /* Reset */
  518. OGR_F_UnsetField(Ogr_feature, ogrfieldnum);
  519. /* prevent writing NULL values */
  520. if (!db_test_value_isnull(value)) {
  521. switch (ctype) {
  522. case DB_C_TYPE_INT:
  523. OGR_F_SetFieldInteger(Ogr_feature, ogrfieldnum,
  524. db_get_value_int(value));
  525. break;
  526. case DB_C_TYPE_DOUBLE:
  527. OGR_F_SetFieldDouble(Ogr_feature, ogrfieldnum,
  528. db_get_value_double(value));
  529. break;
  530. case DB_C_TYPE_STRING:
  531. OGR_F_SetFieldString(Ogr_feature, ogrfieldnum,
  532. db_get_value_string(value));
  533. break;
  534. case DB_C_TYPE_DATETIME:
  535. db_convert_column_value_to_string(column,
  536. &dbstring);
  537. OGR_F_SetFieldString(Ogr_feature, ogrfieldnum,
  538. db_get_string(&dbstring));
  539. break;
  540. }
  541. }
  542. }
  543. db_close_cursor (&cursor);
  544. db_free_string(&dbstring);
  545. return 1;
  546. }
  547. int sqltype_to_ogrtype(int sqltype)
  548. {
  549. int ctype, ogrtype;
  550. ctype = db_sqltype_to_Ctype(sqltype);
  551. switch(ctype) {
  552. case DB_C_TYPE_INT:
  553. ogrtype = OFTInteger;
  554. break;
  555. case DB_C_TYPE_DOUBLE:
  556. ogrtype = OFTReal;
  557. break;
  558. case DB_C_TYPE_STRING:
  559. ogrtype = OFTString;
  560. break;
  561. case DB_C_TYPE_DATETIME:
  562. ogrtype = OFTString;
  563. break;
  564. default:
  565. ogrtype = OFTString;
  566. break;
  567. }
  568. return ogrtype;
  569. }
  570. #endif /* HAVE_OGR */