diff --git a/mysql-test/r/gis-json.result b/mysql-test/r/gis-json.result index 8d7c2d12172..d888b08351d 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 67674c9b33f..5e695fbca9c 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 8c9b61d98a1..3f0efbfa871 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 095f7ff81db..1ba754b6b13 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 45f335596c8..78e850dc2d7 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -323,6 +323,7 @@ public: 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) {