list.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. #include <string.h>
  2. #include <grass/gis.h>
  3. #include <grass/vector.h>
  4. #include <grass/dbmi.h>
  5. #include <grass/gprojects.h>
  6. #include <grass/glocale.h>
  7. #ifdef HAVE_OGR
  8. #include "ogr_api.h"
  9. #endif
  10. #ifdef HAVE_POSTGRES
  11. #include <libpq-fe.h>
  12. #endif
  13. #include "local_proto.h"
  14. static int cmp(const void *, const void *);
  15. static char **format_list(int *, size_t *);
  16. static char *feature_type(const char *);
  17. #ifdef HAVE_OGR
  18. static int list_layers_ogr(FILE *, const char *, char **, int);
  19. #endif /* HAVE_OGR */
  20. #ifdef HAVE_POSTGRES
  21. static int list_layers_pg(FILE *, const char *, char **, int);
  22. #endif /* HAVE_POSTGRES */
  23. int cmp(const void *a, const void *b)
  24. {
  25. return strcmp(*(char **)a, *(char **)b);
  26. }
  27. char **format_list(int *count, size_t *len)
  28. {
  29. int i;
  30. char **list;
  31. list = NULL;
  32. *count = 0;
  33. if (len)
  34. *len = 0;
  35. #ifdef HAVE_OGR
  36. char buf[2000];
  37. OGRSFDriverH Ogr_driver;
  38. /* Open OGR DSN */
  39. OGRRegisterAll();
  40. G_debug(2, "driver count = %d", OGRGetDriverCount());
  41. for (i = 0; i < OGRGetDriverCount(); i++) {
  42. Ogr_driver = OGRGetDriver(i);
  43. G_debug(2, "driver %d/%d : %s", i, OGRGetDriverCount(),
  44. OGR_Dr_GetName(Ogr_driver));
  45. list = G_realloc(list, ((*count) + 1) * sizeof(char *));
  46. /* chg white space to underscore in OGR driver names */
  47. sprintf(buf, "%s", OGR_Dr_GetName(Ogr_driver));
  48. G_strchg(buf, ' ', '_');
  49. list[(*count)++] = G_store(buf);
  50. if (len)
  51. *len += strlen(buf) + 1; /* + ',' */
  52. }
  53. /* order formats by name */
  54. qsort(list, *count, sizeof(char *), cmp);
  55. #endif
  56. #if defined HAVE_POSTGRES && !defined HAVE_OGR
  57. list = G_realloc(list, ((*count) + 1) * sizeof(char *));
  58. list[(*count)++] = G_store("PostgreSQL");
  59. if (len)
  60. *len += strlen("PostgreSQL") + 1;
  61. #endif
  62. return list;
  63. }
  64. char *feature_type(const char *ftype)
  65. {
  66. char *ftype_ret;
  67. ftype_ret = G_str_replace(ftype, " ", "");
  68. G_str_to_lower(ftype_ret);
  69. /* let's OS to release the memory */
  70. return ftype_ret;
  71. }
  72. void list_formats(void)
  73. {
  74. int i, count;
  75. char **list;
  76. G_message(_("Supported formats:"));
  77. list = format_list(&count, NULL);
  78. for (i = 0; i < count; i++)
  79. fprintf(stdout, "%s\n", list[i]);
  80. fflush(stdout);
  81. G_free(list);
  82. }
  83. int list_layers(FILE *fd, const char *dsn, char **layer, int print_types, int use_ogr)
  84. {
  85. if (!use_ogr) {
  86. #ifdef HAVE_POSTGRES
  87. return list_layers_pg(fd, dsn, layer, print_types);
  88. #else
  89. G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
  90. #endif
  91. }
  92. #ifdef HAVE_OGR
  93. return list_layers_ogr(fd, dsn, layer, print_types);
  94. #else
  95. G_fatal_error(_("GRASS is not compiled with OGR support"));
  96. #endif
  97. return -1;
  98. }
  99. void get_table_name(const char *table, char **table_name, char **schema_name)
  100. {
  101. char **tokens;
  102. tokens = G_tokenize(table, ".");
  103. if (G_number_of_tokens(tokens) > 1) {
  104. *schema_name = G_store(tokens[0]);
  105. *table_name = G_store(tokens[1]);
  106. }
  107. else {
  108. *schema_name = NULL;
  109. *table_name = G_store(tokens[0]);
  110. }
  111. G_free_tokens(tokens);
  112. }
  113. #ifdef HAVE_POSTGRES
  114. int list_layers_pg(FILE *fd, const char *conninfo, char **table, int print_types)
  115. {
  116. int row, ntables, ret, print_schema;
  117. char *value_schema, *value_table, *value_type, *value_column;
  118. char *schema_name, *table_name;
  119. PGconn *conn;
  120. PGresult *res;
  121. dbString sql;
  122. ret = -1;
  123. conn = PQconnectdb(conninfo);
  124. G_debug(1, "PQconnectdb(): %s", conninfo);
  125. if (PQstatus(conn) == CONNECTION_BAD)
  126. G_fatal_error("%s\n%s", _("Connection to PostgreSQL database failed."),
  127. PQerrorMessage(conn));
  128. db_init_string(&sql);
  129. db_set_string(&sql, "SELECT f_table_schema, f_table_name, f_geometry_column, type "
  130. "FROM geometry_columns ORDER BY "
  131. "f_table_schema, f_table_name");
  132. G_debug(2, "SQL: %s", db_get_string(&sql));
  133. res = PQexec(conn, db_get_string(&sql));
  134. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  135. G_fatal_error("%s\n%s", _("No feature tables found in database."),
  136. PQresultErrorMessage(res));
  137. /* get schema & table_name */
  138. table_name = schema_name = NULL;
  139. if (table)
  140. get_table_name(*table, &table_name, &schema_name);
  141. ntables = PQntuples(res);
  142. G_debug(3, " nrows = %d", ntables);
  143. if (fd)
  144. G_message(n_("PostGIS database <%s> contains %d feature table:",
  145. "PostGIS database <%s> contains %d feature tables:",
  146. ntables),
  147. PQdb(conn), ntables);
  148. /* report also schemas */
  149. print_schema = FALSE;
  150. if (fd) {
  151. for (row = 0; row < ntables; row++) {
  152. value_schema = PQgetvalue(res, row, 0);
  153. if (G_strcasecmp(value_schema, "public") != 0) {
  154. print_schema = TRUE;
  155. break;
  156. }
  157. }
  158. }
  159. /* report layers */
  160. for (row = 0; row < ntables; row++) {
  161. value_schema = PQgetvalue(res, row, 0);
  162. value_table = PQgetvalue(res, row, 1);
  163. value_column = PQgetvalue(res, row, 2);
  164. value_type = PQgetvalue(res, row, 3);
  165. if (fd) {
  166. if (print_types) {
  167. if (print_schema && G_strcasecmp(value_schema, "public") != 0)
  168. fprintf(fd, "%s.", value_schema);
  169. fprintf(fd, "%s,%s,0,%s\n", value_table,
  170. feature_type(value_type), value_column);
  171. }
  172. else {
  173. if (print_schema && G_strcasecmp(value_schema, "public") != 0)
  174. fprintf(fd, "%s.%s\n", value_schema, value_table);
  175. else
  176. fprintf(fd, "%s\n", value_table);
  177. }
  178. }
  179. if ((!schema_name || strcmp(value_schema, schema_name) == 0) &&
  180. table_name && strcmp(value_table, table_name) == 0) {
  181. ret = row;
  182. }
  183. }
  184. if (table_name)
  185. G_free(table_name);
  186. if (schema_name)
  187. G_free(schema_name);
  188. PQclear(res);
  189. PQfinish(conn);
  190. G_debug(1, "PQfinish()");
  191. return ret;
  192. }
  193. #endif /* HAVE_POSTGRES */
  194. #ifdef HAVE_OGR
  195. int list_layers_ogr(FILE *fd, const char *dsn, char **layer, int print_types)
  196. {
  197. int i, ret;
  198. int nlayers;
  199. char *layer_name;
  200. struct Key_Value *loc_proj_info, *loc_proj_units;
  201. struct Key_Value *proj_info, *proj_units;
  202. struct Cell_head loc_wind;
  203. OGRDataSourceH Ogr_ds;
  204. OGRLayerH Ogr_layer;
  205. OGRFeatureDefnH Ogr_featuredefn;
  206. OGRwkbGeometryType Ogr_geom_type;
  207. ret = -1;
  208. loc_proj_info = loc_proj_units = NULL;
  209. proj_info = proj_units = NULL;
  210. /* open OGR DSN */
  211. Ogr_ds = OGROpen(dsn, FALSE, NULL);
  212. if (!Ogr_ds) {
  213. G_fatal_error(_("Unable to open data source '%s'"), dsn);
  214. }
  215. /* Make a list of available layers */
  216. nlayers = OGR_DS_GetLayerCount(Ogr_ds);
  217. if (fd) {
  218. G_message(n_("Data source <%s> (format '%s') contains %d layer:",
  219. "Data source <%s> (format '%s') contains %d layers:",
  220. nlayers),
  221. dsn, OGR_Dr_GetName(OGR_DS_GetDriver(Ogr_ds)), nlayers);
  222. }
  223. else if (layer && !(*layer)) {
  224. /* return first layer by default (if layer not defined) */
  225. if (nlayers > 0) {
  226. Ogr_layer = OGR_DS_GetLayer(Ogr_ds, 0);
  227. Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
  228. *layer = G_store((char *) OGR_FD_GetName(Ogr_featuredefn));
  229. return 0;
  230. }
  231. return -1;
  232. }
  233. G_get_default_window(&loc_wind);
  234. if (print_types && loc_wind.proj != PROJECTION_XY) {
  235. loc_proj_info = G_get_projinfo();
  236. loc_proj_units = G_get_projunits();
  237. }
  238. for (i = 0; i < nlayers; i++) {
  239. Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);
  240. Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
  241. #if GDAL_VERSION_NUM < 1110000
  242. Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn);
  243. #endif
  244. layer_name = (char *) OGR_FD_GetName(Ogr_featuredefn);
  245. if (fd) {
  246. if (print_types) {
  247. int proj_same, igeom;
  248. OGRSpatialReferenceH Ogr_projection;
  249. #if GDAL_VERSION_NUM >= 1110000
  250. OGRGeomFieldDefnH Ogr_geomdefn;
  251. #endif
  252. /* projection check */
  253. Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer);
  254. proj_same = 0;
  255. G_suppress_warnings(TRUE);
  256. if (GPJ_osr_to_grass(&loc_wind, &proj_info,
  257. &proj_units, Ogr_projection, 0) < 0) {
  258. G_warning(_("Unable to convert input map projection to GRASS "
  259. "format. Projection check cannot be provided for "
  260. "OGR layer <%s>"), layer_name);
  261. }
  262. else {
  263. if (TRUE == G_compare_projections(loc_proj_info, loc_proj_units,
  264. proj_info, proj_units))
  265. proj_same = 1;
  266. else
  267. proj_same = 0;
  268. }
  269. G_suppress_warnings(FALSE);
  270. #if GDAL_VERSION_NUM >= 1110000
  271. for (igeom = 0; igeom < OGR_FD_GetGeomFieldCount(Ogr_featuredefn); igeom++) {
  272. Ogr_geomdefn = OGR_FD_GetGeomFieldDefn(Ogr_featuredefn, igeom);
  273. if (!Ogr_geomdefn) {
  274. G_warning(_("Invalid geometry column %d"), igeom);
  275. continue;
  276. }
  277. Ogr_geom_type = OGR_GFld_GetType(Ogr_geomdefn);
  278. fprintf(fd, "%s,%s,%d,%s\n", layer_name,
  279. feature_type(OGRGeometryTypeToName(Ogr_geom_type)),
  280. proj_same, OGR_GFld_GetNameRef(Ogr_geomdefn));
  281. }
  282. #else
  283. fprintf(fd, "%s,%s,%d,\n", layer_name,
  284. feature_type(OGRGeometryTypeToName(Ogr_geom_type)),
  285. proj_same);
  286. #endif
  287. }
  288. else {
  289. fprintf(fd, "%s\n", layer_name);
  290. }
  291. }
  292. if (layer)
  293. if (strcmp(layer_name, *layer) == 0) {
  294. ret = i;
  295. }
  296. }
  297. OGR_DS_Destroy(Ogr_ds);
  298. return ret;
  299. }
  300. #endif /* HAVE_OGR */