Added GIS extension
BitKeeper/etc/ignore: Added myisam/rt_test myisam/sp_test to the ignore list
This commit is contained in:
parent
3d5dc65dfd
commit
32a08516c9
@ -460,3 +460,5 @@ vio/test-sslserver
|
||||
vio/viotest-ssl
|
||||
Docs/mysql.xml
|
||||
mysql-test/r/rpl000001.eval
|
||||
myisam/rt_test
|
||||
myisam/sp_test
|
||||
|
@ -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)
|
||||
|
||||
|
57
sql/field.cc
57
sql/field.cc
@ -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))
|
||||
|
32
sql/field.h
32
sql/field.h
@ -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)
|
||||
|
137
sql/gstream.cc
Normal file
137
sql/gstream.cc
Normal file
@ -0,0 +1,137 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
|
61
sql/gstream.h
Normal file
61
sql/gstream.h
Normal file
@ -0,0 +1,61 @@
|
||||
#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);
|
||||
|
||||
|
129
sql/item_func.cc
129
sql/item_func.cc
@ -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"; }
|
||||
};
|
||||
|
||||
*/
|
||||
|
43
sql/lex.h
43
sql/lex.h
@ -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}
|
||||
|
||||
};
|
||||
|
120
sql/opt_range.cc
120
sql/opt_range.cc
@ -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;
|
||||
}
|
||||
|
1435
sql/spatial.cc
Normal file
1435
sql/spatial.cc
Normal file
File diff suppressed because it is too large
Load Diff
476
sql/spatial.h
Normal file
476
sql/spatial.h
Normal file
@ -0,0 +1,476 @@
|
||||
#ifndef _spatial_h
|
||||
#define _spatial_h
|
||||
|
||||
#include "gstream.h"
|
||||
|
||||
const int POINT_DATA_SIZE = 8+8;
|
||||
const int WKB_HEADER_SIZE = 1+4;
|
||||
|
||||
struct stPoint2D
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
struct stLinearRing
|
||||
{
|
||||
size_t n_points;
|
||||
stPoint2D points;
|
||||
};
|
||||
|
||||
/***************************** MBR *******************************/
|
||||
|
||||
struct MBR
|
||||
{
|
||||
MBR()
|
||||
{
|
||||
xmin=DBL_MAX;
|
||||
ymin=DBL_MAX;
|
||||
xmax=-DBL_MAX;
|
||||
ymax=-DBL_MAX;
|
||||
}
|
||||
|
||||
MBR(const double &_xmin, const double &_ymin, const double &_xmax, const double &_ymax)
|
||||
{
|
||||
xmin=_xmin;
|
||||
ymin=_ymin;
|
||||
xmax=_xmax;
|
||||
ymax=_ymax;
|
||||
}
|
||||
|
||||
MBR(const stPoint2D &min, const stPoint2D &max)
|
||||
{
|
||||
xmin=min.x;
|
||||
ymin=min.y;
|
||||
xmax=max.x;
|
||||
ymax=max.y;
|
||||
}
|
||||
|
||||
double xmin;
|
||||
double ymin;
|
||||
double xmax;
|
||||
double ymax;
|
||||
|
||||
void add_xy(double x, double y)
|
||||
{ /* Not using "else" for proper one point MBR calculation */
|
||||
if (x<xmin)
|
||||
{
|
||||
xmin=x;
|
||||
}
|
||||
if (x>xmax)
|
||||
{
|
||||
xmax=x;
|
||||
}
|
||||
if (y<ymin)
|
||||
{
|
||||
ymin=y;
|
||||
}
|
||||
if (y>ymax)
|
||||
{
|
||||
ymax=y;
|
||||
}
|
||||
}
|
||||
|
||||
void add_xy(double *px, double *py)
|
||||
{ /* Not using "else" for proper one point MBR calculation */
|
||||
double x, y;
|
||||
float8get(x, px);
|
||||
float8get(y, py);
|
||||
if (x<xmin)
|
||||
{
|
||||
xmin=x;
|
||||
}
|
||||
if (x>xmax)
|
||||
{
|
||||
xmax=x;
|
||||
}
|
||||
if (y<ymin)
|
||||
{
|
||||
ymin=y;
|
||||
}
|
||||
if (y>ymax)
|
||||
{
|
||||
ymax=y;
|
||||
}
|
||||
}
|
||||
|
||||
void add_mbr(const MBR *mbr)
|
||||
{
|
||||
if (mbr->xmin<xmin)
|
||||
{
|
||||
xmin=mbr->xmin;
|
||||
}
|
||||
if (mbr->xmax>xmax)
|
||||
{
|
||||
xmax=mbr->xmax;
|
||||
}
|
||||
if (mbr->ymin<ymin)
|
||||
{
|
||||
ymin=mbr->ymin;
|
||||
}
|
||||
if (mbr->ymax>ymax)
|
||||
{
|
||||
ymax=mbr->ymax;
|
||||
}
|
||||
}
|
||||
|
||||
int equals(const MBR *mbr)
|
||||
{
|
||||
return (mbr->xmin==xmin)&&(mbr->ymin==ymin)&&(mbr->xmax==xmax)&&(mbr->ymax==ymax);
|
||||
}
|
||||
|
||||
int disjoint(const MBR *mbr)
|
||||
{
|
||||
return (mbr->xmin>xmax)||(mbr->ymin>ymax)||(mbr->xmax<xmin)||(mbr->ymax<ymin);
|
||||
}
|
||||
|
||||
int intersects(const MBR *mbr)
|
||||
{
|
||||
return !disjoint(mbr);
|
||||
}
|
||||
|
||||
int touches(const MBR *mbr)
|
||||
{
|
||||
return (((mbr->xmin==xmax) || (mbr->xmax==xmin)) &&
|
||||
((mbr->ymin>=ymin) && (mbr->ymin<=ymax) ||
|
||||
(mbr->ymax>=ymin) && (mbr->ymax<=ymax))) ||
|
||||
(((mbr->ymin==ymax) || (mbr->ymax==ymin)) &&
|
||||
((mbr->xmin>=xmin) && (mbr->xmin<=xmax) ||
|
||||
(mbr->xmax>=xmin)&&(mbr->xmax<=xmax)));
|
||||
}
|
||||
|
||||
int within(const MBR *mbr)
|
||||
{
|
||||
return (mbr->xmin<=xmin) && (mbr->ymin<=ymin) &&
|
||||
(mbr->xmax>=xmax) && (mbr->ymax>=ymax);
|
||||
}
|
||||
|
||||
int contains(const MBR *mbr)
|
||||
{
|
||||
return (mbr->xmin>=xmin) && (mbr->ymin>=ymin) &&
|
||||
(mbr->xmax<=xmax) && (mbr->ymax<=ymax);
|
||||
}
|
||||
|
||||
bool inner_point(double x, double y) const
|
||||
{
|
||||
return (xmin<x) && (xmax>x) && (ymin<y) && (ymax>x);
|
||||
}
|
||||
|
||||
int overlaps(const MBR *mbr)
|
||||
{
|
||||
int lb = mbr->inner_point(xmin, ymin);
|
||||
int rb = mbr->inner_point(xmax, ymin);
|
||||
int rt = mbr->inner_point(xmax, ymax);
|
||||
int lt = mbr->inner_point(xmin, ymax);
|
||||
|
||||
int a = lb+rb+rt+lt;
|
||||
return (a>0) && (a<4) && (!within(mbr));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/***************************** Geometry *******************************/
|
||||
|
||||
class Geometry;
|
||||
|
||||
typedef int (Geometry::*GF_InitFromText)(GTextReadStream *, String *);
|
||||
typedef int (Geometry::*GF_GetDataAsText)(String *) const;
|
||||
typedef size_t (Geometry::*GF_GetDataSize)() const;
|
||||
typedef int (Geometry::*GF_GetMBR)(MBR *) const;
|
||||
|
||||
typedef int (Geometry::*GF_GetD)(double *) const;
|
||||
typedef int (Geometry::*GF_GetI)(int *) const;
|
||||
typedef int (Geometry::*GF_GetUI)(uint32 *) const;
|
||||
typedef int (Geometry::*GF_GetWS)(String *) const;
|
||||
typedef int (Geometry::*GF_GetUIWS)(uint32, String *) const;
|
||||
|
||||
#define GEOM_METHOD_PRESENT(geom_obj, method)\
|
||||
(geom_obj.m_vmt->method != &Geometry::method)
|
||||
|
||||
class Geometry
|
||||
{
|
||||
public:
|
||||
enum wkbType
|
||||
{
|
||||
wkbPoint = 1,
|
||||
wkbLineString = 2,
|
||||
wkbPolygon = 3,
|
||||
wkbMultiPoint = 4,
|
||||
wkbMultiLineString = 5,
|
||||
wkbMultiPolygon = 6,
|
||||
wkbGeometryCollection = 7
|
||||
};
|
||||
enum wkbByteOrder
|
||||
{
|
||||
wkbXDR = 0, /* Big Endian */
|
||||
wkbNDR = 1 /* Little Endian */
|
||||
};
|
||||
|
||||
|
||||
class GClassInfo
|
||||
{
|
||||
public:
|
||||
GF_InitFromText init_from_text;
|
||||
GF_GetDataAsText get_data_as_text;
|
||||
GF_GetDataSize get_data_size;
|
||||
GF_GetMBR get_mbr;
|
||||
GF_GetD get_x;
|
||||
GF_GetD get_y;
|
||||
GF_GetD length;
|
||||
GF_GetD area;
|
||||
|
||||
GF_GetI is_closed;
|
||||
|
||||
GF_GetUI num_interior_ring;
|
||||
GF_GetUI num_points;
|
||||
GF_GetUI num_geometries;
|
||||
GF_GetUI dimension;
|
||||
|
||||
GF_GetWS start_point;
|
||||
GF_GetWS end_point;
|
||||
GF_GetWS exterior_ring;
|
||||
GF_GetWS centroid;
|
||||
|
||||
GF_GetUIWS point_n;
|
||||
GF_GetUIWS interior_ring_n;
|
||||
GF_GetUIWS geometry_n;
|
||||
|
||||
int m_type_id;
|
||||
const char *m_name;
|
||||
GClassInfo *m_next_rt;
|
||||
};
|
||||
GClassInfo *m_vmt;
|
||||
|
||||
const GClassInfo *get_class_info() const { return m_vmt; }
|
||||
size_t get_data_size() const { return (this->*m_vmt->get_data_size)(); }
|
||||
|
||||
int init_from_text(GTextReadStream *trs, String *wkb)
|
||||
{ return (this->*m_vmt->init_from_text)(trs, wkb); }
|
||||
|
||||
int get_data_as_text(String *txt) const
|
||||
{ return (this->*m_vmt->get_data_as_text)(txt); }
|
||||
|
||||
int get_mbr(MBR *mbr) const { return (this->*m_vmt->get_mbr)(mbr); }
|
||||
int dimension(uint32 *dim) const
|
||||
{ return (this->*m_vmt->dimension)(dim); }
|
||||
|
||||
int get_x(double *x) const { return (this->*m_vmt->get_x)(x); }
|
||||
int get_y(double *y) const { return (this->*m_vmt->get_y)(y); }
|
||||
int length(double *len) const { return (this->*m_vmt->length)(len); }
|
||||
int area(double *ar) const { return (this->*m_vmt->area)(ar); }
|
||||
|
||||
int is_closed(int *closed) const { return (this->*m_vmt->is_closed)(closed); }
|
||||
|
||||
int num_interior_ring(uint32 *n_int_rings) const
|
||||
{ return (this->*m_vmt->num_interior_ring)(n_int_rings); }
|
||||
int num_points(uint32 *n_points) const
|
||||
{ return (this->*m_vmt->num_points)(n_points); }
|
||||
|
||||
int num_geometries(uint32 *num) const
|
||||
{ return (this->*m_vmt->num_geometries)(num); }
|
||||
|
||||
int start_point(String *point) const
|
||||
{ return (this->*m_vmt->start_point)(point); }
|
||||
int end_point(String *point) const
|
||||
{ return (this->*m_vmt->end_point)(point); }
|
||||
int exterior_ring(String *ring) const
|
||||
{ return (this->*m_vmt->exterior_ring)(ring); }
|
||||
int centroid(String *point) const
|
||||
{ return (this->*m_vmt->centroid)(point); }
|
||||
|
||||
int point_n(uint32 num, String *result) const
|
||||
{ return (this->*m_vmt->point_n)(num, result); }
|
||||
int interior_ring_n(uint32 num, String *result) const
|
||||
{ return (this->*m_vmt->interior_ring_n)(num, result); }
|
||||
int geometry_n(uint32 num, String *result) const
|
||||
{ return (this->*m_vmt->geometry_n)(num, result); }
|
||||
|
||||
public:
|
||||
int create_from_wkb(const char *data, uint32 data_len);
|
||||
int create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream=1);
|
||||
int init(int type_id)
|
||||
{
|
||||
m_vmt = find_class(type_id);
|
||||
return !m_vmt;
|
||||
}
|
||||
int new_geometry(const char *name, size_t len)
|
||||
{
|
||||
m_vmt = find_class(name, len);
|
||||
return !m_vmt;
|
||||
}
|
||||
|
||||
int as_wkt(String *wkt) const
|
||||
{
|
||||
if(wkt->reserve(strlen(get_class_info()->m_name) + 2, 512))
|
||||
return 1;
|
||||
wkt->qs_append(get_class_info()->m_name);
|
||||
wkt->qs_append('(');
|
||||
if(get_data_as_text(wkt))
|
||||
return 1;
|
||||
wkt->qs_append(')');
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_from_wkb(const char *data, uint32 data_len)
|
||||
{
|
||||
m_data = data;
|
||||
m_data_end = data + data_len;
|
||||
}
|
||||
|
||||
void shift_wkb_header()
|
||||
{
|
||||
m_data += WKB_HEADER_SIZE;
|
||||
}
|
||||
|
||||
int envelope(String *result) const;
|
||||
|
||||
protected:
|
||||
static GClassInfo *find_class(int type_id);
|
||||
static GClassInfo *find_class(const char *name, size_t len);
|
||||
|
||||
bool no_data(const char *cur_data, uint32 data_amount) const
|
||||
{
|
||||
return cur_data + data_amount > m_data_end;
|
||||
}
|
||||
|
||||
const char *m_data;
|
||||
const char *m_data_end;
|
||||
};
|
||||
|
||||
/***************************** Point *******************************/
|
||||
|
||||
class GPoint: public Geometry
|
||||
{
|
||||
public:
|
||||
size_t get_data_size() const;
|
||||
int init_from_text(GTextReadStream *trs, String *wkb);
|
||||
int get_data_as_text(String *txt) const;
|
||||
int get_mbr(MBR *mbr) const;
|
||||
|
||||
int get_xy(double *x, double *y) const
|
||||
{
|
||||
const char *data = m_data;
|
||||
if(no_data(data, sizeof(double)) * 2) return 1;
|
||||
float8get(*x, data);
|
||||
float8get(*y, data + sizeof(double));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_x(double *x) const
|
||||
{
|
||||
if(no_data(m_data, sizeof(double))) return 1;
|
||||
float8get(*x, m_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_y(double *y) const
|
||||
{
|
||||
const char *data = m_data;
|
||||
if(no_data(data, sizeof(double)) * 2) return 1;
|
||||
float8get(*y, data + sizeof(double));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dimension(uint32 *dim) const { *dim = 0; return 0; }
|
||||
};
|
||||
|
||||
/***************************** LineString *******************************/
|
||||
|
||||
class GLineString: public Geometry
|
||||
{
|
||||
public:
|
||||
size_t get_data_size() const;
|
||||
int init_from_text(GTextReadStream *trs, String *wkb);
|
||||
int get_data_as_text(String *txt) const;
|
||||
int get_mbr(MBR *mbr) const;
|
||||
|
||||
int length(double *len) const;
|
||||
int is_closed(int *closed) const;
|
||||
int num_points(uint32 *n_points) const;
|
||||
int start_point(String *point) const;
|
||||
int end_point(String *point) const;
|
||||
int point_n(uint32 n, String *result) const;
|
||||
int dimension(uint32 *dim) const { *dim = 1; return 0; }
|
||||
// IsRing
|
||||
};
|
||||
|
||||
/***************************** Polygon *******************************/
|
||||
|
||||
class GPolygon: public Geometry
|
||||
{
|
||||
public:
|
||||
size_t get_data_size() const;
|
||||
int init_from_text(GTextReadStream *trs, String *wkb);
|
||||
int get_data_as_text(String *txt) const;
|
||||
int get_mbr(MBR *mbr) const;
|
||||
|
||||
int area(double *ar) const;
|
||||
int exterior_ring(String *result) const;
|
||||
int num_interior_ring(uint32 *n_int_rings) const;
|
||||
int interior_ring_n(uint32 num, String *result) const;
|
||||
int centroid_xy(double *x, double *y) const;
|
||||
int centroid(String *result) const;
|
||||
int dimension(uint32 *dim) const { *dim = 2; return 0; }
|
||||
// PointOnSurface
|
||||
};
|
||||
|
||||
/***************************** MultiPoint *******************************/
|
||||
|
||||
class GMultiPoint: public Geometry
|
||||
{
|
||||
public:
|
||||
size_t get_data_size() const;
|
||||
int init_from_text(GTextReadStream *trs, String *wkb);
|
||||
int get_data_as_text(String *txt) const;
|
||||
int get_mbr(MBR *mbr) const;
|
||||
int dimension(uint32 *dim) const { *dim = 0; return 0; }
|
||||
};
|
||||
|
||||
/***************************** MultiLineString *******************************/
|
||||
|
||||
class GMultiLineString: public Geometry
|
||||
{
|
||||
public:
|
||||
size_t get_data_size() const;
|
||||
int init_from_text(GTextReadStream *trs, String *wkb);
|
||||
int get_data_as_text(String *txt) const;
|
||||
int get_mbr(MBR *mbr) const;
|
||||
|
||||
int length(double *len) const;
|
||||
int is_closed(int *closed) const;
|
||||
int dimension(uint32 *dim) const { *dim = 1; return 0; }
|
||||
};
|
||||
|
||||
/***************************** MultiPolygon *******************************/
|
||||
|
||||
class GMultiPolygon: public Geometry
|
||||
{
|
||||
public:
|
||||
size_t get_data_size() const;
|
||||
int init_from_text(GTextReadStream *trs, String *wkb);
|
||||
int get_data_as_text(String *txt) const;
|
||||
int get_mbr(MBR *mbr) const;
|
||||
|
||||
int area(double *ar) const;
|
||||
int centroid(String *result) const;
|
||||
int dimension(uint32 *dim) const { *dim = 2; return 0; }
|
||||
// PointOnSurface
|
||||
};
|
||||
|
||||
/***************************** GeometryCollection *******************************/
|
||||
|
||||
class GGeometryCollection: public Geometry
|
||||
{
|
||||
public:
|
||||
size_t get_data_size() const;
|
||||
int init_from_text(GTextReadStream *trs, String *wkb);
|
||||
int get_data_as_text(String *txt) const;
|
||||
int get_mbr(MBR *mbr) const;
|
||||
|
||||
int num_geometries(uint32 *num) const;
|
||||
int geometry_n(uint32 num, String *result) const;
|
||||
|
||||
int dimension(uint32 *dim) const;
|
||||
};
|
||||
|
||||
#endif
|
@ -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
|
||||
|
||||
@ -713,21 +728,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
|
||||
@ -874,10 +890,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
|
||||
@ -942,6 +958,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;
|
||||
@ -1083,6 +1101,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; }
|
||||
|
||||
@ -1099,6 +1119,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); }
|
||||
@ -1684,6 +1714,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 ')'
|
||||
@ -1708,6 +1742,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 ')'
|
||||
@ -1720,6 +1757,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 ')'
|
||||
@ -1728,6 +1774,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 */
|
||||
|
24
sql/table.cc
24
sql/table.cc
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user