[evolvis-commits] r11958: [#2617] Text searching enhancement

mirabilos at evolvis.org mirabilos at evolvis.org
Thu Feb 24 18:30:49 CET 2011


Author: mirabilos
Date: 2011-02-24 18:30:49 +0100 (Thu, 24 Feb 2011)
New Revision: 11958

Added:
   trunk/gforge_base/evolvisforge-5.1/gforge/db/FTI-20061025.sql
Modified:
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ArtifactSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/DocsSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ExportProjectSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ForumSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/FrsSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/NewsSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/PeopleSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ProjectSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SkillSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/TasksSearchQuery.class
   trunk/gforge_base/evolvisforge-5.1/gforge/common/search/TrackersSearchQuery.class
Log:
[#2617] Text searching enhancement

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ArtifactSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ArtifactSearchQuery.class	2011-02-24 17:30:47 UTC (rev 11957)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ArtifactSearchQuery.class	2011-02-24 17:30:49 UTC (rev 11958)
@@ -39,6 +39,7 @@
 	 * @param int $artifactId artifact id
 	 */
 	function ArtifactSearchQuery($words, $offset, $isExact, $groupId, $artifactId) {
+		//TODO: Why is groupId an arg and var since it isn't used anywhere?
 		$this->groupId = $groupId;
 		$this->artifactId = $artifactId;
 		
@@ -55,20 +56,46 @@
 		if ($sys_use_fti) {
 			$words=$this->getFormattedWords();
 			$artifactId = $this->artifactId;
-			$sql = "SELECT DISTINCT ON (artifact.artifact_id) artifact.artifact_id,
-				artifact.group_artifact_id, artifact.summary AS summary,
-				artifact.open_date, users.realname, artifact_group_list.name
-				FROM artifact LEFT JOIN artifact_message USING (artifact_id), users,
-				artifact_group_list
-				WHERE users.user_id = artifact.submitted_by
-				AND artifact_group_list.group_artifact_id = artifact.group_artifact_id
-				AND artifact_group_list.group_artifact_id='$artifactId'
-				AND artifact.artifact_id IN (
-				SELECT artifact_id FROM artifact_idx,
-				to_tsquery('$words') AS q WHERE vectors @@ q ORDER BY rank(vectors, q) DESC)
-				OR artifact.artifact_id IN (
-				SELECT artifact_id FROM artifact_message_idx,
-				to_tsquery('$words') AS q WHERE vectors @@ q ORDER BY rank(vectors, q) DESC)";
+		    if(count($words)) {
+				$tsquery0 = "headline(summary, '".$this->getFormattedWords()."') as summary";
+				$tsquery = ", artifact_idx ai, artifact_message_idx ami, to_tsquery('".$words."') q";
+				$tsmatch = "(ai.vectors @@ q OR ami.vectors @@ q)"; 
+				$rankCol = "sum((rank(ai.vectors, q)+rank(ami.vectors, q))) as rank";
+				$tsjoin = 'AND ai.artifact_id = a.artifact_id '
+						. 'AND ami.id = am.id ';
+				$phraseOp = $this->getOperator();
+			} else {
+				$tsquery0 = "summary";
+				$tsquery = "";
+				$tsmatch = "";
+				$tsjoin = "";
+				$rankCol = "0 as rank";
+				$phraseOp = "";
+			}
+			$phraseCond = '';
+			if(count($this->phrases)) {
+				$detailsCond = $this->getMatchCond('a.details', $this->phrases);
+				$summaryCond = $this->getMatchCond('a.summary', $this->phrases);
+				$msgCond = $this->getMatchCond('am.body', $this->phrases);
+				$phraseCond = "$phraseOp (($detailsCond) OR ($summaryCond))";
+			}
+			$sql = "
+				select a.group_artifact_id,a.artifact_id, $tsquery0,
+				a.open_date,users.realname, rank
+				FROM (SELECT a.artifact_id,
+				$rankCol
+				FROM artifact a LEFT OUTER JOIN artifact_message am USING (artifact_id)
+				$tsquery
+				WHERE 
+				a.group_artifact_id='$artifactId'
+				$tsjoin
+				AND ($tsmatch $phraseCond)
+				GROUP BY a.artifact_id) x,
+				artifact a, users
+				WHERE
+				a.artifact_id = x.artifact_id
+				AND users.user_id=a.submitted_by
+				ORDER BY group_artifact_id ASC, rank DESC, a.artifact_id ASC";
 		} else {
 			$sql = 'SELECT DISTINCT ON (a.group_artifact_id,a.artifact_id) a.group_artifact_id,a.artifact_id,a.summary,a.open_date,users.realname '
 				. 'FROM artifact a LEFT OUTER JOIN artifact_message am USING (artifact_id), users ' 

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/DocsSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/DocsSearchQuery.class	2011-02-24 17:30:47 UTC (rev 11957)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/DocsSearchQuery.class	2011-02-24 17:30:49 UTC (rev 11958)
@@ -88,16 +88,40 @@
 		}
 		$words = $this->getFormattedWords();
 		$group_id=$this->groupId;
+
+		if(count($this->words)) {
+			$tsquery0 = "headline(doc_data.title, q) AS title, headline(doc_data.description, q) AS description";
+			$tsquery = ", doc_data_idx, to_tsquery('".$words()."') q";
+			$tsmatch = "vectors @@ q";
+			$rankCol = "";
+			$tsjoin = 'AND doc_data.docid = doc_data_idx.docid  ';
+			$orderBy = "ORDER BY rank(vectors, q) DESC, groupname ASC";
+			$phraseOp = $this->getOperator();
+		} else {
+			$tsquery0 = "title, description";
+			$tsquery = "";
+			$tsmatch = "";
+			$tsjoin = "";
+			$rankCol = "";
+			$orderBy = "ORDER BY groupname";
+			$phraseOp = "";
+		}
+
+		$phraseCond = '';
+		if(count($this->phrases)) {
+			$titleCond = $this->getMatchCond('title', $this->phrases);
+			$descCond = $this->getMatchCond('description', $this->phrases);
+			$phraseCond = $phraseOp.' (('.$titleCond.') OR ('.$descCond.'))';
+		}
 		
-		$sql="SELECT doc_data.docid, headline(doc_data.title, q) AS title,
-		headline(doc_data.description, q) AS description, doc_groups.groupname
-		FROM doc_data, doc_groups, to_tsquery('$words') AS q, doc_data_idx
-		WHERE doc_data.doc_group = doc_groups.doc_group
-		AND  doc_data.docid = doc_data_idx.docid AND vectors @@ q
-		AND doc_data.group_id = '$group_id'
-		$sections
-		AND doc_data.stateid IN ($nonPublic)
-		ORDER BY rank(vectors, q) DESC";		
+		$sql="SELECT doc_data.docid, $tsquery0, doc_groups.groupname
+			FROM doc_data, doc_groups $tsquery
+			WHERE doc_data.doc_group = doc_groups.doc_group
+			$tsjoin AND ($tsmatch $phraseCond )
+			AND doc_data.group_id = '$group_id'
+			$sections
+			AND doc_data.stateid IN ($nonPublic)
+			$orderBy";
 		return $sql;
 	}
 

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ExportProjectSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ExportProjectSearchQuery.class	2011-02-24 17:30:47 UTC (rev 11957)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ExportProjectSearchQuery.class	2011-02-24 17:30:49 UTC (rev 11958)
@@ -35,13 +35,39 @@
 		global $sys_use_fti;
 		if ($sys_use_fti) {
 			$words = $this->getFormattedWords();
-			$sql = "SELECT headline(group_name, q) as group_name,
-					headline(unix_group_name, q) as unix_group_name,
-					type_id,groups.group_id,headline(short_description, q) as short_description,
-					license,register_time FROM groups, to_tsquery('$words') AS q, groups_idx 
-					WHERE groups.group_id = groups_idx.group_id AND vectors @@ q AND 
-					status IN ('A', 'H') AND is_public='1' AND short_description <> '' 
-					ORDER BY rank(vectors, q) DESC";
+			if(count($this->words)) {
+				$tsquery0 = "headline(unix_group_name, q) as unix_group_name, headline(short_description, q) as short_description";
+				$tsquery = ", groups_idx, to_tsquery('".$words."') q";
+				$tsmatch = "vectors @@ q";
+				$rankCol = "";
+				$tsjoin = 'AND groups.group_id = groups_idx.group_id ';
+				$orderBy = "ORDER BY rank(vectors, q) DESC, group_name ASC";
+				$phraseOp = $this->getOperator();
+			} else {
+				$tsquery0 = "unix_group_name, short_description";
+				$tsquery = "";
+				$tsmatch = "";
+				$tsjoin = "";
+				$rankCol = "";
+				$orderBy = "ORDER BY group_name";
+				$phraseOp = "";
+			}
+			$phraseCond = '';
+			if(count($this->phrases)) {
+				$groupNameCond = $this->getMatchCond('group_name', $this->phrases);
+				$groupDescriptionCond = $this->getMatchCond('short_description', $this->phrases);
+				$groupUnixNameCond = $this->getMatchCond('unix_group_name', $this->phrases);
+				$phraseCond = $phraseOp.' (('.$groupNameCond.') OR ('.$groupDescriptionCond.') OR ('.$groupUnixNameCond.'))';
+			}
+			$sql = "SELECT $tsquery0,
+				type_id,
+				groups.group_id,
+				license,
+				register_time
+				FROM groups $tsquery
+				WHERE status IN ('A', 'H') AND is_public='1' AND short_description <> ''
+				$tsjoin AND ($tsmatch $phraseCond)
+				$orderBy";
 		} else {
 			$groupNameCond = $this->getIlikeCondition('group_name', $this->words);
 			$groupDescriptionCond = $this->getIlikeCondition('short_description', $this->words);

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ForumSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ForumSearchQuery.class	2011-02-24 17:30:47 UTC (rev 11957)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ForumSearchQuery.class	2011-02-24 17:30:49 UTC (rev 11958)
@@ -54,11 +54,36 @@
 		global $sys_use_fti;
 		if ($sys_use_fti) {
 			$words = $this->getFormattedWords();
-			$sql = "SELECT forum.msg_id, headline(forum.subject, q) AS subject, forum.post_date, users.realname "
-					." FROM forum, users, to_tsquery('$words') AS q, forum_idx as fi "
-					." WHERE fi.msg_id = forum.msg_id AND vectors @@ q "
-					." AND users.user_id=forum.posted_by AND forum.group_forum_id=$this->forumId "
-					." ORDER BY rank(vectors, q) DESC";
+			if(count($this->words)) {
+				$tsquery0 = "headline(forum.subject, q) AS subject";
+				$tsquery = ", to_tsquery('".$words."') AS q, forum_idx as fi";
+				$tsmatch = "vectors @@ q";
+				$rankCol = "";
+				$tsjoin = 'AND fi.msg_id = forum.msg_id';
+				$orderBy = "ORDER BY rank(vectors, q) DESC";
+				$phraseOp = $this->getOperator();
+			} else {
+				$tsquery0 = "subject";
+				$tsquery = "";
+				$tsmatch = "";
+				$tsjoin = "";
+				$rankCol = "";
+				$orderBy = "ORDER BY post_date DESC";
+				$phraseOp = "";
+			}
+			$phraseCond = '';
+			if(count($this->phrases)) {
+				$bodyCond = $this->getMatchCond('forum.body', $this->phrases);
+				$subjectCond = $this->getMatchCond('forum.subject', $this->phrases);
+				$phraseCond = $phraseOp.' (('.$bodyCond.') OR ('.$subjectCond.'))';
+			}
+			$sql = "SELECT forum.msg_id, $tsquery0, forum.post_date, users.realname
+				FROM forum, users $tsquery
+				WHERE
+				forum.group_forum_id =".$this->forumId."
+				AND forum.posted_by = users.user_id
+				$tsjoin AND ($tsmatch $phraseCond)
+				$orderBy";
 		} else {
 			$sql = 'SELECT forum.msg_id, forum.subject, forum.post_date, users.realname '
 				. 'FROM forum,users '

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/FrsSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/FrsSearchQuery.class	2011-02-24 17:30:47 UTC (rev 11957)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/FrsSearchQuery.class	2011-02-24 17:30:49 UTC (rev 11958)
@@ -53,15 +53,46 @@
 	function getQuery() {
 		global $sys_use_fti;
 		if ($sys_use_fti) {
-			$nonPublic = 'false';
-			$sections = '';
-			if ($this->showNonPublic) {
-				$nonPublic = 'true';
+			if(count($this->words)) {
+				$tsquery0 = "headline(frs_package.name, q) AS package_name, headline(frs_release.name, q) as release_name";
+				$tsquery = ", to_tsquery('".$this->getFormattedWords()."') AS q, frs_release_idx r, frs_file_idx f";
+				$tsmatch = "(f.vectors @@ q OR r.vectors @@ q)";
+				$rankCol = "";
+				$tsjoin = 'AND r.release_id = frs_release.release_id AND f.file_id = frs_file.file_id';
+				$orderBy = "ORDER BY frs_package.name, frs_release.name";
+				$phraseOp = $this->getOperator();
+			} else {
+				$tsquery0 = "frs_package.name as package_name, frs_release.name as release_name";
+				$tsquery = "";
+				$tsmatch = "";
+				$tsjoin = "";
+				$rankCol = "";
+				$orderBy = "ORDER BY frs_package.name, frs_release.name";
+				$phraseOp = "";
 			}
+			$phraseCond = '';
+			if(count($this->phrases)) {
+				$phraseCond .= $phraseOp.'(('.$this->getMatchCond('frs_release.changes', $this->phrases).')'
+					. ' OR ('.$this->getMatchCond('frs_release.notes', $this->phrases).')'
+					. ' OR ('.$this->getMatchCond('frs_release.name', $this->phrases).')'
+					. ' OR ('.$this->getMatchCond('frs_file.filename', $this->phrases).'))';
+			}
+			$sql = 'SELECT '.$tsquery0.', frs_release.release_date, frs_release.release_id, users.realname'
+				. ' FROM frs_file, frs_release, users, frs_package'.$tsquery
+				. ' WHERE frs_release.released_by = users.user_id'
+				. $tsjoin
+				. ' AND frs_package.package_id = frs_release.package_id'
+				. ' AND frs_file.release_id=frs_release.release_id'
+				. ' AND frs_package.group_id='.$this->groupId;
 			if ($this->sections != SEARCH__ALL_SECTIONS) {
 				$sections = $this->sections;
+				$sql .= ' AND frs_package.package_id IN ('.$this->sections.') ';
 			}
-			$sql = "SELECT * FROM frs_search('".$this->getFormattedWords()."', ".$this->groupId.", '$sections', $nonPublic)";
+			if(!$this->showNonPublic) {
+				$sql .= ' AND is_public=1';
+			}
+
+			$sql .= ' AND (  '.$tsmatch.' '.$phraseCond.') '.$orderBy;
 		} else {
 			$sql = 'SELECT frs_package.name as package_name, frs_release.name as release_name, frs_release.release_date, frs_release.release_id, users.realname'
 				. ' FROM frs_file, frs_release, users, frs_package'

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/NewsSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/NewsSearchQuery.class	2011-02-24 17:30:47 UTC (rev 11957)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/NewsSearchQuery.class	2011-02-24 17:30:49 UTC (rev 11958)
@@ -42,18 +42,41 @@
 	function getQuery() {
 		global $sys_use_fti;
 		if ($sys_use_fti) {
-			$words = $this->getFormattedWords();
 			$group_id=$this->groupId;
-			$sql = "SELECT headline(news_bytes.summary, q) as summary,
+			if(count($this->words)) {
+				$tsquery0 = "headline(news_bytes.summary, q) as summary";
+				$words = $this->getFormattedWords();
+				$tsquery = ", to_tsquery('$words') AS q, news_bytes_idx";
+				$tsmatch = "vectors @@ q";
+				$rankCol = "";
+				$tsjoin = 'AND news_bytes_idx.id = news_bytes.id';
+				$orderBy = "ORDER BY rank(vectors, q) DESC, post_date DESC";
+				$phraseOp = $this->getOperator();
+			} else {
+				$tsquery0 = "summary";
+				$tsquery = "";
+				$tsmatch = "";
+				$tsjoin = "";
+				$rankCol = "";
+				$orderBy = "ORDER BY post_date DESC";
+				$phraseOp = "";
+			}
+			$phraseCond = '';
+			if(count($this->phrases)) {
+				$phraseCond .= $phraseOp.'('
+					. ' ('.$this->getMatchCond('summary', $this->phrases).')'
+					. ' OR ('.$this->getMatchCond('details', $this->phrases).'))';
+			}
+			$sql = "SELECT $tsquery0,
 				news_bytes.post_date,
 				news_bytes.forum_id,
 				users.realname
-				FROM news_bytes, users, to_tsquery('$words') AS q, news_bytes_idx
+				FROM news_bytes, users $tsquery
 				WHERE (news_bytes.group_id='$group_id' AND news_bytes.is_approved <> '4'
-				AND news_bytes_idx.id = news_bytes.id
+				$tsjoin
 				AND news_bytes.submitted_by=users.user_id) AND
-				(vectors @@ q)
-				ORDER BY rank(vectors, q) DESC";		
+				($tsmatch $phraseCond)
+				$orderBy";
 		} else {
 			$sql = 'SELECT news_bytes.summary, news_bytes.post_date, news_bytes.forum_id, users.realname'
 				. ' FROM news_bytes, users'

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/PeopleSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/PeopleSearchQuery.class	2011-02-24 17:30:47 UTC (rev 11957)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/PeopleSearchQuery.class	2011-02-24 17:30:49 UTC (rev 11958)
@@ -34,7 +34,36 @@
 	function getQuery() {
 		global $sys_use_fti;
 		if ($sys_use_fti) {
-			$sql = "SELECT * FROM users_search('".$this->getFormattedWords()."')";
+			if(count($this->words)) {
+				$tsquery0 = ", user_name, headline(realname, q) as realname ";
+				$words = $this->getFormattedWords();
+				$tsquery = ", to_tsquery('$words') AS q, users_idx ";
+				$tsmatch = "vectors @@ q";
+				$rankCol = "";
+				$tsjoin = 'AND users_idx.user_id = users.user_id';
+				$orderBy = "ORDER BY rank(vectors, q) DESC, user_name";
+				$phraseOp = $this->getOperator();
+			} else {
+				$tsquery0 = ", user_name, realname ";
+				$tsquery = "";
+				$tsmatch = "";
+				$tsjoin = "";
+				$rankCol = "";
+				$orderBy = "ORDER BY user_name";
+				$phraseOp = "";
+			}
+			$phraseCond = '';
+			if(count($this->phrases)) {
+				$phraseCond .= $phraseOp.'('
+					. ' ('.$this->getMatchCond('user_name', $this->phrases).')'
+					. ' OR ('.$this->getMatchCond('realname', $this->phrases).'))';
+			}
+			$sql = 'SELECT users.user_id '.$tsquery0
+				. 'FROM users '.$tsquery
+				. 'WHERE (status=\'A\') '
+				. $tsjoin
+				. " AND ($tsmatch $phraseCond) "
+				. $orderBy;
 		} else {
 			$sql = 'SELECT user_name,user_id,realname ' 
 				. 'FROM users ' 

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ProjectSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ProjectSearchQuery.class	2011-02-24 17:30:47 UTC (rev 11957)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/ProjectSearchQuery.class	2011-02-24 17:30:49 UTC (rev 11958)
@@ -34,7 +34,38 @@
 	function getQuery() {
 		global $sys_use_fti;
 		if ($sys_use_fti) {
-			$sql = "SELECT * FROM groups_search('".$this->getFormattedWords()."')";
+			if(count($this->words)) {
+				$tsquery0 = "headline(group_name, q) as group_name, " .
+						"unix_group_name, " .
+						"headline(short_description, q) as short_description";
+				$words = $this->getFormattedWords();
+				$tsquery = ", to_tsquery('$words') AS q, groups_idx as i ";
+				$tsmatch = "vectors @@ q";
+				$rankCol = "";
+				$tsjoin = 'AND g.group_id = i.group_id';
+				$distinctOn = "rank(vectors, q), group_name";
+				$orderBy = "ORDER BY rank(vectors, q) DESC, group_name";
+				$phraseOp = $this->getOperator();
+			} else {
+				$tsquery0 = "group_name, unix_group_name, short_description";
+				$tsquery = "";
+				$tsmatch = "";
+				$tsjoin = "";
+				$rankCol = "";
+				$distinctOn = "group_name";
+				$orderBy = "ORDER BY group_name";
+				$phraseOp = "";
+			}
+			$phraseCond = '';
+			if(count($this->phrases)) {
+				$groupNameCond = $this->getMatchCond('group_name', $this->phrases);
+				$groupDescriptionCond = $this->getMatchCond('short_description', $this->phrases);
+				$groupUnixNameCond = $this->getMatchCond('unix_group_name', $this->phrases);
+				$phraseCond = $phraseOp.' (('.$groupNameCond.') OR ('.$groupDescriptionCond.') OR ('.$groupUnixNameCond.'))';
+			}
+			$sql = "SELECT DISTINCT ON ($distinctOn) type_id, g.group_id, " .$tsquery0.
+					" FROM groups AS g ".$tsquery.
+					" WHERE g.status in ('A', 'H') AND ($tsmatch $phraseCond) $tsjoin $orderBy";
 		} else {
 			$groupNameCond = $this->getIlikeCondition('group_name', $this->words);
 			$groupDescriptionCond = $this->getIlikeCondition('short_description', $this->words);

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SearchQuery.class	2011-02-24 17:30:47 UTC (rev 11957)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SearchQuery.class	2011-02-24 17:30:49 UTC (rev 11958)
@@ -67,6 +67,10 @@
 	 */	
 	var $sections = SEARCH__ALL_SECTIONS;
 
+	var $words;
+
+	var $phrases;
+
 	/**
 	 * Constructor
 	 *
@@ -105,7 +109,38 @@
 				$this->setError('error_search_minlength');
 				return;
 			}
-			$this->words = explode(' ', quotemeta($words));
+			$this->words = array();
+			$this->phrases = array();
+			$phrase = '';
+			$inQuote = false;
+			foreach(explode(' ', quotemeta($words)) as $word) {
+				if($inQuote) {
+					if(substr($word, -3) == "\\\\'") {
+						$word = substr($word, 0, -3);
+						$inQuote = false;
+						$phrase .= ' '.$word;
+						$this->phrases[] = $phrase;
+					} else {
+						$phrase .= ' '.$word;
+					}
+				} else {
+					if(substr($word, 0, 3) == "\\\\'") {
+						$word = substr($word, 3);
+						$inQuote = true;
+						if(substr($word, -3) == "\\\\'") {
+							// This is a special case where the phrase is just one word
+							$word = substr($word, 0, -3);
+							$inQuote = false;
+							$this->phrases[] = $word;
+						} else {
+							$phrase = $word;
+						}
+					} else {
+						$this->words[] = $word;
+					}
+				}
+
+			}
 		}
 	}
 	
@@ -151,8 +186,19 @@
 	 * @return string the condition
 	 */
 	function getIlikeCondition($fieldName) {
-		return $fieldName." ILIKE '%" . implode("%' ".$this->operator." ".$fieldName." ILIKE '%", $this->words) ."%'";
+		$wordArgs = array_merge($this->words, str_replace(' ', "\\\s+",$this->phrases));
+		return $fieldName." ILIKE '%" . implode("%' ".$this->operator." ".$fieldName." ILIKE '%", $wordArgs) ."%'";
 	}
+
+	function getMatchCond($fieldName, $arr) {
+		if(!count($arr)) {
+			$result = 'TRUE';
+		} else {
+			$regexs = str_replace(' ', "\\\s+",$arr);
+			$result = $fieldName." ~* '" . implode("' ".$this->operator." ".$fieldName." ~* '", $regexs) ."'";
+		}
+		return $result;
+	}
 	
 	/**
 	 * getOperator - get the operator we have to use in ILIKE condition
@@ -257,7 +303,6 @@
 		} else {
 			$words = implode('|', $this->words);
 		}
-		return $words;
 	}
 }
 

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SkillSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SkillSearchQuery.class	2011-02-24 17:30:47 UTC (rev 11957)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/SkillSearchQuery.class	2011-02-24 17:30:49 UTC (rev 11958)
@@ -33,13 +33,40 @@
 	 */
 	function getQuery() {
 		global $sys_use_fti;
-		$words = $this->getFormattedWords();
-		if ($sys_use_fti) {		
-			$sql = "SELECT skills_data.skills_data_id, skills_data.type, headline(skills_data.title, q) as title,
-					skills_data.start,skills_data.finish,headline(skills_data.keywords, q) as keywords
-					FROM skills_data, to_tsquery('$words') AS q, users, skills_data_types, skills_data_idx 
-					WHERE skills_data.user_id=users.user_id AND skills_data.skills_data_id = skills_data_idx.skills_data_id 
-					AND skills_data.type=skills_data_types.type_id AND (vectors @@ q) ORDER BY rank(vectors, q) DESC";
+		if ($sys_use_fti) {
+			if(count($this->words)) {
+				$words = $this->getFormattedWords();
+				$tsquery0 = "headline(skills_data.title, q) as title, headline(skills_data.keywords, q) as keywords ";
+				$tsquery = ", to_tsquery('$words') AS q, skills_data_idx";
+				$tsmatch = "vectors @@ q";
+				$rankCol = "";
+				$tsjoin = 'AND skills_data.skills_data_id = skills_data_idx.skills_data_id ';
+				$orderBy = "ORDER BY rank(vectors, q) DESC, finish DESC";
+				$phraseOp = $this->getOperator();
+			} else {
+				$tsquery0 = "title, keywords ";
+				$tsquery = "";
+				$tsmatch = "";
+				$tsjoin = "";
+				$rankCol = "";
+				$orderBy = "ORDER BY finish DESC";
+				$phraseOp = "";
+			}
+			$phraseCond = '';
+			if(count($this->phrases)) {
+				$phraseCond .= $phraseOp.'('
+					. ' ('.$this->getMatchCond('skills_data.title', $this->phrases).')'
+					. ' OR ('.$this->getMatchCond('skills_data.keywords', $this->phrases).'))';
+			}
+			$sql = 'SELECT skills_data.skills_data_id, skills_data.type, '
+				. 'skills_data.start, skills_data.finish, '.$tsquery0
+				. 'FROM skills_data, users, skills_data_types '
+				. $tsquery
+				. ' WHERE (vectors @@ q '.$phraseCond.') '
+				. $tsjoin
+				. 'AND (skills_data.user_id=users.user_id) '
+				. 'AND (skills_data.type=skills_data_types.type_id) '
+				. $orderBy;
 		} else {
 			$sql = 'SELECT * '
 				. 'FROM skills_data, users, skills_data_types '

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/TasksSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/TasksSearchQuery.class	2011-02-24 17:30:47 UTC (rev 11957)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/TasksSearchQuery.class	2011-02-24 17:30:49 UTC (rev 11958)
@@ -54,12 +54,37 @@
 	function getQuery() {
 		global $sys_use_fti;
 		if ($sys_use_fti) {
-			$sql = 'SELECT project_task.project_task_id,headline(project_task.summary, q) AS summary,project_task.percent_complete,'
+			if(count($this->words)) {
+				$tsquery0 = "headline(project_task.summary, q) AS summary,";
+				$words = $this->getFormattedWords();
+				$tsquery = ", to_tsquery('$words') AS q, project_task_idx";
+				$tsmatch = "vectors @@ q";
+				$rankCol = "";
+				$tsjoin = ' AND project_task.project_task_id = project_task_idx.project_task_id';
+				$orderBy = "ORDER BY project_group_list.project_name, rank(vectors, q) DESC, project_task.project_task_id";
+				$phraseOp = $this->getOperator();
+			} else {
+				$tsquery0 = "summary, ";
+				$tsquery = "";
+				$tsmatch = "";
+				$tsjoin = "";
+				$rankCol = "";
+				$orderBy = "ORDER BY project_group_list.project_name, project_task.project_task_id";
+				$phraseOp = "";
+			}
+			$phraseCond = '';
+			if(count($this->phrases)) {
+				$phraseCond .= $phraseOp.'('
+					. ' ('.$this->getMatchCond('summary', $this->phrases).')'
+					. ' OR ('.$this->getMatchCond('details', $this->phrases).'))';
+			}
+			$sql = 'SELECT project_task.project_task_id,project_task.percent_complete,'
+			    .  $tsquery0
 				. ' project_task.start_date,project_task.end_date,users.firstname||\' \'||users.lastname AS realname, project_group_list.project_name, project_group_list.group_project_id ' 
-				. ' FROM project_task, users, project_group_list, project_task_idx, ' 
-				. ' to_tsquery(\''.$this->getFormattedWords().'\') q'
+				. ' FROM project_task, users, project_group_list '
+				. $tsquery
 				. ' WHERE project_task.created_by = users.user_id'
-				. ' AND project_task.project_task_id = project_task_idx.project_task_id'
+				. $tsjoin
 				. ' AND project_task.group_project_id = project_group_list.group_project_id '
 				. ' AND project_group_list.group_id  ='.$this->groupId.' ';
 			if ($this->sections != SEARCH__ALL_SECTIONS) {
@@ -68,8 +93,7 @@
 			if (!$this->showNonPublic) {
 				$sql .= 'AND project_group_list.is_public = 1 ';
 			}
-			$sql .= 'AND (vectors @@q)' 
-				. ' ORDER BY rank(vectors, q) DESC';
+			$sql .= "AND ($tsmatch $phraseCond) $orderBy";
 		} else {
 			$sql = 'SELECT project_task.project_task_id,project_task.summary,project_task.percent_complete,'
 				. ' project_task.start_date,project_task.end_date,users.firstname||\' \'||users.lastname AS realname, project_group_list.project_name, project_group_list.group_project_id ' 

Modified: trunk/gforge_base/evolvisforge-5.1/gforge/common/search/TrackersSearchQuery.class
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/common/search/TrackersSearchQuery.class	2011-02-24 17:30:47 UTC (rev 11957)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/common/search/TrackersSearchQuery.class	2011-02-24 17:30:49 UTC (rev 11958)
@@ -54,38 +54,46 @@
 	function getQuery() {
 		global $sys_use_fti;
 		if ($sys_use_fti) {
-			$nonPublic = 'false';
-			$sections = '';
-			if ($this->showNonPublic) {
-				$nonPublic = '';
-				$nonPublicMsg = '';
+			if(count($this->words)) {
+				$tsquery = ", to_tsquery('".$this->getFormattedWords()."') q, artifact_idx, artifact_message_idx ";
+				$tsmatch = "(artifact_idx.vectors @@ q OR artifact_message_idx.vectors @@ q)";
+				$rankCol = ", (rank(artifact_idx.vectors, q)+rank(artifact_message_idx.vectors, q)) AS rank ";
+				$tsjoin = 'AND artifact_idx.artifact_id = artifact.artifact_id '
+						. 'AND artifact_message_idx.id = artifact_message.id '
+						. 'AND artifact_message_idx.artifact_id = artifact_message_idx.artifact_id ';
+				$orderBy = "ORDER BY RANK DESC";
+				$phraseOp = $this->getOperator();
 			} else {
-				$nonPublic = 'AND artifact_group_list.is_public = 1';
-				$nonPublicMsg = 'AND agl.is_public = 1';
+				$tsquery = "";
+				$tsmatch = "";
+				$tsjoin = "";
+				$rankCol = "";
+				$orderBy = "";
+				$phraseOp = "";
 			}
+			$phraseCond = '';
+			if(count($this->phrases)) {
+				$phraseCond .= $phraseOp.'('
+					. ' ('.$this->getMatchCond('artifact.details', $this->phrases).')'
+					. ' OR ('.$this->getMatchCond('artifact.summary', $this->phrases).')'
+					. ' OR ('.$this->getMatchCond('artifact_message.body', $this->phrases).'))';
+			}
+			$sql = 'SELECT artifact.artifact_id, artifact.group_artifact_id, artifact.summary, artifact.open_date, users.realname, artifact_group_list.name '
+				. $rankCol
+				. 'FROM artifact LEFT OUTER JOIN artifact_message USING (artifact_id), users, artifact_group_list '
+				. $tsquery
+				. ' WHERE users.user_id = artifact.submitted_by '
+				. $tsjoin
+				. 'AND artifact_group_list.group_artifact_id = artifact.group_artifact_id '
+				. 'AND artifact_group_list.group_id = '.$this->groupId.' ';
 			if ($this->sections != SEARCH__ALL_SECTIONS) {
-				$sections = "AND artifact_group_list.group_artifact_id IN (".$this->sections.")";
-			} else {
-				$sections = '';
+				$sql .= 'AND artifact_group_list.group_artifact_id in ('.$this->sections.') ';
 			}
-			$words = $this->getFormattedWords();
-			$group_id=$this->groupId;
-			$sql = "SELECT DISTINCT ON (artifact.artifact_id) artifact.artifact_id,
-			artifact.group_artifact_id, artifact.summary AS summary,
-			artifact.open_date, users.realname, artifact_group_list.name
-			FROM artifact LEFT JOIN artifact_message USING (artifact_id), users,
-			artifact_group_list 
-			WHERE users.user_id = artifact.submitted_by
-			$nonPublic
-			AND artifact_group_list.group_artifact_id = artifact.group_artifact_id
-			AND artifact_group_list.group_id = '$group_id'
-			$sections
-			AND artifact.artifact_id IN (
-				SELECT artifact_id FROM artifact_idx, 
-				to_tsquery('$words') AS q WHERE vectors @@ q ORDER BY rank(vectors, q) DESC) 
-			OR artifact.artifact_id IN (
-				SELECT artifact_id FROM artifact_message_idx, 
-				to_tsquery('$words') AS q WHERE vectors @@ q ORDER BY rank(vectors, q) DESC)";
+			if (!$this->showNonPublic) {
+				$sql .= 'AND artifact_group_list.is_public = 1 ';
+			}
+			$sql .= "AND ($tsmatch $phraseCond)";
+			$sql = "SELECT DISTINCT x.* FROM ($sql) x $orderBy";
 		} else {
 			$sql = 'SELECT DISTINCT artifact.artifact_id, artifact.group_artifact_id, artifact.summary, artifact.open_date, users.realname, artifact_group_list.name '
 				. 'FROM artifact LEFT OUTER JOIN artifact_message USING (artifact_id), users, artifact_group_list '

Added: trunk/gforge_base/evolvisforge-5.1/gforge/db/FTI-20061025.sql
===================================================================
--- trunk/gforge_base/evolvisforge-5.1/gforge/db/FTI-20061025.sql	                        (rev 0)
+++ trunk/gforge_base/evolvisforge-5.1/gforge/db/FTI-20061025.sql	2011-02-24 17:30:49 UTC (rev 11958)
@@ -0,0 +1,7 @@
+DROP FUNCTION export_groups_search(text) CASCADE;
+DROP FUNCTION forum_search(text, integer) CASCADE;
+DROP FUNCTION frs_search(text, integer, text, boolean) CASCADE;
+DROP FUNCTION users_search(text) CASCADE;
+DROP FUNCTION groups_search(text) CASCADE;
+DROP FUNCTION skills_data_search(text) CASCADE;
+DROP FUNCTION project_task_search(text, integer, text, boolean) CASCADE;



More information about the evolvis-commits mailing list