📄 cra.c
字号:
{ new->type = CAND_ROWID; new->lastPos = NO_POS; new->length = 4; new->rowID = rowID; msqlDebug1(MOD_ACCESS, "setupCandidate() : Using _ROWID for %s\n", entry->table); if (query->explainOnly) { strcpy(packet,"\tUsing _ROWID\n"); netWritePacket(query->clientSock); } return(new); } /* ** Look for the wierd _seq case. We need this because it's ** possible (in fact normal) to just select the seq value. In ** that situation we can't expect to just fill in the blanks ** for a table row access as there may not be any table data ** yet (e.g. the first insert into a table that uses the SEQ ** as a key). Use this for everything but _rowid and _timestamp. ** It's ugly but it works. */ if (query->fieldHead) { if (query->fieldHead->next == NULL && query->fieldHead->sysvar == 1) { if (strcmp(query->fieldHead->name, "_rowid") != 0 && strcmp(query->fieldHead->name, "_timestamp") != 0) { new->type = CAND_SYS_VAR; new->lastPos = NO_POS; new->length = 0; new->rowID = 0; msqlDebug1(MOD_ACCESS, "setupCandidate() : Fake sysvar for %s\n", entry->table); return(new); } } } /* ** Check for an equality index condition. Match on the longest index ** or the first unique. Keep an eye out for index prefix ** matches that we could use */ new->type = CAND_SEQ; new->nextPos = 0; new->length = 0; doRange = 0; curIndex = entry->indices; index = 0; if (*entry->cname != 0) tableName = entry->cname; else tableName = entry->table; haveUnique = indexMatches = 0; while(curIndex) { idxCond = NULL; field = 0; identKey = 0; while(field < MAX_INDEX_WIDTH && curIndex->fields[field] != -1) { curCond = query->condHead; while(curCond) { if (strcmp(curCond->table, entry->table)!=0) { curCond=curCond->next; continue; } if (curCond->value->type == IDENT_TYPE || curCond->value->type == SYSVAR_TYPE) { identKey |= 1; } if(strcmp(tableName,curIndex->table)==0 && curCond->fieldID == curIndex->fields[field]) { if( (curCond->op == EQ_OP || curCond->op == BETWEEN_OP || curCond->op == LT_OP || curCond->op == LE_OP || curCond->op == GT_OP || curCond->op == GE_OP) && !((curCond->value->type==IDENT_TYPE|| curCond->value->type==SYSVAR_TYPE) && ignoreIdent)) { break; } } curCond = curCond->next; } if (!curCond) { break; } switch(curCond->op) { case BETWEEN_OP: doRange = CAND_IDX_RANGE; break; case LE_OP: doRange = CAND_IDX_RANGE_LE; break; case LT_OP: doRange = CAND_IDX_RANGE_LT; break; case GE_OP: doRange = CAND_IDX_RANGE_GE; break; case GT_OP: doRange = CAND_IDX_RANGE_GT; break; } field++; } /* ** Don't attempt to do a range match on a compound ** index. It can't be done. */ if (doRange) { if (curIndex->fields[1] != -1) curCond = NULL; } if (curCond) { if (identKey == 0) { validIndices[indexMatches] = index; numEntries = idxGetNumEntries(&curIndex->handle); numKeys = idxGetNumKeys(&curIndex->handle); if (numKeys) { indexWeights[indexMatches] = numEntries / numKeys; } else { indexWeights[indexMatches] = 0; } indexMatches++; } if (curIndex->unique) { haveUnique = 1; if (doRange) new->type = doRange; else new->type = CAND_IDX_ABS; new->index = index; new->ident = identKey; new->lastPos = NO_POS; new->length = curIndex->length; strcpy(new->idx_name, curIndex->name); candIndex = curIndex; if (query->explainOnly) { snprintf(packet,PKT_LEN, "\tFound unique %s index (%s)\n", new->type == CAND_IDX_RANGE? "range" : "absolute", curIndex->name); netWritePacket(query->clientSock); } break; } if (curIndex->length > new->length) { if (doRange) new->type = doRange; else new->type = CAND_IDX_ABS; new->index = index; new->ident = identKey; new->lastPos = NO_POS; new->length = curIndex->length; strcpy(new->idx_name, curIndex->name); if (query->explainOnly) { snprintf(packet,PKT_LEN, "\tFound %s index (%s) of length %d\n", new->type == CAND_IDX_RANGE? "range" : "absolute", curIndex->name, curIndex->length); netWritePacket(query->clientSock); } candIndex = curIndex; } } curIndex = curIndex->next; index++; } /* ** Can we do a union index? Don't bother if we have a unique. ** If we are going to do it then make sure it's done in the most ** efficient order. */#ifdef UNION_INDEX prevIdx.native = NULL; if (indexMatches > 1 && haveUnique == 0) { /* ** Yup we can. Sort those puppies based on index weight ** (i.e. num entries / num keys) */ while(1) { index = 1; done = 1; while(index < indexMatches) { if(indexWeights[index-1] > indexWeights[index]) { tmpIndex = validIndices[index -1]; validIndices[index - 1] = validIndices[index]; validIndices[index] = tmpIndex; tmpWeight = indexWeights[index -1]; indexWeights[index - 1] = indexWeights[index]; indexWeights[index] = tmpWeight; done = 0; } index++; } if (done) break; } /* ** Scan through the valid indices and ** create an AVL tree containing just the rowid's of ** the intersection of the indices (i.e. the union index) */ index = 0; tmpIdx.native = prevIdx.native = NULL; while(index < indexMatches) { curIndex = entry->indices; count = 0; while(count < validIndices[index]) { curIndex = curIndex->next; count++; } msqlDebug3(MOD_CANDIDATE, "Union index on %s:%s with weight %d\n", curIndex->table,curIndex->name, indexWeights[index]); if (unionIdxCreateTmpIndex(&tmpIdx, &prevIdx, curIndex, query->condHead) < 0) { tmpIdx.native = NULL; } if (prevIdx.native) { unionIdxFree(&prevIdx); } bcopy(&tmpIdx,&prevIdx,sizeof(tmpIdx)); curIndex = curIndex->next; index++; } new->unionIndex = &tmpIdx; new->type = CAND_UNION; msqlDebug1(MOD_CANDIDATE, "setupCandidate() : Using UNION_INDEX for %s\n", entry->table); return(new); }#endif /* UNION_INDEX */ /* ** Setup the index stuff */ if (new->type == CAND_IDX_ABS || new->type == CAND_IDX_RANGE || new->type == CAND_IDX_RANGE_LE || new->type == CAND_IDX_RANGE_LT || new->type == CAND_IDX_RANGE_GE || new->type == CAND_IDX_RANGE_GT ) { new->handle = candIndex->handle; new->buf = (char *)malloc(new->length + 1); new->maxBuf = (char *)malloc(new->length + 1); new->keyType = candIndex->keyType; /* Setup the key buffer */ count = 0; cp = new->buf; bzero(new->buf,new->length + 1); cp1 = new->maxBuf; bzero(new->maxBuf,new->length + 1); while(candIndex->fields[count] != -1) { curCond = query->condHead; while(curCond) { if (curCond->subCond) { curCond = curCond->next; continue; } if(curCond->fieldID==candIndex->fields[count] && curCond->value->type != IDENT_TYPE) { if (curCond->value->nullVal) { snprintf(errMsg,MAX_ERR_MSG, NULL_COND_ERR, curCond->name); return(NULL); } extractFieldValue(cp,curCond); extractMaxFieldValue(cp1,curCond); cp += curCond->length; cp1 += curCond->length; break; } curCond = curCond->next; } count++; } msqlDebug2(MOD_ACCESS, "setupCandidate() : Using IDX %d for %s\n", new->index, entry->table); return(new); } if (query->explainOnly) { strcpy(packet,"\tDidn't find anything of use. Using SEQ\n"); netWritePacket(query->clientSock); } msqlDebug1(MOD_ACCESS, "setupCandidate() : Using SEQ for %s\n", entry->table); return(new);}void craResetCandidate(cand, deleteFlag) mCand_t *cand; int deleteFlag;{ /* ** If it's a SEQ search candidate then just start at the top ** again. We need to reset it in this way when the candidate ** is the inner loop of a join. If this is from a delete only ** reset index based candidates */ if (cand->type == CAND_SEQ && deleteFlag == 0) cand->nextPos = 0; else cand->lastPos = NO_POS;}u_int craGetCandidate(entry, cand) cache_t *entry; mCand_t *cand;{ int length, rangeEnd, res = 0; u_int pos; idx_nod node; switch(cand->type) { case CAND_SEQ: cand->nextPos++; if (cand->nextPos > entry->sblk->numRows) { msqlDebug1(MOD_ACCESS, "getCandidate() : SEQ on %s => NO_POS\n", entry->table); return(NO_POS); } else { msqlDebug2(MOD_ACCESS, "getCandidate() : SEQ on %s => %d\n", entry->table, cand->nextPos -1); return(cand->nextPos -1); } break; case CAND_IDX_ABS: msqlDebug2(MOD_ACCESS, "getCandidate() : using IDX '%s' on %s\n", cand->idx_name, entry->table); msqlDebug3(MOD_ACCESS, "getCandidate() : IDX key on %s = '%s','%d'\n", entry->table, cand->buf, (int) *(int*)cand->buf); length = cand->length; if (cand->lastPos == NO_POS) { res = idxLookup(&cand->handle, cand->buf, cand->length, IDX_EXACT, &node); idxSetCursor(&cand->handle, &cand->cursor); } else { res = idxGetNext(&cand->handle, &cand->cursor,&node); } if (res != IDX_OK) { idxCloseCursor(&cand->handle, &cand->cursor); msqlDebug1(MOD_ACCESS, "getCandidate() : IDX on %s => NO_POS\n", entry->table); return(NO_POS); } if (cand->keyType == IDX_CHAR) { if (strcmp(node.key, cand->buf) != 0) { msqlDebug1(MOD_ACCESS, "getCandidate() : IDX on %s => NO_POS\n", entry->table); return(NO_POS); } } else { if (bcmp(node.key, cand->buf, length) != 0) { msqlDebug1(MOD_ACCESS, "getCandidate() : IDX on %s => NO_POS\n", entry->table); return(NO_POS); } } pos = node.data; if (cand->lastPos == NO_POS) { cand->lastPos = pos; } msqlDebug2(MOD_ACCESS, "getCandidate() : IDX on %s => %d\n", entry->table, pos); return(pos); case CAND_IDX_RANGE: case CAND_IDX_RANGE_LE: case CAND_IDX_RANGE_LT: case CAND_IDX_RANGE_GE: case CAND_IDX_RANGE_GT: msqlDebug2(MOD_ACCESS, "getCandidate() : using RANGE IDX '%s' on %s\n", cand->idx_name, entry->table); msqlDebug3(MOD_ACCESS, "getCandidate() : IDX key on %s = '%s','%d'\n", entry->table, cand->buf, (int) *(int*)cand->buf); length = cand->length; if (cand->lastPos == NO_POS) { switch(cand->type) { case CAND_IDX_RANGE: case CAND_IDX_RANGE_GE: case CAND_IDX_RANGE_GT: res = idxLookup(&cand->handle, cand->buf, cand->length, IDX_CLOSEST, &node); idxSetCursor(&cand->handle, &cand->cursor); break; case CAND_IDX_RANGE_LE: case CAND_IDX_RANGE_LT: res = idxGetFirst(&cand->handle,&node); idxSetCursor(&cand->handle, &cand->cursor); break; } } else { res = idxGetNext(&cand->handle, &cand->cursor,&node); } if (res != IDX_OK) { idxCloseCursor(&cand->handle, &cand->cursor); msqlDebug1(MOD_ACCESS, "getCandidate() : RANGE IDX on %s => NO_POS\n", entry->table); return(NO_POS); } rangeEnd = 0; if (cand->type != CAND_IDX_RANGE_GT && cand->type != CAND_IDX_RANGE_GE) { switch(cand->keyType) { case IDX_CHAR: if (strcmp(node.key, cand->maxBuf) > 0) rangeEnd = 1; break; case IDX_INT: if (idxIntCompare(node.key, cand->maxBuf) > 0) rangeEnd = 1; break; case IDX_UINT: if (idxUIntCompare(node.key, cand->maxBuf) > 0) rangeEnd = 1; break; case IDX_REAL: if (idxRealCompare(node.key, cand->maxBuf) > 0) rangeEnd = 1; break; default: if(idxByteCompare(node.key,cand->maxBuf, length)>0) { rangeEnd = 1; } } } if (rangeEnd) { idxCloseCursor(&cand->handle, &cand->cursor); msqlDebug1(MOD_ACCESS, "getCandidate() : RANGE IDX on %s => NO_POS\n", entry->table); return(NO_POS); } pos = node.data; if (cand->lastPos == NO_POS) { cand->lastPos = pos; } msqlDebug2(MOD_ACCESS, "getCandidate() : RANGE IDX on %s => %d\n", entry->table, pos); return(pos); case CAND_UNION: if (cand->lastPos == NO_POS) { cand->lastPos = 0; } cand->lastPos++; return(unionIdxGet(cand->unionIndex,cand->lastPos-1)); case CAND_ROWID: msqlDebug2(MOD_ACCESS, "getCandidate() : using ROW ID '%d' on %s\n", cand->rowID, entry->table); if (cand->lastPos == NO_POS) { if (entry->sblk->numRows < cand->rowID) { cand->rowID = 0; return(NO_POS); } cand->lastPos = cand->rowID; return(cand->rowID); } else { return(NO_POS); } } return(NO_POS);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -