+ (* Flush out the header while we start the search. *)
+ q#header ();
+ ignore (print_string r th#to_string);
+ ignore (Request.rflush r);
+
+ let t = template_404 in
+ t#set "query" search_terms;
+ t#set "canonical_hostname" host.canonical_hostname;
+
+ (* This is a simplified version of the code in search.ml. *)
+ let have_results =
+ (* Get the keywords from the query string. *)
+ let keywords = Pcre.split ~rex:split_words search_terms in
+ let keywords =
+ List.filter (fun s -> not (string_is_whitespace s)) keywords in
+ let keywords = List.map String.lowercase keywords in
+
+ (* Turn the keywords into a tsearch2 ts_query string. *)
+ let tsquery = String.concat "&" keywords in
+
+ (* Search the titles first. *)
+ let rows =
+ PGSQL(dbh)
+ "select url, title, last_modified_date,
+ (lower (title) = lower ($search_terms)) as exact
+ from pages
+ where hostid = $hostid
+ and url is not null
+ and redirect is null
+ and title_description_fti @@ to_tsquery ('default', $tsquery)
+ order by exact desc, last_modified_date desc, title" in
+
+ let titles =
+ List.map (function
+ | (Some url, title, last_modified, _) ->
+ url, title, last_modified
+ | _ -> assert false) rows in
+
+ let have_titles = titles <> [] in
+ t#conditional "have_titles" have_titles;
+
+ (* Search the contents. *)
+ let rows =
+ PGSQL(dbh)
+ "select c.id, p.url, p.title, p.last_modified_date
+ from contents c, pages p
+ where c.pageid = p.id
+ and p.hostid = $hostid
+ and url is not null
+ and p.redirect is null
+ and c.content_fti @@ to_tsquery ('default', $tsquery)
+ order by p.last_modified_date desc, p.title
+ limit 50" in
+
+ let contents =
+ List.map (function
+ | (contentid, Some url, title, last_modified) ->
+ contentid, url, title, last_modified
+ | _ -> assert false) rows in
+
+ let have_contents = contents <> [] in
+ t#conditional "have_contents" have_contents;
+
+ (* Pull out the actual text which matched so we can generate a summary.
+ * XXX tsearch2 can actually do better than this by emboldening
+ * the text which maps.
+ *)
+ let content_map =
+ if contents = [] then []
+ else (
+ let rows =
+ let contentids =
+ List.map (fun (contentid, _,_,_) -> contentid) contents in
+ PGSQL(dbh)
+ "select id, sectionname, content from contents
+ where id in $@contentids" in
+ List.map (fun (id, sectionname, content) ->
+ id, (sectionname, content)) rows
+ ) in