# # patch "database.ml" # from [a9be75cba7c3959bb719bddc6c16845ccc7f9d7f] # to [c65ed1ed8166c502a853693457268b259762e7ab] # # patch "database.mli" # from [c3b6e7bc7329e3085ebb84fc66917fb0bf32b932] # to [c73fe20033fb3e87ce40f360750a23b79666f190] # # patch "query.ml" # from [256e656a8beb50a97b7a1b7216c8d07693d9e554] # to [433642e55735b40057c21d1cdc488c93f7c556a4] # ======================================================================== --- database.ml a9be75cba7c3959bb719bddc6c16845ccc7f9d7f +++ database.ml c65ed1ed8166c502a853693457268b259762e7ab @@ -203,6 +203,22 @@ let fetch_agraph query db = fetch_with_view query db fetch_agraph_with_view +let revision_contains pattern = function + | (_, [ edge ]) -> + List.exists + (function + | Revision_types.PATCH (f, _, _) -> f = pattern + | Revision_types.ADD_FILE f + | Revision_types.DELETE_FILE f + | Revision_types.DELETE_DIR f -> f = pattern + | Revision_types.RENAME_FILE (f1, f2) + | Revision_types.RENAME_DIR (f1, f2) -> + f1 = pattern || f2 = pattern) + edge.Revision_types.change_set + | _ -> + (* return false for merges *) + false + let decode_and_parse_revision s = Revision_parser.revision_set Revision_lexer.lex @@ -282,6 +298,18 @@ +let with_bool_funs db funs f = + List.iter + (fun (name, p) -> + Sqlite3.create_fun_1 db name + (fun v -> if p (Sqlite3.value_text v) then `INT 1 else `INT 0)) + funs ; + let unregister () = + List.iter + (fun (name, _) -> Sqlite3.delete_function db name) + funs in + try let r = f db in unregister () ; r + with exn -> unregister () ; raise exn @@ -390,19 +418,54 @@ get_matching_cert db "date" (string_is_prefix d_pref) -let query_certs db query name pattern = - let p = string_contains pattern in - List.rev - (fetch_with_view query db.db - (fun db query -> - Sqlite3.fetch_f db - (fun acc -> function - | [| id ; v |] when p v -> id :: acc - | _ -> acc) - [] - "SELECT id, unbase64(value) FROM revision_certs WHERE id IN %s AND name = '%s'" - view_name name)) +let fetch_list db sql = + Sqlite3.fetch db sql + (fun acc -> function [| v |] -> v :: acc | _ -> acc) + [] +let do_query_certs db mode = + let select_cert name = + Printf.sprintf + "SELECT C.id FROM revision_certs AS C \ + WHERE C.id IN %s AND C.name = '%s' AND cert_match(C.value)" + view_name name in + let select_revision sub = + Printf.sprintf + "SELECT R.id FROM revisions AS R \ + WHERE R.id IN %s AND revision_match(R.data)" sub in + match mode with + | `CERTS name -> + fetch_list db (select_cert name) + | `REVISIONS -> + fetch_list db (select_revision view_name) + | `BOTH name -> + fetch_list db (select_revision ("(" ^ select_cert name ^ ")")) + +let query_certs db query name pattern revision_content = + let mode = + match revision_content, name, pattern with + | "", "", _ + | "", _, "" -> `NOTHING + | "", _, _ -> `CERTS name + | _, "", "" -> `REVISIONS + | _, _, _ -> `BOTH name in + match mode with + | `NOTHING -> [] + | `CERTS _ | `REVISIONS | `BOTH _ as mode -> + fetch_with_view query db.db + (fun db _ -> + let p = string_contains pattern in + with_bool_funs db + [ "cert_match", + (fun v -> p (monot_decode v)) ; + "revision_match", + (fun v -> + revision_contains + revision_content + (decode_and_parse_revision v)) ] + (fun db -> do_query_certs db mode)) + + let run_monotone_diff db monotone_exe edge status cb = ignore (spawn_monotone_diff db.filename monotone_exe edge status cb) ======================================================================== --- database.mli c3b6e7bc7329e3085ebb84fc66917fb0bf32b932 +++ database.mli c73fe20033fb3e87ce40f360750a23b79666f190 @@ -20,7 +20,7 @@ val get_matching_tags : t -> (string -> bool) -> (string * string) list val get_matching_dates : t -> string -> (string * string) list -val query_certs : t -> query -> string -> string -> string list +val query_certs : t -> query -> string -> string -> string -> string list val get_key_rowid : t -> string -> int ======================================================================== --- query.ml 256e656a8beb50a97b7a1b7216c8d07693d9e554 +++ query.ml 433642e55735b40057c21d1cdc488c93f7c556a4 @@ -10,15 +10,15 @@ -let do_query ~cert_name ~cert_value v = +let do_query ~cert_name ~cert_value ~revision_content v = match v.View.db, v.View.agraph with - | Some db, Some g when cert_name <> "" && cert_value <> "" -> + | Some db, Some g when revision_content <> "" || (cert_value <> "" && cert_value <> "") -> View.nice_fetch (fun db -> let ids = Database.query_certs db (Agraph.get_query g) - cert_name cert_value in + cert_name cert_value revision_content in let fetch_first_cert id c = match Database.fetch_cert_value db id c with @@ -56,16 +56,22 @@ let setup_query_builder vbox = Lazy.force init_stock ; let (packing, _) = category "Query" vbox in - let packing = (GPack.hbox ~packing ())#pack in - let _ = GMisc.label ~text:"Cert name: " ~packing () in + let packing = (GPack.vbox ~packing ())#pack in + let hbox = GPack.hbox ~packing () in + let _ = GMisc.label ~text:"Cert name: " ~packing:hbox#pack () in let (e_cert_name, _) = GEdit.combo_box_entry_text ~strings:["author" ; "changelog" ; "comment" ; "date" ; "tag" ] - ~packing () in - let _ = GMisc.label ~text:" contains " ~packing () in + ~packing:hbox#pack () in + let _ = GMisc.label ~text:" contains " ~packing:hbox#pack () in let e_cert_value = - GEdit.entry ~packing () in - (e_cert_name#entry, e_cert_value) + GEdit.entry ~packing:(hbox#pack ~expand:true) () in + + let hbox = GPack.hbox ~packing () in + let _ = GMisc.label ~text:"Revision concerns file: " ~packing:hbox#pack () in + let e_revision = + GEdit.entry ~packing:(hbox#pack ~expand:true) () in + (e_cert_name#entry, e_cert_value, e_revision) type model = { @@ -82,7 +88,7 @@ let col_date = cols#add Gobject.Data.string in let col_author = cols#add Gobject.Data.string in let store = GTree.list_store cols in - store#set_sort_column_id col_date.GTree.index `ASCENDING ; + store#set_sort_column_id col_date.GTree.index `DESCENDING ; { model = store ; col_id = col_id ; col_date = col_date ; col_author = col_author } @@ -108,13 +114,15 @@ let update_results m r = if r <> [] then clear_model m ; + m.model#set_sort_column_id (-2) `DESCENDING ; List.iter (fun (id, date, author) -> let row = m.model#append () in m.model#set ~row ~column:m.col_id id ; m.model#set ~row ~column:m.col_date date ; m.model#set ~row ~column:m.col_author author) - r + r ; + m.model#set_sort_column_id m.col_date.GTree.index `DESCENDING @@ -126,7 +134,7 @@ ~border_width:8 ~type_hint:`NORMAL () in - let (e1, e2) = setup_query_builder w#vbox in + let (e1, e2, e3) = setup_query_builder w#vbox in let (m, rv, set_label) = setup_results_view w#vbox in w#add_button_stock `CLOSE `CLOSE ; @@ -138,6 +146,8 @@ ignore (e2#connect#activate (fun () -> w#response `QUERY)) ; + ignore (e3#connect#activate (fun () -> + w#response `QUERY)) ; ignore (w#connect#response (function | `CLOSE | `DELETE_EVENT -> @@ -149,6 +159,7 @@ let results = do_query ~cert_name:e1#text ~cert_value:e2#text + ~revision_content:e3#text v in update_results m results ; set_label (List.length results))) ; @@ -164,6 +175,9 @@ | `CLEAR -> clear_model m ; set_label 0 ; + e1#set_text "" ; + e2#set_text "" ; + e3#set_text "" ; w#set_response_sensitive `QUERY false | `UPDATE_BEGIN -> w#set_response_sensitive `QUERY true