[Commits] 11948d7: MDEV-12180 ST_GeomFromGeoJSON option argument appears to have no effect.

Alexey Botchkov holyfoot at askmonty.org
Sun Aug 6 15:28:48 EEST 2017


revision-id: 11948d75862941e2780e550cbc5411895e1cc1c7 (mariadb-10.2.7-21-g11948d7)
parent(s): 6d51817d2cd79edbc15328bef532a5375f184219
committer: Alexey Botchkov
timestamp: 2017-08-06 16:27:37 +0400
message:

MDEV-12180 ST_GeomFromGeoJSON option argument appears to have no effect.

        Implement the 'option' argument for the ST_GeomFromGeoJSON.

---
 mysql-test/r/gis-json.result | 13 ++++++++++++
 mysql-test/t/gis-json.test   | 10 ++++++++++
 sql/item_geofunc.cc          | 23 +++++++++++++++++++---
 sql/spatial.cc               | 47 ++++++++++++++++++++++++++------------------
 sql/spatial.h                | 22 +++++++++++----------
 5 files changed, 83 insertions(+), 32 deletions(-)

diff --git a/mysql-test/r/gis-json.result b/mysql-test/r/gis-json.result
index 8625a5b..8d7c2d12 100644
--- a/mysql-test/r/gis-json.result
+++ b/mysql-test/r/gis-json.result
@@ -61,6 +61,19 @@ POINT(102 0.5)
 SELECT st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }]}'));
 st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }]}'))
 GEOMETRYCOLLECTION(POINT(102 0.5))
+SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',5));
+ERROR HY000: Incorrect option value: '5' for function ST_GeometryFromJSON
+SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',1));
+ERROR 22023: Invalid GIS data provided to function ST_GeometryFromJSON.
+SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',2));
+ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',2))
+POINT(5.3 15)
+SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',3));
+ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',3))
+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)
 #
 # End of 10.2 tests
 #
diff --git a/mysql-test/t/gis-json.test b/mysql-test/t/gis-json.test
index 645c21b..67674c9 100644
--- a/mysql-test/t/gis-json.test
+++ b/mysql-test/t/gis-json.test
@@ -23,6 +23,16 @@ SELECT st_astext(st_geomfromgeojson('{"type""point"}'));
 SELECT st_astext(st_geomfromgeojson('{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] } }'));
 SELECT st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }]}'));
 
+--error ER_WRONG_VALUE_FOR_TYPE
+SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',5));
+
+--error ER_GIS_INVALID_DATA
+SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',1));
+
+SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',2));
+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));
+
 --echo #
 --echo # End of 10.2 tests
 --echo #
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 560d822..8c9b61d 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -131,13 +131,27 @@ String *Item_func_geometry_from_json::val_str(String *str)
   Geometry_buffer buffer;
   String *js= args[0]->val_str_ascii(&tmp_js);
   uint32 srid= 0;
+  longlong options= 0;
   json_engine_t je;
 
   if ((null_value= args[0]->null_value))
     return 0;
 
-  if ((arg_count == 2) && !args[1]->null_value)
-    srid= (uint32)args[1]->val_int();
+  if (arg_count > 1 && !args[1]->null_value)
+  {
+    options= args[1]->val_int();
+    if (options > 4 || options < 1)
+    {
+      String *sv= args[1]->val_str(&tmp_js);
+      my_error(ER_WRONG_VALUE_FOR_TYPE, MYF(0),
+               "option", sv->c_ptr(), "ST_GeometryFromJSON");
+      null_value= 1;
+      return 0;
+    }
+  }
+
+  if ((arg_count == 3) && !args[2]->null_value)
+    srid= (uint32)args[2]->val_int();
 
   str->set_charset(&my_charset_bin);
   if (str->reserve(SRID_SIZE, 512))
@@ -148,7 +162,7 @@ String *Item_func_geometry_from_json::val_str(String *str)
   json_scan_start(&je, js->charset(), (const uchar *) js->ptr(),
                   (const uchar *) js->end());
 
-  if ((null_value= !Geometry::create_from_json(&buffer, &je, str)))
+  if ((null_value= !Geometry::create_from_json(&buffer, &je, options==1,  str)))
   {
     int code= 0;
 
@@ -163,6 +177,9 @@ String *Item_func_geometry_from_json::val_str(String *str)
     case Geometry::GEOJ_POLYGON_NOT_CLOSED:
       code= ER_GEOJSON_NOT_CLOSED;
       break;
+    case Geometry::GEOJ_DIMENSION_NOT_SUPPORTED:
+      my_error(ER_GIS_INVALID_DATA, MYF(0), "ST_GeometryFromJSON");
+      break;
     default:
       report_json_error_ex(js, &je, func_name(), 0, Sql_condition::WARN_LEVEL_WARN);
       return NULL;
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 7c9d8bb..095f7ff 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -339,7 +339,7 @@ Geometry *Geometry::create_from_wkb(Geometry_buffer *buffer,
 
 
 Geometry *Geometry::create_from_json(Geometry_buffer *buffer,
-                      json_engine_t *je, String *res)
+                      json_engine_t *je, bool er_on_3D, String *res)
 {
   Class_info *ci= NULL;
   const uchar *coord_start= NULL, *geom_start= NULL,
@@ -514,14 +514,14 @@ Geometry *Geometry::create_from_json(Geometry_buffer *buffer,
   result= (*ci->m_create_func)(buffer->data);
   res->q_append((char) wkb_ndr);
   res->q_append((uint32) result->get_class_info()->m_type_id);
-  if (result->init_from_json(je, res))
+  if (result->init_from_json(je, er_on_3D, res))
     goto err_return;
 
   return result;
 
 handle_geometry_key:
   json_scan_start(je, je->s.cs, geometry_start, je->s.str_end);
-  return create_from_json(buffer, je, res);
+  return create_from_json(buffer, je, er_on_3D, res);
 
 err_return:
   return NULL;
@@ -780,7 +780,8 @@ uint Gis_point::init_from_wkb(const char *wkb, uint len,
 }
 
 
-static int read_point_from_json(json_engine_t *je, double *x, double *y)
+static int read_point_from_json(json_engine_t *je, bool er_on_3D,
+                                double *x, double *y)
 {
   int n_coord= 0, err;
   double tmp, *d;
@@ -803,14 +804,17 @@ static int read_point_from_json(json_engine_t *je, double *x, double *y)
     n_coord++;
   }
 
-  return 0;
+  if (n_coord <= 2 || !er_on_3D)
+    return 0;
+  je->s.error= Geometry::GEOJ_DIMENSION_NOT_SUPPORTED;
+  return 1;
 bad_coordinates:
   je->s.error= Geometry::GEOJ_INCORRECT_GEOJSON;
   return 1;
 }
 
 
-bool Gis_point::init_from_json(json_engine_t *je, String *wkb)
+bool Gis_point::init_from_json(json_engine_t *je, bool er_on_3D, String *wkb)
 {
   double x, y;
   if (json_read_value(je))
@@ -822,7 +826,7 @@ bool Gis_point::init_from_json(json_engine_t *je, String *wkb)
     return TRUE;
   }
 
-  if (read_point_from_json(je, &x, &y) ||
+  if (read_point_from_json(je, er_on_3D, &x, &y) ||
       wkb->reserve(POINT_DATA_SIZE))
     return TRUE;
 
@@ -971,7 +975,8 @@ uint Gis_line_string::init_from_wkb(const char *wkb, uint len,
 }
 
 
-bool Gis_line_string::init_from_json(json_engine_t *je, String *wkb)
+bool Gis_line_string::init_from_json(json_engine_t *je, bool er_on_3D,
+                                     String *wkb)
 {
   uint32 n_points= 0;
   uint32 np_pos= wkb->length();
@@ -994,7 +999,7 @@ bool Gis_line_string::init_from_json(json_engine_t *je, String *wkb)
   {
     DBUG_ASSERT(je->state == JST_VALUE);
 
-    if (p.init_from_json(je, wkb))
+    if (p.init_from_json(je, er_on_3D, wkb))
       return TRUE;
     n_points++;
   }
@@ -1364,7 +1369,7 @@ uint Gis_polygon::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
 }
 
 
-bool Gis_polygon::init_from_json(json_engine_t *je, String *wkb)
+bool Gis_polygon::init_from_json(json_engine_t *je, bool er_on_3D, String *wkb)
 {
   uint32 n_linear_rings= 0;
   uint32 lr_pos= wkb->length();
@@ -1389,7 +1394,7 @@ bool Gis_polygon::init_from_json(json_engine_t *je, String *wkb)
     DBUG_ASSERT(je->state == JST_VALUE);
 
     uint32 ls_pos=wkb->length();
-    if (ls.init_from_json(je, wkb))
+    if (ls.init_from_json(je, er_on_3D, wkb))
       return TRUE;
     ls.set_data_ptr(wkb->ptr() + ls_pos, wkb->length() - ls_pos);
     if (ls.is_closed(&closed) || !closed)
@@ -1855,7 +1860,8 @@ uint Gis_multi_point::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
 }
 
 
-bool Gis_multi_point::init_from_json(json_engine_t *je, String *wkb)
+bool Gis_multi_point::init_from_json(json_engine_t *je, bool er_on_3D,
+                                     String *wkb)
 {
   uint32 n_points= 0;
   uint32 np_pos= wkb->length();
@@ -1883,7 +1889,7 @@ bool Gis_multi_point::init_from_json(json_engine_t *je, String *wkb)
     wkb->q_append((char) wkb_ndr);
     wkb->q_append((uint32) wkb_point);
 
-    if (p.init_from_json(je, wkb))
+    if (p.init_from_json(je, er_on_3D, wkb))
       return TRUE;
     n_points++;
   }
@@ -2123,7 +2129,8 @@ uint Gis_multi_line_string::init_from_wkb(const char *wkb, uint len,
 }
 
 
-bool Gis_multi_line_string::init_from_json(json_engine_t *je, String *wkb)
+bool Gis_multi_line_string::init_from_json(json_engine_t *je, bool er_on_3D,
+                                           String *wkb)
 {
   uint32 n_line_strings= 0;
   uint32 ls_pos= wkb->length();
@@ -2151,7 +2158,7 @@ bool Gis_multi_line_string::init_from_json(json_engine_t *je, String *wkb)
     wkb->q_append((char) wkb_ndr);
     wkb->q_append((uint32) wkb_linestring);
 
-    if (ls.init_from_json(je, wkb))
+    if (ls.init_from_json(je, er_on_3D, wkb))
       return TRUE;
 
     n_line_strings++;
@@ -2511,7 +2518,8 @@ uint Gis_multi_polygon::init_from_opresult(String *bin,
 }
 
 
-bool Gis_multi_polygon::init_from_json(json_engine_t *je, String *wkb)
+bool Gis_multi_polygon::init_from_json(json_engine_t *je, bool er_on_3D,
+                                       String *wkb)
 {
   uint32 n_polygons= 0;
   int np_pos= wkb->length();
@@ -2539,7 +2547,7 @@ bool Gis_multi_polygon::init_from_json(json_engine_t *je, String *wkb)
     wkb->q_append((char) wkb_ndr);
     wkb->q_append((uint32) wkb_polygon);
 
-    if (p.init_from_json(je, wkb))
+    if (p.init_from_json(je, er_on_3D, wkb))
       return TRUE;
 
     n_polygons++;
@@ -2986,7 +2994,8 @@ uint Gis_geometry_collection::init_from_wkb(const char *wkb, uint len,
 }
 
 
-bool Gis_geometry_collection::init_from_json(json_engine_t *je, String *wkb)
+bool Gis_geometry_collection::init_from_json(json_engine_t *je, bool er_on_3D,
+                                             String *wkb)
 {
   uint32 n_objects= 0;
   uint32 no_pos= wkb->length();
@@ -3012,7 +3021,7 @@ bool Gis_geometry_collection::init_from_json(json_engine_t *je, String *wkb)
 
     DBUG_ASSERT(je->state == JST_VALUE);
 
-    if (!(g= create_from_json(&buffer, je, wkb)))
+    if (!(g= create_from_json(&buffer, je, er_on_3D, wkb)))
       return TRUE;
 
     *je= sav_je;
diff --git a/sql/spatial.h b/sql/spatial.h
index 3858c0d..45f3355 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -255,6 +255,7 @@ class Geometry
     GEOJ_INCORRECT_GEOJSON= 1,
     GEOJ_TOO_FEW_POINTS= 2,
     GEOJ_POLYGON_NOT_CLOSED= 3,
+    GEOJ_DIMENSION_NOT_SUPPORTED= 4,
   };
 
 
@@ -281,7 +282,8 @@ class Geometry
   virtual uint init_from_opresult(String *bin,
                                   const char *opres, uint res_len)
   { return init_from_wkb(opres + 4, UINT_MAX32, wkb_ndr, bin) + 4; }
-  virtual bool init_from_json(json_engine_t *je, String *wkb) {return true;}
+  virtual bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb)
+  { return true; }
 
   virtual bool get_data_as_wkt(String *txt, const char **end) const=0;
   virtual bool get_data_as_json(String *txt, uint max_dec_digits,
@@ -315,8 +317,8 @@ class Geometry
 				   bool init_stream=1);
   static Geometry *create_from_wkb(Geometry_buffer *buffer,
                                    const char *wkb, uint32 len, String *res);
-  static Geometry *create_from_json(Geometry_buffer *buffer,
-                                    json_engine_t *je, String *res);
+  static Geometry *create_from_json(Geometry_buffer *buffer, json_engine_t *je,
+                                    bool er_on_3D, String *res);
   static Geometry *create_from_opresult(Geometry_buffer *g_buf,
                                   String *res, Gcalc_result_receiver &rr);
   int as_wkt(String *wkt, const char **end);
@@ -395,7 +397,7 @@ class Gis_point: public Geometry
   uint32 get_data_size() const;
   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
-  bool init_from_json(json_engine_t *je, String *wkb);
+  bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
   bool get_data_as_wkt(String *txt, const char **end) const;
   bool get_data_as_json(String *txt, uint max_dec_digits,
                         const char **end) const;
@@ -450,7 +452,7 @@ class Gis_line_string: public Geometry
   uint32 get_data_size() const;
   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
-  bool init_from_json(json_engine_t *je, String *wkb);
+  bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
   bool get_data_as_wkt(String *txt, const char **end) const;
   bool get_data_as_json(String *txt, uint max_dec_digits,
                         const char **end) const;
@@ -484,7 +486,7 @@ class Gis_polygon: public Geometry
   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
   uint init_from_opresult(String *bin, const char *opres, uint res_len);
-  bool init_from_json(json_engine_t *je, String *wkb);
+  bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
   bool get_data_as_wkt(String *txt, const char **end) const;
   bool get_data_as_json(String *txt, uint max_dec_digits,
                         const char **end) const;
@@ -521,7 +523,7 @@ class Gis_multi_point: public Geometry
   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
   uint init_from_opresult(String *bin, const char *opres, uint res_len);
-  bool init_from_json(json_engine_t *je, String *wkb);
+  bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
   bool get_data_as_wkt(String *txt, const char **end) const;
   bool get_data_as_json(String *txt, uint max_dec_digits,
                         const char **end) const;
@@ -550,7 +552,7 @@ class Gis_multi_line_string: public Geometry
   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
   uint init_from_opresult(String *bin, const char *opres, uint res_len);
-  bool init_from_json(json_engine_t *je, String *wkb);
+  bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
   bool get_data_as_wkt(String *txt, const char **end) const;
   bool get_data_as_json(String *txt, uint max_dec_digits,
                         const char **end) const;
@@ -580,7 +582,7 @@ class Gis_multi_polygon: public Geometry
   uint32 get_data_size() const;
   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
-  bool init_from_json(json_engine_t *je, String *wkb);
+  bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
   bool get_data_as_wkt(String *txt, const char **end) const;
   bool get_data_as_json(String *txt, uint max_dec_digits,
                         const char **end) const;
@@ -612,7 +614,7 @@ class Gis_geometry_collection: public Geometry
   bool init_from_wkt(Gis_read_stream *trs, String *wkb);
   uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
   uint init_from_opresult(String *bin, const char *opres, uint res_len);
-  bool init_from_json(json_engine_t *je, String *wkb);
+  bool init_from_json(json_engine_t *je, bool er_on_3D, String *wkb);
   bool get_data_as_wkt(String *txt, const char **end) const;
   bool get_data_as_json(String *txt, uint max_dec_digits,
                         const char **end) const;


More information about the commits mailing list