28#include "local_proto.h"
31#include "pg_local_proto.h"
33#define WKBSRIDFLAG 0x20000000
35#define TOPOGEOM_COLUMN "topo"
40#define USE_TOPO_STMT 0
45static int create_pg_layer(
struct Map_info *,
int);
51static char *binary_to_hex(
int,
const unsigned char *);
52static unsigned char *point_to_wkb(
int,
const struct line_pnts *,
int,
int *);
53static unsigned char *linestring_to_wkb(
int,
const struct line_pnts *,
int,
55static unsigned char *polygon_to_wkb(
int,
const struct line_pnts **,
int,
int,
61static char *build_insert_stmt(
const struct Format_info_pg *,
const char *,
int,
63static int insert_topo_element(
struct Map_info *,
int,
int,
const char *);
65static int update_next_edge(
struct Map_info *,
int,
int);
71static int update_topo_face(
struct Map_info *,
int);
74static int delete_line_from_topo_pg(
struct Map_info *,
int,
int,
76static int set_constraint_to_deferrable(
struct Format_info_pg *,
const char *,
77 const char *,
const char *,
78 const char *,
const char *);
85#define NOPG_UNUSED UNUSED
120 if (create_pg_layer(
Map, type) < 0)
127 if (!
pg_info->toposchema_name) {
128 return write_line_sf(
Map, type, &points, 1, cats);
132 return write_line_tp(
Map, type,
FALSE, points, cats);
134 G_fatal_error(
_(
"GRASS is not compiled with PostgreSQL support"));
161 if (!
pg_info->toposchema_name) {
166 return write_line_tp(
Map, type,
FALSE, points, cats);
168 G_fatal_error(
_(
"GRASS is not compiled with PostgreSQL support"));
197 G_warning(
_(
"Unable to rewrite feature (incompatible feature types)"));
206 G_fatal_error(
_(
"GRASS is not compiled with PostgreSQL support"));
233 G_debug(3,
"V2_rewrite_line_pg(): line=%d type=%d", (
int)line, type);
247 G_warning(
_(
"Attempt to access feature with invalid id (%d)"),
252 Line =
Map->plus.Line[line];
254 G_warning(
_(
"Attempt to access dead feature %d"), (
int)line);
259 if (!(
Map->plus.update_cidx)) {
267 G_warning(
_(
"Unable to rewrite feature (incompatible feature types)"));
272 if (0 != delete_line_from_topo_pg(
Map, line,
type, Points))
275 if (
pg_info->toposchema_name) {
276 schema_name =
pg_info->toposchema_name;
281 table_name =
"edge_data";
286 schema_name =
pg_info->schema_name;
287 table_name =
pg_info->table_name;
293 "UPDATE \"%s\".\"%s\" SET geom = '%s'::GEOMETRY WHERE %s_id = "
299 G_warning(
_(
"Unable to rewrite feature %d"), (
int)line);
308 G_fatal_error(
_(
"GRASS is not compiled with PostgreSQL support"));
347 G_debug(3,
"V1_delete_line_pg(): offset = %lu -> fid = %ld",
348 (
unsigned long)
offset, fid);
357 snprintf(stmt,
sizeof(stmt),
"DELETE FROM %s WHERE %s = %ld",
369 G_fatal_error(
_(
"GRASS is not compiled with PostgreSQL support"));
396 G_warning(
_(
"Attempt to access feature with invalid id (%d)"),
401 if (!
pg_info->toposchema_name) {
412 G_warning(
_(
"Attempt to access feature with invalid id (%d)"),
417 Line =
Map->plus.Line[line];
419 G_warning(
_(
"Attempt to access dead feature %d"), (
int)line);
423 if (!(
Map->plus.update_cidx)) {
424 Map->plus.cidx_up_to_date =
434 table_name =
"edge_data";
440 "UPDATE \"%s\".\"%s\" SET abs_next_left_edge = edge_id, "
441 "next_left_edge = -edge_id WHERE abs_next_left_edge = %d",
450 "UPDATE \"%s\".\"%s\" SET abs_next_right_edge = edge_id, "
451 "next_right_edge = edge_id WHERE abs_next_right_edge = %d",
469 stmt,
sizeof(stmt),
"DELETE FROM \"%s\".\"%s\" WHERE %s_id = %d",
483 pg_info->cache.lines_types[line - 1] = 0;
484 pg_info->cache.lines_cats[line - 1] = 0;
488 ret = delete_line_from_topo_pg(
Map, line,
type, Points);
496 G_fatal_error(
_(
"GRASS is not compiled with PostgreSQL support"));
567 for (part = 0; part <
nparts; part++) {
568 npoints = points[part]->
n_points - 1;
569 if (points[part]->
x[0] != points[part]->
x[npoints] ||
570 points[part]->y[0] != points[part]->y[npoints] ||
571 points[part]->z[0] != points[part]->z[npoints]) {
572 G_warning(
_(
"Boundary is not closed. Skipping."));
583 "UPDATE \"%s\".\"%s\" SET %s = '%s'::GEOMETRY WHERE %s = %d",
652 if (check_schema(
pg_info) != 0)
658 "CREATE TABLE \"%s\".\"%s\" (%s SERIAL%s, %s INTEGER",
685 G_warning(
_(
"Unable to describe table <%s>"),
Fi->table);
693 "copying attributes: driver = %s database = %s table = %s cols "
695 Fi->driver,
Fi->database,
Fi->table, ncols);
703 G_debug(3,
"\tcolumn = %d name = %s type = %d length = %d",
col,
740 switch (
pg_info->feature_type) {
764 "SELECT AddGeometryColumn('%s', '%s', "
765 "'%s', %d, '%s', %d)",
782 snprintf(stmt,
sizeof(stmt),
"CREATE INDEX %s_%s_idx ON \"%s\".\"%s\" (%s)",
794 "CREATE INDEX %s_%s_idx ON \"%s\".\"%s\" USING GIST (%s)",
834 snprintf(stmt,
sizeof(stmt),
"SELECT nspname FROM pg_namespace");
854 snprintf(stmt,
sizeof(stmt),
"CREATE SCHEMA %s",
pg_info->schema_name);
859 G_warning(
_(
"Schema <%s> doesn't exist, created"),
907 G_debug(1,
"PG: tolerance: %f", tolerance);
941 "SELECT topology.createtopology('%s', "
942 "find_srid('%s', '%s', '%s'), %f, '%s')",
945 with_z ==
WITH_Z ?
"t" :
"f");
947 if (
pg_info->toposchema_id == -1) {
956 "SELECT topology.AddTopoGeometryColumn('%s', '%s', '%s', "
960 get_sftype(
pg_info->feature_type));
968 "CREATE INDEX \"%s_%s_%s_idx\" ON \"%s\".\"%s\" (((%s).id))",
979 if (-1 == set_constraint_to_deferrable(
pg_info,
"node",
"face_exists",
980 "containing_face",
"face",
982 -1 == set_constraint_to_deferrable(
pg_info,
"edge_data",
983 "end_node_exists",
"end_node",
984 "node",
"node_id") ||
985 -1 == set_constraint_to_deferrable(
pg_info,
"edge_data",
986 "left_face_exists",
"left_face",
987 "face",
"face_id") ||
988 -1 == set_constraint_to_deferrable(
989 pg_info,
"edge_data",
"right_face_exists",
"right_face",
990 "face",
"face_id") ||
991 -1 == set_constraint_to_deferrable(
pg_info,
"edge_data",
993 "start_node",
"node",
"node_id"))
1005 "CREATE TABLE \"%s\".%s (node_id SERIAL PRIMARY KEY, "
1006 "lines integer[], angles float[])",
1014 "ALTER TABLE \"%s\".%s ADD CONSTRAINT node_exists "
1015 "FOREIGN KEY (node_id) REFERENCES \"%s\".node (node_id) "
1016 "DEFERRABLE INITIALLY DEFERRED",
1028 "CREATE TABLE \"%s\".%s (line_id SERIAL PRIMARY KEY, "
1029 "left_area integer, right_area integer)",
1037 "ALTER TABLE \"%s\".%s ADD CONSTRAINT line_exists "
1038 "FOREIGN KEY (line_id) REFERENCES \"%s\".edge_data (edge_id) "
1039 "DEFERRABLE INITIALLY DEFERRED",
1052 "CREATE TABLE \"%s\".%s (area_id SERIAL PRIMARY KEY, "
1053 "lines integer[], centroid integer, isles integer[])",
1065 "CREATE TABLE \"%s\".%s (isle_id SERIAL PRIMARY KEY, "
1066 "lines integer[], area integer)",
1101int create_pg_layer(
struct Map_info *
Map,
int type)
1109 G_warning(
_(
"Connection string not defined"));
1114 G_warning(
_(
"PostGIS feature table not defined"));
1118 G_debug(1,
"Vect__open_new_pg(): conninfo='%s' table='%s' -> type = %d",
1142 G_warning(
_(
"Unsupported geometry type (%d)"), type);
1155 G_warning(
_(
"More layers defined, using driver <%s> and "
1160 G_warning(
_(
"Database connection not defined. "
1161 "Unable to write attributes."));
1166 if (create_table(
pg_info) == -1) {
1167 G_warning(
_(
"Unable to create new PostGIS feature table"));
1172 if (
pg_info->toposchema_name) {
1181 G_warning(
_(
"Unable to create new PostGIS topology schema"));
1211 return "COLLECTION";
1254 G_warning(
_(
"PostGIS feature table not defined"));
1260 if (create_pg_layer(
Map, type) < 0)
1275 G_warning(
_(
"No category defined for layer %d"), field);
1277 G_warning(
_(
"Feature has more categories, using "
1278 "category %d (from layer %d)"),
1283 sf_type =
pg_info->feature_type;
1288 G_warning(
_(
"Point skipped (output feature type: %s)"),
1295 G_warning(
_(
"Line skipped (output feature type: %s)"),
1302 G_warning(
_(
"Centroid skipped (output feature type: %s)"),
1309 G_warning(
_(
"Boundary skipped (output feature type: %s)"),
1316 G_warning(
_(
"Face skipped (output feature type: %s)"),
1322 G_warning(
_(
"Unsupported feature type %d"), type);
1326 G_debug(3,
"write_line_sf(): type = %d n_points = %d cat = %d", type,
1327 points[0]->n_points, cat);
1333 for (part = 0; part <
nparts; part++) {
1334 npoints = points[part]->
n_points - 1;
1335 if (points[part]->x[0] != points[part]->x[npoints] ||
1336 points[part]->y[0] != points[part]->y[npoints] ||
1337 points[part]->z[0] != points[part]->z[npoints]) {
1338 G_warning(
_(
"Boundary is not closed. Skipping."));
1345 if (-1 == write_feature(
Map, -1, type, points,
nparts, cat)) {
1363 G_debug(3,
"write_line_sf(): -> offset = %lu offset_num = %d cat = %d",
1364 (
unsigned long)offset,
offset_info->array_num, cat);
1393 plus = &(
Map->plus);
1401 G_warning(
_(
"Invalid feature type (%d) for nodes"), type);
1411 G_warning(
_(
"PostGIS feature table not defined"));
1414 if (!
pg_info->toposchema_name) {
1415 G_warning(
_(
"PostGIS topology schema not defined"));
1421 if (create_pg_layer(
Map, type) < 0)
1428 G_debug(3,
"write_line_pg(): type = %d n_points = %d", type,
1434 if (cats && cats->
n_cats > 0) {
1439 G_warning(
_(
"No category defined for layer %d"),
Fi->number);
1441 G_warning(
_(
"Feature has more categories, using "
1442 "category %d (from layer %d)"),
1443 cat, cats->
field[0]);
1471 line = add_line_to_topo_pg(
Map, offset, type, points);
1479 line_id = write_feature(
Map, line, type, &points, 1, cat);
1489 pg_info->cache.lines_types[line - 1] = type;
1490 pg_info->cache.lines_cats[line - 1] = cat;
1514 update_topo_face(
Map, line);
1529char *binary_to_hex(
int nbytes,
const unsigned char *wkb_data)
1533 static const char ach_hex[] =
"0123456789ABCDEF";
1538 for (i = 0; i < nbytes; i++) {
1539 nlow = wkb_data[i] & 0x0f;
1540 nhigh = (wkb_data[i] & 0xf0) >> 4;
1562unsigned char *point_to_wkb(
int byte_order,
const struct line_pnts *points,
1563 int with_z,
int *
nsize)
1565 unsigned char *wkb_data;
1566 unsigned int sf_type;
1572 *
nsize = with_z ? 29 : 21;
1576 G_debug(5,
"\t->point size=%d (with_z = %d)", *
nsize, with_z);
1580 wkb_data[0] =
'\001';
1582 wkb_data[0] =
'\000';
1591 memcpy(wkb_data + 1, &sf_type, 4);
1594 memcpy(wkb_data + 5, &(points->
x[0]), 8);
1595 memcpy(wkb_data + 5 + 8, &(points->
y[0]), 8);
1598 memcpy(wkb_data + 5 + 16, &(points->
z[0]), 8);
1626unsigned char *linestring_to_wkb(
int byte_order,
const struct line_pnts *points,
1627 int with_z,
int *
nsize)
1630 unsigned char *wkb_data;
1631 unsigned int sf_type;
1642 G_debug(5,
"\t->linestring size=%d (with_z = %d)", *
nsize, with_z);
1646 wkb_data[0] =
'\001';
1648 wkb_data[0] =
'\000';
1657 memcpy(wkb_data + 1, &sf_type, 4);
1663 for (i = 0; i < points->
n_points; i++) {
1674 int npoints, nitems;
1677 memcpy(wkb_data + 5, &npoints, 4);
1679 nitems = (with_z ? 3 : 2) * points->
n_points;
1680 for (i = 0; i < nitems; i++) {
1702unsigned char *polygon_to_wkb(
int byte_order,
const struct line_pnts **points,
1706 unsigned char *wkb_data;
1707 unsigned int sf_type;
1712 for (ring = 0; ring <
nrings; ring++) {
1713 if (points[ring]->n_points < 3)
1720 for (ring = 0; ring <
nrings; ring++)
1725 G_debug(5,
"\t->polygon size=%d (with_z = %d)", *
nsize, with_z);
1729 wkb_data[0] =
'\001';
1731 wkb_data[0] =
'\000';
1740 memcpy(wkb_data + 1, &sf_type, 4);
1755 for (ring = 0; ring <
nrings; ring++) {
1756 memcpy(wkb_data + offset, &(points[ring]->n_points), 4);
1757 for (i = 0; i < points[ring]->
n_points; i++) {
1759 &(points[ring]->x[i]), 8);
1761 &(points[ring]->y[i]), 8);
1765 &(points[ring]->z[i]), 8);
1773 int npoints, nitems;
1775 npoints =
SWAP32(points[ring]->n_points);
1776 memcpy(wkb_data + 5, &npoints, 4);
1778 nitems = (with_z ? 3 : 2) * points[ring]->n_points;
1779 for (i = 0; i < nitems; i++) {
1806 int byte_order, nbytes,
nsize;
1807 unsigned int sf_type;
1809 unsigned char *wkb_data;
1818 wkb_data = point_to_wkb(byte_order, points[0], with_z, &nbytes);
1821 wkb_data = linestring_to_wkb(byte_order, points[0], with_z, &nbytes);
1826 polygon_to_wkb(byte_order, points,
nparts, with_z, &nbytes);
1831 linestring_to_wkb(byte_order, points[0], with_z, &nbytes);
1835 if (!wkb_data || nbytes < 1) {
1836 G_warning(
_(
"Unsupported feature type %d"), type);
1843 nsize = nbytes * 2 + 8 + 1;
1847 hex_data = binary_to_hex(1, wkb_data);
1853 memcpy(&sf_type, wkb_data + 1, 4);
1866 hex_data = binary_to_hex(4, (
unsigned char *)&sf_type);
1885 hex_data = binary_to_hex(nbytes - 5, wkb_data + 5);
1906int write_feature(
struct Map_info *
Map,
int line,
int type,
1915 with_z =
Map->head.with_z;
1917 if (with_z &&
pg_info->coor_dim != 3) {
1918 G_warning(
_(
"Trying to insert 3D data into feature table "
1919 "which store 2D data only"));
1922 if (!with_z &&
pg_info->coor_dim != 2) {
1923 G_warning(
_(
"Trying to insert 2D data into feature table "
1924 "which store 3D data only"));
1934 if (!
pg_info->inTransaction) {
1944 if (
pg_info->toposchema_name) {
1948 G_warning(
_(
"Unable to insert topological element into PostGIS "
1949 "Topology schema"));
2007 if (
pg_info->toposchema_name) {
2016 if (
Fi && cat > -1) {
2034 snprintf(buf,
sizeof(buf),
"SELECT * FROM %s WHERE %s = %d",
Fi->table,
2040 snprintf(buf,
sizeof(buf),
"INSERT INTO \"%s\".\"%s\" (",
2046 G_warning(
_(
"Unable to select attributes for category %d"), cat);
2050 G_warning(
_(
"Unable to fetch data from table <%s>"),
Fi->table);
2054 G_warning(
_(
"No database record for category %d, "
2055 "no attributes will be written"),
2080 G_warning(
_(
"FID column must be integer, column <%s> "
2119 G_warning(
_(
"Unsupported column type %d"), ctype);
2126 G_warning(
_(
"Invalid value for FID column: NULL"));
2134 if (!
pg_info->toposchema_name) {
2136 G_asprintf(&stmt,
"%s,%s) VALUES (%s,'%s'::GEOMETRY)", buf,
2142 if (buf[
strlen(buf) - 1] ==
',') {
2143 buf[
strlen(buf) - 1] =
'\0';
2147 "%s, %s) VALUES (%s, '(%d, 1, %d, "
2148 "%d)'::topology.TopoGeometry)",
2157 if (!
pg_info->toposchema_name) {
2162 "INSERT INTO \"%s\".\"%s\" (%s,%s) VALUES "
2163 "(%d, '%s'::GEOMETRY)",
2170 "INSERT INTO \"%s\".\"%s\" (%s) VALUES "
2180 "INSERT INTO \"%s\".\"%s\" (%s,%s) VALUES "
2181 "(%d, '(%d, 1, %d, %d)'::topology.TopoGeometry)",
2205int insert_topo_element(
struct Map_info *
Map,
int id,
int type,
2215 plus = &(
Map->plus);
2257 G_asprintf(&stmt,
"SELECT topology.AddNode('%s', '%s'::GEOMETRY)",
2263 "SELECT nextval('\"%s\".node_node_id_seq')",
2270 "INSERT INTO \"%s\".node (node_id, geom) VALUES "
2271 "(%d, '%s'::GEOMETRY)",
2280 G_asprintf(&stmt,
"SELECT topology.AddEdge('%s', '%s'::GEOMETRY)",
2292 "SELECT nextval('\"%s\".edge_data_edge_id_seq')",
2310 for (i = 0; i < 2; i++) {
2326 G_warning(
_(
"Unable to determine next left/right edge for "
2333 G_warning(
_(
"Unable to insert new edge. Topology not available."));
2337 G_debug(3,
"new edge: id=%d next_left_edge=%d next_right_edge=%d",
2347 "INSERT INTO \"%s\".edge_data (edge_id, start_node, end_node, "
2348 "next_left_edge, abs_next_left_edge, next_right_edge, "
2349 "abs_next_right_edge, "
2350 "left_face, right_face, geom) VALUES "
2351 "(%d, %d, %d, %d, %d, %d, %d, 0, 0, '%s'::GEOMETRY)",
2360 G_asprintf(&stmt,
"SELECT topology.AddNode('%s', '%s'::GEOMETRY)",
2368 "SELECT nextval('\"%s\".node_node_id_seq')",
2384 "INSERT INTO \"%s\".node (node_id, containing_face, geom) VALUES "
2385 "(%d, %d, '%s'::GEOMETRY)",
2391 G_warning(
_(
"Unsupported feature type %d"), type);
2413 switch (
pg_info->feature_type) {
2441 "INSERT into \"%s\".relation VALUES(%d, 1, %d, %d)",
2465int update_next_edge(
struct Map_info *
Map,
int nlines,
int line)
2467 int ret, next_line, edge;
2483 G_debug(3,
"line=%d next_line=%d", line, next_line);
2484 if (next_line == 0) {
2489 Line =
Map->plus.Line[
abs(line)];
2505 if (next_line < 0) {
2507 "UPDATE \"%s\".edge_data SET next_left_edge = %d, "
2508 "abs_next_left_edge = %d WHERE edge_id = %d AND "
2509 "abs_next_left_edge = %d",
2512 G_debug(3,
"update edge=%d next_left_edge=%d (?)",
2517 "UPDATE \"%s\".edge_data SET next_right_edge = %d, "
2518 "abs_next_right_edge = %d WHERE edge_id = %d AND "
2519 "abs_next_right_edge = %d",
2522 G_debug(3,
"update edge=%d next_right_edge=%d (?)",
2541 if (next_line < 0) {
2543 "UPDATE \"%s\".edge_data SET next_left_edge = %d, "
2544 "abs_next_left_edge = %d WHERE edge_id = %d",
2547 G_debug(3,
"update edge=%d next_left_edge=%d",
2552 "UPDATE \"%s\".edge_data SET next_right_edge = %d, "
2553 "abs_next_right_edge = %d WHERE edge_id = %d",
2556 G_debug(3,
"update edge=%d next_right_edge=%d",
2601 "INSERT INTO \"%s\".face (face_id, mbr) VALUES "
2602 "(%d, ST_GeomFromText('POLYGON((%.12f %.12f, %.12f %.12f, %.12f "
2603 "%.12f, %.12f %.12f, "
2604 "%.12f %.12f))', %d))",
2605 pg_info->toposchema_name, area, box.
W, box.
S, box.
W, box.
N,
2607 G_debug(3,
"new face id=%d", area);
2639 snprintf(stmt,
sizeof(stmt),
"UPDATE \"%s\".node SET containing_face = 0 "
2640 "WHERE containing_face = %d",
pg_info->toposchema_name, area);
2648 snprintf(stmt,
sizeof(stmt),
"UPDATE \"%s\".edge_data SET left_face = 0 "
2649 "WHERE left_face = %d",
pg_info->toposchema_name, area);
2657 snprintf(stmt,
sizeof(stmt),
"UPDATE \"%s\".edge_data SET right_face = 0 "
2658 "WHERE right_face = %d",
pg_info->toposchema_name, area);
2666 snprintf(stmt,
sizeof(stmt),
"DELETE FROM \"%s\".face WHERE face_id = %d",
2667 pg_info->toposchema_name, area);
2668 G_debug(3,
"delete face id=%d", area);
2706 G_warning(
_(
"Attempt to access non-existing feature %d"), line);
2709 Line =
Map->plus.Line[line];
2711 G_warning(
_(
"Attempt to access dead feature %d"), line);
2720 for (i = 0; i < 2; i++) {
2728 next_edge = update_next_edge(
Map, n, i == 0 ? line : -line);
2736 G_warning(
_(
"Unable to determine next left/right edge"));
2741 if (
nle == 0 &&
nre == 0)
2744 if (
nle != 0 &&
nre != 0) {
2746 snprintf(stmt,
sizeof(stmt),
"UPDATE \"%s\".edge_data SET "
2747 "next_left_edge = %d, abs_next_left_edge = %d, "
2748 "next_right_edge = %d, abs_next_right_edge = %d "
2749 "WHERE edge_id = %d",
pg_info->toposchema_name,
2752 else if (
nle != 0) {
2754 snprintf(stmt,
sizeof(stmt),
"UPDATE \"%s\".edge_data SET "
2755 "next_left_edge = %d, abs_next_left_edge = %d "
2756 "WHERE edge_id = %d",
pg_info->toposchema_name,
2761 snprintf(stmt,
sizeof(stmt),
"UPDATE \"%s\".edge_data SET "
2762 "next_right_edge = %d, abs_next_right_edge = %d "
2763 "WHERE edge_id = %d",
pg_info->toposchema_name,
2766 G_debug(3,
"update edge=%d next_left_edge=%d next_right_edge=%d",
2790int update_topo_face(
struct Map_info *
Map,
int line)
2792 int i, s, area,
face[2];
2803 G_warning(
_(
"Attempt to access non-existing feature %d"), line);
2806 Line =
Map->plus.Line[line];
2808 G_warning(
_(
"Attempt to access dead feature %d"), line);
2816 for (s = 0; s < 2; s++) {
2817 area = s == 0 ? topo->
left : topo->
right;
2829 for (s = 0; s < 2; s++) {
2830 area = s == 0 ? topo->
left : topo->
right;
2834 Area =
Map->plus.Area[area];
2835 for (i = 0; i < Area->
n_lines; i++) {
2841 "UPDATE \"%s\".edge_data SET "
2842 "left_face = %d, right_face = %d "
2843 "WHERE edge_id = %d",
2858 "UPDATE \"%s\".node SET containing_face = %d "
2859 "WHERE node_id = %d",
2892 plus = &(
Map->plus);
2906 for (i = 0; i <
n_nodes; i++) {
2912 G_debug(3,
" new node: %d", node);
2919 (
const struct line_pnts **)&Points, 1, -1);
2937int delete_line_from_topo_pg(
struct Map_info *
Map,
int line,
int type,
2957 Node =
Map->plus.Node[N1];
2958 if (!Node || Node->
n_lines == 0) {
2961 "DELETE FROM \"%s\".\"node\" WHERE node_id = %d",
2970 Node =
Map->plus.Node[N2];
2971 if (!Node || Node->
n_lines == 0) {
2974 "DELETE FROM \"%s\".\"node\" WHERE node_id = %d",
2987 const char *table,
const char *constraint,
2993 snprintf(stmt,
sizeof(stmt),
"ALTER TABLE \"%s\".%s DROP CONSTRAINT %s",
2994 pg_info->toposchema_name, table, constraint);
3001 "ALTER TABLE \"%s\".%s ADD CONSTRAINT %s "
3002 "FOREIGN KEY (%s) REFERENCES \"%s\".%s (%s) "
3003 "DEFERRABLE INITIALLY DEFERRED",
3035 G_warning(
_(
"Unable to start driver <%s>"),
Fi->driver);
3040 G_warning(
_(
"Unable to open database <%s> by driver <%s>"),
3041 Fi->database,
Fi->driver);
#define DB_C_TYPE_DATETIME
#define DB_SQL_TYPE_CHARACTER
int db_test_value_isnull(dbValue *)
Check of value is null.
int db_describe_table(dbDriver *, dbString *, dbTable **)
Describe table.
int db_get_column_length(dbColumn *)
Get column's length.
dbColumn * db_get_table_column(dbTable *, int)
Returns column structure for given table and column number.
double db_get_value_double(dbValue *)
Get double precision value.
int db_sqltype_to_Ctype(int)
Get C data type based on given SQL data type.
dbValue * db_get_column_value(dbColumn *)
Returns column value for given column structure.
int db_get_column_sqltype(dbColumn *)
Returns column sqltype for column.
int db_open_database(dbDriver *, dbHandle *)
Open database connection.
int db_close_database_shutdown_driver(dbDriver *)
Close driver/database connection.
void db_free_string(dbString *)
Free allocated space for dbString.
char * db_get_string(const dbString *)
Get string.
dbTable * db_get_cursor_table(dbCursor *)
Get table allocated by cursor.
int db_set_string(dbString *, const char *)
Inserts string to dbString (enlarge string)
const char * db_get_column_name(dbColumn *)
Returns column name for given column.
int db_set_handle(dbHandle *, const char *, const char *)
Set handle (database and schema name)
int db_get_value_int(dbValue *)
Get integer value.
dbDriver * db_start_driver(const char *)
Initialize a new dbDriver for db transaction.
void db_init_handle(dbHandle *)
Initialize handle (i.e database/schema)
void db_init_string(dbString *)
Initialize dbString.
int db_open_select_cursor(dbDriver *, dbString *, dbCursor *, int)
Open select cursor.
const char * db_sqltype_name(int)
Get SQL data type description.
int db_convert_column_value_to_string(dbColumn *, dbString *)
?
const char * db_get_value_string(dbValue *)
Get string value.
int db_fetch(dbCursor *, int, int *)
Fetch data from open cursor.
int db_get_table_number_of_columns(dbTable *)
Return the number of columns of the table.
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
void G_free(void *)
Free allocated memory.
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
void void G_verbose_message(const char *,...) __attribute__((format(printf
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
const char * G_find_file2(const char *, const char *, const char *)
Searches for a file from the mapset search list or in a specified mapset. (look but don't touch)
void G_free_key_value(struct Key_Value *)
Free allocated Key_Value structure.
int G_asprintf(char **, const char *,...) __attribute__((format(printf
const char * G_find_key_value(const char *, const struct Key_Value *)
Find given key (case sensitive)
struct Key_Value * G_fread_key_value(FILE *)
Read key/values pairs from file.
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
char * G_store(const char *)
Copy string to allocated memory.
char * G_str_replace(const char *, const char *, const char *)
Replace all occurrences of old_str in buffer with new_str.
int G_debug(int, const char *,...) __attribute__((format(printf
const char * G_mapset(void)
Get current mapset name.
void Vect_destroy_line_struct(struct line_pnts *)
Frees all memory associated with a line_pnts structure, including the structure itself.
int Vect_get_line_nodes(struct Map_info *, int, int *, int *)
Get line nodes.
off_t V2_write_line_sfa(struct Map_info *, int, const struct line_pnts *, const struct line_cats *)
Writes feature on level 2 (OGR/PostGIS interface, pseudo-topological level)
int Vect_get_node_coor(struct Map_info *, int, double *, double *, double *)
Get node coordinates.
int Vect_get_updated_node(struct Map_info *, int)
Get updated (modified) node by index.
int V2_read_line_pg(struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read feature from PostGIS layer on topological level.
int Vect_cat_get(const struct line_cats *, int, int *)
Get first found category of given field.
plus_t Vect_get_num_primitives(struct Map_info *, int)
Get number of primitives in vector map.
void Vect_reset_updated(struct Map_info *)
Reset list of updated lines/nodes.
int Vect_get_area_box(struct Map_info *, int, struct bound_box *)
Get bounding box of area.
const char * Vect_get_finfo_geometry_type(struct Map_info *)
Get geometry type as string (relevant only for non-native formats)
struct field_info * Vect_get_dblink(struct Map_info *, int)
Get information about link to database.
int Vect_get_num_dblinks(struct Map_info *)
Get number of defined dblinks.
int Vect_get_num_updated_nodes(struct Map_info *)
Get number of updated nodes.
int Vect_get_isle_box(struct Map_info *, int, struct bound_box *)
Get bounding box of isle.
int Vect_get_node_n_lines(struct Map_info *, int)
Get number of lines for node.
plus_t Vect_get_num_nodes(struct Map_info *)
Get number of nodes in vector map.
void Vect_reset_line(struct line_pnts *)
Reset line.
int V1_read_line_pg(struct Map_info *, struct line_pnts *, struct line_cats *, off_t)
Read feature from PostGIS layer at given offset (level 1 without topology)
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
int Vect_is_3d(struct Map_info *)
Check if vector map is 3D.
void Vect_set_updated(struct Map_info *, int)
Enable/disable maintenance of list of updated lines/nodes.
int Vect_append_point(struct line_pnts *, double, double, double)
Appends one point to the end of a line.
int V2_delete_line_sfa(struct Map_info *, off_t)
Deletes feature on level 2 (OGR/PostGIS interface)
SF_FeatureType
Simple feature types.
#define GV_POINT
Feature types used in memory on run time (may change)
#define GV_BUILD_BASE
Topology levels - basic level (without areas and isles)
#define GV_BUILD_AREAS
Topology levels - build areas.
#define LEVEL_2
Vector level - with 2D topology.
#define GV_LEFT
Boundary side indicator left/right.
int dig_angle_next_line(struct Plus_head *, plus_t, int, int, float *)
Find line number of next angle to follow a line.
int dig__byte_order_out(void)
Get byte order.
int dig_add_node(struct Plus_head *, double, double, double)
Add new node to plus structure.
#define GV_KEY_COLUMN
Name of default key column.
#define ENDIAN_LITTLE
Endian check.
#define UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
int Vect__execute_get_value_pg(PGconn *conn, const char *stmt)
Execute SQL statement and get value.
int Vect__execute_pg(PGconn *conn, const char *stmt)
Execute SQL statement.
void Vect__reallocate_cache(struct Format_info_cache *cache, int num, int incr)
Reallocate lines cache.
plus_t n_lines
Number of boundary lines.
plus_t * lines
List of boundary lines.
plus_t centroid
Number of first centroid within area.
off_t offset
Offset in coor file for line.
void * topo
Topology info.
Topological feature - node.
plus_t n_lines
Number of attached lines (size of lines, angle)
plus_t left
Area number to the left, negative for isle.
plus_t right
Area number to the right, negative for isle.
plus_t area
Area number, negative for duplicate centroid.
Basic topology-related info.
plus_t n_nodes
Current number of topological features derived from vector geometries.
int cidx_up_to_date
Category index to be updated.
int update_cidx
Update category index if vector is modified.
struct P_node ** Node
Array of nodes.
int built
Highest level of topology currently available.
Layer (old: field) information.
char * table
Name of DB table.
int * field
Array of layers (fields)
int n_cats
Number of categories attached to element.
Feature geometry info - coordinates.
double * y
Array of Y coordinates.
double * x
Array of X coordinates.
int n_points
Number of points.
double * z
Array of Z coordinates.
int V2__add_line_to_topo_nat(struct Map_info *Map, off_t offset, int type, const struct line_pnts *points, const struct line_cats *cats, int restore_line, int(*external_routine)(struct Map_info *, int))
Add feature (line) to topology (internal use only)
int V2__delete_line_from_topo_nat(struct Map_info *Map, int line, int type, const struct line_pnts *points, const struct line_cats *cats)
Delete feature from topology (internal use only)
int Vect__define_topo_relation(const struct Format_info_pg *pg_info, int topo_id, int element_id)
int V2_delete_line_pg(struct Map_info *Map, off_t line)
Deletes feature on topological level (PostGIS interface)
off_t V1_rewrite_line_pg(struct Map_info *Map, off_t offset, int type, const struct line_pnts *points, const struct line_cats *cats)
Rewrites feature at the given offset (level 1) (PostGIS interface, internal use only)
off_t V2_write_line_pg(struct Map_info *Map, int type, const struct line_pnts *points, const struct line_cats *cats)
Writes feature on topological level (PostGIS interface)
off_t V1_write_line_pg(struct Map_info *Map, int type, const struct line_pnts *points, const struct line_cats *cats)
Writes feature on level 1 (PostGIS interface)
off_t V2__write_area_pg(struct Map_info *Map, const struct line_pnts **points, int nparts, const struct line_cats *cats)
Writes area on topological level (PostGIS Simple Features interface, internal use only)
int V2__update_area_pg(struct Map_info *Map, const struct line_pnts **points, int nparts, int cat)
Updates simple features geometry from GRASS-like topo.
off_t V2__write_node_pg(struct Map_info *Map, const struct line_pnts *points)
Writes node on topological level (PostGIS Topology interface, internal use only)
int Vect__insert_face_pg(struct Map_info *Map, int area)
Insert new face to the 'face' table (topo only)
int V1_delete_line_pg(struct Map_info *Map, off_t offset)
Deletes feature at the given offset (level 1)
off_t V2_rewrite_line_pg(struct Map_info *Map, off_t line, int type, const struct line_pnts *points, const struct line_cats *cats)
Rewrites feature at topological level (PostGIS interface, internal use only)