Merge pull request #4486 from uniun/patch-2

BUGFIX. FulltextFilter requires table identifiers in match query
This commit is contained in:
Daniel Hensby 2015-10-07 10:28:15 +01:00
commit 95ae107c4c
2 changed files with 33 additions and 8 deletions

View File

@ -58,12 +58,12 @@ class FulltextFilter extends SearchFilter {
if(is_array($indexes) && array_key_exists($this->getName(), $indexes)) {
$index = $indexes[$this->getName()];
if(is_array($index) && array_key_exists("value", $index)) {
return $index['value'];
return $this->prepareColumns($index['value']);
} else {
// Parse a fulltext string (eg. fulltext ("ColumnA", "ColumnB")) to figure out which columns
// we need to search.
if(preg_match('/^fulltext\s+\((.+)\)$/i', $index, $matches)) {
return $matches[1];
return $this->prepareColumns($matches[1]);
} else {
throw new Exception("Invalid fulltext index format for '" . $this->getName()
. "' on '" . $this->model . "'");
@ -74,4 +74,19 @@ class FulltextFilter extends SearchFilter {
return parent::getDbName();
}
/**
* Adds table identifier to the every column.
* Columns must have table identifier to prevent duplicate column name error.
*
* @return string
*/
protected function prepareColumns($columns) {
$cols = preg_split('/"?\s*,\s*"?/', trim($columns, '(") '));
$class = ClassInfo::table_for_object_field($this->model, current($cols));
$cols = array_map(function($col) use ($class) {
return sprintf('"%s"."%s"', $class, $col);
}, $cols);
return implode(',', $cols);
}
}

View File

@ -40,26 +40,36 @@ class FulltextFilterTest extends SapphireTest {
}
public function testGenerateQuery() {
// Test if columns have table identifier
$filter1 = new FulltextFilter('SearchFields', 'SilverStripe');
$filter1->setModel('FulltextFilterTest_DataObject');
$query1 = FulltextFilterTest_DataObject::get()->dataQuery();
$filter1->apply($query1);
$this->assertNotEquals('"ColumnA","ColumnB"', $filter1->getDbName());
$this->assertNotEquals(
array("MATCH (\"ColumnA\",\"ColumnB\") AGAINST ('SilverStripe')"),
$query1->query()->getWhere()
);
// Test SearchFields
$filter1 = new FulltextFilter('SearchFields', 'SilverStripe');
$filter1->setModel('FulltextFilterTest_DataObject');
$query1 = FulltextFilterTest_DataObject::get()->dataQuery();
$filter1->apply($query1);
$this->assertEquals('"ColumnA", "ColumnB"', $filter1->getDbName());
$this->assertEquals('"FulltextFilterTest_DataObject"."ColumnA","FulltextFilterTest_DataObject"."ColumnB"', $filter1->getDbName());
$this->assertEquals(
array("MATCH (\"ColumnA\", \"ColumnB\") AGAINST ('SilverStripe')"),
array("MATCH (\"FulltextFilterTest_DataObject\".\"ColumnA\",\"FulltextFilterTest_DataObject\".\"ColumnB\") AGAINST ('SilverStripe')"),
$query1->query()->getWhere()
);
// Test Other searchfields
$filter2 = new FulltextFilter('OtherSearchFields', 'SilverStripe');
$filter2->setModel('FulltextFilterTest_DataObject');
$query2 = FulltextFilterTest_DataObject::get()->dataQuery();
$filter2->apply($query2);
$this->assertEquals('"ColumnC", "ColumnD"', $filter2->getDbName());
$this->assertEquals('"FulltextFilterTest_DataObject"."ColumnC","FulltextFilterTest_DataObject"."ColumnD"', $filter2->getDbName());
$this->assertEquals(
array("MATCH (\"ColumnC\", \"ColumnD\") AGAINST ('SilverStripe')"),
array("MATCH (\"FulltextFilterTest_DataObject\".\"ColumnC\",\"FulltextFilterTest_DataObject\".\"ColumnD\") AGAINST ('SilverStripe')"),
$query2->query()->getWhere()
);