[Commits] 4ff6ebf: MDEV-12181 ST_AsGeoJSON argument does not limit decimals.

Alexey Botchkov holyfoot at askmonty.org
Mon Aug 7 11:49:53 EEST 2017


revision-id: 4ff6ebf76af763f8e9e98b22773ac68cc2415aa1 (mariadb-10.2.7-42-g4ff6ebf)
parent(s): c508691a9303579e5d614159bc872eeb65b8f84c
committer: Alexey Botchkov
timestamp: 2017-08-07 12:49:04 +0400
message:

MDEV-12181 ST_AsGeoJSON argument does not limit decimals.

        Options handling implemented for ST_AsGeoJSON.

---
 mysql-test/r/gis-json.result | 15 +++++++++++++
 mysql-test/t/gis-json.test   |  7 ++++++
 sql/item_geofunc.cc          | 33 +++++++++++++++++++++++++++-
 sql/spatial.cc               | 52 ++++++++++++++++++++++++++++++++++++++------
 sql/spatial.h                |  1 +
 5 files changed, 100 insertions(+), 8 deletions(-)

diff --git a/mysql-test/r/gis-json.result b/mysql-test/r/gis-json.result
index 8d7c2d12..d888b08 100644
--- a/mysql-test/r/gis-json.result
+++ b/mysql-test/r/gis-json.result
@@ -74,6 +74,21 @@ POINT(5.3 15)
 SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',4));
 ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',4))
 POINT(5.3 15)
+SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),2);
+ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),2)
+{"type": "Point", "coordinates": [5.36, 7.27]}
+SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),1);
+ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),1)
+{"type": "Point", "coordinates": [5.4, 7.3]}
+SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),10);
+ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),10)
+{"type": "Point", "coordinates": [5.363, 7.266]}
+SELECT ST_AsGeoJSON(ST_GeomFromText("POINT(10 11)"), 100, 1);
+ST_AsGeoJSON(ST_GeomFromText("POINT(10 11)"), 100, 1)
+{"bbox": [10, 11, 10, 11], "type": "Point", "coordinates": [10, 11]}
+SELECT ST_AsGeoJSON(ST_GeomFromText("POINT(10 11)"), 100, 5);
+ST_AsGeoJSON(ST_GeomFromText("POINT(10 11)"), 100, 5)
+{"bbox": [10, 11, 10, 11], "type": "Point", "coordinates": [10, 11]}
 #
 # End of 10.2 tests
 #
diff --git a/mysql-test/t/gis-json.test b/mysql-test/t/gis-json.test
index 67674c9..5e695fb 100644
--- a/mysql-test/t/gis-json.test
+++ b/mysql-test/t/gis-json.test
@@ -33,6 +33,13 @@ SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.
 SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',3));
 SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',4));
 
+SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),2);
+SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),1);
+SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),10);
+
+SELECT ST_AsGeoJSON(ST_GeomFromText("POINT(10 11)"), 100, 1);
+SELECT ST_AsGeoJSON(ST_GeomFromText("POINT(10 11)"), 100, 5);
+
 --echo #
 --echo # End of 10.2 tests
 --echo #
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 8c9b61d..3f0efbf 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -259,6 +259,8 @@ String *Item_func_as_geojson::val_str_ascii(String *str)
   DBUG_ASSERT(fixed == 1);
   String arg_val;
   String *swkb= args[0]->val_str(&arg_val);
+  uint max_dec= FLOATING_POINT_DECIMALS;
+  longlong options= 0;
   Geometry_buffer buffer;
   Geometry *geom= NULL;
   const char *dummy;
@@ -268,12 +270,41 @@ String *Item_func_as_geojson::val_str_ascii(String *str)
 	!(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))))
     return 0;
 
+  if (arg_count > 1)
+  {
+    max_dec= (uint) args[1]->val_int();
+    if (args[1]->null_value)
+      max_dec= FLOATING_POINT_DECIMALS;
+    if (arg_count > 2)
+    {
+      options= args[2]->val_int();
+      if (args[2]->null_value)
+        options= 0;
+    }
+  }
+
   str->length(0);
   str->set_charset(&my_charset_latin1);
-  if ((null_value= geom->as_json(str, FLOATING_POINT_DECIMALS, &dummy)))
+
+  if (str->reserve(1, 512))
     return 0;
 
+  str->qs_append('{');
+
+  if (options & 1)
+  {
+    if (geom->bbox_as_json(str) || str->append(", ", 2))
+      goto error;
+  }
+
+  if ((geom->as_json(str, max_dec, &dummy) || str->append("}", 1)))
+      goto error;
+
   return str;
+
+error:
+  null_value= 1;
+  return 0;
 }
 
 
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 095f7ff..1ba754b 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -21,6 +21,10 @@
 #include "gstream.h"                            // Gis_read_stream
 #include "sql_string.h"                         // String
 
+/* This is from item_func.h. Didn't want to #include the whole file. */
+double my_double_round(double value, longlong dec, bool dec_unsigned,
+                       bool truncate);
+
 #ifdef HAVE_SPATIAL
 
 /* 
@@ -250,6 +254,8 @@ static const uchar feature_type[]= "feature";
 static const int feature_type_len= 7;
 static const uchar feature_coll_type[]= "featurecollection";
 static const int feature_coll_type_len= 17;
+static const uchar bbox_keyname[]= "bbox";
+static const int bbox_keyname_len= 4;
 
 
 int Geometry::as_json(String *wkt, uint max_dec_digits, const char **end)
@@ -258,7 +264,7 @@ int Geometry::as_json(String *wkt, uint max_dec_digits, const char **end)
   if (wkt->reserve(4 + type_keyname_len + 2 + len + 2 + 2 +
                    coord_keyname_len + 4, 512))
     return 1;
-  wkt->qs_append("{\"", 2);
+  wkt->qs_append("\"", 1);
   wkt->qs_append((const char *) type_keyname, type_keyname_len);
   wkt->qs_append("\": \"", 4);
   wkt->qs_append(get_class_info()->m_geojson_name.str, len);
@@ -269,10 +275,35 @@ int Geometry::as_json(String *wkt, uint max_dec_digits, const char **end)
     wkt->qs_append((const char *) coord_keyname, coord_keyname_len);
 
   wkt->qs_append("\": ", 3);
-  if (get_data_as_json(wkt, max_dec_digits, end) ||
-      wkt->reserve(1))
+  if (get_data_as_json(wkt, max_dec_digits, end))
     return 1;
-  wkt->qs_append('}');
+
+  return 0;
+}
+
+
+int Geometry::bbox_as_json(String *wkt)
+{
+  MBR mbr;
+  const char *end;
+  if (wkt->reserve(5 + bbox_keyname_len + (FLOATING_POINT_DECIMALS+2)*4, 512))
+    return 1;
+  wkt->qs_append("\"", 1);
+  wkt->qs_append((const char *) bbox_keyname, bbox_keyname_len);
+  wkt->qs_append("\": [", 4);
+
+  if (get_mbr(&mbr, &end))
+    return 1;
+
+  wkt->qs_append(mbr.xmin);
+  wkt->qs_append(", ", 2);
+  wkt->qs_append(mbr.ymin);
+  wkt->qs_append(", ", 2);
+  wkt->qs_append(mbr.xmax);
+  wkt->qs_append(", ", 2);
+  wkt->qs_append(mbr.ymax);
+  wkt->qs_append("]", 1);
+
   return 0;
 }
 
@@ -670,6 +701,11 @@ static void append_json_point(String *txt, uint max_dec, const char *data)
 {
   double x,y;
   get_point(&x, &y, data);
+  if (max_dec < FLOATING_POINT_DECIMALS)
+  {
+    x= my_double_round(x, max_dec, FALSE, FALSE);
+    y= my_double_round(y, max_dec, FALSE, FALSE);
+  }
   txt->qs_append('[');
   txt->qs_append(x);
   txt->qs_append(", ", 2);
@@ -3106,12 +3142,14 @@ bool Gis_geometry_collection::get_data_as_json(String *txt, uint max_dec_digits,
     if (!(geom= create_by_typeid(&buffer, wkb_type)))
       return 1;
     geom->set_data_ptr(data, (uint) (m_data_end - data));
-    if (geom->as_json(txt, max_dec_digits, &data) ||
-        txt->append(STRING_WITH_LEN(", "), 512))
+    if (txt->append("{", 1) ||
+        geom->as_json(txt, max_dec_digits, &data) ||
+        txt->append(STRING_WITH_LEN("}, "), 512))
       return 1;
   }
   txt->length(txt->length() - 2);
-  txt->qs_append(']');
+  if (txt->append("]", 1))
+    return 1;
 
   *end= data;
   return 0;
diff --git a/sql/spatial.h b/sql/spatial.h
index 45f3355..78e850d 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -323,6 +323,7 @@ class Geometry
                                   String *res, Gcalc_result_receiver &rr);
   int as_wkt(String *wkt, const char **end);
   int as_json(String *wkt, uint max_dec_digits, const char **end);
+  int bbox_as_json(String *wkt);
 
   inline void set_data_ptr(const char *data, uint32 data_len)
   {


More information about the commits mailing list