Repository: duckdb/duckdb
File: src/optimizer/filter_combiner.cpp (C++)

Code before:
			return false;
		}
		prev_value = current_value;
	}
	// dense range
	return true;
}

static bool SupportedFilterComparison(ExpressionType expression_type) {
	switch (expression_type) {
	case ExpressionType::COMPARE_EQUAL:
	case ExpressionType::COMPARE_GREATERTHAN:
	case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
	case ExpressionType::COMPARE_LESSTHAN:
	case ExpressionType::COMPARE_LESSTHANOREQUALTO:
	case ExpressionType::COMPARE_NOTEQUAL:
		return true;
	default:
		return false;
	}
}

bool FilterCombiner::FindNextLegalUTF8(string &prefix_string) {
	// find the start of the last codepoint
	idx_t last_codepoint_start;
	for (last_codepoint_start = prefix_string.size() - 1; last_codepoint_start >= 0; last_codepoint_start--) {
		if (IsCharacter(prefix_string[last_codepoint_start])) {
			break;
		}
	}
	D_ASSERT(last_codepoint_start >= 0);
	int codepoint_size;
	auto codepoint = Utf8Proc::UTF8ToCodepoint(prefix_string.c_str() + last_codepoint_start, codepoint_size) + 1;
	if (codepoint >= 0xD800 && codepoint <= 0xDFFF) {
		// next codepoint falls within surrogate range increment to next valid character
		codepoint = 0xE000;
	}
	char next_codepoint_text[4];
	int next_codepoint_size;
	if (!Utf8Proc::CodepointToUtf8(codepoint, next_codepoint_size, next_codepoint_text)) {
		// invalid codepoint
		return false;
	}
	auto s = static_cast<idx_t>(next_codepoint_size);
	prefix_string = prefix_string.substr(0, last_codepoint_start) + string(next_codepoint_text, s);
	return true;
}

bool TypeSupportsConstantFilter(const LogicalType &type) {
	if (TypeIsNumeric(type.InternalType())) {
		return true;

Review comment (bug):
`last_codepoint_start >= 0` is always true because `last_codepoint_start` is an `idx_t` - this will instead underflow (and loop infinitely) if this does not find a character. Could you modify this to the following loop for safety purposes - otherwise we might get infinite loops if invalid UTF8 somehow enters the system:

```cpp
idx_t last_codepoint_start;
for(last_codepoint_start = prefix_string.size(); last_codepoint_start > 0; last_codepoint_start--) {
    if (IsCharacter(prefix_string[last_codepoint_start - 1])) {
        break;
    }
}
if (last_codepoint_start == 0) {
    throw InvalidInputException("Invalid UTF8 found in string \"%s\"", prefix_string);
}
last_codepoint_start--;
```

Code after:
			return false;
		}
		prev_value = current_value;
	}
	// dense range
	return true;
}

static bool SupportedFilterComparison(ExpressionType expression_type) {
	switch (expression_type) {
	case ExpressionType::COMPARE_EQUAL:
	case ExpressionType::COMPARE_GREATERTHAN:
	case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
	case ExpressionType::COMPARE_LESSTHAN:
	case ExpressionType::COMPARE_LESSTHANOREQUALTO:
	case ExpressionType::COMPARE_NOTEQUAL:
		return true;
	default:
		return false;
	}
}

bool FilterCombiner::FindNextLegalUTF8(string &prefix_string) {
	// find the start of the last codepoint
	idx_t last_codepoint_start;
	for (last_codepoint_start = prefix_string.size(); last_codepoint_start > 0; last_codepoint_start--) {
		if (IsCharacter(prefix_string[last_codepoint_start - 1])) {
			break;
		}
	}
	if (last_codepoint_start == 0) {
		throw InvalidInputException("Invalid UTF8 found in string \"%s\"", prefix_string);
	}
	last_codepoint_start--;
	int codepoint_size;
	auto codepoint = Utf8Proc::UTF8ToCodepoint(prefix_string.c_str() + last_codepoint_start, codepoint_size) + 1;
	if (codepoint >= 0xD800 && codepoint <= 0xDFFF) {
		// next codepoint falls within surrogate range increment to next valid character
		codepoint = 0xE000;
	}
	char next_codepoint_text[4];
	int next_codepoint_size;
	if (!Utf8Proc::CodepointToUtf8(codepoint, next_codepoint_size, next_codepoint_text)) {
		// invalid codepoint
		return false;
	}
	auto s = static_cast<idx_t>(next_codepoint_size);
	prefix_string = prefix_string.substr(0, last_codepoint_start) + string(next_codepoint_text, s);
	return true;
}