summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2003-05-30 21:09:36 +0300
committerunknown <bell@sanja.is.com.ua>2003-05-30 21:09:36 +0300
commit82fd4268a0acec88ad3b7fab9925672e5b3f3739 (patch)
treebebfc06778e247bc753786f26c89b3ced61d8310 /sql
parent4ecdc7a4161d9d275da3ddc24c8c5ced6ad268f9 (diff)
parent487a64963b2382fdf816770402fb05d0c681aa23 (diff)
downloadmariadb-git-82fd4268a0acec88ad3b7fab9925672e5b3f3739.tar.gz
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-4.1
into sanja.is.com.ua:/home/bell/mysql/bk/work-mem_root-4.1
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am4
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_cmpfunc.cc82
-rw-r--r--sql/item_cmpfunc.h76
-rw-r--r--sql/item_create.cc4
-rw-r--r--sql/item_func.cc136
-rw-r--r--sql/item_func.h95
-rw-r--r--sql/item_geofunc.cc653
-rw-r--r--sql/item_geofunc.h360
-rw-r--r--sql/item_strfunc.cc422
-rw-r--r--sql/item_strfunc.h239
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/mysqld.cc22
-rw-r--r--sql/protocol.cc2
-rw-r--r--sql/protocol.h2
-rw-r--r--sql/set_var.cc138
-rw-r--r--sql/set_var.h42
-rw-r--r--sql/sql_base.cc4
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_db.cc44
-rw-r--r--sql/sql_help.cc782
-rw-r--r--sql/sql_load.cc2
-rw-r--r--sql/sql_parse.cc13
-rw-r--r--sql/sql_table.cc3
-rw-r--r--sql/sql_yacc.yy8
-rw-r--r--sql/table.cc27
-rw-r--r--sql/udf_example.cc4
28 files changed, 1772 insertions, 1398 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 608b959a8b9..6e7f2f08a1d 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -46,7 +46,7 @@ mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \
noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
item_strfunc.h item_timefunc.h item_uniq.h \
item_create.h item_subselect.h item_row.h \
- mysql_priv.h \
+ mysql_priv.h item_geofunc.h \
procedure.h sql_class.h sql_lex.h sql_list.h \
sql_manager.h sql_map.h sql_string.h unireg.h \
field.h handler.h \
@@ -62,7 +62,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
thr_malloc.cc item_create.cc item_subselect.cc \
- item_row.cc \
+ item_row.cc item_geofunc.cc \
field.cc key.cc sql_class.cc sql_list.cc \
net_serv.cc protocol.cc lock.cc my_lock.c \
sql_string.cc sql_manager.cc sql_map.cc \
diff --git a/sql/item.h b/sql/item.h
index 470937f8ee7..2d285bbe434 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -644,6 +644,7 @@ public:
#include "item_row.h"
#include "item_cmpfunc.h"
#include "item_strfunc.h"
+#include "item_geofunc.h"
#include "item_timefunc.h"
#include "item_uniq.h"
#include "item_subselect.h"
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 4f55357f288..299014689f0 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -2363,85 +2363,3 @@ longlong Item_cond_xor::val_int()
}
return (longlong) result;
}
-
-/****************************************************************
- Classes and functions for spatial relations
-*****************************************************************/
-
-longlong Item_func_spatial_rel::val_int()
-{
- String *res1= args[0]->val_str(&tmp_value1);
- String *res2= args[1]->val_str(&tmp_value2);
- Geometry g1, g2;
- MBR mbr1, mbr2;
-
- if ((null_value= (args[0]->null_value ||
- args[1]->null_value ||
- g1.create_from_wkb(res1->ptr() + SRID_SIZE,
- res1->length() - SRID_SIZE) ||
- g2.create_from_wkb(res2->ptr() + SRID_SIZE,
- res2->length() - SRID_SIZE) ||
- g1.get_mbr(&mbr1) ||
- g2.get_mbr(&mbr2))))
- return 0;
-
- switch (spatial_rel)
- {
- case SP_CONTAINS_FUNC:
- return mbr1.contains(&mbr2);
- case SP_WITHIN_FUNC:
- return mbr1.within(&mbr2);
- case SP_EQUALS_FUNC:
- return mbr1.equals(&mbr2);
- case SP_DISJOINT_FUNC:
- return mbr1.disjoint(&mbr2);
- case SP_INTERSECTS_FUNC:
- return mbr1.intersects(&mbr2);
- case SP_TOUCHES_FUNC:
- return mbr1.touches(&mbr2);
- case SP_OVERLAPS_FUNC:
- return mbr1.overlaps(&mbr2);
- case SP_CROSSES_FUNC:
- return 0;
- default:
- break;
- }
-
- null_value=1;
- return 0;
-}
-
-longlong Item_func_isempty::val_int()
-{
- String tmp;
- null_value=0;
- return args[0]->null_value ? 1 : 0;
-}
-
-longlong Item_func_issimple::val_int()
-{
- String tmp;
- String *wkb=args[0]->val_str(&tmp);
-
- if ((null_value= (!wkb || args[0]->null_value )))
- return 0;
- /* TODO: Ramil or Holyfoot, add real IsSimple calculation */
- return 0;
-}
-
-longlong Item_func_isclosed::val_int()
-{
- String tmp;
- String *swkb= args[0]->val_str(&tmp);
- Geometry geom;
- int isclosed;
-
- null_value= (!swkb ||
- args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom,is_closed) ||
- geom.is_closed(&isclosed));
-
- return (longlong) isclosed;
-}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index ff469deab30..4438b902011 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -850,79 +850,3 @@ inline Item *and_conds(Item *a,Item *b)
}
Item *and_expressions(Item *a, Item *b, Item **org_item);
-
-/**************************************************************
- Spatial relations
-***************************************************************/
-
-class Item_func_spatial_rel :public Item_bool_func2
-{
- enum Functype spatial_rel;
-public:
- Item_func_spatial_rel(Item *a,Item *b, enum Functype sp_rel) :
- Item_bool_func2(a,b) { spatial_rel = sp_rel; }
- longlong val_int();
- enum Functype functype() const
- {
- switch (spatial_rel) {
- case SP_CONTAINS_FUNC:
- return SP_WITHIN_FUNC;
- case SP_WITHIN_FUNC:
- return SP_CONTAINS_FUNC;
- default:
- return spatial_rel;
- }
- }
- enum Functype rev_functype() const { return spatial_rel; }
- const char *func_name() const
- {
- switch (spatial_rel) {
- case SP_CONTAINS_FUNC:
- return "contains";
- case SP_WITHIN_FUNC:
- return "within";
- case SP_EQUALS_FUNC:
- return "equals";
- case SP_DISJOINT_FUNC:
- return "disjoint";
- case SP_INTERSECTS_FUNC:
- return "intersects";
- case SP_TOUCHES_FUNC:
- return "touches";
- case SP_CROSSES_FUNC:
- return "crosses";
- case SP_OVERLAPS_FUNC:
- return "overlaps";
- default:
- return "sp_unknown";
- }
- }
-};
-
-
-class Item_func_isempty :public Item_bool_func
-{
-public:
- Item_func_isempty(Item *a) :Item_bool_func(a) {}
- longlong val_int();
- optimize_type select_optimize() const { return OPTIMIZE_NONE; }
- const char *func_name() const { return "isempty"; }
-};
-
-class Item_func_issimple :public Item_bool_func
-{
-public:
- Item_func_issimple(Item *a) :Item_bool_func(a) {}
- longlong val_int();
- optimize_type select_optimize() const { return OPTIMIZE_NONE; }
- const char *func_name() const { return "issimple"; }
-};
-
-class Item_func_isclosed :public Item_bool_func
-{
-public:
- Item_func_isclosed(Item *a) :Item_bool_func(a) {}
- longlong val_int();
- optimize_type select_optimize() const { return OPTIMIZE_NONE; }
- const char *func_name() const { return "isclosed"; }
-};
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 723610c0df4..3edec7fdab0 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -464,8 +464,8 @@ Item *create_func_cast(Item *a, Item_cast cast_type, CHARSET_INFO *cs)
switch (cast_type) {
case ITEM_CAST_BINARY: res= new Item_func_binary(a); break;
case ITEM_CAST_CHAR:
- res= (cs == NULL) ? new Item_char_typecast(a) :
- new Item_func_conv_charset(a,cs);
+ res= (cs == NULL) ? (Item*) new Item_char_typecast(a) :
+ (Item*) new Item_func_conv_charset(a,cs);
break;
case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break;
case ITEM_CAST_UNSIGNED_INT: res= new Item_func_unsigned(a); break;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 7ed9e5c85f6..6482d81f484 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2680,139 +2680,3 @@ longlong Item_func_is_used_lock::val_int()
null_value=0;
return ull->thread_id;
}
-
-
-
-/**************************************************************************
- Spatial functions
-***************************************************************************/
-
-longlong Item_func_dimension::val_int()
-{
- uint32 dim;
- String *swkb= args[0]->val_str(&value);
- Geometry geom;
-
- null_value= (!swkb ||
- args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- geom.dimension(&dim));
- return (longlong) dim;
-}
-
-longlong Item_func_numinteriorring::val_int()
-{
- uint32 num;
- String *swkb= args[0]->val_str(&value);
- Geometry geom;
-
- null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, num_interior_ring) ||
- geom.num_interior_ring(&num));
- return (longlong) num;
-}
-
-longlong Item_func_numgeometries::val_int()
-{
- uint32 num= 0;
- String *swkb= args[0]->val_str(&value);
- Geometry geom;
-
- null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, num_geometries) ||
- geom.num_geometries(&num));
- return (longlong) num;
-}
-
-longlong Item_func_numpoints::val_int()
-{
- uint32 num;
- String *swkb= args[0]->val_str(&value);
- Geometry geom;
-
- null_value= (!swkb ||
- args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, num_points) ||
- geom.num_points(&num));
- return (longlong) num;
-}
-
-
-double Item_func_x::val()
-{
- double res;
- String *swkb= args[0]->val_str(&value);
- Geometry geom;
-
- null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, get_x) ||
- geom.get_x(&res));
- return res;
-}
-
-
-double Item_func_y::val()
-{
- double res;
- String *swkb= args[0]->val_str(&value);
- Geometry geom;
-
- null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, get_y) ||
- geom.get_y(&res));
- return res;
-}
-
-
-double Item_func_area::val()
-{
- double res;
- String *swkb= args[0]->val_str(&value);
- Geometry geom;
-
- null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, area) ||
- geom.area(&res));
- return res;
-}
-
-
-double Item_func_glength::val()
-{
- double res;
- String *swkb= args[0]->val_str(&value);
- Geometry geom;
-
- null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, length) ||
- geom.length(&res));
- return res;
-}
-
-
-longlong Item_func_srid::val_int()
-{
- String *swkb= args[0]->val_str(&value);
- Geometry geom;
-
- null_value= (!swkb ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE));
- uint32 res= uint4korr(swkb->ptr());
- return (longlong) res;
-}
diff --git a/sql/item_func.h b/sql/item_func.h
index e1d6156c12c..8ef2b85de52 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1037,101 +1037,6 @@ public:
};
-class Item_func_dimension :public Item_int_func
-{
- String value;
-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; }
-};
-
-
-class Item_func_x :public Item_real_func
-{
- String value;
-public:
- Item_func_x(Item *a) :Item_real_func(a) {}
- double val();
- const char *func_name() const { return "x"; }
-};
-
-
-class Item_func_y :public Item_real_func
-{
- String value;
-public:
- Item_func_y(Item *a) :Item_real_func(a) {}
- double val();
- const char *func_name() const { return "y"; }
-};
-
-
-class Item_func_numgeometries :public Item_int_func
-{
- String value;
-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; }
-};
-
-
-class Item_func_numinteriorring :public Item_int_func
-{
- String value;
-public:
- Item_func_numinteriorring(Item *a) :Item_int_func(a) {}
- longlong val_int();
- const char *func_name() const { return "numinteriorring"; }
- void fix_length_and_dec() { max_length=10; }
-};
-
-
-class Item_func_numpoints :public Item_int_func
-{
- String value;
-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; }
-};
-
-
-class Item_func_area :public Item_real_func
-{
- String value;
-public:
- Item_func_area(Item *a) :Item_real_func(a) {}
- double val();
- const char *func_name() const { return "area"; }
-};
-
-
-class Item_func_glength :public Item_real_func
-{
- String value;
-public:
- Item_func_glength(Item *a) :Item_real_func(a) {}
- double val();
- const char *func_name() const { return "glength"; }
-};
-
-
-class Item_func_srid: public Item_int_func
-{
- String value;
-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; }
-};
-
-
class Item_func_match_nl :public Item_func_match
{
public:
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
new file mode 100644
index 00000000000..06ba67cbc73
--- /dev/null
+++ b/sql/item_geofunc.cc
@@ -0,0 +1,653 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+/* This file defines all spatial functions */
+
+#ifdef __GNUC__
+#pragma implementation // gcc: Class implementation
+#endif
+
+#include "mysql_priv.h"
+#include "sql_acl.h"
+#include <m_ctype.h>
+
+String *Item_func_geometry_from_text::val_str(String *str)
+{
+ Geometry geom;
+ String arg_val;
+ String *wkt= args[0]->val_str(&arg_val);
+ GTextReadStream trs(wkt->ptr(), wkt->length());
+ uint32 srid;
+
+ if ((arg_count == 2) && !args[1]->null_value)
+ srid= args[1]->val_int();
+ else
+ srid= 0;
+
+ if (str->reserve(SRID_SIZE, 512))
+ return 0;
+ str->length(0);
+ str->q_append(srid);
+ if ((null_value=(args[0]->null_value || geom.create_from_wkt(&trs, str, 0))))
+ return 0;
+ return str;
+}
+
+
+void Item_func_geometry_from_text::fix_length_and_dec()
+{
+ max_length=MAX_BLOB_WIDTH;
+}
+
+
+String *Item_func_geometry_from_wkb::val_str(String *str)
+{
+ String arg_val;
+ String *wkb= args[0]->val_str(&arg_val);
+ Geometry geom;
+ uint32 srid;
+
+ if ((arg_count == 2) && !args[1]->null_value)
+ srid= args[1]->val_int();
+ else
+ srid= 0;
+
+ if (str->reserve(SRID_SIZE, 512))
+ return 0;
+ str->length(0);
+ str->q_append(srid);
+ if ((null_value= (args[0]->null_value ||
+ geom.create_from_wkb(wkb->ptr(), wkb->length()))))
+ return 0;
+
+ str->append(*wkb);
+ return str;
+}
+
+
+void Item_func_geometry_from_wkb::fix_length_and_dec()
+{
+ max_length=MAX_BLOB_WIDTH;
+}
+
+
+String *Item_func_as_text::val_str(String *str)
+{
+ String arg_val;
+ String *swkb= args[0]->val_str(&arg_val);
+ Geometry geom;
+
+ if ((null_value= (args[0]->null_value ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE))))
+ return 0;
+
+ str->length(0);
+
+ if ((null_value= geom.as_wkt(str)))
+ return 0;
+
+ return str;
+}
+
+void Item_func_as_text::fix_length_and_dec()
+{
+ max_length=MAX_BLOB_WIDTH;
+}
+
+String *Item_func_as_wkb::val_str(String *str)
+{
+ String arg_val;
+ String *swkb= args[0]->val_str(&arg_val);
+ Geometry geom;
+
+ if ((null_value= (args[0]->null_value ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE))))
+ return 0;
+
+ str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE,
+ &my_charset_bin);
+ return str;
+}
+
+void Item_func_as_wkb::fix_length_and_dec()
+{
+ max_length= MAX_BLOB_WIDTH;
+}
+
+String *Item_func_geometry_type::val_str(String *str)
+{
+ String *swkb= args[0]->val_str(str);
+ Geometry geom;
+
+ if ((null_value= (args[0]->null_value ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE))))
+ return 0;
+ str->copy(geom.get_class_info()->m_name,
+ strlen(geom.get_class_info()->m_name),
+ default_charset_info);
+ return str;
+}
+
+
+String *Item_func_envelope::val_str(String *str)
+{
+ String arg_val;
+ String *swkb= args[0]->val_str(&arg_val);
+ Geometry geom;
+
+ if ((null_value= args[0]->null_value ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)))
+ return 0;
+
+ uint32 srid= uint4korr(swkb->ptr());
+ str->length(0);
+ if (str->reserve(SRID_SIZE, 512))
+ return 0;
+ str->q_append(srid);
+ return (null_value= geom.envelope(str)) ? 0 : str;
+}
+
+
+String *Item_func_centroid::val_str(String *str)
+{
+ String arg_val;
+ String *swkb= args[0]->val_str(&arg_val);
+ Geometry geom;
+
+ if ((null_value= args[0]->null_value ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE) ||
+ !GEOM_METHOD_PRESENT(geom, centroid)))
+ return 0;
+
+ if (str->reserve(SRID_SIZE, 512))
+ return 0;
+ str->length(0);
+ uint32 srid= uint4korr(swkb->ptr());
+ str->q_append(srid);
+
+ return (null_value= geom.centroid(str)) ? 0 : str;
+}
+
+
+/*
+ Spatial decomposition functions
+*/
+
+String *Item_func_spatial_decomp::val_str(String *str)
+{
+ String arg_val;
+ String *swkb= args[0]->val_str(&arg_val);
+ Geometry geom;
+
+ if ((null_value= (args[0]->null_value ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE))))
+ return 0;
+
+ null_value= 1;
+ if (str->reserve(SRID_SIZE, 512))
+ return 0;
+ str->length(0);
+ uint32 srid= uint4korr(swkb->ptr());
+ str->q_append(srid);
+ switch(decomp_func)
+ {
+ case SP_STARTPOINT:
+ if (!GEOM_METHOD_PRESENT(geom,start_point) || geom.start_point(str))
+ goto ret;
+ break;
+
+ case SP_ENDPOINT:
+ if (!GEOM_METHOD_PRESENT(geom,end_point) || geom.end_point(str))
+ goto ret;
+ break;
+
+ case SP_EXTERIORRING:
+ if (!GEOM_METHOD_PRESENT(geom,exterior_ring) || geom.exterior_ring(str))
+ goto ret;
+ break;
+
+ default:
+ goto ret;
+ }
+ null_value= 0;
+
+ret:
+ return null_value ? 0 : str;
+}
+
+
+String *Item_func_spatial_decomp_n::val_str(String *str)
+{
+ String arg_val;
+ String *swkb= args[0]->val_str(&arg_val);
+ long n= (long) args[1]->val_int();
+ Geometry geom;
+
+ if ((null_value= (args[0]->null_value || args[1]->null_value ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE))))
+ return 0;
+
+ null_value= 1;
+ if (str->reserve(SRID_SIZE, 512))
+ return 0;
+ str->length(0);
+ uint32 srid= uint4korr(swkb->ptr());
+ str->q_append(srid);
+ switch(decomp_func_n)
+ {
+ case SP_POINTN:
+ if (!GEOM_METHOD_PRESENT(geom,point_n) || geom.point_n(n,str))
+ goto ret;
+ break;
+
+ case SP_GEOMETRYN:
+ if (!GEOM_METHOD_PRESENT(geom,geometry_n) || geom.geometry_n(n,str))
+ goto ret;
+ break;
+
+ case SP_INTERIORRINGN:
+ if (!GEOM_METHOD_PRESENT(geom,interior_ring_n) ||
+ geom.interior_ring_n(n,str))
+ goto ret;
+ break;
+
+ default:
+ goto ret;
+ }
+ null_value= 0;
+
+ret:
+ return null_value ? 0 : str;
+}
+
+
+/*
+ Functions to concatinate various spatial objects
+*/
+
+
+/*
+* Concatinate doubles into Point
+*/
+
+
+String *Item_func_point::val_str(String *str)
+{
+ double x= args[0]->val();
+ double y= args[1]->val();
+
+ if ( (null_value= (args[0]->null_value ||
+ args[1]->null_value ||
+ str->realloc(1 + 4 + 8 + 8))))
+ return 0;
+
+ str->length(0);
+ str->q_append((char)Geometry::wkbNDR);
+ str->q_append((uint32)Geometry::wkbPoint);
+ str->q_append(x);
+ str->q_append(y);
+ return str;
+}
+
+
+/*
+ Concatinates various items into various collections
+ with checkings for valid wkb type of items.
+ For example, MultiPoint can be a collection of Points only.
+ coll_type contains wkb type of target collection.
+ item_type contains a valid wkb type of items.
+ In the case when coll_type is wkbGeometryCollection,
+ we do not check wkb type of items, any is valid.
+*/
+
+String *Item_func_spatial_collection::val_str(String *str)
+{
+ String arg_value;
+ uint i;
+
+ null_value= 1;
+
+ str->length(0);
+ if (str->reserve(1 + 4 + 4, 512))
+ return 0;
+
+ str->q_append((char) Geometry::wkbNDR);
+ str->q_append((uint32) coll_type);
+ str->q_append((uint32) arg_count);
+
+ for (i= 0; i < arg_count; ++i)
+ {
+ String *res= args[i]->val_str(&arg_value);
+ if (args[i]->null_value)
+ goto ret;
+
+ if ( coll_type == Geometry::wkbGeometryCollection )
+ {
+ /*
+ In the case of GeometryCollection we don't need
+ any checkings for item types, so just copy them
+ into target collection
+ */
+ if ((null_value= str->reserve(res->length(), 512)))
+ goto ret;
+
+ str->q_append(res->ptr(), res->length());
+ }
+ else
+ {
+ enum Geometry::wkbType wkb_type;
+ uint32 len=res->length();
+ const char *data= res->ptr() + 1;
+
+ /*
+ In the case of named collection we must to
+ check that items are of specific type, let's
+ do this checking now
+ */
+
+ if (len < 5)
+ goto ret;
+ wkb_type= (Geometry::wkbType) uint4korr(data);
+ data+= 4;
+ len-= 5;
+ if (wkb_type != item_type)
+ goto ret;
+
+ switch (coll_type) {
+ case Geometry::wkbMultiPoint:
+ case Geometry::wkbMultiLineString:
+ case Geometry::wkbMultiPolygon:
+ if (len < WKB_HEADER_SIZE)
+ goto ret;
+
+ data-= WKB_HEADER_SIZE;
+ len+= WKB_HEADER_SIZE;
+ if (str->reserve(len, 512))
+ goto ret;
+ str->q_append(data, len);
+ break;
+
+ case Geometry::wkbLineString:
+ if (str->reserve(POINT_DATA_SIZE, 512))
+ goto ret;
+ str->q_append(data, POINT_DATA_SIZE);
+ break;
+
+ case Geometry::wkbPolygon:
+ {
+ uint32 n_points;
+ double x1, y1, x2, y2;
+
+ if (len < 4 + 2 * POINT_DATA_SIZE)
+ goto ret;
+
+ uint32 llen= len;
+ const char *ldata= data;
+
+ n_points= uint4korr(data);
+ data+= 4;
+ float8get(x1, data);
+ data+= 8;
+ float8get(y1, data);
+ data+= 8;
+
+ data+= (n_points - 2) * POINT_DATA_SIZE;
+
+ float8get(x2, data);
+ float8get(y2, data + 8);
+
+ if ((x1 != x2) || (y1 != y2))
+ goto ret;
+
+ if (str->reserve(llen, 512))
+ goto ret;
+ str->q_append(ldata, llen);
+ }
+ break;
+
+ default:
+ goto ret;
+ }
+ }
+ }
+
+ if (str->length() > current_thd->variables.max_allowed_packet)
+ goto ret;
+
+ null_value = 0;
+
+ret:
+ return null_value ? 0 : str;
+}
+
+/*
+ Functions for spatial relations
+*/
+
+longlong Item_func_spatial_rel::val_int()
+{
+ String *res1= args[0]->val_str(&tmp_value1);
+ String *res2= args[1]->val_str(&tmp_value2);
+ Geometry g1, g2;
+ MBR mbr1, mbr2;
+
+ if ((null_value= (args[0]->null_value ||
+ args[1]->null_value ||
+ g1.create_from_wkb(res1->ptr() + SRID_SIZE,
+ res1->length() - SRID_SIZE) ||
+ g2.create_from_wkb(res2->ptr() + SRID_SIZE,
+ res2->length() - SRID_SIZE) ||
+ g1.get_mbr(&mbr1) ||
+ g2.get_mbr(&mbr2))))
+ return 0;
+
+ switch (spatial_rel)
+ {
+ case SP_CONTAINS_FUNC:
+ return mbr1.contains(&mbr2);
+ case SP_WITHIN_FUNC:
+ return mbr1.within(&mbr2);
+ case SP_EQUALS_FUNC:
+ return mbr1.equals(&mbr2);
+ case SP_DISJOINT_FUNC:
+ return mbr1.disjoint(&mbr2);
+ case SP_INTERSECTS_FUNC:
+ return mbr1.intersects(&mbr2);
+ case SP_TOUCHES_FUNC:
+ return mbr1.touches(&mbr2);
+ case SP_OVERLAPS_FUNC:
+ return mbr1.overlaps(&mbr2);
+ case SP_CROSSES_FUNC:
+ return 0;
+ default:
+ break;
+ }
+
+ null_value=1;
+ return 0;
+}
+
+longlong Item_func_isempty::val_int()
+{
+ String tmp;
+ null_value=0;
+ return args[0]->null_value ? 1 : 0;
+}
+
+longlong Item_func_issimple::val_int()
+{
+ String tmp;
+ String *wkb=args[0]->val_str(&tmp);
+
+ if ((null_value= (!wkb || args[0]->null_value )))
+ return 0;
+ /* TODO: Ramil or Holyfoot, add real IsSimple calculation */
+ return 0;
+}
+
+longlong Item_func_isclosed::val_int()
+{
+ String tmp;
+ String *swkb= args[0]->val_str(&tmp);
+ Geometry geom;
+ int isclosed;
+
+ null_value= (!swkb ||
+ args[0]->null_value ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE) ||
+ !GEOM_METHOD_PRESENT(geom,is_closed) ||
+ geom.is_closed(&isclosed));
+
+ return (longlong) isclosed;
+}
+
+/*
+ Numerical functions
+*/
+
+longlong Item_func_dimension::val_int()
+{
+ uint32 dim;
+ String *swkb= args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!swkb ||
+ args[0]->null_value ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE) ||
+ geom.dimension(&dim));
+ return (longlong) dim;
+}
+
+longlong Item_func_numinteriorring::val_int()
+{
+ uint32 num;
+ String *swkb= args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!swkb ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE) ||
+ !GEOM_METHOD_PRESENT(geom, num_interior_ring) ||
+ geom.num_interior_ring(&num));
+ return (longlong) num;
+}
+
+longlong Item_func_numgeometries::val_int()
+{
+ uint32 num= 0;
+ String *swkb= args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!swkb ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE) ||
+ !GEOM_METHOD_PRESENT(geom, num_geometries) ||
+ geom.num_geometries(&num));
+ return (longlong) num;
+}
+
+longlong Item_func_numpoints::val_int()
+{
+ uint32 num;
+ String *swkb= args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!swkb ||
+ args[0]->null_value ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE) ||
+ !GEOM_METHOD_PRESENT(geom, num_points) ||
+ geom.num_points(&num));
+ return (longlong) num;
+}
+
+double Item_func_x::val()
+{
+ double res;
+ String *swkb= args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!swkb ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE) ||
+ !GEOM_METHOD_PRESENT(geom, get_x) ||
+ geom.get_x(&res));
+ return res;
+}
+
+double Item_func_y::val()
+{
+ double res;
+ String *swkb= args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!swkb ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE) ||
+ !GEOM_METHOD_PRESENT(geom, get_y) ||
+ geom.get_y(&res));
+ return res;
+}
+
+double Item_func_area::val()
+{
+ double res;
+ String *swkb= args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!swkb ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE) ||
+ !GEOM_METHOD_PRESENT(geom, area) ||
+ geom.area(&res));
+ return res;
+}
+
+double Item_func_glength::val()
+{
+ double res;
+ String *swkb= args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!swkb ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE) ||
+ !GEOM_METHOD_PRESENT(geom, length) ||
+ geom.length(&res));
+ return res;
+}
+
+longlong Item_func_srid::val_int()
+{
+ String *swkb= args[0]->val_str(&value);
+ Geometry geom;
+
+ null_value= (!swkb ||
+ geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE));
+ uint32 res= uint4korr(swkb->ptr());
+ return (longlong) res;
+}
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
new file mode 100644
index 00000000000..21e94735f31
--- /dev/null
+++ b/sql/item_geofunc.h
@@ -0,0 +1,360 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+/* This file defines all spatial functions */
+
+#ifdef __GNUC__
+#pragma interface /* gcc class implementation */
+#endif
+
+#define SRID_SIZE sizeof(uint32)
+
+class Item_func_geometry_from_text: public Item_str_func
+{
+public:
+ Item_func_geometry_from_text(Item *a) :Item_str_func(a) {}
+ Item_func_geometry_from_text(Item *a, Item *srid) :Item_str_func(a, srid) {}
+ const char *func_name() const { return "geometryfromtext"; }
+ String *val_str(String *);
+ void fix_length_and_dec();
+};
+
+class Item_func_geometry_from_wkb: public Item_str_func
+{
+public:
+ Item_func_geometry_from_wkb(Item *a): Item_str_func(a) {}
+ Item_func_geometry_from_wkb(Item *a, Item *srid): Item_str_func(a, srid) {}
+ const char *func_name() const { return "geometryfromwkb"; }
+ String *val_str(String *);
+ void fix_length_and_dec();
+};
+
+class Item_func_as_text: public Item_str_func
+{
+public:
+ Item_func_as_text(Item *a): Item_str_func(a) {}
+ const char *func_name() const { return "astext"; }
+ String *val_str(String *);
+ void fix_length_and_dec();
+};
+
+class Item_func_as_wkb: public Item_str_func
+{
+public:
+ Item_func_as_wkb(Item *a): Item_str_func(a) {}
+ const char *func_name() const { return "aswkb"; }
+ String *val_str(String *);
+ void fix_length_and_dec();
+};
+
+class Item_func_geometry_type: public Item_str_func
+{
+public:
+ Item_func_geometry_type(Item *a): Item_str_func(a) {}
+ String *val_str(String *);
+ const char *func_name() const { return "geometrytype"; }
+ void fix_length_and_dec()
+ {
+ max_length=20; // "GeometryCollection" is the most long
+ };
+};
+
+class Item_func_centroid: public Item_str_func
+{
+public:
+ Item_func_centroid(Item *a): Item_str_func(a) {}
+ const char *func_name() const { return "centroid"; }
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+};
+
+class Item_func_envelope: public Item_str_func
+{
+public:
+ Item_func_envelope(Item *a): Item_str_func(a) {}
+ const char *func_name() const { return "envelope"; }
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+};
+
+class Item_func_point: public Item_str_func
+{
+public:
+ Item_func_point(Item *a, Item *b): Item_str_func(a, b) {}
+ Item_func_point(Item *a, Item *b, Item *srid): Item_str_func(a, b, srid) {}
+ const char *func_name() const { return "point"; }
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+};
+
+class Item_func_spatial_decomp: public Item_str_func
+{
+ enum Functype decomp_func;
+public:
+ Item_func_spatial_decomp(Item *a, Item_func::Functype ft) :
+ Item_str_func(a) { decomp_func = ft; }
+ const char *func_name() const
+ {
+ switch (decomp_func)
+ {
+ case SP_STARTPOINT:
+ return "startpoint";
+ case SP_ENDPOINT:
+ return "endpoint";
+ case SP_EXTERIORRING:
+ return "exteriorring";
+ default:
+ return "spatial_decomp_unknown";
+ }
+ }
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+};
+
+class Item_func_spatial_decomp_n: public Item_str_func
+{
+ enum Functype decomp_func_n;
+public:
+ Item_func_spatial_decomp_n(Item *a, Item *b, Item_func::Functype ft):
+ Item_str_func(a, b) { decomp_func_n = ft; }
+ const char *func_name() const
+ {
+ switch (decomp_func_n)
+ {
+ case SP_POINTN:
+ return "pointn";
+ case SP_GEOMETRYN:
+ return "geometryn";
+ case SP_INTERIORRINGN:
+ return "interiorringn";
+ default:
+ return "spatial_decomp_n_unknown";
+ }
+ }
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+};
+
+class Item_func_spatial_collection: public Item_str_func
+{
+ String tmp_value;
+ enum Geometry::wkbType coll_type;
+ enum Geometry::wkbType item_type;
+public:
+ Item_func_spatial_collection(
+ List<Item> &list, enum Geometry::wkbType ct, enum Geometry::wkbType it):
+ Item_str_func(list)
+ {
+ coll_type=ct;
+ item_type=it;
+ }
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
+ const char *func_name() const { return "multipoint"; }
+};
+
+#ifdef HAVE_COMPRESS
+
+class Item_func_compress: public Item_str_func
+{
+ String buffer;
+public:
+ Item_func_compress(Item *a):Item_str_func(a){}
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;}
+ const char *func_name() const{return "compress";}
+};
+
+class Item_func_uncompress: public Item_str_func
+{
+ String buffer;
+public:
+ Item_func_uncompress(Item *a): Item_str_func(a){}
+ String *val_str(String *);
+ void fix_length_and_dec(){max_length= MAX_BLOB_WIDTH;}
+ const char *func_name() const{return "uncompress";}
+};
+
+#endif
+
+/*
+ Spatial relations
+*/
+
+class Item_func_spatial_rel: public Item_bool_func2
+{
+ enum Functype spatial_rel;
+public:
+ Item_func_spatial_rel(Item *a,Item *b, enum Functype sp_rel) :
+ Item_bool_func2(a,b) { spatial_rel = sp_rel; }
+ longlong val_int();
+ enum Functype functype() const
+ {
+ switch (spatial_rel) {
+ case SP_CONTAINS_FUNC:
+ return SP_WITHIN_FUNC;
+ case SP_WITHIN_FUNC:
+ return SP_CONTAINS_FUNC;
+ default:
+ return spatial_rel;
+ }
+ }
+ enum Functype rev_functype() const { return spatial_rel; }
+ const char *func_name() const
+ {
+ switch (spatial_rel) {
+ case SP_CONTAINS_FUNC:
+ return "contains";
+ case SP_WITHIN_FUNC:
+ return "within";
+ case SP_EQUALS_FUNC:
+ return "equals";
+ case SP_DISJOINT_FUNC:
+ return "disjoint";
+ case SP_INTERSECTS_FUNC:
+ return "intersects";
+ case SP_TOUCHES_FUNC:
+ return "touches";
+ case SP_CROSSES_FUNC:
+ return "crosses";
+ case SP_OVERLAPS_FUNC:
+ return "overlaps";
+ default:
+ return "sp_unknown";
+ }
+ }
+};
+
+class Item_func_isempty: public Item_bool_func
+{
+public:
+ Item_func_isempty(Item *a): Item_bool_func(a) {}
+ longlong val_int();
+ optimize_type select_optimize() const { return OPTIMIZE_NONE; }
+ const char *func_name() const { return "isempty"; }
+};
+
+class Item_func_issimple: public Item_bool_func
+{
+public:
+ Item_func_issimple(Item *a): Item_bool_func(a) {}
+ longlong val_int();
+ optimize_type select_optimize() const { return OPTIMIZE_NONE; }
+ const char *func_name() const { return "issimple"; }
+};
+
+class Item_func_isclosed: public Item_bool_func
+{
+public:
+ Item_func_isclosed(Item *a): Item_bool_func(a) {}
+ longlong val_int();
+ optimize_type select_optimize() const { return OPTIMIZE_NONE; }
+ const char *func_name() const { return "isclosed"; }
+};
+
+class Item_func_dimension: public Item_int_func
+{
+ String value;
+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; }
+};
+
+class Item_func_x: public Item_real_func
+{
+ String value;
+public:
+ Item_func_x(Item *a): Item_real_func(a) {}
+ double val();
+ const char *func_name() const { return "x"; }
+};
+
+
+class Item_func_y: public Item_real_func
+{
+ String value;
+public:
+ Item_func_y(Item *a): Item_real_func(a) {}
+ double val();
+ const char *func_name() const { return "y"; }
+};
+
+
+class Item_func_numgeometries: public Item_int_func
+{
+ String value;
+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; }
+};
+
+
+class Item_func_numinteriorring: public Item_int_func
+{
+ String value;
+public:
+ Item_func_numinteriorring(Item *a): Item_int_func(a) {}
+ longlong val_int();
+ const char *func_name() const { return "numinteriorring"; }
+ void fix_length_and_dec() { max_length=10; }
+};
+
+
+class Item_func_numpoints: public Item_int_func
+{
+ String value;
+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; }
+};
+
+
+class Item_func_area: public Item_real_func
+{
+ String value;
+public:
+ Item_func_area(Item *a): Item_real_func(a) {}
+ double val();
+ const char *func_name() const { return "area"; }
+};
+
+
+class Item_func_glength: public Item_real_func
+{
+ String value;
+public:
+ Item_func_glength(Item *a): Item_real_func(a) {}
+ double val();
+ const char *func_name() const { return "glength"; }
+};
+
+
+class Item_func_srid: public Item_int_func
+{
+ String value;
+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; }
+};
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index ae48aeb115a..06569095018 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2522,428 +2522,6 @@ null:
return 0;
}
-
-/*******************************************************
-General functions for spatial objects
-********************************************************/
-
-String *Item_func_geometry_from_text::val_str(String *str)
-{
- Geometry geom;
- String arg_val;
- String *wkt= args[0]->val_str(&arg_val);
- GTextReadStream trs(wkt->ptr(), wkt->length());
- uint32 srid;
-
- if ((arg_count == 2) && !args[1]->null_value)
- srid= args[1]->val_int();
- else
- srid= 0;
-
- if (str->reserve(SRID_SIZE, 512))
- return 0;
- str->length(0);
- str->q_append(srid);
- if ((null_value=(args[0]->null_value || geom.create_from_wkt(&trs, str, 0))))
- return 0;
- return str;
-}
-
-
-void Item_func_geometry_from_text::fix_length_and_dec()
-{
- max_length=MAX_BLOB_WIDTH;
-}
-
-
-String *Item_func_geometry_from_wkb::val_str(String *str)
-{
- String arg_val;
- String *wkb= args[0]->val_str(&arg_val);
- Geometry geom;
- uint32 srid;
-
- if ((arg_count == 2) && !args[1]->null_value)
- srid= args[1]->val_int();
- else
- srid= 0;
-
- if (str->reserve(SRID_SIZE, 512))
- return 0;
- str->length(0);
- str->q_append(srid);
- if ((null_value= (args[0]->null_value ||
- geom.create_from_wkb(wkb->ptr(), wkb->length()))))
- return 0;
-
- str->append(*wkb);
- return str;
-}
-
-
-void Item_func_geometry_from_wkb::fix_length_and_dec()
-{
- max_length=MAX_BLOB_WIDTH;
-}
-
-
-String *Item_func_as_text::val_str(String *str)
-{
- String arg_val;
- String *swkb= args[0]->val_str(&arg_val);
- Geometry geom;
-
- if ((null_value= (args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE))))
- return 0;
-
- str->length(0);
-
- if ((null_value= geom.as_wkt(str)))
- return 0;
-
- return str;
-}
-
-void Item_func_as_text::fix_length_and_dec()
-{
- max_length=MAX_BLOB_WIDTH;
-}
-
-String *Item_func_as_wkb::val_str(String *str)
-{
- String arg_val;
- String *swkb= args[0]->val_str(&arg_val);
- Geometry geom;
-
- if ((null_value= (args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE))))
- return 0;
-
- str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE,
- &my_charset_bin);
- return str;
-}
-
-void Item_func_as_wkb::fix_length_and_dec()
-{
- max_length= MAX_BLOB_WIDTH;
-}
-
-String *Item_func_geometry_type::val_str(String *str)
-{
- String *swkb= args[0]->val_str(str);
- Geometry geom;
-
- if ((null_value= (args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE))))
- return 0;
- str->copy(geom.get_class_info()->m_name,
- strlen(geom.get_class_info()->m_name),
- default_charset_info);
- return str;
-}
-
-
-String *Item_func_envelope::val_str(String *str)
-{
- String arg_val;
- String *swkb= args[0]->val_str(&arg_val);
- Geometry geom;
-
- if ((null_value= args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE)))
- return 0;
-
- uint32 srid= uint4korr(swkb->ptr());
- str->length(0);
- if (str->reserve(SRID_SIZE, 512))
- return 0;
- str->q_append(srid);
- return (null_value= geom.envelope(str)) ? 0 : str;
-}
-
-
-String *Item_func_centroid::val_str(String *str)
-{
- String arg_val;
- String *swkb= args[0]->val_str(&arg_val);
- Geometry geom;
-
- if ((null_value= args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE) ||
- !GEOM_METHOD_PRESENT(geom, centroid)))
- return 0;
-
- if (str->reserve(SRID_SIZE, 512))
- return 0;
- str->length(0);
- uint32 srid= uint4korr(swkb->ptr());
- str->q_append(srid);
-
- return (null_value= geom.centroid(str)) ? 0 : str;
-}
-
-
-/***********************************************
- Spatial decomposition functions
-***********************************************/
-
-String *Item_func_spatial_decomp::val_str(String *str)
-{
- String arg_val;
- String *swkb= args[0]->val_str(&arg_val);
- Geometry geom;
-
- if ((null_value= (args[0]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE))))
- return 0;
-
- null_value= 1;
- if (str->reserve(SRID_SIZE, 512))
- return 0;
- str->length(0);
- uint32 srid= uint4korr(swkb->ptr());
- str->q_append(srid);
- switch(decomp_func)
- {
- case SP_STARTPOINT:
- if (!GEOM_METHOD_PRESENT(geom,start_point) || geom.start_point(str))
- goto ret;
- break;
-
- case SP_ENDPOINT:
- if (!GEOM_METHOD_PRESENT(geom,end_point) || geom.end_point(str))
- goto ret;
- break;
-
- case SP_EXTERIORRING:
- if (!GEOM_METHOD_PRESENT(geom,exterior_ring) || geom.exterior_ring(str))
- goto ret;
- break;
-
- default:
- goto ret;
- }
- null_value= 0;
-
-ret:
- return null_value ? 0 : str;
-}
-
-
-String *Item_func_spatial_decomp_n::val_str(String *str)
-{
- String arg_val;
- String *swkb= args[0]->val_str(&arg_val);
- long n= (long) args[1]->val_int();
- Geometry geom;
-
- if ((null_value= (args[0]->null_value || args[1]->null_value ||
- geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE))))
- return 0;
-
- null_value= 1;
- if (str->reserve(SRID_SIZE, 512))
- return 0;
- str->length(0);
- uint32 srid= uint4korr(swkb->ptr());
- str->q_append(srid);
- switch(decomp_func_n)
- {
- case SP_POINTN:
- if (!GEOM_METHOD_PRESENT(geom,point_n) || geom.point_n(n,str))
- goto ret;
- break;
-
- case SP_GEOMETRYN:
- if (!GEOM_METHOD_PRESENT(geom,geometry_n) || geom.geometry_n(n,str))
- goto ret;
- break;
-
- case SP_INTERIORRINGN:
- if (!GEOM_METHOD_PRESENT(geom,interior_ring_n) ||
- geom.interior_ring_n(n,str))
- goto ret;
- break;
-
- default:
- goto ret;
- }
- null_value= 0;
-
-ret:
- return null_value ? 0 : str;
-}
-
-
-
-/***********************************************
-Functions to concatinate various spatial objects
-************************************************/
-
-
-/*
-* Concatinate doubles into Point
-*/
-
-
-String *Item_func_point::val_str(String *str)
-{
- double x= args[0]->val();
- double y= args[1]->val();
-
- if ( (null_value= (args[0]->null_value ||
- args[1]->null_value ||
- str->realloc(1 + 4 + 8 + 8))))
- return 0;
-
- str->length(0);
- str->q_append((char)Geometry::wkbNDR);
- str->q_append((uint32)Geometry::wkbPoint);
- str->q_append(x);
- str->q_append(y);
- return str;
-}
-
-
-/*
- Concatinates various items into various collections
- with checkings for valid wkb type of items.
- For example, MultiPoint can be a collection of Points only.
- coll_type contains wkb type of target collection.
- item_type contains a valid wkb type of items.
- In the case when coll_type is wkbGeometryCollection,
- we do not check wkb type of items, any is valid.
-*/
-
-String *Item_func_spatial_collection::val_str(String *str)
-{
- String arg_value;
- uint i;
-
- null_value= 1;
-
- str->length(0);
- if (str->reserve(1 + 4 + 4, 512))
- return 0;
-
- str->q_append((char) Geometry::wkbNDR);
- str->q_append((uint32) coll_type);
- str->q_append((uint32) arg_count);
-
- for (i= 0; i < arg_count; ++i)
- {
- String *res= args[i]->val_str(&arg_value);
- if (args[i]->null_value)
- goto ret;
-
- if ( coll_type == Geometry::wkbGeometryCollection )
- {
- /*
- In the case of GeometryCollection we don't need
- any checkings for item types, so just copy them
- into target collection
- */
- if ((null_value= str->reserve(res->length(), 512)))
- goto ret;
-
- str->q_append(res->ptr(), res->length());
- }
- else
- {
- enum Geometry::wkbType wkb_type;
- uint32 len=res->length();
- const char *data= res->ptr() + 1;
-
- /*
- In the case of named collection we must to
- check that items are of specific type, let's
- do this checking now
- */
-
- if (len < 5)
- goto ret;
- wkb_type= (Geometry::wkbType) uint4korr(data);
- data+= 4;
- len-= 5;
- if (wkb_type != item_type)
- goto ret;
-
- switch (coll_type) {
- case Geometry::wkbMultiPoint:
- case Geometry::wkbMultiLineString:
- case Geometry::wkbMultiPolygon:
- if (len < WKB_HEADER_SIZE)
- goto ret;
-
- data-= WKB_HEADER_SIZE;
- len+= WKB_HEADER_SIZE;
- if (str->reserve(len, 512))
- goto ret;
- str->q_append(data, len);
- break;
-
- case Geometry::wkbLineString:
- if (str->reserve(POINT_DATA_SIZE, 512))
- goto ret;
- str->q_append(data, POINT_DATA_SIZE);
- break;
-
- case Geometry::wkbPolygon:
- {
- uint32 n_points;
- double x1, y1, x2, y2;
-
- if (len < 4 + 2 * POINT_DATA_SIZE)
- goto ret;
-
- uint32 llen= len;
- const char *ldata= data;
-
- n_points= uint4korr(data);
- data+= 4;
- float8get(x1, data);
- data+= 8;
- float8get(y1, data);
- data+= 8;
-
- data+= (n_points - 2) * POINT_DATA_SIZE;
-
- float8get(x2, data);
- float8get(y2, data + 8);
-
- if ((x1 != x2) || (y1 != y2))
- goto ret;
-
- if (str->reserve(llen, 512))
- goto ret;
- str->q_append(ldata, llen);
- }
- break;
-
- default:
- goto ret;
- }
- }
- }
-
- if (str->length() > current_thd->variables.max_allowed_packet)
- goto ret;
-
- null_value = 0;
-
-ret:
- return null_value ? 0 : str;
-}
-
#ifdef HAVE_COMPRESS
#include "../zlib/zlib.h"
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 8ae5c995375..65aad3a3fff 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -628,242 +628,3 @@ public:
set_charset(default_charset());
};
};
-
-
-/*******************************************************
-Spatial functions
-********************************************************/
-
-#define SRID_SIZE sizeof(uint32)
-
-class Item_func_geometry_from_text :public Item_str_func
-{
-public:
- Item_func_geometry_from_text(Item *a) :Item_str_func(a) {}
- Item_func_geometry_from_text(Item *a, Item *srid) :Item_str_func(a, srid) {}
- const char *func_name() const { return "geometryfromtext"; }
- String *val_str(String *);
- void fix_length_and_dec();
-};
-
-class Item_func_geometry_from_wkb: public Item_str_func
-{
-public:
- Item_func_geometry_from_wkb(Item *a) :Item_str_func(a) {}
- Item_func_geometry_from_wkb(Item *a, Item *srid) :Item_str_func(a, srid) {}
- const char *func_name() const { return "geometryfromwkb"; }
- String *val_str(String *);
- void fix_length_and_dec();
-};
-
-class Item_func_as_text :public Item_str_func
-{
-public:
- Item_func_as_text(Item *a) :Item_str_func(a) {}
- const char *func_name() const { return "astext"; }
- String *val_str(String *);
- void fix_length_and_dec();
-};
-
-class Item_func_as_wkb :public Item_str_func
-{
-public:
- Item_func_as_wkb(Item *a) :Item_str_func(a) {}
- const char *func_name() const { return "aswkb"; }
- String *val_str(String *);
- void fix_length_and_dec();
-};
-
-class Item_func_geometry_type :public Item_str_func
-{
-public:
- Item_func_geometry_type(Item *a) :Item_str_func(a) {}
- String *val_str(String *);
- const char *func_name() const { return "geometrytype"; }
- void fix_length_and_dec()
- {
- max_length=20; // "GeometryCollection" is the most long
- };
-};
-
-class Item_func_centroid :public Item_str_func
-{
-public:
- Item_func_centroid(Item *a) :Item_str_func(a) {}
- const char *func_name() const { return "centroid"; }
- String *val_str(String *);
- void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
-};
-
-class Item_func_envelope :public Item_str_func
-{
-public:
- Item_func_envelope(Item *a) :Item_str_func(a) {}
- const char *func_name() const { return "envelope"; }
- String *val_str(String *);
- void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
-};
-
-class Item_func_point :public Item_str_func
-{
-public:
- Item_func_point(Item *a, Item *b) :Item_str_func(a, b) {}
- Item_func_point(Item *a, Item *b, Item *srid) :Item_str_func(a, b, srid) {}
- const char *func_name() const { return "point"; }
- String *val_str(String *);
- void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
-};
-
-class Item_func_spatial_decomp :public Item_str_func
-{
- enum Functype decomp_func;
-public:
- Item_func_spatial_decomp(Item *a, Item_func::Functype ft) :
- Item_str_func(a) { decomp_func = ft; }
- const char *func_name() const
- {
- switch (decomp_func)
- {
- case SP_STARTPOINT:
- return "startpoint";
- case SP_ENDPOINT:
- return "endpoint";
- case SP_EXTERIORRING:
- return "exteriorring";
- default:
- return "spatial_decomp_unknown";
- }
- }
- String *val_str(String *);
- void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
-};
-
-class Item_func_spatial_decomp_n :public Item_str_func
-{
- enum Functype decomp_func_n;
-public:
- Item_func_spatial_decomp_n(Item *a, Item *b, Item_func::Functype ft) :
- Item_str_func(a, b) { decomp_func_n = ft; }
- const char *func_name() const
- {
- switch (decomp_func_n)
- {
- case SP_POINTN:
- return "pointn";
- case SP_GEOMETRYN:
- return "geometryn";
- case SP_INTERIORRINGN:
- return "interiorringn";
- default:
- return "spatial_decomp_n_unknown";
- }
- }
- String *val_str(String *);
- void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
-};
-
-
-class Item_func_spatial_collection :public Item_str_func
-{
- String tmp_value;
- enum Geometry::wkbType coll_type;
- enum Geometry::wkbType item_type;
-public:
- Item_func_spatial_collection(
- List<Item> &list, enum Geometry::wkbType ct, enum Geometry::wkbType it) :
- Item_str_func(list)
- {
- coll_type=ct;
- item_type=it;
- }
- String *val_str(String *);
- void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
- const char *func_name() const { return "multipoint"; }
-};
-
-#ifdef HAVE_COMPRESS
-
-class Item_func_compress : public Item_str_func
-{
- String buffer;
-public:
- Item_func_compress(Item *a):Item_str_func(a){}
- String *val_str(String *);
- void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;}
- const char *func_name() const{return "compress";}
-};
-
-class Item_func_uncompress : public Item_str_func
-{
- String buffer;
-public:
- Item_func_uncompress(Item *a):Item_str_func(a){}
- String *val_str(String *);
- void fix_length_and_dec(){max_length= MAX_BLOB_WIDTH;}
- const char *func_name() const{return "uncompress";}
-};
-
-#endif
-
-/*
-class Item_func_multipoint :public Item_str_func
-{
- String tmp_value;
-public:
- Item_func_multipoint(List<Item> &list) :Item_str_func(list) {}
- String *val_str(String *);
- void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
- const char *func_name() const { return "multipoint"; }
-};
-
-class Item_func_linestring :public Item_str_func
-{
- String tmp_value;
-public:
- Item_func_linestring(List<Item> &list) :Item_str_func(list) {}
- String *val_str(String *);
- void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
- const char *func_name() const { return "linestring"; }
-};
-
-class Item_func_multilinestring :public Item_str_func
-{
- String tmp_value;
-public:
- Item_func_multilinestring(List<Item> &list) :Item_str_func(list) {}
- String *val_str(String *);
- void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
- const char *func_name() const { return "multilinestring"; }
-};
-
-class Item_func_polygon :public Item_str_func
-{
- String tmp_value;
-public:
- Item_func_polygon(List<Item> &list) :Item_str_func(list) {}
- String *val_str(String *);
- void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
- const char *func_name() const { return "polygon"; }
-};
-
-class Item_func_multipolygon :public Item_str_func
-{
- String tmp_value;
-public:
- Item_func_multipolygon(List<Item> &list) :Item_str_func(list) {}
- String *val_str(String *);
- void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
- const char *func_name() const { return "multipolygon"; }
-};
-
-class Item_func_geometrycollection :public Item_str_func
-{
- String tmp_value;
-public:
- Item_func_geometrycollection(List<Item> &list) :Item_str_func(list) {}
- String *val_str(String *);
- void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
- const char *func_name() const { return "geometrycollection"; }
-};
-
-*/
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 712c8853a20..a59f1d4b81a 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -877,6 +877,7 @@ bool check_db_name(char *db);
bool check_column_name(const char *name);
bool check_table_name(const char *name, uint length);
char *get_field(MEM_ROOT *mem, Field *field);
+bool get_field(MEM_ROOT *mem, Field *field, class String *res);
int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr);
/* from hostname.cc */
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 6d31abc3dc9..7011f6dcd36 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -300,7 +300,7 @@ char* log_error_file_ptr= log_error_file;
char mysql_real_data_home[FN_REFLEN],
language[LIBLEN],reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file;
-char *language_ptr, *default_collation_name;
+char *language_ptr, *default_collation_name, *default_character_set_name;
char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home;
char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION;
char *mysql_unix_port, *opt_mysql_tmpdir;
@@ -2028,7 +2028,7 @@ static int init_common_variables(const char *conf_file_name, int argc,
#ifdef USE_REGEX
regex_init(&my_charset_latin1);
#endif
- if (!(default_charset_info= get_charset_by_csname(sys_charset.value,
+ if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
MY_CS_PRIMARY,
MYF(MY_WME))))
return 1;
@@ -2046,7 +2046,9 @@ static int init_common_variables(const char *conf_file_name, int argc,
}
default_charset_info= default_collation;
}
- global_system_variables.character_set_results= NULL;
+ global_system_variables.character_set_server= default_charset_info;
+ global_system_variables.character_set_database= default_charset_info;
+ global_system_variables.character_set_results= default_charset_info;
global_system_variables.character_set_client= default_charset_info;
global_system_variables.collation_connection= default_charset_info;
@@ -3542,8 +3544,8 @@ Disable with --skip-bdb (will save memory)",
0, 0, 0, 0, 0, 0},
#endif /* HAVE_OPENSSL */
{"default-character-set", 'C', "Set the default character set",
- (gptr*) &sys_charset.value, (gptr*) &sys_charset.value, 0, GET_STR,
- REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ (gptr*) &default_character_set_name, (gptr*) &default_character_set_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{"default-collation", OPT_DEFAULT_COLLATION, "Set the default collation",
(gptr*) &default_collation_name, (gptr*) &default_collation_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
@@ -4538,7 +4540,7 @@ static void use_help(void)
static void usage(void)
{
- if (!(default_charset_info= get_charset_by_csname(sys_charset.value,
+ if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
MY_CS_PRIMARY,
MYF(MY_WME))))
exit(1);
@@ -4642,7 +4644,6 @@ static void mysql_init_variables(void)
pidfile_name_ptr= pidfile_name;
log_error_file_ptr= log_error_file;
language_ptr= language;
- default_collation_name= (char*) MYSQL_DEFAULT_COLLATION_NAME;
mysql_data_home= mysql_real_data_home;
thd_startup_options= (OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL |
OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE);
@@ -4681,11 +4682,14 @@ static void mysql_init_variables(void)
/* Variables in libraries */
charsets_dir= 0;
- sys_charset.value= (char*) MYSQL_DEFAULT_CHARSET_NAME;
+ default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME;
+ default_collation_name= (char*) MYSQL_DEFAULT_COLLATION_NAME;
sys_charset_system.value= (char*) system_charset_info->csname;
/* Set default values for some option variables */
- global_system_variables.character_set_results= NULL;
+ global_system_variables.character_set_server= default_charset_info;
+ global_system_variables.character_set_database= default_charset_info;
+ global_system_variables.character_set_results= default_charset_info;
global_system_variables.character_set_client= default_charset_info;
global_system_variables.collation_connection= default_charset_info;
global_system_variables.table_type= DB_TYPE_MYISAM;
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 848321c1576..7abbf3ce85b 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -499,7 +499,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
Protocol_simple prot(thd);
String *packet= prot.storage_packet();
- CHARSET_INFO *thd_charset= thd->charset();
+ CHARSET_INFO *thd_charset= thd->variables.character_set_results;
DBUG_ENTER("send_fields");
if (flag & 1)
diff --git a/sql/protocol.h b/sql/protocol.h
index 2110f1877c2..ffd61b3e848 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -60,6 +60,8 @@ public:
{ return store_longlong((longlong) from, 0); }
inline bool store(ulonglong from)
{ return store_longlong((longlong) from, 1); }
+ inline bool store(String *str)
+ { return store(str->c_ptr(),str->length(),str->charset()); }
virtual bool prepare_for_send(List<Item> *item_list)
{
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 3145504951d..60b0d24430d 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -103,15 +103,14 @@ sys_var_long_ptr sys_binlog_cache_size("binlog_cache_size",
&binlog_cache_size);
sys_var_thd_ulong sys_bulk_insert_buff_size("bulk_insert_buffer_size",
&SV::bulk_insert_buff_size);
-sys_var_str sys_charset("character_set_server",
- sys_check_charset,
- sys_update_charset,
- sys_set_default_charset);
-sys_var_str sys_charset_system("character_set_system",
+sys_var_character_set_server sys_character_set_server("character_set_server");
+sys_var_str sys_charset_system("character_set_system",
sys_check_charset,
sys_update_charset,
sys_set_default_charset);
+sys_var_character_set_database sys_character_set_database("character_set_database");
sys_var_character_set_client sys_character_set_client("character_set_client");
+sys_var_character_set_connection sys_character_set_connection("character_set_connection");
sys_var_character_set_results sys_character_set_results("character_set_results");
sys_var_collation_connection sys_collation_connection("collation_connection");
sys_var_bool_ptr sys_concurrent_insert("concurrent_insert",
@@ -362,7 +361,10 @@ sys_var *sys_variables[]=
&sys_binlog_cache_size,
&sys_buffer_results,
&sys_bulk_insert_buff_size,
+ &sys_character_set_server,
+ &sys_character_set_database,
&sys_character_set_client,
+ &sys_character_set_connection,
&sys_character_set_results,
&sys_collation_connection,
&sys_concurrent_insert,
@@ -481,9 +483,11 @@ struct show_var_st init_vars[]= {
#endif
{sys_binlog_cache_size.name,(char*) &sys_binlog_cache_size, SHOW_SYS},
{sys_bulk_insert_buff_size.name,(char*) &sys_bulk_insert_buff_size,SHOW_SYS},
- {sys_charset.name, (char*) &sys_charset, SHOW_SYS},
+ {sys_character_set_server.name, (char*) &sys_character_set_server,SHOW_SYS},
{sys_charset_system.name, (char*) &sys_charset_system, SHOW_SYS},
+ {sys_character_set_database.name, (char*) &sys_character_set_database,SHOW_SYS},
{sys_character_set_client.name,(char*) &sys_character_set_client,SHOW_SYS},
+ {sys_character_set_connection.name,(char*) &sys_character_set_connection,SHOW_SYS},
{sys_character_set_results.name,(char*) &sys_character_set_results, SHOW_SYS},
{sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS},
{sys_concurrent_insert.name,(char*) &sys_concurrent_insert, SHOW_SYS},
@@ -1276,9 +1280,15 @@ bool sys_var_character_set::check(THD *thd, set_var *var)
String str(buff,sizeof(buff), system_charset_info), *res;
if (!(res=var->value->val_str(&str)))
- res= &empty_string;
-
- if (!(tmp=get_charset_by_csname(res->c_ptr(),MY_CS_PRIMARY,MYF(0))) &&
+ {
+ if (!nullable)
+ {
+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "NULL");
+ return 1;
+ }
+ tmp= NULL;
+ }
+ else if (!(tmp=get_charset_by_csname(res->c_ptr(),MY_CS_PRIMARY,MYF(0))) &&
!(tmp=get_old_charset_by_name(res->c_ptr())))
{
my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), res->c_ptr());
@@ -1288,23 +1298,44 @@ bool sys_var_character_set::check(THD *thd, set_var *var)
return 0;
}
-bool sys_var_character_set_client::update(THD *thd, set_var *var)
+bool sys_var_character_set::update(THD *thd, set_var *var)
{
- if (var->type == OPT_GLOBAL)
- global_system_variables.character_set_client= var->save_result.charset;
- else
- thd->variables.character_set_client= var->save_result.charset;
+ ci_ptr(thd,var->type)[0]= var->save_result.charset;
return 0;
}
-byte *sys_var_character_set_client::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_character_set::value_ptr(THD *thd, enum_var_type type)
{
- CHARSET_INFO *cs= ((type == OPT_GLOBAL) ?
- global_system_variables.character_set_client :
- thd->variables.character_set_client);
+ CHARSET_INFO *cs= ci_ptr(thd,type)[0];
return cs ? (byte*) cs->csname : (byte*) "NULL";
}
+
+CHARSET_INFO ** sys_var_character_set_connection::ci_ptr(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ return &global_system_variables.collation_connection;
+ else
+ return &thd->variables.collation_connection;
+}
+
+void sys_var_character_set_connection::set_default(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ global_system_variables.collation_connection= default_charset_info;
+ else
+ thd->variables.collation_connection= global_system_variables.collation_connection;
+}
+
+
+CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ return &global_system_variables.character_set_client;
+ else
+ return &thd->variables.character_set_client;
+}
+
void sys_var_character_set_client::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
@@ -1313,58 +1344,81 @@ void sys_var_character_set_client::set_default(THD *thd, enum_var_type type)
thd->variables.character_set_client= global_system_variables.character_set_client;
}
-
-bool sys_var_collation_connection::update(THD *thd, set_var *var)
+CHARSET_INFO ** sys_var_character_set_results::ci_ptr(THD *thd, enum_var_type type)
{
- if (var->type == OPT_GLOBAL)
- global_system_variables.collation_connection= var->save_result.charset;
+ if (type == OPT_GLOBAL)
+ return &global_system_variables.character_set_results;
else
- thd->variables.collation_connection= var->save_result.charset;
- return 0;
+ return &thd->variables.character_set_results;
}
-byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type)
+void sys_var_character_set_results::set_default(THD *thd, enum_var_type type)
{
- CHARSET_INFO *cs= ((type == OPT_GLOBAL) ?
- global_system_variables.collation_connection :
- thd->variables.collation_connection);
- return cs ? (byte*) cs->name : (byte*) "NULL";
+ if (type == OPT_GLOBAL)
+ global_system_variables.character_set_results= default_charset_info;
+ else
+ thd->variables.character_set_results= global_system_variables.character_set_results;
}
-void sys_var_collation_connection::set_default(THD *thd, enum_var_type type)
+CHARSET_INFO ** sys_var_character_set_server::ci_ptr(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ return &global_system_variables.character_set_server;
+ else
+ return &thd->variables.character_set_server;
+}
+
+void sys_var_character_set_server::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
- global_system_variables.collation_connection= default_charset_info;
+ global_system_variables.character_set_server= default_charset_info;
else
- thd->variables.collation_connection= global_system_variables.collation_connection;
+ thd->variables.character_set_server= global_system_variables.character_set_server;
+}
+
+CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ return &global_system_variables.character_set_database;
+ else
+ return &thd->variables.character_set_database;
}
-bool sys_var_character_set_results::update(THD *thd, set_var *var)
+void sys_var_character_set_database::set_default(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ global_system_variables.character_set_database= default_charset_info;
+ else
+ thd->variables.character_set_database= thd->db_charset;
+}
+
+bool sys_var_collation_connection::update(THD *thd, set_var *var)
{
if (var->type == OPT_GLOBAL)
- global_system_variables.character_set_results= var->save_result.charset;
+ global_system_variables.collation_connection= var->save_result.charset;
else
- thd->variables.character_set_results= var->save_result.charset;
+ thd->variables.collation_connection= var->save_result.charset;
return 0;
}
-byte *sys_var_character_set_results::value_ptr(THD *thd, enum_var_type type)
+byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type)
{
CHARSET_INFO *cs= ((type == OPT_GLOBAL) ?
- global_system_variables.character_set_results :
- thd->variables.character_set_results);
- return cs ? (byte*) cs->csname : (byte*) "NULL";
+ global_system_variables.collation_connection :
+ thd->variables.collation_connection);
+ return cs ? (byte*) cs->name : (byte*) "NULL";
}
-void sys_var_character_set_results::set_default(THD *thd, enum_var_type type)
+void sys_var_collation_connection::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
- global_system_variables.character_set_results= NULL;
+ global_system_variables.collation_connection= default_charset_info;
else
- thd->variables.character_set_results= global_system_variables.character_set_results;
+ thd->variables.collation_connection= global_system_variables.collation_connection;
}
+
/*****************************************************************************
Functions to handle SET NAMES and SET CHARACTER SET
*****************************************************************************/
diff --git a/sql/set_var.h b/sql/set_var.h
index f501426e553..d016c3a7085 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -433,7 +433,9 @@ SHOW_TYPE type() { return SHOW_CHAR; }
class sys_var_character_set :public sys_var_thd
{
public:
- sys_var_character_set(const char *name_arg) :sys_var_thd(name_arg) {}
+ bool nullable;
+ sys_var_character_set(const char *name_arg) :sys_var_thd(name_arg)
+ { nullable= 0; }
bool check(THD *thd, set_var *var);
SHOW_TYPE type() { return SHOW_CHAR; }
bool check_update_type(Item_result type)
@@ -441,7 +443,10 @@ SHOW_TYPE type() { return SHOW_CHAR; }
return type != STRING_RESULT; /* Only accept strings */
}
bool check_default(enum_var_type type) { return 0; }
+ bool update(THD *thd, set_var *var);
+ byte *value_ptr(THD *thd, enum_var_type type);
virtual void set_default(THD *thd, enum_var_type type)= 0;
+ virtual CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type)= 0;
};
class sys_var_character_set_client :public sys_var_character_set
@@ -449,19 +454,45 @@ class sys_var_character_set_client :public sys_var_character_set
public:
sys_var_character_set_client(const char *name_arg) :
sys_var_character_set(name_arg) {}
- bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
- byte *value_ptr(THD *thd, enum_var_type type);
+ CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type);
};
class sys_var_character_set_results :public sys_var_character_set
{
public:
sys_var_character_set_results(const char *name_arg) :
+ sys_var_character_set(name_arg)
+ { nullable= 1; }
+ void set_default(THD *thd, enum_var_type type);
+ CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type);
+};
+
+class sys_var_character_set_server :public sys_var_character_set
+{
+public:
+ sys_var_character_set_server(const char *name_arg) :
sys_var_character_set(name_arg) {}
- bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
- byte *value_ptr(THD *thd, enum_var_type type);
+ CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type);
+};
+
+class sys_var_character_set_database :public sys_var_character_set
+{
+public:
+ sys_var_character_set_database(const char *name_arg) :
+ sys_var_character_set(name_arg) {}
+ void set_default(THD *thd, enum_var_type type);
+ CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type);
+};
+
+class sys_var_character_set_connection :public sys_var_character_set
+{
+public:
+ sys_var_character_set_connection(const char *name_arg) :
+ sys_var_character_set(name_arg) {}
+ void set_default(THD *thd, enum_var_type type);
+ CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type);
};
class sys_var_collation_connection :public sys_var_collation
@@ -606,6 +637,5 @@ sys_var *find_sys_var(const char *str, uint length=0);
int sql_set_variables(THD *thd, List<set_var_base> *var_list);
void fix_delay_key_write(THD *thd, enum_var_type type);
-extern sys_var_str sys_charset;
extern sys_var_str sys_charset_system;
CHARSET_INFO *get_old_charset_by_name(const char *old_name);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index eeaf560693e..81c620fdaf4 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2311,7 +2311,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
DBUG_ENTER("mysql_create_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
- create_info.table_charset= thd->db_charset;
+ create_info.table_charset= thd->variables.character_set_database;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
@@ -2328,7 +2328,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
DBUG_ENTER("mysql_drop_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
- create_info.table_charset= thd->db_charset;
+ create_info.table_charset= thd->variables.character_set_database;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 9f6edd629ca..fb088b602b1 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -109,7 +109,7 @@ THD::THD():user_time(0), is_fatal_error(0),
file_id = 0;
cond_count=0;
warn_id= 0;
- db_charset=default_charset_info;
+ db_charset= global_system_variables.character_set_database;
mysys_var=0;
#ifndef DBUG_OFF
dbug_sentry=THD_SENTRY_MAGIC;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 00b3b9f8444..157a58cb8fa 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -386,6 +386,8 @@ struct system_variables
my_bool low_priority_updates;
my_bool new_mode;
+ CHARSET_INFO *character_set_server;
+ CHARSET_INFO *character_set_database;
CHARSET_INFO *character_set_client;
CHARSET_INFO *character_set_results;
CHARSET_INFO *collation_connection;
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index e0a592d2450..f8cf1eee0c5 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -51,7 +51,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
1 Could not create file or write to it. Error sent through my_error()
*/
-static bool write_db_opt(const char *path, HA_CREATE_INFO *create)
+static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
{
register File file;
char buf[256]; // Should be enough for one option
@@ -61,8 +61,9 @@ static bool write_db_opt(const char *path, HA_CREATE_INFO *create)
{
ulong length;
CHARSET_INFO *cs= (create && create->table_charset) ?
- create->table_charset : default_charset_info;
- length= my_sprintf(buf,(buf, "default-character-set=%s\n", cs->name));
+ create->table_charset :
+ thd->variables.character_set_database;
+ length= my_sprintf(buf,(buf, "default-character-set=%s\ndefault-collation=%s\n", cs->csname,cs->name));
/* Error is written by my_write */
if (!my_write(file,(byte*) buf, length, MYF(MY_NABP+MY_WME)))
@@ -89,7 +90,7 @@ static bool write_db_opt(const char *path, HA_CREATE_INFO *create)
*/
-static bool load_db_opt(const char *path, HA_CREATE_INFO *create)
+static bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
{
File file;
char buf[256];
@@ -98,7 +99,7 @@ static bool load_db_opt(const char *path, HA_CREATE_INFO *create)
uint nbytes;
bzero((char*) create,sizeof(*create));
- create->table_charset= default_charset_info;
+ create->table_charset= global_system_variables.character_set_database;
if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) >= 0)
{
IO_CACHE cache;
@@ -115,12 +116,18 @@ static bool load_db_opt(const char *path, HA_CREATE_INFO *create)
{
if (!strncmp(buf,"default-character-set", (pos-buf)))
{
- if (strcmp(pos+1,"DEFAULT"))
+ if (!(create->table_charset=get_charset_by_csname(pos+1,
+ MY_CS_PRIMARY,
+ MYF(0))))
{
- if (!(create->table_charset=get_charset_by_name(pos+1, MYF(0))))
- {
- sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1);
- }
+ sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1);
+ }
+ }
+ else if (!strncmp(buf,"default-collation", (pos-buf)))
+ {
+ if (!(create->table_charset=get_charset_by_name(pos+1, MYF(0))))
+ {
+ sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1);
}
}
}
@@ -197,7 +204,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
unpack_dirname(path, path);
strcat(path,MY_DB_OPT_FILE);
- if (write_db_opt(path, create_info))
+ if (write_db_opt(thd, path, create_info))
{
/*
Could not create options file.
@@ -270,7 +277,7 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
/* Check directory */
(void)sprintf(path,"%s/%s/%s", mysql_data_home, db, MY_DB_OPT_FILE);
fn_format(path, path, "", "", MYF(MY_UNPACK_FILENAME));
- if ((error=write_db_opt(path, create_info)))
+ if ((error=write_db_opt(thd, path, create_info)))
goto exit;
/*
@@ -280,7 +287,9 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
if (thd->db && !strcmp(thd->db,db))
{
thd->db_charset= (create_info && create_info->table_charset) ?
- create_info->table_charset : default_charset_info;
+ create_info->table_charset :
+ global_system_variables.character_set_database;
+ thd->variables.character_set_database= thd->db_charset;
}
mysql_update_log.write(thd,thd->query, thd->query_length);
@@ -615,8 +624,11 @@ bool mysql_change_db(THD *thd, const char *name)
thd->db_access=db_access;
strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
- load_db_opt(path, &create);
- thd->db_charset= create.table_charset ? create.table_charset : default_charset_info;
+ load_db_opt(thd, path, &create);
+ thd->db_charset= create.table_charset ?
+ create.table_charset :
+ global_system_variables.character_set_database;
+ thd->variables.character_set_database= thd->db_charset;
DBUG_RETURN(0);
}
@@ -674,7 +686,7 @@ int mysqld_show_create_db(THD *thd, char *dbname,
if (found_libchar)
path[length-1]= FN_LIBCHAR;
strmov(path+length, MY_DB_OPT_FILE);
- load_db_opt(path, &create);
+ load_db_opt(thd, path, &create);
List<Item> field_list;
field_list.push_back(new Item_empty_string("Database",NAME_LEN));
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 36c7ef87b17..2925141d331 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -26,74 +26,155 @@ struct st_find_field
static struct st_find_field init_used_fields[]=
{
- { "help_topic", "name", 0},
- { "help_topic","description", 0},
- { "help_topic","example", 0},
- { "help_topic", "help_topic_id", 0},
- { "help_category","name", 0},
- { "help_category","help_category_id", 0},
- { "help_relation","help_topic_id", 0},
- { "help_relation","help_category_id", 0}
+ { "help_topic", "help_topic_id", 0},
+ { "help_topic", "name", 0},
+ { "help_topic", "help_category_id", 0},
+ { "help_topic", "description", 0},
+ { "help_topic", "example", 0},
+
+ { "help_category", "help_category_id", 0},
+ { "help_category", "parent_category_id", 0},
+ { "help_category", "name", 0},
+
+ { "help_keyword", "help_keyword_id", 0},
+ { "help_keyword", "name", 0},
+
+ { "help_relation", "help_topic_id", 0},
+ { "help_relation", "help_keyword_id", 0}
};
enum enum_used_fields
{
- help_topic_name=0, help_topic_description, help_topic_example,
- help_topic_help_topic_id,
- help_category_name, help_category_help_category_id,
- help_relation_help_topic_id, help_relation_help_category_id
+ help_topic_help_topic_id= 0,
+ help_topic_name,
+ help_topic_help_category_id,
+ help_topic_description,
+ help_topic_example,
+
+ help_category_help_category_id,
+ help_category_parent_category_id,
+ help_category_name,
+
+ help_keyword_help_keyword_id,
+ help_keyword_name,
+
+ help_relation_help_topic_id,
+ help_relation_help_keyword_id
};
/*
- Fill local used field structure with pointer to fields */
+ Fill st_find_field structure with pointers to fields
+
+ SYNOPSIS
+ init_fields()
+ thd Thread handler
+ tables list of all tables for fields
+ find_fields array of structures
+ count size of previous array
+
+ RETURN VALUES
+ 0 all ok
+ 1 one of the fileds didn't finded
+*/
static bool init_fields(THD *thd, TABLE_LIST *tables,
- struct st_find_field *find_field,
- uint count)
+ struct st_find_field *find_fields, uint count)
{
- for (; count-- ; find_field++)
+ DBUG_ENTER("init_fields");
+ for (; count-- ; find_fields++)
{
TABLE_LIST *not_used;
/* We have to use 'new' here as field will be re_linked on free */
- Item_field *field= new Item_field("mysql", find_field->table_name,
- find_field->field_name);
- if (!(find_field->field= find_field_in_tables(thd, field, tables,
- &not_used,
- TRUE)))
- return 1;
+ Item_field *field= new Item_field("mysql", find_fields->table_name,
+ find_fields->field_name);
+ if (!(find_fields->field= find_field_in_tables(thd, field, tables,
+ &not_used, TRUE)))
+ DBUG_RETURN(1);
}
- return 0;
+ DBUG_RETURN(0);
}
+/*
+
+ Returns variants of found topic for help (if it is just single topic,
+ returns description and example, or else returns only names..)
+
+ SYNOPSIS
+ memorize_variant_topic()
+
+ thd Thread handler
+ topics Table of topics
+ count number of alredy found topics
+ find_fields Filled array of information for work with fields
+
+ RETURN VALUES
+ names array of names of found topics (out)
-#define help_charset &my_charset_latin1
+ name name of found topic (out)
+ description description of found topic (out)
+ example example for found topic (out)
+
+ NOTE
+ Field 'names' is set only if more than one topic is found.
+ Fields 'name', 'description', 'example' are set only if
+ found exactly one topic.
+*/
+
+void memorize_variant_topic(THD *thd, TABLE *topics, int count,
+ struct st_find_field *find_fields,
+ List<String> *names,
+ String *name, String *description, String *example)
+{
+ DBUG_ENTER("memorize_variant_topic");
+ MEM_ROOT *mem_root= &thd->mem_root;
+ if (count==0)
+ {
+ get_field(mem_root,find_fields[help_topic_name].field, name);
+ get_field(mem_root,find_fields[help_topic_description].field, description);
+ get_field(mem_root,find_fields[help_topic_example].field, example);
+ }
+ else
+ {
+ if (count==1)
+ names->push_back(name);
+ String *new_name= new String;
+ get_field(mem_root,find_fields[help_topic_name].field,new_name);
+ names->push_back(new_name);
+ }
+ DBUG_VOID_RETURN;
+}
/*
Look for topics by mask
SYNOPSIS
search_topics()
- thd Thread handler
- topics Table of topic
- select Function to test for if matching help topic.
- Normally 'help_topic.name like 'bit%'
- pfname Pointer to Field structure for field "name"
- names List of founded topic's names (out)
- name Name of founded topic (out),
- Only set if founded exactly one topic)
- description Description of founded topic (out)
- Only set if founded exactly one topic.
- example Example for founded topic (out)
- Only if founded exactly one topic.
+ thd Thread handler
+ topics Table of topics
+ find_fields Filled array of info for fields
+ select Function to test for matching help topic.
+ Normally 'help_topic.name like 'bit%'
+
RETURN VALUES
- # number of topics founded
+ # number of topics found
+
+ names array of names of found topics (out)
+ name name of found topic (out)
+ description description of found topic (out)
+ example example for found topic (out)
+
+ NOTE
+ Field 'names' is set only if more than one topic was found.
+ Fields 'name', 'description', 'example' are set only if
+ exactly one topic was found.
+
*/
-int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_field,
- SQL_SELECT *select, List<char> *names,
- char **name, char **description, char **example)
+int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_fields,
+ SQL_SELECT *select, List<String> *names,
+ String *name, String *description, String *example)
{
- DBUG_ENTER("search_functions");
+ DBUG_ENTER("search_topics");
int count= 0;
READ_RECORD read_record_info;
@@ -102,139 +183,93 @@ int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_field,
{
if (!select->cond->val_int()) // Dosn't match like
continue;
-
- char *lname= get_field(&thd->mem_root, find_field[help_topic_name].field);
+ memorize_variant_topic(thd,topics,count,find_fields,
+ names,name,description,example);
count++;
- if (count > 2)
- {
- names->push_back(lname);
- }
- else if (count == 1)
- {
- *description= get_field(&thd->mem_root,
- find_field[help_topic_description].field);
- *example= get_field(&thd->mem_root,
- find_field[help_topic_example].field);
- *name= lname;
- }
- else
- {
- names->push_back(*name);
- names->push_back(lname);
- *name= 0;
- *description= 0;
- *example= 0;
- }
}
end_read_record(&read_record_info);
+
DBUG_RETURN(count);
}
/*
- Look for categories by mask
+ Look for keyword by mask
SYNOPSIS
- search_categories()
- thd THD for init_read_record
- categories Table of categories
- select Function to test for if matching help topic.
- Normally 'help_topic.name like 'bit%'
- names List of founded topic's names (out)
- res_id Primary index of founded category (only if
- founded exactly one category)
+ search_keyword()
+ thd Thread handler
+ keywords Table of keywords
+ find_fields Filled array of info for fields
+ select Function to test for matching keyword.
+ Normally 'help_keyword.name like 'bit%'
+
+ key_id help_keyword_if of found topics (out)
RETURN VALUES
- # Number of categories founded
+ 0 didn't find any topics matching the mask
+ 1 found exactly one topic matching the mask
+ 2 found more then one topic matching the mask
*/
-int search_categories(THD *thd, TABLE *categories,
- struct st_find_field *find_fields,
- SQL_SELECT *select, List<char> *names, int16 *res_id)
+int search_keyword(THD *thd, TABLE *keywords, struct st_find_field *find_fields,
+ SQL_SELECT *select, int *key_id)
{
- Field *pfname= find_fields[help_category_name].field;
- DBUG_ENTER("search_categories");
+ DBUG_ENTER("search_keyword");
int count= 0;
- READ_RECORD read_record_info;
- init_read_record(&read_record_info, thd, categories, select,1,0);
- while (!read_record_info.read_record(&read_record_info))
+ READ_RECORD read_record_info;
+ init_read_record(&read_record_info, thd, keywords, select,1,0);
+ while (!read_record_info.read_record(&read_record_info) && count<2)
{
- if (select && !select->cond->val_int())
+ if (!select->cond->val_int()) // Dosn't match like
continue;
- char *lname= get_field(&thd->mem_root,pfname);
- if (++count == 1 && res_id)
- {
- Field *pcat_id= find_fields[help_category_help_category_id].field;
- *res_id= (int16) pcat_id->val_int();
- }
- names->push_back(lname);
+
+ *key_id= find_fields[help_keyword_help_keyword_id].field->val_int();
+
+ count++;
}
end_read_record(&read_record_info);
-
+
DBUG_RETURN(count);
}
-
/*
- Send to client rows in format:
- column1 : <name>
- column2 : <is_it_category>
+ Look for all topics with keyword
SYNOPSIS
- send_variant_2_list()
- protocol Protocol for sending
- names List of names
- cat Value of the column <is_it_category>
+ get_topics_for_keyword()
+ thd Thread handler
+ topics Table of topics
+ relations Table of m:m relation "topic/keyword"
+ find_fields Filled array of info for fields
+ key_id Primary index to use to find for keyword
RETURN VALUES
- -1 Writing fail
- 0 Data was successefully send
-*/
-
-int send_variant_2_list(Protocol *protocol, List<char> *names,
- const char *cat)
-{
- DBUG_ENTER("send_names");
-
- List_iterator<char> it(*names);
- const char *cur_name;
- while ((cur_name= it++))
- {
- protocol->prepare_for_resend();
- protocol->store(cur_name, system_charset_info);
- protocol->store(cat, system_charset_info);
- if (protocol->write())
- DBUG_RETURN(-1);
- }
- DBUG_RETURN(0);
-}
+ # number of topics found
+ names array of name of found topics (out)
-/*
- Look for all topics of category
+ name name of found topic (out)
+ description description of found topic (out)
+ example example for found topic (out)
- SYNOPSIS
- get_all_topics_for_category()
- thd Thread handler
- topics Table of topics
- relations Table of m:m relation "topic/category"
- cat_id Primary index looked for category
- res List of founded topic's names (out)
-
- RETURN VALUES
- -1 corrupt database
- 0 succesefull
+ NOTE
+ Field 'names' is set only if more than one topic was found.
+ Fields 'name', 'description', 'example' are set only if
+ exactly one topic was found.
*/
-int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations,
- struct st_find_field *find_fields,
- int16 cat_id, List<char> *res)
+int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
+ struct st_find_field *find_fields, int16 key_id,
+ List<String> *names,
+ String *name, String *description, String *example)
{
- char buff[8]; // Max int length
- DBUG_ENTER("get_all_topics_for_category");
-
+ char buff[8]; // Max int length
+ int count= 0;
int iindex_topic, iindex_relations;
- Field *rtopic_id, *rcat_id;
+ Field *rtopic_id, *rkey_id;
+
+ DBUG_ENTER("get_topics_for_keyword");
if ((iindex_topic= find_type((char*) "PRIMARY",
&topics->keynames, 1+2)-1)<0 ||
@@ -245,37 +280,156 @@ int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations,
DBUG_RETURN(-1);
}
rtopic_id= find_fields[help_relation_help_topic_id].field;
- rcat_id= find_fields[help_relation_help_category_id].field;
+ rkey_id= find_fields[help_relation_help_keyword_id].field;
topics->file->index_init(iindex_topic);
relations->file->index_init(iindex_relations);
- rcat_id->store((longlong) cat_id);
- rcat_id->get_key_image(buff, rcat_id->pack_length(), help_charset,
+ rkey_id->store((longlong) key_id);
+ rkey_id->get_key_image(buff, rkey_id->pack_length(), rkey_id->charset(),
Field::itRAW);
int key_res= relations->file->index_read(relations->record[0],
- (byte *)buff, rcat_id->pack_length(),
+ (byte *)buff, rkey_id->pack_length(),
HA_READ_KEY_EXACT);
- for ( ; !key_res && cat_id == (int16) rcat_id->val_int() ;
+ for ( ;
+ !key_res && key_id == (int16) rkey_id->val_int() ;
key_res= relations->file->index_next(relations->record[0]))
{
char topic_id_buff[8];
longlong topic_id= rtopic_id->val_int();
Field *field= find_fields[help_topic_help_topic_id].field;
field->store((longlong) topic_id);
- field->get_key_image(topic_id_buff, field->pack_length(), help_charset,
+ field->get_key_image(topic_id_buff, field->pack_length(), field->charset(),
Field::itRAW);
-
+
if (!topics->file->index_read(topics->record[0], (byte *)topic_id_buff,
- field->pack_length(),
- HA_READ_KEY_EXACT))
- res->push_back(get_field(&thd->mem_root,
- find_fields[help_topic_name].field));
+ field->pack_length(), HA_READ_KEY_EXACT))
+ {
+ memorize_variant_topic(thd,topics,count,find_fields,
+ names,name,description,example);
+ count++;
+ }
}
- DBUG_RETURN(0);
+ DBUG_RETURN(count);
+}
+
+/*
+ Look for topics with keyword by mask
+
+ SYNOPSIS
+ search_topics_by_keyword()
+ thd Thread handler
+ keywords Table of keywords
+ topics Table of topics
+ relations Table of m:m relation "topic/keyword"
+ find_fields Filled array of info for fields
+ select Function to test for if matching help keyword.
+ Normally 'help_keyword.name like 'bit%'
+
+ RETURN VALUES
+ # number of topics found
+
+ names array of name of found topics (out)
+
+ name name of found topic (out)
+ description description of found topic (out)
+ example example for found topic (out)
+
+ NOTE
+ Field 'names' is set only if more than one topic was found.
+ Fields 'name', 'description', 'example' are set only if
+ exactly one topic was found.
+*/
+
+int search_topics_by_keyword(THD *thd,
+ TABLE *keywords, TABLE *topics, TABLE *relations,
+ struct st_find_field *find_fields,
+ SQL_SELECT *select, List<String> *names,
+ String *name, String *description, String *example)
+{
+ int key_id;
+ return search_keyword(thd,keywords,find_fields,select,&key_id)!=1
+ ? 0 : get_topics_for_keyword(thd,topics,relations,find_fields,key_id,
+ names,name,description,example);
+}
+
+/*
+ Look for categories by mask
+
+ SYNOPSIS
+ search_categories()
+ thd THD for init_read_record
+ categories Table of categories
+ find_fields Filled array of info for fields
+ select Function to test for if matching help topic.
+ Normally 'help_vategory.name like 'bit%'
+ names List of found categories names (out)
+ res_id Primary index of found category (only if
+ found exactly one category)
+
+ RETURN VALUES
+ # Number of categories found
+*/
+
+int search_categories(THD *thd, TABLE *categories,
+ struct st_find_field *find_fields,
+ SQL_SELECT *select, List<String> *names, int16 *res_id)
+{
+ Field *pfname= find_fields[help_category_name].field;
+ Field *pcat_id= find_fields[help_category_help_category_id].field;
+ int count= 0;
+ READ_RECORD read_record_info;
+
+ DBUG_ENTER("search_categories");
+
+ init_read_record(&read_record_info, thd, categories, select,1,0);
+ while (!read_record_info.read_record(&read_record_info))
+ {
+ if (select && !select->cond->val_int())
+ continue;
+ String *lname= new String;
+ get_field(&thd->mem_root,pfname,lname);
+ if (++count == 1 && res_id)
+ *res_id= (int16) pcat_id->val_int();
+ names->push_back(lname);
+ }
+ end_read_record(&read_record_info);
+
+ DBUG_RETURN(count);
}
+/*
+ Look for all topics or subcategories of category
+
+ SYNOPSIS
+ get_all_items_for_category()
+ thd Thread handler
+ items Table of items
+ pfname Field "name" in items
+ select "where" part of query..
+ res list of finded names
+*/
+
+void get_all_items_for_category(THD *thd, TABLE *items, Field *pfname,
+ SQL_SELECT *select, List<String> *res)
+{
+ DBUG_ENTER("get_all_items_for_category");
+
+ READ_RECORD read_record_info;
+ init_read_record(&read_record_info, thd, items, select,1,0);
+ while (!read_record_info.read_record(&read_record_info))
+ {
+ if (!select->cond->val_int())
+ continue;
+ String *name= new String();
+ get_field(&thd->mem_root,pfname,name);
+ res->push_back(name);
+ }
+ end_read_record(&read_record_info);
+
+ DBUG_VOID_RETURN;
+}
/*
Send to client answer for help request
@@ -284,17 +438,16 @@ int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations,
send_answer_1()
protocol - protocol for sending
s1 - value of column "Name"
- s2 - value of column "Category"
- s3 - value of column "Description"
- s4 - value of column "Example"
+ s2 - value of column "Description"
+ s3 - value of column "Example"
IMPLEMENTATION
Format used:
- +----------+---------+------------+------------+
- |Name: |Category |Description |Example |
- +----------+---------+------------+------------+
- |String(64)|String(1)|String(1000)|String(1000)|
- +----------+---------+------------+------------+
+ +----------+------------+------------+
+ |name |description |example |
+ +----------+------------+------------+
+ |String(64)|String(1000)|String(1000)|
+ +----------+------------+------------+
with exactly one row!
RETURN VALUES
@@ -303,24 +456,21 @@ int get_all_topics_for_category(THD *thd, TABLE *topics, TABLE *relations,
0 Successeful send
*/
-int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
- const char *s3, const char *s4)
+int send_answer_1(Protocol *protocol, String *s1, String *s2, String *s3)
{
DBUG_ENTER("send_answer_1");
List<Item> field_list;
- field_list.push_back(new Item_empty_string("Name",64));
- field_list.push_back(new Item_empty_string("Category",1));
- field_list.push_back(new Item_empty_string("Description",1000));
- field_list.push_back(new Item_empty_string("Example",1000));
+ field_list.push_back(new Item_empty_string("name",64));
+ field_list.push_back(new Item_empty_string("description",1000));
+ field_list.push_back(new Item_empty_string("example",1000));
if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
protocol->prepare_for_resend();
- protocol->store(s1, system_charset_info);
- protocol->store(s2, system_charset_info);
- protocol->store(s3, system_charset_info);
- protocol->store(s4, system_charset_info);
+ protocol->store(s1);
+ protocol->store(s2);
+ protocol->store(s3);
if (protocol->write())
DBUG_RETURN(-1);
DBUG_RETURN(0);
@@ -332,28 +482,151 @@ int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
SYNOPSIS
send_header_2()
- protocol - protocol for sending
+ protocol - protocol for sending
+ is_it_category - need column 'source_category_name'
IMPLEMENTATION
- +----------+---------+
- |Name: |Category |
- +----------+---------+
- |String(64)|String(1)|
- +----------+---------+
+ +- -+
+ |+-------------------- | +----------+--------------+
+ ||source_category_name | |name |is_it_category|
+ |+-------------------- | +----------+--------------+
+ ||String(64) | |String(64)|String(1) |
+ |+-------------------- | +----------+--------------+
+ +- -+
RETURN VALUES
result of protocol->send_fields
*/
-int send_header_2(Protocol *protocol)
+int send_header_2(Protocol *protocol, bool for_category)
{
- DBUG_ENTER("send_header2");
+ DBUG_ENTER("send_header_2");
List<Item> field_list;
- field_list.push_back(new Item_empty_string("Name",64));
- field_list.push_back(new Item_empty_string("Category",1));
+ if (for_category)
+ field_list.push_back(new Item_empty_string("source_category_name",64));
+ field_list.push_back(new Item_empty_string("name",64));
+ field_list.push_back(new Item_empty_string("is_it_category",1));
DBUG_RETURN(protocol->send_fields(&field_list,1));
}
+/*
+ strcmp for using in qsort
+
+ SYNOPSIS
+ strptrcmp()
+ ptr1 (const void*)&str1
+ ptr2 (const void*)&str2
+
+ RETURN VALUES
+ same as strcmp
+*/
+
+int string_ptr_cmp(const void* ptr1, const void* ptr2)
+{
+ String *str1= *(String**)ptr1;
+ String *str2= *(String**)ptr2;
+ return strcmp(str1->c_ptr(),str2->c_ptr());
+}
+
+/*
+ Send to client rows in format:
+ column1 : <name>
+ column2 : <is_it_category>
+
+ SYNOPSIS
+ send_variant_2_list()
+ protocol Protocol for sending
+ names List of names
+ cat Value of the column <is_it_category>
+ source_name name of category for all items..
+
+ RETURN VALUES
+ -1 Writing fail
+ 0 Data was successefully send
+*/
+
+int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
+ List<String> *names,
+ const char *cat, String *source_name)
+{
+ DBUG_ENTER("send_variant_2_list");
+
+ String **pointers= (String**)alloc_root(mem_root,
+ sizeof(String*)*names->elements);
+ String **pos= pointers;
+
+ List_iterator<String> it(*names);
+ String *cur_name;
+ while ((*pos++= it++));
+
+ qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp);
+
+ String **end= pointers + names->elements;
+ for (String **pos= pointers; pos!=end; pos++)
+ {
+ protocol->prepare_for_resend();
+ if (source_name)
+ protocol->store(source_name);
+ protocol->store(*pos);
+ protocol->store(cat,1,&my_charset_latin1);
+ if (protocol->write())
+ DBUG_RETURN(-1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+/*
+ Prepare simple SQL_SELECT table.* WHERE <Item>
+
+ SYNOPSIS
+ prepare_simple_select()
+ thd Thread handler
+ cond WHERE part of select
+ tables list of tables, used in WHERE
+ table goal table
+
+ error code of error (out)
+
+ RETURN VALUES
+ # created SQL_SELECT
+*/
+
+SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables,
+ TABLE *table, int *error)
+{
+ cond->fix_fields(thd, tables, &cond); // can never fail
+ SQL_SELECT *res= make_select(table,0,0,cond,error);
+ return (*error || (res && res->check_quick(0, HA_POS_ERROR))) ? 0 : res;
+}
+
+/*
+ Prepare simple SQL_SELECT table.* WHERE table.name LIKE mask
+
+ SYNOPSIS
+ prepare_select_for_name()
+ thd Thread handler
+ mask mask for compare with name
+ mlen length of mask
+ tables list of tables, used in WHERE
+ table goal table
+ pfname field "name" in table
+
+ error code of error (out)
+
+ RETURN VALUES
+ # created SQL_SELECT
+*/
+
+SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
+ TABLE_LIST *tables, TABLE *table,
+ Field *pfname, int *error)
+{
+ Item *cond= new Item_func_like(new Item_field(pfname),
+ new Item_string(mask,mlen,pfname->charset()),
+ (char*) "\\");
+ return prepare_simple_select(thd,cond,tables,table,error);
+}
/*
Server-side function 'help'
@@ -371,12 +644,13 @@ int send_header_2(Protocol *protocol)
int mysqld_help(THD *thd, const char *mask)
{
Protocol *protocol= thd->protocol;
- SQL_SELECT *select= 0, *select_cat= 0;
- Item *cond_topic, *cond_cat;
+ SQL_SELECT *select_topics_by_name= 0, *select_keyword_by_name= 0,
+ *select_cat_by_name= 0, *select_topics_by_cat= 0, *select_cat_by_cat= 0,
+ *select_root_cats= 0;
st_find_field used_fields[array_elements(init_used_fields)];
DBUG_ENTER("mysqld_help");
- TABLE_LIST tables[3];
+ TABLE_LIST tables[4];
bzero((gptr)tables,sizeof(tables));
tables[0].alias= tables[0].real_name= (char*) "help_topic";
tables[0].lock_type= TL_READ;
@@ -389,11 +663,17 @@ int mysqld_help(THD *thd, const char *mask)
tables[2].alias= tables[2].real_name= (char*) "help_relation";
tables[2].lock_type= TL_READ;
tables[2].db= (char*) "mysql";
- tables[2].next= 0;
+ tables[2].next= &tables[3];
+ tables[3].alias= tables[3].real_name= (char*) "help_keyword";
+ tables[3].lock_type= TL_READ;
+ tables[3].db= (char*) "mysql";
+ tables[3].next= 0;
- List<char> function_list, categories_list;
- char *name, *description, *example;
+ List<String> topics_list, categories_list, subcategories_list;
+ String name, description, example;
int res, count_topics, count_categories, error;
+ uint mlen= strlen(mask);
+ MEM_ROOT *mem_root= &thd->mem_root;
if (open_and_lock_tables(thd, tables))
{
@@ -409,111 +689,101 @@ int mysqld_help(THD *thd, const char *mask)
goto end;
}
- /* TODO: Find out why these are needed (should not be) */
- tables[0].table->file->init_table_handle_for_HANDLER();
- tables[1].table->file->init_table_handle_for_HANDLER();
- tables[2].table->file->init_table_handle_for_HANDLER();
+ for (size_t i=0; i<sizeof(tables)/sizeof(TABLE_LIST); i++)
+ tables[i].table->file->init_table_handle_for_HANDLER();
- cond_topic= new Item_func_like(new Item_field(used_fields[help_topic_name].
- field),
- new Item_string(mask, strlen(mask),
- help_charset),
- (char*) "\\");
- cond_topic->fix_fields(thd, tables, &cond_topic); // can never fail
- select= make_select(tables[0].table,0,0,cond_topic,&error);
- if (error || (select && select->check_quick(0, HA_POS_ERROR)))
- {
- res= -1;
- goto end;
- }
-
- cond_cat= new Item_func_like(new Item_field(used_fields[help_category_name].
- field),
- new Item_string(mask, strlen(mask),
- help_charset),
- (char*) "\\");
- cond_cat->fix_fields(thd, tables, &cond_topic); // can never fail
- select_cat= make_select(tables[1].table,0,0,cond_cat,&error);
- if (error || (select_cat && select_cat->check_quick(0, HA_POS_ERROR)))
+ if (!(select_topics_by_name=
+ prepare_select_for_name(thd,mask,mlen,tables,tables[0].table,
+ used_fields[help_topic_name].field,&error)) ||
+ !(select_cat_by_name=
+ prepare_select_for_name(thd,mask,mlen,tables,tables[1].table,
+ used_fields[help_category_name].field,&error))||
+ !(select_keyword_by_name=
+ prepare_select_for_name(thd,mask,mlen,tables,tables[3].table,
+ used_fields[help_keyword_name].field,&error)))
{
res= -1;
goto end;
}
res= 1;
- count_topics= search_topics(thd,tables[0].table, used_fields, select,
- &function_list, &name, &description, &example);
+ count_topics= search_topics(thd,tables[0].table,used_fields,
+ select_topics_by_name,&topics_list,
+ &name, &description, &example);
+
+ if (count_topics == 0)
+ count_topics= search_topics_by_keyword(thd,tables[3].table,tables[0].table,
+ tables[2].table,used_fields,
+ select_keyword_by_name,&topics_list,
+ &name,&description,&example);
+
if (count_topics == 0)
{
int16 category_id;
- Item *cond=
- new Item_func_like(new
- Item_field(used_fields[help_category_name].field),
- new Item_string(mask, strlen(mask),
- help_charset),
- (char*) "\\");
- (void) cond->fix_fields(thd, tables, &cond); // can never fail
-
+ Field *cat_cat_id= used_fields[help_category_parent_category_id].field;
count_categories= search_categories(thd, tables[1].table, used_fields,
- select_cat, &categories_list,
- &category_id);
- if (count_categories == 1)
+ select_cat_by_name,
+ &categories_list,&category_id);
+ if (!count_categories)
{
- if (get_all_topics_for_category(thd,tables[0].table,
- tables[2].table, used_fields,
- category_id, &function_list))
- {
- res= -1;
+ if (send_header_2(protocol,false))
goto end;
- }
- List_iterator<char> it(function_list);
- char *cur_topic;
- char buff[1024];
- String example(buff, sizeof(buff), help_charset);
- example.length(0);
-
- while ((cur_topic= it++))
- {
- example.append(cur_topic);
- example.append("\n",1);
- }
- if ((send_answer_1(protocol, categories_list.head(),
- "Y","",example.ptr())))
+ }
+ else if (count_categories > 1)
+ {
+ if (send_header_2(protocol,false) ||
+ send_variant_2_list(mem_root,protocol,&categories_list,"Y",0))
goto end;
}
- else
+ else
{
- if (send_header_2(protocol))
+ Field *topic_cat_id= used_fields[help_topic_help_category_id].field;
+ Item *cond_topic_by_cat= new Item_func_equal(new Item_field(topic_cat_id),
+ new Item_int(category_id));
+ Item *cond_cat_by_cat= new Item_func_equal(new Item_field(cat_cat_id),
+ new Item_int(category_id));
+ if (!(select_topics_by_cat= prepare_simple_select(thd,cond_topic_by_cat,
+ tables,tables[0].table,
+ &error)) ||
+ !(select_cat_by_cat= prepare_simple_select(thd,cond_cat_by_cat,tables,
+ tables[1].table,&error)))
+ {
+ res= -1;
goto end;
- if (count_categories == 0)
- search_categories(thd,tables[1].table, used_fields, (SQL_SELECT *) 0,
- &categories_list, 0);
- if (send_variant_2_list(protocol,&categories_list,"Y"))
+ }
+ get_all_items_for_category(thd,tables[0].table,
+ used_fields[help_topic_name].field,
+ select_topics_by_cat,&topics_list);
+ get_all_items_for_category(thd,tables[1].table,
+ used_fields[help_category_name].field,
+ select_cat_by_cat,&subcategories_list);
+ String *cat= categories_list.head();
+ if (send_header_2(protocol, true) ||
+ send_variant_2_list(mem_root,protocol,&topics_list, "N",cat) ||
+ send_variant_2_list(mem_root,protocol,&subcategories_list,"Y",cat))
goto end;
}
}
else if (count_topics == 1)
{
- if (send_answer_1(protocol,name,"N",description, example))
+ if (send_answer_1(protocol,&name,&description,&example))
goto end;
}
else
{
/* First send header and functions */
- if (send_header_2(protocol) ||
- send_variant_2_list(protocol, &function_list, "N"))
+ if (send_header_2(protocol, false) ||
+ send_variant_2_list(mem_root,protocol, &topics_list, "N", 0))
goto end;
- search_categories(thd, tables[1].table, used_fields, select_cat,
- &categories_list, 0);
+ search_categories(thd, tables[1].table, used_fields,
+ select_cat_by_name,&categories_list, 0);
/* Then send categories */
- if (send_variant_2_list(protocol, &categories_list, "Y"))
+ if (send_variant_2_list(mem_root,protocol, &categories_list, "Y", 0))
goto end;
}
res= 0;
send_eof(thd);
end:
- delete select;
- delete select_cat;
DBUG_RETURN(res);
}
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 758ff88477b..12acfb9b5df 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -215,7 +215,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
info.handle_duplicates=handle_duplicates;
info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
- READ_INFO read_info(file,tot_length,thd->db_charset,
+ READ_INFO read_info(file,tot_length,thd->variables.character_set_database,
*field_term,*ex->line_start, *ex->line_term, *enclosed,
info.escape_char, read_file_from_client, is_fifo);
if (read_info.error)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index b1e0b2dc91d..542b2e0d96e 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -669,9 +669,12 @@ check_connections(THD *thd)
global_system_variables.character_set_client;
thd->variables.collation_connection=
global_system_variables.collation_connection;
+ thd->variables.character_set_results=
+ global_system_variables.character_set_results;
}
else
{
+ thd->variables.character_set_results=
thd->variables.collation_connection=
thd->variables.character_set_client;
}
@@ -1319,7 +1322,8 @@ restore_user:
break;
#else
{
- char *fields;
+ char *fields, *pend;
+ String convname;
TABLE_LIST table_list;
statistic_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status);
bzero((char*) &table_list,sizeof(table_list));
@@ -1329,8 +1333,11 @@ restore_user:
break;
}
thd->free_list=0;
- table_list.alias= table_list.real_name= thd->strdup(packet);
- packet=strend(packet)+1;
+ pend= strend(packet);
+ convname.copy(packet, pend-packet,
+ thd->variables.character_set_client, system_charset_info);
+ table_list.alias= table_list.real_name= convname.c_ptr();
+ packet= pend+1;
// command not cachable => no gap for data base name
if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1)))
break;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index ea3b30d24e8..c53ca0b68a8 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -481,7 +481,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
if (!sql_field->charset)
sql_field->charset = create_info->table_charset ?
- create_info->table_charset : thd->db_charset;
+ create_info->table_charset :
+ thd->variables.character_set_database;
switch (sql_field->sql_type) {
case FIELD_TYPE_BLOB:
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index bab6d05a0e0..1002d06be88 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -848,7 +848,7 @@ create:
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.options=$2 | $4;
lex->create_info.db_type= (enum db_type) lex->thd->variables.table_type;
- lex->create_info.table_charset= thd->db_charset;
+ lex->create_info.table_charset= thd->variables.character_set_database;
lex->name=0;
}
create2
@@ -1536,7 +1536,7 @@ alter:
lex->select_lex.db=lex->name=0;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.db_type= DB_TYPE_DEFAULT;
- lex->create_info.table_charset= thd->db_charset;
+ lex->create_info.table_charset= thd->variables.character_set_database;
lex->create_info.row_type= ROW_TYPE_NOT_USED;
lex->alter_keys_onoff=LEAVE_AS_IS;
lex->simple_alter=1;
@@ -4439,7 +4439,7 @@ option_value:
THD *thd= YYTHD;
LEX *lex= Lex;
$2= $2 ? $2: global_system_variables.character_set_client;
- lex->var_list.push_back(new set_var_collation_client($2,thd->db_charset,$2));
+ lex->var_list.push_back(new set_var_collation_client($2,thd->variables.character_set_database,$2));
}
| NAMES_SYM charset_name_or_default opt_collate
{
@@ -4452,7 +4452,7 @@ option_value:
net_printf(thd,ER_COLLATION_CHARSET_MISMATCH,$3->name,$2->csname);
YYABORT;
}
- lex->var_list.push_back(new set_var_collation_client($3,$3,NULL));
+ lex->var_list.push_back(new set_var_collation_client($3,$3,$3));
}
| PASSWORD equal text_or_password
{
diff --git a/sql/table.cc b/sql/table.cc
index 3aed75c7ac6..908d6807450 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1161,6 +1161,33 @@ rename_file_ext(const char * from,const char * to,const char * ext)
/*
+ Allocate string field in MEM_ROOT and return it as String
+
+ SYNOPSIS
+ get_field()
+ mem MEM_ROOT for allocating
+ field Field for retrieving of string
+ res result String
+
+ RETURN VALUES
+ true string is empty
+ false all ok
+*/
+
+bool get_field(MEM_ROOT *mem, Field *field, String *res)
+{
+ char buff[MAX_FIELD_WIDTH];
+ String str(buff,sizeof(buff),&my_charset_bin);
+ field->val_str(&str,&str);
+ uint length=str.length();
+ if (!length)
+ return true;
+ char *to= strmake_root(mem, str.ptr(), length);
+ res->set(to,length,((Field_str*)field)->charset());
+ return false;
+}
+
+/*
Allocate string field in MEM_ROOT and return it as NULL-terminated string
SYNOPSIS
diff --git a/sql/udf_example.cc b/sql/udf_example.cc
index dfe8177bfce..7f4417bf8fe 100644
--- a/sql/udf_example.cc
+++ b/sql/udf_example.cc
@@ -284,8 +284,8 @@ char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result,
for (n = ntrans + 1, n_end = ntrans + sizeof(ntrans)-2;
word != w_end && n < n_end; word++ )
- if ( my_isalpha ( my_charset_latin1, *word ))
- *n++ = my_toupper ( my_charset_latin1, *word );
+ if ( my_isalpha ( &my_charset_latin1, *word ))
+ *n++ = my_toupper ( &my_charset_latin1, *word );
if ( n == ntrans + 1 ) /* return empty string if 0 bytes */
{