Change subject line so it shows the name of the site.
[cocanwiki.git] / scripts / search.ml
index 456c0e9..13899ce 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: search.ml,v 1.8 2004/11/02 22:26:36 rich Exp $
+ * $Id: search.ml,v 1.10 2006/03/28 16:24:08 rich Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,7 +32,7 @@ open Cocanwiki_date
 
 let split_words = Pcre.regexp "\\W+"
 
-let run r (q : cgi) (dbh : Dbi.connection) hostid host user =
+let run r (q : cgi) dbh hostid host user =
   let template = get_template dbh hostid "search.html" in
 
   template#set "canonical_hostname" host.canonical_hostname;
@@ -68,77 +68,91 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid host user =
       let tsquery = String.concat "&" keywords in
 
       (* Search the titles first. *)
-      let sth =
-       dbh#prepare_cached
-         ("select id, url, url_deleted, title, last_modified_date,
-                   (lower (title) = lower (?)) as exact
-              from pages
-             where hostid = ? " ^
-          (if not old_versions then "and url is not null " else "") ^ "
-              and redirect is null
-               and title_description_fti @@ to_tsquery (?, ?)
-             order by exact desc, last_modified_date desc, title") in
-      sth#execute [`String query;
-                  `Int hostid; `String "default"; `String tsquery];
+      let rows =
+       if not old_versions then
+         PGSQL(dbh)
+           "select id, url, url_deleted, title, last_modified_date,
+                    (lower (title) = lower ($query)) 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"
+       else
+         PGSQL(dbh)
+           "select id, url, url_deleted, title, last_modified_date,
+                    (lower (title) = lower ($query)) as exact
+               from pages
+              where hostid = $hostid
+               and redirect is null
+                and title_description_fti @@ to_tsquery ('default', $tsquery)
+              order by exact desc, last_modified_date desc, title" in
 
       let titles =
-       sth#map (function
-                  | [_; `String url; `Null; `String title;
-                     `Timestamp last_modified; _] ->
-                      url, title, None, last_modified
-                  | [`Int version; `Null; `String url; `String title;
-                     `Timestamp last_modified; _] ->
-                      url, title, Some version, last_modified
-                  | _ -> assert false) in
+       List.map (function
+                 | (_, Some url, None, title, last_modified, _) ->
+                     url, title, None, last_modified
+                 | (version, None, Some url, title, last_modified, _) ->
+                     url, title, Some version, last_modified
+                 | _ -> assert false) rows in
 
       let have_titles = titles <> [] in
       template#conditional "have_titles" have_titles;
 
       (* Search the contents. *)
-      let sth =
-       dbh#prepare_cached
-         ("select c.id, p.id, p.url, p.url_deleted, p.title,
-                   p.last_modified_date
-              from contents c, pages p
-             where c.pageid = p.id
-               and p.hostid = ? " ^
-           (if not old_versions then "and url is not null " else "") ^ "
-               and p.redirect is null
-               and c.content_fti @@ to_tsquery (?, ?)
-             order by p.last_modified_date desc, p.title
-             limit 50") in
-      sth#execute [`Int hostid; `String "default"; `String tsquery];
+      let rows =
+       if not old_versions then
+         PGSQL(dbh)
+         "select c.id, p.id, p.url, p.url_deleted, 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"
+       else
+         PGSQL(dbh)
+         "select c.id, p.id, p.url, p.url_deleted, p.title,
+                  p.last_modified_date
+             from contents c, pages p
+            where c.pageid = p.id
+              and p.hostid = $hostid
+              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 =
-       sth#map (function
-                  | [`Int contentid; _; `String url; `Null;
-                     `String title; `Timestamp last_modified] ->
+       List.map (function
+                  | (contentid, _, Some url, None, title, last_modified) ->
                       contentid, url, title, None, last_modified
-                  | [`Int contentid; `Int version; `Null; `String url;
-                     `String title; `Timestamp last_modified] ->
+                  | (contentid, version, None, Some url, title,
+                     last_modified) ->
                       contentid, url, title, Some version, last_modified
-                  | _ -> assert false) in
+                  | _ -> assert false) rows in
 
       let have_contents = contents <> [] in
       template#conditional "have_contents" have_contents;
 
-      (* Pull out the actual text which matched so we can generate a summary.*)
+      (* 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 qs = Dbi.placeholders (List.length contents) in
-         let sth =
-           dbh#prepare_cached
-             ("select id, sectionname, content from contents
-                 where id in " ^ qs) in
-         sth#execute
-           (List.map (fun (contentid, _,_,_,_) -> `Int contentid) contents);
-         sth#map (function
-                    | [ `Int id; `Null; `String content ] ->
-                        id, (None, content)
-                    | [ `Int id; `String sectionname; `String content ] ->
-                        id, (Some sectionname, content)
-                    | _ -> assert false)
+         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
 
       (* Generate the final tables. *)
@@ -146,13 +160,13 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid host user =
        List.map (fun (url, title, version, last_modified) ->
                    let have_version, version =
                      match version with
-                         None -> false, 0
+                         None -> false, 0l
                        | Some version -> true, version in
                    let last_modified = printable_date last_modified in
                    [ "url", Template.VarString url;
                      "title", Template.VarString title;
                      "have_version", Template.VarConditional have_version;
-                     "version", Template.VarString (string_of_int version);
+                     "version", Template.VarString (Int32.to_string version);
                      "last_modified", Template.VarString last_modified ]
                 ) titles in
       template#table "titles" table;
@@ -162,7 +176,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid host user =
          (fun (contentid, url, title, version, last_modified) ->
             let have_version, version =
               match version with
-                  None -> false, 0
+                  None -> false, 0l
                 | Some version -> true, version in
             let sectionname, content = List.assoc contentid content_map in
             let have_sectionname, sectionname =
@@ -178,7 +192,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid host user =
             [ "url", Template.VarString url;
               "title", Template.VarString title;
               "have_version", Template.VarConditional have_version;
-              "version", Template.VarString (string_of_int version);
+              "version", Template.VarString (Int32.to_string version);
               "have_sectionname", Template.VarConditional have_sectionname;
               "sectionname", Template.VarString sectionname;
               "linkname", Template.VarString linkname;