1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-22 13:30:55 +01:00

Fix a fulltext search issue where finding token length and stopwords could fail

Summary:
Ref T12137. If a database is missing the InnoDB or MyISAM table engines, the big combined query to get both will fail.

Instead, try InnoDB first and then MyISAM.

(I have both engines locally so this worked until I deployed it.)

Test Plan: Faked an InnoDB error like `secure`, got a MyISAM result.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T12137

Differential Revision: https://secure.phabricator.com/D17673
This commit is contained in:
epriestley 2017-04-12 19:16:58 -07:00
parent 3245e74f16
commit ada9046e31

View file

@ -473,43 +473,56 @@ final class PhabricatorMySQLFulltextStorageEngine
}
private function newEngineLimits(AphrontDatabaseConnection $conn) {
$result = queryfx_one(
$conn,
'SELECT
@@innodb_ft_min_token_size innodb_max,
@@ft_min_word_len myisam_max,
@@ft_stopword_file myisam_stopwords');
// First, try InnoDB. Some database may not have both table engines, so
// selecting variables from missing table engines can fail and throw.
if ($result['innodb_max']) {
try {
$result = queryfx_one(
$conn,
'SELECT @@innodb_ft_min_token_size innodb_max');
} catch (AphrontQueryException $ex) {
$result = null;
}
if ($result) {
$min_len = $result['innodb_max'];
$stopwords = queryfx_all(
$conn,
'SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD');
$stopwords = ipull($stopwords, 'value');
$stopwords = array_fuse($stopwords);
} else {
$min_len = $result['myisam_max'];
$file = $result['myisam_stopwords'];
if (preg_match('(/resources/sql/stopwords\.txt\z)', $file)) {
// If this is set to something that looks like the Phabricator
// stopword file, read that.
$file = 'stopwords.txt';
} else {
// Otherwise, just use the default stopwords. This might be wrong
// but we can't read the actual value dynamically and reading
// whatever file the variable is set to could be a big headache
// to get right from a security perspective.
$file = 'stopwords_myisam.txt';
}
$root = dirname(phutil_get_library_root('phabricator'));
$data = Filesystem::readFile($root.'/resources/sql/'.$file);
$stopwords = explode("\n", $data);
$stopwords = array_filter($stopwords);
$stopwords = array_fuse($stopwords);
return array($min_len, $stopwords);
}
// If InnoDB fails, try MyISAM.
$result = queryfx_one(
$conn,
'SELECT
@@ft_min_word_len myisam_max,
@@ft_stopword_file myisam_stopwords');
$min_len = $result['myisam_max'];
$file = $result['myisam_stopwords'];
if (preg_match('(/resources/sql/stopwords\.txt\z)', $file)) {
// If this is set to something that looks like the Phabricator
// stopword file, read that.
$file = 'stopwords.txt';
} else {
// Otherwise, just use the default stopwords. This might be wrong
// but we can't read the actual value dynamically and reading
// whatever file the variable is set to could be a big headache
// to get right from a security perspective.
$file = 'stopwords_myisam.txt';
}
$root = dirname(phutil_get_library_root('phabricator'));
$data = Filesystem::readFile($root.'/resources/sql/'.$file);
$stopwords = explode("\n", $data);
$stopwords = array_filter($stopwords);
$stopwords = array_fuse($stopwords);
return array($min_len, $stopwords);
}