123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- /***************************************************************
- *
- * MODULE: v.out.postgis
- *
- * AUTHOR(S): Martin Landa <landa.martin gmail.com>
- *
- * PURPOSE: Converts GRASS vector map layer to PostGIS
- *
- * COPYRIGHT: (C) 2012-2013 by Martin Landa, and the GRASS Development Team
- *
- * This program is free software under the GNU General
- * Public License (>=v2). Read the file COPYING that
- * comes with GRASS for details.
- *
- **************************************************************/
- #include <stdlib.h>
- #include <grass/gis.h>
- #include <grass/glocale.h>
- #include <libpq-fe.h>
- #include "local_proto.h"
- static void link_handler(void *);
- static void output_handler(void *);
- int main(int argc, char *argv[])
- {
- struct GModule *module;
- struct params params;
- struct flags flags;
-
- int ret, field, otype, verbose;
- char *schema, *olayer, *pg_file;
- char *fid_column, *geom_column;
-
- struct Map_info In, Out;
-
- G_gisinit(argv[0]);
- module = G_define_module();
- G_add_keyword(_("vector"));
- G_add_keyword(_("export"));
- G_add_keyword(_("output"));
- G_add_keyword(_("PostGIS"));
- G_add_keyword(_("simple features"));
- G_add_keyword(_("topology"));
- G_add_keyword(_("3D"));
-
- module->description =
- _("Exports a vector map layer to PostGIS feature table.");
- module->overwrite = TRUE;
-
- define_options(¶ms, &flags);
-
- if (G_parser(argc, argv))
- exit(EXIT_FAILURE);
- /* parse parameters */
- otype = Vect_option_to_types(params.type);
- /* if olayer not given, use input as the name */
- schema = NULL;
- if (!params.olayer->answer) {
- char name[GNAME_MAX], mapset[GMAPSET_MAX];
-
- /* check for fully qualified name */
- if (G_name_is_fully_qualified(params.input->answer,
- name, mapset))
- olayer = G_store(name);
- else
- olayer = G_store(params.input->answer);
- G_debug(1, "olayer=%s", olayer);
- }
- else {
- /* check for schema */
- char **tokens;
- tokens = G_tokenize(params.olayer->answer, ".");
- if (G_number_of_tokens(tokens) == 2) {
- schema = G_store(tokens[0]);
- olayer = G_store(tokens[1]);
- }
- else {
- olayer = G_store(params.olayer->answer);
- }
-
- G_free_tokens(tokens);
- }
-
- /* if schema not defined, use 'public' */
- if (!schema)
- schema = "public";
- G_debug(1, "Database schema: %s", schema);
-
- /* open input for reading */
- ret = Vect_open_old2(&In, params.input->answer, "", params.layer->answer);
- if (ret == -1)
- G_fatal_error(_("Unable to open vector map <%s>"),
- params.input->answer);
- if (Vect_maptype(&In) != GV_FORMAT_NATIVE)
- G_fatal_error(_("Vector map <%s> is not in native format. Export cancelled."),
- Vect_get_full_name(&In));
- Vect_set_error_handler_io(&In, NULL);
- if (params.olink->answer)
- G_add_error_handler(link_handler, params.olink->answer);
- if (ret < 2)
- G_warning(_("Unable to open vector map <%s> on topological level"),
- params.input->answer);
-
- /* default columns */
- fid_column = GV_PG_FID_COLUMN;
- geom_column = GV_PG_GEOMETRY_COLUMN;
-
- /* create output for writing */
- pg_file = create_pgfile(params.dsn->answer, schema, params.olink->answer,
- params.opts->answers, flags.topo->answer ? TRUE : FALSE,
- &fid_column, &geom_column);
- G_debug(1, "fid_column: %s", fid_column);
- G_debug(1, "geom_column: %s", geom_column);
-
- if (!flags.table->answer) {
- /* check fid column */
- check_columns(&In, params.layer->answer, fid_column, geom_column);
- }
- /* don't use temporary maps, writes vector features immediately to
- the output PostGIS layer */
- putenv("GRASS_VECTOR_EXTERNAL_IMMEDIATE=1");
- if (-1 == Vect_open_new(&Out, olayer,
- !flags.force2d->answer ? Vect_is_3d(&In) : WITHOUT_Z))
- G_fatal_error(_("Unable to create PostGIS layer <%s>"),
- olayer);
- G_add_error_handler(output_handler, &Out);
- /* copy attributes (must be done before checking output type
- otherwise attributes are not copied) */
- field = Vect_get_field_number(&In, params.layer->answer);
- /* BUG: this works only if the input vector uses for its attributes
- * the same PG connection to be used for the output */
- if (!flags.table->answer)
- Vect_copy_map_dblinks(&In, &Out, TRUE);
- /* check output type */
- if (otype < 1 && Vect_level(&In) > 1) {
- /* type 'auto' -> try to guess output feature type on level 2 */
- if (Vect_get_num_areas(&In) > 0)
- otype = GV_AREA;
- else if (Vect_get_num_primitives(&In, GV_LINE) > 0)
- otype = GV_LINE;
- else if (Vect_get_num_primitives(&In, GV_POINT) > 0)
- otype = GV_POINT;
- }
- if (otype > 0) {
- if (otype & (GV_FACE | GV_KERNEL))
- G_fatal_error(_("Feature type '%s' not supported"),
- params.type->answer);
-
- /* set up output feature type if possible */
- if (Vect_write_line(&Out, otype, NULL, NULL) < 0)
- G_fatal_error(_("Feature type %d is not supported"), otype);
- Vect_set_constraint_type(&In, otype);
- }
-
- /* copy vector features & create PostGIS table */
- if (Vect_copy_map_lines_field(&In, field, &Out) != 0)
- G_fatal_error(_("Copying features failed"));
- /* close input map */
- Vect_close(&In);
- /* build topology for output map -> write output to DB */
- G_message(_("Writing output..."));
- verbose = G_verbose();
- if (!flags.topo->answer)
- G_set_verbose(0); /* do not print build info when writing simple features */
-
- Vect_build_partial(&Out, GV_BUILD_NONE);
- if (Vect_build(&Out) != 1)
- G_fatal_error(_("Building %s topology failed"),
- flags.topo->answer ? "PostGIS" : "pseudo");
- G_set_verbose(verbose);
-
- if (Vect_get_num_lines(&Out) < 1)
- G_fatal_error(_("No features exported. PostGIS layer <%s> not created."),
- Vect_get_name(&Out));
- if (!flags.topo->answer)
- G_done_msg(n_("%d feature (%s type) written to <%s>.",
- "%d features (%s type) written to <%s>.",
- Vect_sfa_get_num_features(&Out)),
- Vect_sfa_get_num_features(&Out), Vect_get_finfo_geometry_type(&Out),
- Vect_get_name(&Out));
- else
- G_done_msg(n_("%d primitive written to <%s>.",
- "%d primitives written to <%s>.",
- Vect_get_num_lines(&Out)),
- Vect_get_num_lines(&Out),
- Vect_get_name(&Out));
-
- /* close output map */
- Vect_close(&Out);
- /* remove PG file */
- G_remove("", pg_file);
-
- exit(EXIT_SUCCESS);
- }
- void link_handler(void *p)
- {
- const char *link = (const char *) p;
-
- G_debug(1, "link_handler: %s", link);
- if (G_find_vector2(link, G_mapset()))
- Vect_delete(link);
- }
- void output_handler(void *p)
- {
- char stmt[DB_SQL_MAX];
-
- struct Map_info *Map;
- struct Format_info_pg *pg_info;
- PGresult *result;
-
- Map = (struct Map_info *) p;
- pg_info = &Map->fInfo.pg;
-
- G_debug(1, "output_handler(): schema = %s; olayer = %s", pg_info->schema_name, pg_info->table_name);
- sprintf(stmt, "SELECT DropGeometryTable('%s', '%s')", pg_info->schema_name, pg_info->table_name);
- result = PQexec(pg_info->conn, stmt);
- /*
- be quiet - table may do not exists
- if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
- G_warning(_("Unable to drop table <%s.%s>"), pg_info->schema_name, pg_info->table_name);
- }
- */
- PQclear(result);
- if (pg_info->toposchema_name) {
- sprintf(stmt, "SELECT topology.DropTopology('%s')", pg_info->toposchema_name);
- result = PQexec(pg_info->conn, stmt);
- if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
- G_warning(_("Unable to drop topology schema <%s>"), pg_info->toposchema_name);
- }
- PQclear(result);
- }
- }
|