diff --git a/lib/searchlib.php b/lib/searchlib.php index 4f74d923e4c..964e745ae57 100644 --- a/lib/searchlib.php +++ b/lib/searchlib.php @@ -302,6 +302,128 @@ class search_parser { } } +// Primitive function to generate a SQL string from a parse tree +// using TEXT indexes. If searches aren't suitable to use TEXT +// this function calls the default search_generate_SQL() one. +// +// $parsetree should be a parse tree generated by a +// search_lexer/search_parser combination. +// Other fields are database table names to search. +function search_generate_text_SQL($parsetree, $datafield, $metafield, $mainidfield, $useridfield, + $userfirstnamefield, $userlastnamefield, $timefield, $instancefield) { + global $CFG; + +/// First of all, search for reasons to switch to standard SQL generation +/// Only mysql are supported for now + if ($CFG->dbfamily != 'mysql') { + return search_generate_SQL($parsetree, $datafield, $metafield, $mainidfield, $useridfield, + $userfirstnamefield, $userlastnamefield, $timefield, $instancefield); + } + +/// Here we'll acumulate non-textual tokens + $non_text_tokens = array(); + + $ntokens = count($parsetree); + if ($ntokens == 0) { + return ""; + } + + $SQLString = ''; + $text_sql_string = ''; + + $datasearch_clause = ''; + $metasearch_clause = ''; + + foreach ($parsetree as $token) { + + $type = $token->getType(); + $value = $token->getValue(); + + switch($type){ + case TOKEN_STRING: + /// If it's a multiword token, quote it + if (strstr($value, ' ')) { + $datasearch_clause .= '"' . $value . '" '; + /// Simple word token, search for it as prefix + } else { + $datasearch_clause .= $value . '* '; + } + break; + case TOKEN_EXACT: + /// token must be exactly as requested + $datasearch_clause .= '+' . $value . ' '; + break; + case TOKEN_NEGATE: + /// token must not exist as prefix + $datasearch_clause .= '-' . $value . '* '; + break; + case TOKEN_META: + /// token in metafield, search for it as prefix + $metasearch_clause .= $value . '* '; + break; + case TOKEN_USER: + case TOKEN_USERID: + case TOKEN_INSTANCE: + case TOKEN_DATETO: + case TOKEN_DATEFROM: + /// delegate to standard search + $non_text_tokens[] = $token; + break; + default: + return ''; + } + } + +/// Call to standard search for pending tokens + if (!empty($non_text_tokens)) { + $SQLString = search_generate_SQL($non_text_tokens, $datafield, $metafield, $mainidfield, $useridfield, + $userfirstnamefield, $userlastnamefield, $timefield, $instancefield); + } +/// Build the final SQL clause + if (!empty($datasearch_clause)) { + /// Must have $datafield to search within + if (!empty($datafield)) { + $text_sql_string .= 'MATCH (' . $datafield; + /// And optionally $metafield + if (!empty($metafield)) { + $text_sql_string .= ', ' . $metafield; + } + /// Begin with the AGAINST clause + $text_sql_string .= ') AGAINST (' . "'"; + /// Add the search terms + $text_sql_string .= trim($datasearch_clause); + /// Close AGAINST clause + $text_sql_string .= "' IN BOOLEAN MODE)"; + } + } +/// Now add the metasearch_clause + if (!empty($metasearch_clause)) { + /// Must have $metafield to search within + if (!empty($metafield)) { + /// AND operator if needed + if (!empty($text_sql_string)) { + $text_sql_string .= ' AND '; + } + $text_sql_string .= 'MATCH (' . $metafield; + /// Begin with the AGAINST clause + $text_sql_string .= ') AGAINST (' . "'"; + /// Add the search terms + $text_sql_string .= trim($metasearch_clause); + /// Close AGAINST clause + $text_sql_string .= "' IN BOOLEAN MODE)"; + } + } +/// Finally add the non-text conditions + if (!empty($SQLString)) { + /// AND operator if needed + if (!empty($text_sql_string)) { + $text_sql_string .= ' AND '; + } + $text_sql_string .= $SQLString; + } + + return $text_sql_string; +} // Primitive function to generate a SQL string from a parse tree. // Parameters: