summaryrefslogtreecommitdiff
path: root/myisam/rt_mbr.c
diff options
context:
space:
mode:
Diffstat (limited to 'myisam/rt_mbr.c')
-rw-r--r--myisam/rt_mbr.c758
1 files changed, 758 insertions, 0 deletions
diff --git a/myisam/rt_mbr.c b/myisam/rt_mbr.c
new file mode 100644
index 00000000000..a6467500183
--- /dev/null
+++ b/myisam/rt_mbr.c
@@ -0,0 +1,758 @@
+/* Copyright (C) 2000 MySQL AB & Ramil Kalimullin & MySQL Finland AB
+ & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "myisamdef.h"
+
+#include "rt_index.h"
+#include "rt_mbr.h"
+
+#define INTERSECT_CMP(amin, amax, bmin, bmax) ((amin > bmax) || (bmin > amax))
+#define CONTAIN_CMP(amin, amax, bmin, bmax) ((bmin > amin) || (bmax < amax))
+#define WITHIN_CMP(amin, amax, bmin, bmax) ((amin > bmin) || (amax < bmax))
+#define DISJOINT_CMP(amin, amax, bmin, bmax) ((amin <= bmax) && (bmin <= amax))
+#define EQUAL_CMP(amix, amax, bmin, bmax) ((amix != bmin) || (amax != bmax))
+
+#define FCMP(A, B) ((int)(A) - (int)(B))
+#define p_inc(A, B, X) {A += X; B += X;}
+
+#define RT_CMP(nextflag) \
+ if (nextflag & MBR_INTERSECT) \
+ { \
+ if (INTERSECT_CMP(amin, amax, bmin, bmax)) \
+ return 1; \
+ } \
+ else if (nextflag & MBR_CONTAIN) \
+ { \
+ if (CONTAIN_CMP(amin, amax, bmin, bmax)) \
+ return 1; \
+ } \
+ else if (nextflag & MBR_WITHIN) \
+ { \
+ if (WITHIN_CMP(amin, amax, bmin, bmax)) \
+ return 1; \
+ } \
+ else if (nextflag & MBR_EQUAL) \
+ { \
+ if (EQUAL_CMP(amin, amax, bmin, bmax)) \
+ return 1; \
+ } \
+ else /* if (nextflag & MBR_DISJOINT) */ \
+ { \
+ if (DISJOINT_CMP(amin, amax, bmin, bmax)) \
+ return 1; \
+ }
+
+#define RT_CMP_KORR(type, korr_func, len, nextflag) \
+{ \
+ type amin, amax, bmin, bmax; \
+ amin = korr_func(a); \
+ bmin = korr_func(b); \
+ p_inc(a, b, len); \
+ amax = korr_func(a); \
+ bmax = korr_func(b); \
+ RT_CMP(nextflag); \
+ p_inc(a, b, len); \
+ break; \
+}
+
+#define RT_CMP_GET(type, get_func, len, nextflag) \
+{ \
+ type amin, amax, bmin, bmax; \
+ get_func(amin, a); \
+ get_func(bmin, b); \
+ p_inc(a, b, len); \
+ get_func(amax, a); \
+ get_func(bmax, b); \
+ RT_CMP(nextflag); \
+ p_inc(a, b, len); \
+ break; \
+}
+
+/*
+ Compares two keys a and b depending on nextflag
+ nextflag can contain these flags:
+ MBR_INTERSECT(a,b) a overlaps b
+ MBR_CONTAIN(a,b) a contains b
+ MBR_DISJOINT(a,b) a disjoint b
+ MBR_WITHIN(a,b) a within b
+ MBR_EQUAL(a,b) All coordinates of MBRs are equal
+ MBR_DATA(a,b) Data reference is the same
+ Returns 0 on success.
+*/
+int rtree_key_cmp(HA_KEYSEG *keyseg, uchar *b, uchar *a, uint key_length,
+ uint nextflag)
+{
+ for (; (int) key_length > 0; keyseg += 2 )
+ {
+ key_length -= keyseg->length * 2;
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return 1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin,amax,bmin,bmax;
+ amin = (int)*((signed char *)a);
+ bmin = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ amax = (int)*((signed char *)a);
+ bmax = (int)*((signed char *)b);
+ RT_CMP(nextflag);
+ p_inc(a, b, 1);
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_CMP_KORR(int16, mi_sint2korr, 2, nextflag);
+ case HA_KEYTYPE_USHORT_INT:
+ RT_CMP_KORR(uint16, mi_uint2korr, 2, nextflag);
+ case HA_KEYTYPE_INT24:
+ RT_CMP_KORR(int32, mi_sint3korr, 3, nextflag);
+ case HA_KEYTYPE_UINT24:
+ RT_CMP_KORR(uint32, mi_uint3korr, 3, nextflag);
+ case HA_KEYTYPE_LONG_INT:
+ RT_CMP_KORR(int32, mi_sint4korr, 4, nextflag);
+ case HA_KEYTYPE_ULONG_INT:
+ RT_CMP_KORR(uint32, mi_uint4korr, 4, nextflag);
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_CMP_KORR(longlong, mi_sint8korr, 8, nextflag)
+ case HA_KEYTYPE_ULONGLONG:
+ RT_CMP_KORR(ulonglong, mi_uint8korr, 8, nextflag)
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_CMP_GET(float, mi_float4get, 4, nextflag);
+ case HA_KEYTYPE_DOUBLE:
+ RT_CMP_GET(double, mi_float8get, 8, nextflag);
+ case HA_KEYTYPE_END:
+ goto end;
+ }
+ }
+
+end:
+ if (nextflag & MBR_DATA)
+ {
+ uchar *end = a + keyseg->length;
+ do
+ {
+ if (*a++ != *b++)
+ return FCMP(a[-1], b[-1]);
+ } while (a != end);
+ }
+ return 0;
+}
+
+#define RT_VOL_KORR(type, korr_func, len) \
+{ \
+ type amin, amax; \
+ amin = korr_func(a); \
+ a += len; \
+ amax = korr_func(a); \
+ a += len; \
+ res *= ((double)amax - (double)amin); \
+ break; \
+}
+
+#define RT_VOL_GET(type, get_func, len) \
+{ \
+ type amin, amax; \
+ get_func(amin, a); \
+ a += len; \
+ get_func(amax, a); \
+ a += len; \
+ res *= ((double)amax - (double)amin); \
+ break; \
+}
+
+/*
+ Calculates rectangle volume
+*/
+double rtree_rect_volume(HA_KEYSEG *keyseg, uchar *a, uint key_length)
+{
+ double res = 1;
+ for (; (int)key_length > 0; keyseg += 2)
+ {
+ key_length -= keyseg->length * 2;
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return 1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin, amax;
+ amin = (int)*((signed char *)a);
+ a += 1;
+ amax = (int)*((signed char *)a);
+ a += 1;
+ res *= ((double)amax - (double)amin);
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_VOL_KORR(int16, mi_sint2korr, 2);
+ case HA_KEYTYPE_USHORT_INT:
+ RT_VOL_KORR(uint16, mi_uint2korr, 2);
+ case HA_KEYTYPE_INT24:
+ RT_VOL_KORR(int32, mi_sint3korr, 3);
+ case HA_KEYTYPE_UINT24:
+ RT_VOL_KORR(uint32, mi_uint3korr, 3);
+ case HA_KEYTYPE_LONG_INT:
+ RT_VOL_KORR(int32, mi_sint4korr, 4);
+ case HA_KEYTYPE_ULONG_INT:
+ RT_VOL_KORR(uint32, mi_uint4korr, 4);
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_VOL_KORR(longlong, mi_sint8korr, 8);
+ case HA_KEYTYPE_ULONGLONG:
+ RT_VOL_KORR(ulonglong, mi_uint8korr, 8);
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_VOL_GET(float, mi_float4get, 4);
+ case HA_KEYTYPE_DOUBLE:
+ RT_VOL_GET(double, mi_float8get, 8);
+ case HA_KEYTYPE_END:
+ key_length = 0;
+ break;
+ }
+ }
+ return res;
+}
+
+#define RT_D_MBR_KORR(type, korr_func, len) \
+{ \
+ type amin, amax; \
+ amin = korr_func(a); \
+ a += len; \
+ amax = korr_func(a); \
+ a += len; \
+ *res++ = (double)amin; \
+ *res++ = (double)amax; \
+ break; \
+}
+
+#define RT_D_MBR_GET(type, get_func, len) \
+{ \
+ type amin, amax; \
+ get_func(amin, a); \
+ a += len; \
+ get_func(amax, a); \
+ a += len; \
+ *res++ = (double)amin; \
+ *res++ = (double)amax; \
+ break; \
+}
+
+/*
+ Creates an MBR as an array of doubles.
+*/
+int rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res)
+{
+ for (; (int)key_length > 0; keyseg += 2)
+ {
+ key_length -= keyseg->length * 2;
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return 1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin, amax;
+ amin = (int)*((signed char *)a);
+ a += 1;
+ amax = (int)*((signed char *)a);
+ a += 1;
+ *res++ = (double)amin;
+ *res++ = (double)amax;
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_D_MBR_KORR(int16, mi_sint2korr, 2);
+ case HA_KEYTYPE_USHORT_INT:
+ RT_D_MBR_KORR(uint16, mi_uint2korr, 2);
+ case HA_KEYTYPE_INT24:
+ RT_D_MBR_KORR(int32, mi_sint3korr, 3);
+ case HA_KEYTYPE_UINT24:
+ RT_D_MBR_KORR(uint32, mi_uint3korr, 3);
+ case HA_KEYTYPE_LONG_INT:
+ RT_D_MBR_KORR(int32, mi_sint4korr, 4);
+ case HA_KEYTYPE_ULONG_INT:
+ RT_D_MBR_KORR(uint32, mi_uint4korr, 4);
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_D_MBR_KORR(longlong, mi_sint8korr, 8);
+ case HA_KEYTYPE_ULONGLONG:
+ RT_D_MBR_KORR(ulonglong, mi_uint8korr, 8);
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_D_MBR_GET(float, mi_float4get, 4);
+ case HA_KEYTYPE_DOUBLE:
+ RT_D_MBR_GET(double, mi_float8get, 8);
+ case HA_KEYTYPE_END:
+ key_length = 0;
+ break;
+ }
+ }
+ return 0;
+}
+
+#define RT_COMB_KORR(type, korr_func, store_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ amin = korr_func(a); \
+ bmin = korr_func(b); \
+ p_inc(a, b, len); \
+ amax = korr_func(a); \
+ bmax = korr_func(b); \
+ p_inc(a, b, len); \
+ amin = min(amin, bmin); \
+ amax = max(amax, bmax); \
+ store_func(c, amin); \
+ c += len; \
+ store_func(c, amax); \
+ c += len; \
+ break; \
+}
+
+#define RT_COMB_GET(type, get_func, store_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ get_func(amin, a); \
+ get_func(bmin, b); \
+ p_inc(a, b, len); \
+ get_func(amax, a); \
+ get_func(bmax, b); \
+ p_inc(a, b, len); \
+ amin = min(amin, bmin); \
+ amax = max(amax, bmax); \
+ store_func(c, amin); \
+ c += len; \
+ store_func(c, amax); \
+ c += len; \
+ break; \
+}
+
+/*
+Creates common minimal bounding rectungle
+for two input rectagnles a and b
+Result is written to c
+*/
+int rtree_combine_rect(HA_KEYSEG *keyseg, uchar* a, uchar* b, uchar* c,
+ uint key_length)
+{
+
+ for ( ; (int) key_length > 0 ; keyseg += 2)
+ {
+ key_length -= keyseg->length * 2;
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return 1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin, amax, bmin, bmax;
+ amin = (int)*((signed char *)a);
+ bmin = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ amax = (int)*((signed char *)a);
+ bmax = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ amin = min(amin, bmin);
+ amax = max(amax, bmax);
+ *((signed char*)c) = amin;
+ c += 1;
+ *((signed char*)c) = amax;
+ c += 1;
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_COMB_KORR(int16, mi_sint2korr, mi_int2store, 2);
+ case HA_KEYTYPE_USHORT_INT:
+ RT_COMB_KORR(uint16, mi_uint2korr, mi_int2store, 2);
+ case HA_KEYTYPE_INT24:
+ RT_COMB_KORR(int32, mi_sint3korr, mi_int3store, 3);
+ case HA_KEYTYPE_UINT24:
+ RT_COMB_KORR(uint32, mi_uint3korr, mi_int3store, 3);
+ case HA_KEYTYPE_LONG_INT:
+ RT_COMB_KORR(int32, mi_sint4korr, mi_int4store, 4);
+ case HA_KEYTYPE_ULONG_INT:
+ RT_COMB_KORR(uint32, mi_uint4korr, mi_int4store, 4);
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_COMB_KORR(longlong, mi_sint8korr, mi_int8store, 8);
+ case HA_KEYTYPE_ULONGLONG:
+ RT_COMB_KORR(ulonglong, mi_uint8korr, mi_int8store, 8);
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_COMB_GET(float, mi_float4get, mi_float4store, 4);
+ case HA_KEYTYPE_DOUBLE:
+ RT_COMB_GET(double, mi_float8get, mi_float8store, 8);
+ case HA_KEYTYPE_END:
+ return 0;
+ }
+ }
+ return 0;
+}
+
+#define RT_OVL_AREA_KORR(type, korr_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ amin = korr_func(a); \
+ bmin = korr_func(b); \
+ p_inc(a, b, len); \
+ amax = korr_func(a); \
+ bmax = korr_func(b); \
+ p_inc(a, b, len); \
+ amin = max(amin, bmin); \
+ amax = min(amax, bmax); \
+ if (amin >= amax) \
+ return 0; \
+ res *= amax - amin; \
+ break; \
+}
+
+#define RT_OVL_AREA_GET(type, get_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ get_func(amin, a); \
+ get_func(bmin, b); \
+ p_inc(a, b, len); \
+ get_func(amax, a); \
+ get_func(bmax, b); \
+ p_inc(a, b, len); \
+ amin = max(amin, bmin); \
+ amax = min(amax, bmax); \
+ if (amin >= amax) \
+ return 0; \
+ res *= amax - amin; \
+ break; \
+}
+
+/*
+Calculates overlapping area of two MBRs a & b
+*/
+double rtree_overlapping_area(HA_KEYSEG *keyseg, uchar* a, uchar* b,
+ uint key_length)
+{
+ double res = 1;
+ for (; (int) key_length > 0 ; keyseg += 2)
+ {
+ key_length -= keyseg->length * 2;
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return -1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin, amax, bmin, bmax;
+ amin = (int)*((signed char *)a);
+ bmin = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ amax = (int)*((signed char *)a);
+ bmax = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ amin = max(amin, bmin);
+ amax = min(amax, bmax);
+ if (amin >= amax)
+ return 0;
+ res *= amax - amin;
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_OVL_AREA_KORR(int16, mi_sint2korr, 2);
+ case HA_KEYTYPE_USHORT_INT:
+ RT_OVL_AREA_KORR(uint16, mi_uint2korr, 2);
+ case HA_KEYTYPE_INT24:
+ RT_OVL_AREA_KORR(int32, mi_sint3korr, 3);
+ case HA_KEYTYPE_UINT24:
+ RT_OVL_AREA_KORR(uint32, mi_uint3korr, 3);
+ case HA_KEYTYPE_LONG_INT:
+ RT_OVL_AREA_KORR(int32, mi_sint4korr, 4);
+ case HA_KEYTYPE_ULONG_INT:
+ RT_OVL_AREA_KORR(uint32, mi_uint4korr, 4);
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_OVL_AREA_KORR(longlong, mi_sint8korr, 8);
+ case HA_KEYTYPE_ULONGLONG:
+ RT_OVL_AREA_KORR(ulonglong, mi_uint8korr, 8);
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_OVL_AREA_GET(float, mi_float4get, 4);
+ case HA_KEYTYPE_DOUBLE:
+ RT_OVL_AREA_GET(double, mi_float8get, 8);
+ case HA_KEYTYPE_END:
+ return res;
+ }
+ }
+ return res;
+}
+
+#define RT_AREA_INC_KORR(type, korr_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ amin = korr_func(a); \
+ bmin = korr_func(b); \
+ p_inc(a, b, len); \
+ amax = korr_func(a); \
+ bmax = korr_func(b); \
+ p_inc(a, b, len); \
+ a_area *= (((double)amax) - ((double)amin)); \
+ *ab_area *= ((double)max(amax, bmax) - (double)min(amin, bmin)); \
+ break; \
+}
+
+#define RT_AREA_INC_GET(type, get_func, len)\
+{\
+ type amin, amax, bmin, bmax; \
+ get_func(amin, a); \
+ get_func(bmin, b); \
+ p_inc(a, b, len); \
+ get_func(amax, a); \
+ get_func(bmax, b); \
+ p_inc(a, b, len); \
+ a_area *= (((double)amax) - ((double)amin)); \
+ *ab_area *= ((double)max(amax, bmax) - (double)min(amin, bmin)); \
+ break; \
+}
+
+/*
+Calculates MBR_AREA(a+b) - MBR_AREA(a)
+*/
+double rtree_area_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b,
+ uint key_length, double *ab_area)
+{
+ double a_area = 1;
+
+ *ab_area = 1;
+ for (; (int)key_length > 0; keyseg += 2)
+ {
+ key_length -= keyseg->length * 2;
+
+ /* Handle NULL part */
+ if (keyseg->null_bit)
+ {
+ return -1;
+ }
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return 1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin, amax, bmin, bmax;
+ amin = (int)*((signed char *)a);
+ bmin = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ amax = (int)*((signed char *)a);
+ bmax = (int)*((signed char *)b);
+ p_inc(a, b, 1);
+ a_area *= (((double)amax) - ((double)amin));
+ *ab_area *= ((double)max(amax, bmax) - (double)min(amin, bmin));
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_AREA_INC_KORR(int16, mi_sint2korr, 2);
+ case HA_KEYTYPE_USHORT_INT:
+ RT_AREA_INC_KORR(uint16, mi_uint2korr, 2);
+ case HA_KEYTYPE_INT24:
+ RT_AREA_INC_KORR(int32, mi_sint3korr, 3);
+ case HA_KEYTYPE_UINT24:
+ RT_AREA_INC_KORR(int32, mi_uint3korr, 3);
+ case HA_KEYTYPE_LONG_INT:
+ RT_AREA_INC_KORR(int32, mi_sint4korr, 4);
+ case HA_KEYTYPE_ULONG_INT:
+ RT_AREA_INC_KORR(uint32, mi_uint4korr, 4);
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_AREA_INC_KORR(longlong, mi_sint8korr, 8);
+ case HA_KEYTYPE_ULONGLONG:
+ RT_AREA_INC_KORR(ulonglong, mi_uint8korr, 8);
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_AREA_INC_GET(float, mi_float4get, 4);
+ case HA_KEYTYPE_DOUBLE:
+ RT_AREA_INC_GET(double, mi_float8get, 8);
+ case HA_KEYTYPE_END:
+ return *ab_area - a_area;
+ }
+ }
+ return *ab_area - a_area;
+}
+
+#define RT_PAGE_MBR_KORR(type, korr_func, store_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ amin = korr_func(k + inc); \
+ amax = korr_func(k + inc + len); \
+ k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); \
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) \
+{ \
+ bmin = korr_func(k + inc); \
+ bmax = korr_func(k + inc + len); \
+ if (amin > bmin) \
+ amin = bmin; \
+ if (amax < bmax) \
+ amax = bmax; \
+} \
+ store_func(c, amin); \
+ c += len; \
+ store_func(c, amax); \
+ c += len; \
+ inc += 2 * len; \
+ break; \
+}
+
+#define RT_PAGE_MBR_GET(type, get_func, store_func, len) \
+{ \
+ type amin, amax, bmin, bmax; \
+ get_func(amin, k + inc); \
+ get_func(amax, k + inc + len); \
+ k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); \
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) \
+{ \
+ get_func(bmin, k + inc); \
+ get_func(bmax, k + inc + len); \
+ if (amin > bmin) \
+ amin = bmin; \
+ if (amax < bmax) \
+ amax = bmax; \
+} \
+ store_func(c, amin); \
+ c += len; \
+ store_func(c, amax); \
+ c += len; \
+ inc += 2 * len; \
+ break; \
+}
+
+/*
+Calculates key page total MBR = MBR(key1) + MBR(key2) + ...
+*/
+int rtree_page_mbr(MI_INFO *info, HA_KEYSEG *keyseg, uchar *page_buf,
+ uchar *c, uint key_length)
+{
+ uint inc = 0;
+ uint k_len = key_length;
+ uint nod_flag = mi_test_if_nod(page_buf);
+ uchar *k;
+ uchar *last = rt_PAGE_END(page_buf);
+
+ for (; (int)key_length > 0; keyseg += 2)
+ {
+ key_length -= keyseg->length * 2;
+
+ /* Handle NULL part */
+ if (keyseg->null_bit)
+ {
+ return 1;
+ }
+
+ k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
+
+ switch ((enum ha_base_keytype) keyseg->type) {
+ case HA_KEYTYPE_TEXT:
+ case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_NUM:
+ default:
+ return 1;
+ break;
+ case HA_KEYTYPE_INT8:
+ {
+ int amin, amax, bmin, bmax;
+ amin = (int)*((signed char *)(k + inc));
+ amax = (int)*((signed char *)(k + inc + 1));
+ k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag);
+ for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag))
+ {
+ bmin = (int)*((signed char *)(k + inc));
+ bmax = (int)*((signed char *)(k + inc + 1));
+
+ if (amin > bmin)
+ amin = bmin;
+ if (amax < bmax)
+ amax = bmax;
+ }
+ *((signed char*)c) = amin;
+ c += 1;
+ *((signed char*)c) = amax;
+ c += 1;
+ inc += 1 * 2;
+ break;
+ }
+ case HA_KEYTYPE_SHORT_INT:
+ RT_PAGE_MBR_KORR(int16, mi_sint2korr, mi_int2store, 2);
+ case HA_KEYTYPE_USHORT_INT:
+ RT_PAGE_MBR_KORR(uint16, mi_uint2korr, mi_int2store, 2);
+ case HA_KEYTYPE_INT24:
+ RT_PAGE_MBR_KORR(int32, mi_sint3korr, mi_int3store, 3);
+ case HA_KEYTYPE_UINT24:
+ RT_PAGE_MBR_KORR(uint32, mi_uint3korr, mi_int3store, 3);
+ case HA_KEYTYPE_LONG_INT:
+ RT_PAGE_MBR_KORR(int32, mi_sint4korr, mi_int4store, 4);
+ case HA_KEYTYPE_ULONG_INT:
+ RT_PAGE_MBR_KORR(uint32, mi_uint4korr, mi_int4store, 4);
+#ifdef HAVE_LONG_LONG
+ case HA_KEYTYPE_LONGLONG:
+ RT_PAGE_MBR_KORR(longlong, mi_sint8korr, mi_int8store, 8);
+ case HA_KEYTYPE_ULONGLONG:
+ RT_PAGE_MBR_KORR(ulonglong, mi_uint8korr, mi_int8store, 8);
+#endif
+ case HA_KEYTYPE_FLOAT:
+ RT_PAGE_MBR_GET(float, mi_float4get, mi_float4store, 4);
+ case HA_KEYTYPE_DOUBLE:
+ RT_PAGE_MBR_GET(double, mi_float8get, mi_float8store, 8);
+ case HA_KEYTYPE_END:
+ return 0;
+ }
+ }
+ return 0;
+}