📄 compare.c
字号:
/*** Copyright (c) 1995-2001 Hughes Technologies Pty Ltd. All rights** reserved. **** Terms under which this software may be used or copied are** provided in the specific license associated with this product.**** Hughes Technologies disclaims all warranties with regard to this ** software, including all implied warranties of merchantability and ** fitness, in no event shall Hughes Technologies be liable for any ** special, indirect or consequential damages or any damages whatsoever ** resulting from loss of use, data or profits, whether in an action of ** contract, negligence or other tortious action, arising out of or in ** connection with the use or performance of this software.****** $Id: compare.c,v 1.20 2002/12/13 04:03:35 bambi Exp $***//*** Module : main : compare** Purpose : ** Exports : ** Depends Upon : */#define HAVE_STRCOLL/**************************************************************************** STANDARD INCLUDES**************************************************************************/#include <common/config.h>#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_STRING_H# include <string.h>#endif#ifdef HAVE_STRINGS_H# include <strings.h>#endif#include <common/portability.h>/**************************************************************************** MODULE SPECIFIC INCLUDES**************************************************************************/#include <common/msql_defs.h>#include <common/debug/debug.h>#include <msqld/index/index.h>#include <msqld/includes/errmsg.h>#include <msqld/includes/msqld.h>#include <msqld/main/main.h>#include <msqld/main/yaccer.h>#include <msqld/main/varchar.h>#include <msqld/main/sysvar.h>#include <msqld/main/util.h>#include <msqld/main/table.h>#include <msqld/main/compare.h>#include <msqld/main/parse.h>#include <msqld/main/regex.h>#include <msqld/main/memory.h>#include <common/types/types.h>#include <libmsql/msql.h>/**************************************************************************** GLOBAL VARIABLES**************************************************************************//* HACK*/extern char errMsg[];/**************************************************************************** PRIVATE ROUTINES**************************************************************************//*** Operator class macros*/#define ISA_NULL_OP(op) ((op == EQ_OP) || (op == NE_OP))#define ISA_LIKE_OP(op) ((op >= LIKE_OP) && (op <= NOT_SLIKE_OP))int localByteCmp(b1, b2, len) void *b1, *b2; int len;{ register char *p1, *p2; if (len == 0) return(0); p1 = (char *)b1; p2 = (char *)b2; while (len) { if (*p1 != *p2) break; p1++; p2++; len--; } if (len == 0) return(0); if (*p1 > *p2) return(1); return(-1);}/****************************************************************************** _byteMatch**** Purpose : comparison suite for single bytes.** Args :** Returns :** Notes : in-lined for performance***/#define byteMatch(v1,v2,op, result) \{ \ switch(op) \ { \ case EQ_OP: \ result = ((char)v1 == (char)v2); \ break; \ case NE_OP: \ result = ((char)v1 != (char)v2); \ break; \ case LT_OP: \ result = ((char)v1 < (char)v2); \ break; \ case LE_OP: \ result = ((char)v1 <= (char)v2); \ break; \ case GT_OP: \ result = ((char)v1 > (char)v2); \ break; \ case GE_OP: \ result = ((char)v1 >= (char)v2); \ break; \ } \}/****************************************************************************** _intMatch**** Purpose : comparison suite for integer fields.** Args : ** Returns : ** Notes : in-lined for performance*/#define intMatch(v1,v2,op,result) \{ \ switch(op) \ { \ case EQ_OP: \ result = (v1 == v2); \ break; \ case NE_OP: \ result = (v1 != v2); \ break; \ case LT_OP: \ result = (v1 < v2); \ break; \ case LE_OP: \ result = (v1 <= v2); \ break; \ case GT_OP: \ result = (v1 > v2); \ break; \ case GE_OP: \ result = (v1 >= v2); \ break; \ } \}/****************************************************************************** _uintMatch**** Purpose : comparison suite for unsigned integer fields.** Args : ** Returns : ** Notes : in-lined for performance*/#define uintMatch(v1,v2,op,result) \{ \ switch(op) \ { \ case EQ_OP: \ result = ((u_int)v1 == (u_int)v2); \ break; \ case NE_OP: \ result = ((u_int)v1 != (u_int)v2);\ break; \ case LT_OP: \ result = ((u_int)v1 < (u_int)v2);\ break; \ case LE_OP: \ result = ((u_int)v1 <= (u_int)v2);\ break; \ case GT_OP: \ result = ((u_int)v1 > (u_int)v2);\ break; \ case GE_OP: \ result = ((u_int)v1 >= (u_int)v2);\ break; \ } \}#define int64Match intMatch#define uint64Match uintMatch/****************************************************************************** _charMatch**** Purpose : Comparison suite for text fields** Args : ** Returns : ** Notes : */static int charMatch(v1,v2,op,maxLen) char *v1, *v2; int op, maxLen;{ int v1Len, v2Len; /* actual length of input data */ int result = 0, cmp = 0; /* needed for both ordinary and *LIKE operators */ v1Len = regexStringLength( v1, maxLen ); v2Len = strlen( v2 ); /* common stuff for ordinary operators (=, <, ...) */ if (!ISA_LIKE_OP(op)) {#ifdef HAVE_STRCOLL { /* ** Sadly there isn't an strncoll so we must ** ensure the data from the row is NULL ** terminated. */ char tmp; tmp = *(v1+v1Len); *(v1+v1Len) = 0; cmp = strcoll( v1, v2); *(v1+v1Len) = tmp; }#else cmp = strncmp( v1, v2, (v1Len < v2Len) ? v1Len : v2Len );#endif if (cmp == 0) { cmp = v1Len - v2Len; } } switch(op) { case EQ_OP: result = (cmp == 0); break; case NE_OP: result = (cmp != 0); break; case LT_OP: result = (cmp < 0); break; case LE_OP: result = (cmp <= 0); break; case GT_OP: result = (cmp > 0); break; case GE_OP: result = (cmp >= 0); break; case RLIKE_OP: result = rLikeTest(v1,v2,v1Len); break; case LIKE_OP: result = likeTest(v1,v2,v1Len, 0, CHAR_TYPE); break; case CLIKE_OP: result = likeTest(v1,v2,v1Len, 1, CHAR_TYPE); break; case SLIKE_OP: result = sLikeTest(v1,v2,v1Len); break; case NOT_RLIKE_OP: result = !(rLikeTest(v1,v2,v1Len)); break; case NOT_LIKE_OP: result = !(likeTest(v1,v2,v1Len, 0, CHAR_TYPE)); break; case NOT_CLIKE_OP: result = !(likeTest(v1,v2,v1Len, 1, CHAR_TYPE)); break; case NOT_SLIKE_OP: result = !(sLikeTest(v1,v2,v1Len)); break; } return(result);}/****************************************************************************** _byteRangeMatch**** Purpose : Comparison suite for byte ranges (i.e. basetype = BYTE)** Args : ** Returns : ** Notes : */static int byteRangeMatch(v1,v2,op,len) void *v1, *v2; int op, len;{ int result = 0, cmp = 0; cmp = localByteCmp( v1, v2, len); switch(op) { case EQ_OP: result = (cmp == 0); break; case NE_OP: result = (cmp != 0); break; case LT_OP: result = (cmp < 0); break; case LE_OP: result = (cmp <= 0); break; case GT_OP: result = (cmp > 0); break; case GE_OP: result = (cmp >= 0); break; } return(result);}/****************************************************************************** _cidr4Match**** Purpose : Comparison suite for cidr4 fields** Args : ** Returns : ** Notes : */int cidr4Match(p1, p2, op) void *p1, *p2; int op;{ u_char byte1, byte2, byte3, byte4, byte5; u_int addr1, addr2, len, len1, len2, mask; int result; byte1 = (u_char)*(u_char*)(p1); byte2 = (u_char)*(u_char*)(p1 + 1); byte3 = (u_char)*(u_char*)(p1 + 2); byte4 = (u_char)*(u_char*)(p1 + 3); byte5 = (u_char)*(u_char*)(p1 + 4); addr1 = ( byte1 << 24) + (byte2 << 16) + (byte3 << 8) + byte4; len1 = byte5; byte1 = (u_char)*(u_char*)(p2); byte2 = (u_char)*(u_char*)(p2 + 1); byte3 = (u_char)*(u_char*)(p2 + 2); byte4 = (u_char)*(u_char*)(p2 + 3); byte5 = (u_char)*(u_char*)(p2 + 4); addr2 = ( byte1 << 24) + (byte2 << 16) + (byte3 << 8) + byte4; len2 = byte5; len = (len1 < len2 ? len1 : len2); switch(len) { case 0 : mask = 0; break; case 1 : mask = 2147483648u; break; case 2 : mask = 3221225472u; break; case 3 : mask = 3758096384u; break; case 4 : mask = 4026531840u; break; case 5 : mask = 4160749568u; break; case 6 : mask = 4227858432u; break; case 7 : mask = 4261412864u; break; case 8 : mask = 4278190080u; break; case 9 : mask = 4286578688u; break; case 10 : mask = 4290772992u; break; case 11 : mask = 4292870144u; break; case 12 : mask = 4293918720u; break; case 13 : mask = 4294443008u; break; case 14 : mask = 4294705152u; break; case 15 : mask = 4294836224u; break; case 16 : mask = 4294901760u; break; case 17 : mask = 4294934528u; break; case 18 : mask = 4294950912u; break; case 19 : mask = 4294959104u; break; case 20 : mask = 4294963200u; break; case 21 : mask = 4294965248u; break; case 22 : mask = 4294966272u; break; case 23 : mask = 4294966784u; break; case 24 : mask = 4294967040u; break; case 25 : mask = 4294967168u; break; case 26 : mask = 4294967232u; break; case 27 : mask = 4294967264u; break; case 28 : mask = 4294967280u; break; case 29 : mask = 4294967288u; break; case 30 : mask = 4294967292u; break; case 31 : mask = 4294967294u; break; case 32 : mask = 4294967295u; break; } /* ** The manual (and slow) way of working out a mask ** while(count < len) { mask = (mask << 1) + 1; count++; } mask = mask << (32 - len); ** */ switch(op) { case EQ_OP: result = (addr1 == addr2) && (len1 == len2); break; case NE_OP: result = (addr1 != addr2) || (len1 != len2); break; case LT_OP: result = ((addr1 & mask) == (addr2 & mask)) && (len1 < len2); break; case LE_OP: result = ((addr1 & mask) == (addr2 & mask)) && (len1 <= len2); break; case GT_OP: result = ((addr1 & mask) == (addr2 & mask)) && (len1 > len2); break; case GE_OP: result = ((addr1 & mask) == (addr2 & mask)) && (len1 >= len2); break; default: strcpy(errMsg, "Invalid cidr4 comparison"); return(-1); } return(result);}/****************************************************************************** _realMatch**** Purpose : Comparison suite for real fields** Args : ** Returns : ** Notes : in-lined for performance*/#define realMatch(v1,v2,op, result) \{ \ switch(op) \ { \ case EQ_OP: \ result = (v1 == v2); \ break; \ case NE_OP: \ result = (v1 != v2); \ break; \ case LT_OP: \ result = (v1 < v2); \ break; \ case LE_OP: \ result = (v1 <= v2); \ break; \ case GT_OP: \ result = (v1 > v2); \ break; \ case GE_OP: \ result = (v1 >= v2); \ break; \ } \}/****************************************************************************** Row comparison routines*/static int processBetweenMatch(cacheEntry,curCond,data, offset, tmpVal) cache_t *cacheEntry; mCond_t *curCond; u_char *data; int *offset; mVal_t *tmpVal;{ int tmp = 0; int iv; double fv; char *cp;#ifdef HUGE_T HUGE_T hv;#endif switch(typeBaseType(curCond->type)) { case INT_TYPE: bcopy4((data + *offset +1),&iv); intMatch(iv,curCond->value->val.intVal,GE_OP,tmp); if (tmp == 1) { intMatch(iv,curCond->maxValue->val.intVal, LE_OP,tmp); } break; case UINT_TYPE: bcopy4((data + *offset +1),&iv); uintMatch(iv,curCond->value->val.intVal,GE_OP,tmp); if (tmp == 1) { uintMatch(iv,curCond->maxValue->val.intVal, LE_OP, tmp); } break;#ifdef HUGE_T case INT64_TYPE: bcopy((data + *offset +1),&hv, sizeof(HUGE_T)); int64Match(hv,curCond->value->val.int64Val,GE_OP,tmp); if (tmp == 1) { int64Match(hv,curCond->maxValue->val.int64Val, LE_OP,tmp); } break; case UINT64_TYPE: bcopy((data + *offset +1),&hv, sizeof(HUGE_T)); uint64Match(hv,curCond->value->val.int64Val,GE_OP,tmp); if (tmp == 1) { uint64Match(hv,curCond->maxValue->val.int64Val, LE_OP, tmp); } break;#endif case CHAR_TYPE: cp = (char *)data + *offset +1; tmp = charMatch(cp,curCond->value->val.charVal, GE_OP, curCond->length); if (tmp == 1) { tmp = charMatch(cp, curCond->maxValue->val.charVal, LE_OP, curCond->length); } break; case TEXT_TYPE: cp = (char *)data + *offset +1; tmp = varcharMatch(cacheEntry,cp, curCond->value->val.charVal, curCond->length, GE_OP); if (tmp == 1) { tmp = varcharMatch(cacheEntry,cp, curCond->maxValue->val.charVal, curCond->length, LE_OP); } break; case REAL_TYPE: bcopy8((data + *offset + 2),&fv); realMatch(fv,curCond->value->val.realVal,GE_OP, tmp); if (tmp == 1) { realMatch(fv,curCond->maxValue->val.realVal, LE_OP, tmp); } break; case BYTE_TYPE: cp = (char *)data + *offset +1; tmp = byteRangeMatch(cp,curCond->value->val.byteVal, GE_OP, curCond->length); if (tmp == 1) { tmp = byteRangeMatch(cp, curCond->maxValue->val.byteVal, LE_OP, curCond->length); } break; } return(tmp);} static int processCondMatch(cacheEntry,curCond,value,row, data, offset, tmpVal) cache_t *cacheEntry; mCond_t *curCond; mVal_t *value; row_t *row; u_char *data;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -