[BACK]Return to mansearch.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/mansearch.c between version 1.6 and 1.7

version 1.6, 2013/06/05 02:00:26 version 1.7, 2013/10/19 20:43:13
Line 1 
Line 1 
 /*      $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
    * Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above   * purpose with or without fee is hereby granted, provided that the above
Line 119  static struct expr *exprcomp(const struct mansearch *,
Line 120  static struct expr *exprcomp(const struct mansearch *,
                                 int, char *[]);                                  int, char *[]);
 static  void             exprfree(struct expr *);  static  void             exprfree(struct expr *);
 static  struct expr     *exprterm(const struct mansearch *, char *);  static  struct expr     *exprterm(const struct mansearch *, char *);
   static  void             sql_match(sqlite3_context *context,
                                   int argc, sqlite3_value **argv);
 static  char            *sql_statement(const struct expr *,  static  char            *sql_statement(const struct expr *,
                                 const char *, const char *);                                  const char *, const char *);
   
Line 205  mansearch(const struct mansearch *search,
Line 208  mansearch(const struct mansearch *search,
                         continue;                          continue;
                 }                  }
   
                   /* Define the SQL function for substring matching. */
   
                   c = sqlite3_create_function(db, "match", 2,
                       SQLITE_ANY, NULL, sql_match, NULL, NULL);
                   if (SQLITE_OK != c) {
                           fprintf(stderr, "%s\n", sqlite3_errmsg(db));
                           break;
                   }
   
                 j = 1;                  j = 1;
                 c = sqlite3_prepare_v2(db, sql, -1, &s, NULL);                  c = sqlite3_prepare_v2(db, sql, -1, &s, NULL);
                 if (SQLITE_OK != c)                  if (SQLITE_OK != c)
Line 287  out:
Line 299  out:
 }  }
   
 /*  /*
    * Implement substring match as an application-defined SQL function.
    * Using the SQL LIKE or GLOB operators instead would be a bad idea
    * because that would require escaping metacharacters in the string
    * being searched for.
    */
   static void
   sql_match(sqlite3_context *context, int argc, sqlite3_value **argv)
   {
   
           assert(2 == argc);
           sqlite3_result_int(context, NULL != strcasestr(
               (const char *)sqlite3_value_text(argv[1]),
               (const char *)sqlite3_value_text(argv[0])));
   }
   
   /*
  * Prepare the search SQL statement.   * Prepare the search SQL statement.
  * We search for any of the words specified in our match expression.   * We search for any of the words specified in our match expression.
  * We filter the per-doc AND expressions when collecting results.   * We filter the per-doc AND expressions when collecting results.
Line 295  static char *
Line 323  static char *
 sql_statement(const struct expr *e, const char *arch, const char *sec)  sql_statement(const struct expr *e, const char *arch, const char *sec)
 {  {
         char            *sql;          char            *sql;
           const char      *substr = "(key MATCH ? AND bits & ?)";
         const char      *glob = "(key GLOB ? AND bits & ?)";          const char      *glob = "(key GLOB ? AND bits & ?)";
         const char      *eq = "(key = ? AND bits & ?)";  
         const char      *andarch = "arch = ? AND ";          const char      *andarch = "arch = ? AND ";
         const char      *andsec = "sec = ? AND ";          const char      *andsec = "sec = ? AND ";
           size_t           substrsz;
         size_t           globsz;          size_t           globsz;
         size_t           eqsz;  
         size_t           sz;          size_t           sz;
   
         sql = mandoc_strdup          sql = mandoc_strdup
Line 309  sql_statement(const struct expr *e, const char *arch, 
Line 337  sql_statement(const struct expr *e, const char *arch, 
                  "INNER JOIN docs ON docs.id=keys.docid "                   "INNER JOIN docs ON docs.id=keys.docid "
                  "WHERE ");                   "WHERE ");
         sz = strlen(sql);          sz = strlen(sql);
           substrsz = strlen(substr);
         globsz = strlen(glob);          globsz = strlen(glob);
         eqsz = strlen(eq);  
   
         if (NULL != arch) {          if (NULL != arch) {
                 sz += strlen(andarch) + 1;                  sz += strlen(andarch) + 1;
Line 329  sql_statement(const struct expr *e, const char *arch, 
Line 357  sql_statement(const struct expr *e, const char *arch, 
         strlcat(sql, "(", sz);          strlcat(sql, "(", sz);
   
         for ( ; NULL != e; e = e->next) {          for ( ; NULL != e; e = e->next) {
                 sz += (e->glob ? globsz : eqsz) +                  sz += (e->glob ? globsz : substrsz) +
                         (NULL == e->next ? 3 : 5);                          (NULL == e->next ? 3 : 5);
                 sql = mandoc_realloc(sql, sz);                  sql = mandoc_realloc(sql, sz);
                 strlcat(sql, e->glob ? glob : eq, sz);                  strlcat(sql, e->glob ? glob : substr, sz);
                 strlcat(sql, NULL == e->next ? ");" : " OR ", sz);                  strlcat(sql, NULL == e->next ? ");" : " OR ", sz);
         }          }
   

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.7

CVSweb