27#include "local_proto.h"
30#include "pg_local_proto.h"
32#define WKBSRIDFLAG 0x20000000
34#define TOPOGEOM_COLUMN "topo"
39#define USE_TOPO_STMT 0
44static int create_pg_layer(
struct Map_info *,
int);
50static char *binary_to_hex(
int,
const unsigned char *);
51static unsigned char *point_to_wkb(
int,
const struct line_pnts *,
int,
int *);
52static unsigned char *linestring_to_wkb(
int,
const struct line_pnts *,
int,
54static unsigned char *polygon_to_wkb(
int,
const struct line_pnts **,
int,
int,
60static char *build_insert_stmt(
const struct Format_info_pg *,
const char *,
int,
62static int insert_topo_element(
struct Map_info *,
int,
int,
const char *);
64static int update_next_edge(
struct Map_info *,
int,
int);
70static int update_topo_face(
struct Map_info *,
int);
73static int delete_line_from_topo_pg(
struct Map_info *,
int,
int,
75static int set_constraint_to_deferrable(
struct Format_info_pg *,
const char *,
76 const char *,
const char *,
77 const char *,
const char *);
84#define NOPG_UNUSED G_UNUSED
119 if (create_pg_layer(
Map, type) < 0)
126 if (!
pg_info->toposchema_name) {
127 return write_line_sf(
Map, type, &points, 1, cats);
131 return write_line_tp(
Map, type,
FALSE, points, cats);
133 G_fatal_error(
_(
"GRASS is not compiled with PostgreSQL support"));
160 if (!
pg_info->toposchema_name) {
165 return write_line_tp(
Map, type,
FALSE, points, cats);
167 G_fatal_error(
_(
"GRASS is not compiled with PostgreSQL support"));
196 G_warning(
_(
"Unable to rewrite feature (incompatible feature types)"));
205 G_fatal_error(
_(
"GRASS is not compiled with PostgreSQL support"));
232 G_debug(3,
"V2_rewrite_line_pg(): line=%d type=%d", (
int)line, type);
246 G_warning(
_(
"Attempt to access feature with invalid id (%d)"),
251 Line =
Map->plus.Line[line];
253 G_warning(
_(
"Attempt to access dead feature %d"), (
int)line);
258 if (!(
Map->plus.update_cidx)) {
266 G_warning(
_(
"Unable to rewrite feature (incompatible feature types)"));
271 if (0 != delete_line_from_topo_pg(
Map, line,
type, Points))
274 if (
pg_info->toposchema_name) {
275 schema_name =
pg_info->toposchema_name;
280 table_name =
"edge_data";
285 schema_name =
pg_info->schema_name;
286 table_name =
pg_info->table_name;
292 "UPDATE \"%s\".\"%s\" SET geom = '%s'::GEOMETRY WHERE %s_id = "
298 G_warning(
_(
"Unable to rewrite feature %d"), (
int)line);
307 G_fatal_error(
_(
"GRASS is not compiled with PostgreSQL support"));
346 G_debug(3,
"V1_delete_line_pg(): offset = %lu -> fid = %ld",
347 (
unsigned long)
offset, fid);
356 snprintf(stmt,
sizeof(stmt),
"DELETE FROM %s WHERE %s = %ld",
368 G_fatal_error(
_(
"GRASS is not compiled with PostgreSQL support"));
395 G_warning(
_(
"Attempt to access feature with invalid id (%d)"),
400 if (!
pg_info->toposchema_name) {
411 G_warning(
_(
"Attempt to access feature with invalid id (%d)"),
416 Line =
Map->plus.Line[line];
418 G_warning(
_(
"Attempt to access dead feature %d"), (
int)line);
422 if (!(
Map->plus.update_cidx)) {
423 Map->plus.cidx_up_to_date =
433 table_name =
"edge_data";
439 "UPDATE \"%s\".\"%s\" SET abs_next_left_edge = edge_id, "
440 "next_left_edge = -edge_id WHERE abs_next_left_edge = %d",
449 "UPDATE \"%s\".\"%s\" SET abs_next_right_edge = edge_id, "
450 "next_right_edge = edge_id WHERE abs_next_right_edge = %d",
468 stmt,
sizeof(stmt),
"DELETE FROM \"%s\".\"%s\" WHERE %s_id = %d",
482 pg_info->cache.lines_types[line - 1] = 0;
483 pg_info->cache.lines_cats[line - 1] = 0;
487 ret = delete_line_from_topo_pg(
Map, line,
type, Points);
495 G_fatal_error(
_(
"GRASS is not compiled with PostgreSQL support"));
566 for (part = 0; part <
nparts; part++) {
567 npoints = points[part]->
n_points - 1;
568 if (points[part]->
x[0] != points[part]->
x[npoints] ||
569 points[part]->y[0] != points[part]->y[npoints] ||
570 points[part]->z[0] != points[part]->z[npoints]) {
571 G_warning(
_(
"Boundary is not closed. Skipping."));
582 "UPDATE \"%s\".\"%s\" SET %s = '%s'::GEOMETRY WHERE %s = %d",
651 if (check_schema(
pg_info) != 0)
657 "CREATE TABLE \"%s\".\"%s\" (%s SERIAL%s, %s INTEGER",
684 G_warning(
_(
"Unable to describe table <%s>"),
Fi->table);
692 "copying attributes: driver = %s database = %s table = %s cols "
694 Fi->driver,
Fi->database,
Fi->table, ncols);
702 G_debug(3,
"\tcolumn = %d name = %s type = %d length = %d",
col,
739 switch (
pg_info->feature_type) {
763 "SELECT AddGeometryColumn('%s', '%s', "
764 "'%s', %d, '%s', %d)",
781 snprintf(stmt,
sizeof(stmt),
"CREATE INDEX %s_%s_idx ON \"%s\".\"%s\" (%s)",
793 "CREATE INDEX %s_%s_idx ON \"%s\".\"%s\" USING GIST (%s)",
833 snprintf(stmt,
sizeof(stmt),
"SELECT nspname FROM pg_namespace");
853 snprintf(stmt,
sizeof(stmt),
"CREATE SCHEMA %s",
pg_info->schema_name);
858 G_warning(
_(
"Schema <%s> doesn't exist, created"),
906 G_debug(1,
"PG: tolerance: %f", tolerance);
940 "SELECT topology.createtopology('%s', "
941 "find_srid('%s', '%s', '%s'), %f, '%s')",
944 with_z ==
WITH_Z ?
"t" :
"f");
946 if (
pg_info->toposchema_id == -1) {
955 "SELECT topology.AddTopoGeometryColumn('%s', '%s', '%s', "
959 get_sftype(
pg_info->feature_type));
967 "CREATE INDEX \"%s_%s_%s_idx\" ON \"%s\".\"%s\" (((%s).id))",
978 if (-1 == set_constraint_to_deferrable(
pg_info,
"node",
"face_exists",
979 "containing_face",
"face",
981 -1 == set_constraint_to_deferrable(
pg_info,
"edge_data",
982 "end_node_exists",
"end_node",
983 "node",
"node_id") ||
984 -1 == set_constraint_to_deferrable(
pg_info,
"edge_data",
985 "left_face_exists",
"left_face",
986 "face",
"face_id") ||
987 -1 == set_constraint_to_deferrable(
988 pg_info,
"edge_data",
"right_face_exists",
"right_face",
989 "face",
"face_id") ||
990 -1 == set_constraint_to_deferrable(
pg_info,
"edge_data",
992 "start_node",
"node",
"node_id"))
1004 "CREATE TABLE \"%s\".%s (node_id SERIAL PRIMARY KEY, "
1005 "lines integer[], angles float[])",
1013 "ALTER TABLE \"%s\".%s ADD CONSTRAINT node_exists "
1014 "FOREIGN KEY (node_id) REFERENCES \"%s\".node (node_id) "
1015 "DEFERRABLE INITIALLY DEFERRED",
1027 "CREATE TABLE \"%s\".%s (line_id SERIAL PRIMARY KEY, "
1028 "left_area integer, right_area integer)",
1036 "ALTER TABLE \"%s\".%s ADD CONSTRAINT line_exists "
1037 "FOREIGN KEY (line_id) REFERENCES \"%s\".edge_data (edge_id) "
1038 "DEFERRABLE INITIALLY DEFERRED",
1051 "CREATE TABLE \"%s\".%s (area_id SERIAL PRIMARY KEY, "
1052 "lines integer[], centroid integer, isles integer[])",
1064 "CREATE TABLE \"%s\".%s (isle_id SERIAL PRIMARY KEY, "
1065 "lines integer[], area integer)",
1100int create_pg_layer(
struct Map_info *
Map,
int type)
1108 G_warning(
_(
"Connection string not defined"));
1113 G_warning(
_(
"PostGIS feature table not defined"));
1117 G_debug(1,
"Vect__open_new_pg(): conninfo='%s' table='%s' -> type = %d",
1141 G_warning(
_(
"Unsupported geometry type (%d)"), type);
1154 G_warning(
_(
"More layers defined, using driver <%s> and "
1159 G_warning(
_(
"Database connection not defined. "
1160 "Unable to write attributes."));
1165 if (create_table(
pg_info) == -1) {
1166 G_warning(
_(
"Unable to create new PostGIS feature table"));
1171 if (
pg_info->toposchema_name) {
1180 G_warning(
_(
"Unable to create new PostGIS topology schema"));
1210 return "COLLECTION";
1253 G_warning(
_(
"PostGIS feature table not defined"));
1259 if (create_pg_layer(
Map, type) < 0)
1274 G_warning(
_(
"No category defined for layer %d"), field);
1276 G_warning(
_(
"Feature has more categories, using "
1277 "category %d (from layer %d)"),
1282 sf_type =
pg_info->feature_type;
1287 G_warning(
_(
"Point skipped (output feature type: %s)"),
1294 G_warning(
_(
"Line skipped (output feature type: %s)"),
1301 G_warning(
_(
"Centroid skipped (output feature type: %s)"),
1308 G_warning(
_(
"Boundary skipped (output feature type: %s)"),
1315 G_warning(
_(
"Face skipped (output feature type: %s)"),
1321 G_warning(
_(
"Unsupported feature type %d"), type);
1325 G_debug(3,
"write_line_sf(): type = %d n_points = %d cat = %d", type,
1326 points[0]->n_points, cat);
1332 for (part = 0; part <
nparts; part++) {
1333 npoints = points[part]->
n_points - 1;
1334 if (points[part]->x[0] != points[part]->x[npoints] ||
1335 points[part]->y[0] != points[part]->y[npoints] ||
1336 points[part]->z[0] != points[part]->z[npoints]) {
1337 G_warning(
_(
"Boundary is not closed. Skipping."));
1344 if (-1 == write_feature(
Map, -1, type, points,
nparts, cat)) {
1362 G_debug(3,
"write_line_sf(): -> offset = %lu offset_num = %d cat = %d",
1363 (
unsigned long)offset,
offset_info->array_num, cat);
1392 plus = &(
Map->plus);
1400 G_warning(
_(
"Invalid feature type (%d) for nodes"), type);
1410 G_warning(
_(
"PostGIS feature table not defined"));
1413 if (!
pg_info->toposchema_name) {
1414 G_warning(
_(
"PostGIS topology schema not defined"));
1420 if (create_pg_layer(
Map, type) < 0)
1427 G_debug(3,
"write_line_pg(): type = %d n_points = %d", type,
1433 if (cats && cats->
n_cats > 0) {
1438 G_warning(
_(
"No category defined for layer %d"),
Fi->number);
1440 G_warning(
_(
"Feature has more categories, using "
1441 "category %d (from layer %d)"),
1442 cat, cats->
field[0]);
1470 line = add_line_to_topo_pg(
Map, offset, type, points);
1478 line_id = write_feature(
Map, line, type, &points, 1, cat);
1488 pg_info->cache.lines_types[line - 1] = type;
1489 pg_info->cache.lines_cats[line - 1] = cat;
1513 update_topo_face(
Map, line);
1528char *binary_to_hex(
int nbytes,
const unsigned char *wkb_data)
1532 static const char ach_hex[] =
"0123456789ABCDEF";
1537 for (i = 0; i < nbytes; i++) {
1538 nlow = wkb_data[i] & 0x0f;
1539 nhigh = (wkb_data[i] & 0xf0) >> 4;
1561unsigned char *point_to_wkb(
int byte_order,
const struct line_pnts *points,
1562 int with_z,
int *
nsize)
1564 unsigned char *wkb_data;
1565 unsigned int sf_type;
1571 *
nsize = with_z ? 29 : 21;
1575 G_debug(5,
"\t->point size=%d (with_z = %d)", *
nsize, with_z);
1579 wkb_data[0] =
'\001';
1581 wkb_data[0] =
'\000';
1590 memcpy(wkb_data + 1, &sf_type, 4);
1593 memcpy(wkb_data + 5, &(points->
x[0]), 8);
1594 memcpy(wkb_data + 5 + 8, &(points->
y[0]), 8);
1597 memcpy(wkb_data + 5 + 16, &(points->
z[0]), 8);
1625unsigned char *linestring_to_wkb(
int byte_order,
const struct line_pnts *points,
1626 int with_z,
int *
nsize)
1629 unsigned char *wkb_data;
1630 unsigned int sf_type;
1641 G_debug(5,
"\t->linestring size=%d (with_z = %d)", *
nsize, with_z);
1645 wkb_data[0] =
'\001';
1647 wkb_data[0] =
'\000';
1656 memcpy(wkb_data + 1, &sf_type, 4);
1662 for (i = 0; i < points->
n_points; i++) {
1673 int npoints, nitems;
1676 memcpy(wkb_data + 5, &npoints, 4);
1678 nitems = (with_z ? 3 : 2) * points->
n_points;
1679 for (i = 0; i < nitems; i++) {
1701unsigned char *polygon_to_wkb(
int byte_order,
const struct line_pnts **points,
1705 unsigned char *wkb_data;
1706 unsigned int sf_type;
1711 for (ring = 0; ring <
nrings; ring++) {
1712 if (points[ring]->n_points < 3)
1719 for (ring = 0; ring <
nrings; ring++)
1724 G_debug(5,
"\t->polygon size=%d (with_z = %d)", *
nsize, with_z);
1728 wkb_data[0] =
'\001';
1730 wkb_data[0] =
'\000';
1739 memcpy(wkb_data + 1, &sf_type, 4);
1754 for (ring = 0; ring <
nrings; ring++) {
1755 memcpy(wkb_data + offset, &(points[ring]->n_points), 4);
1756 for (i = 0; i < points[ring]->
n_points; i++) {
1758 &(points[ring]->x[i]), 8);
1760 &(points[ring]->y[i]), 8);
1764 &(points[ring]->z[i]), 8);
1772 int npoints, nitems;
1774 npoints =
SWAP32(points[ring]->n_points);
1775 memcpy(wkb_data + 5, &npoints, 4);
1777 nitems = (with_z ? 3 : 2) * points[ring]->n_points;
1778 for (i = 0; i < nitems; i++) {
1805 int byte_order, nbytes,
nsize;
1806 unsigned int sf_type;
1808 unsigned char *wkb_data;
1817 wkb_data = point_to_wkb(byte_order, points[0], with_z, &nbytes);
1820 wkb_data = linestring_to_wkb(byte_order, points[0], with_z, &nbytes);
1825 polygon_to_wkb(byte_order, points,
nparts, with_z, &nbytes);
1830 linestring_to_wkb(byte_order, points[0], with_z, &nbytes);
1834 if (!wkb_data || nbytes < 1) {
1835 G_warning(
_(
"Unsupported feature type %d"), type);
1842 nsize = nbytes * 2 + 8 + 1;
1846 hex_data = binary_to_hex(1, wkb_data);
1852 memcpy(&sf_type, wkb_data + 1, 4);
1865 hex_data = binary_to_hex(4, (
unsigned char *)&sf_type);
1884 hex_data = binary_to_hex(nbytes - 5, wkb_data + 5);
1905int write_feature(
struct Map_info *
Map,
int line,
int type,
1914 with_z =
Map->head.with_z;
1916 if (with_z &&
pg_info->coor_dim != 3) {
1917 G_warning(
_(
"Trying to insert 3D data into feature table "
1918 "which store 2D data only"));
1921 if (!with_z &&
pg_info->coor_dim != 2) {
1922 G_warning(
_(
"Trying to insert 2D data into feature table "
1923 "which store 3D data only"));
1933 if (!
pg_info->inTransaction) {
1943 if (
pg_info->toposchema_name) {
1947 G_warning(
_(
"Unable to insert topological element into PostGIS "
1948 "Topology schema"));
2006 if (
pg_info->toposchema_name) {
2015 if (
Fi && cat > -1) {
2033 snprintf(buf,
sizeof(buf),
"SELECT * FROM %s WHERE %s = %d",
Fi->table,
2039 snprintf(buf,
sizeof(buf),
"INSERT INTO \"%s\".\"%s\" (",
2045 G_warning(
_(
"Unable to select attributes for category %d"), cat);
2049 G_warning(
_(
"Unable to fetch data from table <%s>"),
Fi->table);
2053 G_warning(
_(
"No database record for category %d, "
2054 "no attributes will be written"),
2079 G_warning(
_(
"FID column must be integer, column <%s> "
2118 G_warning(
_(
"Unsupported column type %d"), ctype);
2125 G_warning(
_(
"Invalid value for FID column: NULL"));
2133 if (!
pg_info->toposchema_name) {
2135 G_asprintf(&stmt,
"%s,%s) VALUES (%s,'%s'::GEOMETRY)", buf,
2141 if (buf[
strlen(buf) - 1] ==
',') {
2142 buf[
strlen(buf) - 1] =
'\0';
2146 "%s, %s) VALUES (%s, '(%d, 1, %d, "
2147 "%d)'::topology.TopoGeometry)",
2156 if (!
pg_info->toposchema_name) {
2161 "INSERT INTO \"%s\".\"%s\" (%s,%s) VALUES "
2162 "(%d, '%s'::GEOMETRY)",
2169 "INSERT INTO \"%s\".\"%s\" (%s) VALUES "
2179 "INSERT INTO \"%s\".\"%s\" (%s,%s) VALUES "
2180 "(%d, '(%d, 1, %d, %d)'::topology.TopoGeometry)",
2204int insert_topo_element(
struct Map_info *
Map,
int id,
int type,
2214 plus = &(
Map->plus);
2256 G_asprintf(&stmt,
"SELECT topology.AddNode('%s', '%s'::GEOMETRY)",
2262 "SELECT nextval('\"%s\".node_node_id_seq')",
2269 "INSERT INTO \"%s\".node (node_id, geom) VALUES "
2270 "(%d, '%s'::GEOMETRY)",
2279 G_asprintf(&stmt,
"SELECT topology.AddEdge('%s', '%s'::GEOMETRY)",
2291 "SELECT nextval('\"%s\".edge_data_edge_id_seq')",
2309 for (i = 0; i < 2; i++) {
2325 G_warning(
_(
"Unable to determine next left/right edge for "
2332 G_warning(
_(
"Unable to insert new edge. Topology not available."));
2336 G_debug(3,
"new edge: id=%d next_left_edge=%d next_right_edge=%d",
2346 "INSERT INTO \"%s\".edge_data (edge_id, start_node, end_node, "
2347 "next_left_edge, abs_next_left_edge, next_right_edge, "
2348 "abs_next_right_edge, "
2349 "left_face, right_face, geom) VALUES "
2350 "(%d, %d, %d, %d, %d, %d, %d, 0, 0, '%s'::GEOMETRY)",
2359 G_asprintf(&stmt,
"SELECT topology.AddNode('%s', '%s'::GEOMETRY)",
2367 "SELECT nextval('\"%s\".node_node_id_seq')",
2383 "INSERT INTO \"%s\".node (node_id, containing_face, geom) VALUES "
2384 "(%d, %d, '%s'::GEOMETRY)",
2390 G_warning(
_(
"Unsupported feature type %d"), type);
2412 switch (
pg_info->feature_type) {
2440 "INSERT into \"%s\".relation VALUES(%d, 1, %d, %d)",
2464int update_next_edge(
struct Map_info *
Map,
int nlines,
int line)
2466 int ret, next_line, edge;
2482 G_debug(3,
"line=%d next_line=%d", line, next_line);
2483 if (next_line == 0) {
2488 Line =
Map->plus.Line[
abs(line)];
2504 if (next_line < 0) {
2506 "UPDATE \"%s\".edge_data SET next_left_edge = %d, "
2507 "abs_next_left_edge = %d WHERE edge_id = %d AND "
2508 "abs_next_left_edge = %d",
2511 G_debug(3,
"update edge=%d next_left_edge=%d (?)",
2516 "UPDATE \"%s\".edge_data SET next_right_edge = %d, "
2517 "abs_next_right_edge = %d WHERE edge_id = %d AND "
2518 "abs_next_right_edge = %d",
2521 G_debug(3,
"update edge=%d next_right_edge=%d (?)",
2540 if (next_line < 0) {
2542 "UPDATE \"%s\".edge_data SET next_left_edge = %d, "
2543 "abs_next_left_edge = %d WHERE edge_id = %d",
2546 G_debug(3,
"update edge=%d next_left_edge=%d",
2551 "UPDATE \"%s\".edge_data SET next_right_edge = %d, "
2552 "abs_next_right_edge = %d WHERE edge_id = %d",
2555 G_debug(3,
"update edge=%d next_right_edge=%d",
2600 "INSERT INTO \"%s\".face (face_id, mbr) VALUES "
2601 "(%d, ST_GeomFromText('POLYGON((%.12f %.12f, %.12f %.12f, %.12f "
2602 "%.12f, %.12f %.12f, "
2603 "%.12f %.12f))', %d))",
2604 pg_info->toposchema_name, area, box.
W, box.
S, box.
W, box.
N,
2606 G_debug(3,
"new face id=%d", area);
2638 snprintf(stmt,
sizeof(stmt),
"UPDATE \"%s\".node SET containing_face = 0 "
2639 "WHERE containing_face = %d",
pg_info->toposchema_name, area);
2647 snprintf(stmt,
sizeof(stmt),
"UPDATE \"%s\".edge_data SET left_face = 0 "
2648 "WHERE left_face = %d",
pg_info->toposchema_name, area);
2656 snprintf(stmt,
sizeof(stmt),
"UPDATE \"%s\".edge_data SET right_face = 0 "
2657 "WHERE right_face = %d",
pg_info->toposchema_name, area);
2665 snprintf(stmt,
sizeof(stmt),
"DELETE FROM \"%s\".face WHERE face_id = %d",
2666 pg_info->toposchema_name, area);
2667 G_debug(3,
"delete face id=%d", area);
2705 G_warning(
_(
"Attempt to access non-existing feature %d"), line);
2708 Line =
Map->plus.Line[line];
2710 G_warning(
_(
"Attempt to access dead feature %d"), line);
2719 for (i = 0; i < 2; i++) {
2727 next_edge = update_next_edge(
Map, n, i == 0 ? line : -line);
2735 G_warning(
_(
"Unable to determine next left/right edge"));
2740 if (
nle == 0 &&
nre == 0)
2743 if (
nle != 0 &&
nre != 0) {
2745 snprintf(stmt,
sizeof(stmt),
"UPDATE \"%s\".edge_data SET "
2746 "next_left_edge = %d, abs_next_left_edge = %d, "
2747 "next_right_edge = %d, abs_next_right_edge = %d "
2748 "WHERE edge_id = %d",
pg_info->toposchema_name,
2751 else if (
nle != 0) {
2753 snprintf(stmt,
sizeof(stmt),
"UPDATE \"%s\".edge_data SET "
2754 "next_left_edge = %d, abs_next_left_edge = %d "
2755 "WHERE edge_id = %d",
pg_info->toposchema_name,
2760 snprintf(stmt,
sizeof(stmt),
"UPDATE \"%s\".edge_data SET "
2761 "next_right_edge = %d, abs_next_right_edge = %d "
2762 "WHERE edge_id = %d",
pg_info->toposchema_name,
2765 G_debug(3,
"update edge=%d next_left_edge=%d next_right_edge=%d",
2789int update_topo_face(
struct Map_info *
Map,
int line)
2791 int i, s, area,
face[2];
2802 G_warning(
_(
"Attempt to access non-existing feature %d"), line);
2805 Line =
Map->plus.Line[line];
2807 G_warning(
_(
"Attempt to access dead feature %d"), line);
2815 for (s = 0; s < 2; s++) {
2816 area = s == 0 ? topo->
left : topo->
right;
2828 for (s = 0; s < 2; s++) {
2829 area = s == 0 ? topo->
left : topo->
right;
2833 Area =
Map->plus.Area[area];
2834 for (i = 0; i < Area->
n_lines; i++) {
2840 "UPDATE \"%s\".edge_data SET "
2841 "left_face = %d, right_face = %d "
2842 "WHERE edge_id = %d",
2857 "UPDATE \"%s\".node SET containing_face = %d "
2858 "WHERE node_id = %d",
2891 plus = &(
Map->plus);
2905 for (i = 0; i <
n_nodes; i++) {
2911 G_debug(3,
" new node: %d", node);
2918 (
const struct line_pnts **)&Points, 1, -1);
2936int delete_line_from_topo_pg(
struct Map_info *
Map,
int line,
int type,
2956 Node =
Map->plus.Node[N1];
2957 if (!Node || Node->
n_lines == 0) {
2960 "DELETE FROM \"%s\".\"node\" WHERE node_id = %d",
2969 Node =
Map->plus.Node[N2];
2970 if (!Node || Node->
n_lines == 0) {
2973 "DELETE FROM \"%s\".\"node\" WHERE node_id = %d",
2986 const char *table,
const char *constraint,
2992 snprintf(stmt,
sizeof(stmt),
"ALTER TABLE \"%s\".%s DROP CONSTRAINT %s",
2993 pg_info->toposchema_name, table, constraint);
3000 "ALTER TABLE \"%s\".%s ADD CONSTRAINT %s "
3001 "FOREIGN KEY (%s) REFERENCES \"%s\".%s (%s) "
3002 "DEFERRABLE INITIALLY DEFERRED",
3034 G_warning(
_(
"Unable to start driver <%s>"),
Fi->driver);
3039 G_warning(
_(
"Unable to open database <%s> by driver <%s>"),
3040 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 G_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)