📄 cra.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: cra.c,v 1.14 2002/06/29 04:08:58 bambi Exp $***//*** Module : cra : cra** Purpose : ** Exports : ** Depends Upon : *//**************************************************************************** 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/cra/cra.h>#include <msqld/cra/uidx.h>#include <common/types/types.h>#include <msqld/main/main.h>#include <msqld/main/parse.h>#include <msqld/main/sysvar.h>#include <msqld/main/net.h>#include <libmsql/msql.h>/**************************************************************************** GLOBAL VARIABLES**************************************************************************//* HACK */extern char *msqlHomeDir;extern char *packet;extern char errMsg[];extern int outSock;/**************************************************************************** PRIVATE ROUTINES**************************************************************************/static void extractCondValue(buf,cond,max) char *buf; mCond_t *cond; int max;{ int length; switch(typeBaseType(cond->value->type)) { case INT_TYPE: case UINT_TYPE: if (max) bcopy(&(cond->maxValue->val.intVal),buf,4); else bcopy(&(cond->value->val.intVal),buf,4); break; case REAL_TYPE: if (max) bcopy(&(cond->maxValue->val.realVal),buf,8); else bcopy(&(cond->value->val.realVal),buf,8); break; case CHAR_TYPE: if (max) length = strlen(cond->maxValue->val.charVal); else length = strlen(cond->value->val.charVal); if (length > cond->length) length = cond->length; if (max) bcopy((char *)cond->maxValue->val.charVal, buf,length); else bcopy((char *)cond->value->val.charVal, buf,length); break; }}static void extractFieldValue(buf,cond) char *buf; mCond_t *cond;{ extractCondValue(buf,cond,0);}static void extractMaxFieldValue(buf,cond) char *buf; mCond_t *cond;{ if (cond->op == BETWEEN_OP) extractCondValue(buf,cond,1); if (cond->op == LE_OP || cond->op == LT_OP) extractCondValue(buf,cond,0);}#define CACHE_LEN 5static int candCount = 0;static mCand_t *candCache[CACHE_LEN];static mCand_t *_mallocCand(){ mCand_t *new; if (candCount > 0) { candCount--; new = candCache[candCount]; } else { new = (mCand_t *)malloc(sizeof(mCand_t)); } new->type = new->index = new->ident = new->length = new->rowID = new->keyType = new->nextPos = 0; new->rangeMin = new->rangeMax = new->buf = new->maxBuf = NULL; *new->idx_name = 0; new->unionIndex = NULL; return(new);}static void _freeCand(ptr) mCand_t *ptr;{ if (candCount >= CACHE_LEN) { free(ptr); } else { candCache[candCount] = ptr; candCount++; }}/**************************************************************************** PUBLIC ROUTINES**************************************************************************//*** This is the mSQL 2.0 Candidate Row Abstraction code. In short, it's** the query optimsation module.*/void craFreeCandidate(cand) mCand_t *cand;{ if (cand) { if (cand->buf) { free(cand->buf); cand->buf = NULL; } if (cand->maxBuf) { free(cand->maxBuf); cand->maxBuf = NULL; } _freeCand(cand); }}int craSetCandidateValues(inner, cand, fields, conds, row, query) cache_t *inner; mCand_t *cand; mField_t *fields; mCond_t *conds; row_t *row; mQuery_t *query;{ mIndex_t *curIndex; mField_t *curField, tmpField; mCond_t *curCond; int count, fieldID; char *cp; if (cand->type == CAND_SEQ) { return(0); } curIndex = inner->indices; count = cand->index; while(count && curIndex) { count--; curIndex = curIndex->next; } if (!curIndex) return(0); /* ** We can't use fillIndexBuffer() here as some of the ** values are in the cond list and others are in the ident ** fields list. Sigh... */ curIndex = inner->indices; count = 0; while(count < cand->index) { curIndex = curIndex->next; count ++; } cp = cand->buf; bzero(cp, curIndex->length + 1); count = 0; while(curIndex->fields[count] != -1) { fieldID = curIndex->fields[count]; /* ** Look for an ident value first */ curField = fields; while(curField) { if(curField->fieldID == fieldID) { if (parseCopyValue(cp,curField->value,curField->type, curField->length,0) < 0) { snprintf(errMsg,MAX_ERR_MSG, NULL_JOIN_COND_ERR, curField->name); return(-1); } cp+=curField->length; break; } curField = curField->next; } if (curField) { /* Found it */ count++; continue; } /* ** OK, check out the normal conditions */ curCond = conds; while(curCond) { if(curCond->fieldID == fieldID) { /* ** Could be a sysvar ? */ strcpy(tmpField.name,curCond->name); if (sysvarCheckVariable(inner, &tmpField) == 0) { sysvarGetVariable(inner,row,&tmpField, query); if(parseCopyValue(cp,tmpField.value, tmpField.type,tmpField.length,0)<0) { snprintf(errMsg,MAX_ERR_MSG, NULL_JOIN_COND_ERR, curField->name); return(-1); } cp += tmpField.length; } else { /* ** Nope, it's a normal field */ if(parseCopyValue(cp,curCond->value, curCond->type,curCond->length,0)<0) { snprintf(errMsg,MAX_ERR_MSG, NULL_JOIN_COND_ERR, curField->name); return(-1); } cp += curCond->length; } break; } curCond = curCond->next; } if (curCond) { /* Found it */ count++; continue; }/***/ abort(); } cand->lastPos = NO_POS; return(0);}mTable_t *craReorderTableList(query) mQuery_t *query;{ /* ** This isn't part of the CRA but it still an important part ** of the query optimiser so it's in this module. ** ** Work out the best order for the tables of a join to be ** processed as the user may have specified them in a bad ** order (like certain benchmark suites). */ mCond_t *curCond; mTable_t *head = NULL, *tail = NULL, *prevTable = NULL, *curTable = NULL, *pivotTable = NULL, *pivotPrev = NULL; int condCount, maxCount; /* ** Any table with a literal condition goes to the head ** of the list */ curTable = query->tableHead; prevTable = NULL; while(curTable) { curCond = query->condHead; while(curCond) { if (strcmp(curCond->table,curTable->name) == 0 && curCond->value->type != IDENT_TYPE) { break; } curCond = curCond->next; } if (curCond) { /* ** Pull it out of the original list */ if (prevTable) prevTable->next = curTable->next; else query->tableHead = curTable->next; /* ** Add it to the new list */ if (head) tail->next = curTable; else head = curTable; tail = curTable; tail->next = NULL; /* ** Move on to the next */ if (prevTable) curTable = prevTable->next; else curTable = query->tableHead; continue; } prevTable = curTable; curTable = curTable->next; } /* ** Next, move the remaining tables onto the list ensuring that ** the "pivot" table of the remainder is moved first. */ while(query->tableHead) { maxCount = 0; curTable = query->tableHead; prevTable = NULL; while(curTable) { curCond = query->condHead; condCount = 0; while(curCond) { if (curCond->subCond) { curCond = curCond->next; continue; } if (strcmp(curCond->table, curTable->name)==0) { condCount++; } else if (curCond->value) { if(curCond->value->type==IDENT_TYPE && strcmp(curCond->value->val.identVal->seg1, curTable->name)==0) { condCount++; } } curCond = curCond->next; continue; } if (condCount > maxCount) { pivotTable = curTable; pivotPrev = prevTable; maxCount = condCount; } prevTable = curTable; curTable = curTable->next; } if (maxCount == 0) { /* ** Not good. Break out so we just append the ** rest and bail */ break; } if (pivotPrev) pivotPrev->next = pivotTable->next; else query->tableHead = pivotTable->next; if (head) tail->next = pivotTable; else head = pivotTable; tail = pivotTable; tail->next = NULL; } if (head) tail->next = query->tableHead; else head = query->tableHead; return(head);}mCand_t *craSetupCandidate(entry, query, ignoreIdent) cache_t *entry; mQuery_t *query; int ignoreIdent;{ mCand_t *new; mIndex_t *curIndex = NULL, *candIndex = NULL; mCond_t *curCond, *idxCond; int count, field, identKey, index, doRowID, doRange, haveUnique, indexMatches, rowID, validIndices[NUM_INDEX], indexWeights[NUM_INDEX], numKeys, numEntries; char *tableName, *cp, *cp1;#ifdef UNION_INDEX static idx_hnd tmpIdx, prevIdx; int tmpIndex, tmpWeight, done;#endif /* ** This is the query optimiser! The conditions are checked to ** see which access mechanism is going to provide the fastest ** query result. */ if (query->explainOnly) { snprintf(packet,PKT_LEN, "Setup Candidate called\n\tTable = %s\n\tCheck ident comparisons = %s\n", entry->result?entry->resInfo:entry->table, ignoreIdent?"No":"Yes"); netWritePacket(query->clientSock); } new = _mallocCand(); new->buf = NULL; new->maxBuf = NULL; /* ** We can't handle OR's yet so do a quick scan through the ** conditions */ curCond = query->condHead; while(curCond) { if (curCond->bool == OR_BOOL) { new->type = CAND_SEQ; new->nextPos = 0; msqlDebug1(MOD_ACCESS, "setupCandidate() : Using SEQ for %s\n", entry->table); if (query->explainOnly) { strcpy(packet,"\tFound OR! Using SEQ\n"); netWritePacket(query->clientSock); } return(new); } curCond = curCond->next; } /* ** First test is to see if we can do a row_id based access */ rowID = 0; curCond = query->condHead; doRowID = 0; while(curCond) { if (strcmp(curCond->name, "_rowid")==0 && curCond->op == EQ_OP) { doRowID++; rowID = curCond->value->val.intVal; break; } curCond = curCond->next; } if (doRowID == 1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -