Below is the list of changes that have just been committed into a local
4.1 repository of ram. When ram does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-02-21 14:45:19+04:00, ramil@stripped +6 -0
Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL
Having maybe_null flag unset for geometry/spatial functions leads to
wrong Item_func_isnull::val_int()'s results.
Fix: set maybe_null flag and add is_null() methods.
mysql-test/r/gis.result@stripped, 2007-02-21 14:45:18+04:00, ramil@stripped +43 -1
Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL
- test result.
mysql-test/t/gis.test@stripped, 2007-02-21 14:45:18+04:00, ramil@stripped +35 -1
Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL
- test case.
sql/item_geofunc.cc@stripped, 2007-02-21 14:45:18+04:00, ramil@stripped +17 -12
Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL
- set maybe_null flag for Item_geometry_func and Item_func_as_wkt.
- moved length check to the beginnig of the
Item_func_spatial_collection::val_str() to affect geometry
collection objects at once.
- changed Item_func_isempty::val_int() and Item_func_issimple::val_int()
to properly handle null_value.
sql/item_geofunc.h@stripped, 2007-02-21 14:45:18+04:00, ramil@stripped +32 -5
Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL
- set maybe_null flag for geometry/spatial functions.
- added is_null() to Item_geometry_func and Item_func_spatial_rel
classes.
sql/spatial.cc@stripped, 2007-02-21 14:45:18+04:00, ramil@stripped +7 -6
Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL
- changed return type of Geometry::create_from_wkb() to be
consistent with Geometry::create_from_wkt(), now it returns
Geometry object or NULL in case of error.
sql/spatial.h@stripped, 2007-02-21 14:45:18+04:00, ramil@stripped +2 -2
Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL
- changed return type of Geometry::create_from_wkb() to be
consistent with Geometry::create_from_wkt(), now it returns
Geometry object or NULL in case of error.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: ramil
# Host: ramil.myoffice.izhnet.ru
# Root: /home/ram/work/b26038/b26038.4.1
--- 1.23/sql/spatial.cc 2007-02-21 14:45:22 +04:00
+++ 1.24/sql/spatial.cc 2007-02-21 14:45:22 +04:00
@@ -210,23 +210,24 @@ static uint32 wkb_get_uint(const char *p
}
-int Geometry::create_from_wkb(Geometry_buffer *buffer,
- const char *wkb, uint32 len, String *res)
+Geometry *Geometry::create_from_wkb(Geometry_buffer *buffer,
+ const char *wkb, uint32 len, String *res)
{
uint32 geom_type;
Geometry *geom;
if (len < WKB_HEADER_SIZE)
- return 1;
+ return NULL;
geom_type= wkb_get_uint(wkb+1, (wkbByteOrder)wkb[0]);
if (!(geom= create_by_typeid(buffer, (int) geom_type)) ||
res->reserve(WKB_HEADER_SIZE, 512))
- return 1;
+ return NULL;
res->q_append((char) wkb_ndr);
res->q_append(geom_type);
- return geom->init_from_wkb(wkb+WKB_HEADER_SIZE, len - WKB_HEADER_SIZE,
- (wkbByteOrder) wkb[0], res);
+
+ return geom->init_from_wkb(wkb + WKB_HEADER_SIZE, len - WKB_HEADER_SIZE,
+ (wkbByteOrder) wkb[0], res) ? geom : NULL;
}
--- 1.16/sql/spatial.h 2007-02-21 14:45:22 +04:00
+++ 1.17/sql/spatial.h 2007-02-21 14:45:22 +04:00
@@ -244,8 +244,8 @@ public:
static Geometry *create_from_wkt(Geometry_buffer *buffer,
Gis_read_stream *trs, String *wkt,
bool init_stream=1);
- static int create_from_wkb(Geometry_buffer *buffer,
- const char *wkb, uint32 len, String *res);
+ static Geometry *create_from_wkb(Geometry_buffer *buffer, const char *wkb,
+ uint32 len, String *res);
int as_wkt(String *wkt, const char **end)
{
uint32 len= get_class_info()->m_name.length;
--- 1.23/mysql-test/r/gis.result 2007-02-21 14:45:22 +04:00
+++ 1.24/mysql-test/r/gis.result 2007-02-21 14:45:22 +04:00
@@ -578,7 +578,7 @@ create table t1 select POINT(1,3);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `POINT(1,3)` longblob NOT NULL
+ `POINT(1,3)` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
CREATE TABLE `t1` (`object_id` bigint(20) unsigned NOT NULL default '0', `geo`
@@ -677,3 +677,45 @@ load data infile '../../std_data/bad_gis
ERROR 01000: Data truncated; NULL supplied to NOT NULL column 'b' at row 1
alter table t1 enable keys;
drop table t1;
+create table t1 (a int, b blob);
+insert into t1 values (1, ''), (2, NULL), (3, '1');
+select * from t1;
+a b
+1
+2 NULL
+3 1
+select
+geometryfromtext(b) IS NULL, geometryfromwkb(b) IS NULL, astext(b) IS NULL,
+aswkb(b) IS NULL, geometrytype(b) IS NULL, centroid(b) IS NULL,
+envelope(b) IS NULL, startpoint(b) IS NULL, endpoint(b) IS NULL,
+exteriorring(b) IS NULL, pointn(b, 1) IS NULL, geometryn(b, 1) IS NULL,
+interiorringn(b, 1) IS NULL, multipoint(b) IS NULL, isempty(b) IS NULL,
+issimple(b) IS NULL, isclosed(b) IS NULL, dimension(b) IS NULL,
+numgeometries(b) IS NULL, numinteriorrings(b) IS NULL, numpoints(b) IS NULL,
+area(b) IS NULL, glength(b) IS NULL, srid(b) IS NULL, x(b) IS NULL,
+y(b) IS NULL
+from t1;
+geometryfromtext(b) IS NULL geometryfromwkb(b) IS NULL astext(b) IS NULL aswkb(b) IS
NULL geometrytype(b) IS NULL centroid(b) IS NULL envelope(b) IS NULL startpoint(b) IS
NULL endpoint(b) IS NULL exteriorring(b) IS NULL pointn(b, 1) IS NULL geometryn(b, 1) IS
NULL interiorringn(b, 1) IS NULL multipoint(b) IS NULL isempty(b) IS NULL issimple(b) IS
NULL isclosed(b) IS NULL dimension(b) IS NULL numgeometries(b) IS
NULL numinteriorrings(b) IS NULL numpoints(b) IS NULL area(b) IS NULL glength(b) IS
NULL srid(b) IS NULL x(b) IS NULL y(b) IS NULL
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+select
+within(b, b) IS NULL, contains(b, b) IS NULL, overlaps(b, b) IS NULL,
+equals(b, b) IS NULL, disjoint(b, b) IS NULL, touches(b, b) IS NULL,
+intersects(b, b) IS NULL, crosses(b, b) IS NULL
+from t1;
+within(b, b) IS NULL contains(b, b) IS NULL overlaps(b, b) IS NULL equals(b, b) IS
NULL disjoint(b, b) IS NULL touches(b, b) IS NULL intersects(b, b) IS NULL crosses(b, b)
IS NULL
+1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1
+1 1 1 1 1 1 1 1
+select
+point(b, b) IS NULL, linestring(b) IS NULL, polygon(b) IS NULL, multipoint(b) IS NULL,
+multilinestring(b) IS NULL, multipolygon(b) IS NULL,
+geometrycollection(b) IS NULL
+from t1;
+point(b, b) IS NULL linestring(b) IS NULL polygon(b) IS NULL multipoint(b) IS
NULL multilinestring(b) IS NULL multipolygon(b) IS NULL geometrycollection(b) IS NULL
+0 1 1 1 1 1 1
+1 1 1 1 1 1 1
+0 1 1 1 1 1 1
+drop table t1;
+End of 4.1 tests
--- 1.21/mysql-test/t/gis.test 2007-02-21 14:45:22 +04:00
+++ 1.22/mysql-test/t/gis.test 2007-02-21 14:45:22 +04:00
@@ -377,4 +377,38 @@ load data infile '../../std_data/bad_gis
alter table t1 enable keys;
drop table t1;
-# End of 4.1 tests
+#
+# Bug #26038: is null and bad data
+#
+
+create table t1 (a int, b blob);
+insert into t1 values (1, ''), (2, NULL), (3, '1');
+select * from t1;
+
+select
+ geometryfromtext(b) IS NULL, geometryfromwkb(b) IS NULL, astext(b) IS NULL,
+ aswkb(b) IS NULL, geometrytype(b) IS NULL, centroid(b) IS NULL,
+ envelope(b) IS NULL, startpoint(b) IS NULL, endpoint(b) IS NULL,
+ exteriorring(b) IS NULL, pointn(b, 1) IS NULL, geometryn(b, 1) IS NULL,
+ interiorringn(b, 1) IS NULL, multipoint(b) IS NULL, isempty(b) IS NULL,
+ issimple(b) IS NULL, isclosed(b) IS NULL, dimension(b) IS NULL,
+ numgeometries(b) IS NULL, numinteriorrings(b) IS NULL, numpoints(b) IS NULL,
+ area(b) IS NULL, glength(b) IS NULL, srid(b) IS NULL, x(b) IS NULL,
+ y(b) IS NULL
+from t1;
+
+select
+ within(b, b) IS NULL, contains(b, b) IS NULL, overlaps(b, b) IS NULL,
+ equals(b, b) IS NULL, disjoint(b, b) IS NULL, touches(b, b) IS NULL,
+ intersects(b, b) IS NULL, crosses(b, b) IS NULL
+from t1;
+
+select
+ point(b, b) IS NULL, linestring(b) IS NULL, polygon(b) IS NULL, multipoint(b) IS NULL,
+ multilinestring(b) IS NULL, multipolygon(b) IS NULL,
+ geometrycollection(b) IS NULL
+from t1;
+
+drop table t1;
+
+--echo End of 4.1 tests
--- 1.24/sql/item_geofunc.cc 2007-02-21 14:45:22 +04:00
+++ 1.25/sql/item_geofunc.cc 2007-02-21 14:45:22 +04:00
@@ -30,6 +30,7 @@ void Item_geometry_func::fix_length_and_
collation.set(&my_charset_bin);
decimals=0;
max_length=MAX_BLOB_WIDTH;
+ maybe_null= 1;
}
@@ -109,6 +110,7 @@ String *Item_func_as_wkt::val_str(String
void Item_func_as_wkt::fix_length_and_dec()
{
max_length=MAX_BLOB_WIDTH;
+ maybe_null= 1;
}
@@ -356,7 +358,8 @@ String *Item_func_spatial_collection::va
for (i= 0; i < arg_count; ++i)
{
String *res= args[i]->val_str(&arg_value);
- if (args[i]->null_value)
+ uint32 len;
+ if (args[i]->null_value || ((len= res->length()) < WKB_HEADER_SIZE))
goto err;
if (coll_type == Geometry::wkb_geometrycollection)
@@ -365,13 +368,12 @@ String *Item_func_spatial_collection::va
In the case of GeometryCollection we don't need any checkings
for item types, so just copy them into target collection
*/
- if (str->append(res->ptr(), res->length(), (uint32) 512))
+ if (str->append(res->ptr(), len, (uint32) 512))
goto err;
}
else
{
enum Geometry::wkbType wkb_type;
- uint32 len=res->length();
const char *data= res->ptr() + 1;
/*
@@ -379,8 +381,6 @@ String *Item_func_spatial_collection::va
are of specific type, let's do this checking now
*/
- if (len < 5)
- goto err;
wkb_type= (Geometry::wkbType) uint4korr(data);
data+= 4;
len-= 5;
@@ -502,9 +502,13 @@ longlong Item_func_spatial_rel::val_int(
longlong Item_func_isempty::val_int()
{
DBUG_ASSERT(fixed == 1);
- String tmp;
- null_value=0;
- return args[0]->null_value ? 1 : 0;
+ String tmp;
+ String *swkb= args[0]->val_str(&tmp);
+ Geometry_buffer buffer;
+
+ null_value= args[0]->null_value ||
+ !(Geometry::construct(&buffer, swkb->ptr(), swkb->length()));
+ return null_value ? 1 : 0;
}
@@ -512,10 +516,11 @@ longlong Item_func_issimple::val_int()
{
DBUG_ASSERT(fixed == 1);
String tmp;
- String *wkb=args[0]->val_str(&tmp);
-
- if ((null_value= (!wkb || args[0]->null_value)))
- return 0;
+ String *swkb= args[0]->val_str(&tmp);
+ Geometry_buffer buffer;
+
+ null_value= args[0]->null_value ||
+ !(Geometry::construct(&buffer, swkb->ptr(), swkb->length()));
/* TODO: Ramil or Holyfoot, add real IsSimple calculation */
return 0;
}
--- 1.10/sql/item_geofunc.h 2007-02-21 14:45:22 +04:00
+++ 1.11/sql/item_geofunc.h 2007-02-21 14:45:22 +04:00
@@ -33,6 +33,7 @@ public:
Item_geometry_func(List<Item> &list) :Item_str_func(list) {}
void fix_length_and_dec();
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
+ bool is_null() { (void) val_int(); return null_value; }
};
class Item_func_geometry_from_text: public Item_geometry_func
@@ -80,6 +81,7 @@ public:
void fix_length_and_dec()
{
max_length=20; // "GeometryCollection" is the most long
+ maybe_null= 1;
};
};
@@ -221,6 +223,8 @@ public:
}
}
void print(String *str) { Item_func::print(str); }
+ void fix_length_and_dec() { maybe_null= 1; }
+ bool is_null() { (void) val_int(); return null_value; }
};
class Item_func_isempty: public Item_bool_func
@@ -230,6 +234,7 @@ public:
longlong val_int();
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
const char *func_name() const { return "isempty"; }
+ void fix_length_and_dec() { maybe_null= 1; }
};
class Item_func_issimple: public Item_bool_func
@@ -239,6 +244,7 @@ public:
longlong val_int();
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
const char *func_name() const { return "issimple"; }
+ void fix_length_and_dec() { maybe_null= 1; }
};
class Item_func_isclosed: public Item_bool_func
@@ -248,6 +254,7 @@ public:
longlong val_int();
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
const char *func_name() const { return "isclosed"; }
+ void fix_length_and_dec() { maybe_null= 1; }
};
class Item_func_dimension: public Item_int_func
@@ -257,7 +264,7 @@ public:
Item_func_dimension(Item *a): Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "dimension"; }
- void fix_length_and_dec() { max_length=10; }
+ void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
};
class Item_func_x: public Item_real_func
@@ -267,6 +274,11 @@ public:
Item_func_x(Item *a): Item_real_func(a) {}
double val();
const char *func_name() const { return "x"; }
+ void fix_length_and_dec()
+ {
+ Item_real_func::fix_length_and_dec();
+ maybe_null= 1;
+ }
};
@@ -277,6 +289,11 @@ public:
Item_func_y(Item *a): Item_real_func(a) {}
double val();
const char *func_name() const { return "y"; }
+ void fix_length_and_dec()
+ {
+ Item_real_func::fix_length_and_dec();
+ maybe_null= 1;
+ }
};
@@ -287,7 +304,7 @@ public:
Item_func_numgeometries(Item *a): Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "numgeometries"; }
- void fix_length_and_dec() { max_length=10; }
+ void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
};
@@ -298,7 +315,7 @@ public:
Item_func_numinteriorring(Item *a): Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "numinteriorrings"; }
- void fix_length_and_dec() { max_length=10; }
+ void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
};
@@ -309,7 +326,7 @@ public:
Item_func_numpoints(Item *a): Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "numpoints"; }
- void fix_length_and_dec() { max_length=10; }
+ void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
};
@@ -320,6 +337,11 @@ public:
Item_func_area(Item *a): Item_real_func(a) {}
double val();
const char *func_name() const { return "area"; }
+ void fix_length_and_dec()
+ {
+ Item_real_func::fix_length_and_dec();
+ maybe_null= 1;
+ }
};
@@ -330,6 +352,11 @@ public:
Item_func_glength(Item *a): Item_real_func(a) {}
double val();
const char *func_name() const { return "glength"; }
+ void fix_length_and_dec()
+ {
+ Item_real_func::fix_length_and_dec();
+ maybe_null= 1;
+ }
};
@@ -340,7 +367,7 @@ public:
Item_func_srid(Item *a): Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "srid"; }
- void fix_length_and_dec() { max_length= 10; }
+ void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
};
#define GEOM_NEW(obj_constructor) new obj_constructor
| Thread |
|---|
| • bk commit into 4.1 tree (ramil:1.2609) BUG#26038 | ramil | 21 Feb |