← Back to team overview

maria-developers team mailing list archive

Re: MDEV-12803 Improve function parameter data type control

 

Hello Alexey,

Thanks for your feedback.

Sending a new version, as discussed in this email and on IRC.
Please find attached.

- Removed Item_geometry_func_importer
- Renamed Item_xxx_geometry_property to Item_xxx_args_geometry
- Renamed Item_xxx_dyadic_operation to Item_xxx_args_geometry_geometry.



This is the new hierarchy:


Item_str_func
  Item_geometry_func
    Item_geometry_func_args_geometry
      Item_func_centroid
      Item_func_envelope
      Item_func_boundary
      Item_func_spatial_decomp
      Item_func_spatial_decomp_n
      Item_func_buffer
      Item_func_pointonsurface
    Item_func_geometry_from_text
    Item_func_geometry_from_wkb
    Item_func_geometry_from_json
    Item_func_point
    Item_func_spatial_collection
    Item_func_spatial_operation
  Item_binary_func_args_geometry
    Item_func_as_wkb
Item_real_func
  Item_real_func_args_geometry
    Item_func_x
    Item_func_y
    Item_func_area
    Item_func_glength
  Item_real_func_args_geometry_geometry
    Item_func_distance
Item_long_func
  Item_long_func_args_geometry
    Item_func_issimple
      Item_func_isring
    Item_func_isclosed
    Item_func_dimension
    Item_func_numgeometries
    Item_func_numinteriorring
    Item_func_numpoints
    Item_func_srid
Item_bool_func
  Item_bool_func_args_geometry
    Item_func_isempty
  Item_bool_func_args_geometry_geometry
    Item_func_spatial_relate
Item_str_ascii_func
  Item_str_ascii_func_args_geometry
    Item_func_as_wkt
    Item_func_as_geojson
    Item_func_geometry_type


Thanks!


On 05/26/2017 11:50 AM, Alexey Botchkov wrote:
>>1. It will look like a C fragment in a C++ code.
>>   Why is it more natural than a virtual method?
> 
> The Item hierarchy and 'check_type' hierarchy are parallel.
> So it seems natural to me if we can assign an already-prepared
> parameter-validation function to the type.
> 
>> 2. It will make the Item size bigger.
> But it will make Item** virtual tables smaller.
> 
>> 4. It will need more CPU for m_check_arguments_function initialization.
> Must be really small overhead.
> 
>> Are you afraid that I'll have to modify class hierarchy?
> Yes. My only concern is that the class hierarchy becomes more complicated
> and with repeating code.
> 
> But after a while i sort of used to it so now i'm fine with the virtual
> method.
> 
> 
>> We have a convention that functions return true on error and false on
>> success.
> For the check_something function returning TRUE or FALSE doesn't mean an
> 'error'.
> It's just the condition fits or doesn't.
> But fine, our code has many examples of 'check' functions returning
> results this way.
> 
> Typenames discussed.
> So otherwise i'm ok with the patch.
> 
> Best regards.
> HF 
> 
> On Wed, May 24, 2017 at 4:22 PM, Alexander Barkov <bar@xxxxxxxxxxx
> <mailto:bar@xxxxxxxxxxx>> wrote:
> 
>     Hi Alexey,
> 
>     Thank you very much for your review!
> 
>     Please see my comments below:
> 
> 
>     On 05/23/2017 12:16 AM, Alexey Botchkov wrote:
>     > Firstly I'd say i don't like the idea of the 'virtual check_arguments()'
>     > function.
>     > I belive it's more natural to have a member 'm_check_arguments_function'
>     > that would be set in constructor (or be an argument to the constructor)
>     > and the non-virtual 'check_arguments()' that would just call that member.
>     > This would make Item class structure much nicer and would even save us
>     > memory.
>     >
>     > If you have good arguments for your approach, I have some
>     > comments/questions to your patch :)
> 
>     I'm not sure that a function member is better.
> 
>     1. It will look like a C fragment in a C++ code.
>        Why is it more natural than a virtual method?
> 
>     2. It will make the Item size bigger.
> 
>     3. It will need more coding.
>        Now we have to declare only virtual functions.
>        With a function member, we'll have to do:
>        - declare function anyway
>        - add a code into constructors
> 
>     4. It will need more CPU for m_check_arguments_function initialization.
>        On the contrary, having a virtual methods costs nothing,
>        except a small initialization in VMTs during mysqld startup.
> 
> 
>     What is your main concern?
>     Are you afraid that I'll have to modify class hierarchy
>     for other Item_xxx_func?  It should not be necessary.
>     We'll just have a set of protected methods on the Item_func level,
>     for most typical cases.
> 
> 
>     >
>     > Why this change?
>     > +++ b/mysql-test/t/gis-rtree.test
>     > @@ -61,7 +61,7 @@ while ($1)
>     >    let $2=10;
>     >    while ($2)
>     >    {
>     > -    eval DELETE FROM t2 WHERE Within(g,
>     > Envelope(GeometryFromWKB(Point($1 * 10 - 9, $2 * 10 - 9), Point($1 * 10,
>     > $2 * 10))));
>     > +    eval DELETE FROM t2 WHERE Within(g,
>     > Envelope(GeometryFromWKB(Point($1 * 10 - 9, $2 * 10 - 9), 0)));
>     >      SELECT count(*) FROM t2;
>     >      dec $2;
> 
> 
>     It passed POINT() as the second argiment to GeometryFromWKB.
>     The second argument is for SRID. After my changes it's not allowed.
> 
> 
>     >    }
>     >
>     >
>     > It looks weird when the 'check_something' functions returns FALSE if
>     > the argument fits the check. I'd make them returning TRUE in this case
>     > as people normally expect.
> 
>     We have a convention that functions return true on error and false on
>     success.
> 
>     Please have a look into:
> 
>     check_db_name()
>     check_for_broken_triggers()
>     check_unique_table()
> 
>     They all return true on error.
>     I did the same.
> 
> 
>     >
>     > +bool Item_func::check_argument_types_scalar(uint start, uint end) const
>     > +{
>     > +  for (uint i= start; i < end; i++)
>     > +  {
>     > +    DBUG_ASSERT(i < arg_count);
>     >
>     > In code like this i'd rather do
>     > bool Item_func::check_argument_types_scalar(uint start, uint end) const
>     > {
>     >   DBUG_ASSERT(end < arg_count);
>     >
>     >   for (uint i= start; i < end; i++)
>     >   {
>     >     // no DBUG_ASSERT here
>     >     ...
> 
>     Agree.
> 
>     >
>     >
>     >
>     > Some typenames feel misleading. I'd suggest changes
>     > Item_real_func_geometry_property  -> Item_real_func_arg_geometry
>     > Item_int_func_geometry_property   -> Item_int_func_arg_geometry
>     > Item_bool_func_geometry_property  -> Item_bool_func_arg_geometry
>     > Item_str_ascii_func_geometry_property -> Item_ascii_func_arg_geometry
>     > Item_geometry_func_geometry_property -> Item_geometry_func_arg_geometry
> 
>     This looks like a property.
>     The first argument is an object of some complex type (GEOMETRY in
>     our case).
>     The other arguments are simple type additional optional parameters.
> 
>     In C++ this would look like:
> 
>     geom->IsSimple();
>     geom->Buffer(10);
> 
> 
>     OpenGIS also calls these methods "properties",
>     so do we in the documentation:
> 
>     https://dev.mysql.com/doc/refman/5.7/en/gis-class-point.html
>     <https://dev.mysql.com/doc/refman/5.7/en/gis-class-point.html>
> 
> 
> 
>     >
>     > Item_binary_func_geometry_property - do we really need this type?
> 
>     Right, there is only one binary string property: AsWKB().
> 
>     I added Item_xxx_geometry_property for regularity
>     (to have a symmetric class hierarchy with other "properties" ).
> 
>     Here's the class structure:
> 
> 
>     Item_str_func
>       Item_geometry_func
>         Item_geometry_func_geometry_property
>           Item_func_centroid
>           Item_func_envelope
>           Item_func_boundary
>           Item_func_spatial_decomp
>           Item_func_spatial_decomp_n
>           Item_func_buffer
>           Item_func_pointonsurface
>         Item_geometry_func_importer
>           Item_func_geometry_from_text
>           Item_func_geometry_from_wkb
>           Item_func_geometry_from_json
>           Item_func_point
>         Item_func_spatial_collection
>         Item_func_spatial_operation
>       Item_binary_func_geometry_property
>         Item_func_as_wkb
>     Item_real_func
>       Item_real_func_geometry_property
>         Item_func_x
>         Item_func_y
>         Item_func_area
>         Item_func_glength
>       Item_real_func_geometry_dyadic_operation
>         Item_func_distance
>     Item_int_func
>       Item_int_func_geometry_property
>         Item_func_issimple
>           Item_func_isring
>         Item_func_isclosed
>         Item_func_dimension
>         Item_func_numgeometries
>         Item_func_numinteriorring
>         Item_func_numpoints
>         Item_func_srid
>       Item_func_gis_debug
>     Item_bool_func
>       Item_bool_func_geometry_property
>         Item_func_isempty
>       Item_bool_func_geometry_dyadic_operation
>         Item_func_spatial_relate
>     Item_str_ascii_func
>       Item_str_ascii_func_geometry_property
>         Item_func_as_wkt
>         Item_func_as_geojson
>         Item_func_geometry_type
> 
>     Btw, do you need a program to print this hierarchy? :)
>     I wrote it a few years ago, and use it almost every day.
> 
>     >
>     > Item_geometry_func_importer - do we need this type?
> 
>     I can remove this. It does not have shared methods indeed.
> 
>     >
>     > Item_real_func_geometry_dyadic_operation -> Item_real_func_arg_2_geometries
>     > Item_bool_func_geometry_dyadic_operation -> Item_bool_func_arg_2_geometries
> 
>     It's an operation on two geometries.
>     My names is quite self-descriptive.
>     Also, it tells that:
>     - there is no any other GEOMETRY arguments
>     - there can be optional non-GEOMETRY additional arguments
> 
>     >
>     >
>     > +  bool check_arguments() const
>     > +  {
>     > +    DBUG_ASSERT(arg_count >= 2);
>     > +    return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
>     >
>     > the check_argument_types_or_binary() does the check of the arg_count so
>     > no need for the DBUG_ASSERT().
>     > But i don't insist on removing this line :)
> 
>     I can remove it :)
> 
>     >
>     >
>     > On Mon, May 15, 2017 at 5:56 PM, Alexander Barkov <bar@xxxxxxxxxxx <mailto:bar@xxxxxxxxxxx>
>     > <mailto:bar@xxxxxxxxxxx <mailto:bar@xxxxxxxxxxx>>> wrote:
>     >
>     >     Hello Alexey,
>     >
>     >     can you please review a patch for MDEV-12803?
>     >
>     >     Thanks!
>     >
>     >
> 
> 
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index cbd0dfa..097e07a 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -1044,7 +1044,7 @@ DROP TABLE t1;
 CREATE TABLE t1(f1 int);
 INSERT INTO t1 values (0),(0);
 SELECT POLYGON((SELECT 1 FROM (SELECT 1 IN (GROUP_CONCAT(t1.f1)) FROM t1, t1 t GROUP BY t.f1 ) d));
-ERROR 22007: Illegal non geometric '(select 1 from (select 1 = group_concat(`test`.`t1`.`f1` separator ',') AS `1 IN (GROUP_CONCAT(t1.f1))` from `test`.`t1` join `test`.`t1` `t` group by `test`.`t`.`f1`) `d`)' value found during parsing
+ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
 DROP TABLE t1;
 #
 # Bug#58396 group_concat and explain extended are still crashy
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index d86db4c..c99d7e6 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -566,9 +566,9 @@ DROP TABLE t1;
 # Bug#11764994  57900: CREATE TABLE .. SELECT ASSERTS SCALE >= 0 && PRECISION > 0 && SCALE <= PR
 #
 CREATE TABLE t1 SELECT CEIL(LINESTRINGFROMWKB(1) DIV NULL);
-DROP TABLE t1;
+ERROR HY000: Illegal parameter data type int for operation 'st_geometryfromwkb'
 CREATE TABLE t1 SELECT FLOOR(LINESTRINGFROMWKB(1) DIV NULL);
-DROP TABLE t1;
+ERROR HY000: Illegal parameter data type int for operation 'st_geometryfromwkb'
 #
 # Bug#11765923  58937: MANY VALGRIND ERRORS AFTER GROUPING BY RESULT OF DECIMAL COLUMN FUNCTION
 #
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 34c28e6..4641781 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -3124,7 +3124,7 @@ sha1('P'),
 )
 )
 ) AS r;
-ERROR HY000: Illegal parameter data types geometry and decimal for operation 'coalesce'
+ERROR HY000: Illegal parameter data type varchar for operation 'st_geometryfromwkb'
 connection conn1;
 SET @@global.max_allowed_packet:= @tmp_max;
 disconnect newconn;
diff --git a/mysql-test/r/gis-precise.result b/mysql-test/r/gis-precise.result
index 3824ba6..f816278 100644
--- a/mysql-test/r/gis-precise.result
+++ b/mysql-test/r/gis-precise.result
@@ -223,8 +223,7 @@ st_u
 MULTIPOLYGON(((525400 18370,525000.9677614468 183300,525400 183300,525400 18370)),((525000 183300,525000 183700,525000.9677614468 183300,525000 183300)),((525265.58 183481.95,525263.95 183484.75,525260.7 183491.55,525276.79 183500,525278.39 183500.84,525278.63 183500.97,525280.98 183502.26,525283.17 183503.47,525289.11 183506.62,525296.42 183510.31,525296.57 183510.39,525298.67 183511.53,525302.81 183513.8,525304.5 183510.83,525307.85 183504.95,525304.45 183504.25,525301.75 183509.35,525283.55 183500,525282.2 183499.3,525282.3 183499.1,525280.35 183498.2,525275.5 183495.7,525276.5 183493.45,525278.97 183488.73,525265.58 183481.95),(525266.99 183484.33,525263.26 183491.55,525266.15 183493.04,525269.88 183485.82,525266.99 183484.33),(525272.06 183488.37,525268.94 183494.51,525271.94 183496.03,525275.06 183489.89,525272.06 183488.37)))
 SET @a=0x0000000001030000000200000005000000000000000000000000000000000000000000000000002440000000000000000000000000000024400000000000002440000000000000000000000000000024400000000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F0000000000000040000000000000F03F000000000000F03F;
 SELECT ASTEXT(TOUCHES(@a, GEOMFROMTEXT('point(0 0)'))) t;
-t
-NULL
+ERROR HY000: Illegal parameter data type int for operation 'st_astext'
 SELECT astext(ST_UNION (
 PolyFromText('POLYGON(( 2 2 ,3 2,2 7,2 2),( 0 0,8 2,1 9,0 0))'),
 ExteriorRing( Envelope( MultiLineStringFromText('MULTILINESTRING((3 4,5 3),(3 0,0 5))')))));
diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result
index 9373237..55f7ab8 100644
--- a/mysql-test/r/gis-rtree.result
+++ b/mysql-test/r/gis-rtree.result
@@ -309,403 +309,403 @@ fid	AsText(g)
 56	LINESTRING(41 41,50 50)
 45	LINESTRING(51 51,60 60)
 55	LINESTRING(41 51,50 60)
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 10 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 9 * 10 - 9), Point(10 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 9 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 8 * 10 - 9), Point(10 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 8 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 7 * 10 - 9), Point(10 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 7 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 6 * 10 - 9), Point(10 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 6 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 5 * 10 - 9), Point(10 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 5 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 4 * 10 - 9), Point(10 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 4 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 3 * 10 - 9), Point(10 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 3 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 2 * 10 - 9), Point(10 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 2 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 1 * 10 - 9), Point(10 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 1 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 10 * 10 - 9), Point(9 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 10 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 9 * 10 - 9), Point(9 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 9 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 8 * 10 - 9), Point(9 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 8 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 7 * 10 - 9), Point(9 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 7 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 6 * 10 - 9), Point(9 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 6 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 5 * 10 - 9), Point(9 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 5 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 4 * 10 - 9), Point(9 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 4 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 3 * 10 - 9), Point(9 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 3 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 2 * 10 - 9), Point(9 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 2 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 1 * 10 - 9), Point(9 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 1 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 10 * 10 - 9), Point(8 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 10 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 9 * 10 - 9), Point(8 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 9 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 8 * 10 - 9), Point(8 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 8 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 7 * 10 - 9), Point(8 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 7 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 6 * 10 - 9), Point(8 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 6 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 5 * 10 - 9), Point(8 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 5 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 4 * 10 - 9), Point(8 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 4 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 3 * 10 - 9), Point(8 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 3 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 2 * 10 - 9), Point(8 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 2 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 1 * 10 - 9), Point(8 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 1 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 10 * 10 - 9), Point(7 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 10 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 9 * 10 - 9), Point(7 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 9 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 8 * 10 - 9), Point(7 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 8 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 7 * 10 - 9), Point(7 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 7 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 6 * 10 - 9), Point(7 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 6 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 5 * 10 - 9), Point(7 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 5 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 4 * 10 - 9), Point(7 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 4 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 3 * 10 - 9), Point(7 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 3 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 2 * 10 - 9), Point(7 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 2 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 1 * 10 - 9), Point(7 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 1 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 10 * 10 - 9), Point(6 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 10 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 9 * 10 - 9), Point(6 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 9 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 8 * 10 - 9), Point(6 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 8 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 7 * 10 - 9), Point(6 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 7 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 6 * 10 - 9), Point(6 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 6 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 5 * 10 - 9), Point(6 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 5 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 4 * 10 - 9), Point(6 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 4 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 3 * 10 - 9), Point(6 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 3 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 2 * 10 - 9), Point(6 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 2 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 1 * 10 - 9), Point(6 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 1 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 10 * 10 - 9), Point(5 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 10 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 9 * 10 - 9), Point(5 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 9 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 8 * 10 - 9), Point(5 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 8 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 7 * 10 - 9), Point(5 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 7 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 6 * 10 - 9), Point(5 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 6 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 5 * 10 - 9), Point(5 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 5 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 4 * 10 - 9), Point(5 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 4 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 3 * 10 - 9), Point(5 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 3 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 2 * 10 - 9), Point(5 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 2 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 1 * 10 - 9), Point(5 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 1 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 10 * 10 - 9), Point(4 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 10 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 9 * 10 - 9), Point(4 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 9 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 8 * 10 - 9), Point(4 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 8 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 7 * 10 - 9), Point(4 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 7 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 6 * 10 - 9), Point(4 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 6 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 5 * 10 - 9), Point(4 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 5 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 4 * 10 - 9), Point(4 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 4 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 3 * 10 - 9), Point(4 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 3 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 2 * 10 - 9), Point(4 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 2 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 1 * 10 - 9), Point(4 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 1 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 10 * 10 - 9), Point(3 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 10 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 9 * 10 - 9), Point(3 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 9 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 8 * 10 - 9), Point(3 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 8 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 7 * 10 - 9), Point(3 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 7 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 6 * 10 - 9), Point(3 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 6 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 5 * 10 - 9), Point(3 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 5 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 4 * 10 - 9), Point(3 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 4 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 3 * 10 - 9), Point(3 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 3 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 2 * 10 - 9), Point(3 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 2 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 1 * 10 - 9), Point(3 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 1 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 10 * 10 - 9), Point(2 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 10 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 9 * 10 - 9), Point(2 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 9 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 8 * 10 - 9), Point(2 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 8 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 7 * 10 - 9), Point(2 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 7 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 6 * 10 - 9), Point(2 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 6 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 5 * 10 - 9), Point(2 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 5 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 4 * 10 - 9), Point(2 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 4 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 3 * 10 - 9), Point(2 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 3 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 2 * 10 - 9), Point(2 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 2 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 1 * 10 - 9), Point(2 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 1 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 10 * 10 - 9), Point(1 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 10 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 9 * 10 - 9), Point(1 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 9 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 8 * 10 - 9), Point(1 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 8 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 7 * 10 - 9), Point(1 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 7 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 6 * 10 - 9), Point(1 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 6 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 5 * 10 - 9), Point(1 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 5 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 4 * 10 - 9), Point(1 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 4 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 3 * 10 - 9), Point(1 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 3 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 2 * 10 - 9), Point(1 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 2 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 1 * 10 - 9), Point(1 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 1 * 10 - 9), 0)));
 SELECT count(*) FROM t2;
 count(*)
 100
@@ -1617,23 +1617,17 @@ DROP TABLE t1;
 CREATE TABLE t1  (a GEOMETRY NOT NULL, SPATIAL KEY(a)) ENGINE=MyISAM;
 INSERT INTO t1 VALUES (Point(1,1)),(Point(2,2)),(Point(3,3));
 EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,1);
-id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+ERROR HY000: Illegal parameter data type int for operation 'st_contains'
 EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,1.0);
-id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+ERROR HY000: Illegal parameter data type decimal for operation 'st_contains'
 EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,1e0);
-id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+ERROR HY000: Illegal parameter data type double for operation 'st_contains'
 EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,TIME'00:00:00');
-id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+ERROR HY000: Illegal parameter data type time for operation 'st_contains'
 EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,DATE'2001-01-01');
-id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+ERROR HY000: Illegal parameter data type date for operation 'st_contains'
 EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,TIMESTAMP'2001-01-01 00:00:00');
-id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+ERROR HY000: Illegal parameter data type datetime for operation 'st_contains'
 DROP TABLE t1;
 #
 # End of 10.1 tests
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index 5e6716b..b335f2b 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -1045,9 +1045,9 @@ f5	datetime	YES		NULL
 drop view v1;
 drop table t1;
 SELECT MultiPoint(12345,'');
-ERROR 22007: Illegal non geometric '12345' value found during parsing
+ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
 SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
-ERROR 22007: Illegal non geometric ''00000'' value found during parsing
+ERROR HY000: Illegal parameter data type varchar for operation 'geometrycollection'
 #
 # BUG#51875: crash when loading data into geometry function polyfromwkb
 #
@@ -1115,7 +1115,7 @@ ISCLOSED(CONVERT(CONCAT('     ', 0x2), BINARY(20)))
 # GEOMETRY FUNCTION ARGUMENTS
 #
 SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
-ERROR 22007: Illegal non geometric '' value found during parsing
+ERROR HY000: Illegal parameter data type bigint for operation 'geometrycollection'
 #
 # MDEV-4252 geometry query crashes server
 #
@@ -1614,13 +1614,7 @@ insert into t1 values(geomfromtext("POINT(0 0)"));
 insert into t1 values(geomfromtext("POINT(0 9.2233720368548e18)"));
 insert into t1 values(geomfromtext("POINT(0 9.2233720368548e18)"));
 select equals(`a`,convert(`a` using utf8)) from `t1`;
-equals(`a`,convert(`a` using utf8))
-1
-NULL
-NULL
-Warnings:
-Warning	1300	Invalid utf8 character string: '\xE0C'
-Warning	1300	Invalid utf8 character string: '\xE0C'
+ERROR HY000: Illegal parameter data type longblob for operation 'st_equals'
 select equals(`a`,left(`a`,23)) from `t1`;
 equals(`a`,left(`a`,23))
 NULL
@@ -4341,5 +4335,308 @@ def					ST_SRID(POINT(1,1))	3	10	1	Y	32896	0	63
 ST_ISSIMPLE(POINT(1,1))	ST_ISRING(POINT(1,1))	ST_ISCLOSED(POINT(1,1))	ST_DIMENSION(POINT(1,1))	ST_NUMGEOMETRIES(POINT(1,1))	ST_NUMINTERIORRINGS(POINT(1,1))	ST_NUMPOINTS(POINT(1,1))	ST_SRID(POINT(1,1))
 1	-1	-1	0	NULL	NULL	NULL	0
 #
+# MDEV-12803 Improve function parameter data type control
+#
+#
+# Item_geometry_func_args_geometry
+#
+SELECT ST_CENTROID(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_centroid'
+SELECT ST_ENVELOPE(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_envelope'
+SELECT ST_BOUNDARY(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_boundary'
+SELECT ST_STARTPOINT(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_startpoint'
+SELECT ST_POINTONSURFACE(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_pointonsurface'
+SELECT ST_POINTN(1,1);
+ERROR HY000: Illegal parameter data type int for operation 'st_pointn'
+SELECT ST_POINTN(LineString(Point(1,1)),Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_pointn'
+SELECT ST_BUFFER(1, 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_buffer'
+SELECT ST_BUFFER(Point(1,1), Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_buffer'
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ST_ENVELOPE(?) AS g';
+EXECUTE stmt USING 1;
+ERROR HY000: Illegal parameter data type bigint for operation 'st_envelope'
+EXECUTE stmt USING POINT(1,1);
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `g` polygon DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT ST_ASTEXT(g) FROM t1;
+ST_ASTEXT(g)
+POLYGON((1 1,1 1,1 1,1 1,1 1))
+DROP TABLE t1;
+DEALLOCATE PREPARE stmt;
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ST_BUFFER(?,?) AS g';
+EXECUTE stmt USING 1,1;
+ERROR HY000: Illegal parameter data type bigint for operation 'st_buffer'
+EXECUTE stmt USING POINT(1,1),POINT(1,1);
+ERROR HY000: Illegal parameter data type geometry for operation 'st_buffer'
+EXECUTE stmt USING POINT(1,1),0;
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `g` geometry DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT ST_GEOMETRYTYPE(g) FROM t1;
+ST_GEOMETRYTYPE(g)
+POINT
+DROP TABLE t1;
+DEALLOCATE PREPARE stmt;
+#
+# Functions created GEOMETRY from non-GEOMETRY
+#
+SELECT ST_GEOMETRYFROMTEXT(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_geometryfromtext'
+SELECT ST_GEOMETRYFROMTEXT(Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_geometryfromtext'
+SELECT ST_GEOMETRYFROMTEXT(Point(1,1), 1);
+ERROR HY000: Illegal parameter data type geometry for operation 'st_geometryfromtext'
+SELECT ST_GEOMETRYFROMTEXT('test', Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_geometryfromtext'
+SELECT ST_GEOMETRYFROMWKB(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_geometryfromwkb'
+SELECT ST_GEOMETRYFROMWKB(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_geometryfromwkb'
+SELECT ST_GEOMETRYFROMWKB(1, 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_geometryfromwkb'
+SELECT ST_GEOMETRYFROMWKB(Point(1,1), Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_geometryfromwkb'
+SELECT ST_GEOMFROMGEOJSON(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_geomfromgeojson'
+SELECT ST_GEOMFROMGEOJSON(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_geomfromgeojson'
+SELECT ST_GEOMFROMGEOJSON(1,1);
+ERROR HY000: Illegal parameter data type int for operation 'st_geomfromgeojson'
+SELECT ST_GEOMFROMGEOJSON(Point(1,1), Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_geomfromgeojson'
+SELECT POINT(ROW(1,1),1);
+ERROR HY000: Illegal parameter data type row for operation 'point'
+SELECT POINT(POINT(1,1),1);
+ERROR HY000: Illegal parameter data type geometry for operation 'point'
+SELECT POINT(1,ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'point'
+SELECT POINT(1,POINT(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'point'
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ST_GEOMFROMTEXT(?,?) AS g';
+EXECUTE stmt USING 1,1;
+ERROR HY000: Illegal parameter data type bigint for operation 'st_geometryfromtext'
+EXECUTE stmt USING POINT(1,1),POINT(1,1);
+ERROR HY000: Illegal parameter data type geometry for operation 'st_geometryfromtext'
+EXECUTE stmt USING 'POINT(1 1)',1;
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `g` geometry DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT ST_ASTEXT(g), SRID(g) FROM t1;
+ST_ASTEXT(g)	SRID(g)
+POINT(1 1)	1
+DROP TABLE t1;
+DEALLOCATE PREPARE stmt;
+# Item_func_spatial_collection
+SELECT GEOMETRYCOLLECTION(ROW(1,1), POINT(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'geometrycollection'
+SELECT GEOMETRYCOLLECTION(POINT(1,1), ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'geometrycollection'
+SELECT GEOMETRYCOLLECTION(1, POINT(1,1));
+ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
+SELECT GEOMETRYCOLLECTION(POINT(1,1), 1);
+ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
+# Item_func_spatial_operation
+SELECT ST_UNION(ROW(1,1), POINT(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_union'
+SELECT ST_UNION(POINT(1,1), ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_union'
+SELECT ST_UNION(1, POINT(1,1));
+ERROR HY000: Illegal parameter data type int for operation 'st_union'
+SELECT ST_UNION(POINT(1,1), 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_union'
+# Item_binary_func_args_geometry
+SELECT ST_ASWKB(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_aswkb'
+SELECT ST_ASWKB(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_aswkb'
+SELECT ST_ASWKB('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_aswkb'
+# Item_real_func_args_geometry
+SELECT ST_X(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_x'
+SELECT ST_X(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_x'
+SELECT ST_X('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_x'
+SELECT ST_Y(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_y'
+SELECT ST_Y(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_y'
+SELECT ST_Y('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_y'
+SELECT ST_AREA(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_area'
+SELECT ST_AREA(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_area'
+SELECT ST_AREA('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_area'
+SELECT ST_LENGTH(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_length'
+SELECT ST_LENGTH(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_length'
+SELECT ST_LENGTH('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_length'
+# Item_real_func_geometry_args_geometry_geometry
+SELECT ST_DISTANCE(ROW(1,1), 1);
+ERROR HY000: Illegal parameter data type row for operation 'st_distance'
+SELECT ST_DISTANCE(1, 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_distance'
+SELECT ST_DISTANCE('test', 1);
+ERROR HY000: Illegal parameter data type varchar for operation 'st_distance'
+SELECT ST_DISTANCE(POINT(1,1), ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_distance'
+SELECT ST_DISTANCE(POINT(1,1), 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_distance'
+SELECT ST_DISTANCE(POINT(1,1), 'test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_distance'
+# Item_int_func_args_geometry
+SELECT ST_ISSIMPLE(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_issimple'
+SELECT ST_ISSIMPLE(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_issimple'
+SELECT ST_ISSIMPLE('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_issimple'
+SELECT ST_ISRING(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_isring'
+SELECT ST_ISRING(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_isring'
+SELECT ST_ISRING('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_isring'
+SELECT ST_ISCLOSED(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_isclosed'
+SELECT ST_ISCLOSED(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_isclosed'
+SELECT ST_ISCLOSED('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_isclosed'
+SELECT ST_DIMENSION(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_dimension'
+SELECT ST_DIMENSION(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_dimension'
+SELECT ST_DIMENSION('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_dimension'
+SELECT ST_NUMGEOMETRIES(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_numgeometries'
+SELECT ST_NUMGEOMETRIES(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_numgeometries'
+SELECT ST_NUMGEOMETRIES('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_numgeometries'
+SELECT ST_NUMINTERIORRINGS(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_numinteriorrings'
+SELECT ST_NUMINTERIORRINGS(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_numinteriorrings'
+SELECT ST_NUMINTERIORRINGS('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_numinteriorrings'
+SELECT ST_NUMPOINTS(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_numpoints'
+SELECT ST_NUMPOINTS(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_numpoints'
+SELECT ST_NUMPOINTS('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_numpoints'
+SELECT ST_SRID(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'srid'
+SELECT ST_SRID(1);
+ERROR HY000: Illegal parameter data type int for operation 'srid'
+SELECT ST_SRID('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'srid'
+# Item_bool_func_args_geometry
+SELECT ST_ISEMPTY(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_isempty'
+SELECT ST_ISEMPTY(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_isempty'
+SELECT ST_ISEMPTY('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_isempty'
+# Item_bool_func_geometry_args_geometry_geometry
+SELECT ST_RELATE(ROW(1,1), POINT(1,1), 'T*F**FFF*');
+ERROR HY000: Illegal parameter data type row for operation 'st_relate'
+SELECT ST_RELATE(POINT(1,1), ROW(1,1), 'T*F**FFF*');
+ERROR HY000: Illegal parameter data type row for operation 'st_relate'
+SELECT ST_RELATE(1, POINT(1,1), 'T*F**FFF*');
+ERROR HY000: Illegal parameter data type int for operation 'st_relate'
+SELECT ST_RELATE(POINT(1,1), 1, 'T*F**FFF*');
+ERROR HY000: Illegal parameter data type int for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),'T*F**FFF*') AS equals;
+equals
+1
+SELECT ST_RELATE(Point(1,1),Point(1,1),NULL);
+ST_RELATE(Point(1,1),Point(1,1),NULL)
+NULL
+SELECT ST_RELATE(Point(1,1),Point(1,1),ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),1);
+ERROR HY000: Illegal parameter data type int for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),1.0);
+ERROR HY000: Illegal parameter data type decimal for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),1e0);
+ERROR HY000: Illegal parameter data type double for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),TIME'10:10:10');
+ERROR HY000: Illegal parameter data type time for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),DATE'2010-01-01');
+ERROR HY000: Illegal parameter data type date for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),TIMESTAMP'2010-01-01 10:10:10');
+ERROR HY000: Illegal parameter data type datetime for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_relate'
+# Item_str_ascii_func_args_geometry
+SELECT ST_ASTEXT(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_astext'
+SELECT ST_ASTEXT(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_astext'
+SELECT ST_ASTEXT('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_astext'
+SELECT ST_GEOMETRYTYPE(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_geometrytype'
+SELECT ST_GEOMETRYTYPE(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_geometrytype'
+SELECT ST_GEOMETRYTYPE('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_geometrytype'
+SELECT ST_ASGEOJSON(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_asgeojson'
+SELECT ST_ASGEOJSON(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_asgeojson'
+SELECT ST_ASGEOJSON('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_asgeojson'
+SELECT ST_ASGEOJSON(POINT(1,1), POINT(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_asgeojson'
+SELECT ST_ASGEOJSON(POINT(1,1), 1, POINT(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_asgeojson'
+# Item_func_spatial_rel
+SELECT ST_TOUCHES(ROW(1,1), POINT(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_touches'
+SELECT ST_TOUCHES(POINT(1,1), ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_touches'
+SELECT ST_TOUCHES(1, POINT(1,1));
+ERROR HY000: Illegal parameter data type int for operation 'st_touches'
+SELECT ST_TOUCHES(POINT(1,1), 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_touches'
+SELECT ST_TOUCHES('test', POINT(1,1));
+ERROR HY000: Illegal parameter data type varchar for operation 'st_touches'
+SELECT ST_TOUCHES(POINT(1,1), 'test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_touches'
+SELECT MBRTOUCHES(ROW(1,1), POINT(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_touches'
+SELECT MBRTOUCHES(POINT(1,1), ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_touches'
+SELECT MBRTOUCHES(1, POINT(1,1));
+ERROR HY000: Illegal parameter data type int for operation 'st_touches'
+SELECT MBRTOUCHES(POINT(1,1), 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_touches'
+SELECT MBRTOUCHES('test', POINT(1,1));
+ERROR HY000: Illegal parameter data type varchar for operation 'st_touches'
+SELECT MBRTOUCHES(POINT(1,1), 'test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_touches'
+#
 # End of 10.3 tests
 #
diff --git a/mysql-test/suite/innodb_gis/r/1.result b/mysql-test/suite/innodb_gis/r/1.result
index 3ab57ba..0c0c683 100644
--- a/mysql-test/suite/innodb_gis/r/1.result
+++ b/mysql-test/suite/innodb_gis/r/1.result
@@ -1024,9 +1024,9 @@ f5	datetime	YES		NULL
 drop view v1;
 drop table t1;
 SELECT MultiPoint(12345,'');
-ERROR 22007: Illegal non geometric '12345' value found during parsing
+ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
 SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
-ERROR 22007: Illegal non geometric ''00000'' value found during parsing
+ERROR HY000: Illegal parameter data type varchar for operation 'geometrycollection'
 #
 # BUG#51875: crash when loading data into geometry function ST_polyfromwkb
 #
@@ -1090,7 +1090,7 @@ ST_ISCLOSED(CONVERT(CONCAT('     ', 0x2), BINARY(20)))
 # GEOMETRY FUNCTION ARGUMENTS
 #
 SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
-ERROR 22007: Illegal non geometric '' value found during parsing
+ERROR HY000: Illegal parameter data type bigint for operation 'geometrycollection'
 End of 5.1 tests
 #
 # Bug#11908153: CRASH AND/OR VALGRIND ERRORS IN FIELD_BLOB::GET_KEY_IMAGE
@@ -1489,5 +1489,4 @@ DROP DATABASE gis_ogs;
 # Bug#13362660 ASSERTION `FIELD_POS < FIELD_COUNT' FAILED. IN PROTOCOL_TEXT::STORE
 #
 SELECT ST_Union('', ''), md5(1);
-ST_Union('', '')	md5(1)
-NULL	c4ca4238a0b923820dcc509a6f75849b
+ERROR HY000: Illegal parameter data type varchar for operation 'st_union'
diff --git a/mysql-test/suite/innodb_gis/r/gis.result b/mysql-test/suite/innodb_gis/r/gis.result
index beb4115..836a15b 100644
--- a/mysql-test/suite/innodb_gis/r/gis.result
+++ b/mysql-test/suite/innodb_gis/r/gis.result
@@ -1020,9 +1020,9 @@ f5	datetime	YES		NULL
 drop view v1;
 drop table t1;
 SELECT MultiPoint(12345,'');
-ERROR 22007: Illegal non geometric '12345' value found during parsing
+ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
 SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
-ERROR 22007: Illegal non geometric ''00000'' value found during parsing
+ERROR HY000: Illegal parameter data type varchar for operation 'geometrycollection'
 #
 # BUG#51875: crash when loading data into geometry function ST_polyfromwkb
 #
@@ -1091,7 +1091,7 @@ ST_ISCLOSED(CONVERT(CONCAT('     ', 0x2), BINARY(20)))
 # GEOMETRY FUNCTION ARGUMENTS
 #
 SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
-ERROR 22007: Illegal non geometric '' value found during parsing
+ERROR HY000: Illegal parameter data type bigint for operation 'geometrycollection'
 End of 5.1 tests
 #
 # Bug#11908153: CRASH AND/OR VALGRIND ERRORS IN FIELD_BLOB::GET_KEY_IMAGE
@@ -1481,5 +1481,4 @@ DROP DATABASE gis_ogs;
 # Bug#13362660 ASSERTION `FIELD_POS < FIELD_COUNT' FAILED. IN PROTOCOL_TEXT::STORE
 #
 SELECT ST_Union('', ''), md5(1);
-ST_Union('', '')	md5(1)
-NULL	c4ca4238a0b923820dcc509a6f75849b
+ERROR HY000: Illegal parameter data type varchar for operation 'st_union'
diff --git a/mysql-test/suite/innodb_gis/r/precise.result b/mysql-test/suite/innodb_gis/r/precise.result
index 9d6538b..3c05b81 100644
--- a/mysql-test/suite/innodb_gis/r/precise.result
+++ b/mysql-test/suite/innodb_gis/r/precise.result
@@ -216,8 +216,7 @@ st_u
 MULTIPOLYGON(((525400 18370,525000.9677614468 183300,525400 183300,525400 18370)),((525000 183300,525000 183700,525000.9677614468 183300,525000 183300)),((525265.58 183481.95,525263.95 183484.75,525260.7 183491.55,525276.79 183500,525278.39 183500.84,525278.63 183500.97,525280.98 183502.26,525283.17 183503.47,525289.11 183506.62,525296.42 183510.31,525296.57 183510.39,525298.67 183511.53,525302.81 183513.8,525304.5 183510.83,525307.85 183504.95,525304.45 183504.25,525301.75 183509.35,525283.55 183500,525282.2 183499.3,525282.3 183499.1,525280.35 183498.2,525275.5 183495.7,525276.5 183493.45,525278.97 183488.73,525265.58 183481.95),(525266.99 183484.33,525263.26 183491.55,525266.15 183493.04,525269.88 183485.82,525266.99 183484.33),(525272.06 183488.37,525268.94 183494.51,525271.94 183496.03,525275.06 183489.89,525272.06 183488.37)))
 SET @a=0x0000000001030000000200000005000000000000000000000000000000000000000000000000002440000000000000000000000000000024400000000000002440000000000000000000000000000024400000000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F0000000000000040000000000000F03F000000000000F03F;
 SELECT ST_ASTEXT(ST_TOUCHES(@a, ST_GEOMFROMTEXT('point(0 0)'))) t;
-t
-NULL
+ERROR HY000: Illegal parameter data type int for operation 'st_astext'
 DROP TABLE IF EXISTS p1;
 CREATE PROCEDURE p1(dist DOUBLE, geom TEXT)
 BEGIN
diff --git a/mysql-test/suite/innodb_gis/t/1.test b/mysql-test/suite/innodb_gis/t/1.test
index cda4ef0..0dd4d32 100644
--- a/mysql-test/suite/innodb_gis/t/1.test
+++ b/mysql-test/suite/innodb_gis/t/1.test
@@ -738,7 +738,7 @@ drop table t1;
 # Bug#44684: valgrind reports invalid reads in 
 # Item_func_spatial_collection::val_str
 #
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT MultiPoint(12345,'');
 #SELECT MultiPoint(123451,'');
 #SELECT MultiPoint(1234512,'');
@@ -765,7 +765,7 @@ SELECT MultiPoint(12345,'');
 #
 # Bug55531 crash with conversions of geometry types / strings
 #
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
 
 
@@ -868,7 +868,7 @@ SELECT ST_ISCLOSED(CONVERT(CONCAT('     ', 0x2), BINARY(20)));
 --echo # GEOMETRY FUNCTION ARGUMENTS
 --echo #
 --replace_regex /non geometric .* value/non geometric '' value/
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
 
 
@@ -1449,5 +1449,5 @@ DROP DATABASE gis_ogs;
 --echo # Bug#13362660 ASSERTION `FIELD_POS < FIELD_COUNT' FAILED. IN PROTOCOL_TEXT::STORE
 --echo #
 
-# --error ER_GIS_INVALID_DATA
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT ST_Union('', ''), md5(1);
diff --git a/mysql-test/suite/innodb_gis/t/gis.test b/mysql-test/suite/innodb_gis/t/gis.test
index d6de03a..8087f6b 100644
--- a/mysql-test/suite/innodb_gis/t/gis.test
+++ b/mysql-test/suite/innodb_gis/t/gis.test
@@ -732,7 +732,7 @@ drop table t1;
 # Bug#44684: valgrind reports invalid reads in
 # Item_func_spatial_collection::val_str
 #
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT MultiPoint(12345,'');
 #SELECT MultiPoint(123451,'');
 #SELECT MultiPoint(1234512,'');
@@ -759,7 +759,7 @@ SELECT MultiPoint(12345,'');
 #
 # Bug55531 crash with conversions of geometry types / strings
 #
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
 
 
@@ -870,7 +870,7 @@ SELECT ST_ISCLOSED(CONVERT(CONCAT('     ', 0x2), BINARY(20)));
 --echo # GEOMETRY FUNCTION ARGUMENTS
 --echo #
 --replace_regex /non geometric .* value/non geometric '' value/
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
 
 
@@ -1443,4 +1443,5 @@ DROP DATABASE gis_ogs;
 --echo #
 
 # --error ER_GIS_INVALID_DATA
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT ST_Union('', ''), md5(1);
diff --git a/mysql-test/suite/innodb_gis/t/precise.test b/mysql-test/suite/innodb_gis/t/precise.test
index 9174a10..08b7e34 100644
--- a/mysql-test/suite/innodb_gis/t/precise.test
+++ b/mysql-test/suite/innodb_gis/t/precise.test
@@ -140,7 +140,7 @@ ST_geomfromtext('POLYGON((525298.67 183511.53,525296.57
 183491.55))'))) st_u;
 
 SET @a=0x0000000001030000000200000005000000000000000000000000000000000000000000000000002440000000000000000000000000000024400000000000002440000000000000000000000000000024400000000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F0000000000000040000000000000F03F000000000000F03F;
-# --error ER_GIS_INVALID_DATA
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT ST_ASTEXT(ST_TOUCHES(@a, ST_GEOMFROMTEXT('point(0 0)'))) t;
 
 
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index abc8647..1038fc0 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -745,7 +745,7 @@ DROP TABLE t1;
 CREATE TABLE t1(f1 int);
 INSERT INTO t1 values (0),(0);
 --disable_ps_protocol
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT POLYGON((SELECT 1 FROM (SELECT 1 IN (GROUP_CONCAT(t1.f1)) FROM t1, t1 t GROUP BY t.f1 ) d));
 --enable_ps_protocol
 DROP TABLE t1;
diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
index ff8d6bb..ee70102 100644
--- a/mysql-test/t/func_math.test
+++ b/mysql-test/t/func_math.test
@@ -352,10 +352,10 @@ DROP TABLE t1;
 --echo # Bug#11764994  57900: CREATE TABLE .. SELECT ASSERTS SCALE >= 0 && PRECISION > 0 && SCALE <= PR
 --echo #
 
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 CREATE TABLE t1 SELECT CEIL(LINESTRINGFROMWKB(1) DIV NULL);
-DROP TABLE t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 CREATE TABLE t1 SELECT FLOOR(LINESTRINGFROMWKB(1) DIV NULL);
-DROP TABLE t1;
 
 --echo #
 --echo # Bug#11765923  58937: MANY VALGRIND ERRORS AFTER GROUPING BY RESULT OF DECIMAL COLUMN FUNCTION
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index c469461..2f7dd63 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -1606,7 +1606,7 @@ format(rpad('111111111.1',
 # and can't suppress prepare time warnings for DO.
 #
 
---error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT
 round(
   concat( (
diff --git a/mysql-test/t/gis-precise.test b/mysql-test/t/gis-precise.test
index 5e57569..1f8259b 100644
--- a/mysql-test/t/gis-precise.test
+++ b/mysql-test/t/gis-precise.test
@@ -134,6 +134,7 @@ geomfromtext('POLYGON((525298.67 183511.53,525296.57
 183491.55))'))) st_u;
 
 SET @a=0x0000000001030000000200000005000000000000000000000000000000000000000000000000002440000000000000000000000000000024400000000000002440000000000000000000000000000024400000000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F0000000000000040000000000000F03F000000000000F03F;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT ASTEXT(TOUCHES(@a, GEOMFROMTEXT('point(0 0)'))) t;
 
 
diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test
index a17d691..9763983 100644
--- a/mysql-test/t/gis-rtree.test
+++ b/mysql-test/t/gis-rtree.test
@@ -61,7 +61,7 @@ while ($1)
   let $2=10;
   while ($2)
   {
-    eval DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point($1 * 10 - 9, $2 * 10 - 9), Point($1 * 10, $2 * 10))));
+    eval DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point($1 * 10 - 9, $2 * 10 - 9), 0)));
     SELECT count(*) FROM t2;
     dec $2;
   }
@@ -998,11 +998,17 @@ DROP TABLE t1;
 --echo #
 CREATE TABLE t1  (a GEOMETRY NOT NULL, SPATIAL KEY(a)) ENGINE=MyISAM;
 INSERT INTO t1 VALUES (Point(1,1)),(Point(2,2)),(Point(3,3));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,1.0);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,1e0);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,TIME'00:00:00');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,DATE'2001-01-01');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,TIMESTAMP'2001-01-01 00:00:00');
 DROP TABLE t1;
 
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index b38e68f..a3d27d3 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -706,7 +706,7 @@ drop table t1;
 # Bug#44684: valgrind reports invalid reads in 
 # Item_func_spatial_collection::val_str
 #
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT MultiPoint(12345,'');
 #SELECT MultiPoint(123451,'');
 #SELECT MultiPoint(1234512,'');
@@ -733,7 +733,7 @@ SELECT MultiPoint(12345,'');
 #
 # Bug55531 crash with conversions of geometry types / strings
 #
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
 
 
@@ -826,7 +826,7 @@ SELECT ISCLOSED(CONVERT(CONCAT('     ', 0x2), BINARY(20)));
 --echo # GEOMETRY FUNCTION ARGUMENTS
 --echo #
 --replace_regex /non geometric .* value/non geometric '' value/
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
 
 --echo #
@@ -1373,6 +1373,7 @@ create table t1(a geometry not null)engine=myisam;
 insert into t1 values(geomfromtext("POINT(0 0)"));
 insert into t1 values(geomfromtext("POINT(0 9.2233720368548e18)"));
 insert into t1 values(geomfromtext("POINT(0 9.2233720368548e18)"));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
 select equals(`a`,convert(`a` using utf8)) from `t1`;
 select equals(`a`,left(`a`,23)) from `t1`;
 drop table t1;
@@ -2305,7 +2306,6 @@ EXECUTE stmt USING POINT(1,1);
 SHOW CREATE TABLE t1;
 DROP TABLE t1;
 
-
 --echo #
 --echo # MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
 --echo #
@@ -2326,5 +2326,341 @@ SELECT
 
 
 --echo #
+--echo # MDEV-12803 Improve function parameter data type control
+--echo #
+
+--echo #
+--echo # Item_geometry_func_args_geometry
+--echo #
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_CENTROID(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ENVELOPE(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_BOUNDARY(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_STARTPOINT(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_POINTONSURFACE(1);
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_POINTN(1,1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_POINTN(LineString(Point(1,1)),Point(1,1));
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_BUFFER(1, 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_BUFFER(Point(1,1), Point(1,1));
+
+
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ST_ENVELOPE(?) AS g';
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+EXECUTE stmt USING 1;
+EXECUTE stmt USING POINT(1,1);
+SHOW CREATE TABLE t1;
+SELECT ST_ASTEXT(g) FROM t1;
+DROP TABLE t1;
+DEALLOCATE PREPARE stmt;
+
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ST_BUFFER(?,?) AS g';
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+EXECUTE stmt USING 1,1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+EXECUTE stmt USING POINT(1,1),POINT(1,1);
+EXECUTE stmt USING POINT(1,1),0;
+SHOW CREATE TABLE t1;
+SELECT ST_GEOMETRYTYPE(g) FROM t1;
+DROP TABLE t1;
+DEALLOCATE PREPARE stmt;
+
+--echo #
+--echo # Functions created GEOMETRY from non-GEOMETRY
+--echo #
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMTEXT(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMTEXT(Point(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMTEXT(Point(1,1), 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMTEXT('test', Point(1,1));
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMWKB(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMWKB(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMWKB(1, 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMWKB(Point(1,1), Point(1,1));
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMFROMGEOJSON(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMFROMGEOJSON(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMFROMGEOJSON(1,1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMFROMGEOJSON(Point(1,1), Point(1,1));
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT POINT(ROW(1,1),1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT POINT(POINT(1,1),1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT POINT(1,ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT POINT(1,POINT(1,1));
+
+
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ST_GEOMFROMTEXT(?,?) AS g';
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+EXECUTE stmt USING 1,1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+EXECUTE stmt USING POINT(1,1),POINT(1,1);
+EXECUTE stmt USING 'POINT(1 1)',1;
+SHOW CREATE TABLE t1;
+SELECT ST_ASTEXT(g), SRID(g) FROM t1;
+DROP TABLE t1;
+DEALLOCATE PREPARE stmt;
+
+
+
+--echo # Item_func_spatial_collection
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT GEOMETRYCOLLECTION(ROW(1,1), POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT GEOMETRYCOLLECTION(POINT(1,1), ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT GEOMETRYCOLLECTION(1, POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT GEOMETRYCOLLECTION(POINT(1,1), 1);
+
+--echo # Item_func_spatial_operation
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_UNION(ROW(1,1), POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_UNION(POINT(1,1), ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_UNION(1, POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_UNION(POINT(1,1), 1);
+
+--echo # Item_binary_func_args_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASWKB(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASWKB(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASWKB('test');
+
+
+--echo # Item_real_func_args_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_X(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_X(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_X('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_Y(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_Y(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_Y('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_AREA(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_AREA(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_AREA('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_LENGTH(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_LENGTH(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_LENGTH('test');
+
+
+--echo # Item_real_func_geometry_args_geometry_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DISTANCE(ROW(1,1), 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DISTANCE(1, 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DISTANCE('test', 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DISTANCE(POINT(1,1), ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DISTANCE(POINT(1,1), 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DISTANCE(POINT(1,1), 'test');
+
+
+--echo # Item_int_func_args_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISSIMPLE(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISSIMPLE(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISSIMPLE('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISRING(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISRING(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISRING('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISCLOSED(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISCLOSED(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISCLOSED('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DIMENSION(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DIMENSION(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DIMENSION('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMGEOMETRIES(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMGEOMETRIES(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMGEOMETRIES('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMINTERIORRINGS(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMINTERIORRINGS(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMINTERIORRINGS('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMPOINTS(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMPOINTS(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMPOINTS('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_SRID(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_SRID(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_SRID('test');
+
+
+--echo # Item_bool_func_args_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISEMPTY(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISEMPTY(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISEMPTY('test');
+
+--echo # Item_bool_func_geometry_args_geometry_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(ROW(1,1), POINT(1,1), 'T*F**FFF*');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(POINT(1,1), ROW(1,1), 'T*F**FFF*');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(1, POINT(1,1), 'T*F**FFF*');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(POINT(1,1), 1, 'T*F**FFF*');
+SELECT ST_RELATE(Point(1,1),Point(1,1),'T*F**FFF*') AS equals;
+SELECT ST_RELATE(Point(1,1),Point(1,1),NULL);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),1.0);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),1e0);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),TIME'10:10:10');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),DATE'2010-01-01');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),TIMESTAMP'2010-01-01 10:10:10');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),Point(1,1));
+
+
+--echo # Item_str_ascii_func_args_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASTEXT(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASTEXT(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASTEXT('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYTYPE(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYTYPE(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYTYPE('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASGEOJSON(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASGEOJSON(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASGEOJSON('test');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASGEOJSON(POINT(1,1), POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASGEOJSON(POINT(1,1), 1, POINT(1,1));
+
+--echo # Item_func_spatial_rel
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_TOUCHES(ROW(1,1), POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_TOUCHES(POINT(1,1), ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_TOUCHES(1, POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_TOUCHES(POINT(1,1), 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_TOUCHES('test', POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_TOUCHES(POINT(1,1), 'test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MBRTOUCHES(ROW(1,1), POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MBRTOUCHES(POINT(1,1), ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MBRTOUCHES(1, POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MBRTOUCHES(POINT(1,1), 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MBRTOUCHES('test', POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MBRTOUCHES(POINT(1,1), 'test');
+
+--echo #
 --echo # End of 10.3 tests
 --echo #
diff --git a/sql/item.cc b/sql/item.cc
index 43a443d..f4236ee 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1059,6 +1059,75 @@ bool Item::check_cols(uint c)
   return 0;
 }
 
+
+bool Item::check_type_or_binary(const char *opname,
+                                const Type_handler *expect) const
+{
+  const Type_handler *handler= type_handler();
+  if (handler == expect ||
+      (handler->is_general_purpose_string_type() &&
+       collation.collation == &my_charset_bin))
+    return false;
+  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+           handler->name().ptr(), opname);
+  return true;
+}
+
+
+bool Item::check_type_general_purpose_string(const char *opname) const
+{
+  const Type_handler *handler= type_handler();
+  if (handler->is_general_purpose_string_type())
+    return false;
+  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+           handler->name().ptr(), opname);
+  return true;
+}
+
+
+bool Item::check_type_traditional_scalar(const char *opname) const
+{
+  const Type_handler *handler= type_handler();
+  if (handler->is_traditional_type() && handler->is_scalar_type())
+    return false;
+  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+           handler->name().ptr(), opname);
+  return true;
+}
+
+
+bool Item::check_type_can_return_int(const char *opname) const
+{
+  const Type_handler *handler= type_handler();
+  if (handler->can_return_int())
+    return false;
+  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+           handler->name().ptr(), opname);
+  return true;
+}
+
+
+bool Item::check_type_can_return_real(const char *opname) const
+{
+  const Type_handler *handler= type_handler();
+  if (handler->can_return_real())
+    return false;
+  my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+           handler->name().ptr(), opname);
+  return true;
+}
+
+
+bool Item::check_type_scalar(const char *opname) const
+{
+  const Type_handler *handler= type_handler();
+  if (handler->is_scalar_type())
+    return false;
+  my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
+  return true;
+}
+
+
 void Item::set_name(THD *thd, const char *str, uint length, CHARSET_INFO *cs)
 {
   if (!length)
@@ -3553,7 +3622,16 @@ Item_param::Item_param(THD *thd, const LEX_CSTRING *name_arg,
                        uint pos_in_query_arg, uint len_in_query_arg):
   Item_basic_value(thd),
   Rewritable_query_parameter(pos_in_query_arg, len_in_query_arg),
-  Type_handler_hybrid_field_type(&type_handler_varchar),
+  /*
+    Set handler to type_handler_null. Its data type test methods such as:
+    - is_scalar_type()
+    - can_return_int()
+    - can_return_real(),
+    - is_general_purpose_string_type()
+    all return "true". This is needed to avoid any "illegal parameter type"
+    errors in Item::check_type_xxx() at PS prepare time.
+  */
+  Type_handler_hybrid_field_type(&type_handler_null),
   state(NO_VALUE),
   /* Don't pretend to be a literal unless value for this item is set. */
   item_type(PARAM_ITEM),
diff --git a/sql/item.h b/sql/item.h
index 05badb1..44f2ab6 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1645,6 +1645,12 @@ class Item: public Value_source,
   }
   virtual Item** addr(uint i) { return 0; }
   virtual bool check_cols(uint c);
+  bool check_type_traditional_scalar(const char *opname) const;
+  bool check_type_scalar(const char *opname) const;
+  bool check_type_or_binary(const char *opname, const Type_handler *handler) const;
+  bool check_type_general_purpose_string(const char *opname) const;
+  bool check_type_can_return_int(const char *opname) const;
+  bool check_type_can_return_real(const char *opname) const;
   // It is not row => null inside is impossible
   virtual bool null_inside() { return 0; }
   // used in row subselects to get value of elements
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 3c61a9c..e21e074 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -481,12 +481,14 @@ class Item_bool_rowready_func2 :public Item_bool_func2_with_rev
 {
 protected:
   Arg_comparator cmp;
+  bool check_arguments() const
+  {
+    return check_argument_types_like_args0();
+  }
 public:
   Item_bool_rowready_func2(THD *thd, Item *a, Item *b):
     Item_bool_func2_with_rev(thd, a, b), cmp(tmp_arg, tmp_arg + 1)
-  {
-    allowed_arg_cols= 0;  // Fetch this value from first argument
-  }
+  { }
   void print(String *str, enum_query_type query_type)
   {
     Item_func::print_op(str, query_type);
@@ -952,12 +954,14 @@ class Item_func_interval :public Item_long_func
   Item_row *row;
   bool use_decimal_comparison;
   interval_range *intervals;
+  bool check_arguments() const
+  {
+    return check_argument_types_like_args0();
+  }
 public:
   Item_func_interval(THD *thd, Item_row *a):
     Item_long_func(thd, a), row(a), intervals(0)
-  {
-    allowed_arg_cols= 0;    // Fetch this value from first argument
-  }
+  { }
   longlong val_int();
   void fix_length_and_dec();
   const char *func_name() const { return "interval"; }
@@ -2117,6 +2121,10 @@ class Item_func_in :public Item_func_opt_neg,
     return true;
   }
   bool prepare_predicant_and_values(THD *thd, uint *found_types);
+  bool check_arguments() const
+  {
+    return check_argument_types_like_args0();
+  }
 protected:
   SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
                              Field *field, Item *value);
@@ -2141,9 +2149,7 @@ class Item_func_in :public Item_func_opt_neg,
     Predicant_to_list_comparator(thd, arg_count - 1),
     array(0), have_null(0),
     arg_types_compatible(FALSE)
-  {
-    allowed_arg_cols= 0;  // Fetch this value from first argument
-  }
+  { }
   longlong val_int();
   bool fix_fields(THD *, Item **);
   void fix_length_and_dec();
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 19e91da..502149d 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -151,15 +151,81 @@ void Item_func::sync_with_sum_func_and_with_field(List<Item> &list)
 }
 
 
-bool Item_func::check_allowed_arg_cols(uint n)
+bool Item_func::check_argument_types_like_args0() const
 {
-  if (allowed_arg_cols)
-    return args[n]->check_cols(allowed_arg_cols);
+  uint cols;
+  if (arg_count == 0)
+    return false;
+  cols= args[0]->cols();
+  for (uint i= 1; i < arg_count; i++)
+  {
+    if (args[i]->check_cols(cols))
+      return true;
+  }
+  return false;
+}
 
-  /*  we have to fetch allowed_arg_cols from first argument */
-  DBUG_ASSERT(n == 0); // it is first argument
-  allowed_arg_cols= args[n]->cols();
-  DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more
+
+bool Item_func::check_argument_types_or_binary(const Type_handler *handler,
+                                               uint start, uint end) const
+{
+  for (uint i= start; i < end ; i++)
+  {
+    DBUG_ASSERT(i < arg_count);
+    if (args[i]->check_type_or_binary(func_name(), handler))
+      return true;
+  }
+  return false;
+}
+
+
+bool Item_func::check_argument_types_traditional_scalar(uint start,
+                                                        uint end) const
+{
+  for (uint i= start; i < end ; i++)
+  {
+    DBUG_ASSERT(i < arg_count);
+    if (args[i]->check_type_traditional_scalar(func_name()))
+      return true;
+  }
+  return false;
+}
+
+
+bool Item_func::check_argument_types_can_return_int(uint start,
+                                                    uint end) const
+{
+  for (uint i= start; i < end ; i++)
+  {
+    DBUG_ASSERT(i < arg_count);
+    if (args[i]->check_type_can_return_int(func_name()))
+      return true;
+  }
+  return false;
+}
+
+
+bool Item_func::check_argument_types_can_return_real(uint start,
+                                                     uint end) const
+{
+  for (uint i= start; i < end ; i++)
+  {
+    DBUG_ASSERT(i < arg_count);
+    if (args[i]->check_type_can_return_real(func_name()))
+      return true;
+  }
+  return false;
+}
+
+
+bool Item_func::check_argument_types_scalar(uint start, uint end) const
+{
+  for (uint i= start; i < end; i++)
+  {
+    DBUG_ASSERT(i < arg_count);
+    if (args[i]->check_type_scalar(func_name()))
+      return true;
+  }
   return false;
 }
 
@@ -236,9 +302,6 @@ Item_func::fix_fields(THD *thd, Item **ref)
 	return TRUE;				/* purecov: inspected */
       item= *arg;
 
-      if (check_allowed_arg_cols(arg - args))
-        return true;
-
       if (item->maybe_null)
 	maybe_null=1;
 
@@ -249,6 +312,8 @@ Item_func::fix_fields(THD *thd, Item **ref)
       with_subselect|=        item->has_subquery();
     }
   }
+  if (check_arguments())
+    return true;
   fix_length_and_dec();
   if (thd->is_error()) // An error inside fix_length_and_dec occurred
     return TRUE;
diff --git a/sql/item_func.h b/sql/item_func.h
index e58740e..b17642e 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -35,14 +35,19 @@ class Item_func :public Item_func_or_sum
 {
   void sync_with_sum_func_and_with_field(List<Item> &list);
 protected:
-  /*
-    Allowed numbers of columns in result (usually 1, which means scalar value)
-    0 means get this number from first argument
-  */
-  uint allowed_arg_cols;
   String *val_str_from_val_str_ascii(String *str, String *str2);
 
-  virtual bool check_allowed_arg_cols(uint argno);
+  virtual bool check_arguments() const
+  {
+    return check_argument_types_scalar(0, arg_count);
+  }
+  bool check_argument_types_like_args0() const;
+  bool check_argument_types_scalar(uint start, uint end) const;
+  bool check_argument_types_traditional_scalar(uint start, uint end) const;
+  bool check_argument_types_or_binary(const Type_handler *handler,
+                                      uint start, uint end) const;
+  bool check_argument_types_can_return_int(uint start, uint end) const;
+  bool check_argument_types_can_return_real(uint start, uint end) const;
 public:
 
   table_map not_null_tables_cache;
@@ -65,30 +70,30 @@ class Item_func :public Item_func_or_sum
                   NEG_FUNC, GSYSVAR_FUNC, DYNCOL_FUNC };
   enum Type type() const { return FUNC_ITEM; }
   virtual enum Functype functype() const   { return UNKNOWN_FUNC; }
-  Item_func(THD *thd): Item_func_or_sum(thd), allowed_arg_cols(1)
+  Item_func(THD *thd): Item_func_or_sum(thd)
   {
     with_sum_func= 0;
     with_field= 0;
   }
-  Item_func(THD *thd, Item *a): Item_func_or_sum(thd, a), allowed_arg_cols(1)
+  Item_func(THD *thd, Item *a): Item_func_or_sum(thd, a)
   {
     with_sum_func= a->with_sum_func;
     with_field= a->with_field;
   }
   Item_func(THD *thd, Item *a, Item *b):
-    Item_func_or_sum(thd, a, b), allowed_arg_cols(1)
+    Item_func_or_sum(thd, a, b)
   {
     with_sum_func= a->with_sum_func || b->with_sum_func;
     with_field= a->with_field || b->with_field;
   }
   Item_func(THD *thd, Item *a, Item *b, Item *c):
-    Item_func_or_sum(thd, a, b, c), allowed_arg_cols(1)
+    Item_func_or_sum(thd, a, b, c)
   {
     with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func;
     with_field= a->with_field || b->with_field || c->with_field;
   }
   Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d):
-    Item_func_or_sum(thd, a, b, c, d), allowed_arg_cols(1)
+    Item_func_or_sum(thd, a, b, c, d)
   {
     with_sum_func= a->with_sum_func || b->with_sum_func ||
                    c->with_sum_func || d->with_sum_func;
@@ -96,7 +101,7 @@ class Item_func :public Item_func_or_sum
                 c->with_field || d->with_field;
   }
   Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e):
-    Item_func_or_sum(thd, a, b, c, d, e), allowed_arg_cols(1)
+    Item_func_or_sum(thd, a, b, c, d, e)
   {
     with_sum_func= a->with_sum_func || b->with_sum_func ||
                    c->with_sum_func || d->with_sum_func || e->with_sum_func;
@@ -104,14 +109,13 @@ class Item_func :public Item_func_or_sum
                 c->with_field || d->with_field || e->with_field;
   }
   Item_func(THD *thd, List<Item> &list):
-    Item_func_or_sum(thd, list), allowed_arg_cols(1)
+    Item_func_or_sum(thd, list)
   {
     set_arguments(thd, list);
   }
   // Constructor used for Item_cond_and/or (see Item comment)
   Item_func(THD *thd, Item_func *item):
     Item_func_or_sum(thd, item),
-    allowed_arg_cols(item->allowed_arg_cols),
     not_null_tables_cache(item->not_null_tables_cache)
   {
   }
@@ -141,7 +145,6 @@ class Item_func :public Item_func_or_sum
   virtual Item *key_item() const { return args[0]; }
   void set_arguments(THD *thd, List<Item> &list)
   {
-    allowed_arg_cols= 1;
     Item_args::set_arguments(thd, list);
     sync_with_sum_func_and_with_field(list);
     list.empty();                                     // Fields are used
@@ -2662,7 +2665,7 @@ class Item_func_sp :public Item_func
   bool is_expensive_processor(void *arg)
   { return is_expensive(); }
 
-  bool check_allowed_arg_cols(uint n)
+  bool check_arguments() const
   {
     // sp_prepare_func_item() checks that the number of columns is correct
     return false;
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index cbd37fc..838f0b2 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -42,8 +42,160 @@ class Item_geometry_func: public Item_str_func
   const Type_handler *type_handler() const { return &type_handler_geometry; }
 };
 
+
+/*
+  Functions returning REAL measurements of a single GEOMETRY argument
+*/
+class Item_real_func_args_geometry: public Item_real_func
+{
+protected:
+  String value;
+  bool check_arguments() const
+  {
+    DBUG_ASSERT(arg_count == 1);
+    return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+  }
+public:
+  Item_real_func_args_geometry(THD *thd, Item *a)
+   :Item_real_func(thd, a) {}
+};
+
+
+/*
+  Functions returning INT measurements of a single GEOMETRY argument
+*/
+class Item_long_func_args_geometry: public Item_long_func
+{
+  bool check_arguments() const
+  {
+    DBUG_ASSERT(arg_count == 1);
+    return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+  }
+protected:
+  String value;
+public:
+  Item_long_func_args_geometry(THD *thd, Item *a)
+   :Item_long_func(thd, a) {}
+};
+
+
+/*
+  Functions returning BOOL measurements of a single GEOMETRY argument
+*/
+class Item_bool_func_args_geometry: public Item_bool_func
+{
+protected:
+  String value;
+  bool check_arguments() const
+  {
+    DBUG_ASSERT(arg_count == 1);
+    return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+  }
+public:
+  Item_bool_func_args_geometry(THD *thd, Item *a)
+   :Item_bool_func(thd, a) {}
+};
+
+
+/*
+  Functions returning ASCII string measurements of a single GEOMETRY argument
+*/
+class Item_str_ascii_func_args_geometry: public Item_str_ascii_func
+{
+protected:
+  bool check_arguments() const
+  {
+    DBUG_ASSERT(arg_count >= 1);
+    return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+  }
+public:
+  Item_str_ascii_func_args_geometry(THD *thd, Item *a)
+   :Item_str_ascii_func(thd, a) {}
+  Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b)
+   :Item_str_ascii_func(thd, a, b) {}
+  Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b, Item *c)
+   :Item_str_ascii_func(thd, a, b, c) {}
+};
+
+
+/*
+  Functions returning binary string measurements of a single GEOMETRY argument
+*/
+class Item_binary_func_args_geometry: public Item_str_func
+{
+protected:
+  bool check_arguments() const
+  {
+    DBUG_ASSERT(arg_count >= 1);
+    return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+  }
+public:
+  Item_binary_func_args_geometry(THD *thd, Item *a)
+   :Item_str_func(thd, a) {}
+};
+
+
+/*
+  Functions returning GEOMETRY measurements of a single GEOEMETRY argument
+*/
+class Item_geometry_func_args_geometry: public Item_geometry_func
+{
+protected:
+  bool check_arguments() const
+  {
+    DBUG_ASSERT(arg_count >= 1);
+    return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+  }
+public:
+  Item_geometry_func_args_geometry(THD *thd, Item *a)
+   :Item_geometry_func(thd, a) {}
+  Item_geometry_func_args_geometry(THD *thd, Item *a, Item *b)
+   :Item_geometry_func(thd, a, b) {}
+};
+
+
+/*
+  Functions returning REAL result relationships between two GEOMETRY arguments
+*/
+class Item_real_func_args_geometry_geometry: public Item_real_func
+{
+protected:
+  bool check_arguments() const
+  {
+    DBUG_ASSERT(arg_count >= 2);
+    return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+  }
+public:
+  Item_real_func_args_geometry_geometry(THD *thd, Item *a, Item *b)
+   :Item_real_func(thd, a, b) {}
+};
+
+
+/*
+  Functions returning BOOL result relationships between two GEOMETRY arguments
+*/
+class Item_bool_func_args_geometry_geometry: public Item_bool_func
+{
+protected:
+  String value;
+  bool check_arguments() const
+  {
+    DBUG_ASSERT(arg_count >= 2);
+    return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+  }
+public:
+  Item_bool_func_args_geometry_geometry(THD *thd, Item *a, Item *b, Item *c)
+   :Item_bool_func(thd, a, b, c) {}
+};
+
+
 class Item_func_geometry_from_text: public Item_geometry_func
 {
+  bool check_arguments() const
+  {
+    return args[0]->check_type_general_purpose_string(func_name()) ||
+           check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
+  }
 public:
   Item_func_geometry_from_text(THD *thd, Item *a): Item_geometry_func(thd, a) {}
   Item_func_geometry_from_text(THD *thd, Item *a, Item *srid):
@@ -56,6 +208,11 @@ class Item_func_geometry_from_text: public Item_geometry_func
 
 class Item_func_geometry_from_wkb: public Item_geometry_func
 {
+  bool check_arguments() const
+  {
+    return args[0]->check_type_or_binary(func_name(), &type_handler_geometry) ||
+           check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
+  }
 public:
   Item_func_geometry_from_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
   Item_func_geometry_from_wkb(THD *thd, Item *a, Item *srid):
@@ -70,6 +227,12 @@ class Item_func_geometry_from_wkb: public Item_geometry_func
 class Item_func_geometry_from_json: public Item_geometry_func
 {
   String tmp_js;
+  bool check_arguments() const
+  {
+    // TODO: check with Alexey, for better args[1] and args[2] type control
+    return args[0]->check_type_general_purpose_string(func_name()) ||
+           check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count));
+  }
 public:
   Item_func_geometry_from_json(THD *thd, Item *js): Item_geometry_func(thd, js) {}
   Item_func_geometry_from_json(THD *thd, Item *js, Item *opt):
@@ -83,10 +246,11 @@ class Item_func_geometry_from_json: public Item_geometry_func
 };
 
 
-class Item_func_as_wkt: public Item_str_ascii_func
+class Item_func_as_wkt: public Item_str_ascii_func_args_geometry
 {
 public:
-  Item_func_as_wkt(THD *thd, Item *a): Item_str_ascii_func(thd, a) {}
+  Item_func_as_wkt(THD *thd, Item *a)
+   :Item_str_ascii_func_args_geometry(thd, a) {}
   const char *func_name() const { return "st_astext"; }
   String *val_str_ascii(String *);
   void fix_length_and_dec();
@@ -94,26 +258,41 @@ class Item_func_as_wkt: public Item_str_ascii_func
   { return get_item_copy<Item_func_as_wkt>(thd, mem_root, this); }
 };
 
-class Item_func_as_wkb: public Item_geometry_func
+class Item_func_as_wkb: public Item_binary_func_args_geometry
 {
 public:
-  Item_func_as_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+  Item_func_as_wkb(THD *thd, Item *a)
+   :Item_binary_func_args_geometry(thd, a) {}
   const char *func_name() const { return "st_aswkb"; }
   String *val_str(String *);
   const Type_handler *type_handler() const { return &type_handler_long_blob; }
+  void fix_length_and_dec()
+  {
+    collation.set(&my_charset_bin);
+    decimals=0;
+    max_length= (uint32) UINT_MAX32;
+    maybe_null= 1;
+  }
   Item *get_copy(THD *thd, MEM_ROOT *mem_root)
   { return get_item_copy<Item_func_as_wkb>(thd, mem_root, this); }
 };
 
 
-class Item_func_as_geojson: public Item_str_ascii_func
+class Item_func_as_geojson: public Item_str_ascii_func_args_geometry
 {
+  bool check_arguments() const
+  {
+    // TODO: check with Alexey, for better args[1] and args[2] type control
+    return Item_str_ascii_func_args_geometry::check_arguments() ||
+           check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count));
+  }
 public:
-  Item_func_as_geojson(THD *thd, Item *js): Item_str_ascii_func(thd, js) {}
-  Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits):
-    Item_str_ascii_func(thd, js, max_dec_digits) {}
-  Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt):
-    Item_str_ascii_func(thd, js, max_dec_digits, opt) {}
+  Item_func_as_geojson(THD *thd, Item *js)
+   :Item_str_ascii_func_args_geometry(thd, js) {}
+  Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits)
+   :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits) {}
+  Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt)
+   :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits, opt) {}
   const char *func_name() const { return "st_asgeojson"; }
   void fix_length_and_dec();
   String *val_str_ascii(String *);
@@ -122,10 +301,11 @@ class Item_func_as_geojson: public Item_str_ascii_func
 };
 
 
-class Item_func_geometry_type: public Item_str_ascii_func
+class Item_func_geometry_type: public Item_str_ascii_func_args_geometry
 {
 public:
-  Item_func_geometry_type(THD *thd, Item *a): Item_str_ascii_func(thd, a) {}
+  Item_func_geometry_type(THD *thd, Item *a)
+   :Item_str_ascii_func_args_geometry(thd, a) {}
   String *val_str_ascii(String *);
   const char *func_name() const { return "st_geometrytype"; }
   void fix_length_and_dec() 
@@ -140,7 +320,7 @@ class Item_func_geometry_type: public Item_str_ascii_func
 
 
 // #define HEAVY_CONVEX_HULL
-class Item_func_convexhull: public Item_geometry_func
+class Item_func_convexhull: public Item_geometry_func_args_geometry
 {
   class ch_node: public Gcalc_dyn_list::Item
   {
@@ -163,7 +343,8 @@ class Item_func_convexhull: public Item_geometry_func
   ch_node *new_ch_node() { return (ch_node *) res_heap.new_item(); }
   int add_node_to_line(ch_node **p_cur, int dir, const Gcalc_heap::Info *pi);
 public:
-  Item_func_convexhull(THD *thd, Item *a): Item_geometry_func(thd, a),
+  Item_func_convexhull(THD *thd, Item *a)
+   :Item_geometry_func_args_geometry(thd, a),
     res_heap(8192, sizeof(ch_node))
     {}
   const char *func_name() const { return "st_convexhull"; }
@@ -173,10 +354,11 @@ class Item_func_convexhull: public Item_geometry_func
 };
 
 
-class Item_func_centroid: public Item_geometry_func
+class Item_func_centroid: public Item_geometry_func_args_geometry
 {
 public:
-  Item_func_centroid(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+  Item_func_centroid(THD *thd, Item *a)
+   :Item_geometry_func_args_geometry(thd, a) {}
   const char *func_name() const { return "st_centroid"; }
   String *val_str(String *);
   Field::geometry_type get_geometry_type() const;
@@ -184,10 +366,11 @@ class Item_func_centroid: public Item_geometry_func
   { return get_item_copy<Item_func_centroid>(thd, mem_root, this); }
 };
 
-class Item_func_envelope: public Item_geometry_func
+class Item_func_envelope: public Item_geometry_func_args_geometry
 {
 public:
-  Item_func_envelope(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+  Item_func_envelope(THD *thd, Item *a)
+   :Item_geometry_func_args_geometry(thd, a) {}
   const char *func_name() const { return "st_envelope"; }
   String *val_str(String *);
   Field::geometry_type get_geometry_type() const;
@@ -196,7 +379,7 @@ class Item_func_envelope: public Item_geometry_func
 };
 
 
-class Item_func_boundary: public Item_geometry_func
+class Item_func_boundary: public Item_geometry_func_args_geometry
 {
   class Transporter : public Gcalc_shape_transporter
   {
@@ -221,7 +404,8 @@ class Item_func_boundary: public Item_geometry_func
   };
   Gcalc_result_receiver res_receiver;
 public:
-  Item_func_boundary(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+  Item_func_boundary(THD *thd, Item *a)
+   :Item_geometry_func_args_geometry(thd, a) {}
   const char *func_name() const { return "st_boundary"; }
   String *val_str(String *);
   Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -231,6 +415,8 @@ class Item_func_boundary: public Item_geometry_func
 
 class Item_func_point: public Item_geometry_func
 {
+  bool check_arguments() const
+  { return check_argument_types_can_return_real(0, 2); }
 public:
   Item_func_point(THD *thd, Item *a, Item *b): Item_geometry_func(thd, a, b) {}
   Item_func_point(THD *thd, Item *a, Item *b, Item *srid):
@@ -242,12 +428,12 @@ class Item_func_point: public Item_geometry_func
   { return get_item_copy<Item_func_point>(thd, mem_root, this); }
 };
 
-class Item_func_spatial_decomp: public Item_geometry_func
+class Item_func_spatial_decomp: public Item_geometry_func_args_geometry
 {
   enum Functype decomp_func;
 public:
   Item_func_spatial_decomp(THD *thd, Item *a, Item_func::Functype ft):
-    Item_geometry_func(thd, a) { decomp_func = ft; }
+    Item_geometry_func_args_geometry(thd, a) { decomp_func = ft; }
   const char *func_name() const 
   { 
     switch (decomp_func)
@@ -268,12 +454,19 @@ class Item_func_spatial_decomp: public Item_geometry_func
   { return get_item_copy<Item_func_spatial_decomp>(thd, mem_root, this); }
 };
 
-class Item_func_spatial_decomp_n: public Item_geometry_func
+class Item_func_spatial_decomp_n: public Item_geometry_func_args_geometry
 {
   enum Functype decomp_func_n;
+  bool check_arguments() const
+  {
+    return Item_geometry_func_args_geometry::check_arguments() ||
+           args[1]->check_type_can_return_int(func_name());
+  }
 public:
-  Item_func_spatial_decomp_n(THD *thd, Item *a, Item *b, Item_func::Functype ft):
-    Item_geometry_func(thd, a, b) { decomp_func_n = ft; }
+  Item_func_spatial_decomp_n(THD *thd, Item *a, Item *b, Item_func::Functype ft)
+   :Item_geometry_func_args_geometry(thd, a, b),
+    decomp_func_n(ft)
+  { }
   const char *func_name() const 
   { 
     switch (decomp_func_n)
@@ -296,6 +489,10 @@ class Item_func_spatial_decomp_n: public Item_geometry_func
 
 class Item_func_spatial_collection: public Item_geometry_func
 {
+  bool check_arguments() const
+  {
+    return check_argument_types_or_binary(&type_handler_geometry, 0, arg_count);
+  }
   String tmp_value;
   enum Geometry::wkbType coll_type; 
   enum Geometry::wkbType item_type;
@@ -342,6 +539,11 @@ class Item_func_spatial_rel: public Item_bool_func2_with_rev
   SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field,
                        KEY_PART *key_part,
                        Item_func::Functype type, Item *value);
+  bool check_arguments() const
+  {
+    DBUG_ASSERT(arg_count >= 2);
+    return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+  }
 public:
   Item_func_spatial_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
     Item_bool_func2_with_rev(thd, a, b), spatial_rel(sp_rel)
@@ -392,15 +594,20 @@ class Item_func_spatial_precise_rel: public Item_func_spatial_rel
 };
 
 
-class Item_func_spatial_relate: public Item_bool_func
+class Item_func_spatial_relate: public Item_bool_func_args_geometry_geometry
 {
   Gcalc_heap collector;
   Gcalc_scan_iterator scan_it;
   Gcalc_function func;
   String tmp_value1, tmp_value2, tmp_matrix;
+  bool check_arguments() const
+  {
+    return Item_bool_func_args_geometry_geometry::check_arguments() ||
+           args[2]->check_type_general_purpose_string(func_name());
+  }
 public:
   Item_func_spatial_relate(THD *thd, Item *a, Item *b, Item *matrix):
-    Item_bool_func(thd, a, b, matrix)
+    Item_bool_func_args_geometry_geometry(thd, a, b, matrix)
   { }
   longlong val_int();
   const char *func_name() const { return "st_relate"; }
@@ -416,6 +623,11 @@ class Item_func_spatial_relate: public Item_bool_func
 
 class Item_func_spatial_operation: public Item_geometry_func
 {
+  bool check_arguments() const
+  {
+    DBUG_ASSERT(arg_count >= 2);
+    return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+  }
 public:
   Gcalc_function::op_type spatial_op;
   Gcalc_heap collector;
@@ -441,8 +653,13 @@ class Item_func_spatial_operation: public Item_geometry_func
 };
 
 
-class Item_func_buffer: public Item_geometry_func
+class Item_func_buffer: public Item_geometry_func_args_geometry
 {
+  bool check_arguments() const
+  {
+    return Item_geometry_func_args_geometry::check_arguments() ||
+           args[1]->check_type_can_return_real(func_name());
+  }
 protected:
   class Transporter : public Gcalc_operation_transporter
   {
@@ -485,8 +702,8 @@ class Item_func_buffer: public Item_geometry_func
   String tmp_value;
 
 public:
-  Item_func_buffer(THD *thd, Item *obj, Item *distance):
-    Item_geometry_func(thd, obj, distance) {}
+  Item_func_buffer(THD *thd, Item *obj, Item *distance)
+   :Item_geometry_func_args_geometry(thd, obj, distance) {}
   const char *func_name() const { return "st_buffer"; }
   String *val_str(String *);
   Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -494,10 +711,11 @@ class Item_func_buffer: public Item_geometry_func
 };
 
 
-class Item_func_isempty: public Item_bool_func
+class Item_func_isempty: public Item_bool_func_args_geometry
 {
 public:
-  Item_func_isempty(THD *thd, Item *a): Item_bool_func(thd, a) {}
+  Item_func_isempty(THD *thd, Item *a)
+   :Item_bool_func_args_geometry(thd, a) {}
   longlong val_int();
   const char *func_name() const { return "st_isempty"; }
   void fix_length_and_dec() { maybe_null= 1; }
@@ -506,14 +724,15 @@ class Item_func_isempty: public Item_bool_func
   { return get_item_copy<Item_func_isempty>(thd, mem_root, this); }
 };
 
-class Item_func_issimple: public Item_long_func
+class Item_func_issimple: public Item_long_func_args_geometry
 {
   Gcalc_heap collector;
   Gcalc_function func;
   Gcalc_scan_iterator scan_it;
   String tmp;
 public:
-  Item_func_issimple(THD *thd, Item *a): Item_long_func(thd, a) {}
+  Item_func_issimple(THD *thd, Item *a)
+   :Item_long_func_args_geometry(thd, a) {}
   longlong val_int();
   const char *func_name() const { return "st_issimple"; }
   void fix_length_and_dec() { decimals=0; max_length=2; }
@@ -522,10 +741,11 @@ class Item_func_issimple: public Item_long_func
   { return get_item_copy<Item_func_issimple>(thd, mem_root, this); }
 };
 
-class Item_func_isclosed: public Item_long_func
+class Item_func_isclosed: public Item_long_func_args_geometry
 {
 public:
-  Item_func_isclosed(THD *thd, Item *a): Item_long_func(thd, a) {}
+  Item_func_isclosed(THD *thd, Item *a)
+   :Item_long_func_args_geometry(thd, a) {}
   longlong val_int();
   const char *func_name() const { return "st_isclosed"; }
   void fix_length_and_dec() { decimals=0; max_length=2; }
@@ -544,11 +764,11 @@ class Item_func_isring: public Item_func_issimple
   { return get_item_copy<Item_func_isring>(thd, mem_root, this); }
 };
 
-class Item_func_dimension: public Item_long_func
+class Item_func_dimension: public Item_long_func_args_geometry
 {
-  String value;
 public:
-  Item_func_dimension(THD *thd, Item *a): Item_long_func(thd, a) {}
+  Item_func_dimension(THD *thd, Item *a)
+   :Item_long_func_args_geometry(thd, a) {}
   longlong val_int();
   const char *func_name() const { return "st_dimension"; }
   void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -556,11 +776,11 @@ class Item_func_dimension: public Item_long_func
   { return get_item_copy<Item_func_dimension>(thd, mem_root, this); }
 };
 
-class Item_func_x: public Item_real_func
+
+class Item_func_x: public Item_real_func_args_geometry
 {
-  String value;
 public:
-  Item_func_x(THD *thd, Item *a): Item_real_func(thd, a) {}
+  Item_func_x(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
   double val_real();
   const char *func_name() const { return "st_x"; }
   void fix_length_and_dec() 
@@ -573,11 +793,10 @@ class Item_func_x: public Item_real_func
 };
 
 
-class Item_func_y: public Item_real_func
+class Item_func_y: public Item_real_func_args_geometry
 {
-  String value;
 public:
-  Item_func_y(THD *thd, Item *a): Item_real_func(thd, a) {}
+  Item_func_y(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
   double val_real();
   const char *func_name() const { return "st_y"; }
   void fix_length_and_dec() 
@@ -590,11 +809,11 @@ class Item_func_y: public Item_real_func
 };
 
 
-class Item_func_numgeometries: public Item_long_func
+class Item_func_numgeometries: public Item_long_func_args_geometry
 {
-  String value;
 public:
-  Item_func_numgeometries(THD *thd, Item *a): Item_long_func(thd, a) {}
+  Item_func_numgeometries(THD *thd, Item *a)
+   :Item_long_func_args_geometry(thd, a) {}
   longlong val_int();
   const char *func_name() const { return "st_numgeometries"; }
   void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -603,11 +822,11 @@ class Item_func_numgeometries: public Item_long_func
 };
 
 
-class Item_func_numinteriorring: public Item_long_func
+class Item_func_numinteriorring: public Item_long_func_args_geometry
 {
-  String value;
 public:
-  Item_func_numinteriorring(THD *thd, Item *a): Item_long_func(thd, a) {}
+  Item_func_numinteriorring(THD *thd, Item *a)
+   :Item_long_func_args_geometry(thd, a) {}
   longlong val_int();
   const char *func_name() const { return "st_numinteriorrings"; }
   void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -616,11 +835,11 @@ class Item_func_numinteriorring: public Item_long_func
 };
 
 
-class Item_func_numpoints: public Item_long_func
+class Item_func_numpoints: public Item_long_func_args_geometry
 {
-  String value;
 public:
-  Item_func_numpoints(THD *thd, Item *a): Item_long_func(thd, a) {}
+  Item_func_numpoints(THD *thd, Item *a)
+   :Item_long_func_args_geometry(thd, a) {}
   longlong val_int();
   const char *func_name() const { return "st_numpoints"; }
   void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -629,11 +848,10 @@ class Item_func_numpoints: public Item_long_func
 };
 
 
-class Item_func_area: public Item_real_func
+class Item_func_area: public Item_real_func_args_geometry
 {
-  String value;
 public:
-  Item_func_area(THD *thd, Item *a): Item_real_func(thd, a) {}
+  Item_func_area(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
   double val_real();
   const char *func_name() const { return "st_area"; }
   void fix_length_and_dec() 
@@ -646,11 +864,12 @@ class Item_func_area: public Item_real_func
 };
 
 
-class Item_func_glength: public Item_real_func
+class Item_func_glength: public Item_real_func_args_geometry
 {
   String value;
 public:
-  Item_func_glength(THD *thd, Item *a): Item_real_func(thd, a) {}
+  Item_func_glength(THD *thd, Item *a)
+   :Item_real_func_args_geometry(thd, a) {}
   double val_real();
   const char *func_name() const { return "st_length"; }
   void fix_length_and_dec() 
@@ -663,11 +882,11 @@ class Item_func_glength: public Item_real_func
 };
 
 
-class Item_func_srid: public Item_long_func
+class Item_func_srid: public Item_long_func_args_geometry
 {
-  String value;
 public:
-  Item_func_srid(THD *thd, Item *a): Item_long_func(thd, a) {}
+  Item_func_srid(THD *thd, Item *a)
+   :Item_long_func_args_geometry(thd, a) {}
   longlong val_int();
   const char *func_name() const { return "srid"; }
   void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -676,7 +895,7 @@ class Item_func_srid: public Item_long_func
 };
 
 
-class Item_func_distance: public Item_real_func
+class Item_func_distance: public Item_real_func_args_geometry_geometry
 {
   String tmp_value1;
   String tmp_value2;
@@ -684,7 +903,8 @@ class Item_func_distance: public Item_real_func
   Gcalc_function func;
   Gcalc_scan_iterator scan_it;
 public:
-  Item_func_distance(THD *thd, Item *a, Item *b): Item_real_func(thd, a, b) {}
+  Item_func_distance(THD *thd, Item *a, Item *b)
+   :Item_real_func_args_geometry_geometry(thd, a, b) {}
   double val_real();
   const char *func_name() const { return "st_distance"; }
   Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -692,14 +912,15 @@ class Item_func_distance: public Item_real_func
 };
 
 
-class Item_func_pointonsurface: public Item_geometry_func
+class Item_func_pointonsurface: public Item_geometry_func_args_geometry
 {
   String tmp_value;
   Gcalc_heap collector;
   Gcalc_function func;
   Gcalc_scan_iterator scan_it;
 public:
-  Item_func_pointonsurface(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+  Item_func_pointonsurface(THD *thd, Item *a)
+   :Item_geometry_func_args_geometry(thd, a) {}
   const char *func_name() const { return "st_pointonsurface"; }
   String *val_str(String *);
   Field::geometry_type get_geometry_type() const;
diff --git a/sql/sql_type.h b/sql/sql_type.h
index c377f26..48b0699 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -658,6 +658,10 @@ class Type_handler
   {
     return true;
   }
+  virtual bool is_scalar_type() const { return true; }
+  virtual bool can_return_int() const { return true; }
+  virtual bool can_return_real() const { return true; }
+  virtual bool is_general_purpose_string_type() const { return false; }
   virtual uint Item_time_precision(Item *item) const;
   virtual uint Item_datetime_precision(Item *item) const;
   virtual uint Item_decimal_scale(const Item *item) const;
@@ -944,6 +948,9 @@ class Type_handler_row: public Type_handler
 public:
   virtual ~Type_handler_row() {}
   const Name name() const { return m_name_row; }
+  bool is_scalar_type() const { return false; }
+  bool can_return_int() const { return false; }
+  bool can_return_real() const { return false; }
   enum_field_types field_type() const
   {
     DBUG_ASSERT(0);
@@ -1660,6 +1667,13 @@ class Type_handler_string_result: public Type_handler
 };
 
 
+class Type_handler_general_purpose_string: public Type_handler_string_result
+{
+public:
+  bool is_general_purpose_string_type() const { return true; }
+};
+
+
 /***
   Instantiable classes for every MYSQL_TYPE_XXX
 
@@ -2312,7 +2326,7 @@ class Type_handler_newdecimal: public Type_handler_decimal_result
 };
 
 
-class Type_handler_null: public Type_handler_string_result
+class Type_handler_null: public Type_handler_general_purpose_string
 {
   static const Name m_name_null;
 public:
@@ -2350,7 +2364,7 @@ class Type_handler_null: public Type_handler_string_result
 };
 
 
-class Type_handler_longstr: public Type_handler_string_result
+class Type_handler_longstr: public Type_handler_general_purpose_string
 {
 public:
   bool type_can_have_key_part() const
@@ -2582,6 +2596,8 @@ class Type_handler_geometry: public Type_handler_string_result
                           const Type_all_attributes &attr,
                           TABLE *table) const;
 
+  bool can_return_int() const { return false; }
+  bool can_return_real() const { return false; }
   bool is_traditional_type() const
   {
     return false;
@@ -2613,7 +2629,7 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_geometry type_handler_geometry;
 #endif
 
 
-class Type_handler_typelib: public Type_handler_string_result
+class Type_handler_typelib: public Type_handler_general_purpose_string
 {
 public:
   virtual ~Type_handler_typelib() { }

References