00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <drizzled/charset_info.h>
00023 #include <drizzled/base.h>
00024 #include <plugin/myisam/my_handler.h>
00025 #include <drizzled/internal/my_sys.h>
00026
00027 #include <cassert>
00028 #include <algorithm>
00029
00030 using namespace drizzled;
00031 using namespace std;
00032
00033 template<class T>
00034 int CMP_NUM(const T& a, const T&b)
00035 {
00036 return (a < b) ? -1 : (a == b) ? 0 : 1;
00037 }
00038
00039
00040 int ha_compare_text(const CHARSET_INFO * const charset_info, unsigned char *a, uint32_t a_length,
00041 unsigned char *b, uint32_t b_length, bool part_key,
00042 bool skip_end_space)
00043 {
00044 if (!part_key)
00045 return charset_info->coll->strnncollsp(charset_info, a, a_length,
00046 b, b_length, (bool)!skip_end_space);
00047 return charset_info->coll->strnncoll(charset_info, a, a_length,
00048 b, b_length, part_key);
00049 }
00050
00051
00052 static int compare_bin(unsigned char *a, uint32_t a_length, unsigned char *b, uint32_t b_length,
00053 bool part_key, bool skip_end_space)
00054 {
00055 uint32_t length= min(a_length,b_length);
00056 unsigned char *end= a+ length;
00057 int flag;
00058
00059 while (a < end)
00060 if ((flag= (int) *a++ - (int) *b++))
00061 return flag;
00062 if (part_key && b_length < a_length)
00063 return 0;
00064 if (skip_end_space && a_length != b_length)
00065 {
00066 int swap= 1;
00067
00068
00069
00070
00071
00072
00073
00074
00075 if (a_length < b_length)
00076 {
00077
00078 a_length= b_length;
00079 a= b;
00080 swap= -1;
00081 }
00082 for (end= a + a_length-length; a < end ; a++)
00083 {
00084 if (*a != ' ')
00085 return (*a < ' ') ? -swap : swap;
00086 }
00087 return 0;
00088 }
00089 return (int) (a_length-b_length);
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 #define FCMP(A,B) ((int) (A) - (int) (B))
00134
00135 int ha_key_cmp(register HA_KEYSEG *keyseg, register unsigned char *a,
00136 register unsigned char *b, uint32_t key_length, uint32_t nextflag,
00137 uint32_t *diff_pos)
00138 {
00139 int flag;
00140 int32_t l_1,l_2;
00141 uint32_t u_1,u_2;
00142 double d_1,d_2;
00143 uint32_t next_key_length;
00144 unsigned char *orig_b= b;
00145
00146 *diff_pos=0;
00147 for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
00148 {
00149 unsigned char *end;
00150 uint32_t piks=! (keyseg->flag & HA_NO_SORT);
00151 (*diff_pos)++;
00152 diff_pos[1]= (uint)(b - orig_b);
00153
00154
00155 if (keyseg->null_bit)
00156 {
00157 key_length--;
00158 if (*a != *b && piks)
00159 {
00160 flag = (int) *a - (int) *b;
00161 return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
00162 }
00163 b++;
00164 if (!*a++)
00165 {
00166 if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
00167 nextflag=SEARCH_SAME;
00168 else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL)
00169 {
00170
00171
00172
00173
00174
00175 return -1;
00176 }
00177 next_key_length=key_length;
00178 continue;
00179 }
00180 }
00181 end= a+ min((uint32_t)keyseg->length,key_length);
00182 next_key_length=key_length-keyseg->length;
00183
00184 switch ((enum ha_base_keytype) keyseg->type) {
00185 case HA_KEYTYPE_TEXT:
00186 if (keyseg->flag & HA_SPACE_PACK)
00187 {
00188 int a_length,b_length,pack_length;
00189 get_key_length(a_length,a);
00190 get_key_pack_length(b_length,pack_length,b);
00191 next_key_length=key_length-b_length-pack_length;
00192
00193 if (piks &&
00194 (flag=ha_compare_text(keyseg->charset,a,a_length,b,b_length,
00195 (bool) ((nextflag & SEARCH_PREFIX) &&
00196 next_key_length <= 0),
00197 (bool)!(nextflag & SEARCH_PREFIX))))
00198 return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
00199 a+=a_length;
00200 b+=b_length;
00201 break;
00202 }
00203 else
00204 {
00205 uint32_t length=(uint) (end-a), a_length=length, b_length=length;
00206 if (piks &&
00207 (flag= ha_compare_text(keyseg->charset, a, a_length, b, b_length,
00208 (bool) ((nextflag & SEARCH_PREFIX) &&
00209 next_key_length <= 0),
00210 (bool)!(nextflag & SEARCH_PREFIX))))
00211 return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
00212 a=end;
00213 b+=length;
00214 }
00215 break;
00216 case HA_KEYTYPE_BINARY:
00217 if (keyseg->flag & HA_SPACE_PACK)
00218 {
00219 int a_length,b_length,pack_length;
00220 get_key_length(a_length,a);
00221 get_key_pack_length(b_length,pack_length,b);
00222 next_key_length=key_length-b_length-pack_length;
00223
00224 if (piks &&
00225 (flag=compare_bin(a,a_length,b,b_length,
00226 (bool) ((nextflag & SEARCH_PREFIX) &&
00227 next_key_length <= 0),1)))
00228 return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
00229 a+=a_length;
00230 b+=b_length;
00231 break;
00232 }
00233 else
00234 {
00235 uint32_t length=keyseg->length;
00236 if (piks &&
00237 (flag=compare_bin(a,length,b,length,
00238 (bool) ((nextflag & SEARCH_PREFIX) &&
00239 next_key_length <= 0),0)))
00240 return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
00241 a+=length;
00242 b+=length;
00243 }
00244 break;
00245 case HA_KEYTYPE_VARTEXT1:
00246 case HA_KEYTYPE_VARTEXT2:
00247 {
00248 int a_length,b_length,pack_length;
00249 get_key_length(a_length,a);
00250 get_key_pack_length(b_length,pack_length,b);
00251 next_key_length=key_length-b_length-pack_length;
00252
00253 if (piks &&
00254 (flag= ha_compare_text(keyseg->charset,a,a_length,b,b_length,
00255 (bool) ((nextflag & SEARCH_PREFIX) &&
00256 next_key_length <= 0),
00257 (bool) ((nextflag & (SEARCH_FIND |
00258 SEARCH_UPDATE)) ==
00259 SEARCH_FIND &&
00260 ! (keyseg->flag &
00261 HA_END_SPACE_ARE_EQUAL)))))
00262 return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
00263 a+= a_length;
00264 b+= b_length;
00265 break;
00266 }
00267 case HA_KEYTYPE_VARBINARY1:
00268 case HA_KEYTYPE_VARBINARY2:
00269 {
00270 int a_length,b_length,pack_length;
00271 get_key_length(a_length,a);
00272 get_key_pack_length(b_length,pack_length,b);
00273 next_key_length=key_length-b_length-pack_length;
00274
00275 if (piks &&
00276 (flag=compare_bin(a,a_length,b,b_length,
00277 (bool) ((nextflag & SEARCH_PREFIX) &&
00278 next_key_length <= 0), 0)))
00279 return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
00280 a+=a_length;
00281 b+=b_length;
00282 break;
00283 }
00284 case HA_KEYTYPE_LONG_INT:
00285 l_1= mi_sint4korr(a);
00286 l_2= mi_sint4korr(b);
00287 if (piks && (flag = CMP_NUM(l_1,l_2)))
00288 return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
00289 a= end;
00290 b+= 4;
00291 break;
00292 case HA_KEYTYPE_ULONG_INT:
00293 u_1= mi_sint4korr(a);
00294 u_2= mi_sint4korr(b);
00295 if (piks && (flag = CMP_NUM(u_1,u_2)))
00296 return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
00297 a= end;
00298 b+= 4;
00299 break;
00300 case HA_KEYTYPE_DOUBLE:
00301 mi_float8get(d_1,a);
00302 mi_float8get(d_2,b);
00303
00304
00305
00306
00307
00308 if (piks && (flag = CMP_NUM(d_1,d_2)))
00309 return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
00310 a= end;
00311 b+= 8;
00312 break;
00313 case HA_KEYTYPE_LONGLONG:
00314 {
00315 int64_t ll_a,ll_b;
00316 ll_a= mi_sint8korr(a);
00317 ll_b= mi_sint8korr(b);
00318 if (piks && (flag = CMP_NUM(ll_a,ll_b)))
00319 return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
00320 a= end;
00321 b+= 8;
00322 break;
00323 }
00324 case HA_KEYTYPE_ULONGLONG:
00325 {
00326 uint64_t ll_a,ll_b;
00327 ll_a= mi_uint8korr(a);
00328 ll_b= mi_uint8korr(b);
00329 if (piks && (flag = CMP_NUM(ll_a,ll_b)))
00330 return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
00331 a= end;
00332 b+= 8;
00333 break;
00334 }
00335 case HA_KEYTYPE_END:
00336 goto end;
00337 }
00338 }
00339 (*diff_pos)++;
00340 end:
00341 if (!(nextflag & SEARCH_FIND))
00342 {
00343 uint32_t i;
00344 if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST))
00345 return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
00346 flag=0;
00347 for (i=keyseg->length ; i-- > 0 ; )
00348 {
00349 if (*a++ != *b++)
00350 {
00351 flag= FCMP(a[-1],b[-1]);
00352 break;
00353 }
00354 }
00355 if (nextflag & SEARCH_SAME)
00356 return (flag);
00357 if (nextflag & SEARCH_BIGGER)
00358 return (flag <= 0 ? -1 : 1);
00359 return (flag < 0 ? -1 : 1);
00360 }
00361 return 0;
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, unsigned char *a)
00387 {
00388 for (; (enum ha_base_keytype) keyseg->type != HA_KEYTYPE_END; keyseg++)
00389 {
00390 unsigned char *end;
00391 if (keyseg->null_bit)
00392 {
00393 if (!*a++)
00394 return keyseg;
00395 }
00396 end= a+ keyseg->length;
00397
00398 switch ((enum ha_base_keytype) keyseg->type) {
00399 case HA_KEYTYPE_TEXT:
00400 case HA_KEYTYPE_BINARY:
00401 if (keyseg->flag & HA_SPACE_PACK)
00402 {
00403 int a_length;
00404 get_key_length(a_length, a);
00405 a += a_length;
00406 break;
00407 }
00408 else
00409 a= end;
00410 break;
00411 case HA_KEYTYPE_VARTEXT1:
00412 case HA_KEYTYPE_VARTEXT2:
00413 case HA_KEYTYPE_VARBINARY1:
00414 case HA_KEYTYPE_VARBINARY2:
00415 {
00416 int a_length;
00417 get_key_length(a_length, a);
00418 a+= a_length;
00419 break;
00420 }
00421 case HA_KEYTYPE_LONG_INT:
00422 case HA_KEYTYPE_ULONG_INT:
00423 case HA_KEYTYPE_LONGLONG:
00424 case HA_KEYTYPE_ULONGLONG:
00425 case HA_KEYTYPE_DOUBLE:
00426 a= end;
00427 break;
00428 case HA_KEYTYPE_END:
00429
00430 assert(0);
00431 break;
00432 }
00433 }
00434 return keyseg;
00435 }
00436
00437
00438