src/db/20110728-fix-mta-lists-view.sql -text
src/db/20110824-plugin-projects-hierarchy-rename.sql -text
src/db/20111002-docman-doc_groups-createdate-updatedate.sql -text
+src/db/20111007-add-fti-for-task-messages.sql -text
+src/db/20111007-fti-aggregate-functions.sql -text
+src/db/20111009-string-aggregate-function.sql -text
src/db/FTI-20061025.sql -text
src/db/SQL_2.6/replicate.sh svneol=native#text/x-sh
src/db/gforge-data-mysql.sql -text
define('SYS_DB_TROVE', $gfconn2);
define('SYS_DB_SEARCH', $gfconn2);
- db_query_params ('SELECT set_config($1, $2, false)',
- array('default_text_search_config',
- 'simple'));
-
+ $res = db_query_params ('SELECT set_config($1, $2, false)',
+ array('default_text_search_config',
+ 'simple'));
+ if (!$res) {
+ // Cope with PostgreSQL < 8.3
+ db_query_params ('SELECT set_curcfg($1)',
+ array('simple'));
+ }
+
// Register top-level "finally" handler to abort current
// transaction in case of error
register_shutdown_function("system_cleanup");
if ($sysdebug_dbquery) {
ffDebug('trace', "tracing call of db_query_params():\n",
debug_string_backtrace());
+ error_log('SQL: '.db_query_to_string($qstring,$params).'; ');
}
$res = @pg_query_params($dbconn,$qstring,$params);
return db_construct_qpa ($old_qpa, $new_qpa[0], $new_qpa[1]) ;
}
-function db_qpa_to_string ($qpa) {
- $sql = $qpa[0];
- $params = $qpa[1];
+function db_query_to_string ($sql, $params = array()) {
foreach ($params as $index => $value) {
$sql = preg_replace('/\\$'.($index+1).'(?!\d)/', "'".$value."'", $sql);
}
return $sql;
}
+function db_qpa_to_string ($qpa) {
+ return db_query_to_string($qpa[0], $qpa[1]);
+}
+
// Local Variables:
// mode: php
// c-file-style: "bsd"
$sql[]="DROP VIEW rep_site_act_oa_vw";
$sql[]="CREATE VIEW rep_site_act_oa_vw AS
+ SELECT
sum(tracker_opened) AS tracker_opened,
sum(tracker_closed) AS tracker_closed,
sum(forum) AS forum,
* @return array query+params array
*/
function getQuery() {
+ $qpa = db_construct_qpa () ;
+
+ $words = $this->getFTIwords();
+
+ $qpa = db_construct_qpa ($qpa,
+ 'SELECT x.* FROM (SELECT artifact.artifact_id, artifact.group_artifact_id, artifact.summary, artifact.open_date, users.realname, artifact.summary||$1||artifact.details||$1||coalesce(ff_string_agg(artifact_message.body), $1) as full_string_agg',
+ array (''));
+ if (forge_get_config('use_fti')) {
+ $qpa = db_construct_qpa ($qpa,
+ ', (artifact_idx.vectors || coalesce(ff_tsvector_agg(artifact_message_idx.vectors), $1::tsvector)) AS full_vector_agg',
+ array(''));
+ }
+ $qpa = db_construct_qpa ($qpa,
+ ' FROM artifact LEFT OUTER JOIN artifact_message USING (artifact_id), users',
+ array ()) ;
+ if (forge_get_config('use_fti')) {
+ $qpa = db_construct_qpa ($qpa,
+ ', artifact_idx, artifact_message_idx',
+ array ()) ;
+ }
+ $qpa = db_construct_qpa ($qpa,
+ ' WHERE users.user_id = artifact.submitted_by AND artifact.group_artifact_id = $1 ',
+ array ($this->artifactId)) ;
+ if (forge_get_config('use_fti')) {
+ $qpa = db_construct_qpa ($qpa,
+ 'AND artifact.artifact_id = artifact_idx.artifact_id AND artifact_message.id = artifact_message_idx.id ',
+ array ()) ;
+ }
+ $qpa = db_construct_qpa ($qpa,
+ 'GROUP BY artifact.artifact_id, artifact.group_artifact_id, artifact.summary, artifact.open_date, users.realname, artifact.details') ;
+
+ if (forge_get_config('use_fti')) {
+ $qpa = db_construct_qpa ($qpa,
+ ', artifact_idx.vectors',
+ array ()) ;
+ }
+ $qpa = db_construct_qpa ($qpa,
+ ') AS x WHERE ') ;
+
+ if (forge_get_config('use_fti')) {
+ $qpa = db_construct_qpa ($qpa,
+ 'full_vector_agg @@ $1 ',
+ array($words));
+ if (count($this->phrases)) {
+ $qpa = db_construct_qpa ($qpa,
+ 'AND (') ;
+ $qpa = $this->addMatchCondition ($qpa, 'x.full_string_agg') ;
+ $qpa = db_construct_qpa ($qpa,
+ ') ') ;
+ }
+ $qpa = db_construct_qpa ($qpa,
+ 'ORDER BY ts_rank(full_vector_agg, $1) DESC',
+ array($words)) ;
+
+ } else {
+ $qpa = $this->addIlikeCondition ($qpa, 'x.full_string_agg') ;
+ $qpa = db_construct_qpa ($qpa,
+ 'ORDER BY x.artifact_id') ;
+ }
+ return $qpa ;
+
+
+
+
+
+
$qpa = db_construct_qpa () ;
if (forge_get_config('use_fti')) {
'SELECT a.group_artifact_id, a.artifact_id, ts_headline(summary, $1) AS summary, ',
array ($words)) ;
$qpa = db_construct_qpa ($qpa,
- 'a.open_date, users.realname, rank FROM (SELECT a.artifact_id, SUM (ts_rank(ai.vectors, q) + ts_rank(ami.vectors, q)) AS rank FROM artifact a LEFT OUTER JOIN artifact_message am USING (artifact_id)') ;
+ 'a.open_date, users.realname, rank FROM (SELECT a.artifact_id, SUM (ts_rank(ai.vectors, q) + ts_rank(ami.vectors, q)) AS rank, artifact.summary||$1||artifact.details||$1||coalesce(ff_string_agg(artifact_message.body), $1) as full_string_agg FROM artifact a LEFT OUTER JOIN artifact_message am USING (artifact_id)',
+ array('')) ;
$qpa = db_construct_qpa ($qpa,
', artifact_idx ai, artifact_message_idx ami, to_tsquery($1) q',
if (forge_get_config('use_fti')) {
return $this->getFTIQuery();
} else {
- $qpa = db_construct_qpa();
- $qpa = db_construct_qpa($qpa,
- 'SELECT doc_data.docid, doc_data.title, doc_data.description, doc_data.filename, doc_groups.groupname FROM doc_data, doc_groups WHERE doc_data.doc_group = doc_groups.doc_group AND doc_data.group_id = $1',
- array ($this->groupId));
+ $qpa = db_construct_qpa () ;
+ $qpa = db_construct_qpa ($qpa,
+ 'SELECT x.* FROM (SELECT doc_data.docid, doc_data.title, doc_data.filename, doc_data.description, doc_groups.groupname, title||$1||description AS full_string_agg FROM doc_data, doc_groups WHERE doc_data.doc_group = doc_groups.doc_group AND doc_data.group_id = $2',
+ array ($this->field_separator,
+ $this->groupId)) ;
if ($this->sections != SEARCH__ALL_SECTIONS) {
$qpa = db_construct_qpa ($qpa,
'AND doc_groups.doc_group = ANY ($1) ',
} else {
$qpa = db_construct_qpa($qpa, ' AND doc_data.stateid = 1');
}
- $qpa = db_construct_qpa($qpa, ' AND ((');
- $qpa = $this->addIlikeCondition($qpa, 'title');
- $qpa = db_construct_qpa($qpa, ') OR (');
- $qpa = $this->addIlikeCondition($qpa, 'description');
- $qpa = db_construct_qpa($qpa, ') OR (');
- $qpa = $this->addIlikeCondition($qpa, 'data_words', $this->words);
- $qpa = db_construct_qpa($qpa, ')) ORDER BY doc_groups.groupname, doc_data.docid');
+ $qpa = db_construct_qpa ($qpa,
+ ') AS x WHERE ') ;
+ $qpa = $this->addIlikeCondition ($qpa, 'full_string_agg') ;
+ $qpa = db_construct_qpa ($qpa,
+ ' ORDER BY x.groupname, x.docid') ;
}
return $qpa;
}
$qpa = db_construct_qpa () ;
$qpa = db_construct_qpa ($qpa,
- 'SELECT doc_data.docid, doc_data.filename, ts_headline(doc_data.title, q) AS title, ts_headline(doc_data.description, q) AS description doc_groups.groupname FROM doc_data, doc_groups, doc_data_idx, to_tsquery($1) q',
- array (implode (' ', $words))) ;
+ 'SELECT x.* FROM (SELECT doc_data.docid, doc_data.filename, ts_headline(doc_data.title, q) AS title, ts_headline(doc_data.description, q) AS description, doc_groups.groupname, title||$1||description AS full_string_agg, doc_data_idx.vectors FROM doc_data, doc_groups, doc_data_idx, to_tsquery($2) AS q',
+ array ($this->field_separator,
+ $words)) ;
$qpa = db_construct_qpa ($qpa,
- ' WHERE doc_data.doc_group = doc_groups.doc_group AND doc_data.docid = doc_data_idx.docid AND (vectors @@ q') ;
- if (count($this->phrases)) {
- $qpa = db_construct_qpa ($qpa,
- $this->getOperator()) ;
- $qpa = db_construct_qpa ($qpa,
- '(') ;
- $qpa = $this->addMatchCondition($qpa, 'title');
- $qpa = db_construct_qpa ($qpa,
- ') OR (') ;
- $qpa = $this->addMatchCondition($qpa, 'description');
- $qpa = db_construct_qpa ($qpa,
- ')') ;
- }
+ ' WHERE doc_data.doc_group = doc_groups.doc_group AND doc_data.docid = doc_data_idx.docid AND (vectors @@ $1',
+ array ($words)) ;
$qpa = db_construct_qpa ($qpa,
') AND doc_data.group_id = $1',
array ($group_id)) ;
' AND doc_data.stateid = 1') ;
}
$qpa = db_construct_qpa ($qpa,
- ' ORDER BY ts_rank(vectors, q) DESC, groupname ASC') ;
+ ') AS x ') ;
+ if (count($this->phrases)) {
+ $qpa = db_construct_qpa ('WHERE ') ;
+ $qpa = $this->addMatchCondition($qpa, 'full_string_agg');
+ }
+ $qpa = db_construct_qpa ($qpa,
+ ' ORDER BY ts_rank(vectors, $1) DESC, groupname ASC',
+ array($words)) ;
return $qpa ;
}
if (forge_get_config('use_fti')) {
$words = $this->getFTIwords();
$qpa = db_construct_qpa ($qpa,
- 'SELECT forum.msg_id, ts_headline(forum.subject, q) AS subject, forum.post_date, users.realname FROM forum, users, to_tsquery($1) AS q, forum_idx as fi WHERE forum.group_forum_id = $2 AND forum.posted_by = users.user_id AND fi.msg_id = forum.msg_id AND vectors @@ q ',
+ 'SELECT x.* FROM (SELECT forum.msg_id, ts_headline(forum.subject, $1::tsquery) AS subject, forum.post_date, users.realname, forum.subject||$2||forum.body as full_string_agg, forum_idx.vectors FROM forum, users, to_tsquery($1) AS q, forum_idx WHERE forum.group_forum_id = $3 AND forum.posted_by = users.user_id AND forum_idx.msg_id = forum.msg_id GROUP BY forum.msg_id, subject, body, post_date, realname, forum_idx.vectors) AS x WHERE vectors @@ $1::tsquery ',
array ($words,
+ $this->field_separator,
$this->forumId)) ;
$phraseOp = $this->getOperator();
if(count($this->phrases)) {
$qpa = db_construct_qpa ($qpa,
- 'AND ((') ;
- $qpa = $this->addMatchCondition($qpa, 'forum.body');
+ 'AND (') ;
+ $qpa = $this->addMatchCondition($qpa, 'full_string_agg');
$qpa = db_construct_qpa ($qpa,
- ') OR (') ;
- $qpa = $this->addMatchCondition($qpa, 'forum.subject');
- $qpa = db_construct_qpa ($qpa,
- ')) ') ;
+ ') ') ;
}
$qpa = db_construct_qpa ($qpa,
- 'ORDER BY ts_rank(vectors, q) DESC') ;
+ 'ORDER BY ts_rank(vectors, $1) DESC',
+ array($words)) ;
} else {
$qpa = db_construct_qpa ($qpa,
- 'SELECT forum.msg_id, forum.subject, forum.post_date, users.realname FROM forum,users WHERE users.user_id=forum.posted_by AND ((') ;
- $qpa = $this->addIlikeCondition ($qpa, 'forum.body') ;
- $qpa = db_construct_qpa ($qpa,
- ') OR (') ;
- $qpa = $this->addIlikeCondition ($qpa, 'forum.subject') ;
+ 'SELECT x.* FROM (SELECT forum.msg_id, forum.subject, forum.post_date, users.realname, forum.subject||$1||forum.body as full_string_agg FROM forum,users WHERE users.user_id=forum.posted_by AND forum.group_forum_id=$2 GROUP BY msg_id, subject, post_date, realname, body) AS x WHERE ',
+ array ($this->field_separator,
+ $this->forumId)) ;
+ $qpa = $this->addIlikeCondition ($qpa, 'full_string_agg') ;
$qpa = db_construct_qpa ($qpa,
- ')) AND forum.group_forum_id=$1 GROUP BY msg_id, subject, post_date, realname',
- array ($this->forumId)) ;
+ ' ');
}
return $qpa ;
}
}
$qpa = db_construct_qpa ($qpa,
- 'SELECT forum.msg_id, ts_headline(forum.subject, q) AS subject, forum.post_date, users.realname, forum_group_list.forum_name FROM forum, users, forum_group_list, forum_idx, to_tsquery($1) as q ',
- array ($this->getFTIwords())) ;
+ 'SELECT forum.msg_id, ts_headline(forum.subject, q) AS subject, forum.post_date, users.realname, forum_group_list.forum_name, forum.subject||$2||forum.body as full_string_agg FROM forum, users, forum_group_list, forum_idx, to_tsquery($1) as q ',
+ array ($this->getFTIwords(),
+ $this->field_separator)) ;
$qpa = db_construct_qpa ($qpa,
'WHERE users.user_id = forum.posted_by AND vectors @@ q AND forum.msg_id = forum_idx.msg_id AND forum_group_list.group_forum_id = forum.group_forum_id AND forum_group_list.is_public <> 9 AND forum.group_forum_id IN (SELECT group_forum_id FROM forum_group_list WHERE group_id = $1) ',
array ($this->groupId));
$qpa = db_construct_qpa ($qpa,
'AND forum_group_list.is_public = 1 ') ;
}
+
+ if(count($this->phrases)) {
+ $qpa = db_construct_qpa ($qpa,
+ 'AND (') ;
+ $qpa = $this->addMatchCondition($qpa, 'full_string_agg');
+ $qpa = db_construct_qpa ($qpa,
+ ') ') ;
+ }
+
$qpa = db_construct_qpa ($qpa,
'ORDER BY forum_group_list.forum_name ASC, forum.msg_id ASC, ts_rank(vectors, q) DESC') ;
} else {
$qpa = db_construct_qpa ($qpa,
- 'SELECT forum.msg_id, forum.subject, forum.post_date, users.realname, forum_group_list.forum_name FROM forum, users, forum_group_list WHERE users.user_id = forum.posted_by AND forum_group_list.group_forum_id = forum.group_forum_id AND forum_group_list.is_public <> 9 AND forum.group_forum_id IN (SELECT group_forum_id FROM forum_group_list WHERE group_id = $1) ',
- array ($this->groupId)) ;
+ 'SELECT x.* FROM (SELECT forum.msg_id, forum.subject, forum.post_date, users.realname, forum_group_list.forum_name, forum.subject||$1||forum.body as full_string_agg FROM forum, users, forum_group_list WHERE users.user_id = forum.posted_by AND forum_group_list.group_forum_id = forum.group_forum_id AND forum_group_list.is_public <> 9 AND forum.group_forum_id IN (SELECT group_forum_id FROM forum_group_list WHERE group_id = $2) ',
+ array ($this->field_separator,
+ $this->groupId)) ;
if ($this->sections != SEARCH__ALL_SECTIONS) {
$qpa = db_construct_qpa ($qpa,
'AND forum_group_list.group_forum_id = ANY ($1) ',
'AND forum_group_list.is_public = 1 ') ;
}
$qpa = db_construct_qpa ($qpa,
- 'AND ((') ;
- $qpa = $this->addIlikeCondition ($qpa, 'forum.body') ;
- $qpa = db_construct_qpa ($qpa,
- ') OR (') ;
- $qpa = $this->addIlikeCondition ($qpa,'forum.subject') ;
+ ') AS x WHERE ') ;
+ $qpa = $this->addIlikeCondition ($qpa, 'full_string_agg') ;
$qpa = db_construct_qpa ($qpa,
- ')) ORDER BY forum_group_list.forum_name, forum.msg_id') ;
+ ' ORDER BY x.forum_name, x.msg_id') ;
}
return $qpa ;
}
$words = $this->getFTIwords();
$qpa = db_construct_qpa ($qpa,
- 'SELECT ts_headline(news_bytes.summary, q) as summary, news_bytes.post_date, news_bytes.forum_id, users.realname FROM news_bytes, users, to_tsquery($1) AS q, news_bytes_idx WHERE (news_bytes.group_id=$2 AND news_bytes.is_approved <> 4 AND news_bytes_idx.id = news_bytes.id AND news_bytes.submitted_by=users.user_id) AND (vectors @@ q ',
- array ($words,
+ 'SELECT x.* FROM (SELECT ts_headline(news_bytes.summary, q) as summary, news_bytes.post_date, news_bytes.forum_id, users.realname, summary||$1||details AS full_string_agg, news_bytes_idx.vectors FROM news_bytes, users, to_tsquery($2) AS q, news_bytes_idx WHERE (news_bytes.group_id=$3 AND news_bytes.is_approved <> 4 AND news_bytes_idx.id = news_bytes.id AND news_bytes.submitted_by=users.user_id) AND vectors @@ q) AS x ',
+ array ($this->field_separator,
+ $words,
$group_id)) ;
if (count ($this->phrases)) {
$qpa = db_construct_qpa ($qpa,
- $this->getOperator()) ;
- $qpa = db_construct_qpa ($qpa,
- ' ((') ;
- $qpa = $this->addMatchCondition ($qpa, 'summary') ;
- $qpa = db_construct_qpa ($qpa,
- ') OR (') ;
- $qpa = $this->addMatchCondition ($qpa, 'details') ;
- $qpa = db_construct_qpa ($qpa,
- '))') ;
+ 'WHERE ');
+ $qpa = $this->addMatchCondition ($qpa, 'full_string_agg') ;
}
$qpa = db_construct_qpa ($qpa,
- ') ORDER BY ts_rank(vectors, q) DESC, post_date DESC') ;
+ ' ORDER BY ts_rank(vectors, $1) DESC, post_date DESC',
+ array($words)) ;
} else {
$qpa = db_construct_qpa ($qpa,
- 'SELECT news_bytes.summary, news_bytes.post_date, news_bytes.forum_id, users.realname FROM news_bytes, users WHERE group_id=$1 AND is_approved <> 4 AND news_bytes.submitted_by = users.user_id AND ((',
- array ($this->groupId)) ;
- $qpa = $this->addIlikeCondition ($qpa, 'summary') ;
- $qpa = db_construct_qpa ($qpa,
- ') OR (') ;
- $qpa = $this->addIlikeCondition ($qpa, 'details') ;
+ 'SELECT x.* FROM (SELECT news_bytes.summary, news_bytes.post_date, news_bytes.forum_id, users.realname, summary||$1||details AS full_string_agg FROM news_bytes, users WHERE group_id=$2 AND is_approved <> 4 AND news_bytes.submitted_by = users.user_id) AS x WHERE ',
+ array ($this->field_separator,
+ $this->groupId)) ;
+ $qpa = $this->addIlikeCondition ($qpa, 'full_string_agg') ;
$qpa = db_construct_qpa ($qpa,
- ')) ORDER BY post_date DESC') ;
+ ' ORDER BY post_date DESC') ;
}
return $qpa ;
}
var $phrases = array();
+ // Something that's hopefully not going to end up in real data
+ var $field_separator = ' ioM0Thu6_fieldseparator_kaeph9Ee ';
+
/**
* Constructor
*
* @param int $rowsPerPage number of rows per page
*/
function SearchQuery($words, $offset, $isExact, $rowsPerPage = SEARCH__DEFAULT_ROWS_PER_PAGE) {
+ $this->field_separator = ' ioM0Thu6_fieldseparator_kaeph9Ee ';
+
$this->cleanSearchWords($words);
//We manual escap because every Query in Search escap parameters
$words = addslashes($words);
*/
function setSections($sections) {
if(is_array($sections)) {
- $this->sections = array_keys($sections);
+ $this->sections = array_values($sections) ;
} else {
$this->sections = $sections;
}
* @return array query+params array
*/
function getQuery() {
-
-
$qpa = db_construct_qpa () ;
+ $qpa = db_construct_qpa ($qpa,
+ 'SELECT x.* FROM (SELECT project_task.project_task_id, project_task.summary, project_task.percent_complete, project_task.start_date, project_task.end_date, users.realname, project_group_list.project_name, project_task.summary||$1||project_task.details||$1||coalesce(ff_string_agg(project_messages.body), $1) as full_string_agg',
+ array (''));
if (forge_get_config('use_fti')) {
$words = $this->getFTIwords();
-
$qpa = db_construct_qpa ($qpa,
- 'SELECT project_task.project_task_id, project_task.percent_complete, ts_headline(project_task.summary, q) AS summary, project_task.start_date,project_task.end_date,users.firstname||$1||users.lastname AS realname, project_group_list.project_name, project_group_list.group_project_id FROM project_task, users, project_group_list, to_tsquery($2) AS q, project_task_idx WHERE project_task.created_by = users.user_id AND project_task.project_task_id = project_task_idx.project_task_id AND project_task.group_project_id = project_group_list.group_project_id AND project_group_list.group_id=$3 ',
- array (' ',
- $words,
- $this->groupId)) ;
- if ($this->sections != SEARCH__ALL_SECTIONS) {
- $qpa = db_construct_qpa ($qpa,
- 'AND project_group_list.group_project_id = ANY ($1) ',
- array(db_int_array_to_any_clause ($this->sections))) ;
- }
- if (!$this->showNonPublic) {
- $qpa = db_construct_qpa ($qpa,
- 'AND project_group_list.is_public = 1 ') ;
- }
- if (count($this->phrases)) {
- $qpa = db_construct_qpa ($qpa,
- 'AND (vectors @@ q AND (') ;
- $qpa = $this->addMatchCondition($qpa, 'summary');
- $qpa = db_construct_qpa ($qpa,
- ') OR (') ;
- $qpa = $this->addMatchCondition($qpa, 'details');
- $qpa = db_construct_qpa ($qpa,
- ')) ') ;
- }
+ ', (project_task_idx.vectors || coalesce(ff_tsvector_agg(project_messages_idx.vectors), $1::tsvector)) AS full_vector_agg',
+ array (''));
+ }
+ $qpa = db_construct_qpa ($qpa,
+ ' FROM project_task LEFT OUTER JOIN project_messages USING (project_task_id), users, project_group_list',
+ array ()) ;
+ if (forge_get_config('use_fti')) {
+ $qpa = db_construct_qpa ($qpa,
+ ', project_task_idx, project_messages_idx',
+ array ()) ;
+ }
+ $qpa = db_construct_qpa ($qpa,
+ ' WHERE project_task.created_by = users.user_id AND project_task.group_project_id = project_group_list.group_project_id AND project_group_list.group_id = $1 AND project_messages.project_task_id = project_task.project_task_id ',
+ array ($this->groupId)) ;
+ if ($this->sections != SEARCH__ALL_SECTIONS) {
$qpa = db_construct_qpa ($qpa,
- 'ORDER BY project_group_list.project_name, ts_rank(vectors, q) DESC, project_task.project_task_id') ;
- } else {
+ 'AND project_group_list.group_project_id = ANY ($1) ',
+ array (db_int_array_to_any_clause ($this->sections))) ;
+ }
+ if (!$this->showNonPublic) {
$qpa = db_construct_qpa ($qpa,
- 'SELECT project_task.project_task_id, project_task.summary, project_task.percent_complete, project_task.start_date, project_task.end_date, users.firstname||$1||users.lastname AS realname, project_group_list.project_name, project_group_list.group_project_id FROM project_task, users, project_group_list WHERE project_task.created_by = users.user_id AND project_task.group_project_id = project_group_list.group_project_id AND project_group_list.group_id = $2 ',
- array (' ',
- $this->groupId)) ;
- if ($this->sections != SEARCH__ALL_SECTIONS) {
+ 'AND project_group_list.is_public = 1 ') ;
+ }
+
+ if (forge_get_config('use_fti')) {
+ $qpa = db_construct_qpa ($qpa,
+ 'AND project_task.project_task_id = project_task_idx.project_task_id AND project_messages.project_message_id = project_messages_idx.id ',
+ array ()) ;
+ }
+ $qpa = db_construct_qpa ($qpa,
+ 'GROUP BY project_task.project_task_id, project_task.summary, project_task.percent_complete, project_task.start_date, project_task.end_date, users.realname, project_group_list.project_name, project_task.details') ;
+ if (forge_get_config('use_fti')) {
+ $qpa = db_construct_qpa ($qpa,
+ ', project_task_idx.vectors',
+ array ()) ;
+ }
+ $qpa = db_construct_qpa ($qpa,
+ ') AS x WHERE ') ;
+
+ if (forge_get_config('use_fti')) {
+ $qpa = db_construct_qpa ($qpa,
+ 'full_vector_agg @@ $1 ',
+ array($words));
+ if (count($this->phrases)) {
$qpa = db_construct_qpa ($qpa,
- 'AND project_group_list.group_project_id = ANY ($1) ',
- array( db_int_array_to_any_clause ($this->sections))) ;
- }
- if (!$this->showNonPublic) {
+ 'AND (') ;
+ $qpa = $this->addMatchCondition ($qpa, 'x.full_string_agg') ;
$qpa = db_construct_qpa ($qpa,
- 'AND project_group_list.is_public = 1 ') ;
+ ') ') ;
}
$qpa = db_construct_qpa ($qpa,
- ' AND ((') ;
- $qpa = $this->addIlikeCondition ($qpa, 'summary') ;
- $qpa = db_construct_qpa ($qpa,
- ') OR (') ;
- $qpa = $this->addIlikeCondition ($qpa, 'details') ;
+ 'ORDER BY ts_rank(full_vector_agg, $1) DESC',
+ array($words)) ;
+
+ } else {
+ $qpa = $this->addIlikeCondition ($qpa, 'x.full_string_agg') ;
$qpa = db_construct_qpa ($qpa,
- ')) ORDER BY project_group_list.project_name, project_task.project_task_id') ;
+ ' ORDER BY x.project_name, x.project_task_id') ;
}
return $qpa ;
}
* @return array query+params array
*/
function getQuery() {
-
-
$qpa = db_construct_qpa () ;
+ $qpa = db_construct_qpa ($qpa,
+ 'SELECT x.* FROM (SELECT artifact.artifact_id, artifact.group_artifact_id, artifact.summary, artifact.open_date, users.realname, artifact_group_list.name, artifact.summary||$1||artifact.details||$1||coalesce(ff_string_agg(artifact_message.body), $1) as full_string_agg',
+ array (''));
if (forge_get_config('use_fti')) {
+ $words = $this->getFTIwords();
$qpa = db_construct_qpa ($qpa,
- 'SELECT DISTINCT x.* FROM (SELECT artifact.artifact_id, artifact.group_artifact_id, artifact.summary, artifact.open_date, users.realname, artifact_group_list.name, (ts_rank(artifact_idx.vectors, q)+ts_rank(artifact_message_idx.vectors, q)) AS rank FROM artifact LEFT OUTER JOIN artifact_message USING (artifact_id), users, artifact_group_list, to_tsquery($1) q, artifact_idx, artifact_message_idx WHERE users.user_id = artifact.submitted_by 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 AND artifact_group_list.group_artifact_id = artifact.group_artifact_id AND artifact_group_list.group_id = $2 ',
- array ($this->getFTIwords(),
- $this->groupId)) ;
- $tsmatch = "(artifact_idx.vectors @@ q OR artifact_message_idx.vectors @@ q)";
- $phraseOp = $this->getOperator();
-
- if (count($this->phrases)) {
- $qpa = db_construct_qpa ($qpa,
- 'AND ((') ;
- $qpa = $this->addMatchCondition($qpa, 'artifact.details');
- $qpa = db_construct_qpa ($qpa,
- ') OR (') ;
- $qpa = $this->addMatchCondition($qpa, 'artifact.summary');
- $qpa = db_construct_qpa ($qpa,
- ') OR (') ;
- $qpa = $this->addMatchCondition($qpa, 'artifact_message.body');
- $qpa = db_construct_qpa ($qpa,
- ')) ') ;
- }
- if ($this->sections != SEARCH__ALL_SECTIONS) {
- $qpa = db_construct_qpa ($qpa,
- 'AND artifact_group_list.group_artifact_id = ANY ($1) ',
- array( db_int_array_to_any_clause ($this->sections))) ;
- }
- if (!$this->showNonPublic) {
- $qpa = db_construct_qpa ($qpa,
- 'AND artifact_group_list.is_public = 1 ') ;
- }
+ ', (artifact_idx.vectors || coalesce(ff_tsvector_agg(artifact_message_idx.vectors), $1::tsvector)) AS full_vector_agg',
+ array (''));
+ }
+ $qpa = db_construct_qpa ($qpa,
+ ' FROM artifact LEFT OUTER JOIN artifact_message USING (artifact_id), users, artifact_group_list',
+ array ()) ;
+ if (forge_get_config('use_fti')) {
+ $qpa = db_construct_qpa ($qpa,
+ ', artifact_idx, artifact_message_idx',
+ array ()) ;
+ }
+ $qpa = db_construct_qpa ($qpa,
+ ' WHERE users.user_id = artifact.submitted_by AND artifact_group_list.group_artifact_id = artifact.group_artifact_id AND artifact_group_list.group_id = $1 AND artifact_message.artifact_id = artifact.artifact_id ',
+ array ($this->groupId)) ;
+ if ($this->sections != SEARCH__ALL_SECTIONS) {
$qpa = db_construct_qpa ($qpa,
- ') x') ;
+ 'AND artifact_group_list.group_artifact_id = ANY ($1) ',
+ array (db_int_array_to_any_clause ($this->sections))) ;
+ }
+ if (!$this->showNonPublic) {
$qpa = db_construct_qpa ($qpa,
- 'ORDER BY rank DESC') ;
- } else {
+ 'AND artifact_group_list.is_public = 1 ') ;
+ }
+ if (forge_get_config('use_fti')) {
+ $qpa = db_construct_qpa ($qpa,
+ 'AND artifact.artifact_id = artifact_idx.artifact_id AND artifact_message.id = artifact_message_idx.id ',
+ array ()) ;
+ }
+ $qpa = db_construct_qpa ($qpa,
+ 'GROUP BY artifact.artifact_id, artifact.group_artifact_id, artifact.summary, artifact.open_date, users.realname, artifact_group_list.name, artifact.details') ;
+
+ if (forge_get_config('use_fti')) {
+ $qpa = db_construct_qpa ($qpa,
+ ', artifact_idx.vectors',
+ array ()) ;
+ }
+ $qpa = db_construct_qpa ($qpa,
+ ') AS x WHERE ') ;
+
+ if (forge_get_config('use_fti')) {
$qpa = db_construct_qpa ($qpa,
- '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 WHERE users.user_id = artifact.submitted_by AND artifact_group_list.group_artifact_id = artifact.group_artifact_id AND artifact_group_list.group_id = $1 ',
- array ($this->groupId)) ;
- if ($this->sections != SEARCH__ALL_SECTIONS) {
+ 'full_vector_agg @@ $1 ',
+ array($words));
+ if (count($this->phrases)) {
$qpa = db_construct_qpa ($qpa,
- 'AND artifact_group_list.group_artifact_id = ANY ($1) ',
- array(db_int_array_to_any_clause ($this->sections))) ;
- }
- if (!$this->showNonPublic) {
+ 'AND (') ;
+ $qpa = $this->addMatchCondition ($qpa, 'x.full_string_agg') ;
$qpa = db_construct_qpa ($qpa,
- 'AND artifact_group_list.is_public = 1 ') ;
+ ') ') ;
}
-
- $qpa = db_construct_qpa ($qpa,
- ' AND ((') ;
- $qpa = $this->addIlikeCondition ($qpa, 'artifact.details') ;
$qpa = db_construct_qpa ($qpa,
- ') OR (') ;
- $qpa = $this->addIlikeCondition ($qpa, 'artifact.summary') ;
- $qpa = db_construct_qpa ($qpa,
- ') OR (') ;
- $qpa = $this->addIlikeCondition ($qpa, 'artifact_message.body') ;
+ 'ORDER BY ts_rank(full_vector_agg, $1) DESC',
+ array($words)) ;
+
+ } else {
+ $qpa = $this->addIlikeCondition ($qpa, 'x.full_string_agg') ;
$qpa = db_construct_qpa ($qpa,
- ')) ORDER BY artifact_group_list.name, artifact.artifact_id') ;
+ ' ORDER BY x.name, x.artifact_id') ;
}
return $qpa ;
}
--- /dev/null
+CREATE TABLE project_messages_idx (
+ id integer,
+ project_task_id integer,
+ vectors tsvector
+);
+
+CREATE OR REPLACE FUNCTION update_vectors() RETURNS TRIGGER AS '
+DECLARE
+table_name TEXT;
+BEGIN
+ table_name := TG_ARGV[0];
+ -- **** artifact table ****
+ IF table_name = ''artifact'' THEN
+ IF TG_OP = ''INSERT'' THEN
+ INSERT INTO artifact_idx (artifact_id, group_artifact_id, vectors) VALUES (NEW.artifact_id, NEW.group_artifact_id, to_tsvector(coalesce(NEW.details,\'\') ||\' \'|| coalesce(NEW.summary,\'\')));
+ ELSIF TG_OP = ''UPDATE'' THEN
+ UPDATE artifact_idx SET group_artifact_id=NEW.group_artifact_id, vectors=to_tsvector(coalesce(NEW.details,\'\') ||\' \'|| coalesce(NEW.summary,\'\')) WHERE artifact_id=NEW.artifact_id;
+ ELSIF TG_OP = ''DELETE'' THEN
+ DELETE FROM artifact_idx WHERE artifact_id=OLD.artifact_id;
+ END IF;
+ -- **** artifact_message table ****
+ ELSIF table_name = ''artifact_message'' THEN
+ IF TG_OP = ''INSERT'' THEN
+ INSERT INTO artifact_message_idx (id, artifact_id, vectors) VALUES (NEW.id, NEW.artifact_id, to_tsvector(coalesce(NEW.body,\'\')));
+ ELSIF TG_OP = ''UPDATE'' THEN
+ UPDATE artifact_message_idx SET artifact_id=NEW.artifact_id, vectors=to_tsvector(coalesce(NEW.body,\'\')) WHERE id=NEW.id;
+ ELSIF TG_OP = ''DELETE'' THEN
+ DELETE FROM artifact_message_idx WHERE id=OLD.id;
+ END IF;
+ -- **** doc_data table ****
+ ELSIF table_name = ''doc_data'' THEN
+ IF TG_OP = ''INSERT'' THEN
+ INSERT INTO doc_data_idx (docid, group_id, vectors) VALUES (NEW.docid, NEW.group_id, to_tsvector(coalesce(NEW.title,\'\') ||\' \'|| coalesce(NEW.description,\'\')));
+ ELSIF TG_OP = ''UPDATE'' THEN
+ UPDATE doc_data_idx SET group_id=NEW.group_id, vectors=to_tsvector(coalesce(NEW.title,\'\') ||\' \'|| coalesce(NEW.description,\'\')) WHERE docid=NEW.docid;
+ ELSIF TG_OP = ''DELETE'' THEN
+ DELETE FROM doc_data_idx WHERE docid=OLD.docid;
+ END IF;
+ -- **** forum table ****
+ ELSIF table_name = ''forum'' THEN
+ IF TG_OP = ''INSERT'' THEN
+ INSERT INTO forum_idx (msg_id, group_id, vectors) (SELECT f.msg_id, g.group_id, to_tsvector(coalesce(f.subject,\'\') ||\' \'||
+ coalesce(f.body,\'\')) AS vectors FROM forum f, forum_group_list g WHERE f.group_forum_id = g.group_forum_id AND f.msg_id = NEW.msg_id);
+ ELSIF TG_OP = ''UPDATE'' THEN
+ UPDATE forum_idx SET vectors=to_tsvector(coalesce(NEW.subject,\'\') ||\' \'|| coalesce(NEW.body,\'\')) WHERE msg_id=NEW.msg_id;
+ ELSIF TG_OP = ''DELETE'' THEN
+ DELETE FROM forum_idx WHERE msg_id=OLD.msg_id;
+ END IF;
+ -- **** frs_file table ****
+ ELSIF table_name = ''frs_file'' THEN
+ IF TG_OP = ''INSERT'' THEN
+ INSERT INTO frs_file_idx (file_id, release_id, vectors) VALUES (NEW.file_id, NEW.release_id, to_tsvector(coalesce(NEW.filename,\'\')));
+ ELSIF TG_OP = ''UPDATE'' THEN
+ UPDATE frs_file_idx SET vectors=to_tsvector(coalesce(NEW.filename,\'\')), release_id=NEW.release_id WHERE file_id=NEW.file_id;
+ ELSIF TG_OP = ''DELETE'' THEN
+ DELETE FROM frs_file_idx WHERE file_id=OLD.file_id;
+ END IF;
+ -- **** frs_release table ****
+ ELSIF table_name = ''frs_release'' THEN
+ IF TG_OP = ''INSERT'' THEN
+ INSERT INTO frs_release_idx (release_id, vectors) VALUES (NEW.release_id, to_tsvector(coalesce(NEW.changes,\'\') ||\' \'|| coalesce(NEW.notes,\'\') ||\' \'|| coalesce(NEW.name,\'\')));
+ ELSIF TG_OP = ''UPDATE'' THEN
+ UPDATE frs_release_idx SET vectors=to_tsvector(coalesce(NEW.changes,\'\') ||\' \'|| coalesce(NEW.notes,\'\') ||\' \'|| coalesce(NEW.name,\'\')) WHERE release_id=NEW.release_id;
+ ELSIF TG_OP = ''DELETE'' THEN
+ DELETE FROM frs_release_idx WHERE release_id=OLD.release_id;
+ DELETE FROM frs_file_idx WHERE release_id=OLD.release_id;
+ END IF;
+ -- **** groups table ****
+ ELSIF table_name = ''groups'' THEN
+ IF TG_OP = ''INSERT'' THEN
+ INSERT INTO groups_idx (group_id, vectors) VALUES (NEW.group_id, to_tsvector(coalesce(NEW.group_name,\'\') ||\' \'|| coalesce(NEW.short_description,\'\') ||\' \'|| coalesce(NEW.unix_group_name,\'\')));
+ ELSIF TG_OP = ''UPDATE'' THEN
+ UPDATE groups_idx SET vectors=to_tsvector(coalesce(NEW.group_name,\'\') ||\' \'|| coalesce(NEW.short_description,\'\') ||\' \'|| coalesce(NEW.unix_group_name,\'\')) WHERE group_id=NEW.group_id;
+ ELSIF TG_OP = ''DELETE'' THEN
+ DELETE FROM groups_idx WHERE group_id=OLD.group_id;
+ END IF;
+ -- **** news_bytes table ****
+ ELSIF table_name = ''news_bytes'' THEN
+ IF TG_OP = ''INSERT'' THEN
+ INSERT INTO news_bytes_idx (id, vectors) VALUES (NEW.id, to_tsvector(coalesce(NEW.summary,\'\') ||\' \'|| coalesce(NEW.details,\'\')));
+ ELSIF TG_OP = ''UPDATE'' THEN
+ UPDATE news_bytes_idx SET vectors=to_tsvector(coalesce(NEW.summary,\'\') ||\' \'|| coalesce(NEW.details,\'\')) WHERE id=NEW.id;
+ ELSIF TG_OP = ''DELETE'' THEN
+ DELETE FROM news_bytes_idx WHERE id=OLD.id;
+ END IF;
+ -- **** project_task table ****
+ ELSIF table_name = ''project_task'' THEN
+ IF TG_OP = ''INSERT'' THEN
+ INSERT INTO project_task_idx (project_task_id, vectors) VALUES (NEW.project_task_id, to_tsvector(coalesce(NEW.summary,\'\') ||\' \'|| coalesce(NEW.details,\'\')));
+ ELSIF TG_OP = ''UPDATE'' THEN
+ UPDATE project_task_idx SET vectors=to_tsvector(coalesce(NEW.summary,\'\') ||\' \'|| coalesce(NEW.details,\'\')) WHERE project_task_id=NEW.project_task_id;
+ ELSIF TG_OP = ''DELETE'' THEN
+ DELETE FROM project_task_idx WHERE project_task_id=OLD.project_task_id;
+ END IF;
+ -- **** project_messages table ****
+ ELSIF table_name = ''project_messages'' THEN
+ IF TG_OP = ''INSERT'' THEN
+ INSERT INTO project_messages_idx (id, project_task_id, vectors) VALUES (NEW.project_message_id, NEW.project_task_id, to_tsvector(coalesce(NEW.body,\'\')));
+ ELSIF TG_OP = ''UPDATE'' THEN
+ UPDATE project_messages_idx SET project_task_id=NEW.project_task_id, vectors=to_tsvector(coalesce(NEW.body,\'\')) WHERE id=NEW.project_message_id;
+ ELSIF TG_OP = ''DELETE'' THEN
+ DELETE FROM project_messages_idx WHERE id=OLD.project_message_id;
+ END IF;
+ -- **** skills_data table ****
+ ELSIF table_name = ''skills_data'' THEN
+ IF TG_OP = ''INSERT'' THEN
+ INSERT INTO skills_data_idx (skills_data_id, vectors) VALUES (NEW.skill_data_id, to_tsvector(coalesce(NEW.title,\'\') ||\' \'|| coalesce(NEW.keywords,\'\')));
+ ELSIF TG_OP = ''UPDATE'' THEN
+ UPDATE skills_data_idx SET vectors=to_tsvector(coalesce(NEW.title,\'\') ||\' \'|| coalesce(NEW.keywords,\'\')) WHERE skills_data_id=NEW.skills_data_id;
+ ELSIF TG_OP = ''DELETE'' THEN
+ DELETE FROM skills_data_idx WHERE skills_data_id=OLD.skills_data_id;
+ END IF;
+ -- **** users table ****
+ ELSIF table_name = ''users'' THEN
+ IF TG_OP = ''INSERT'' THEN
+ INSERT INTO users_idx (user_id, vectors) VALUES (NEW.user_id, to_tsvector(coalesce(NEW.user_name,\'\') ||\' \'|| coalesce(NEW.realname,\'\')));
+ ELSIF TG_OP = ''UPDATE'' THEN
+ UPDATE users_idx SET vectors=to_tsvector(coalesce(NEW.user_name,\'\') ||\' \'|| coalesce(NEW.realname,\'\')) WHERE user_id=NEW.user_id;
+ ELSIF TG_OP = ''DELETE'' THEN
+ DELETE FROM users_idx WHERE user_id=OLD.user_id;
+ END IF;
+ END IF;
+
+ RETURN NEW;
+END;'
+LANGUAGE 'plpgsql';
+
+CREATE TRIGGER projectmessage_ts_update AFTER UPDATE OR INSERT OR DELETE ON project_messages
+FOR EACH ROW EXECUTE PROCEDURE update_vectors('project_messages');
+
+DELETE FROM project_messages_idx;
+
+INSERT INTO project_messages_idx (id, project_task_id, vectors)
+SELECT project_message_id, project_task_id, to_tsvector(coalesce(body,'')) AS vectors
+FROM project_messages ORDER BY project_message_id;
--- /dev/null
+CREATE OR REPLACE FUNCTION ff_tsvector_add (v1 tsvector, v2 tsvector)
+RETURNS tsvector
+AS $$
+BEGIN
+ RETURN v1 || v2 ;
+END;
+$$ LANGUAGE plpgsql
+IMMUTABLE
+RETURNS NULL ON NULL INPUT;
+
+CREATE AGGREGATE ff_tsvector_agg (
+ basetype = tsvector,
+ sfunc = ff_tsvector_add,
+ stype = tsvector
+);
--- /dev/null
+CREATE OR REPLACE FUNCTION ff_string_add (t1 text, t2 text)
+RETURNS text
+AS $$
+BEGIN
+ RETURN t1 || ' ioM0Thu6_fieldseparator_kaeph9Ee ' || t2 ;
+END;
+$$ LANGUAGE plpgsql
+IMMUTABLE
+RETURNS NULL ON NULL INPUT;
+
+CREATE AGGREGATE ff_string_agg (
+ basetype = text,
+ sfunc = ff_string_add,
+ stype = text
+);
&update_with_sql("FTI-20050530","5.1-6");
&update_with_sql("FTI-20060130","5.1-7");
&update_with_sql("FTI-20061025","5.1-8");
+ &update_with_sql("20111007-fti-aggregate-functions","5.1-9");
+ &update_with_sql("20111007-add-fti-for-task-messages","5.1-10");
+ &update_with_sql("20111009-string-aggregate-function","5.1-11");
&update_with_sql("20110118-user-tooltips","5.1.51-1");
&update_with_sql("20110211-docman-activityvw","5.1.51-2");
&update_with_sql("20110222-pluginify-auth","5.1.51-3");
$params['group_id'] = $group->getID();
$params['repos'] = $repos;
$params['hooks'] = &$hooks;
- plugin_hook('cmd_for_post_commit_hook', $params);
+ plugin_hook_by_reference('cmd_for_post_commit_hook', $params);
foreach ($params['hooks'] as $plugin => $cmd ) {
if (getenv('sys_localinc')) {
$suite->addTestFiles(glob("func/PluginsBlocks/*Test.php"));
$suite->addTestFiles(glob("func/RBAC/*Test.php"));
$suite->addTestFiles(glob("func/Surveys/*Test.php"));
+ $suite->addTestFiles(glob("func/Search/*Test.php"));
return $suite;
}
// $suite->addTestFiles(glob("func/PluginsSvnTracker/*Test.php"));
$suite->addTestFiles(glob("func/RBAC/*Test.php"));
$suite->addTestFiles(glob("func/Surveys/*Test.php"));
+ $suite->addTestFiles(glob("func/Search/*Test.php"));
return $suite;
}
// $suite->addTestFiles(glob("func/PluginsSvnTracker/*Test.php"));
$suite->addTestFiles(glob("func/RBAC/*Test.php"));
$suite->addTestFiles(glob("func/Surveys/*Test.php"));
+ $suite->addTestFiles(glob("func/Search/*Test.php"));
return $suite;
}
CONFIGURED=true
# Debian mirrors
-DEBMIRROR=http://cdn.debian.net/debian/
+DEBMIRROR=http://ftp.debian.org/debian/
DEBMIRRORSEC=http://security.debian.org/
# Redhat mirrors
function testPeopleSearch()
{
- $this->switchUser('admin');
+ $this->switchUser(FORGE_ADMIN_USERNAME);
$this->createUser('ratatouille');
$this->createUser('tartiflette');
$this->assertTrue($this->isTextPresent("tartiflette Lastname"));
}
+
+ function testSearchInTools()
+ {
+ $this->populateStandardTemplate();
+ $this->createProject('projecta');
+
+ // TODO: check that search results vary according to what items are visible to the user
+ // $this->createProject('projectb');
+ // $this->createUser('piperade');
+ // $this->createUser('cassoulet');
+
+ // Prepare some tracker items
+
+ $this->gotoProject('projecta');
+ $this->clickAndWait("link=Tracker");
+ $this->clickAndWait("link=Bugs");
+ $this->clickAndWait("link=Submit New");
+ $this->type("summary", "Bug1 boustrophédon");
+ $this->type("details", "brebis outremanchienne");
+ $this->clickAndWait("//form[@id='trackeraddform']//input[@type='submit']");
+ $this->clickAndWait("link=Bug1 boustrophédon");
+ $this->type("details", 'Ceci était une référence au « Génie des Alpages », rien à voir avec Charlie');
+ $this->clickAndWait("submit");
+ $this->clickAndWait("link=Bug1 boustrophédon");
+ $this->type("details", 'This is the needle');
+ $this->clickAndWait("submit");
+
+ $this->clickAndWait("link=Tracker");
+ $this->clickAndWait("link=Patches");
+ $this->clickAndWait("link=Submit New");
+ $this->type("summary", "Bug2 gratapouêt");
+ $this->type("details", "cthulhu was here");
+ $this->clickAndWait("//form[@id='trackeraddform']//input[@type='submit']");
+ $this->clickAndWait("link=Bug2 gratapouêt");
+ $this->type("details", 'Charlie was here too');
+ $this->clickAndWait("submit");
+
+ // Search in trackers
+
+ $this->select("type_of_search", "label=This project's trackers");
+ $this->type("//input[@name='words']", "brebis");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Bug1"));
+
+ $this->select("type_of_search", "label=This project's trackers");
+ $this->type("//input[@name='words']", "alpages");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Bug1"));
+
+ $this->select("type_of_search", "label=This project's trackers");
+ $this->type("//input[@name='words']", "boustrophédon brebis alpages");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Bug1"));
+
+ $this->select("type_of_search", "label=This project's trackers");
+ $this->type("//input[@name='words']", "'boustrophédon brebis'");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertTrue($this->isTextPresent("No matches found for"));
+ $this->assertFalse($this->isTextPresent("Bug1"));
+
+ $this->select("type_of_search", "label=This project's trackers");
+ $this->type("//input[@name='words']", "boustrophédon cthulhu");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertTrue($this->isTextPresent("No matches found for"));
+ $this->assertFalse($this->isTextPresent("Bug1"));
+ $this->assertFalse($this->isTextPresent("Bug2"));
+
+ // Search in one particular tracker
+
+ $this->select("type_of_search", "label=This project's trackers");
+ $this->type("//input[@name='words']", "charlie");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Bug1"));
+ $this->assertTrue($this->isTextPresent("Bug2"));
+
+ $this->clickAndWait("link=Tracker");
+ $this->clickAndWait("link=Bugs");
+ $this->select("type_of_search", "label=Bugs");
+ $this->type("//input[@name='words']", "charlie");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Bug1"));
+ $this->assertFalse($this->isTextPresent("Bug2"));
+
+ $this->clickAndWait("link=Bugs");
+ $this->select("type_of_search", "label=Bugs");
+ $this->type("//input[@name='words']", "charlie boustrophédon");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Bug1"));
+ $this->assertFalse($this->isTextPresent("Bug2"));
+
+ // Create some tasks
+
+ $this->gotoProject('projecta');
+ $this->clickAndWait("link=Tasks");
+ $this->clickAndWait("link=To Do");
+ $this->clickAndWait("link=Add Task");
+ $this->type("summary", "Task1 the brain");
+ $this->type("details", "The same thing we do every night, Pinky - try to take over the world!");
+ $this->type("hours", "199");
+ $this->clickAndWait("submit");
+
+ $this->clickAndWait("link=Task1 the brain");
+ $this->type("details", 'This is the needle for tasks');
+ $this->clickAndWait("submit");
+
+ $this->clickAndWait("link=Add Task");
+ $this->type("summary", "Task2 world peace");
+ $this->type("details", "Otherwise WW4 will be fought with sticks");
+ $this->type("hours", "199");
+ $this->clickAndWait("submit");
+
+ // Search in Tasks
+
+ $this->select("type_of_search", "label=This project's tasks");
+ $this->type("//input[@name='words']", "pinky");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Task1"));
+
+ $this->select("type_of_search", "label=This project's tasks");
+ $this->type("//input[@name='words']", "cortex");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertTrue($this->isTextPresent("No matches found for"));
+ $this->assertFalse($this->isTextPresent("Task1"));
+
+ $this->select("type_of_search", "label=This project's tasks");
+ $this->type("//input[@name='words']", "brain pinky needle");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Task1"));
+
+ // Post some messages in a forum
+
+ $this->gotoProject('projecta');
+ $this->clickAndWait("link=Forums");
+ $this->clickAndWait("link=open-discussion");
+ $this->click("link=Start New Thread");
+ $this->waitForPageToLoad("30000");
+ $this->type("subject", "Message1 in a bottle");
+ $this->type("body", "ninetynine of them on Charlie's wall");
+ $this->clickAndWait("submit");
+ $this->clickAndWait("link=Message1 in a bottle");
+ $this->clickAndWait("link=[ reply ]");
+ $this->type("subject", "Message2 in a bottle");
+ $this->type("body", "ninetyeight of them in Charlie's fridge");
+ $this->clickAndWait("submit");
+ $this->clickAndWait("link=Message1 in a bottle");
+ $this->clickAndWait("link=[ reply ]");
+ $this->type("subject", "Message3 in a bottle");
+ $this->type("body", "and yet another needle for the forums");
+ $this->clickAndWait("submit");
+
+ $this->clickAndWait("link=Forums");
+ $this->clickAndWait("link=developers-discussion");
+ $this->click("link=Start New Thread");
+ $this->waitForPageToLoad("30000");
+ $this->type("subject", "Message4 in an envelope");
+ $this->type("body", "not the same thing as an antilope (and different thread anyway) (but still related to Charlie)");
+ $this->clickAndWait("submit");
+
+ // Search in Forums
+
+ $this->select("type_of_search", "label=This project's forums");
+ $this->type("//input[@name='words']", "bottle");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Message1"));
+ $this->assertTrue($this->isTextPresent("Message2"));
+ $this->assertTrue($this->isTextPresent("Message3"));
+ $this->assertFalse($this->isTextPresent("Message4"));
+
+ $this->select("type_of_search", "label=This project's forums");
+ $this->type("//input[@name='words']", "bottle fridge");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertFalse($this->isTextPresent("Message1"));
+ $this->assertTrue($this->isTextPresent("Message2"));
+ $this->assertFalse($this->isTextPresent("Message3"));
+ $this->assertFalse($this->isTextPresent("Message4"));
+
+ // Search in one particular forum
+
+ $this->select("type_of_search", "label=This project's forums");
+ $this->type("//input[@name='words']", "charlie");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Message1"));
+ $this->assertTrue($this->isTextPresent("Message2"));
+ $this->assertFalse($this->isTextPresent("Message3"));
+ $this->assertTrue($this->isTextPresent("Message4"));
+
+ $this->clickAndWait("link=Forums");
+ $this->clickAndWait("link=open-discussion");
+ $this->select("type_of_search", "label=This forum");
+ $this->type("//input[@name='words']", "charlie");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Message1"));
+ $this->assertTrue($this->isTextPresent("Message2"));
+ $this->assertFalse($this->isTextPresent("Message3"));
+ $this->assertFalse($this->isTextPresent("Message4"));
+
+ $this->clickAndWait("link=Forums");
+ $this->clickAndWait("link=open-discussion");
+ $this->select("type_of_search", "label=This forum");
+ $this->type("//input[@name='words']", "charlie fridge");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ // Only one result => threaded view => need to check on bodies, not subjects
+ $this->assertFalse($this->isTextPresent("wall"));
+ $this->assertTrue($this->isTextPresent("fridge"));
+ $this->assertFalse($this->isTextPresent("needle"));
+ $this->assertFalse($this->isTextPresent("Message4"));
+
+ // Create some documents
+
+ $this->gotoProject('projecta');
+ $this->clickAndWait("link=Docs");
+ $this->clickAndWait("link=Submit new documentation");
+ $this->type("title", "Doc1 Vladimir");
+ $this->type("description", "Jenkins buildbot");
+ $this->click("//input[@name='type' and @value='pasteurl']");
+ $this->type("file_url", "http://buildbot3.fusionforge.org/");
+ $this->clickAndWait("submit");
+
+ $this->clickAndWait("link=Submit new documentation");
+ $this->type("title", "Doc2 Astromir");
+ $this->type("description", "Hudson (the needle)");
+ $this->click("//input[@name='type' and @value='pasteurl']");
+ $this->type("file_url", "http://buildbot.fusionforge.org/");
+ $this->clickAndWait("submit");
+
+ // Search in Documents
+
+ $this->select("type_of_search", "label=This project's documents");
+ $this->type("//input[@name='words']", "jenkins");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Doc1"));
+ $this->assertFalse($this->isTextPresent("Doc2"));
+
+ $this->select("type_of_search", "label=This project's documents");
+ $this->type("//input[@name='words']", "vladimir jenkins");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("Doc1"));
+ $this->assertFalse($this->isTextPresent("Doc2"));
+
+ // Create some news
+
+ $this->gotoProject('projecta');
+ $this->clickAndWait("link=News");
+ $this->clickAndWait("link=Submit");
+ $this->type("summary", "News1 daily planet");
+ $this->type("details", "Clark Kent's newspaper");
+ $this->clickAndWait("submit");
+
+ $this->clickAndWait("link=Submit");
+ $this->type("summary", "News2 usenet");
+ $this->type("details", "alt sysadmin recovery (needle)");
+ $this->clickAndWait("submit");
+ $this->clickAndWait("link=News");
+
+ // Search in news
+
+ $this->select("type_of_search", "label=This project's news");
+ $this->type("//input[@name='words']", "sysadmin");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("News2"));
+
+ $this->select("type_of_search", "label=This project's news");
+ $this->type("//input[@name='words']", "daily newspaper");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertFalse($this->isTextPresent("No matches found for"));
+ $this->assertTrue($this->isTextPresent("News1"));
+
+ // Search in entire project
+
+ $this->gotoProject('projecta');
+ $this->select("type_of_search", "label=Search the entire project");
+ $this->type("//input[@name='words']", "needle");
+ $this->clickAndWait("//input[@name='Search']");
+ $this->assertTrue($this->isTextPresent("Bug1"));
+ $this->assertFalse($this->isTextPresent("Bug2"));
+ $this->assertTrue($this->isTextPresent("Task1"));
+ $this->assertFalse($this->isTextPresent("Task2"));
+ $this->assertFalse($this->isTextPresent("Message1"));
+ $this->assertFalse($this->isTextPresent("Message2"));
+ $this->assertTrue($this->isTextPresent("Message3"));
+ $this->assertFalse($this->isTextPresent("Message4"));
+ $this->assertFalse($this->isTextPresent("Doc1"));
+ $this->assertTrue($this->isTextPresent("Doc2"));
+ $this->assertFalse($this->isTextPresent("News1"));
+ $this->assertTrue($this->isTextPresent("News2"));
+
+ // Advanced search
+ $this->gotoProject('projecta');
+ $this->clickAndWait('Link=Advanced search');
+ $this->click("//a[contains(@href,'short_forum') and .='all']");
+ $this->click("//a[contains(@href,'short_tracker') and .='all']");
+ $this->click("//a[contains(@href,'short_pm') and .='all']");
+ $this->click("//a[contains(@href,'short_docman') and .='all']");
+ $this->click("//a[contains(@href,'short_news') and .='all']");
+ $this->type("//div[@id='maindiv']//input[@name='words']", "needle");
+ $this->clickAndWait("//input[@name='submitbutton']");
+ $this->assertTrue($this->isTextPresent("Bug1"));
+ $this->assertFalse($this->isTextPresent("Bug2"));
+ $this->assertTrue($this->isTextPresent("Task1"));
+ $this->assertFalse($this->isTextPresent("Task2"));
+ $this->assertFalse($this->isTextPresent("Message1"));
+ $this->assertFalse($this->isTextPresent("Message2"));
+ $this->assertTrue($this->isTextPresent("Message3"));
+ $this->assertFalse($this->isTextPresent("Message4"));
+ $this->assertFalse($this->isTextPresent("Doc1"));
+ $this->assertTrue($this->isTextPresent("Doc2"));
+ $this->assertFalse($this->isTextPresent("News1"));
+ $this->assertTrue($this->isTextPresent("News2"));
+ }
}
?>
echo "Set forge admin password"
ssh root@$HOST "/usr/share/gforge/bin/forge_set_password $FORGE_ADMIN_USERNAME $FORGE_ADMIN_PASSWORD"
ssh root@$HOST "LANG=C a2dissite default ; LANG=C invoke-rc.d apache2 reload"
-ssh root@$HOST "(echo [core];echo use_ssl=no) > /etc/gforge/config.ini.d/zzz-builbot.ini"
+ssh root@$HOST "(echo [core];echo use_ssl=no) > /etc/gforge/config.ini.d/zzz-buildbot.ini"
# Dump database
echo "Dump freshly installed database"
ssh root@$HOST "FFORGE_DB=$DB_NAME FFORGE_USER=gforge FFORGE_ADMIN_USER=$FORGE_ADMIN_USERNAME FFORGE_ADMIN_PASSWORD=$FORGE_ADMIN_PASSWORD export FFORGE_DB FFORGE_USER FFORGE_ADMIN_USER FFORGE_ADMIN_PASSWORD; yum install -y --skip-broken fusionforge fusionforge-plugin-scmsvn fusionforge-plugin-online_help fusionforge-plugin-extratabs fusionforge-plugin-ldapextauth fusionforge-plugin-scmgit fusionforge-plugin-blocks"
scp -p root@$HOST:/var/cache/yum/timedhosts.txt /tmp/timedhosts.txt || true
-ssh root@$HOST '(echo [core];echo use_ssl=no) > /etc/gforge/config.ini.d/zzz-builbot.ini'
+ssh root@$HOST '(echo [core];echo use_ssl=no;echo use_fti=no) > /etc/gforge/config.ini.d/zzz-buildbot.ini'
ssh root@$HOST "su - postgres -c \"pg_dumpall\" > /root/dump"
# Install a fake sendmail to catch all outgoing emails.
# ssh root@".HOST." 'perl -spi -e s#/usr/sbin/sendmail#/usr/share/tests/scripts/catch_mail.php# /etc/gforge/local.inc'
ssh root@$HOST "su - postgres -c \"pg_dumpall\" > /root/dump"
echo "Set use_ssl=no"
-ssh root@$HOST "(echo [core];echo use_ssl=no) > /etc/gforge/config.ini.d/zzz-zbuildbot.ini"
+ssh root@$HOST "(echo [core];echo use_ssl=no;echo use_fti=no) > /etc/gforge/config.ini.d/zzz-zbuildbot.ini"
# Install a fake sendmail to catch all outgoing emails.
# ssh root@$HOST "perl -spi -e s#/usr/sbin/sendmail#/opt/tests/scripts/catch_mail.php# /etc/gforge/local.inc"