Skip to content

Commit

Permalink
Fix a few more bugs with indexes
Browse files Browse the repository at this point in the history
  • Loading branch information
muglug committed May 19, 2023
1 parent 0f084d8 commit e15dd14
Showing 1 changed file with 49 additions and 8 deletions.
57 changes: 49 additions & 8 deletions src/Query/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,22 @@ private static function filterWithIndexes(
$matched_all_expressions = true;
$candidates = self::getIndexCandidates($where, $columns, inout $matched_all_expressions);
if ($candidates) {
$filtered_keys = self::getKeysForConditional($data_keys, $index_refs, $indexes, $candidates);
$all_expressions_indexed = true;
$filtered_keys = self::getKeysForConditional(
$data_keys,
$index_refs,
$indexes,
$candidates,
inout $all_expressions_indexed,
);

if ($filtered_keys is nonnull) {
$data = Dict\filter_keys($data, $row_pk ==> C\contains_key($filtered_keys, $row_pk));
if ($matched_all_expressions) {
$all_matched = true;
if ($all_expressions_indexed) {
$all_matched = true;
}

return $data;
}
}
Expand All @@ -86,7 +96,13 @@ private static function filterWithIndexes(
$candidates = self::getIndexCandidates($ored_where, $columns, inout $matched_all_expressions);

if ($candidates) {
$filtered_keys = self::getKeysForConditional($data_keys, $index_refs, $indexes, $candidates);
$filtered_keys = self::getKeysForConditional(
$data_keys,
$index_refs,
$indexes,
$candidates,
inout $matched_all_expressions,
);

if ($filtered_keys is nonnull) {
$all_filtered_keys = Keyset\union($all_filtered_keys, $filtered_keys);
Expand All @@ -113,6 +129,7 @@ private static function getKeysForConditional(
index_refs $index_refs,
vec<Index> $indexes,
dict<string, vec<mixed>> $candidates,
inout bool $all_expressions_indexed,
): ?keyset<arraykey> {
$candidate_keys = Keyset\keys($candidates);
$matched_fields = 0;
Expand Down Expand Up @@ -141,6 +158,10 @@ private static function getKeysForConditional(
}

if ($matched_index) {
if (C\count($candidates) > $matched_fields) {
$all_expressions_indexed = false;
}

return self::filterDataWithMatchedIndex(
$data_keys,
$index_refs,
Expand All @@ -150,6 +171,8 @@ private static function getKeysForConditional(
true,
);
} else {
$all_expressions_indexed = false;

if ($has_multiple_fields) {
foreach ($indexes as $index) {
if (C\count($index->fields) > 1) {
Expand Down Expand Up @@ -288,7 +311,7 @@ private static function getIndexCandidates(
if ($in_expr is ConstantExpression) {
$value = $in_expr->value;
if (isset($columns[$column_name])) {
if ($columns[$column_name]->hack_type === 'int') {
if ($columns[$column_name]->hack_type === 'int' && $value is string) {
$value = (int)$value;
}
}
Expand Down Expand Up @@ -389,6 +412,9 @@ private static function filterDataWithMatchedIndex(

$matched_field = C\firstx($matched_index->fields);
foreach ($candidates[$matched_field] as $candidate_value) {
if ($candidate_value is null) {
$candidate_value = '__NULL__';
}
$keys[] = $candidate_value as arraykey;
}
} else {
Expand All @@ -404,6 +430,9 @@ private static function filterDataWithMatchedIndex(

foreach ($keys as $key_parts) {
foreach ($candidates[$matched_field] as $candidate_value) {
if ($candidate_value is null) {
$candidate_value = '__NULL__';
}
$new_keys[] = Vec\concat($key_parts, vec[$candidate_value as arraykey]);
}
}
Expand Down Expand Up @@ -875,11 +904,13 @@ public static function getIndexModificationsForRow(

$store_as_unique = $index->type === 'UNIQUE' || $index->type === 'PRIMARY';

if (C\count($index->fields) === 1) {
$index_field_count = C\count($index->fields);

if ($index_field_count === 1) {
$index_part = $row[C\firstx($index->fields)] as ?arraykey;

if ($index_part is null) {
continue;
$index_part = '__NULL__';
}

$index_key = vec[$index_part];
Expand All @@ -894,8 +925,12 @@ public static function getIndexModificationsForRow(
if ($index_part is null) {
$index_part = '__NULL__';

if ($index->type === 'UNIQUE' && $inc > 0) {
$store_as_unique = false;
// don't store unique indexes with null
if ($index->type === 'UNIQUE' && $inc < $index_field_count - 1) {
if ($inc > 0) {
$store_as_unique = false;
}

break;
}
}
Expand All @@ -904,6 +939,12 @@ public static function getIndexModificationsForRow(

$inc++;
}

// this happens if the first index column contains a null value — in which case
// we don't store anything
if ($index_key === vec[]) {
continue;
}
}

$index_ref_deletes[] = tuple($index->name, $index_key, $store_as_unique);
Expand Down

0 comments on commit e15dd14

Please sign in to comment.