📄 nbtutils.c
字号:
{ if (i < numberOfKeys) { /* See comments above: any NULL implies cannot match qual */ if (cur->sk_flags & SK_ISNULL) { so->qual_ok = false; /* * Quit processing so we don't try to invoke comparison * routines on NULLs. */ return; } } /* * If we are at the end of the keys for a particular attr, finish * up processing and emit the cleaned-up keys. */ if (i == numberOfKeys || cur->sk_attno != attno) { bool priorAllEqualSoFar = allEqualSoFar; /* check input keys are correctly ordered */ if (i < numberOfKeys && cur->sk_attno != attno + 1) elog(ERROR, "key(s) for attribute %d missed", attno + 1); /* * If = has been specified, no other key will be used. In case * of key > 2 && key == 1 and so on we have to set qual_ok to * false before discarding the other keys. */ if (init[BTEqualStrategyNumber - 1]) { ScanKeyData *eq, *chk; eq = &xform[BTEqualStrategyNumber - 1]; for (j = BTMaxStrategyNumber; --j >= 0;) { if (!init[j] || j == (BTEqualStrategyNumber - 1)) continue; chk = &xform[j]; test = OidFunctionCall2(chk->sk_procedure, eq->sk_argument, chk->sk_argument); if (!DatumGetBool(test)) so->qual_ok = false; } init[BTLessStrategyNumber - 1] = false; init[BTLessEqualStrategyNumber - 1] = false; init[BTGreaterEqualStrategyNumber - 1] = false; init[BTGreaterStrategyNumber - 1] = false; } else { /* * No "=" for this key, so we're done with required keys */ allEqualSoFar = false; } /* keep only one of <, <= */ if (init[BTLessStrategyNumber - 1] && init[BTLessEqualStrategyNumber - 1]) { ScanKeyData *lt = &xform[BTLessStrategyNumber - 1]; ScanKeyData *le = &xform[BTLessEqualStrategyNumber - 1]; test = OidFunctionCall2(le->sk_procedure, lt->sk_argument, le->sk_argument); if (DatumGetBool(test)) init[BTLessEqualStrategyNumber - 1] = false; else init[BTLessStrategyNumber - 1] = false; } /* keep only one of >, >= */ if (init[BTGreaterStrategyNumber - 1] && init[BTGreaterEqualStrategyNumber - 1]) { ScanKeyData *gt = &xform[BTGreaterStrategyNumber - 1]; ScanKeyData *ge = &xform[BTGreaterEqualStrategyNumber - 1]; test = OidFunctionCall2(ge->sk_procedure, gt->sk_argument, ge->sk_argument); if (DatumGetBool(test)) init[BTGreaterEqualStrategyNumber - 1] = false; else init[BTGreaterStrategyNumber - 1] = false; } /* * Emit the cleaned-up keys back into the key[] array in the * correct order. Note we are overwriting our input here! * It's OK because (a) xform[] is a physical copy of the keys * we want, (b) we cannot emit more keys than we input, so we * won't overwrite as-yet-unprocessed keys. */ for (j = BTMaxStrategyNumber; --j >= 0;) { if (init[j]) memcpy(&key[new_numberOfKeys++], &xform[j], sizeof(ScanKeyData)); } /* * If all attrs before this one had "=", include these keys * into the required-keys count. */ if (priorAllEqualSoFar) so->numberOfRequiredKeys = new_numberOfKeys; /* * Exit loop here if done. */ if (i == numberOfKeys) break; /* Re-initialize for new attno */ attno = cur->sk_attno; map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation), BTMaxStrategyNumber, attno); MemSet(xform, 0, sizeof(xform)); /* not really necessary */ MemSet(init, 0, sizeof(init)); } /* figure out which strategy this key's operator corresponds to */ j = _bt_getstrategynumber(cur->sk_procedure, map); /* have we seen one of these before? */ if (init[j]) { /* yup, keep the more restrictive value */ test = FunctionCall2(&cur->sk_func, cur->sk_argument, xform[j].sk_argument); if (DatumGetBool(test)) xform[j].sk_argument = cur->sk_argument; else if (j == (BTEqualStrategyNumber - 1)) so->qual_ok = false; /* key == a && key == b, but a != b */ } else { /* nope, so remember this scankey */ memcpy(&xform[j], cur, sizeof(ScanKeyData)); init[j] = true; } } so->numberOfKeys = new_numberOfKeys; /* * If unique index and we have equality keys for all columns, set * keys_are_unique flag for higher levels. */ if (allEqualSoFar && relation->rd_index->indisunique && relation->rd_rel->relnatts == new_numberOfKeys) scan->keys_are_unique = true;}/* * Determine which btree strategy an operator procedure matches. * * Result is strategy number minus 1. */static int_bt_getstrategynumber(RegProcedure sk_procedure, StrategyMap map){ int j; for (j = BTMaxStrategyNumber; --j >= 0;) { if (sk_procedure == map->entry[j].sk_procedure) return j; } elog(ERROR, "could not identify operator %u", sk_procedure); return -1; /* keep compiler quiet */}/* * Test whether an indextuple satisfies all the scankey conditions. * * If the tuple fails to pass the qual, we also determine whether there's * any need to continue the scan beyond this tuple, and set *continuescan * accordingly. See comments for _bt_orderkeys(), above, about how this is * done. */bool_bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, ScanDirection dir, bool *continuescan){ BTScanOpaque so = (BTScanOpaque) scan->opaque; int keysz = so->numberOfKeys; int keysok; TupleDesc tupdesc; ScanKey key; *continuescan = true; /* If no keys, always scan the whole index */ if (keysz == 0) return true; tupdesc = RelationGetDescr(scan->indexRelation); key = so->keyData; keysok = 0; IncrIndexProcessed(); while (keysz > 0) { Datum datum; bool isNull; Datum test; datum = index_getattr(tuple, key->sk_attno, tupdesc, &isNull); /* btree doesn't support 'A is null' clauses, yet */ if (key->sk_flags & SK_ISNULL) { /* we shouldn't get here, really; see _bt_orderkeys() */ *continuescan = false; return false; } if (isNull) { /* * Since NULLs are sorted after non-NULLs, we know we have * reached the upper limit of the range of values for this * index attr. On a forward scan, we can stop if this qual is * one of the "must match" subset. On a backward scan, * however, we should keep going. */ if (keysok < so->numberOfRequiredKeys && ScanDirectionIsForward(dir)) *continuescan = false; /* * In any case, this indextuple doesn't match the qual. */ return false; } if (key->sk_flags & SK_COMMUTE) test = FunctionCall2(&key->sk_func, key->sk_argument, datum); else test = FunctionCall2(&key->sk_func, datum, key->sk_argument); if (DatumGetBool(test) == !!(key->sk_flags & SK_NEGATE)) { /* * Tuple fails this qual. If it's a required qual, then we * can conclude no further tuples will pass, either. */ if (keysok < so->numberOfRequiredKeys) *continuescan = false; return false; } keysok++; key++; keysz--; } /* If we get here, the tuple passes all quals. */ return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -