pike.git / lib / modules / Search.pmod / Query.pmod

version» Context lines:

pike.git/lib/modules/Search.pmod/Query.pmod:1: +  +    // This file is part of Roxen Search   // Copyright © 2001 Roxen IS. All rights reserved.   // - // $Id: Query.pmod,v 1.25 2002/03/25 12:54:32 js Exp $ + // $Id: Query.pmod,v 1.26 2004/08/07 15:26:58 js Exp $    - static function(string,int:string) blobfeeder(Search.Database.Base db, array words) + static function(string,int:string) blobfeeder(Search.Database.Base db, +  array words)   {    mapping state = mkmapping(words,allocate(sizeof(words)));    mapping(string:mapping(int:string)) blobcache = ([ ]);    return lambda( string word, int foo )    {    return db->get_blob(word, state[word]++, blobcache);    };   }      static array(string) uniq_preserve_order(array(string) a) {
pike.git/lib/modules/Search.pmod/Query.pmod:52:    Search.RankingProfile ranking)   {    Search.ResultSet result =    _WhiteFish.do_query_phrase(words,    ranking->field_ranking,    // ranking->cutoff,    blobfeeder(db, words));    return result;   }    + enum search_order + { +  RELEVANCE=1, DATE_ASC, DATE_DESC, NONE + }; +  + static Search.ResultSet sort_resultset(Search.ResultSet resultset, +  search_order order, +  Search.Database.Base db) + { +  + } +  +    //! @param query   //! The query string entered by user.   //! @param db   //! The search database.   //! @param defaultRanking   //! Used when searching in the field "any:".   //!   //! @returns   //! An array with two elements:   //! @array   //! @elem Search.ResultSet 0   //! The ResultSet containing the hits.   //! @elem array(string) 1   //! All wanted words in the query. (I.e. not the words that were   //! preceded by minus.)   //! @endarray   //!   array(Search.ResultSet|array(string)) execute(Search.Database.Base db,    Search.Grammar.AbstractParser parser,    string query, -  Search.RankingProfile defaultRanking, -  array(string)|void stop_words) +  Search.RankingProfile ranking, +  void|array(string) stop_words, +  void|search_order order)   {    Search.Grammar.ParseNode q = parser->parse(query); -  if (stop_words && sizeof(stop_words)) { -  q = Search.Grammar.remove_stop_words(q, stop_words); -  } +  if (stop_words && sizeof(stop_words)) +  Search.Grammar.remove_stop_words(q, stop_words);       q = Search.Grammar.optimize(q);       if (!q) // The query was a null query    return ({ Search.ResultSet(), ({}) }); // so return an empty resultset       string error = Search.Grammar.validate(q);    if (error)    throw (error);    -  return class { +  array(Search.ResultSet|array(string)) res = class {    static Search.RankingProfile defaultRanking;    static Search.Database.Base db;       // Used when search is limited to another field than "any:".    static Search.RankingProfile specialRanking;       static void create(Search.Database.Base _db, Search.RankingProfile _defaultRanking) {    db = _db;    defaultRanking = _defaultRanking;    specialRanking = defaultRanking->copy(); -  +  pop = stack->pop; +  push = stack->push;    }       static array(array(string)) split_words(array(string) words)    {    array a=({}),b=({});    foreach(words, string word)    if(has_value(word, "*") || has_value(word, "?"))    b+=({ word });    else    a+=({ word });    return ({ a, b });    }       static constant ParseNode = Search.Grammar.ParseNode;       static array(array(string)|string) words = ({ }); -  static array(Search.ResultSet) stack = ({ }); -  static void push(Search.ResultSet r) { -  stack = ({ r }) + stack; -  } -  static Search.ResultSet pop() { -  if (!sizeof(stack)) -  error("Very bad!"); -  Search.ResultSet r = stack[0]; -  stack = stack[1 .. ]; -  return r; -  } +  static ADT.Stack stack = ADT.Stack(); +  static function(Search.ResultSet:void) push; +  static function(void:Search.ResultSet) pop;       array(Search.ResultSet|array(string)) execute(ParseNode q) {    exec(q);    if (sizeof(stack) != 1) -  throw ("Stack should have exactly one item!"); +  error("Stack should have exactly one item!");    return ({ pop(), words });    }          void exec(ParseNode q) {    int max_globs = 100;    switch (q->op) {    case "and":    {    int first = 1;    foreach (q->children, ParseNode child) -  if (child->op != "date") { +  {    exec(child);    if (!first) {    Search.ResultSet r2 = pop();    Search.ResultSet r1 = pop();    push(r1 & r2);    }    else    first = 0;    } -  // ( DATE: limitations not implemented yet... ) -  // -  // foreach (q->children, ParseNode child) -  // if (child->op == "date") -  // exec(child); +     }    break;    case "or": -  +  {    int first = 1;    foreach (q->children, ParseNode child) {    exec(child);    if (!first) {    Search.ResultSet r2 = pop();    Search.ResultSet r1 = pop();    push(r1 | r2);    }    else    first = 0;    } -  +  }    break;    case "date": -  // NOT IMPLEMENTED YET +  _WhiteFish.DateSet global_dateset = db->get_global_dateset(); +  +  int t = Calendar.ISO.dwim_day(q->date)->unix_time(); +  +  if(!sizeof(global_dateset)) +  { +  push(global_dateset);    break; -  +  } +  +  _WhiteFish.DateSet restriction; +  switch(q->operator[1]) +  { +  case "=": +  break; +  case "<>": +  break; +  case "!=": +  // restriction = global_dateset->...; +  break; +  case "<=": +  restriction = global_dateset->before(t+1)->finalize(); +  break; +  case ">=": +  restriction = global_dateset->after(t-1)->finalize(); +  break; +  case "<": +  restriction = global_dateset->before(t)->finalize(); +  break; +  case ">": +  restriction = global_dateset->after(t)->finalize(); +  break; +  } +  push(restriction); +  break; +     case "text":    {    Search.RankingProfile ranking = defaultRanking;       if (q->field != "any")    {    ranking = specialRanking;    int fieldID = db->get_field_id(q->field, 1);    if (!fieldID && q->field != "body")    {
pike.git/lib/modules/Search.pmod/Query.pmod:198:    break;    }    ranking->field_ranking = allocate(65);    ranking->field_ranking[fieldID] = 1;    }       [array plusWords, array plusWordGlobs] = split_words(q->plusWords);    [array ordinaryWords, array ordinaryWordGlobs] = split_words(q->words);    [array minusWords, array minusWordGlobs] = split_words(q->minusWords);    - // werror("[%-10s] plus: %-15s ordinary: %-15s minus: %-15s\n", q->field, q>plusWords*", ", q->words*", ", q->minusWords*", "); + // werror("[%-10s] plus: %-15s ordinary: %-15s minus: %-15s\n", q->field, q>plusWords*", ", q->words*", ", q->minusWords*", ");       int hasPlus = sizeof(q->plusWords) || sizeof(q->plusPhrases);    int hasOrdinary = sizeof(q->words) || sizeof(q->phrases);    int hasMinus = sizeof(q->minusWords) || sizeof(q->minusPhrases);       if(hasPlus)    {    int first = 1;    if(sizeof(plusWords))    {
pike.git/lib/modules/Search.pmod/Query.pmod:322:    Search.ResultSet r1 = pop();    push(r1 - r2);    }    }    break;    default:    error("Unknown type of ParseNode!");    } // switch (q->op)    }    -  } (db, defaultRanking)->execute(q); +  } (db, ranking)->execute(q); +  +  res[0] -= db->get_deleted_documents(); +  +  if(!order) +  order = RELEVANCE; +  +  if(order!=NONE) +  switch(order) +  { +  case RELEVANCE: +  res[0]->sort(); +  break; +  case DATE_ASC: +  case DATE_DESC: +  res[0] = res[0]->finalize()->add_ranking(db->get_global_dateset()); +  if(order==DATE_DESC) +  res[0]->sort(); +  else +  res[0]->sort_rev(); +  case NONE:    } -  +  +  return res; + }