Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
735b27d5
Commit
735b27d5
authored
Feb 22, 2002
by
bar@gw.udmsearch.izhnet.ru
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added GIS extension
parent
fc74d81b
Changes
31
Show whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
3674 additions
and
48 deletions
+3674
-48
.bzrignore
.bzrignore
+2
-0
libmysqld/Makefile.am
libmysqld/Makefile.am
+2
-1
sql/Makefile.am
sql/Makefile.am
+2
-1
sql/field.cc
sql/field.cc
+55
-2
sql/field.h
sql/field.h
+29
-3
sql/gstream.cc
sql/gstream.cc
+137
-0
sql/gstream.h
sql/gstream.h
+61
-0
sql/ha_myisam.cc
sql/ha_myisam.cc
+5
-3
sql/item.h
sql/item.h
+1
-0
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+81
-0
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+79
-0
sql/item_create.cc
sql/item_create.cc
+155
-0
sql/item_create.h
sql/item_create.h
+38
-0
sql/item_func.cc
sql/item_func.cc
+129
-0
sql/item_func.h
sql/item_func.h
+86
-1
sql/item_strfunc.cc
sql/item_strfunc.cc
+330
-0
sql/item_strfunc.h
sql/item_strfunc.h
+193
-0
sql/lex.h
sql/lex.h
+43
-0
sql/opt_range.cc
sql/opt_range.cc
+100
-20
sql/opt_range.h
sql/opt_range.h
+6
-3
sql/opt_sum.cc
sql/opt_sum.cc
+1
-1
sql/spatial.cc
sql/spatial.cc
+1435
-0
sql/spatial.h
sql/spatial.h
+476
-0
sql/sql_class.h
sql/sql_class.h
+6
-1
sql/sql_show.cc
sql/sql_show.cc
+6
-0
sql/sql_string.cc
sql/sql_string.cc
+40
-0
sql/sql_string.h
sql/sql_string.h
+45
-0
sql/sql_table.cc
sql/sql_table.cc
+52
-5
sql/sql_yacc.yy
sql/sql_yacc.yy
+55
-6
sql/structs.h
sql/structs.h
+1
-0
sql/table.cc
sql/table.cc
+23
-1
No files found.
.bzrignore
View file @
735b27d5
...
...
@@ -460,3 +460,5 @@ vio/test-sslserver
vio/viotest-ssl
Docs/mysql.xml
mysql-test/r/rpl000001.eval
myisam/rt_test
myisam/sp_test
libmysqld/Makefile.am
View file @
735b27d5
...
...
@@ -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
...
...
sql/Makefile.am
View file @
735b27d5
...
...
@@ -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)
...
...
sql/field.cc
View file @
735b27d5
...
...
@@ -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
))
...
...
sql/field.h
View file @
735b27d5
...
...
@@ -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)
sql/gstream.cc
0 → 100644
View file @
735b27d5
#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
);
}
sql/gstream.h
0 → 100644
View file @
735b27d5
#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
sql/ha_myisam.cc
View file @
735b27d5
...
...
@@ -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
++
)
...
...
sql/item.h
View file @
735b27d5
...
...
@@ -357,6 +357,7 @@ public:
};
#include "spatial.h"
#include "item_sum.h"
#include "item_func.h"
#include "item_cmpfunc.h"
...
...
sql/item_cmpfunc.cc
View file @
735b27d5
...
...
@@ -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
;
}
sql/item_cmpfunc.h
View file @
735b27d5
...
...
@@ -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"
;
}
};
sql/item_create.cc
View file @
735b27d5
...
...
@@ -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
);
}
sql/item_create.h
View file @
735b27d5
...
...
@@ -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
);
sql/item_func.cc
View file @
735b27d5
...
...
@@ -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
;
}
sql/item_func.h
View file @
735b27d5
...
...
@@ -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:
...
...
sql/item_strfunc.cc
View file @
735b27d5
...
...
@@ -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
;
}
sql/item_strfunc.h
View file @
735b27d5
...
...
@@ -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"; }
};
*/
sql/lex.h
View file @
735b27d5
...
...
@@ -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
}
};
sql/opt_range.cc
View file @
735b27d5
...
...
@@ -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,10 +2345,15 @@ 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
((
flag
&
GEOM_FLAG
)
==
0
)
{
if
(
tmp_min_key
!=
param
->
min_key
)
flag
&=
~
NO_MIN_RANGE
;
else
...
...
@@ -2306,7 +2362,7 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *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
)
...
...
sql/opt_range.h
View file @
735b27d5
...
...
@@ -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
;
Field
::
imagetype
image_type
;
}
KEY_PART
;
class
QUICK_RANGE
:
public
Sql_alloc
{
...
...
sql/opt_sum.cc
View file @
735b27d5
...
...
@@ -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
;
}
...
...
sql/spatial.cc
0 → 100644
View file @
735b27d5
#include "mysql_priv.h"
#define MAX_DIGITS_IN_DOUBLE 16
/***************************** GClassInfo *******************************/
#define IMPLEMENT_GEOM(class_name, type_id, name) \
{ \
(GF_InitFromText) &class_name::init_from_text, \
(GF_GetDataAsText) &class_name::get_data_as_text, \
(GF_GetDataSize) &class_name::get_data_size, \
(GF_GetMBR) &class_name::get_mbr, \
(GF_GetD) &class_name::get_x, \
(GF_GetD) &class_name::get_y, \
(GF_GetD) &class_name::length, \
(GF_GetD) &class_name::area, \
(GF_GetI) &class_name::is_closed, \
(GF_GetUI) &class_name::num_interior_ring, \
(GF_GetUI) &class_name::num_points, \
(GF_GetUI) &class_name::num_geometries, \
(GF_GetUI) &class_name::dimension, \
(GF_GetWS) &class_name::start_point, \
(GF_GetWS) &class_name::end_point, \
(GF_GetWS) &class_name::exterior_ring, \
(GF_GetWS) &class_name::centroid, \
(GF_GetUIWS) &class_name::point_n, \
(GF_GetUIWS) &class_name::interior_ring_n, \
(GF_GetUIWS) &class_name::geometry_n, \
class_name::type_id, \
name, \
NULL \
},
static
Geometry
::
GClassInfo
ci_collection
[]
=
{
IMPLEMENT_GEOM
(
GPoint
,
wkbPoint
,
"POINT"
)
IMPLEMENT_GEOM
(
GLineString
,
wkbLineString
,
"LINESTRING"
)
IMPLEMENT_GEOM
(
GPolygon
,
wkbPolygon
,
"POLYGON"
)
IMPLEMENT_GEOM
(
GMultiPoint
,
wkbMultiPoint
,
"MULTIPOINT"
)
IMPLEMENT_GEOM
(
GMultiLineString
,
wkbMultiLineString
,
"MULTILINESTRING"
)
IMPLEMENT_GEOM
(
GMultiPolygon
,
wkbMultiPolygon
,
"MULTIPOLYGON"
)
IMPLEMENT_GEOM
(
GGeometryCollection
,
wkbGeometryCollection
,
"GEOMETRYCOLLECTION"
)
};
static
Geometry
::
GClassInfo
*
ci_collection_end
=
ci_collection
+
sizeof
(
ci_collection
);
/***************************** Geometry *******************************/
Geometry
::
GClassInfo
*
Geometry
::
find_class
(
int
type_id
)
{
for
(
GClassInfo
*
cur_rt
=
ci_collection
;
cur_rt
<
ci_collection_end
;
++
cur_rt
)
{
if
(
cur_rt
->
m_type_id
==
type_id
)
{
return
cur_rt
;
}
}
return
NULL
;
}
Geometry
::
GClassInfo
*
Geometry
::
find_class
(
const
char
*
name
,
size_t
len
)
{
for
(
GClassInfo
*
cur_rt
=
ci_collection
;
cur_rt
<
ci_collection_end
;
++
cur_rt
)
{
if
((
cur_rt
->
m_name
[
len
]
==
0
)
&&
(
strncmp
(
cur_rt
->
m_name
,
name
,
len
)
==
0
))
{
return
cur_rt
;
}
}
return
NULL
;
}
int
Geometry
::
create_from_wkb
(
const
char
*
data
,
uint32
data_len
)
{
uint32
geom_type
;
if
(
data_len
<
1
+
4
)
return
1
;
data
+=
sizeof
(
char
);
//FIXME: check byte ordering
geom_type
=
uint4korr
(
data
);
data
+=
4
;
m_vmt
=
find_class
(
geom_type
);
if
(
!
m_vmt
)
return
-
1
;
m_data
=
data
;
m_data_end
=
data
+
data_len
;
return
0
;
}
int
Geometry
::
create_from_wkt
(
GTextReadStream
*
trs
,
String
*
wkt
,
int
init_stream
)
{
int
name_len
;
const
char
*
name
=
trs
->
get_next_word
(
&
name_len
);
if
(
!
name
)
{
trs
->
set_error_msg
(
"Geometry name expected"
);
return
-
1
;
}
if
(
!
(
m_vmt
=
find_class
(
name
,
name_len
)))
return
-
1
;
if
(
wkt
->
reserve
(
1
+
4
,
512
))
return
1
;
wkt
->
q_append
((
char
)
wkbNDR
);
wkt
->
q_append
((
uint32
)
get_class_info
()
->
m_type_id
);
if
(
trs
->
get_next_symbol
()
!=
'('
)
{
trs
->
set_error_msg
(
"'(' expected"
);
return
-
1
;
}
if
(
init_from_text
(
trs
,
wkt
))
return
1
;
if
(
trs
->
get_next_symbol
()
!=
')'
)
{
trs
->
set_error_msg
(
"')' expected"
);
return
-
1
;
}
if
(
init_stream
)
{
init_from_wkb
(
wkt
->
ptr
(),
wkt
->
length
());
shift_wkb_header
();
}
return
0
;
}
int
Geometry
::
envelope
(
String
*
result
)
const
{
MBR
mbr
;
get_mbr
(
&
mbr
);
if
(
result
->
reserve
(
1
+
4
*
3
+
sizeof
(
double
)
*
10
))
return
1
;
result
->
q_append
((
char
)
wkbNDR
);
result
->
q_append
((
uint32
)
wkbPolygon
);
result
->
q_append
((
uint32
)
1
);
result
->
q_append
((
uint32
)
5
);
result
->
q_append
(
mbr
.
xmin
);
result
->
q_append
(
mbr
.
ymin
);
result
->
q_append
(
mbr
.
xmax
);
result
->
q_append
(
mbr
.
ymin
);
result
->
q_append
(
mbr
.
xmax
);
result
->
q_append
(
mbr
.
ymax
);
result
->
q_append
(
mbr
.
xmin
);
result
->
q_append
(
mbr
.
ymax
);
result
->
q_append
(
mbr
.
xmin
);
result
->
q_append
(
mbr
.
ymin
);
return
0
;
}
/***************************** Point *******************************/
size_t
GPoint
::
get_data_size
()
const
{
return
POINT_DATA_SIZE
;
}
int
GPoint
::
init_from_text
(
GTextReadStream
*
trs
,
String
*
wkb
)
{
double
x
,
y
;
if
(
wkb
->
reserve
(
sizeof
(
double
)
*
2
))
return
1
;
if
(
trs
->
get_next_number
(
&
x
))
return
1
;
if
(
trs
->
get_next_number
(
&
y
))
return
1
;
wkb
->
q_append
(
x
);
wkb
->
q_append
(
y
);
return
0
;
}
int
GPoint
::
get_data_as_text
(
String
*
txt
)
const
{
double
x
,
y
;
if
(
get_xy
(
&
x
,
&
y
))
return
1
;
if
(
txt
->
reserve
(
MAX_DIGITS_IN_DOUBLE
*
2
+
1
))
return
1
;
txt
->
qs_append
(
x
);
txt
->
qs_append
(
' '
);
txt
->
qs_append
(
y
);
return
0
;
}
int
GPoint
::
get_mbr
(
MBR
*
mbr
)
const
{
double
x
,
y
;
if
(
get_xy
(
&
x
,
&
y
))
return
1
;
mbr
->
add_xy
(
x
,
y
);
return
0
;
}
/***************************** LineString *******************************/
size_t
GLineString
::
get_data_size
()
const
{
uint32
n_points
=
uint4korr
(
m_data
);
return
4
+
n_points
*
POINT_DATA_SIZE
;
}
int
GLineString
::
init_from_text
(
GTextReadStream
*
trs
,
String
*
wkb
)
{
uint32
n_points
=
0
;
int
np_pos
=
wkb
->
length
();
GPoint
p
;
if
(
wkb
->
reserve
(
4
,
512
))
return
1
;
wkb
->
q_append
((
uint32
)
n_points
);
for
(;;)
{
if
(
p
.
init_from_text
(
trs
,
wkb
))
return
1
;
++
n_points
;
if
(
trs
->
get_next_toc_type
()
==
GTextReadStream
::
comma
)
trs
->
get_next_symbol
();
else
break
;
}
if
(
n_points
<
2
)
{
trs
->
set_error_msg
(
"Too few points in LINESTRING"
);
return
1
;
}
wkb
->
WriteAtPosition
(
np_pos
,
n_points
);
return
0
;
}
int
GLineString
::
get_data_as_text
(
String
*
txt
)
const
{
uint32
n_points
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_points
=
uint4korr
(
data
);
data
+=
4
;
if
(
no_data
(
data
,
sizeof
(
double
)
*
2
*
n_points
))
return
1
;
if
(
txt
->
reserve
(((
MAX_DIGITS_IN_DOUBLE
+
1
)
*
2
+
1
)
*
n_points
))
return
1
;
for
(;
n_points
>
0
;
--
n_points
)
{
double
x
,
y
;
float8get
(
x
,
data
);
data
+=
sizeof
(
double
);
float8get
(
y
,
data
);
data
+=
sizeof
(
double
);
txt
->
qs_append
(
x
);
txt
->
qs_append
(
' '
);
txt
->
qs_append
(
y
);
txt
->
qs_append
(
','
);
}
txt
->
length
(
txt
->
length
()
-
1
);
return
0
;
}
int
GLineString
::
get_mbr
(
MBR
*
mbr
)
const
{
uint32
n_points
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_points
=
uint4korr
(
data
);
data
+=
4
;
if
(
no_data
(
data
,
sizeof
(
double
)
*
2
*
n_points
))
return
1
;
for
(;
n_points
>
0
;
--
n_points
)
{
mbr
->
add_xy
((
double
*
)
data
,
(
double
*
)(
data
+
8
));
data
+=
8
+
8
;
}
return
0
;
}
int
GLineString
::
length
(
double
*
len
)
const
{
uint32
n_points
;
double
prev_x
,
prev_y
;
const
char
*
data
=
m_data
;
*
len
=
0
;
if
(
no_data
(
data
,
4
))
return
1
;
n_points
=
uint4korr
(
data
);
data
+=
4
;
if
(
no_data
(
data
,
sizeof
(
double
)
*
2
*
n_points
))
return
1
;
--
n_points
;
float8get
(
prev_x
,
data
);
data
+=
8
;
float8get
(
prev_y
,
data
);
data
+=
8
;
for
(;
n_points
>
0
;
--
n_points
)
{
double
x
,
y
;
float8get
(
x
,
data
);
data
+=
8
;
float8get
(
y
,
data
);
data
+=
8
;
*
len
+=
sqrt
(
pow
(
prev_x
-
x
,
2
)
+
pow
(
prev_y
-
y
,
2
));
prev_x
=
x
;
prev_y
=
y
;
}
return
0
;
}
int
GLineString
::
is_closed
(
int
*
closed
)
const
{
uint32
n_points
;
double
x1
,
y1
,
x2
,
y2
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_points
=
uint4korr
(
data
);
data
+=
4
;
if
(
no_data
(
data
,
(
8
+
8
)
*
n_points
))
return
1
;
float8get
(
x1
,
data
);
data
+=
8
;
float8get
(
y1
,
data
);
data
+=
8
+
(
n_points
-
2
)
*
POINT_DATA_SIZE
;
float8get
(
x2
,
data
);
data
+=
8
;
float8get
(
y2
,
data
);
*
closed
=
(
x1
==
x2
)
&&
(
y1
==
y2
);
return
0
;
}
int
GLineString
::
num_points
(
uint32
*
n_points
)
const
{
*
n_points
=
uint4korr
(
m_data
);
return
0
;
}
int
GLineString
::
start_point
(
String
*
result
)
const
{
const
char
*
data
=
m_data
+
4
;
if
(
no_data
(
data
,
8
+
8
))
return
1
;
if
(
result
->
reserve
(
1
+
4
+
sizeof
(
double
)
*
2
))
return
1
;
result
->
q_append
((
char
)
wkbNDR
);
result
->
q_append
((
uint32
)
wkbPoint
);
result
->
q_append
((
double
*
)
data
);
result
->
q_append
((
double
*
)(
data
+
8
));
return
0
;
}
int
GLineString
::
end_point
(
String
*
result
)
const
{
const
char
*
data
=
m_data
;
uint32
n_points
;
if
(
no_data
(
data
,
4
))
return
1
;
n_points
=
uint4korr
(
data
);
data
+=
4
+
(
n_points
-
1
)
*
POINT_DATA_SIZE
;
if
(
no_data
(
data
,
8
+
8
))
return
1
;
if
(
result
->
reserve
(
1
+
4
+
sizeof
(
double
)
*
2
))
return
1
;
result
->
q_append
((
char
)
wkbNDR
);
result
->
q_append
((
uint32
)
wkbPoint
);
result
->
q_append
((
double
*
)
data
);
result
->
q_append
((
double
*
)(
data
+
8
));
return
0
;
}
int
GLineString
::
point_n
(
uint32
num
,
String
*
result
)
const
{
const
char
*
data
=
m_data
;
uint32
n_points
;
if
(
no_data
(
data
,
4
))
return
1
;
n_points
=
uint4korr
(
data
);
if
((
uint32
)(
num
-
1
)
>=
n_points
)
// really means (num > n_points || num < 1)
return
1
;
data
+=
4
+
(
num
-
1
)
*
POINT_DATA_SIZE
;
if
(
no_data
(
data
,
8
+
8
))
return
1
;
if
(
result
->
reserve
(
1
+
4
+
sizeof
(
double
)
*
2
))
return
1
;
result
->
q_append
((
char
)
wkbNDR
);
result
->
q_append
((
uint32
)
wkbPoint
);
result
->
q_append
((
double
*
)
data
);
result
->
q_append
((
double
*
)(
data
+
8
));
return
0
;
}
/***************************** Polygon *******************************/
size_t
GPolygon
::
get_data_size
()
const
{
uint32
n_linear_rings
=
0
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_linear_rings
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_linear_rings
>
0
;
--
n_linear_rings
)
{
if
(
no_data
(
data
,
4
))
return
1
;
data
+=
4
+
uint4korr
(
data
)
*
POINT_DATA_SIZE
;
}
return
data
-
m_data
;
}
int
GPolygon
::
init_from_text
(
GTextReadStream
*
trs
,
String
*
wkb
)
{
uint32
n_linear_rings
=
0
;
int
lr_pos
=
wkb
->
length
();
if
(
wkb
->
reserve
(
4
,
512
))
return
1
;
wkb
->
q_append
((
uint32
)
n_linear_rings
);
for
(;;)
{
GLineString
ls
;
size_t
ls_pos
=
wkb
->
length
();
if
(
trs
->
get_next_symbol
()
!=
'('
)
{
trs
->
set_error_msg
(
"'(' expected"
);
return
1
;
}
if
(
ls
.
init_from_text
(
trs
,
wkb
))
return
1
;
if
(
trs
->
get_next_symbol
()
!=
')'
)
{
trs
->
set_error_msg
(
"')' expected"
);
return
1
;
}
ls
.
init_from_wkb
(
wkb
->
ptr
()
+
ls_pos
,
wkb
->
length
()
-
ls_pos
);
int
closed
;
ls
.
is_closed
(
&
closed
);
if
(
!
closed
)
{
trs
->
set_error_msg
(
"POLYGON's linear ring isn't closed"
);
return
1
;
}
++
n_linear_rings
;
if
(
trs
->
get_next_toc_type
()
==
GTextReadStream
::
comma
)
trs
->
get_next_symbol
();
else
break
;
}
wkb
->
WriteAtPosition
(
lr_pos
,
n_linear_rings
);
return
0
;
}
int
GPolygon
::
get_data_as_text
(
String
*
txt
)
const
{
uint32
n_linear_rings
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_linear_rings
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_linear_rings
>
0
;
--
n_linear_rings
)
{
if
(
no_data
(
data
,
4
))
return
1
;
uint32
n_points
=
uint4korr
(
data
);
data
+=
4
;
if
(
no_data
(
data
,
(
8
+
8
)
*
n_points
))
return
1
;
if
(
txt
->
reserve
(
2
+
((
MAX_DIGITS_IN_DOUBLE
+
1
)
*
2
+
1
)
*
n_points
))
return
1
;
txt
->
qs_append
(
'('
);
for
(;
n_points
>
0
;
--
n_points
)
{
txt
->
qs_append
((
double
*
)
data
);
txt
->
qs_append
(
' '
);
txt
->
qs_append
((
double
*
)(
data
+
8
));
txt
->
qs_append
(
','
);
data
+=
8
+
8
;
}
(
*
txt
)[
txt
->
length
()
-
1
]
=
')'
;
txt
->
qs_append
(
','
);
}
txt
->
length
(
txt
->
length
()
-
1
);
return
0
;
}
int
GPolygon
::
get_mbr
(
MBR
*
mbr
)
const
{
uint32
n_linear_rings
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_linear_rings
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_linear_rings
>
0
;
--
n_linear_rings
)
{
if
(
no_data
(
data
,
4
))
return
1
;
uint32
n_points
=
uint4korr
(
data
);
data
+=
4
;
if
(
no_data
(
data
,
(
8
+
8
)
*
n_points
))
return
1
;
for
(;
n_points
>
0
;
--
n_points
)
{
mbr
->
add_xy
((
double
*
)
data
,
(
double
*
)(
data
+
8
));
data
+=
8
+
8
;
}
}
return
0
;
}
int
GPolygon
::
area
(
double
*
ar
)
const
{
uint32
n_linear_rings
;
double
result
=
-
1.0
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_linear_rings
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_linear_rings
>
0
;
--
n_linear_rings
)
{
double
prev_x
,
prev_y
;
double
lr_area
=
0
;
if
(
no_data
(
data
,
4
))
return
1
;
uint32
n_points
=
uint4korr
(
data
);
if
(
no_data
(
data
,
(
8
+
8
)
*
n_points
))
return
1
;
float8get
(
prev_x
,
data
+
4
);
float8get
(
prev_y
,
data
+
(
4
+
8
));
data
+=
(
4
+
8
+
8
);
--
n_points
;
for
(;
n_points
>
0
;
--
n_points
)
{
double
x
,
y
;
float8get
(
x
,
data
);
float8get
(
y
,
data
+
8
);
lr_area
+=
(
prev_x
+
x
)
*
(
prev_y
-
y
);
prev_x
=
x
;
prev_y
=
y
;
data
+=
(
8
+
8
);
}
lr_area
=
fabs
(
lr_area
)
/
2
;
if
(
result
==-
1
)
result
=
lr_area
;
else
result
-=
lr_area
;
}
*
ar
=
fabs
(
result
);
return
0
;
}
int
GPolygon
::
exterior_ring
(
String
*
result
)
const
{
uint32
n_points
;
const
char
*
data
=
m_data
+
4
;
// skip n_linerings
if
(
no_data
(
data
,
4
))
return
1
;
n_points
=
uint4korr
(
data
);
data
+=
4
;
if
(
no_data
(
data
,
n_points
*
POINT_DATA_SIZE
))
return
1
;
if
(
result
->
reserve
(
1
+
4
+
4
+
n_points
*
POINT_DATA_SIZE
))
return
1
;
result
->
q_append
((
char
)
wkbNDR
);
result
->
q_append
((
uint32
)
wkbLineString
);
result
->
q_append
(
n_points
);
result
->
q_append
(
data
,
n_points
*
POINT_DATA_SIZE
);
return
0
;
}
int
GPolygon
::
num_interior_ring
(
uint32
*
n_int_rings
)
const
{
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
*
n_int_rings
=
uint4korr
(
data
);
--
(
*
n_int_rings
);
return
0
;
}
int
GPolygon
::
interior_ring_n
(
uint32
num
,
String
*
result
)
const
{
const
char
*
data
=
m_data
;
uint32
n_linear_rings
;
uint32
n_points
;
if
(
no_data
(
data
,
4
))
return
1
;
n_linear_rings
=
uint4korr
(
data
);
data
+=
4
;
if
((
num
>=
n_linear_rings
)
||
(
num
<
1
))
return
-
1
;
for
(;
num
>
0
;
--
num
)
{
if
(
no_data
(
data
,
4
))
return
1
;
data
+=
4
+
uint4korr
(
data
)
*
POINT_DATA_SIZE
;
}
if
(
no_data
(
data
,
4
))
return
1
;
n_points
=
uint4korr
(
data
);
int
points_size
=
n_points
*
POINT_DATA_SIZE
;
data
+=
4
;
if
(
no_data
(
data
,
points_size
))
return
1
;
if
(
result
->
reserve
(
1
+
4
+
4
+
points_size
))
return
1
;
result
->
q_append
((
char
)
wkbNDR
);
result
->
q_append
((
uint32
)
wkbLineString
);
result
->
q_append
(
n_points
);
result
->
q_append
(
data
,
points_size
);
return
0
;
}
int
GPolygon
::
centroid_xy
(
double
*
x
,
double
*
y
)
const
{
uint32
n_linear_rings
;
uint32
i
;
double
res_area
,
res_cx
,
res_cy
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_linear_rings
=
uint4korr
(
data
);
data
+=
4
;
for
(
i
=
0
;
i
<
n_linear_rings
;
++
i
)
{
if
(
no_data
(
data
,
4
))
return
1
;
uint32
n_points
=
uint4korr
(
data
);
double
prev_x
,
prev_y
;
double
cur_area
=
0
;
double
cur_cx
=
0
;
double
cur_cy
=
0
;
data
+=
4
;
if
(
no_data
(
data
,
(
8
+
8
)
*
n_points
))
return
1
;
float8get
(
prev_x
,
data
);
float8get
(
prev_y
,
data
+
8
);
data
+=
(
8
+
8
);
uint32
n
=
n_points
-
1
;
for
(;
n
>
0
;
--
n
)
{
double
x
,
y
;
float8get
(
x
,
data
);
float8get
(
y
,
data
+
8
);
cur_area
+=
(
prev_x
+
x
)
*
(
prev_y
-
y
);
cur_cx
+=
x
;
cur_cy
+=
y
;
prev_x
=
x
;
prev_y
=
y
;
data
+=
(
8
+
8
);
}
cur_area
=
fabs
(
cur_area
)
/
2
;
cur_cx
=
cur_cx
/
(
n_points
-
1
);
cur_cy
=
cur_cy
/
(
n_points
-
1
);
if
(
i
)
{
double
d_area
=
res_area
-
cur_area
;
if
(
d_area
<=
0
)
return
1
;
res_cx
=
(
res_area
*
res_cx
-
cur_area
*
cur_cx
)
/
d_area
;
res_cy
=
(
res_area
*
res_cy
-
cur_area
*
cur_cy
)
/
d_area
;
}
else
{
res_area
=
cur_area
;
res_cx
=
cur_cx
;
res_cy
=
cur_cy
;
}
}
*
x
=
res_cx
;
*
y
=
res_cy
;
return
0
;
}
int
GPolygon
::
centroid
(
String
*
result
)
const
{
double
x
,
y
;
this
->
centroid_xy
(
&
x
,
&
y
);
if
(
result
->
reserve
(
1
+
4
+
sizeof
(
double
)
*
2
))
return
1
;
result
->
q_append
((
char
)
wkbNDR
);
result
->
q_append
((
uint32
)
wkbPoint
);
result
->
q_append
(
x
);
result
->
q_append
(
y
);
return
0
;
}
/***************************** MultiPoint *******************************/
size_t
GMultiPoint
::
get_data_size
()
const
{
return
4
+
uint4korr
(
m_data
)
*
(
POINT_DATA_SIZE
+
WKB_HEADER_SIZE
);
}
int
GMultiPoint
::
init_from_text
(
GTextReadStream
*
trs
,
String
*
wkb
)
{
uint32
n_points
=
0
;
int
np_pos
=
wkb
->
length
();
GPoint
p
;
if
(
wkb
->
reserve
(
4
,
512
))
return
1
;
wkb
->
q_append
((
uint32
)
n_points
);
for
(;;)
{
if
(
wkb
->
reserve
(
1
+
4
,
512
))
return
1
;
wkb
->
q_append
((
char
)
wkbNDR
);
wkb
->
q_append
((
uint32
)
wkbPoint
);
if
(
p
.
init_from_text
(
trs
,
wkb
))
return
1
;
++
n_points
;
if
(
trs
->
get_next_toc_type
()
==
GTextReadStream
::
comma
)
trs
->
get_next_symbol
();
else
break
;
}
wkb
->
WriteAtPosition
(
np_pos
,
n_points
);
return
0
;
}
int
GMultiPoint
::
get_data_as_text
(
String
*
txt
)
const
{
uint32
n_points
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_points
=
uint4korr
(
data
);
data
+=
4
;
if
(
no_data
(
data
,
n_points
*
(
8
+
8
+
WKB_HEADER_SIZE
)))
return
1
;
if
(
txt
->
reserve
(((
MAX_DIGITS_IN_DOUBLE
+
1
)
*
2
+
1
)
*
n_points
))
return
1
;
for
(;
n_points
>
0
;
--
n_points
)
{
txt
->
qs_append
((
double
*
)(
data
+
WKB_HEADER_SIZE
));
txt
->
qs_append
(
' '
);
txt
->
qs_append
((
double
*
)(
data
+
(
8
+
WKB_HEADER_SIZE
)));
txt
->
qs_append
(
','
);
data
+=
8
+
8
+
WKB_HEADER_SIZE
;
}
txt
->
length
(
txt
->
length
()
-
1
);
return
0
;
}
int
GMultiPoint
::
get_mbr
(
MBR
*
mbr
)
const
{
uint32
n_points
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_points
=
uint4korr
(
data
);
data
+=
4
;
if
(
no_data
(
data
,
n_points
*
(
8
+
8
+
WKB_HEADER_SIZE
)))
return
1
;
for
(;
n_points
>
0
;
--
n_points
)
{
mbr
->
add_xy
((
double
*
)(
data
+
WKB_HEADER_SIZE
),
(
double
*
)(
data
+
8
+
WKB_HEADER_SIZE
));
data
+=
(
8
+
8
+
WKB_HEADER_SIZE
);
}
return
0
;
}
/***************************** MultiLineString *******************************/
size_t
GMultiLineString
::
get_data_size
()
const
{
uint32
n_line_strings
=
0
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_line_strings
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_line_strings
>
0
;
--
n_line_strings
)
{
if
(
no_data
(
data
,
WKB_HEADER_SIZE
+
4
))
return
1
;
data
+=
WKB_HEADER_SIZE
+
4
+
uint4korr
(
data
+
WKB_HEADER_SIZE
)
*
POINT_DATA_SIZE
;
}
return
data
-
m_data
;
}
int
GMultiLineString
::
init_from_text
(
GTextReadStream
*
trs
,
String
*
wkb
)
{
uint32
n_line_strings
=
0
;
int
ls_pos
=
wkb
->
length
();
if
(
wkb
->
reserve
(
4
,
512
))
return
1
;
wkb
->
q_append
((
uint32
)
n_line_strings
);
for
(;;)
{
GLineString
ls
;
if
(
wkb
->
reserve
(
1
+
4
,
512
))
return
1
;
wkb
->
q_append
((
char
)
wkbNDR
);
wkb
->
q_append
((
uint32
)
wkbLineString
);
if
(
trs
->
get_next_symbol
()
!=
'('
)
{
trs
->
set_error_msg
(
"'(' expected"
);
return
1
;
}
if
(
ls
.
init_from_text
(
trs
,
wkb
))
return
1
;
if
(
trs
->
get_next_symbol
()
!=
')'
)
{
trs
->
set_error_msg
(
"')' expected"
);
return
1
;
}
++
n_line_strings
;
if
(
trs
->
get_next_toc_type
()
==
GTextReadStream
::
comma
)
trs
->
get_next_symbol
();
else
break
;
}
wkb
->
WriteAtPosition
(
ls_pos
,
n_line_strings
);
return
0
;
}
int
GMultiLineString
::
get_data_as_text
(
String
*
txt
)
const
{
uint32
n_line_strings
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_line_strings
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_line_strings
>
0
;
--
n_line_strings
)
{
if
(
no_data
(
data
,
(
WKB_HEADER_SIZE
+
4
)))
return
1
;
uint32
n_points
=
uint4korr
(
data
+
WKB_HEADER_SIZE
);
data
+=
WKB_HEADER_SIZE
+
4
;
if
(
no_data
(
data
,
n_points
*
(
8
+
8
)))
return
1
;
if
(
txt
->
reserve
(
2
+
((
MAX_DIGITS_IN_DOUBLE
+
1
)
*
2
+
1
)
*
n_points
))
return
1
;
txt
->
qs_append
(
'('
);
for
(;
n_points
>
0
;
--
n_points
)
{
txt
->
qs_append
((
double
*
)
data
);
txt
->
qs_append
(
' '
);
txt
->
qs_append
((
double
*
)(
data
+
8
));
txt
->
qs_append
(
','
);
data
+=
8
+
8
;
}
(
*
txt
)[
txt
->
length
()
-
1
]
=
')'
;
txt
->
qs_append
(
','
);
}
txt
->
length
(
txt
->
length
()
-
1
);
return
0
;
}
int
GMultiLineString
::
get_mbr
(
MBR
*
mbr
)
const
{
uint32
n_line_strings
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_line_strings
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_line_strings
>
0
;
--
n_line_strings
)
{
if
(
no_data
(
data
,
WKB_HEADER_SIZE
+
4
))
return
1
;
uint32
n_points
=
uint4korr
(
data
+
WKB_HEADER_SIZE
);
data
+=
4
+
WKB_HEADER_SIZE
;
if
(
no_data
(
data
,
(
8
+
8
)
*
n_points
))
return
1
;
for
(;
n_points
>
0
;
--
n_points
)
{
mbr
->
add_xy
((
double
*
)
data
,
(
double
*
)(
data
+
8
));
data
+=
8
+
8
;
}
}
return
0
;
}
int
GMultiLineString
::
length
(
double
*
len
)
const
{
uint32
n_line_strings
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_line_strings
=
uint4korr
(
data
);
data
+=
4
;
*
len
=
0
;
for
(;
n_line_strings
>
0
;
--
n_line_strings
)
{
double
ls_len
;
GLineString
ls
;
data
+=
WKB_HEADER_SIZE
;
ls
.
init_from_wkb
(
data
,
m_data_end
-
data
);
if
(
ls
.
length
(
&
ls_len
))
return
1
;
*
len
+=
ls_len
;
data
+=
ls
.
get_data_size
();
}
return
0
;
}
int
GMultiLineString
::
is_closed
(
int
*
closed
)
const
{
uint32
n_line_strings
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
1
))
return
1
;
n_line_strings
=
uint4korr
(
data
);
data
+=
4
+
WKB_HEADER_SIZE
;
for
(;
n_line_strings
>
0
;
--
n_line_strings
)
{
GLineString
ls
;
ls
.
init_from_wkb
(
data
,
m_data_end
-
data
);
if
(
ls
.
is_closed
(
closed
))
return
1
;
if
(
!*
closed
)
return
0
;
data
+=
ls
.
get_data_size
()
+
WKB_HEADER_SIZE
;
}
return
0
;
}
/***************************** MultiPolygon *******************************/
size_t
GMultiPolygon
::
get_data_size
()
const
{
uint32
n_polygons
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_polygons
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_polygons
>
0
;
--
n_polygons
)
{
if
(
no_data
(
data
,
4
+
WKB_HEADER_SIZE
))
return
1
;
uint32
n_linear_rings
=
uint4korr
(
data
+
WKB_HEADER_SIZE
);
data
+=
4
+
WKB_HEADER_SIZE
;
for
(;
n_linear_rings
>
0
;
--
n_linear_rings
)
{
data
+=
4
+
uint4korr
(
data
)
*
POINT_DATA_SIZE
;
}
}
return
data
-
m_data
;
}
int
GMultiPolygon
::
init_from_text
(
GTextReadStream
*
trs
,
String
*
wkb
)
{
uint32
n_polygons
=
0
;
int
np_pos
=
wkb
->
length
();
GPolygon
p
;
if
(
wkb
->
reserve
(
4
,
512
))
return
1
;
wkb
->
q_append
((
uint32
)
n_polygons
);
for
(;;)
{
if
(
wkb
->
reserve
(
1
+
4
,
512
))
return
1
;
wkb
->
q_append
((
char
)
wkbNDR
);
wkb
->
q_append
((
uint32
)
wkbPolygon
);
if
(
trs
->
get_next_symbol
()
!=
'('
)
{
trs
->
set_error_msg
(
"'(' expected"
);
return
1
;
}
if
(
p
.
init_from_text
(
trs
,
wkb
))
return
1
;
if
(
trs
->
get_next_symbol
()
!=
')'
)
{
trs
->
set_error_msg
(
"')' expected"
);
return
1
;
}
++
n_polygons
;
if
(
trs
->
get_next_toc_type
()
==
GTextReadStream
::
comma
)
trs
->
get_next_symbol
();
else
break
;
}
wkb
->
WriteAtPosition
(
np_pos
,
n_polygons
);
return
0
;
}
int
GMultiPolygon
::
get_data_as_text
(
String
*
txt
)
const
{
uint32
n_polygons
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_polygons
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_polygons
>
0
;
--
n_polygons
)
{
if
(
no_data
(
data
,
4
+
WKB_HEADER_SIZE
))
return
1
;
data
+=
WKB_HEADER_SIZE
;
uint32
n_linear_rings
=
uint4korr
(
data
);
data
+=
4
;
if
(
txt
->
reserve
(
1
,
512
))
return
1
;
txt
->
q_append
(
'('
);
for
(;
n_linear_rings
>
0
;
--
n_linear_rings
)
{
if
(
no_data
(
data
,
4
))
return
1
;
uint32
n_points
=
uint4korr
(
data
);
data
+=
4
;
if
(
no_data
(
data
,
(
8
+
8
)
*
n_points
))
return
1
;
if
(
txt
->
reserve
(
2
+
((
MAX_DIGITS_IN_DOUBLE
+
1
)
*
2
+
1
)
*
n_points
,
512
))
return
1
;
txt
->
qs_append
(
'('
);
for
(;
n_points
>
0
;
--
n_points
)
{
txt
->
qs_append
((
double
*
)
data
);
txt
->
qs_append
(
' '
);
txt
->
qs_append
((
double
*
)(
data
+
8
));
txt
->
qs_append
(
','
);
data
+=
8
+
8
;
}
(
*
txt
)[
txt
->
length
()
-
1
]
=
')'
;
txt
->
qs_append
(
','
);
}
(
*
txt
)[
txt
->
length
()
-
1
]
=
')'
;
txt
->
qs_append
(
','
);
}
txt
->
length
(
txt
->
length
()
-
1
);
return
0
;
}
int
GMultiPolygon
::
get_mbr
(
MBR
*
mbr
)
const
{
uint32
n_polygons
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_polygons
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_polygons
>
0
;
--
n_polygons
)
{
if
(
no_data
(
data
,
4
+
WKB_HEADER_SIZE
))
return
1
;
uint32
n_linear_rings
=
uint4korr
(
data
+
WKB_HEADER_SIZE
);
data
+=
WKB_HEADER_SIZE
+
4
;
for
(;
n_linear_rings
>
0
;
--
n_linear_rings
)
{
if
(
no_data
(
data
,
4
))
return
1
;
uint32
n_points
=
uint4korr
(
data
);
data
+=
4
;
if
(
no_data
(
data
,
(
8
+
8
)
*
n_points
))
return
1
;
for
(;
n_points
>
0
;
--
n_points
)
{
mbr
->
add_xy
((
double
*
)
data
,
(
double
*
)(
data
+
8
));
data
+=
8
+
8
;
}
}
}
return
0
;
}
int
GMultiPolygon
::
area
(
double
*
ar
)
const
{
uint32
n_polygons
;
const
char
*
data
=
m_data
;
double
result
=
0
;
if
(
no_data
(
data
,
4
))
return
1
;
n_polygons
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_polygons
>
0
;
--
n_polygons
)
{
double
p_area
;
GPolygon
p
;
data
+=
WKB_HEADER_SIZE
;
p
.
init_from_wkb
(
data
,
m_data_end
-
data
);
if
(
p
.
area
(
&
p_area
))
return
1
;
result
+=
p_area
;
data
+=
p
.
get_data_size
();
}
*
ar
=
result
;
return
0
;
}
int
GMultiPolygon
::
centroid
(
String
*
result
)
const
{
uint32
n_polygons
;
uint
i
;
GPolygon
p
;
double
res_area
,
res_cx
,
res_cy
;
double
cur_area
,
cur_cx
,
cur_cy
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_polygons
=
uint4korr
(
data
);
data
+=
4
;
for
(
i
=
0
;
i
<
n_polygons
;
++
i
)
{
data
+=
WKB_HEADER_SIZE
;
p
.
init_from_wkb
(
data
,
m_data_end
-
data
);
if
(
p
.
area
(
&
cur_area
))
return
1
;
if
(
p
.
centroid_xy
(
&
cur_cx
,
&
cur_cy
))
return
1
;
if
(
i
)
{
double
sum_area
=
res_area
+
cur_area
;
res_cx
=
(
res_area
*
res_cx
+
cur_area
*
cur_cx
)
/
sum_area
;
res_cy
=
(
res_area
*
res_cy
+
cur_area
*
cur_cy
)
/
sum_area
;
}
else
{
res_area
=
cur_area
;
res_cx
=
cur_cx
;
res_cy
=
cur_cy
;
}
data
+=
p
.
get_data_size
();
}
if
(
result
->
reserve
(
1
+
4
+
sizeof
(
double
)
*
2
))
return
1
;
result
->
q_append
((
char
)
wkbNDR
);
result
->
q_append
((
uint32
)
wkbPoint
);
result
->
q_append
(
res_cx
);
result
->
q_append
(
res_cy
);
return
0
;
}
/***************************** GeometryCollection *******************************/
size_t
GGeometryCollection
::
get_data_size
()
const
{
uint32
n_objects
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_objects
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_objects
>
0
;
--
n_objects
)
{
if
(
no_data
(
data
,
WKB_HEADER_SIZE
))
return
1
;
uint32
wkb_type
=
uint4korr
(
data
+
sizeof
(
char
));
data
+=
WKB_HEADER_SIZE
;
Geometry
geom
;
if
(
geom
.
init
(
wkb_type
))
return
0
;
geom
.
init_from_wkb
(
data
,
m_data_end
-
data
);
size_t
object_size
=
geom
.
get_data_size
();
data
+=
object_size
;
}
return
data
-
m_data
;
}
int
GGeometryCollection
::
init_from_text
(
GTextReadStream
*
trs
,
String
*
wkb
)
{
uint32
n_objects
=
0
;
int
no_pos
=
wkb
->
length
();
Geometry
g
;
if
(
wkb
->
reserve
(
4
,
512
))
return
1
;
wkb
->
q_append
((
uint32
)
n_objects
);
for
(;;)
{
if
(
g
.
create_from_wkt
(
trs
,
wkb
))
return
1
;
if
(
g
.
get_class_info
()
->
m_type_id
==
wkbGeometryCollection
)
{
trs
->
set_error_msg
(
"Unexpected GEOMETRYCOLLECTION"
);
return
1
;
}
++
n_objects
;
if
(
trs
->
get_next_toc_type
()
==
GTextReadStream
::
comma
)
trs
->
get_next_symbol
();
else
break
;
}
wkb
->
WriteAtPosition
(
no_pos
,
n_objects
);
return
0
;
}
int
GGeometryCollection
::
get_data_as_text
(
String
*
txt
)
const
{
uint32
n_objects
;
const
char
*
data
=
m_data
;
Geometry
geom
;
if
(
no_data
(
data
,
4
))
return
1
;
n_objects
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_objects
>
0
;
--
n_objects
)
{
if
(
no_data
(
data
,
WKB_HEADER_SIZE
))
return
1
;
uint32
wkb_type
=
uint4korr
(
data
+
sizeof
(
char
));
data
+=
WKB_HEADER_SIZE
;
if
(
geom
.
init
(
wkb_type
))
return
1
;
geom
.
init_from_wkb
(
data
,
m_data_end
-
data
);
if
(
geom
.
as_wkt
(
txt
))
return
1
;
data
+=
geom
.
get_data_size
();
txt
->
reserve
(
1
,
512
);
txt
->
q_append
(
','
);
}
txt
->
length
(
txt
->
length
()
-
1
);
return
0
;
}
int
GGeometryCollection
::
get_mbr
(
MBR
*
mbr
)
const
{
uint32
n_objects
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_objects
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_objects
>
0
;
--
n_objects
)
{
if
(
no_data
(
data
,
WKB_HEADER_SIZE
))
return
1
;
uint32
wkb_type
=
uint4korr
(
data
+
sizeof
(
char
));
data
+=
WKB_HEADER_SIZE
;
Geometry
geom
;
if
(
geom
.
init
(
wkb_type
))
return
1
;
geom
.
init_from_wkb
(
data
,
m_data_end
-
data
);
geom
.
get_mbr
(
mbr
);
data
+=
geom
.
get_data_size
();
}
return
0
;
}
int
GGeometryCollection
::
num_geometries
(
uint32
*
num
)
const
{
*
num
=
uint4korr
(
m_data
);
return
0
;
}
int
GGeometryCollection
::
geometry_n
(
uint32
num
,
String
*
result
)
const
{
const
char
*
data
=
m_data
;
uint32
n_objects
;
if
(
no_data
(
data
,
4
))
return
1
;
n_objects
=
uint4korr
(
data
);
data
+=
4
;
if
((
num
>
n_objects
)
||
(
num
<
1
))
{
return
-
1
;
}
for
(;
num
>
0
;
--
num
)
{
if
(
no_data
(
data
,
WKB_HEADER_SIZE
))
return
1
;
uint32
wkb_type
=
uint4korr
(
data
+
sizeof
(
char
));
data
+=
WKB_HEADER_SIZE
;
Geometry
geom
;
if
(
geom
.
init
(
wkb_type
))
return
1
;
geom
.
init_from_wkb
(
data
,
m_data_end
-
data
);
if
(
num
==
1
)
{
if
(
result
->
reserve
(
1
+
4
+
geom
.
get_data_size
()))
return
1
;
result
->
q_append
((
char
)
wkbNDR
);
result
->
q_append
((
uint32
)
wkb_type
);
result
->
q_append
(
data
,
geom
.
get_data_size
());
break
;
}
else
{
data
+=
geom
.
get_data_size
();
}
}
return
0
;
}
int
GGeometryCollection
::
dimension
(
uint32
*
dim
)
const
{
uint32
n_objects
;
*
dim
=
0
;
const
char
*
data
=
m_data
;
if
(
no_data
(
data
,
4
))
return
1
;
n_objects
=
uint4korr
(
data
);
data
+=
4
;
for
(;
n_objects
>
0
;
--
n_objects
)
{
if
(
no_data
(
data
,
WKB_HEADER_SIZE
))
return
1
;
uint32
wkb_type
=
uint4korr
(
data
+
sizeof
(
char
));
data
+=
WKB_HEADER_SIZE
;
uint32
d
;
Geometry
geom
;
if
(
geom
.
init
(
wkb_type
))
return
1
;
geom
.
init_from_wkb
(
data
,
m_data_end
-
data
);
if
(
geom
.
dimension
(
&
d
))
return
1
;
if
(
d
>
*
dim
)
*
dim
=
d
;
data
+=
geom
.
get_data_size
();
}
return
0
;
}
/***************************** /objects *******************************/
sql/spatial.h
0 → 100644
View file @
735b27d5
#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
sql/sql_class.h
View file @
735b27d5
...
...
@@ -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
;
}
};
...
...
sql/sql_show.cc
View file @
735b27d5
...
...
@@ -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
++
)
...
...
sql/sql_string.cc
View file @
735b27d5
...
...
@@ -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
));
}
sql/sql_string.h
View file @
735b27d5
...
...
@@ -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
);
};
sql/sql_table.cc
View file @
735b27d5
...
...
@@ -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,6 +465,30 @@ 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
();
...
...
sql/sql_yacc.yy
View file @
735b27d5
...
...
@@ -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,11 +728,11 @@ 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();
...
...
@@ -727,7 +742,8 @@ create:
'(' 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 ')'
...
...
sql/structs.h
View file @
735b27d5
...
...
@@ -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 */
...
...
sql/table.cc
View file @
735b27d5
...
...
@@ -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
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment