Commit 4b504da0 authored by bar@gw.udmsearch.izhnet.ru's avatar bar@gw.udmsearch.izhnet.ru

Merge abarkov@work.mysql.com:/home/bk/mysql-4.1

into gw.udmsearch.izhnet.ru:/usr/home/bar/mysql-4.1
parents b7d7ce3d 735b27d5
......@@ -58,6 +58,8 @@ Docs/manual_letter.ps
Docs/manual_toc.html
Docs/my_sys.doc
Docs/mysql.info
Docs/mysql.xml
Docs/safe-mysql.xml
Docs/tex.fmt
Docs/texi2dvi.out
INSTALL-SOURCE
......@@ -339,12 +341,15 @@ myisam/mi_test_all
myisam/myisamchk
myisam/myisamlog
myisam/myisampack
myisam/rt_test
myisam/sp_test
myisam/test1.MYD
myisam/test1.MYI
mysql-test/gmon.out
mysql-test/install_test_db
mysql-test/mysql-test-run
mysql-test/r/*.reject
mysql-test/r/rpl000001.eval
mysql-test/r/rpl000002.eval
mysql-test/r/rpl000014.eval
mysql-test/r/rpl000015.eval
......@@ -458,6 +463,3 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
Docs/mysql.xml
mysql-test/r/rpl000001.eval
Docs/safe-mysql.xml
......@@ -53,7 +53,8 @@ sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \
sql_rename.cc sql_repl.cc sql_select.cc sql_do.cc sql_show.cc \
sql_string.cc sql_table.cc sql_test.cc sql_udf.cc \
sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \
unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc
unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc \
spatial.cc gstream.cc
EXTRA_DIST = lib_vio.c
......
......@@ -81,7 +81,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
slave.cc sql_repl.cc sql_union.cc \
mini_client.cc mini_client_errors.c \
stacktrace.c repl_failsafe.h repl_failsafe.cc
stacktrace.c repl_failsafe.h repl_failsafe.cc \
gstream.cc spatial.cc
gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
......
......@@ -3712,7 +3712,7 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
:Field_str(ptr_arg, (1L << min(blob_pack_length,3)*8)-1L,
null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
table_arg),
packlength(blob_pack_length),binary_flag(binary_arg)
packlength(blob_pack_length),binary_flag(binary_arg), geom_flag(true)
{
flags|= BLOB_FLAG;
if (binary_arg)
......@@ -3954,8 +3954,30 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
/* The following is used only when comparing a key */
void Field_blob::get_key_image(char *buff,uint length)
void Field_blob::get_key_image(char *buff,uint length, imagetype type)
{
if(type == itMBR)
{
length-=HA_KEY_BLOB_LENGTH;
ulong blob_length=get_length(ptr);
char *blob;
get_ptr(&blob);
if(!blob_length)
{
return;
}
MBR mbr;
Geometry gobj;
gobj.create_from_wkb(blob,blob_length);
gobj.get_mbr(&mbr);
float8store(buff, mbr.xmin);
float8store(buff+8, mbr.xmax);
float8store(buff+16, mbr.ymin);
float8store(buff+24, mbr.ymax);
return;
}
length-=HA_KEY_BLOB_LENGTH;
uint32 blob_length=get_length(ptr);
char *blob;
......@@ -3977,6 +3999,31 @@ void Field_blob::set_key_image(char *buff,uint length)
Field_blob::store(buff+2,length);
}
void Field_geom::get_key_image(char *buff,uint length, imagetype type)
{
length-=HA_KEY_BLOB_LENGTH;
ulong blob_length=get_length(ptr);
char *blob;
get_ptr(&blob);
memcpy(buff+2,blob,length);
MBR mbr;
Geometry gobj;
gobj.create_from_wkb(blob,blob_length);
gobj.get_mbr(&mbr);
float8store(buff, mbr.xmin);
float8store(buff+8, mbr.xmax);
float8store(buff+16, mbr.ymin);
float8store(buff+24, mbr.ymax);
return;
}
void Field_geom::set_key_image(char *buff,uint length)
{
}
int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length)
{
char *blob1;
......@@ -4606,6 +4653,7 @@ uint32 calc_pack_length(enum_field_types type,uint32 length)
case FIELD_TYPE_LONG_BLOB: return 4+portable_sizeof_char_ptr;
case FIELD_TYPE_SET:
case FIELD_TYPE_ENUM: abort(); return 0; // This shouldn't happen
default: return 0;
}
return 0; // This shouldn't happen
}
......@@ -4652,6 +4700,11 @@ Field *make_field(char *ptr, uint32 field_length,
return new Field_blob(ptr,null_pos,null_bit,
unireg_check, field_name, table,
pack_length,f_is_binary(pack_flag) != 0);
if (f_is_geom(pack_flag))
return new Field_geom(ptr,null_pos,null_bit,
unireg_check, field_name, table,
pack_length,f_is_binary(pack_flag) != 0);
if (interval)
{
if (f_is_enum(pack_flag))
......
......@@ -47,6 +47,9 @@ public:
enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL,
CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD,
BIT_FIELD, TIMESTAMP_FIELD,CAPITALIZE,BLOB_FIELD};
enum imagetype { itRAW, itMBR};
utype unireg_check;
uint32 field_length; // Length of field
uint16 flags;
......@@ -137,7 +140,7 @@ public:
{ memcpy(buff,ptr,length); }
inline void set_image(char *buff,uint length)
{ memcpy(ptr,buff,length); }
virtual void get_key_image(char *buff,uint length)
virtual void get_key_image(char *buff,uint length, imagetype type)
{ get_image(buff,length); }
virtual void set_key_image(char *buff,uint length)
{ set_image(buff,length); }
......@@ -825,6 +828,7 @@ class Field_blob :public Field_str {
uint packlength;
String value; // For temporaries
bool binary_flag;
bool geom_flag;
public:
Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
......@@ -834,7 +838,7 @@ public:
struct st_table *table_arg, bool binary_arg)
:Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, table_arg),
packlength(3),binary_flag(binary_arg)
packlength(3),binary_flag(binary_arg), geom_flag(true)
{
flags|= BLOB_FLAG;
if (binary_arg)
......@@ -881,7 +885,7 @@ public:
store_length(length);
memcpy_fixed(ptr+packlength,&data,sizeof(char*));
}
void get_key_image(char *buff,uint length);
void get_key_image(char *buff,uint length, imagetype type);
void set_key_image(char *buff,uint length);
void sql_type(String &str) const;
inline bool copy()
......@@ -910,6 +914,25 @@ public:
};
class Field_geom :public Field_blob {
public:
Field_geom(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
bool binary_arg)
:Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg, table_arg, blob_pack_length,binary_arg) {}
Field_geom(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
struct st_table *table_arg, bool binary_arg)
:Field_blob(len_arg, maybe_null_arg, field_name_arg,
table_arg, binary_arg) {}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY; }
void get_key_image(char *buff,uint length, imagetype type);
void set_key_image(char *buff,uint length);
};
class Field_enum :public Field_str {
protected:
uint packlength;
......@@ -1059,6 +1082,8 @@ bool test_if_int(const char *str,int length);
#define FIELDFLAG_INTERVAL 256
#define FIELDFLAG_BITFIELD 512 // mangled with dec!
#define FIELDFLAG_BLOB 1024 // mangled with dec!
#define FIELDFLAG_GEOM 2048
#define FIELDFLAG_LEFT_FULLSCREEN 8192
#define FIELDFLAG_RIGHT_FULLSCREEN 16384
#define FIELDFLAG_FORMAT_NUMBER 16384 // predit: ###,,## in output
......@@ -1085,6 +1110,7 @@ bool test_if_int(const char *str,int length);
#define f_is_enum(x) ((x) & FIELDFLAG_INTERVAL)
#define f_is_bitfield(x) ((x) & FIELDFLAG_BITFIELD)
#define f_is_blob(x) (((x) & (FIELDFLAG_BLOB | FIELDFLAG_NUMBER)) == FIELDFLAG_BLOB)
#define f_is_geom(x) ((x) & FIELDFLAG_GEOM)
#define f_is_equ(x) ((x) & (1+2+FIELDFLAG_PACK+31*256))
#define f_settype(x) (((int) x) << FIELDFLAG_PACK_SHIFT)
#define f_maybe_null(x) (x & FIELDFLAG_MAYBE_NULL)
#include "mysql_priv.h"
int GTextReadStream::get_next_toc_type() const
{
const char *cur = m_cur;
while((*cur)&&(strchr(" \t\r\n",*cur)))
{
cur++;
}
if(!(*cur))
{
return eostream;
}
if(((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) || (*cur=='_'))
{
return word;
}
if(((*cur>='0') && (*cur<='9')) || (*cur=='-') || (*cur=='+') || (*cur=='.'))
{
return numeric;
}
if(*cur == '(')
{
return l_bra;
}
if(*cur == ')')
{
return r_bra;
}
if(*cur == ',')
{
return comma;
}
return unknown;
}
const char *GTextReadStream::get_next_word(int *word_len)
{
const char *cur = m_cur;
while((*cur)&&(strchr(" \t\r\n",*cur)))
{
cur++;
}
m_last_text_position = cur;
if(!(*cur))
{
return 0;
}
const char *wd_start = cur;
if(((*cur<'a') || (*cur>'z')) && ((*cur<'A') || (*cur>'Z')) && (*cur!='_'))
{
return NULL;
}
++cur;
while(((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) || (*cur=='_') ||
((*cur>='0') && (*cur<='9')))
{
++cur;
}
*word_len = cur - wd_start;
m_cur = cur;
return wd_start;
}
int GTextReadStream::get_next_number(double *d)
{
const char *cur = m_cur;
while((*cur)&&(strchr(" \t\r\n",*cur)))
{
cur++;
}
m_last_text_position = cur;
if(!(*cur))
{
set_error_msg("Numeric constant expected");
return 1;
}
if(((*cur<'0') || (*cur>'9')) && (*cur!='-') && (*cur!='+') && (*cur!='.'))
{
set_error_msg("Numeric constant expected");
return 1;
}
char *endptr;
*d = strtod(cur, &endptr);
if(endptr)
{
m_cur = endptr;
}
return 0;
}
char GTextReadStream::get_next_symbol()
{
const char *cur = m_cur;
while((*cur)&&(strchr(" \t\r\n",*cur)))
{
cur++;
}
if(!(*cur))
{
return 0;
}
m_cur = cur + 1;
m_last_text_position = cur;
return *cur;
}
void GTextReadStream::set_error_msg(const char *msg)
{
size_t len = strlen(msg);
m_err_msg = (char *)my_realloc(m_err_msg, len + 1, MYF(MY_ALLOW_ZERO_PTR));
memcpy(m_err_msg, msg, len + 1);
}
#ifndef GSTREAM_H
#define GSTREAM_H
#ifdef WITHOUT_MYSQL
#include ".\rtree\myisamdef.h"
#else
#include "mysql_priv.h"
#endif
class GTextReadStream
{
public:
enum TokTypes
{
unknown,
eostream,
word,
numeric,
l_bra,
r_bra,
comma,
};
GTextReadStream(const char *buffer, int size) :
m_cur(buffer), m_limit(buffer + size), m_last_text_position(buffer), m_err_msg(NULL) {}
GTextReadStream() : m_cur(NULL), m_limit(NULL), m_err_msg(NULL) {}
~GTextReadStream()
{
my_free(m_err_msg, MYF(MY_ALLOW_ZERO_PTR));
}
int get_next_toc_type() const;
const char *get_next_word(int *word_len);
int get_next_number(double *d);
char get_next_symbol();
const char *get_last_text_position() const
{
return m_last_text_position;
}
void set_error_msg(const char *msg);
// caller should free this pointer
char *get_error_msg()
{
char *err_msg = m_err_msg;
m_err_msg = NULL;
return err_msg;
}
protected:
const char *m_cur;
const char *m_limit;
const char *m_last_text_position;
char *m_err_msg;
};
#endif
......@@ -28,6 +28,7 @@
#include "../srclib/myisam/myisamdef.h"
#else
#include "../myisam/myisamdef.h"
#include "../myisam/rt_index.h"
#endif
ulong myisam_sort_buffer_size;
......@@ -763,7 +764,7 @@ int ha_myisam::index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
statistic_increment(ha_read_key_count,&LOCK_status);
int error=mi_rkey(file,buf,active_index, key, key_len, find_flag);
int error=mi_rkey(file,buf,active_index, key, key_len, (enum ha_rkey_function)find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
......@@ -772,7 +773,7 @@ int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
statistic_increment(ha_read_key_count,&LOCK_status);
int error=mi_rkey(file,buf,index, key, key_len, find_flag);
int error=mi_rkey(file,buf,index, key, key_len, (enum ha_rkey_function)find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
......@@ -1008,7 +1009,8 @@ int ha_myisam::create(const char *name, register TABLE *table,
pos=table->key_info;
for (i=0; i < table->keys ; i++, pos++)
{
keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT));
keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
keydef[i].key_alg=pos->key_alg; // +BAR
keydef[i].seg=keyseg;
keydef[i].keysegs=pos->key_parts;
for (j=0 ; j < pos->key_parts ; j++)
......
......@@ -357,6 +357,7 @@ public:
};
#include "spatial.h"
#include "item_sum.h"
#include "item_func.h"
#include "item_cmpfunc.h"
......
......@@ -24,6 +24,7 @@
#include "mysql_priv.h"
#include <m_ctype.h>
/*
** Test functions
** These returns 0LL if false and 1LL if true and null if some arg is null
......@@ -1348,3 +1349,83 @@ Item_func_regex::~Item_func_regex()
}
#endif /* USE_REGEX */
/****************************************************************
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(),res1->length()) ||
g2.create_from_wkb(res2->ptr(),res2->length()) ||
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 *wkb=args[0]->val_str(&tmp);
Geometry geom;
int isclosed;
null_value= (!wkb ||
args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,is_closed) ||
geom.is_closed(&isclosed));
return (longlong) isclosed;
}
......@@ -570,3 +570,82 @@ inline Item *and_conds(Item *a,Item *b)
cond->update_used_tables();
return cond;
}
/**************************************************************
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"; }
};
......@@ -413,3 +413,158 @@ Item *create_func_cast(Item *a, Item_cast cast_type)
}
return res;
}
Item *create_func_geometry_from_text(Item* a)
{
return new Item_func_geometry_from_text(a);
}
Item *create_func_as_text(Item* a)
{
return new Item_func_as_text(a);
}
Item *create_func_startpoint(Item* a)
{
return new Item_func_spatial_decomp(a, Item_func::SP_STARTPOINT);
}
Item *create_func_endpoint(Item* a)
{
return new Item_func_spatial_decomp(a, Item_func::SP_ENDPOINT);
}
Item *create_func_exteriorring(Item* a)
{
return new Item_func_spatial_decomp(a, Item_func::SP_EXTERIORRING);
}
Item *create_func_pointn(Item* a, Item* b)
{
return new Item_func_spatial_decomp_n(a,b,Item_func::SP_POINTN);
}
Item *create_func_interiorringn(Item* a, Item* b)
{
return new Item_func_spatial_decomp_n(a,b,Item_func::SP_INTERIORRINGN);
}
Item *create_func_geometryn(Item* a, Item* b)
{
return new Item_func_spatial_decomp_n(a,b,Item_func::SP_GEOMETRYN);
}
Item *create_func_centroid(Item* a)
{
return new Item_func_centroid(a);
}
Item *create_func_envelope(Item* a)
{
return new Item_func_envelope(a);
}
Item *create_func_equals(Item* a, Item* b)
{
return new Item_func_spatial_rel(a, b, Item_func::SP_EQUALS_FUNC);
}
Item *create_func_disjoint(Item* a, Item* b)
{
return new Item_func_spatial_rel(a, b, Item_func::SP_DISJOINT_FUNC);
}
Item *create_func_intersects(Item* a, Item* b)
{
return new Item_func_spatial_rel(a, b, Item_func::SP_INTERSECTS_FUNC);
}
Item *create_func_touches(Item* a, Item* b)
{
return new Item_func_spatial_rel(a, b, Item_func::SP_TOUCHES_FUNC);
}
Item *create_func_crosses(Item* a, Item* b)
{
return new Item_func_spatial_rel(a, b, Item_func::SP_CROSSES_FUNC);
}
Item *create_func_within(Item* a, Item* b)
{
return new Item_func_spatial_rel(a, b, Item_func::SP_WITHIN_FUNC);
}
Item *create_func_contains(Item* a, Item* b)
{
return new Item_func_spatial_rel(a, b, Item_func::SP_CONTAINS_FUNC);
}
Item *create_func_overlaps(Item* a, Item* b)
{
return new Item_func_spatial_rel(a, b, Item_func::SP_OVERLAPS_FUNC);
}
Item *create_func_isempty(Item* a)
{
return new Item_func_isempty(a);
}
Item *create_func_issimple(Item* a)
{
return new Item_func_issimple(a);
}
Item *create_func_isclosed(Item* a)
{
return new Item_func_isclosed(a);
}
Item *create_func_geometry_type(Item* a)
{
return new Item_func_geometry_type(a);
}
Item *create_func_dimension(Item* a)
{
return new Item_func_dimension(a);
}
Item *create_func_x(Item* a)
{
return new Item_func_x(a);
}
Item *create_func_y(Item* a)
{
return new Item_func_y(a);
}
Item *create_func_numpoints(Item* a)
{
return new Item_func_numpoints(a);
}
Item *create_func_numinteriorring(Item* a)
{
return new Item_func_numinteriorring(a);
}
Item *create_func_numgeometries(Item* a)
{
return new Item_func_numgeometries(a);
}
Item *create_func_area(Item* a)
{
return new Item_func_area(a);
}
Item *create_func_glength(Item* a)
{
return new Item_func_glength(a);
}
Item *create_func_point(Item* a, Item* b)
{
return new Item_func_point(a,b);
}
......@@ -88,3 +88,41 @@ Item *create_func_version(void);
Item *create_func_weekday(Item* a);
Item *create_load_file(Item* a);
Item *create_wait_for_master_pos(Item* a, Item* b);
Item *create_func_geometry_from_text(Item* a);
Item *create_func_as_text(Item* a);
Item *create_func_startpoint(Item* a);
Item *create_func_endpoint(Item* a);
Item *create_func_exteriorring(Item* a);
Item *create_func_centroid(Item* a);
Item *create_func_envelope(Item* a);
Item *create_func_pointn(Item* a, Item* b);
Item *create_func_interiorringn(Item* a, Item* b);
Item *create_func_geometryn(Item* a, Item* b);
Item *create_func_equals(Item* a, Item* b);
Item *create_func_disjoint(Item* a, Item* b);
Item *create_func_intersects(Item* a, Item* b);
Item *create_func_touches(Item* a, Item* b);
Item *create_func_crosses(Item* a, Item* b);
Item *create_func_within(Item* a, Item* b);
Item *create_func_contains(Item* a, Item* b);
Item *create_func_overlaps(Item* a, Item* b);
Item *create_func_isempty(Item* a);
Item *create_func_issimple(Item* a);
Item *create_func_isclosed(Item* a);
Item *create_func_geometry_type(Item* a);
Item *create_func_dimension(Item* a);
Item *create_func_x(Item* a);
Item *create_func_y(Item* a);
Item *create_func_area(Item* a);
Item *create_func_glength(Item* a);
Item *create_func_numpoints(Item* a);
Item *create_func_numinteriorring(Item* a);
Item *create_func_numgeometries(Item* a);
Item *create_func_point(Item* a,Item* b);
......@@ -27,6 +27,8 @@
#include <time.h>
#include <ft_global.h>
#include "slave.h" // for wait_for_master_pos
#include "gstream.h"
/* return TRUE if item is a constant */
......@@ -2252,3 +2254,130 @@ Item *get_system_var(LEX_STRING name)
my_error(ER_UNKNOWN_SYSTEM_VARIABLE,MYF(0),name);
return 0;
}
/**************************************************************************
Spatial functions
***************************************************************************/
longlong Item_func_dimension::val_int()
{
uint32 dim;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
geom.dimension(&dim));
return (longlong) dim;
}
longlong Item_func_numinteriorring::val_int()
{
uint32 num;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,num_interior_ring) ||
geom.num_interior_ring(&num));
return (longlong) num;
}
longlong Item_func_numgeometries::val_int()
{
uint32 num;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,num_geometries) ||
geom.num_geometries(&num));
return (longlong) num;
}
longlong Item_func_numpoints::val_int()
{
uint32 num;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,num_points) ||
geom.num_points(&num));
return (longlong) num;
}
double Item_func_x::val()
{
double res;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,get_x) ||
geom.get_x(&res));
return res;
}
double Item_func_y::val()
{
double res;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,get_y) ||
geom.get_y(&res));
return res;
}
double Item_func_area::val()
{
double res;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,area) ||
geom.area(&res));
return res;
}
double Item_func_glength::val()
{
double res;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,length) ||
geom.length(&res));
return res;
}
......@@ -39,7 +39,12 @@ public:
enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC,
GE_FUNC,GT_FUNC,FT_FUNC,
LIKE_FUNC,NOTLIKE_FUNC,ISNULL_FUNC,ISNOTNULL_FUNC,
COND_AND_FUNC,COND_OR_FUNC,BETWEEN,IN_FUNC,INTERVAL_FUNC};
COND_AND_FUNC,COND_OR_FUNC,BETWEEN,IN_FUNC,INTERVAL_FUNC,
SP_EQUALS_FUNC, SP_DISJOINT_FUNC,SP_INTERSECTS_FUNC,
SP_TOUCHES_FUNC,SP_CROSSES_FUNC,SP_WITHIN_FUNC,
SP_CONTAINS_FUNC,SP_OVERLAPS_FUNC,
SP_STARTPOINT,SP_ENDPOINT,SP_EXTERIORRING,
SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN};
enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL };
enum Type type() const { return FUNC_ITEM; }
virtual enum Functype functype() const { return UNKNOWN_FUNC; }
......@@ -944,6 +949,86 @@ public:
void init_search(bool no_order);
};
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_match_nl :public Item_func_match
{
public:
......
......@@ -1953,3 +1953,333 @@ String* Item_func_inet_ntoa::val_str(String* str)
str->length(str->length()-1); // Remove last '.';
return str;
}
/*******************************************************
General functions for spatial objects
********************************************************/
#include "gstream.h"
String *Item_func_geometry_from_text::val_str(String *str)
{
Geometry geom;
String *wkt = args[0]->val_str(str);
GTextReadStream trs(wkt->ptr(), wkt->length());
str->length(0);
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_as_text::val_str(String *str)
{
String *wkt = args[0]->val_str(str);
Geometry geom;
str->length(0);
if ((null_value=(args[0]->null_value ||
geom.create_from_wkb(wkt->ptr(),wkt->length()) ||
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_geometry_type::val_str(String *str)
{
String *wkt = args[0]->val_str(str);
Geometry geom;
if ((null_value=(args[0]->null_value ||
geom.create_from_wkb(wkt->ptr(),wkt->length()))))
return 0;
str->copy(geom.get_class_info()->m_name);
return str;
}
String *Item_func_envelope::val_str(String *str)
{
String *wkb = args[0]->val_str(str);
Geometry geom;
null_value = args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
geom.envelope(str);
return null_value ? 0 : str;
}
String *Item_func_centroid::val_str(String *str)
{
String *wkb = args[0]->val_str(str);
Geometry geom;
null_value = args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,centroid) ||
geom.centroid(str);
return null_value ? 0: str;
}
/***********************************************
Spatial decomposition functions
***********************************************/
String *Item_func_spatial_decomp::val_str(String *str)
{
String *wkb = args[0]->val_str(str);
Geometry geom;
if ((null_value = (args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()))))
return 0;
null_value=1;
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 *wkb = args[0]->val_str(str);
long n = (long) args[1]->val_int();
Geometry geom;
if ((null_value = (args[0]->null_value ||
args[1]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) )))
return 0;
null_value=1;
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)
{
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((double)args[0]->val());
str->q_append((double)args[1]->val());
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)
{
uint i;
null_value=1;
str->length(0);
if(str->reserve(9,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)
{
if (args[i]->null_value)
goto ret;
String *res = args[i]->val_str(str);
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
{
uint32 wkb_type, 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=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 < WKB_HEADER_SIZE + 4 + 8 + 8)
goto ret;
data+=WKB_HEADER_SIZE;
len-=WKB_HEADER_SIZE;
uint32 llen=len;
const char *ldata=data;
n_points=uint4korr(data);
data+=4;
float8get(x1,data);
data+=8;
float8get(y1,data);
data+=8;
len-= 4 + 8 + 8;
if (len < n_points * POINT_DATA_SIZE)
goto ret;
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() > max_allowed_packet)
goto ret;
null_value = 0;
ret:
return null_value ? 0 : str;
}
......@@ -475,3 +475,196 @@ public:
const char *func_name() const { return "inet_ntoa"; }
void fix_length_and_dec() { decimals = 0; max_length=3*8+7; }
};
/*******************************************************
Spatial functions
********************************************************/
class Item_func_geometry_from_text :public Item_str_func
{
public:
Item_func_geometry_from_text(Item *a) :Item_str_func(a) {}
const char *func_name() const { return "geometryfromtext"; }
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_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) {}
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"; }
};
/*
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"; }
};
*/
......@@ -75,6 +75,7 @@ static SYMBOL symbols[] = {
{ "BOOL", SYM(BOOL_SYM),0,0},
{ "BOOLEAN", SYM(BOOLEAN_SYM),0,0},
{ "BOTH", SYM(BOTH),0,0},
{ "BTREE", SYM(BTREE_SYM),0,0},
{ "BY", SYM(BY),0,0},
{ "CACHE", SYM(CACHE_SYM),0,0},
{ "CASCADE", SYM(CASCADE),0,0},
......@@ -158,12 +159,14 @@ static SYMBOL symbols[] = {
{ "FULL", SYM(FULL),0,0},
{ "FULLTEXT", SYM(FULLTEXT_SYM),0,0},
{ "FUNCTION", SYM(UDF_SYM),0,0},
{ "GEOM", SYM(GEOM_SYM),0,0},
{ "GLOBAL", SYM(GLOBAL_SYM),0,0},
{ "GRANT", SYM(GRANT),0,0},
{ "GRANTS", SYM(GRANTS),0,0},
{ "GROUP", SYM(GROUP),0,0},
{ "HAVING", SYM(HAVING),0,0},
{ "HANDLER", SYM(HANDLER_SYM),0,0},
{ "HASH", SYM(HASH_SYM),0,0},
{ "HEAP", SYM(HEAP_SYM),0,0},
{ "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0},
{ "HOUR", SYM(HOUR_SYM),0,0},
......@@ -296,6 +299,7 @@ static SYMBOL symbols[] = {
{ "ROLLBACK", SYM(ROLLBACK_SYM),0,0},
{ "ROW", SYM(ROW_SYM),0,0},
{ "ROWS", SYM(ROWS_SYM),0,0},
{ "RTREE", SYM(RTREE_SYM),0,0},
{ "SECOND", SYM(SECOND_SYM),0,0},
{ "SELECT", SYM(SELECT_SYM),0,0},
{ "SERIALIZABLE", SYM(SERIALIZABLE_SYM),0,0},
......@@ -308,6 +312,7 @@ static SYMBOL symbols[] = {
{ "SLAVE", SYM(SLAVE),0,0},
{ "SMALLINT", SYM(SMALLINT),0,0},
{ "SONAME", SYM(UDF_SONAME_SYM),0,0},
{ "SPATIAL", SYM(SPATIAL_SYM),0,0},
{ "SQL_AUTO_IS_NULL", SYM(SQL_AUTO_IS_NULL),0,0},
{ "SQL_BIG_RESULT", SYM(SQL_BIG_RESULT),0,0},
{ "SQL_BIG_SELECTS", SYM(SQL_BIG_SELECTS),0,0},
......@@ -384,8 +389,10 @@ static SYMBOL sql_functions[] = {
{ "ABS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_abs)},
{ "ACOS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_acos)},
{ "ADDDATE", SYM(DATE_ADD_INTERVAL),0,0},
{ "AREA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_area)},
{ "ASCII", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ascii)},
{ "ASIN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_asin)},
{ "ASTEXT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_text)},
{ "ATAN", SYM(ATAN),0,0},
{ "ATAN2", SYM(ATAN),0,0},
{ "BENCHMARK", SYM(BENCHMARK_SYM),0,0},
......@@ -396,17 +403,20 @@ static SYMBOL sql_functions[] = {
{ "CAST", SYM(CAST_SYM),0,0},
{ "CEILING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
{ "BIT_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)},
{ "CENTROID", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_centroid)},
{ "CHAR_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
{ "CHARACTER_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
{ "COALESCE", SYM(COALESCE),0,0},
{ "CONCAT", SYM(CONCAT),0,0},
{ "CONCAT_WS", SYM(CONCAT_WS),0,0},
{ "CONNECTION_ID", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)},
{ "CONTAINS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_contains)},
{ "CONV", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)},
{ "CONVERT", SYM(CONVERT_SYM),0,0},
{ "COUNT", SYM(COUNT_SYM),0,0},
{ "COS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cos)},
{ "COT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cot)},
{ "CROSSES", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_crosses)},
{ "CURDATE", SYM(CURDATE),0,0},
{ "CURTIME", SYM(CURTIME),0,0},
{ "DATE_ADD", SYM(DATE_ADD_INTERVAL),0,0},
......@@ -420,9 +430,15 @@ static SYMBOL sql_functions[] = {
{ "DEGREES", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_degrees)},
{ "DES_ENCRYPT", SYM(DES_ENCRYPT_SYM),0,0},
{ "DES_DECRYPT", SYM(DES_DECRYPT_SYM),0,0},
{ "DIMENSION", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dimension)},
{ "DISJOINT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_disjoint)},
{ "ELT", SYM(ELT_FUNC),0,0},
{ "ENCODE", SYM(ENCODE_SYM),0,0},
{ "ENCRYPT", SYM(ENCRYPT),0,0},
{ "ENDPOINT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_endpoint)},
{ "ENVELOPE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_envelope)},
{ "EQUALS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_equals)},
{ "EXTERIORRING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_exteriorring)},
{ "EXTRACT", SYM(EXTRACT_SYM),0,0},
{ "EXP", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_exp)},
{ "EXPORT_SET", SYM(EXPORT_SET),0,0},
......@@ -434,6 +450,11 @@ static SYMBOL sql_functions[] = {
{ "FROM_DAYS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_from_days)},
{ "FROM_UNIXTIME", SYM(FROM_UNIXTIME),0,0},
{ "GET_LOCK", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_get_lock)},
{ "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION),0,0},
{ "GEOMETRYN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_geometryn)},
{ "GEOMETRYTYPE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_geometry_type)},
{ "GEOMFROMTEXT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_geometry_from_text)},
{ "GLENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_glength)},
{ "GREATEST", SYM(GREATEST_SYM),0,0},
{ "GROUP_UNIQUE_USERS", SYM(GROUP_UNIQUE_USERS),0,0},
{ "HEX", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_hex)},
......@@ -441,10 +462,16 @@ static SYMBOL sql_functions[] = {
{ "INET_ATON", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_aton)},
{ "INET_NTOA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_ntoa)},
{ "INSTR", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_instr)},
{ "INTERIORRINGN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_interiorringn)},
{ "INTERSECTS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_intersects)},
{ "ISCLOSED", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isclosed)},
{ "ISEMPTY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isempty)},
{ "ISNULL", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isnull)},
{ "ISSIMPLE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_issimple)},
{ "LCASE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)},
{ "LEAST", SYM(LEAST_SYM),0,0},
{ "LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)},
{ "LINESTRING", SYM(LINESTRING),0,0},
{ "LOAD_FILE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_load_file)},
{ "LOCATE", SYM(LOCATE),0,0},
{ "LOG", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log)},
......@@ -460,15 +487,25 @@ static SYMBOL sql_functions[] = {
{ "MID", SYM(SUBSTRING),0,0}, /* unireg function */
{ "MIN", SYM(MIN_SYM),0,0},
{ "MOD", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_mod)},
{ "MULTILINESTRING", SYM(MULTILINESTRING),0,0},
{ "MULTIPOINT", SYM(MULTIPOINT),0,0},
{ "MULTIPOLYGON", SYM(MULTIPOLYGON),0,0},
{ "MONTHNAME", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_monthname)},
{ "NOW", SYM(NOW_SYM),0,0},
{ "NULLIF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_nullif)},
{ "NUMGEOMETRIES", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numgeometries)},
{ "NUMINTERIORRING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numinteriorring)},
{ "NUMPOINTS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numpoints)},
{ "OCTET_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)},
{ "OCT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_oct)},
{ "ORD", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ord)},
{ "OVERLAPS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_overlaps)},
{ "PERIOD_ADD", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)},
{ "PERIOD_DIFF", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_diff)},
{ "PI", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_pi)},
{ "POINT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_point)},
{ "POINTN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pointn)},
{ "POLYGON", SYM(POLYGON),0,0},
{ "POSITION", SYM(POSITION_SYM),0,0},
{ "POW", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
{ "POWER", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
......@@ -489,6 +526,7 @@ static SYMBOL sql_functions[] = {
{ "SOUNDEX", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_soundex)},
{ "SPACE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_space)},
{ "SQRT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sqrt)},
{ "STARTPOINT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_startpoint)},
{ "STD", SYM(STD_SYM),0,0},
{ "STDDEV", SYM(STD_SYM),0,0},
{ "STRCMP", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)},
......@@ -501,6 +539,7 @@ static SYMBOL sql_functions[] = {
{ "TIME_FORMAT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)},
{ "TIME_TO_SEC", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_time_to_sec)},
{ "TO_DAYS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_to_days)},
{ "TOUCHES", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_touches)},
{ "TRIM", SYM(TRIM),0,0},
{ "UCASE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
{ "UNIQUE_USERS", SYM(UNIQUE_USERS),0,0},
......@@ -510,5 +549,9 @@ static SYMBOL sql_functions[] = {
{ "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM),0,0},
{ "WEEKDAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
{ "WITHIN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_within)},
{ "X", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_x)},
{ "Y", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_y)},
{ "YEARWEEK", SYM(YEARWEEK),0,0}
};
......@@ -172,8 +172,9 @@ public:
void store(uint length,char **min_key,uint min_key_flag,
char **max_key, uint max_key_flag)
{
if (!(min_flag & NO_MIN_RANGE) &&
!(min_key_flag & (NO_MIN_RANGE | NEAR_MIN)))
if ((min_flag & GEOM_FLAG) ||
(!(min_flag & NO_MIN_RANGE) &&
!(min_key_flag & (NO_MIN_RANGE | NEAR_MIN))))
{
if (maybe_null && *min_value)
{
......@@ -659,6 +660,8 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
key_parts->null_bit= key_info->key_part[part].null_bit;
if (key_parts->field->type() == FIELD_TYPE_BLOB)
key_parts->part_length+=HA_KEY_BLOB_LENGTH;
key_parts->image_type =
(key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW;
}
param.real_keynr[param.keys++]=idx;
}
......@@ -676,6 +679,7 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
{
SEL_ARG **key,**end,**best_key=0;
for (idx=0,key=tree->keys, end=key+param.keys ;
key != end ;
key++,idx++)
......@@ -1042,7 +1046,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
DBUG_RETURN(0);
if (maybe_null)
*str=0; // Not NULL
field->get_key_image(str+maybe_null,key_part->part_length);
field->get_key_image(str+maybe_null,key_part->part_length, key_part->image_type);
if (!(tree=new SEL_ARG(field,str,str)))
DBUG_RETURN(0);
......@@ -1067,6 +1071,41 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
case Item_func::GE_FUNC:
tree->max_flag=NO_MAX_RANGE;
break;
case Item_func::SP_EQUALS_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_EQUAL;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
case Item_func::SP_DISJOINT_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_DISJOINT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
case Item_func::SP_INTERSECTS_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
case Item_func::SP_TOUCHES_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
case Item_func::SP_CROSSES_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
case Item_func::SP_WITHIN_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_WITHIN;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
case Item_func::SP_CONTAINS_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_CONTAIN;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
case Item_func::SP_OVERLAPS_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE;
break;
default:
break;
}
......@@ -2187,18 +2226,30 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
!memcmp(param->min_key,param->max_key,min_key_length))
tmp=1; // Max one record
else
{
if(tmp_min_flag & GEOM_FLAG)
{
tmp=param->table->file->
records_in_range((int) keynr,(byte*)(param->min_key + 1),
min_key_length, (ha_rkey_function)(tmp_min_flag ^ GEOM_FLAG),
(byte *)NullS,0,HA_READ_KEY_EXACT);
}
else
{
tmp=param->table->file->
records_in_range((int) keynr,
(byte*) (!min_key_length ? NullS :
param->min_key),
min_key_length,
(tmp_min_flag & NEAR_MIN ?
HA_READ_AFTER_KEY : HA_READ_KEY_EXACT),
tmp_min_flag & NEAR_MIN ?
HA_READ_AFTER_KEY : HA_READ_KEY_EXACT,
(byte*) (!max_key_length ? NullS :
param->max_key),
max_key_length,
(tmp_max_flag & NEAR_MAX ?
HA_READ_BEFORE_KEY : HA_READ_AFTER_KEY));
}
}
end:
if (tmp == HA_POS_ERROR) // Impossible range
return tmp;
......@@ -2294,19 +2345,24 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
}
}
else
flag=key_tree->min_flag | key_tree->max_flag;
{
flag = (key_tree->min_flag & GEOM_FLAG) ?
key_tree->min_flag : key_tree->min_flag | key_tree->max_flag;
}
/* Ensure that some part of min_key and max_key are used. If not,
regard this as no lower/upper range */
if (tmp_min_key != param->min_key)
flag&= ~NO_MIN_RANGE;
else
flag|= NO_MIN_RANGE;
if (tmp_max_key != param->max_key)
flag&= ~NO_MAX_RANGE;
else
flag|= NO_MAX_RANGE;
if((flag & GEOM_FLAG) == 0)
{
if (tmp_min_key != param->min_key)
flag&= ~NO_MIN_RANGE;
else
flag|= NO_MIN_RANGE;
if (tmp_max_key != param->max_key)
flag&= ~NO_MAX_RANGE;
else
flag|= NO_MAX_RANGE;
}
if (flag == 0)
{
uint length= (uint) (tmp_min_key - param->min_key);
......@@ -2439,13 +2495,19 @@ int QUICK_SELECT::get_next()
int result;
if (range)
{ // Already read through key
result=((range->flag & EQ_RANGE) ?
/* result=((range->flag & EQ_RANGE) ?
file->index_next_same(record, (byte*) range->min_key,
range->min_length) :
file->index_next(record));
*/
result=((range->flag & (EQ_RANGE | GEOM_FLAG) ) ?
file->index_next_same(record, (byte*) range->min_key,
range->min_length) :
file->index_next(record));
if (!result)
{
if (!cmp_next(*it.ref()))
if ((range->flag & GEOM_FLAG) || !cmp_next(*it.ref()))
DBUG_RETURN(0);
}
else if (result != HA_ERR_END_OF_FILE)
......@@ -2454,6 +2516,23 @@ int QUICK_SELECT::get_next()
if (!(range=it++))
DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used
if(range->flag & GEOM_FLAG)
{
if ((result = file->index_read(record,
(byte*) (range->min_key + ((range->flag & GEOM_FLAG) > 0)),
range->min_length,
(ha_rkey_function)(range->flag ^ GEOM_FLAG))))
{
if (result != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(result);
range=0; // Not found, to next range
continue;
}
DBUG_RETURN(0);
}
if (range->flag & NO_MIN_RANGE) // Read first record
{
int error;
......@@ -2464,13 +2543,14 @@ int QUICK_SELECT::get_next()
range=0; // No matching records; go to next range
continue;
}
if ((result = file->index_read(record,(byte*) range->min_key,
if ((result = file->index_read(record,
(byte*) (range->min_key + ((range->flag & GEOM_FLAG) > 0)),
range->min_length,
((range->flag & NEAR_MIN) ?
(range->flag & NEAR_MIN) ?
HA_READ_AFTER_KEY:
(range->flag & EQ_RANGE) ?
HA_READ_KEY_EXACT :
HA_READ_KEY_OR_NEXT))))
HA_READ_KEY_OR_NEXT)))
{
if (result != HA_ERR_KEY_NOT_FOUND)
......
......@@ -31,11 +31,14 @@
#define UNIQUE_RANGE 16
#define EQ_RANGE 32
#define NULL_RANGE 64
#define GEOM_FLAG 128
typedef struct st_key_part {
uint16 key,part,part_length;
uint8 null_bit;
Field *field;
uint16 key,part,part_length;
uint8 null_bit;
Field *field;
Field::imagetype image_type;
} KEY_PART;
class QUICK_RANGE :public Sql_alloc {
......
......@@ -343,7 +343,7 @@ static bool find_range_key(TABLE_REF *ref, Field* field, COND *cond)
// Save found constant
if (part->null_bit)
*key_ptr++= (byte) test(part->field->is_null());
part->field->get_key_image((char*) key_ptr,part->length);
part->field->get_key_image((char*) key_ptr,part->length, Field::itRAW);
key_ptr+=part->store_length - test(part->null_bit);
left_length-=part->store_length;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -198,13 +198,18 @@ public:
class Key :public Sql_alloc {
public:
enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT };
enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL };
enum Keytype type;
enum ha_key_alg alg; // +BAR
List<key_part_spec> columns;
const char *Name;
Key(enum Keytype type_par,const char *name_arg,List<key_part_spec> &cols)
:type(type_par), columns(cols),Name(name_arg) {}
Key(enum Keytype type_par, enum ha_key_alg alg_par, const char *name_arg,List<key_part_spec> &cols)
:type(type_par),alg(alg_par), columns(cols),Name(name_arg){} //+BAR
~Key() {}
const char *name() { return Name; }
};
......
......@@ -880,11 +880,17 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append("UNIQUE ", 7);
else if (key_info->flags & HA_FULLTEXT)
packet->append("FULLTEXT ", 9);
else if (key_info->flags & HA_SPATIAL)
packet->append("SPATIAL ", 8);
packet->append("KEY ", 4);
if (!found_primary)
append_identifier(thd,packet,key_info->name);
// +BAR: send USING only in non-default case: non-spatial rtree
if((key_info->key_alg == HA_KEY_ALG_RTREE) && !(key_info->flags & HA_SPATIAL))
packet->append(" USING RTREE",12);
packet->append(" (", 2);
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
......
......@@ -459,6 +459,44 @@ bool String::replace(uint32 offset,uint32 arg_length,const String &to)
return FALSE;
}
// added by Holyfoot for "geometry" needs
int String::reserve(uint32 space_needed, uint32 grow_by)
{
if (Alloced_length < str_length + space_needed)
{
if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
return TRUE;
}
return FALSE;
}
void String::qs_append(const char *str)
{
int len = strlen(str);
memcpy(Ptr + str_length, str, len + 1);
str_length += len;
}
void String::qs_append(double d)
{
char *buff = Ptr + str_length;
sprintf(buff,"%.14g", d);
str_length += strlen(buff);
}
void String::qs_append(double *d)
{
double ld;
float8get(ld, d);
qs_append(ld);
}
void String::qs_append(const char &c)
{
Ptr[str_length] = c;
str_length += sizeof(c);
}
int sortcmp(const String *x,const String *y)
{
......@@ -805,3 +843,5 @@ int wild_compare(String &match,String &wild, char escape)
DBUG_RETURN(wild_compare(match.ptr(),match.ptr()+match.length(),
wild.ptr(), wild.ptr()+wild.length(),escape));
}
......@@ -188,4 +188,49 @@ public:
friend int wild_compare(String &match,String &wild,char escape);
uint32 numchars();
int charpos(int i,uint32 offset=0);
// added by Holyfoot for "geometry" needs
int reserve(uint32 space_needed)
{
return realloc(str_length + space_needed);
}
int reserve(uint32 space_needed, uint32 grow_by);
// these append operations do NOT check alloced memory
// q_*** methods writes values of parameters itself
// qs_*** methods writes string representation of value
void q_append(const char &c)
{
Ptr[str_length++] = c;
}
void q_append(const uint32 &n)
{
int4store(Ptr + str_length, n);
str_length += 4;
}
void q_append(double d)
{
float8store(Ptr + str_length, d);
str_length += 8;
}
void q_append(double *d)
{
float8store(Ptr + str_length, *d);
str_length += 8;
}
void q_append(const char *data, uint32 data_len)
{
memcpy(Ptr + str_length, data, data_len);
str_length += data_len;
}
void WriteAtPosition(int position, uint32 value)
{
int4store(Ptr + position,value);
}
void qs_append(const char *str);
void qs_append(double d);
void qs_append(double *d);
void qs_append(const char &c);
};
......@@ -438,8 +438,21 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
uint key_length=0;
key_part_spec *column;
key_info->flags= (key->type == Key::MULTIPLE) ? 0 :
(key->type == Key::FULLTEXT) ? HA_FULLTEXT : HA_NOSAME;
switch(key->type){
case Key::MULTIPLE:
key_info->flags = 0;
break;
case Key::FULLTEXT:
key_info->flags = HA_FULLTEXT;
break;
case Key::SPATIAL:
key_info->flags = HA_SPATIAL;
break;
default:
key_info->flags = HA_NOSAME;
}
key_info->key_alg = key->alg;
key_info->key_parts=(uint8) key->columns.elements;
key_info->key_part=key_part_info;
key_info->usable_key_parts= key_number;
......@@ -452,7 +465,31 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_RETURN(-1);
}
}
/*
Make SPATIAL to be RTREE by default
SPATIAL only on BLOB or at least BINARY, this
actually should be replaced by special GEOM type
in near future when new frm file is ready
checking for proper key parts number:
*/
if(key_info->flags == HA_SPATIAL){
if(key_info->key_parts!=1){
my_printf_error(ER_WRONG_ARGUMENTS,
ER(ER_WRONG_ARGUMENTS),MYF(0),"SPATIAL INDEX");
DBUG_RETURN(-1);
}
}else
{
if(key_info->key_alg == HA_KEY_ALG_RTREE){
if((key_info->key_parts&1)==1){
my_printf_error(ER_WRONG_ARGUMENTS,
ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX");
DBUG_RETURN(-1);
}
}
}
List_iterator<key_part_spec> cols(key->columns);
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
{
......@@ -480,6 +517,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
if (key->type == Key::FULLTEXT)
column->length=1; /* ft-code ignores it anyway :-) */
else if (key->type == Key::SPATIAL)
{
/*
BAR: 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
Lately we'll extend this code to support more dimensions
*/
column->length=4*sizeof(double);
}
else
{
my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH,
......@@ -1471,11 +1516,13 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
key_part_length));
}
if (key_parts.elements)
key_list.push_back(new Key(key_info->flags & HA_NOSAME ?
key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL :
(key_info->flags & HA_NOSAME ?
(!my_strcasecmp(key_name, "PRIMARY") ?
Key::PRIMARY : Key::UNIQUE) :
(key_info->flags & HA_FULLTEXT ?
Key::FULLTEXT : Key::MULTIPLE),
Key::FULLTEXT : Key::MULTIPLE)),
key_info->key_alg,
key_name,key_parts));
}
key_it.rewind();
......
......@@ -54,6 +54,7 @@ inline Item *or_or_concat(Item* A, Item* B)
List<Item> *item_list;
List<String> *string_list;
Key::Keytype key_type;
enum ha_key_alg key_alg;
enum db_type db_type;
enum row_type row_type;
enum ha_rkey_function ha_rkey_mode;
......@@ -154,6 +155,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token BOOL_SYM
%token BOOLEAN_SYM
%token BOTH
%token BTREE_SYM
%token BY
%token CACHE_SYM
%token CASCADE
......@@ -200,6 +202,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token GREATEST_SYM
%token GROUP
%token HAVING
%token HASH_SYM
%token HEAP_SYM
%token HEX_NUM
%token HIGH_PRIORITY
......@@ -291,10 +294,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ROWS_SYM
%token ROW_FORMAT_SYM
%token ROW_SYM
%token RTREE_SYM
%token SET
%token SERIALIZABLE_SYM
%token SESSION_SYM
%token SHUTDOWN
%token SPATIAL_SYM
%token SQL_CACHE_SYM
%token SQL_NO_CACHE_SYM
%token SSL_SYM
......@@ -344,6 +349,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ENUM
%token FAST_SYM
%token FLOAT_SYM
%token GEOM_SYM
%token INT_SYM
%token LIMIT
%token LONGBLOB
......@@ -401,6 +407,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token FORMAT_SYM
%token FOR_SYM
%token FROM_UNIXTIME
%token GEOMETRYCOLLECTION
%token GROUP_UNIQUE_USERS
%token HOUR_MINUTE_SYM
%token HOUR_SECOND_SYM
......@@ -412,6 +419,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token INTERVAL_SYM
%token LAST_INSERT_ID
%token LEFT
%token LINESTRING
%token LOCATE
%token MAKE_SET_SYM
%token MINUTE_SECOND_SYM
......@@ -419,8 +427,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MODE_SYM
%token MODIFY_SYM
%token MONTH_SYM
%token MULTILINESTRING
%token MULTIPOINT
%token MULTIPOLYGON
%token NOW_SYM
%token PASSWORD
%token POLYGON
%token POSITION_SYM
%token PROCEDURE
%token RAND
......@@ -527,6 +539,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <key_type>
key_type opt_unique_or_fulltext
%type <key_alg>
key_alg opt_btree_or_rtree
%type <string_list>
key_usage_list
......@@ -721,21 +736,22 @@ create:
}
create2
| CREATE opt_unique_or_fulltext INDEX ident ON table_ident
| CREATE opt_unique_or_fulltext INDEX ident key_alg ON table_ident
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_CREATE_INDEX;
if (!add_table_to_list($6,NULL,1))
if (!add_table_to_list($7,NULL,1))
YYABORT;
lex->create_list.empty();
lex->key_list.empty();
lex->col_list.empty();
lex->change=NullS;
}
'(' key_list ')'
'(' key_list ')'
{
LEX *lex=Lex;
lex->key_list.push_back(new Key($2,$4.str,lex->col_list));
lex->key_list.push_back(new Key($2,$5,$4.str,lex->col_list));
lex->col_list.empty();
}
| CREATE DATABASE opt_if_not_exists ident
......@@ -882,10 +898,10 @@ field_list_item:
{
Lex->col_list.empty(); /* Alloced by sql_alloc */
}
| key_type opt_ident '(' key_list ')'
| key_type opt_ident key_alg '(' key_list ')'
{
LEX *lex=Lex;
lex->key_list.push_back(new Key($1,$2,lex->col_list));
lex->key_list.push_back(new Key($1,$3,$2,lex->col_list));
lex->col_list.empty(); /* Alloced by sql_alloc */
}
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
......@@ -950,6 +966,8 @@ type:
$$=FIELD_TYPE_TINY_BLOB; }
| BLOB_SYM { Lex->type|=BINARY_FLAG;
$$=FIELD_TYPE_BLOB; }
| GEOM_SYM { Lex->type|=BINARY_FLAG;
$$=FIELD_TYPE_GEOMETRY; }
| MEDIUMBLOB { Lex->type|=BINARY_FLAG;
$$=FIELD_TYPE_MEDIUM_BLOB; }
| LONGBLOB { Lex->type|=BINARY_FLAG;
......@@ -1091,6 +1109,8 @@ key_type:
| key_or_index { $$= Key::MULTIPLE; }
| FULLTEXT_SYM { $$= Key::FULLTEXT; }
| FULLTEXT_SYM key_or_index { $$= Key::FULLTEXT; }
| SPATIAL_SYM { $$= Key::SPATIAL; }
| SPATIAL_SYM key_or_index { $$= Key::SPATIAL; }
| opt_constraint UNIQUE_SYM { $$= Key::UNIQUE; }
| opt_constraint UNIQUE_SYM key_or_index { $$= Key::UNIQUE; }
......@@ -1107,6 +1127,16 @@ opt_unique_or_fulltext:
/* empty */ { $$= Key::MULTIPLE; }
| UNIQUE_SYM { $$= Key::UNIQUE; }
| FULLTEXT_SYM { $$= Key::FULLTEXT; }
| SPATIAL_SYM { $$= Key::SPATIAL; }
key_alg:
/* empty */ { $$= HA_KEY_ALG_BTREE; }
| USING opt_btree_or_rtree { $$= $2 }
opt_btree_or_rtree:
BTREE_SYM { $$= HA_KEY_ALG_BTREE; }
| RTREE_SYM { $$= HA_KEY_ALG_RTREE; }
| HASH_SYM { $$= HA_KEY_ALG_HASH; }
key_list:
key_list ',' key_part order_dir { Lex->col_list.push_back($3); }
......@@ -1692,6 +1722,10 @@ simple_expr:
}
| FIELD_FUNC '(' expr ',' expr_list ')'
{ $$= new Item_func_field($3, *$5); }
| GEOMETRYCOLLECTION '(' expr_list ')'
{ $$= new Item_func_spatial_collection(* $3,
Geometry::wkbGeometryCollection,
Geometry::wkbPoint); }
| HOUR_SYM '(' expr ')'
{ $$= new Item_func_hour($3); }
| IF '(' expr ',' expr ',' expr ')'
......@@ -1716,6 +1750,9 @@ simple_expr:
}
| LEFT '(' expr ',' expr ')'
{ $$= new Item_func_left($3,$5); }
| LINESTRING '(' expr_list ')'
{ $$= new Item_func_spatial_collection(* $3,
Geometry::wkbLineString, Geometry::wkbPoint); }
| LOCATE '(' expr ',' expr ')'
{ $$= new Item_func_locate($5,$3); }
| LOCATE '(' expr ',' expr ',' expr ')'
......@@ -1728,6 +1765,15 @@ simple_expr:
{ $$= new Item_func_minute($3); }
| MONTH_SYM '(' expr ')'
{ $$= new Item_func_month($3); }
| MULTILINESTRING '(' expr_list ')'
{ $$= new Item_func_spatial_collection(* $3,
Geometry::wkbMultiLineString, Geometry::wkbLineString); }
| MULTIPOINT '(' expr_list ')'
{ $$= new Item_func_spatial_collection(* $3,
Geometry::wkbMultiPoint, Geometry::wkbPoint); }
| MULTIPOLYGON '(' expr_list ')'
{ $$= new Item_func_spatial_collection(* $3,
Geometry::wkbMultiPolygon, Geometry::wkbPolygon ); }
| NOW_SYM optional_braces
{ $$= new Item_func_now(); current_thd->safe_to_cache_query=0;}
| NOW_SYM '(' expr ')'
......@@ -1736,6 +1782,9 @@ simple_expr:
{
$$= new Item_func_password($3);
}
| POLYGON '(' expr_list ')'
{ $$= new Item_func_spatial_collection(* $3,
Geometry::wkbPolygon, Geometry::wkbLineString); }
| POSITION_SYM '(' no_in_expr IN_SYM expr ')'
{ $$ = new Item_func_locate($5,$3); }
| RAND '(' expr ')'
......
......@@ -64,6 +64,7 @@ typedef struct st_key_part_info { /* Info about a key part */
typedef struct st_key {
uint key_length; /* Tot length of key */
uint flags; /* dupp key and pack flags */
enum ha_key_alg key_alg; /* +BAR Algorithm BTREE or RTREE */
uint key_parts; /* How many key_parts */
uint extra_length;
uint usable_key_parts; /* Should normally be = key_parts */
......
......@@ -153,7 +153,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
{
keyinfo->flags= ((uint) strpos[0]) ^ HA_NOSAME;
keyinfo->key_length= (uint) uint2korr(strpos+1);
keyinfo->key_parts= (uint) strpos[3]; strpos+=4;
keyinfo->key_parts= (uint) strpos[3];
strpos+=4;
keyinfo->key_part= key_part;
keyinfo->rec_per_key= rec_per_key;
for (j=keyinfo->key_parts ; j-- ; key_part++)
......@@ -395,6 +397,26 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
}
}
keyinfo->key_alg=HA_KEY_ALG_BTREE; // BAR : btree by default
#define BAR_DIRTY_HACK
#ifdef BAR_DIRTY_HACK
// BAR FIXME: Dirty hack while waiting for new .frm format
switch(keyinfo->name[0]){
case 'R':
keyinfo->key_alg=HA_KEY_ALG_RTREE;
break;
case 'S':
keyinfo->key_alg = HA_KEY_ALG_RTREE;
keyinfo->flags |= HA_SPATIAL;
break;
case 'B':
default:
keyinfo->key_alg=HA_KEY_ALG_BTREE;
break;
}
#endif
for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
{
if (new_field_pack_flag <= 1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment