📄 select.c
字号:
{ t2 = tail = newCond; } else { tail->next = newCond; tail = newCond; } } else if (cur->value->type == IDENT_TYPE && strcmp(table2->table,cur->value->val.identVal->seg1)==0) { newCond = condDup(cur); if (!t2) { t2 = tail = newCond; } else { tail->next = newCond; tail = newCond; } strcpy(buf, newCond->table); strcpy(newCond->table, newCond->value->val.identVal->seg1); strcpy(newCond->value->val.identVal->seg1, buf); strcpy(buf, newCond->name); strcpy(newCond->name, newCond->value->val.identVal->seg2); strcpy(newCond->value->val.identVal->seg2, buf); } cur = cur->next; } } new.head = head; new.t1 = t1; new.t2 = t2; return(&new);}static cache_t *joinTables(server, table1,table2, query) msqld *server; cache_t *table1, *table2; mQuery_t *query;{ cache_t *tmpTable = NULL, *outer, *inner; int outerRowNum, innerRowNum, identFList[MAX_FIELDS], t1Partial, t2Partial, doPartial, res; mCond_t *newCondHead, *t1CondHead, *t2CondHead, *outerConds, *innerConds, *newCond, *curCond; mField_t *curField, *tmpField, *identFields; row_t outerRow, innerRow, *row; mCand_t *outerCand, *innerCand, *t1Cand, *t2Cand; mQuery_t t1Query, t2Query; join_t *joinInfo; debugTrace(TRACE_IN,"joinTables()"); if (query->explainOnly) { snprintf(packet,PKT_LEN,"Joining %s and %s.\n", table1->table, table2->table); netWritePacket(query->clientSock); } /* ** Work out the conditions that apply to the join as a whole and ** the two tables individually if (utilSetupConds(table1,query->condHead) < 0) { return(NULL); } if (utilSetupConds(table2,query->condHead) < 0) { return(NULL); } */ joinInfo = setupJoinConditions(table1, table2, query->condHead, query->tableHead); newCondHead = joinInfo->head; t1CondHead = joinInfo->t1; t2CondHead = joinInfo->t2; if(utilSetupConds(table1,t1CondHead) < 0) { return(NULL); } if(utilSetupConds(table2,t2CondHead) < 0) { return(NULL); } /* ** See if we can do partial match optimisation on either table */ t1Partial = checkForPartialMatch(t1CondHead); t2Partial = checkForPartialMatch(t2CondHead); /* ** What about index based lookups? Look for a straight literal ** index first and then an IDENT based key if we don't have ** anything. If we end up with 2 IDENT based indices then we ** drop the first and make it sequential. */ bzero(&t1Query, sizeof(t1Query)); bzero(&t2Query, sizeof(t2Query)); if (query->explainOnly) { sprintf(packet,"Doing candidate setup for table 1 (%s)\n", table1->table); netWritePacket(query->clientSock); strcpy(packet,"Check for literal based index lookups\n"); netWritePacket(query->clientSock); } t1Query.condHead = t1CondHead; t1Query.explainOnly = query->explainOnly; t1Cand = craSetupCandidate(table1, &t1Query, IGNORE_IDENT); if (!t1Cand) return(NULL); if (t1Cand->type == CAND_SEQ) { if (query->explainOnly) { strcpy(packet,"Current access method is sequential."); strcat(packet," Checking for ident index lookup.\n"); netWritePacket(query->clientSock); } craFreeCandidate(t1Cand); t1Cand = craSetupCandidate(table1, &t1Query, KEEP_IDENT); if (query->explainOnly) { if (t1Cand->type == CAND_SEQ) strcpy(packet,"No. Still using sequential.\n"); else strcpy(packet, "Using ident based index lookup.\n"); netWritePacket(query->clientSock); } } if (!t1Cand) return(NULL); if (query->explainOnly) { sprintf(packet,"Doing candidate setup for table 2 (%s)\n", table2->table); netWritePacket(query->clientSock); strcpy(packet,"Check for literal based index lookups\n"); netWritePacket(query->clientSock); } t2Query.condHead = t2CondHead; t2Query.explainOnly = query->explainOnly; t2Cand = craSetupCandidate(table2, &t2Query, IGNORE_IDENT); if (!t2Cand) { craFreeCandidate(t1Cand); return(NULL); } if (t2Cand->type == CAND_SEQ) { if (query->explainOnly) { strcpy(packet,"Current access method is sequential."); strcat(packet," Checking for ident index lookup.\n"); netWritePacket(query->clientSock); } craFreeCandidate(t2Cand); t2Cand=craSetupCandidate(table2,&t2Query, KEEP_IDENT); if (query->explainOnly) { if (t2Cand->type == CAND_SEQ) strcpy(packet,"No. Still using sequential.\n"); else strcpy(packet, "Using ident based index lookup.\n"); netWritePacket(query->clientSock); } } if (!t2Cand) { craFreeCandidate(t1Cand); return(NULL); } if (t1Cand->type > CAND_SEQ && t2Cand->type > CAND_SEQ) { if (t1Cand->ident && t2Cand->ident) { t1Cand->type = CAND_SEQ; t1Cand->lastPos = NO_POS; } } /* ** OK, we know all there is to know. Now what can we do with it? */ if (t1Cand->type > CAND_SEQ) { /* We've got an index on T1 */ if (t1Cand->ident == 0) { if (query->explainOnly) { strcpy(packet,"Checking ident order on table 2 and rerunning candidate setup.\n"); netWritePacket(query->clientSock); } if (swapIdentConds(&t1CondHead, &t2CondHead, query) > 0) { utilSetupConds(table1,t1CondHead); utilSetupConds(table2,t2CondHead); } outer = table1; outerConds = t1CondHead; outerCand = t1Cand; inner = table2; innerConds = t2CondHead; craFreeCandidate(t2Cand); t2Cand=craSetupCandidate(table2, &t2Query, KEEP_IDENT); innerCand = t2Cand; doPartial = 0; } else { if (query->explainOnly) { strcpy(packet,"Checking ident order on table 2 and rerunning candidate setup.\n"); netWritePacket(query->clientSock); } if (swapIdentConds(&t2CondHead, &t1CondHead,query) > 0) { utilSetupConds(table1,t1CondHead); utilSetupConds(table2,t2CondHead); } outer = table2; outerConds = t2CondHead; outerCand = t2Cand; inner = table1; innerConds = t1CondHead; craFreeCandidate(t1Cand); t1Cand=craSetupCandidate(table1, &t1Query, KEEP_IDENT); innerCand = t1Cand; doPartial = 0; } } else if (t2Cand->type > CAND_SEQ) { /* We've got an index on T2 */ if (t2Cand->ident == 0) { if (swapIdentConds(&t2CondHead, &t1CondHead,query) > 0) { utilSetupConds(table1,t1CondHead); utilSetupConds(table2,t2CondHead); } outer = table2; outerConds = t2CondHead; outerCand = t2Cand; inner = table1; innerConds = t1CondHead; craFreeCandidate(t1Cand); t1Cand=craSetupCandidate(table1, &t1Query, KEEP_IDENT); innerCand = t1Cand; doPartial = 0; } else { if (swapIdentConds(&t1CondHead, &t2CondHead,query) > 0) { utilSetupConds(table1,t1CondHead); utilSetupConds(table2,t2CondHead); } outer = table1; outerConds = t1CondHead; outerCand = t1Cand; inner = table2; innerConds = t2CondHead; craFreeCandidate(t2Cand); t2Cand=craSetupCandidate(table2, &t2Query, KEEP_IDENT); innerCand = t2Cand; doPartial = 0; } } else if (t1Partial) { /* We've got a partial match on T1 */ outer = table1; outerConds = t1CondHead; outerCand = t1Cand; inner = table2; innerConds = t2CondHead; innerCand = t2Cand; doPartial = 1; } else if (t2Partial) { /* We've got a partial match on T2 */ outer = table2; outerConds = t2CondHead; outerCand = t2Cand; inner = table1; innerConds = t1CondHead; innerCand = t1Cand; doPartial = 1; } else { /* We've got nothing to speed this up */ outer = table1; outerConds = t1CondHead; outerCand = t1Cand; inner = table2; innerConds = t2CondHead; innerCand = t2Cand; doPartial = 0; } /* ** Now that we know the inner table, we need to create a field ** list containing the fields from the outer table that are used ** as IDENT_TYPE conditions for the inner table. Without this ** we can't do candidate based lookups for the inner table. */ identFields = buildIdentList(outer, innerConds, identFList); /* ** Create a table definition for the join result. We can't do ** this earlier as we must know which is the inner and outer table */ tmpTable = tableCreateTmpTable(server, NULL, NULL, outer,inner, query->fieldHead,ALL_FIELDS); if (!tmpTable) { craFreeCandidate(innerCand); craFreeCandidate(outerCand); debugTrace(TRACE_OUT,"joinTables()"); return(NULL); } (void)snprintf(tmpTable->resInfo,4 * (NAME_LEN + 1), "'%s (%s+%s)'",tmpTable->table, table1->table, table2->table); /* ** Do the join */ row = &(tmpTable->row); if (utilSetupConds(tmpTable,newCondHead) < 0) { craFreeCandidate(innerCand); craFreeCandidate(outerCand); tableFreeTmpTable(server,tmpTable); debugTrace(TRACE_OUT,"joinTables()"); return(NULL); } if (query->explainOnly) { strcpy(packet,"Starting join\n"); netWritePacket(query->clientSock); } outerRowNum = craGetCandidate(outer, outerCand); while(outerRowNum != NO_POS) { tableReadRow(outer,&outerRow,outerRowNum); /* ** Dodge holes */ if (!outerRow.header->active) { outerRowNum = craGetCandidate(outer, outerCand); continue; } /* ** Partial match optimisation ?? */ if(doPartial) { if(compareMatchRow(outer,&outerRow,outerConds,query)!=1) { outerRowNum = craGetCandidate(outer, outerCand); continue; } } /* ** Go ahead and join this row with the inner table */ tableExtractValues(outer,&outerRow,identFields,identFList, query); if (craSetCandidateValues(inner, innerCand, identFields, innerConds, &outerRow, query) < 0) { tableFreeTmpTable(server, tmpTable); craFreeCandidate(innerCand); craFreeCandidate(outerCand); return(NULL); } craResetCandidate(innerCand, 0); innerRowNum = craGetCandidate(inner, innerCand); while(innerRowNum != NO_POS) { tableReadRow(inner,&innerRow,innerRowNum); if (!innerRow.header->active) { innerRowNum = craGetCandidate(inner, innerCand); continue; } row->header->active = 1; mergeRows(tmpTable,row,outer,&outerRow,inner,&innerRow, query); res=compareMatchRow(tmpTable,row,newCondHead,query); if (res < 0) { craFreeCandidate(innerCand); craFreeCandidate(outerCand); tableFreeTmpTable(server, tmpTable); debugTrace(TRACE_OUT,"joinTables()"); return(NULL); } if (res == 1) { if(tableWriteRow(tmpTable,NULL,NO_POS,query)<0) { tableFreeTmpTable(server, tmpTable); craFreeCandidate(outerCand); craFreeCandidate(innerCand); debugTrace(TRACE_OUT,"joinTables()"); return(NULL); } } innerRowNum = craGetCandidate(inner, innerCand); } outerRowNum = craGetCandidate(outer, outerCand); } craFreeCandidate(innerCand); craFreeCandidate(outerCand); /* ** Free up the space allocated to the new condition list. ** We don't need to free the value structs as we just copied ** the pointers to them. They'll be freed during msqlClen(); */ curCond = newCondHead; while(curCond) { newCond = curCond; curCond = curCond->next; if (newCond->value) { parseFreeValue(newCond->value); newCond->value = NULL; } memFreeCondition(newCond); } curCond = t1CondHead; while(curCond) { newCond = curCond; curCond = curCond->next; if (newCond->value) { parseFreeValue(newCond->value); newCond->value = NULL; } memFreeCondition(newCond); } curCond = t2CondHead; while(curCond) { newCond = curCond; curCond = curCond->next; if (newCond->value) { parseFreeValue(newCond->value); newCond->value = NULL; } memFreeCondition(newCond); } if (identFields) { curField = identFields; while(curField) { tmpField = curField; curField = curField->next; if (tmpField->value) { parseFreeValue(tmpField->value); tmpField->value = NULL; } memFreeField(tmpField); } } if (query->explainOnly) { sprintf(packet,"Join complete - result in %s\n", tmpTable->table); netWritePacket(query->clientSock); } debugTrace(TRACE_OUT,"joinTables()"); return(tmpTable);}static int doSelect(cacheEntry, query, dest, checkConds, tmpTable) cache_t *cacheEntry; mQuery_t *query; int dest, checkConds; cache_t *tmpTable;{ int flist[MAX_FIELDS], tmpFlist[MAX_FIELDS], rowLen, rowNum, numFields, abortSelect, count, res; char outBuf[100], outBuf2[100], *fieldName; row_t row; mCand_t *candidate; mField_t *identFields; mField_t *curField; debugTrace(TRACE_IN,"doSelect()"); identFields = NULL; numFields = 0; curField = query->fieldHead; while(curField) { numFields++; curField = curField->next; } /* ** Find the offsets of the given fields and condition */ if (utilSetupFields(cacheEntry,flist,query->fieldHead) < 0) { debugTrace(TRACE_OUT,"doSelect()"); return(-1); } if (checkConds) { if (utilSetupConds(cacheEntry,query->condHead) < 0) { debugTrace(TRACE_OUT,"doSelect()"); return(-1); } } if (tmpTable) { if (utilSetupFields(tmpTable,tmpFlist,query->fieldHead) < 0) { debugTrace(TRACE_OUT,"doSelect()"); return(-1); } } candidate = craSetupCandidate(cacheEntry, query, IGNORE_IDENT); if (!candidate) { return(-1); } rowLen = cacheEntry->rowLen; if (tableInitTable(cacheEntry,FULL_REMAP) < 0) { craFreeCandidate(candidate); debugTrace(TRACE_OUT,"doSelect()"); return(-1); } if (functCheckFunctions(query) < 0) { craFreeCandidate(candidate); debugTrace(TRACE_OUT,"doSelect()"); return(-1); } /* ** Tell the client how many fields there are in a row */ if (dest == DEST_CLIENT && !query->explainOnly) { snprintf(packet,PKT_LEN,"1:%d:\n",numFields); netWritePacket(query->clientSock); } /* ** Special case for singe field sys var access. Check the comments ** in craSetupCandidate() for info on why this is needed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -